[
  {
    "path": ".babelrc",
    "content": "{\n  \"presets\": [\"@babel/preset-env\"]\n}\n"
  },
  {
    "path": ".bumpversion.cfg",
    "content": "[bumpversion]\ncurrent_version = 1.19.2\ncommit = True\nmessage = \n\tPrepare for {new_version} release\n\t\n\tSee changelog for more details.\n\n[bumpversion:file:src/memray/_version.py]\n"
  },
  {
    "path": ".clang-format",
    "content": "BasedOnStyle: LLVM\nLanguage: Cpp\nAccessModifierOffset: -2\nAlignAfterOpenBracket: AlwaysBreak\nAlignConsecutiveAssignments: false\nAlignConsecutiveDeclarations: false\nAlignEscapedNewlines: Right\nAlignOperands: true\nAlignTrailingComments: false\nAllowAllArgumentsOnNextLine: false\nAllowAllParametersOfDeclarationOnNextLine: false\nAllowShortBlocksOnASingleLine: false\nAllowShortCaseLabelsOnASingleLine: false\nAllowShortFunctionsOnASingleLine: None\nAllowShortIfStatementsOnASingleLine: WithoutElse\nAllowShortLoopsOnASingleLine: false\nAlwaysBreakAfterReturnType: TopLevel\nAlwaysBreakBeforeMultilineStrings: false\nAlwaysBreakTemplateDeclarations: Yes\nBinPackArguments: false\nBinPackParameters: false\nBraceWrapping:\n  AfterClass: true\n  AfterControlStatement: MultiLine\n  AfterEnum: false\n  AfterFunction: true\n  AfterNamespace: false\n  AfterStruct: true\n  AfterUnion: false\n  AfterExternBlock: false\n  BeforeCatch: false\n  BeforeElse: false\n  IndentBraces: false\n  SplitEmptyFunction: true\n  SplitEmptyRecord: true\n  SplitEmptyNamespace: true\nBreakBeforeBinaryOperators: NonAssignment\nBreakBeforeBraces: Custom\nBreakBeforeInheritanceComma: false\nBreakBeforeTernaryOperators: true\nBreakConstructorInitializers: BeforeComma\nBreakInheritanceList: BeforeComma\nBreakStringLiterals: true\nColumnLimit: 105\nCompactNamespaces: false\nConstructorInitializerAllOnOneLineOrOnePerLine: false\nConstructorInitializerIndentWidth: 0\nContinuationIndentWidth: 8\nCpp11BracedListStyle: true\nDerivePointerAlignment: false\nFixNamespaceComments: true\nIncludeBlocks: Preserve\nIncludeCategories:\n  - Regex: '^\"(llvm|llvm-c|clang|clang-c)/'\n    Priority: 2\n  - Regex: '^(<|\"(gtest|gmock|isl|json)/)'\n    Priority: 3\n  - Regex: \".*\"\n    Priority: 1\nIndentCaseLabels: true\nIndentGotoLabels: false\nIndentPPDirectives: AfterHash\nIndentWidth: 4\nIndentWrappedFunctionNames: false\nKeepEmptyLinesAtTheStartOfBlocks: false\nMaxEmptyLinesToKeep: 1\nNamespaceIndentation: None\nPenaltyBreakAssignment: 2\nPenaltyBreakBeforeFirstCallParameter: 19\nPenaltyBreakComment: 300\nPenaltyBreakFirstLessLess: 120\nPenaltyBreakString: 1000\nPenaltyBreakTemplateDeclaration: 10\nPenaltyExcessCharacter: 1000000\nPenaltyReturnTypeOnItsOwnLine: 60\nPointerAlignment: Left\nReflowComments: true\nSortIncludes: true\nSortUsingDeclarations: true\nSpaceAfterCStyleCast: false\nSpaceAfterTemplateKeyword: false\nSpaceBeforeAssignmentOperators: true\nSpaceBeforeCpp11BracedList: false\nSpaceBeforeCtorInitializerColon: true\nSpaceBeforeInheritanceColon: true\nSpaceBeforeParens: ControlStatements\nSpaceBeforeRangeBasedForLoopColon: true\nSpaceInEmptyParentheses: false\nSpacesBeforeTrailingComments: 2\nSpacesInAngles: false\nSpacesInContainerLiterals: true\nSpacesInCStyleCastParentheses: false\nSpacesInParentheses: false\nSpacesInSquareBrackets: false\nStandard: Auto\nTabWidth: 8\nUseTab: Never\n"
  },
  {
    "path": ".devcontainer/devcontainer.json",
    "content": "{\n  \"name\": \"Memray development\",\n  \"build\": {\n    \"context\": \"..\",\n    \"dockerfile\": \"../Dockerfile\"\n  },\n  \"runArgs\": [\"--cap-add=SYS_PTRACE\", \"--security-opt\", \"seccomp=unconfined\"],\n  \"onCreateCommand\": \"pip install -e .\"\n}\n"
  },
  {
    "path": ".devcontainer/tutorials/devcontainer.json",
    "content": "{\n  \"name\": \"Memray tutorials\",\n  \"build\": {\n    \"context\": \"../../docs/tutorials\",\n    \"dockerfile\": \"../../docs/tutorials/Dockerfile\"\n  },\n  \"customizations\": {\n    \"vscode\": {\n      \"settings\": {\n        \"python.testing.pytestArgs\": [\"docs/tutorials/tests\"],\n        \"python.testing.unittestEnabled\": false,\n        \"python.testing.pytestEnabled\": true,\n        \"python.defaultInterpreterPath\": \"/venv/bin/python\"\n      },\n      \"extensions\": [\"ms-python.python\"]\n    }\n  },\n  \"runArgs\": [\"--cap-add=SYS_PTRACE\", \"--security-opt\", \"seccomp=unconfined\"]\n}\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/---bug-report.yaml",
    "content": "name: 🐞 Bug Report\ndescription: If something isn't working as expected\nlabels: [bug]\nbody:\n  - type: checkboxes\n    attributes:\n      label: Is there an existing issue for this?\n      description: Please search to see if an issue already exists for the bug you encountered.\n      options:\n        - label: I have searched the existing issues\n          required: true\n  - type: textarea\n    attributes:\n      label: Current Behavior\n      description: A concise description of what you're experiencing.\n    validations:\n      required: false\n  - type: textarea\n    attributes:\n      label: Expected Behavior\n      description: A concise description of what you expected to happen.\n    validations:\n      required: false\n  - type: textarea\n    attributes:\n      label: Steps To Reproduce\n      description: Steps to reproduce the behavior.\n      placeholder: |\n        1. In this environment...\n        2. With this config...\n        3. Run '...'\n        4. See error...\n    validations:\n      required: True\n  - type: input\n    id: memray_version\n    attributes:\n      label: Memray Version\n      description: What version of Memray are you seeing the problem on?\n      placeholder: 1.3.0\n    validations:\n      required: true\n  - type: dropdown\n    id: python_version\n    attributes:\n      label: Python Version\n      description: What version of Python are you running?\n      multiple: true\n      options:\n        - \"3.7\"\n        - \"3.8\"\n        - \"3.9\"\n        - \"3.10\"\n        - \"3.11\"\n        - \"3.12\"\n        - \"3.13\"\n        - \"3.14\"\n    validations:\n      required: true\n  - type: dropdown\n    id: os\n    attributes:\n      label: Operating System\n      description: What OS are you seeing the problem on?\n      multiple: true\n      options:\n        - macOS\n        - Linux\n    validations:\n      required: true\n  - type: textarea\n    attributes:\n      label: Anything else?\n      description: |\n        Links? References? Anything that will give us more context about the issue you are encountering!\n\n        Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in.\n    validations:\n      required: false\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/---feature-request.yaml",
    "content": "name: 🚀 Feature Request\ndescription: Suggest an idea for this project\nlabels: [enhancement]\n\nbody:\n  - type: checkboxes\n    attributes:\n      label: Is there an existing proposal for this?\n      description: Please search to see if a proposal already exists for this feature.\n      options:\n        - label: I have searched the existing proposals\n          required: true\n  - type: textarea\n    attributes:\n      label: Is your feature request related to a problem?\n      description: A clear and concise description of what the problem is\n      placeholder: |\n        I have an issue when [...]\n    validations:\n      required: True\n  - type: textarea\n    attributes:\n      label: Describe the solution you'd like\n      description: A clear and concise description of what you want to happen. Add any considered drawbacks.\n      placeholder: |\n        I would love if Memray could [...]\n    validations:\n      required: True\n  - type: textarea\n    attributes:\n      label: Alternatives you considered\n      description: A clear and concise description of any alternative solutions or features you've considered.\n    validations:\n      required: False\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "content": "blank_issues_enabled: true\ncontact_links:\n  - name: Long question or idea\n    url: https://github.com/bloomberg/memray/discussions\n    about: Ask long-form questions and discuss ideas.\n"
  },
  {
    "path": ".github/dependabot.yml",
    "content": "version: 2\nupdates:\n  - package-ecosystem: \"github-actions\"\n    directory: \"/\"\n    schedule:\n      interval: \"daily\"\n"
  },
  {
    "path": ".github/workflows/build.yml",
    "content": "name: Tests\n\non:\n  push:\n    branches:\n      - main\n  pull_request:\n    branches:\n      - main\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}\n  cancel-in-progress: true\n\njobs:\n  check_generated_files:\n    name: \"Check if generated files are up to date\"\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v6\n      - name: Set up dependencies\n        run: |\n          sudo apt-get update\n          sudo apt-get install -qy npm git\n      - name: Check if files are up to date\n        run: make build-js\n      - name: Check for changes\n        run: |\n          git add -u\n          changes=$(git status --porcelain)\n          # Check for changes in regenerated files\n          if test -n \"$changes\"; then\n            echo \"Generated files not up to date.\"\n            echo \"$changes\"\n            echo \"\"\n            git diff --staged || true\n            exit 1\n          fi\n\n  test_in_alpine:\n    name: \"Test in Alpine Linux\"\n    runs-on: ubuntu-latest\n    container:\n      image: alpine\n      options: --cap-add=SYS_PTRACE\n    steps:\n      - uses: actions/checkout@v6\n      - name: Set up dependencies\n        run: |\n          apk add --update build-base libunwind-dev lz4-dev musl-dev python3-dev python3-dbg gdb lldb git bash perl perl-datetime build-base perl-app-cpanminus\n          cpanm Date::Parse\n          cpanm Capture::Tiny\n          # Build elfutils\n          cd /\n          apk add --update argp-standalone bison bsd-compat-headers bzip2-dev curl curl-dev flex-dev libtool linux-headers musl-fts-dev musl-libintl musl-obstack-dev xz-dev zlib-dev zstd-dev\n          VERS=0.191\n          curl -L https://mirrors.kernel.org/sourceware/elfutils/$VERS/elfutils-$VERS.tar.bz2 >./elfutils.tar.bz2\n          tar -xf elfutils.tar.bz2\n          cd elfutils-$VERS\n          CFLAGS='-Wno-error -DFNM_EXTMATCH=0 -g -O3' CXXFLAGS='-Wno-error -DFNM_EXTMATCH=0 -g -O3' ./configure --enable-libdebuginfod --disable-debuginfod --disable-nls --with-zstd\n          make install\n      - name: Create virtual environment\n        run: |\n          python3 -m venv /venv\n      - name: Install Python dependencies\n        run: |\n          /venv/bin/python -m pip install --upgrade pip\n      - name: Run tests\n        env:\n          PYTHON: /venv/bin/python\n        run: |\n          make test-install check-python\n\n  lint_and_docs:\n    name: \"Lint and Docs\"\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v6\n      - name: Set up Node\n        uses: actions/setup-node@v6\n        with:\n          node-version: 16\n      - name: Symlink node as nodejs\n        run: ln -sf \"$(which node)\" \"$(which node)js\"\n      - name: Set up Python\n        uses: actions/setup-python@v6\n        with:\n          python-version: \"3.10\"\n      - name: Set up dependencies\n        run: |\n          sudo apt-get update\n          sudo apt-get install -qy clang-format npm libdebuginfod-dev libunwind-dev liblz4-dev pkg-config\n      - name: Install Python dependencies\n        run: |\n          python3 -m pip install -r requirements-extra.txt\n      - name: Install Package\n        run: |\n          python3 -m pip install -e .\n      - name: Lint sources\n        run: |\n          make lint\n      - name: Build docs\n        run: |\n          towncrier build --version 99.99 --name memray --keep\n          make docs\n\n  valgrind:\n    name: \"Valgrind & Helgrind\"\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v6\n      - name: Set up Python 3.10\n        uses: actions/setup-python@v6\n        with:\n          python-version: \"3.10\"\n      - name: Set up dependencies\n        run: |\n          sudo apt-get update\n          sudo apt-get install -qy libdebuginfod-dev libunwind-dev liblz4-dev pkg-config npm valgrind\n      - name: Install Python dependencies and package\n        run: |\n          python3 -m pip install --upgrade pip\n          python3 -m pip install -r requirements-test.txt\n          python3 -m pip install -e .\n        env:\n          MEMRAY_MINIMIZE_INLINING: 1\n      - name: Run Valgrind\n        run: make valgrind\n      - name: Run Helgrind\n        run: make helgrind\n"
  },
  {
    "path": ".github/workflows/build_wheels.yml",
    "content": "name: Wheels\n\non:\n  push:\n  pull_request:\n  release:\n    types:\n      - published\n  schedule:\n    # At 12:00 on every day-of-month\n    - cron: \"0 12 */1 * *\"\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}\n  cancel-in-progress: true\n\njobs:\n  build_sdist:\n    name: Build source distribution\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v6\n\n      - name: Build sdist\n        run: pipx run build --sdist\n\n      - uses: actions/upload-artifact@v7\n        with:\n          name: sdist\n          path: dist\n\n      - uses: actions/upload-artifact@v7\n        with:\n          name: tests\n          path: tests\n\n  choose_linux_wheel_types:\n    name: Decide which wheel types to build\n    runs-on: ubuntu-latest\n    steps:\n      - id: manylinux_x86_64\n        run: echo \"wheel_types=manylinux_x86_64\" >> $GITHUB_OUTPUT\n      - id: musllinux_x86_64\n        run: echo \"wheel_types=musllinux_x86_64\" >> $GITHUB_OUTPUT\n      - id: manylinux_i686\n        run: echo \"wheel_types=manylinux_i686\" >> $GITHUB_OUTPUT\n      - id: manylinux_aarch64\n        run: echo \"wheel_types=manylinux_aarch64\" >> $GITHUB_OUTPUT\n    outputs:\n      wheel_types: ${{ toJSON(steps.*.outputs.wheel_types) }}\n\n  build_linux_wheels:\n    needs: [build_sdist, choose_linux_wheel_types]\n    name: ${{ matrix.wheel_type }} wheels\n    runs-on: ${{ matrix.os }}\n    strategy:\n      fail-fast: false\n      matrix:\n        wheel_type: ${{ fromJSON(needs.choose_linux_wheel_types.outputs.wheel_types) }}\n        include:\n          - os: ubuntu-latest\n          - wheel_type: manylinux_aarch64\n            os: ubuntu-24.04-arm\n          - wheel_type: manylinux_i686\n            os: ubuntu-latest\n            cibw_archs_linux: auto32\n    steps:\n      - uses: actions/download-artifact@v8\n        with:\n          name: sdist\n          path: dist\n      - uses: actions/download-artifact@v8\n        with:\n          name: tests\n          path: tests\n      - name: Extract sdist\n        run: |\n          tar zxvf dist/*.tar.gz --strip-components=1\n      - name: Disable ptrace security restrictions\n        run: |\n          echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope\n      - name: Build wheels\n        uses: pypa/cibuildwheel@v3.4.0\n        env:\n          CIBW_BUILD: \"cp3{7..14}{t,}-${{ matrix.wheel_type }}\"\n          CIBW_ARCHS_LINUX: ${{ matrix.cibw_archs_linux || 'auto' }}\n          CIBW_PRERELEASE_PYTHONS: True\n          CIBW_TEST_EXTRAS: test\n          CIBW_TEST_COMMAND: python -um pytest --log-cli-level=DEBUG -s -vvv {package}/tests\n      - uses: actions/upload-artifact@v7\n        with:\n          name: ${{ matrix.wheel_type }}-wheels\n          path: ./wheelhouse/*.whl\n\n  build_macosx_wheels:\n    needs: [build_sdist]\n    name: macosx_${{ matrix.arch }} wheels\n    runs-on: ${{ matrix.os }}\n    strategy:\n      fail-fast: false\n      matrix:\n        include:\n          - os: macos-15-intel\n            arch: x86_64\n          - os: macos-14\n            arch: arm64\n    steps:\n      - uses: actions/download-artifact@v8\n        with:\n          name: sdist\n          path: dist\n      - uses: actions/download-artifact@v8\n        with:\n          name: tests\n          path: tests\n      - name: Extract sdist\n        run: |\n          tar zxvf dist/*.tar.gz --strip-components=1\n      - name: Sets env vars for compilation\n        run: |\n          echo \"LZ4_INSTALL_DIR=/tmp/lz4_install\" >> $GITHUB_ENV\n          echo \"CFLAGS=-arch ${{matrix.arch}}\" >> $GITHUB_ENV\n      - name: Set x86_64-specific environment variables\n        if: matrix.arch == 'x86_64'\n        run: |\n          echo \"MACOSX_DEPLOYMENT_TARGET=10.14\" >> $GITHUB_ENV\n      - name: Set arm64-specific environment variables\n        if: matrix.arch == 'arm64'\n        run: |\n          echo \"MACOSX_DEPLOYMENT_TARGET=11.0\" >> $GITHUB_ENV\n      - name: Build wheels\n        uses: pypa/cibuildwheel@v3.4.0\n        env:\n          CIBW_BUILD: \"cp3{8..14}{t,}-*\"\n          CIBW_ARCHS: \"${{matrix.arch}}\"\n          CIBW_PRERELEASE_PYTHONS: True\n          CIBW_TEST_EXTRAS: test\n          CIBW_TEST_COMMAND: python -um pytest --log-cli-level=DEBUG -s -vvv {package}/tests\n          CIBW_BUILD_VERBOSITY: 1\n          CFLAGS: \"${{env.CFLAGS}} -I${{env.LZ4_INSTALL_DIR}}/include\"\n          LDFLAGS: \"-L${{env.LZ4_INSTALL_DIR}}/lib -Wl,-rpath,${{env.LZ4_INSTALL_DIR}}/lib\"\n          PKG_CONFIG_PATH: \"${{env.LZ4_INSTALL_DIR}}/lib/pkgconfig\"\n          CIBW_REPAIR_WHEEL_COMMAND_MACOS: \"DYLD_LIBRARY_PATH=${{env.LZ4_INSTALL_DIR}}/lib delocate-wheel --require-archs {delocate_archs} -w {dest_dir} -v {wheel}\"\n      - uses: actions/upload-artifact@v7\n        with:\n          name: macosx_${{ matrix.arch }}-wheels\n          path: ./wheelhouse/*.whl\n\n  build_and_test_wheels:\n    name: Build and test wheels\n    needs: [build_linux_wheels, build_macosx_wheels]\n    runs-on: ubuntu-latest\n    if: always() # Don't skip this step if a predecessor failed!\n    steps:\n      # We can't make a matrix job itself a required check in GitHub,\n      # so we instead add a job that depends on the two matrix jobs,\n      # and we mark this job as required instead. This job doesn't do\n      # any work, it just lets us better manage our required checks.\n      - if: \"!success()\"\n        run: echo \"Some builds failed\" && exit 1\n      - run: echo \"All builds succeeded!\"\n\n  upload_pypi:\n    needs: [build_and_test_wheels, build_sdist]\n    runs-on: ubuntu-latest\n    if: github.event_name == 'release' && github.event.action == 'published'\n    steps:\n      - uses: actions/download-artifact@v8\n        with:\n          # with no name set, it downloads all of the artifacts\n          path: dist\n      - run: |\n          mv dist/sdist/*.tar.gz dist/\n          mv dist/*-wheels/*.whl dist/\n          rmdir dist/{sdist,*-wheels}\n          rm -r dist/tests\n          ls -R dist\n      - uses: pypa/gh-action-pypi-publish@release/v1\n        with:\n          skip_existing: true\n          password: ${{ secrets.PYPI_PASSWORD }}\n"
  },
  {
    "path": ".github/workflows/coverage.yml",
    "content": "name: Coverage\n\npermissions:\n  pull-requests: write\n\non:\n  push:\n    branches:\n      - main\n  pull_request:\n    branches:\n      - main\n  release:\n    types:\n      - published\n  schedule:\n    # At 12:00 on every day-of-month\n    - cron: \"0 12 */1 * *\"\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}\n  cancel-in-progress: true\n\njobs:\n  coverage:\n    runs-on: ubuntu-24.04\n    env:\n      PYTHON: python3.13\n      MEMRAY_MINIMIZE_INLINING: 1\n    strategy:\n      fail-fast: false\n    steps:\n      - uses: actions/checkout@v6\n      - name: Set up dependencies\n        run: |\n          sudo add-apt-repository ppa:deadsnakes/ppa\n          sudo apt-get update\n          sudo apt-get install -qy \\\n            pkg-config \\\n            libdebuginfod-dev \\\n            libunwind-dev \\\n            liblz4-dev \\\n            gdb \\\n            lcov \\\n            libdw-dev \\\n            libelf-dev \\\n            ${PYTHON}-dev \\\n            ${PYTHON}-dbg \\\n            ${PYTHON}-venv\n      - name: Create a virtualenv\n        run: |\n          ${PYTHON} -m venv /tmp/coverage-venv\n      - name: Set up PATH\n        run: |\n          echo /tmp/coverage-venv/bin >>\"$GITHUB_PATH\"\n          echo /home/runner/node_modules/.bin >>\"$GITHUB_PATH\"\n      - name: Install Python dependencies\n        run: |\n          ${PYTHON} -m pip install --upgrade pip cython pkgconfig\n          make test-install\n      - name: Disable ptrace security restrictions\n        run: |\n          echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope\n      - name: Compute C++ coverage\n        run: |\n          make ccoverage\n      - name: Compute Python + Cython coverage\n        run: |\n          make pycoverage\n      - name: Upload C++ report to Codecov\n        uses: codecov/codecov-action@v5\n        with:\n          token: ${{ secrets.CODECOV_TOKEN }}\n          files: cppcoverage.lcov\n          flags: cpp\n      - name: Upload {P,C}ython report to Codecov\n        uses: codecov/codecov-action@v5\n        with:\n          token: ${{ secrets.CODECOV_TOKEN }}\n          files: pycoverage.lcov\n          flags: python_and_cython\n"
  },
  {
    "path": ".github/workflows/docs.yml",
    "content": "name: Docs\n\non:\n  push:\n    branches:\n      - main\n\njobs:\n  publish_docs:\n    name: Publish docs\n    runs-on: ubuntu-latest\n    #if: github.event_name == 'release' && github.event.action == 'published'\n    permissions:\n      contents: write\n    steps:\n      - uses: actions/checkout@v6\n      - name: Set up Python\n        uses: actions/setup-python@v6\n        with:\n          python-version: \"3.10\"\n      - name: Set up dependencies\n        run: |\n          sudo apt-get update\n          sudo apt-get install --no-install-recommends -qy libdebuginfod-dev libunwind-dev liblz4-dev pkg-config\n      - name: Install Python dependencies\n        run: |\n          python3 -m pip install -r requirements-extra.txt\n      - name: Install Package\n        run: |\n          python3 -m pip install -e .\n      - name: Build docs\n        run: |\n          make docs\n      - name: Publish docs to GitHub Pages\n        uses: JamesIves/github-pages-deploy-action@v4\n        with:\n          folder: docs/_build/html\n          single-commit: true\n"
  },
  {
    "path": ".github/workflows/news-check.yml",
    "content": "name: News entry check\non:\n  pull_request:\n    paths:\n      - \"src/memray/**\"\n    types:\n      - \"opened\"\n      - \"reopened\"\n      - \"synchronize\"\n      - \"labeled\"\n      - \"unlabeled\"\n\njobs:\n  news_entry_check:\n    runs-on: ubuntu-latest\n    name: Check for news entry\n    steps:\n      - name: \"Check for news entry\"\n        uses: brettcannon/check-for-changed-files@v1\n        with:\n          file-pattern: |\n            news/*.rst\n            NEWS.rst\n          skip-label: \"skip news\"\n          failure-message: \"Missing a news file in ${file-pattern}; please add one or apply the ${skip-label} label to the pull request\"\n"
  },
  {
    "path": ".github/workflows/sanity-check.yml",
    "content": "name: Sanity check\non:\n  pull_request:\n    types:\n      - \"opened\"\n      - \"reopened\"\n      - \"synchronize\"\n      - \"labeled\"\n      - \"unlabeled\"\n\njobs:\n  commits_check_job:\n    runs-on: ubuntu-latest\n    name: Commits Check\n    steps:\n      - name: Get PR Commits\n        id: \"get-pr-commits\"\n        uses: tim-actions/get-pr-commits@master\n        with:\n          token: ${{ secrets.GITHUB_TOKEN }}\n      - name: DCO Check\n        uses: tim-actions/dco@master\n        with:\n          commits: ${{ steps.get-pr-commits.outputs.commits }}\n"
  },
  {
    "path": ".github/workflows/test_uv_python.yml",
    "content": "name: UV Python Tests\n\non:\n  push:\n    branches:\n      - main\n  pull_request:\n    branches:\n      - main\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}\n  cancel-in-progress: true\n\njobs:\n  test_uv_python:\n    name: \"Test with UV Python 3.14\"\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v6\n\n      - name: Install uv and set Python 3.14\n        uses: astral-sh/setup-uv@v7\n        with:\n          python-version: \"3.14\"\n\n      - name: Create virtual environment\n        run: |\n          uv venv --python 3.14\n\n      - name: Set up system dependencies\n        run: |\n          sudo apt-get update\n          sudo apt-get install -qy \\\n            pkg-config \\\n            libdebuginfod-dev \\\n            libunwind-dev \\\n            liblz4-dev \\\n            gdb \\\n            npm\n\n      - name: Install Python dependencies\n        run: |\n          uv pip install --upgrade pip cython pkgconfig\n          uv pip install -r requirements-test.txt\n\n      - name: Build package\n        run: |\n          make build-js\n          uv pip install -e .\n\n      - name: Disable ptrace security restrictions\n        run: |\n          echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope\n\n      - name: Run tests\n        run: |\n          uv run pytest -vvv --log-cli-level=info tests\n"
  },
  {
    "path": ".gitignore",
    "content": "# IDE stuff\n\n.idea/*\n\n# Cmake stuff\n\nCMakeLists.txt.user\nCMakeCache.txt\nCMakeFiles\nCMakeScripts\nTesting\nMakefile\ncmake_install.cmake\ninstall_manifest.txt\ncompile_commands.json\nCTestTestfile.cmake\n_deps\n*.cbp\ncmake-build-*/\n.cmake\n\n# Cython specific files\nsrc/memray/*.cpp\nsrc/memray/_memray_api.h\n\n# Byte-compiled / optimized / DLL files\n__pycache__/\n*.py[cod]\n*$py.class\n\n# C extensions\n*.so\n\n# Distribution / packaging\n.Python\nbuild/\ndevelop-eggs/\ndist/\ndownloads/\neggs/\n.eggs/\nlib/\nlib64/\nparts/\nsdist/\nvar/\nwheels/\nshare/python-wheels/\n*.egg-info/\n.installed.cfg\n*.egg\nMANIFEST\n\n# PyInstaller\n#  Usually these files are written by a python script from a template\n#  before PyInstaller builds the exe, so as to inject date/other infos into it.\n*.manifest\n*.spec\n\n# Installer logs\npip-log.txt\npip-delete-this-directory.txt\n\n# Unit test / coverage reports\nhtmlcov/\n.tox/\n.nox/\n.coverage\n.coverage.*\n.cache\nnosetests.xml\ncoverage.xml\n*.cover\n*.py,cover\n.hypothesis/\n.pytest_cache/\ncover/\n\n# Translations\n*.mo\n*.pot\n\n# Django stuff:\n*.log\nlocal_settings.py\ndb.sqlite3\ndb.sqlite3-journal\n\n# Flask stuff:\ninstance/\n.webassets-cache\n\n# Scrapy stuff:\n.scrapy\n\n# Sphinx documentation\ndocs/_build/\n\n# PyBuilder\n.pybuilder/\ntarget/\n\n# Jupyter Notebook\n.ipynb_checkpoints\n\n# IPython\nprofile_default/\nipython_config.py\n\n# pyenv\n#   For a library or package, you might want to ignore these files since the code is\n#   intended to run in multiple environments; otherwise, check them in:\n# .python-version\n\n# pipenv\n#   According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.\n#   However, in case of collaboration, if having platform-specific dependencies or dependencies\n#   having no cross-platform support, pipenv may install dependencies that don't work, or not\n#   install all needed dependencies.\n#Pipfile.lock\n\n# PEP 582; used by e.g. github.com/David-OConnor/pyflow\n__pypackages__/\n\n# Celery stuff\ncelerybeat-schedule\ncelerybeat.pid\n\n# SageMath parsed files\n*.sage.py\n\n# Environments\n.env\n.venv\nenv/\nvenv/\nENV/\nenv.bak/\nvenv.bak/\n\n# Spyder project settings\n.spyderproject\n.spyproject\n\n# Rope project settings\n.ropeproject\n\n# mkdocs documentation\n/site\n\n# mypy\n.mypy_cache/\n.dmypy.json\ndmypy.json\n\n# Pyre type checker\n.pyre/\n\n# pytype static type analyzer\n.pytype/\n\n# Cython debug symbols\ncython_debug/\n\n# Asv stuff\n.asv\n\n# memray stuff\nmemray-*\n\n# VSCode\n.vscode\n\n# NodeJS\nnode_modules/\n\n# Vendored files\nsrc/vendor/libbacktrace/install\n\n# pytest-textual-snapshot\nsnapshot_report.html\n"
  },
  {
    "path": ".pre-commit-config.yaml",
    "content": "exclude: \"^(src/memray/reporters/templates/assets|src/vendor|benchmarks|docs/_static/flamegraphs)/\"\nrepos:\n  - repo: https://github.com/pre-commit/pre-commit-hooks\n    rev: v4.5.0\n    hooks:\n      - id: check-added-large-files\n      - id: check-json\n        exclude: \"^asv\\\\.conf\\\\.json$\"\n      - id: check-merge-conflict\n      - id: check-toml\n      - id: check-yaml\n      - id: end-of-file-fixer\n      - id: trailing-whitespace\n        exclude: \"^([.]bumpversion[.]cfg|.*/__snapshots__/)\"\n\n  - repo: https://github.com/pre-commit/pygrep-hooks\n    rev: v1.10.0\n    hooks:\n      - id: rst-directive-colons\n      - id: rst-inline-touching-normal\n\n  - repo: https://github.com/charliermarsh/ruff-pre-commit\n    rev: \"v0.1.7\"\n    hooks:\n      - id: ruff\n        args: [--fix, --exit-non-zero-on-fix]\n\n  - repo: https://github.com/psf/black\n    rev: 23.12.0\n    hooks:\n      - id: black\n\n  - repo: https://github.com/pycqa/isort\n    rev: 5.13.2\n    hooks:\n      - id: isort\n        exclude_types: [python]\n\n  - repo: https://github.com/sphinx-contrib/sphinx-lint\n    rev: v0.9.1\n    hooks:\n      - id: sphinx-lint\n\n  - repo: https://github.com/pre-commit/mirrors-prettier\n    rev: v3.1.0\n    hooks:\n      - id: prettier\n        args: [--no-editorconfig]\n        exclude: \"^asv\\\\.conf\\\\.json$\"\n        exclude_types: [html]\n\n  - repo: https://github.com/pre-commit/mirrors-clang-format\n    rev: v17.0.6\n    hooks:\n      - id: clang-format\n        args: [--Werror, -i]\n        exclude: \"^tests/integration/\"\n        types_or: [c++, c, cuda]\n\n  - repo: https://github.com/rstcheck/rstcheck\n    rev: v6.2.0\n    hooks:\n      - id: rstcheck\n        files: ^news/\n        types: [rst]\n        additional_dependencies: [\"sphinx\"]\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing\n\nBefore contributing to this repository, first please discuss the change you wish to make via an\nissue, or any other method of communication with the maintainers of this repository.\n\nYou can also search this project for issues with the following labels:\n\n| Label                                                                                                                                     | Search Term                               | Description                                                                                                                                                        |\n| ----------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| [good-first-issue](https://github.com/bloomberg/memray/search?q=is%3Aissue+is%3Aopen+label%3Agood-first-issue&type=Issues&utf8=%E2%9C%93) | `is:issue is:open label:good-first-issue` | Recommended for first-time contributors! These are well-defined, and allow a user to get familiar with the project's workflow before tackling more complex issues. |\n| [help wanted](https://github.com/bloomberg/memray/search?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22+&type=Issues&utf8=%E2%9C%93)    | `is:issue is:open label:\"help wanted\"`    | General issues where contributors help is wanted.                                                                                                                  |\n| [question](https://github.com/bloomberg/memray/search?q=is%3Aissue+is%3Aopen+label%3Aquestion&type=Issues&utf8=%E2%9C%93)                 | `is:issue is:open label:question`         | Open discussions to resolve everything from implementation details to desired functionality.                                                                       |\n\n## Contribution Licensing\n\nSince this project is distributed under the terms of an [open source license](LICENSE), contributions that\nyou make are licensed under the same terms. In order for us to be able to accept your contributions,\nwe will need explicit confirmation from you that you are able and willing to provide them under\nthese terms, and the mechanism we use to do this is called a Developer's Certificate of Origin\n[(DCO)](https://github.com/bloomberg/.github/blob/main/DCO.md). This is very similar to the process\nused by the Linux kernel, Samba, and many other major open source projects.\n\nTo participate under these terms, all that you must do is include a line like the following as the\nlast line of the commit message for each commit in your contribution:\n\n    Signed-Off-By: Random J. Developer <random@developer.example.org>\n\nThe simplest way to accomplish this is to add `-s` or `--signoff` to your `git commit` command.\n\nYou must use your real name (sorry, no pseudonyms, and no anonymous contributions).\n\n## Documentation\n\n**Public** modules, functions, classes, and methods must be documented using [Python\ndocstrings][pep 257]. **Non-public** functions and methods must also be documented for defining the\nAPI contract. In addition to being useful for generating documentation, docstrings add clarity when\nlooking through the source code or using the [built-in help][builtin-help] system, and can be\nleveraged in autocompletion by IDEs.\n\nPlease see [PEP 257][] for details on semantics and conventions associated with Python docstrings.\n\n### Docstring style\n\nDocstrings must follow [Google style docstrings][google-style]. This docstring style is more\npleasant to read when browsing the source.\n\n## Type hints\n\nAll functions and methods should be type annotated. This allows for static analysis and more\nintelligent code completion from tools & IDEs.\n\n## Tests\n\nChanges should always include tests. If this is a bug fix it is a good idea to add the tests as the\nfirst commit of the pull request and the changes to fix the issue in subsequent commits to make it\neasier to validate it.\n\n## Pull requests\n\n### Linting your code\n\nBefore commiting anything, install the pre-commit hooks:\n\n```shell\npython3 -m pip install -r requirements-extra.txt\npre-commit install\n```\n\nThis will ensure that your contribution passes our linting checks.\n\n### PRs should be linked to a GitHub issue\n\nBefore opening a pull request to this repository, first please make sure there is a GitHub issue\nwhere your change has been discussed with the maintainers. Mention the issue number in your pull\nrequest description using one of the\n[supported keywords](https://help.github.com/articles/closing-issues-using-keywords/). For example,\nadding `Closes: #100` in the pull request description will link the PR with the issue and GitHub\nwill automatically close the issue upon merging it.\n\nDo not include the issue reference in your commit messages however, add it only in the description\nof the PR.\n\n<!-- LINKS -->\n\n[pep 257]: https://www.python.org/dev/peps/pep-0257/ \"Docstring Conventions\"\n[pep 484]: https://www.python.org/dev/peps/pep-0484/ \"Type Hints\"\n[google-style]: https://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html \"Example Google Style Python Docstrings\"\n[builtin-help]: https://docs.python.org/3/library/functions.html#help\n\n<!--\nvim: tw=99:spell\n-->\n"
  },
  {
    "path": "Dockerfile",
    "content": "FROM debian:bookworm-slim\n\nARG DEBIAN_FRONTEND=noninteractive\n\nRUN apt-get update \\\n    && apt-get install -y --force-yes --no-install-recommends \\\n    build-essential \\\n    libdebuginfod-dev \\\n    libunwind-dev \\\n    liblz4-dev \\\n    pkg-config \\\n    python3-dev \\\n    python3-dbg \\\n    python3-pip \\\n    python3-venv \\\n    make \\\n    cmake \\\n    gdb \\\n    valgrind \\\n    lcov \\\n    nodejs \\\n    npm \\\n    clang-format \\\n    git \\\n    ccache \\\n    wget \\\n    && apt-get clean \\\n    && rm -rf /var/lib/apt/lists/*\n\nENV VIRTUAL_ENV=/venv \\\n    PYTHONDONTWRITEBYTECODE=1 \\\n    PATH=/bin:$PATH \\\n    CC=gcc \\\n    CXX=g++\n\nRUN python3 -m venv \"$VIRTUAL_ENV\"\n\nENV PATH=\"${VIRTUAL_ENV}/bin:/usr/lib/ccache:${PATH}\" \\\n    PYTHON=\"${VIRTUAL_ENV}/bin/python\" \\\n    MEMRAY_MINIMIZE_INLINING=\"1\"\n\nCOPY requirements-test.txt requirements-extra.txt requirements-docs.txt /tmp/\n\nRUN $PYTHON -m pip install -U \\\n    -r /tmp/requirements-extra.txt \\\n    -r /tmp/requirements-test.txt \\\n    -r /tmp/requirements-docs.txt \\\n    cython \\\n    pkgconfig \\\n    setuptools \\\n    wheel\n\nRUN npm install -g prettier\n\nWORKDIR /src\n"
  },
  {
    "path": "LICENSE",
    "content": "\n                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright 2022 Bloomberg LP\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "MANIFEST.in",
    "content": "exclude .clang-format\nexclude asv.conf.json\nexclude CONTRIBUTING.md\nexclude Dockerfile\nexclude Jenkinsfile\nexclude requirements-*.txt\nexclude .medusarc\nexclude valgrind.supp\n\nrecursive-exclude src/vendor/libbacktrace/install *\nrecursive-exclude benchmarks *\nrecursive-exclude debian *\nrecursive-exclude docker *\nrecursive-exclude docs *\nrecursive-exclude src/memray *.cpp *.h\nrecursive-exclude src/memray *.md\nrecursive-exclude tests *\nrecursive-exclude news *\nrecursive-exclude vendor *\n\ninclude README.md\ninclude Makefile\ninclude pyproject.toml\ninclude package.json\ninclude package-lock.json\ninclude .bumpversion.cfg\ninclude .babelrc\ninclude webpack.config.js\ninclude NEWS.rst\ninclude .flake8\ninclude src/memray/py.typed\ninclude .pre-commit-config.yaml\n\nrecursive-include src/vendor *\nrecursive-include src/memray *.py\nrecursive-include src/memray *.pyi\nrecursive-include src/memray *.html *.js *.css\nrecursive-include src/memray *.pyx *.pxd\nrecursive-include src/memray *.gdb *.lldb\nrecursive-include src/memray/_memray *\nrecursive-include tools *.sh\n"
  },
  {
    "path": "NEWS.rst",
    "content": ".. note\n    You should *NOT* add new change log entries to this file, this\n    file is managed by towncrier. You *may* edit previous change logs to\n    fix problems like typo corrections or such.\n\nChangelog\n=========\n\n.. towncrier release notes start\n\nmemray 1.19.2 (2026-03-12)\n--------------------------\n\nBug Fixes\n~~~~~~~~~\n\n- Add support for Python 3.14's tail call interpreter. Memray now correctly identifies Python frame boundaries in native stack traces when Python 3.14 is built with the tail call interpreter enabled (``--with-tail-call-interp``), recognizing LLVM-generated tail call functions alongside traditional ``_PyEval_EvalFrameDefault`` functions. (#836)\n- Prevent an ``AssertionError`` when the tracked process exits after the live TUI was closed. (#849)\n- Ensure the command line is properly HTML escaped when writing it into flamegraph and table reports. (#885)\n- Fix the ``--no-web`` option for ``memray flamegraph``, which was generating broken flame graphs. (#876)\n\n\nmemray 1.19.1 (2025-09-29)\n--------------------------\n\n- Fix a bug that caused Memray to refuse to produce stack traces for ``pymalloc`` allocations when ``--trace-python-allocators`` was used. (#832)\n\n\nmemray 1.19.0 (2025-09-26)\n--------------------------\n\nFeatures\n~~~~~~~~\n\n- Add a mode that can be used in Python 3.13.3 and newer where Memray will track Python object creation and destruction events, which can be used to find leaked objects (ones that were created during a tracking session and not destroyed before the end of that tracking session). (#752)\n- Added ``--no-web`` flag to ``flamegraph`` and ``table`` commands for offline HTML report generation. When this flag is specified, memray bundles all external dependencies (Bootstrap, jQuery, D3, DataTables, Plotly.js) directly into the generated HTML files instead of loading them from CDNs. This enables memray to generate fully functional HTML reports on airgapped systems without internet connectivity. (#790)\n- Reduced memory profiling overhead and capture file size by changing how\n  Python code locations are recorded. This makes allocation tracking\n  faster, produces smaller capture files, and improves the accuracy of\n  reports that group allocations by source location. (#801)\n\n\nBug Fixes\n~~~~~~~~~\n\n- Fix a crash that could occur if tracking was started in one thread while another thread was inside of a trace function installed with ``sys.settrace``. This crash wasn't possible to hit with ``memray run``, but could happen when using ``pytest-memray`` and ``pytest-cov`` together. (#823)\n- Fix timestamps on the heap usage line chart when Memray is run on a 32-bit platform. (#826)\n\n\nmemray 1.18.0 (2025-08-07)\n--------------------------\n\nFeatures\n~~~~~~~~\n\n- Add a button to the flame graph and table reports for downloading a CSV of the source data of the graph showing RSS and heap memory usage over time. (#769)\n- Peak memory usage is now included in the stats reporter. (#771)\n- Python 3.14 is now supported. (#804)\n- ``memray attach`` now supports attaching to a process using the new built-in ``sys.remote_exec`` when running in Python 3.14, rather than needing to use a debugger to inject itself. Since this is faster and safer, it is the new default, but you can still use the old methods by passing ``--method=gdb`` or ``--method=lldb`` to ``memray attach``. (#805)\n- Free-threaded builds of Python 3.14 are now supported. (#808)\n\n\nDeprecations and Removals\n~~~~~~~~~~~~~~~~~~~~~~~~~\n\n- We no longer provide musllinux_1_1 wheels. Previously they were provided for Python 3.7 through 3.13, now we provide musllinux_1_2 wheels for those Python versions instead. The manylinux project dropped support for musllinux_1_1 on November 1st, 2024. (#742)\n- We no longer provide manylinux2010 wheels. Previously they were provided for Python 3.7 through 3.12, now we provide manylinux2014 wheels for those Python versions instead. The manylinux project dropped support for manylinux2010 on August 1st, 2022. (#742)\n\n\nBug Fixes\n~~~~~~~~~\n\n- Update all Memray reporters to consistently use kilobytes rather than kibibytes and ensure that the proper SI unit labels are used. (#774)\n- Fix a bug that could have resulted in a use-after-free in a program where Memray's profile hooks were uninstalled by a call to ``PyEval_SetProfileAllThreads``. (#803)\n- Fix a potential use-after-free bug in ``memray attach``. (#808)\n\n\nmemray 1.17.2 (2025-05-08)\n--------------------------\n\nBug Fixes\n~~~~~~~~~\n\n- Fix a bug causing ``memray flamegraph --temporal`` to fail to detect the\n  correct high water mark for the selected time span. (#759)\n\n\nmemray 1.17.1 (2025-04-04)\n--------------------------\n\nBug Fixes\n~~~~~~~~~\n\n- Fix a bug that could result in an infinite loop on ARM Linux systems when a process that Memray is attached to abruptly dies. (#737)\n\n\nmemray 1.17.0 (2025-04-03)\n--------------------------\n\nBug Fixes\n~~~~~~~~~\n\n- Fix a bug with macOS version 15.4 that was causing memray to crash when the internal TLS variables were being created or destroyed. (#732)\n- A backwards incompatible change in Textual prevented the ``memray tree`` and ``memray attach`` commands from working properly. Work around this to support the latest Textual versions. (#734)\n\n\nmemray 1.16.0 (2025-03-06)\n--------------------------\n\nBug Fixes\n~~~~~~~~~\n\n- Fix the tree reporter's rendering of emojis to work for Textual 2, which no longer supports directly assigning label text using emoji shortcodes. (#714)\n\n\nmemray 1.15.0 (2024-12-03)\n--------------------------\n\nBug Fixes\n~~~~~~~~~\n\n- Fix some crashes caused by interposing symbols in memray itself (#685)\n- Fixed a bug that was causing tracking of runtime libraries that are part of the linker cache not work in macOS 15. (#693)\n- Fix a crash when a greenlet switch happens after Memray's profile function has been deactivated or replaced. (#700)\n\n\nmemray 1.14.0 (2024-09-09)\n--------------------------\n\nFeatures\n~~~~~~~~\n\n- Wheels are now published for Python 3.13, though we don't yet support free-threaded (no GIL) builds. (#658)\n\n\nBug Fixes\n~~~~~~~~~\n\n- Fix a lock ordering deadlock in libc between a Memray lock and a lock internal to dlopen. (#549)\n- Ensure flame graphs stay in flame mode when the user has selected it.\n  Previously clicking the \"Hide Irrelevant Frames\" or \"Hide Import System Frames\"\n  checkboxes would switch the flame graph back to icicle mode. (#656)\n- Fix a race condition that was able to cause strange exception messages if two different threads tried to initialize Memray tracking at once. (#667)\n\n\nmemray 1.13.4 (2024-07-18)\n--------------------------\n\nBug Fixes\n~~~~~~~~~\n\n- A backwards-incompatible change released in Textual 0.73 caused the ``memray tree`` reporter to start with no nodes expanded. This release adds a workaround to restore the old behavior of expanding the first child of each node. (#648)\n\n\nmemray 1.13.3 (2024-07-02)\n--------------------------\n\nBug Fixes\n~~~~~~~~~\n\n- Fix a bug that could result in truncated reports for applications that fork without calling :c:func:`PyOS_BeforeFork`, including by using `multiprocessing` with the \"spawn\" start method (the default on macOS). (#644)\n\n\nmemray 1.13.2 (2024-06-27)\n--------------------------\n\nBug Fixes\n~~~~~~~~~\n\n- Fix a bug that could in rare circumstances result in a stack overflow while processing native mode stacks. (#639)\n\n\nMiscellaneous\n~~~~~~~~~~~~~\n\n- Upgrade our vendored copy of ``libbacktrace``, used for reporting native stacks, to the latest version. (#639)\n\n\nmemray 1.13.1 (2024-06-23)\n--------------------------\n\nBug Fixes\n~~~~~~~~~\n\n- Fix a deadlock that could occur on some Linux systems when resolving debug information using debuginfod. (#634)\n\n\nmemray 1.13.0 (2024-06-18)\n--------------------------\n\nFeatures\n~~~~~~~~\n\n- Add :doc:`a tutorial <tutorials/index>` to the Memray documentation. (#590)\n- Include the thread name in the live TUI. (#562)\n- Capture the name attribute of Python `threading.Thread` objects. (#562)\n- Allow using Ctrl+Z to suspend ``memray tree`` and the live mode TUI. (#581)\n- Add a button in the live-mode TUI to show allocations from all threads at once. (#589)\n- Vendor ``libdebuginfod`` into our Linux wheels, so that debuginfod integration can be used without any dependency on system-installed libraries. (#592)\n\n\nBug Fixes\n~~~~~~~~~\n\n- Fix dynamic toggling between descriptions like \"Pause\" vs \"Unpause\" or \"Show\" vs \"Hide\" in the footer of the live-mode TUI and tree reporter. This was broken by changes introduced in Textual 0.61 (and again by Textual 0.63). (#597)\n- Correctly localize the start and end time in the \"Stats\" modal when an HTML report was generated on a different machine than the one it is being displayed on. (#611)\n- Fix a crash in old macOS versions (<11.0) due to the inavailability of some linker cache APIs. (#615)\n- Fix reporting of \"Own Memory\" in the ``live`` and ``summary`` reporters. A bug in our summation caused us to undercount functions' direct allocations. (#617)\n\n\nMiscellaneous\n~~~~~~~~~~~~~\n\n- Builds from source now work for Python 3.13. Wheels are not yet published for 3.13 because it is not yet ABI stable. (#622)\n- Link our Linux wheels against the latest version of ``elfutils``. (#592)\n\n\nmemray 1.12.0 (2024-03-07)\n--------------------------\n\nFeatures\n~~~~~~~~\n\n- Allow ``--temporal`` and ``--max-memory-records`` to be used with our :ref:`Jupyter magic <Jupyter integration>`. (#538)\n- Automatically use aggregated capture files for the :ref:`Jupyter magic <Jupyter integration>` whenever possible, reducing the amount of disk space needed for temporary files. (#538)\n- Expose the main thread id in the FileReader's metadata attribute. (#560)\n\n\nBug Fixes\n~~~~~~~~~\n\n- Fix a bug that was causing ``dlopen`` to not load shared libraries that have an RPATH/RUNPATH set. (#525)\n- Fix a bug where the tree reporter would fail to populate the code pane with relevant lines if the line where the allocation occurred was too near the start of the file. (#544)\n- Fix a bug causing the first entry of ``sys.path`` to be erroneously overwritten by ``memray run`` when the Python interpreter was launched with the ``-I`` or ``-P`` flag, or when the ``PYTHONSAFEPATH`` environment variable was set. (#552)\n\n\nmemray 1.11.0 (2023-12-04)\n--------------------------\n\nFeatures\n~~~~~~~~\n\n- Migrate the  :doc:`live TUI <live>` to Textual. This provides a greatly improved user experience, including the ability to scroll to view rows that don't fit on the screen. (#274)\n- Add a new documentation page to serve as :ref:`an overview of memory concepts <memory overview>`, to help users better interpret the memory profiles provided by Memray. (#496)\n- Where possible, leverage ``pkg-config`` when building the extension from source, picking up appropriate compiler and linker flags automatically. (#498)\n- Port the tree reporter to be an interactive Textual App. (#499)\n\n\nBug Fixes\n~~~~~~~~~\n\n- Fixed a bug that caused ``memray attach`` to fail with newer LLDB versions, including on macOS Sonoma. (#490)\n- Limit the number of memory records displayed in reporters by default. This will help displaying flamegraphs for long capture sessions. (#491)\n- When generating a ``--leaks`` flamegraph, don't show a warning that the ``pymalloc`` allocator is in use if ``--trace-python-allocators`` was used when generating the capture file. (#492)\n- Ensure that we update our terminal progress bars to 100% when processing finishes. (#494)\n\n\nmemray 1.10.0 (2023-10-05)\n--------------------------\n\nFeatures\n~~~~~~~~\n\n- Add support for :ref:`inverted flame graphs`. In an inverted flame graph, the\n  roots are the functions that allocated memory, and the children of any given\n  node represent the percentage of that node's allocations that can be attributed\n  to a particular caller. The inverted flame graph is very helpful in analyzing\n  where memory is being spent in aggregate. You can generate one by passing the\n  ``--inverted`` flag to ``memray flamegraph``. (#439)\n- ``memray attach`` now supports ``--aggregate`` to produce :ref:`aggregated capture files <aggregated capture files>`. (#455)\n- ``memray attach`` has been enhanced to allow tracking for only a set period of\n  time. (#458)\n- A new ``memray detach`` command allows you to manually deactivate tracking that\n  was started by a previous call to ``memray attach``. (#458)\n- Python 3.12 is now supported. (#474)\n\n\nBug Fixes\n~~~~~~~~~\n\n- Update ``memray attach`` on Linux to prefer GDB over LLDB for injecting itself into the process being attached to. We've had several reports of problems with the Linux LLDB, and hope this change will help give Linux users a better experience by default. You can still explicitly use LLDB on Linux even when GDB is detected by running ``memray attach --method=lldb``. (#449)\n- Fix a memory leak in Memray itself when many different capture files are opened by a single Memray process and native stacks are being reported. This issue primarily affected ``pytest-memray``. (#473)\n- Fix a crash in MacOS Sonoma when using system Framework libraries, like when using the ``pyobjc`` library. (#477)\n\n\nmemray 1.9.1 (2023-08-01)\n-------------------------\n\nBug Fixes\n~~~~~~~~~\n\n- Fix an issue that stopped Memray's experimental support for ``greenlet`` from working with versions of the ``greenlet`` module older than 1.0. (#432)\n- Fix a bug leading to a deadlock when Memray is used to profile an application that uses the jemalloc implementation of ``malloc``. (#433)\n- Fix a bug causing the ``summary`` reporter to generate empty reports. (#435)\n\n\nmemray 1.9.0 (2023-07-28)\n-------------------------\n\nFeatures\n~~~~~~~~\n\n- Allow to report the current version of Memray via a ``--version/-V`` command line parameter (#420)\n- Add pause/unpause keybindings to the live reporter that allows the user to pause the live reporter to analyse the current results without pausing the running program (#418)\n\n\nBug Fixes\n~~~~~~~~~\n\n- Support building with Cython 3 (#425)\n\n\nmemray 1.8.1 (2023-06-20)\n-------------------------\n\nFeatures\n~~~~~~~~\n\n- When the high water mark being shown by a temporal flame graph is before the first memory snapshot or after the last one, tell the user so by highlighting a region beyond the end of the memory usage plot. (#399)\n\n\nBug Fixes\n~~~~~~~~~\n\n- Prevent a totally empty memory plot from being shown on flame graphs when the tracked process completes before any periodic memory snapshots are captured. (#399)\n- Fix a bug that prevented the temporal high water mark flame graph from showing the flame graph of a high water mark that occurred after the final periodic memory snapshot was captured. (#399)\n- Fix a bug that prevented Memray from intercepting functions in shared objects that are part of the dyld shared cache in macOS Ventura. (#401)\n\n\nmemray 1.8.0 (2023-06-09)\n-------------------------\n\nFeatures\n~~~~~~~~\n\n- Allow ``memray stats`` to output a JSON report via ``--json`` flag. (#377)\n- We now publish x86-64 musllinux_1_1 wheels, compatible with Alpine Linux. (#379)\n- We now support :ref:`temporal flame graphs`, which provide an exciting new way of analyzing your process's memory usage over time. (#391)\n\n\nBug Fixes\n~~~~~~~~~\n\n- Fix a bug where a non-import call on the same line as an ``import`` statement would be hidden by the \"Hide Import System Frames\" checkbox of a flame graph. (#329)\n- Fixed a bug that was hitting an assert when constructing hybrid stack frames in Python 3.11 when no eval symbols are available. (#334)\n- Change the font color used by the ``%%memray_flamegraph`` Jupyter magic's progress updates for better contrast on the JupyterLab dark theme. (#344)\n- Fix a bug that could result in a deadlock when tracking a process linked against an old version of musl libc. (#379)\n\n\nmemray 1.7.0 (2023-02-21)\n-------------------------\n\nFeatures\n~~~~~~~~\n\n- ``memray run`` now supports ``--aggregate`` to produce :ref:`aggregated capture files <aggregated capture files>`, which can be much smaller but aren't able to be used for generating every type of report. (#277)\n- Add integration with debuginfod to automatically download debug information for binaries if it is available. (#308)\n- Flame graphs produced by ``memray flamegraph`` are now around 85% smaller. (#314)\n\n\nBug Fixes\n~~~~~~~~~\n\n- ``memray run --live`` and ``memray run --live-remote`` silently dropped the ``--trace-python-allocators`` flag. This has been fixed, and the flag is now properly propagated from the CLI to the tracker. (#283)\n- Fix a bug that was causing Memray to crash when the Tracker is being destroyed and some other thread is still registering allocations or deallocations (#289)\n- Work around `a bug in GDB versions before 10.1 <https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=da1df1db9ae43050c8de62e4842428ddda7eb509>`_ that could cause ``memray attach`` to fail. (#310)\n- Work around `a bug in LLDB on Linux <https://github.com/llvm/llvm-project/issues/60408>`_ that could cause ``memray attach`` to hang. (#311)\n\n\nmemray 1.6.0 (2023-01-17)\n-------------------------\n\nFeatures\n~~~~~~~~\n\n- Speed up native allocation tracking by up to 45% (#294)\n\n\nBug Fixes\n~~~~~~~~~\n\n- ``memray run --live`` and ``memray run --live-remote`` silently dropped the ``--trace-python-allocators`` flag. This has been fixed, and the flag is now properly propagated from the CLI to the tracker. (#283)\n- Fix a bug that was causing Memray to crash when the Tracker is being destroyed and some other thread is still registering allocations or deallocations (#289)\n\n\nMemray 1.5.0 (2022-12-09)\n-------------------------\n\nFeatures\n~~~~~~~~\n\n- Memray is now fully supported on macOS, and the warnings that macOS support is experimental have been dropped. (#194)\n- Add a checkbox to flamegraphs that allows hiding frames from the import system (#261)\n- ``memray attach`` can be used to :doc:`attach to a running process <attach>` (#266)\n- Consider frames from the import system as \"irrelevant\" in the generated flamegraphs. (#268)\n\n\nmemray 1.4.1 (2022-11-11)\n-------------------------\n\nBug Fixes\n~~~~~~~~~\n\n- Fix a crash that can happen when two different threads try to register frames at the same time without the GIL held. (#251)\n\n\nmemray 1.4.0 (2022-10-31)\n-------------------------\n\nFeatures\n~~~~~~~~\n\n- Add a new ``transform`` subcomand that allows transforming Memray capture files into output files compatible with other tools. We're starting by supporting conversions to the *gprof2dot* format, which allows producing graph-like reports when combined with *graphviz*. (#200)\n- Added a new ``--temporary-allocations`` option to the ``flamegraph``, ``table``, ``tree``, and ``summary`` reporters for showing the :doc:`temporary allocations </temporary_allocations>` instead of the high water mark ones. (#201)\n- When the ``greenlet`` module is in use, also assign a distinct thread ID to each greenlet. Greenlets aren't threads, but they are distinct threads of execution within a single process, with distinct stacks, so assigning different thread IDs to each makes it easier to interpret reports where ``greenlet`` was used. (#209)\n- Use a monotonic counter to generate thread IDs, rather than using the pthread ID. Those pthread IDs can be reused, making it difficult to tell what thread performed an allocation. (#209)\n- Print a warning when we detect that the Python interpreter was built without debug information or without symbols, letting the user know in advance that these conditions may result in incorrect stack traces or missing filenames and line numbers. (#211)\n- A new ``%%memray_flamegraph`` Jupyter cell magic is provided by ``%load_ext memray``, and can be used to memory profile code directly in a Jupyter notebook. (#237)\n- Add ``csv`` as a possible target format for ``memray transform``, producing a report of all of the allocations that made up the process's high water mark of allocated memory. This CSV file can then be loaded and analyzed using libraries like ``pandas``. (#241)\n\n\nDeprecations and Removals\n~~~~~~~~~~~~~~~~~~~~~~~~~\n\n- Up until now, if the program being profiled included a Cython module built with profiling support enabled, those Cython functions would show up in our Python call stacks. This was rarely useful in practice, as most Cython libraries aren't distributed with profiling support enabled, and supporting this had a surprisingly high maintenance cost. We've removed this integration, so you'll need to use ``--native`` mode to see inside of Cython modules. We are not considering this a backwards-incompatible change, since it does not affect any of our public interfaces (though it could affect the contents of reports generated by Memray). (#206)\n\n\nBug Fixes\n~~~~~~~~~\n\n- Fix a bug that caused incorrect ``--native`` mode stacks on Python 3.11 for allocations performed directly by the interpreter's eval loop. (#209)\n- Fix a crash when an extension module terminates the program using non-Python APIs under tracking. (#228)\n\n\nmemray 1.3.1 (2022-08-30)\n-------------------------\n\nBug Fixes\n~~~~~~~~~\n\n- Prevent a crash that could occur when forked processes that have been under tracking without ``follow_fork=True`` remove the profiling function with pending frames needed to be flushed to the results file. (#196)\n\n\nmemray 1.3.0 (2022-08-18)\n-------------------------\n\nFeatures\n~~~~~~~~\n\n- We now capture Python stacks for allocations made by threads that existed before the Memray tracker was started. (#130)\n- Add support for Python 3.11 (#138)\n- Add support for MacOS. (#174)\n- Add experimental support for Greenlet. (#185)\n\n\nBug Fixes\n~~~~~~~~~\n\n- Prevent a crash that could occur if the Memray API was used to stop and later restart tracking while another thread was running Python code. (#152)\n- Prevent a use-after-free bug that could result in a crash if ``sys.setprofile()`` was called while Memray was tracking. Now if ``sys.setprofile()`` is called, all future allocations on that thread will report unknown Python stacks, instead of potentially incorrect stacks. (#176)\n\n\nMemray 1.2.0 (2022-07-11)\n-------------------------\n\nFeatures\n~~~~~~~~\n\n- Add a progress bar indicator to the record processing phases in the different reporters so users can have an approximate idea of how much time processing the result files will take. (#111)\n- The ``memray stats`` reporter is now up to 50% faster, and its output is easier to interpret because it now processes all allocations by default. (#136)\n- Add a line showing the heap size over time to the memory plot in the html-based reporters (which already showed the resident size over time). (#142)\n\n\nDeprecations and Removals\n~~~~~~~~~~~~~~~~~~~~~~~~~\n\n- Remove the ``--include-all-allocations`` / ``-a`` argument to the ``memray stats`` reporter. Previously this was too slow to be used by default, but now that it has been sped up, it doesn't make sense to use anything else. The old default behavior of only processing allocations that made up the high water mark of the application's memory usage was confusing and misleading. (#136)\n\n\nBug Fixes\n~~~~~~~~~\n\n- Fix a crash with SIGBUS when the file system fills up while ``memray run`` is writing a capture file. (#117)\n- Recognize when a capture file has been truncated (most likely because the tracked process was killed unexpectedly) and ignore any incomplete record at the end of the file. (#129)\n- Fix the histogram used by the ``memray stats`` reporter to choose sane bin sizes when all captured allocations are the same size. (#133)\n- Fix the aggregation by location at the bottom of the ``memray stats`` report when the ``--include-all-allocations`` option is used. (#134)\n- Fix a bug causing deallocations with ``free`` and ``munmap`` to be included in the reported \"Total allocations\" count of ``memray stats --include-all-allocations``. (#136)\n- Fix the two \"largest allocating locations\" sections in the ``memray stats`` report to actually aggregate by location. Previously they were aggregating by distinct stacks, so if two different paths hit the same line of code, it would be counted separately instead of together. (#136)\n- Fix a bug causing memory freed by ``munmap`` to be incorrectly added into the reported \"Total memory allocated\" of ``memray stats --include-all-allocations``. (#136)\n- Exclude ``PYMALLOC_FREE`` from the allocator type distribution (other deallocators were already being ignored, but this recently added one was missed). (#136)\n- Fix the ``memray stats`` histogram to be based on the actual sizes of all allocations. Previously it only saw the sizes after a rollup by stack had already been performed, so it was binning allocation sizes that had already been summed. (#136)\n- Fixed a bug where aggregating native call stacks could give misleading results on aarch64 under some circumstances. (#141)\n- Fix a bug that made ``memray run --live -c`` fail if the command to run contained double quotes. (#147)\n- Ensure our TUI isn't displaying stale data by periodically flushing the latest available data from the tracker (rather than only flushing when a buffer fills up). (#147)\n- Fix the handling of the thread switch commands in the live mode TUI before the first allocation has been seen. (#147)\n\n\nmemray 1.1.0 (2022-05-16)\n-------------------------\n\nFeatures\n~~~~~~~~\n\n- Finalize and document the Memray :doc:`tracking API <api>`. (#42)\n- Ensure that wheels built by ``make dist`` are reproducible (so that running the build twice produces identical artifacts). (#47)\n- Reduce the size of the ``memray run`` capture file by around 20% by using a more efficient encoding for which allocator was used to perform a given allocation and whether we :ref:`captured a native stack <native tracking>` for that allocation. (#52)\n- Support ``memray run -c \"...\"`` to profile an in-line script provided on the command line. (#61)\n- The capture files produced by ``memray run`` are now around 90% smaller thanks to a more efficient encoding scheme for the binary files. (#67)\n- Add support for Alpine Linux and musl libc. (#75)\n- Capture allocations made through the C99 ``aligned_alloc`` function. (#79)\n- By default the capture file will now be compressed using LZ4 after tracking completes. This temporarily requires extra disk space while the compression runs, but results in roughly 75% less disk space required in the end. Compression can be disabled with ``--no-compress``. (#82)\n- Speed up tracking by around 5% by building with link-time optimization (LTO). (#91)\n- Add a new ``--trace-python-allocators`` option to ``memray run`` that allows tracking all allocations made using the Python allocators. This will result in bigger output files and slower profiling but it allows getting insights about all of the interpreter's memory allocations. (#92)\n\n\nBug Fixes\n~~~~~~~~~\n\n- Previously we attempted to read all allocation records into memory when processing a capture file in our reporters. This could fail on large files, so now we process the file in a streaming fashion instead. (#62)\n- Make ``memray run`` perform the same modifications to `sys.path` as the interpreter itself would when running a script. (#86)\n- Fixed a bug in the :doc:`stats reporter <stats>` that could result in the largest allocations being omitted from the histogram. (#95)\n- Fixed a bug that caused Memray reporters to display incorrect stacks when :ref:`native tracking` was enabled and native allocations from different locations occurred underneath the same Python stack. (#96)\n\n\nMiscellaneous\n~~~~~~~~~~~~~\n\n- Support the latest versions of Rich (previously we pinned to an old version due to some formatting changes in more recent versions). (#98)\n\n\nmemray 1.0.3 (2022-04-21)\n-------------------------\n\nFeatures\n~~~~~~~~\n\n- Add ``memray`` as a command line entry point. (#20)\n\nmemray 1.0.2 (2022-04-12)\n-------------------------\n\nFeatures\n~~~~~~~~\n\n- Add publishing of ManyLinux2010 wheels for 64 and 32 bit systems. (#2)\n\nBug Fixes\n~~~~~~~~~\n\n- Fix 32 bit builds. (#2)\n\n\nmemray 1.0.0 (2022-04-09)\n-------------------------\n\n-  Initial release.\n"
  },
  {
    "path": "README.md",
    "content": "<p align=\"center\">\n<img src=\"https://raw.githubusercontent.com/bloomberg/memray/main/docs/_static/images/logo.png\" width=\"70%\">\n</p>\n\n---\n\n[![OS Linux](https://img.shields.io/badge/OS-Linux-blue)](https://pypi.org/project/memray)\n[![OS MacOS](https://img.shields.io/badge/OS-macOS-blue)](https://pypi.org/project/memray)\n[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/memray)](https://pypi.org/project/memray)\n[![PyPI - Implementation](https://img.shields.io/pypi/implementation/memray)](https://pypi.org/project/memray)\n[![PyPI](https://img.shields.io/pypi/v/memray)](https://pypi.org/project/memray)\n[![PyPI - Downloads](https://img.shields.io/pypi/dm/memray)](https://pypistats.org/packages/memray)\n[![Conda Version](https://img.shields.io/conda/vn/conda-forge/memray.svg)](https://anaconda.org/conda-forge/memray)\n[![Tests](https://github.com/bloomberg/memray/actions/workflows/build.yml/badge.svg)](https://github.com/bloomberg/memray/actions/workflows/build.yml)\n[![Wheels](https://github.com/bloomberg/memray/actions/workflows/build_wheels.yml/badge.svg?branch=main)](https://github.com/bloomberg/memray/actions/workflows/build_wheels.yml)\n[![Coverage](https://github.com/bloomberg/memray/actions/workflows/coverage.yml/badge.svg?branch=main)](https://github.com/bloomberg/memray/actions/workflows/coverage.yml)\n[![Code Style](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)\n\n<p align=\"center\"><img src=\"https://raw.githubusercontent.com/bloomberg/memray/main/docs/_static/images/output.png\" alt=\"Memray output\"></p>\n\nMemray is a memory profiler for Python. It can track memory allocations in Python code, in native extension\nmodules, and in the Python interpreter itself. It can generate several different types of reports to help you\nanalyze the captured memory usage data. While commonly used as a CLI tool, it can also be used as a library to\nperform more fine-grained profiling tasks.\n\nNotable features:\n\n- 🕵️‍♀️ Traces every function call so it can accurately represent the call stack, unlike sampling profilers.\n- ℭ Also handles native calls in C/C++ libraries so the entire call stack is present in the results.\n- 🏎 Blazing fast! Profiling slows the application only slightly. Tracking native code is somewhat slower,\n  but this can be enabled or disabled on demand.\n- 📈 It can generate various reports about the collected memory usage data, like flame graphs.\n- 🧵 Works with Python threads.\n- 👽🧵 Works with native-threads (e.g. C++ threads in C extensions).\n\nMemray can help with the following problems:\n\n- Analyze allocations in applications to help discover the cause of high memory usage.\n- Find memory leaks.\n- Find hotspots in code that cause a lot of allocations.\n\n> **Note**\n> Memray only works on Linux and MacOS, and cannot be installed on other platforms.\n\n<p align=\"center\">\n<img src=\"https://raw.githubusercontent.com/bloomberg/memray/main/docs/_static/images/quotes.png\" width=\"100%\">\n</p>\n\n# Help us improve Memray!\n\nWe are constantly looking for feedback from our awesome community ❤️. If you\nhave used Memray to solve a problem, profile an application, find a memory leak\nor anything else, please let us know! We would love to hear about your\nexperience and how Memray helped you.\n\nPlease, consider writing your story in the [Success\nStories discussion page](https://github.com/bloomberg/memray/discussions/226).\n\nIt really makes a difference!\n\n# Installation\n\nMemray requires Python 3.7+ and can be easily installed using most common Python\npackaging tools. We recommend installing the latest stable release from\n[PyPI](https://pypi.org/project/memray/) with pip:\n\n```shell\n    python3 -m pip install memray\n```\n\nNotice that Memray contains a C extension so releases are distributed as binary\nwheels as well as the source code. If a binary wheel is not available for your system\n(Linux x86/x64 or macOS), you'll need to ensure that all the dependencies are satisfied on the\nsystem where you are doing the installation.\n\n## Building from source\n\nIf you wish to build Memray from source you need the following binary dependencies in your system:\n\n- libdebuginfod-dev (for Linux)\n- libunwind (for Linux)\n- liblz4\n\nCheck your package manager on how to install these dependencies (for example `apt-get install build-essential python3-dev libdebuginfod-dev libunwind-dev liblz4-dev` in Debian-based systems\nor `brew install lz4` in MacOS). Note that you may need to teach the compiler where to find the header and library files of the dependencies. For\nexample, in MacOS with `brew` you may need to run:\n\n```shell\nexport CFLAGS=\"-I$(brew --prefix lz4)/include\" LDFLAGS=\"-L$(brew --prefix lz4)/lib -Wl,-rpath,$(brew --prefix lz4)/lib\"\n```\n\nbefore installing `memray`. Check the documentation of your package manager to know the location of the header and library\nfiles for more detailed information.\n\nIf you are building on MacOS, you will also need to set the deployment target.\n\n```shell\nexport MACOSX_DEPLOYMENT_TARGET=10.14\n```\n\nOnce you have the binary dependencies installed, you can clone the repository and follow with the normal building process:\n\n```shell\ngit clone git@github.com:bloomberg/memray.git memray\ncd memray\npython3 -m venv ../memray-env/  # just an example, put this wherever you want\nsource ../memray-env/bin/activate\npython3 -m pip install --upgrade pip\npython3 -m pip install -e . -r requirements-test.txt -r requirements-extra.txt\n```\n\nThis will install Memray in the virtual environment in development mode (the `-e` of the last `pip install` command).\n\nIf you plan to contribute back, you should install the pre-commit hooks:\n\n```shell\npre-commit install\n```\n\nThis will ensure that your contribution passes our linting checks.\n\n# Documentation\n\nYou can find the latest documentation available [here](https://bloomberg.github.io/memray/).\n\n# Usage\n\nThere are many ways to use Memray. The easiest way is to use it as a command line tool to run your script, application, or library.\n\n```\nusage: memray [-h] [-v] {run,flamegraph,table,live,tree,parse,summary,stats} ...\n\nMemory profiler for Python applications\n\nRun `memray run` to generate a memory profile report, then use a reporter command\nsuch as `memray flamegraph` or `memray table` to convert the results into HTML.\n\nExample:\n\n    $ python3 -m memray run -o output.bin my_script.py\n    $ python3 -m memray flamegraph output.bin\n\npositional arguments:\n  {run,flamegraph,table,live,tree,parse,summary,stats}\n                        Mode of operation\n    run                 Run the specified application and track memory usage\n    flamegraph          Generate an HTML flame graph for peak memory usage\n    table               Generate an HTML table with all records in the peak memory usage\n    live                Remotely monitor allocations in a text-based interface\n    tree                Generate a tree view in the terminal for peak memory usage\n    parse               Debug a results file by parsing and printing each record in it\n    summary             Generate a terminal-based summary report of the functions that allocate most memory\n    stats               Generate high level stats of the memory usage in the terminal\n\noptional arguments:\n  -h, --help            Show this help message and exit\n  -v, --verbose         Increase verbosity. Option is additive and can be specified up to 3 times\n  -V, --version         Displays the current version of Memray\n\nPlease submit feedback, ideas, and bug reports by filing a new issue at https://github.com/bloomberg/memray/issues\n```\n\nTo use Memray over a script or a single python file you can use:\n\n```shell\npython3 -m memray run my_script.py\n```\n\nIf you normally run your application with `python3 -m my_module`, you can use the `-m` flag with `memray run`:\n\n```shell\npython3 -m memray run -m my_module\n```\n\nYou can also invoke Memray as a command line tool without having to use `-m` to invoke it as a module:\n\n```shell\nmemray run my_script.py\nmemray run -m my_module\n```\n\nThe output will be a binary file (like `memray-my_script.2369.bin`) that you can analyze in different ways. One way is to use the `memray flamegraph` command to generate a flame graph:\n\n```shell\nmemray flamegraph my_script.2369.bin\n```\n\nThis will produce an HTML file with a flame graph of the memory usage that you can inspect with your favorite browser. There are multiple other reporters that you can use to generate other types of reports, some of them generating terminal-based output and some of them generating HTML files. Here is an example of a Memray flamegraph:\n\n<img src=\"https://github.com/bloomberg/memray/blob/main/docs/_static/images/flamegraph_example.png?raw=true\" align=\"center\"/>\n\n## Pytest plugin\n\nIf you want an easy and convenient way to use `memray` in your test suite, you can consider using [pytest-memray](https://github.com/bloomberg/pytest-memray). Once installed, this pytest plugin allows you to simply add `--memray` to the command line invocation:\n\n```shell\npytest --memray tests/\n```\n\nAnd will automatically get a report like this:\n\n```\npython3 -m pytest tests --memray\n=============================================================================================================================== test session starts ================================================================================================================================\nplatform linux -- Python 3.8.10, pytest-6.2.4, py-1.10.0, pluggy-0.13.1\nrootdir: /mypackage, configfile: pytest.ini\nplugins: cov-2.12.0, memray-0.1.0\ncollected 21 items\n\ntests/test_package.py .....................                                                                                                                                                                                                                      [100%]\n\n\n================================================================================================================================= MEMRAY REPORT ==================================================================================================================================\nAllocations results for tests/test_package.py::some_test_that_allocates\n\n\t 📦 Total memory allocated: 24.4MiB\n\t 📏 Total allocations: 33929\n\t 📈 Peak memory usage: 10.431MB\n\t 📊 Histogram of allocation sizes: |▂   █    |\n\t 🥇 Biggest allocating functions:\n\t\t- parse:/opt/bb/lib/python3.8/ast.py:47 -> 3.0MiB\n\t\t- parse:/opt/bb/lib/python3.8/ast.py:47 -> 2.3MiB\n\t\t- _visit:/opt/bb/lib/python3.8/site-packages/astroid/transforms.py:62 -> 576.0KiB\n\t\t- parse:/opt/bb/lib/python3.8/ast.py:47 -> 517.6KiB\n\t\t- __init__:/opt/bb/lib/python3.8/site-packages/astroid/node_classes.py:1353 -> 512.0KiB\n```\n\nYou can also use some of the included markers to make tests\nfail if the execution of said test allocates more memory than allowed:\n\n```python\n@pytest.mark.limit_memory(\"24 MB\")\ndef test_foobar():\n    # do some stuff that allocates memory\n```\n\nTo learn more on how the plugin can be used and configured check out [the plugin documentation](https://pytest-memray.readthedocs.io).\n\n# Native mode\n\nMemray supports tracking native C/C++ functions as well as Python functions. This can be especially useful when profiling applications that have C extensions (such as `numpy` or `pandas`) as this gives a holistic vision of how much memory is allocated by the extension and how much is allocated by Python itself.\n\nTo activate native tracking, you need to provide the `--native` argument when using the `run` subcommand:\n\n```shell\nmemray run --native my_script.py\n```\n\nThis will automatically add native information to the result file and it will be automatically used by any reporter (such the flamegraph or table reporters). This means that instead of seeing this in the flamegraphs:\n\n<img src=\"https://github.com/bloomberg/memray/blob/main/docs/_static/images/mandelbrot_operation_non_native.png?raw=true\" align=\"center\"/>\n\nYou will now be able to see what's happening inside the Python calls:\n\n<img src=\"https://github.com/bloomberg/memray/blob/main/docs/_static/images/mandelbrot_operation_native.png?raw=true\" align=\"center\"/>\n\nReporters display native frames in a different color than Python frames. They can also be distinguished by looking at the file location in a frame (Python frames will generally be generated from files with a .py extension while native frames will be generated from files with extensions like .c, .cpp or .h).\n\n# Live mode\n\n<p align=\"center\"><img src=\"https://raw.githubusercontent.com/bloomberg/memray/main/docs/_static/images/live_animated.webp\" alt=\"Memray output\"></p>\n\nMemray's live mode runs a script or a module in a terminal-based interface that allows you to interactively inspect its memory usage while it runs. This is useful for debugging scripts or modules that take a long time to run or that exhibit multiple complex memory patterns. You can use the `--live` option to run the script or module in live mode:\n\n```shell\n    memray run --live my_script.py\n```\n\nor if you want to execute a module:\n\n```shell\n    memray run --live -m my_module\n```\n\nThis will show the following TUI interface in your terminal:\n\n<img src=\"https://raw.githubusercontent.com/bloomberg/memray/main/docs/_static/images/live_running.png\" align=\"center\"/>\n\n## Sorting results\n\nThe results are displayed in descending order of total memory allocated by a function and the subfunctions called by it. You can change the ordering with the following keyboard shortcuts:\n\n- t (default): Sort by total memory\n\n- o: Sort by own memory\n\n- a: Sort by allocation count\n\nIn most terminals you can also click the \"Sort by Total\", \"Sort by Own\", and \"Sort by Allocations\" buttons on the footer.\n\nThe sorted column's heading is underlined.\n\n## Viewing different threads\n\nBy default, the live command will present the main thread of the program. You can look at different threads of the program by pressing the greater than and less than keys, `<` and `>`. In most terminals you can also click the \"Previous Thread\" and \"Next Thread\" buttons on the footer.\n\n<img src=\"https://github.com/bloomberg/memray/blob/main/docs/_static/images/live_different_thread.png?raw=true\" align=\"center\"/>\n\n# API\n\nIn addition to tracking Python processes from a CLI using `memray run`, it is also possible to programmatically enable tracking within a running Python program.\n\n```py\nimport memray\n\nwith memray.Tracker(\"output_file.bin\"):\n    print(\"Allocations will be tracked until the with block ends\")\n```\n\nFor details, see the [API documentation](https://bloomberg.github.io/memray/api.html).\n\n# License\n\nMemray is Apache-2.0 licensed, as found in the [LICENSE](LICENSE) file.\n\n# Code of Conduct\n\n- [Code of Conduct](https://github.com/bloomberg/.github/blob/main/CODE_OF_CONDUCT.md)\n\nThis project has adopted a Code of Conduct. If you have any concerns about the Code, or behavior that you have experienced in the project, please contact us at opensource@bloomberg.net.\n\n# Security Policy\n\n- [Security Policy](https://github.com/bloomberg/memray/security/policy)\n\nIf you believe you have identified a security vulnerability in this project, please send an email to the project team at opensource@bloomberg.net, detailing the suspected issue and any methods you've found to reproduce it.\n\nPlease do NOT open an issue in the GitHub repository, as we'd prefer to keep vulnerability reports private until we've had an opportunity to review and address them.\n\n# Contributing\n\nWe welcome your contributions to help us improve and extend this project!\n\nBelow you will find some basic steps required to be able to contribute to the project. If you have any questions about this process or any other aspect of contributing to a Bloomberg open source project, feel free to send an email to opensource@bloomberg.net and we'll get your questions answered as quickly as we can.\n\n## Contribution Licensing\n\nSince this project is distributed under the terms of an [open source license](LICENSE), contributions that\nyou make are licensed under the same terms. In order for us to be able to accept your contributions,\nwe will need explicit confirmation from you that you are able and willing to provide them under\nthese terms, and the mechanism we use to do this is called a Developer's Certificate of Origin\n[(DCO)](https://github.com/bloomberg/.github/blob/main/DCO.md). This is very similar to the process\nused by the Linux kernel, Samba, and many other major open source projects.\n\nTo participate under these terms, all that you must do is include a line like the following as the\nlast line of the commit message for each commit in your contribution:\n\n    Signed-Off-By: Random J. Developer <random@developer.example.org>\n\nThe simplest way to accomplish this is to add `-s` or `--signoff` to your `git commit` command.\n\nYou must use your real name (sorry, no pseudonyms, and no anonymous contributions).\n\n## Steps\n\n- Create an Issue, select 'Feature Request', and explain the proposed change.\n- Follow the guidelines in the issue template presented to you.\n- Submit the Issue.\n- Submit a Pull Request and link it to the Issue by including \"#<issue number>\" in the Pull Request summary.\n"
  },
  {
    "path": "asv.conf.json",
    "content": "{\n    // The version of the config file format.  Do not change, unless\n    // you know what you are doing.\n    \"version\": 1,\n\n    // The name of the project being benchmarked\n    \"project\": \"memray\",\n\n    // The project's homepage\n    \"project_url\": \"\",\n\n    // The URL or local path of the source code repository for the\n    // project being benchmarked\n    \"repo\": \".\",\n\n    // The Python project's subdirectory in your repo.  If missing or\n    // the empty string, the project is assumed to be located at the root\n    // of the repository.\n    // \"repo_subdir\": \"\",\n\n    // Customizable commands for building, installing, and\n    // uninstalling the project. See asv.conf.json documentation.\n    //\n    // \"install_command\": [\"in-dir={env_dir} python -mpip install {wheel_file}\"],\n    // \"uninstall_command\": [\"return-code=any python -mpip uninstall -y {project}\"],\n    \"build_command\": [\n    \"python -m pip install cython pkgconfig\",\n    \"python setup.py build\",\n    \"PIP_NO_BUILD_ISOLATION=false python -mpip wheel --no-deps --no-index -w {build_cache_dir} {build_dir}\"\n    ],\n\n    // List of branches to benchmark. If not provided, defaults to \"main\"\n    // (for git) or \"default\" (for mercurial).\n    \"branches\": [\"main\"], // for git\n    // \"branches\": [\"default\"],    // for mercurial\n\n    // The DVCS being used.  If not set, it will be automatically\n    // determined from \"repo\" by looking at the protocol in the URL\n    // (if remote), or by looking for special directories, such as\n    // \".git\" (if local).\n    // \"dvcs\": \"git\",\n\n    // The tool to use to create environments.  May be \"conda\",\n    // \"virtualenv\" or other value depending on the plugins in use.\n    // If missing or the empty string, the tool will be automatically\n    // determined by looking for tools on the PATH environment\n    // variable.\n    \"environment_type\": \"virtualenv\",\n\n    // timeout in seconds for installing any dependencies in environment\n    // defaults to 10 min\n    //\"install_timeout\": 600,\n\n    // the base URL to show a commit for the project.\n    // \"show_commit_url\": \"http://github.com/owner/project/commit/\",\n\n    // The Pythons you'd like to test against.  If not provided, defaults\n    // to the current version of Python used to run `asv`.\n    // \"pythons\": [\"2.7\", \"3.6\"],\n\n    // The list of conda channel names to be searched for benchmark\n    // dependency packages in the specified order\n    // \"conda_channels\": [\"conda-forge\", \"defaults\"],\n\n    // The matrix of dependencies to test.  Each key is the name of a\n    // package (in PyPI) and the values are version numbers.  An empty\n    // list or empty string indicates to just test against the default\n    // (latest) version. null indicates that the package is to not be\n    // installed. If the package to be tested is only available from\n    // PyPi, and the 'environment_type' is conda, then you can preface\n    // the package name by 'pip+', and the package will be installed via\n    // pip (with all the conda available packages installed first,\n    // followed by the pip installed packages).\n    //\n    // \"matrix\": {\n    //     \"numpy\": [\"1.6\", \"1.7\"],\n    //     \"six\": [\"\", null],        // test with and without six installed\n    //     \"pip+emcee\": [\"\"],   // emcee is only available for install with pip.\n    // },\n\n    // Combinations of libraries/python versions can be excluded/included\n    // from the set to test. Each entry is a dictionary containing additional\n    // key-value pairs to include/exclude.\n    //\n    // An exclude entry excludes entries where all values match. The\n    // values are regexps that should match the whole string.\n    //\n    // An include entry adds an environment. Only the packages listed\n    // are installed. The 'python' key is required. The exclude rules\n    // do not apply to includes.\n    //\n    // In addition to package names, the following keys are available:\n    //\n    // - python\n    //     Python version, as in the *pythons* variable above.\n    // - environment_type\n    //     Environment type, as above.\n    // - sys_platform\n    //     Platform, as in sys.platform. Possible values for the common\n    //     cases: 'linux2', 'win32', 'cygwin', 'darwin'.\n    //\n    // \"exclude\": [\n    //     {\"python\": \"3.2\", \"sys_platform\": \"win32\"}, // skip py3.2 on windows\n    //     {\"environment_type\": \"conda\", \"six\": null}, // don't run without six on conda\n    // ],\n    //\n    // \"include\": [\n    //     // additional env for python2.7\n    //     {\"python\": \"2.7\", \"numpy\": \"1.8\"},\n    //     // additional env if run on windows+conda\n    //     {\"platform\": \"win32\", \"environment_type\": \"conda\", \"python\": \"2.7\", \"libpython\": \"\"},\n    // ],\n\n    // The directory (relative to the current directory) that benchmarks are\n    // stored in.  If not provided, defaults to \"benchmarks\"\n    \"benchmark_dir\": \"benchmarks\",\n\n    // The directory (relative to the current directory) to cache the Python\n    // environments in.  If not provided, defaults to \"env\"\n    \"env_dir\": \".asv/env\",\n\n    // The directory (relative to the current directory) that raw benchmark\n    // results are stored in.  If not provided, defaults to \"results\".\n    \"results_dir\": \".asv/results\",\n\n    // The directory (relative to the current directory) that the html tree\n    // should be written to.  If not provided, defaults to \"html\".\n    \"html_dir\": \".asv/html\",\n\n    // The number of characters to retain in the commit hashes.\n    // \"hash_length\": 8,\n\n    // `asv` will cache results of the recent builds in each\n    // environment, making them faster to install next time.  This is\n    // the number of builds to keep, per environment.\n    // \"build_cache_size\": 2,\n\n    // The commits after which the regression search in `asv publish`\n    // should start looking for regressions. Dictionary whose keys are\n    // regexps matching to benchmark names, and values corresponding to\n    // the commit (exclusive) after which to start looking for\n    // regressions.  The default is to start from the first commit\n    // with results. If the commit is `null`, regression detection is\n    // skipped for the matching benchmark.\n    //\n    // \"regressions_first_commits\": {\n    //    \"some_benchmark\": \"352cdf\",  // Consider regressions only after this commit\n    //    \"another_benchmark\": null,   // Skip regression detection altogether\n    // },\n\n    // The thresholds for relative change in results, after which `asv\n    // publish` starts reporting regressions. Dictionary of the same\n    // form as in ``regressions_first_commits``, with values\n    // indicating the thresholds.  If multiple entries match, the\n    // maximum is taken. If no entry matches, the default is 5%.\n    //\n    // \"regressions_thresholds\": {\n    //    \"some_benchmark\": 0.01,     // Threshold of 1%\n    //    \"another_benchmark\": 0.5,   // Threshold of 50%\n    // },\n}\n"
  },
  {
    "path": "benchmarks/__init__.py",
    "content": ""
  },
  {
    "path": "benchmarks/benchmarking/__main__.py",
    "content": "import dataclasses\nimport json\nimport pathlib\nimport subprocess\nimport sys\nimport tempfile\nfrom typing import List\n\nfrom .plot import plot_diff\n\nCASES_DIR = pathlib.Path(__file__).parent / \"cases\"\nRESULTS_DIR = pathlib.Path(__file__).parent / \"results\"\nDOCUTILS_DATA = pathlib.Path(__file__).parent / \"cases\" / \"docutils_data\" / \"docs\"\nTELCO_DATA = pathlib.Path(__file__).parent / \"cases\" / \"telco_data\" / \"telco-bench.b\"\n\n\n@dataclasses.dataclass\nclass Case:\n    name: str\n    file_name: str\n    arguments: List[str] = dataclasses.field(default_factory=list)\n\n    def run_case(\n        self,\n        run_name: str,\n        template_file: pathlib.Path,\n        tracker_options: str,\n        results_file: str,\n    ) -> None:\n        with tempfile.TemporaryDirectory() as tmpdirname:\n            case_file = pathlib.Path(tmpdirname) / f\"{self.file_name}.py\"\n            code = template_file.read_text()\n            case_file.write_text(code)\n\n            helper_file = pathlib.Path(tmpdirname) / \"memray_helper.py\"\n            helper_code = (\n                \"import memray\\nimport contextlib\\n\"\n                f\"def get_tracker():\\n    return {tracker_options}\"\n            )\n            helper_file.write_text(helper_code)\n\n            results_file = RESULTS_DIR / results_file\n            print(f\"Running {self.name} with arguments {self.arguments} - {run_name}\")\n            subprocess.run(\n                [sys.executable, case_file, \"-o\", results_file] + self.arguments,\n                check=True,\n            )\n\n    def run(self) -> None:\n        template_file = CASES_DIR / f\"{self.file_name}_memray.py\"\n        if not template_file.exists():\n            raise ValueError(f\"Case {self.name} does not exist.\")\n\n        self.run_case(\n            \"\", template_file, \"contextlib.nullcontext()\", f\"{self.name}.json\"\n        )\n\n        self.run_case(\n            \"memray base\",\n            template_file,\n            \"memray.Tracker('/dev/null')\",\n            f\"{self.name}_memray.json\",\n        )\n\n        self.run_case(\n            \"memray python allocators\",\n            template_file,\n            \"memray.Tracker('/dev/null', trace_python_allocators=True)\",\n            f\"{self.name}_memray_python_allocators.json\",\n        )\n\n        self.run_case(\n            \"memray python native\",\n            template_file,\n            \"memray.Tracker('/dev/null', native_traces=True)\",\n            f\"{self.name}_memray_python_native.json\",\n        )\n\n        self.run_case(\n            \"memray python all\",\n            template_file,\n            \"memray.Tracker('/dev/null', trace_python_allocators=True, native_traces=True)\",\n            f\"{self.name}_memray_python_all.json\",\n        )\n\n\nCASES = [\n    Case(\"docutils\", \"docutils_html\", [f\"--doc_root={DOCUTILS_DATA}\"]),\n    Case(\"raytrace\", \"raytrace\", []),\n    Case(\"fannkuch\", \"fannkuch\", []),\n    Case(\"pprint\", \"pprint_format\", []),\n    Case(\"mdp\", \"mdp\", []),\n    Case(\"async_tree\", \"async_tree\", [\"none\"]),\n    Case(\"async_tree_io\", \"async_tree\", [\"io\"]),\n    Case(\"async_tree_mem\", \"async_tree\", [\"memoization\"]),\n    Case(\"async_tree_cpu_io\", \"async_tree\", [\"cpu_io_mixed\"]),\n    Case(\"deltablue\", \"deltablue\", []),\n    Case(\"nbody\", \"nbody\", []),\n    Case(\"nqueens\", \"nqueens\", []),\n    Case(\"regex_dna\", \"regex_dna\", []),\n    Case(\"go\", \"go\", []),\n    Case(\"hexion\", \"hexion\", []),\n    Case(\"meteor_context\", \"meteor_context\", []),\n    Case(\"json_dumps\", \"json_dumps\", []),\n    Case(\"json_loads\", \"json_loads\", []),\n    Case(\n        \"picke_pure_python\",\n        \"pickles\",\n        [\n            \"pickle\",\n            \"--pure-python\",\n        ],\n    ),\n    Case(\"picke\", \"pickles\", [\"pickle\"]),\n    Case(\n        \"unpicke_pure_python\",\n        \"pickles\",\n        [\n            \"unpickle\",\n            \"--pure-python\",\n        ],\n    ),\n    Case(\"unpicke\", \"pickles\", [\"unpickle\"]),\n    Case(\n        \"pickle_list_pure_python\",\n        \"pickles\",\n        [\n            \"pickle_list\",\n            \"--pure-python\",\n        ],\n    ),\n    Case(\"pickle_list\", \"pickles\", [\"pickle_list\"]),\n    Case(\n        \"unpickle_list_pure_python\",\n        \"pickles\",\n        [\n            \"unpickle_list\",\n            \"--pure-python\",\n        ],\n    ),\n    Case(\"unpickle_list\", \"pickles\", [\"unpickle_list\"]),\n    Case(\n        \"pickle_dict_pure_python\",\n        \"pickles\",\n        [\n            \"pickle_dict\",\n            \"--pure-python\",\n        ],\n    ),\n    Case(\"pickle_dict\", \"pickles\", [\"pickle_dict\"]),\n    Case(\"spectral_norm\", \"spectral_norm\", []),\n    Case(\"telco\", \"telco\", [f\"--doc_root={TELCO_DATA}\"]),\n    Case(\"sqlite_synth\", \"sqlite_synth\", []),\n    Case(\"regex_v8\", \"regex_v8\", []),\n    Case(\"regex_effbot\", \"regex_effbot\", []),\n    Case(\"regex_effbot_bytes\", \"regex_effbot\", [\"--force_bytes\"]),\n]\n\n\n@dataclasses.dataclass\nclass BenchmarkResult:\n    name: str\n    data: List\n\n\ndef gather_benchmarks(cases):\n    results = []\n    names = (\"\", \"Defaut\", \"Python allocators\", \"Native\", \"Python allocators + Native\")\n    extensions = (\n        \"\",\n        \"_memray\",\n        \"_memray_python_allocators\",\n        \"_memray_python_native\",\n        \"_memray_python_all\",\n    )\n    for name, extension in zip(names, extensions):\n        type_results = []\n        for case in cases:\n            memray_results_file = RESULTS_DIR / f\"{case.name}{extension}.json\"\n            data = json.loads(memray_results_file.read_text())\n            type_results.append(data)\n        results.append(BenchmarkResult(name=name, data=type_results))\n    return results\n\n\nif __name__ == \"__main__\":\n    # if RESULTS_DIR.exists():\n    #     raise RuntimeError(f\"Results directory {RESULTS_DIR} already exists\")\n\n    # RESULTS_DIR.mkdir()\n\n    for case in CASES:\n        case.run()\n\n    base_results, *memray_results = gather_benchmarks(CASES)\n    for memray_result in memray_results:\n        plot_diff(\n            memray_result,\n            base_results,\n            f\"plot_{memray_result.name}.png\".replace(\" \", \"_\").lower(),\n            f\"Overhead of Memray with {memray_result.name}\",\n        )\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/__init__.py",
    "content": ""
  },
  {
    "path": "benchmarks/benchmarking/cases/async_tree_base.py",
    "content": "\"\"\"\nBenchmark for async tree workload, which calls asyncio.gather() on a tree\n(6 levels deep, 6 branches per level) with the leaf nodes simulating some\n(potentially) async work (depending on the benchmark variant). Benchmark\nvariants include:\n\n1) \"none\": No actual async work in the async tree.\n2) \"io\": All leaf nodes simulate async IO workload (async sleep 50ms).\n3) \"memoization\": All leaf nodes simulate async IO workload with 90% of \n                  the data memoized\n4) \"cpu_io_mixed\": Half of the leaf nodes simulate CPU-bound workload and \n                   the other half simulate the same workload as the \n                   \"memoization\" variant.\n\"\"\"\n\nimport sys\nimport asyncio\nimport math\nimport random\n\nNUM_RECURSE_LEVELS = 6\nNUM_RECURSE_BRANCHES = 6\nRANDOM_SEED = 0\nIO_SLEEP_TIME = 0.05\nMEMOIZABLE_PERCENTAGE = 90\nCPU_PROBABILITY = 0.5\nFACTORIAL_N = 500\n\n\nclass AsyncTree:\n    def __init__(self):\n        self.cache = {}\n        # set to deterministic random, so that the results are reproducible\n        random.seed(RANDOM_SEED)\n\n    async def mock_io_call(self):\n        await asyncio.sleep(IO_SLEEP_TIME)\n\n    async def workload_func(self):\n        raise NotImplementedError(\"To be implemented by each variant's derived class.\")\n\n    async def recurse(self, recurse_level):\n        if recurse_level == 0:\n            await self.workload_func()\n            return\n\n        await asyncio.gather(\n            *[self.recurse(recurse_level - 1) for _ in range(NUM_RECURSE_BRANCHES)]\n        )\n\n    async def run(self):\n        await self.recurse(NUM_RECURSE_LEVELS)\n\n\nclass NoneAsyncTree(AsyncTree):\n    async def workload_func(self):\n        return\n\n\nclass IOAsyncTree(AsyncTree):\n    async def workload_func(self):\n        await self.mock_io_call()\n\n\nclass MemoizationAsyncTree(AsyncTree):\n    async def workload_func(self):\n        # deterministic random, seed set in AsyncTree.__init__()\n        data = random.randint(1, 100)\n\n        if data <= MEMOIZABLE_PERCENTAGE:\n            if self.cache.get(data):\n                return data\n\n            self.cache[data] = True\n\n        await self.mock_io_call()\n        return data\n\n\nclass CpuIoMixedAsyncTree(MemoizationAsyncTree):\n    async def workload_func(self):\n        # deterministic random, seed set in AsyncTree.__init__()\n        if random.random() < CPU_PROBABILITY:\n            # mock cpu-bound call\n            return math.factorial(FACTORIAL_N)\n        else:\n            return await MemoizationAsyncTree.workload_func(self)\n\n\ndef add_metadata(runner):\n    runner.metadata[\"description\"] = \"Async tree workloads.\"\n    runner.metadata[\"async_tree_recurse_levels\"] = NUM_RECURSE_LEVELS\n    runner.metadata[\"async_tree_recurse_branches\"] = NUM_RECURSE_BRANCHES\n    runner.metadata[\"async_tree_random_seed\"] = RANDOM_SEED\n    runner.metadata[\"async_tree_io_sleep_time\"] = IO_SLEEP_TIME\n    runner.metadata[\"async_tree_memoizable_percentage\"] = MEMOIZABLE_PERCENTAGE\n    runner.metadata[\"async_tree_cpu_probability\"] = CPU_PROBABILITY\n    runner.metadata[\"async_tree_factorial_n\"] = FACTORIAL_N\n\n\ndef add_cmdline_args(cmd, args):\n    cmd.append(args.benchmark)\n\n\ndef add_parser_args(parser):\n    parser.add_argument(\n        \"benchmark\",\n        choices=BENCHMARKS,\n        help=\"\"\"\\\nDetermines which benchmark to run. Options:\n1) \"none\": No actual async work in the async tree.\n2) \"io\": All leaf nodes simulate async IO workload (async sleep 50ms).\n3) \"memoization\": All leaf nodes simulate async IO workload with 90% of \n                  the data memoized\n4) \"cpu_io_mixed\": Half of the leaf nodes simulate CPU-bound workload and \n                   the other half simulate the same workload as the \n                   \"memoization\" variant.\n\"\"\",\n    )\n\n\nBENCHMARKS = {\n    \"none\": NoneAsyncTree,\n    \"io\": IOAsyncTree,\n    \"memoization\": MemoizationAsyncTree,\n    \"cpu_io_mixed\": CpuIoMixedAsyncTree,\n}\n\n\ndef run_benchmark(benchmark):\n    async_tree_class = BENCHMARKS[benchmark]\n    async_tree = async_tree_class()\n    asyncio.run(async_tree.run())\n\n\nif __name__ == \"__main__\":\n    benchmark = sys.argv[1]\n    run_benchmark(benchmark)\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/async_tree_memray.py",
    "content": "\"\"\"\nBenchmark for async tree workload, which calls asyncio.gather() on a tree\n(6 levels deep, 6 branches per level) with the leaf nodes simulating some\n(potentially) async work (depending on the benchmark variant). Benchmark\nvariants include:\n\n1) \"none\": No actual async work in the async tree.\n2) \"io\": All leaf nodes simulate async IO workload (async sleep 50ms).\n3) \"memoization\": All leaf nodes simulate async IO workload with 90% of \n                  the data memoized\n4) \"cpu_io_mixed\": Half of the leaf nodes simulate CPU-bound workload and \n                   the other half simulate the same workload as the \n                   \"memoization\" variant.\n\"\"\"\n\n\nimport asyncio\nimport math\nimport random\nfrom memray_helper import get_tracker\n\nimport pyperf\n\n\nNUM_RECURSE_LEVELS = 6\nNUM_RECURSE_BRANCHES = 6\nRANDOM_SEED = 0\nIO_SLEEP_TIME = 0.05\nMEMOIZABLE_PERCENTAGE = 90\nCPU_PROBABILITY = 0.5\nFACTORIAL_N = 500\n\n\nclass AsyncTree:\n    def __init__(self):\n        self.cache = {}\n        # set to deterministic random, so that the results are reproducible\n        random.seed(RANDOM_SEED)\n\n    async def mock_io_call(self):\n        await asyncio.sleep(IO_SLEEP_TIME)\n\n    async def workload_func(self):\n        raise NotImplementedError(\"To be implemented by each variant's derived class.\")\n\n    async def recurse(self, recurse_level):\n        if recurse_level == 0:\n            await self.workload_func()\n            return\n\n        await asyncio.gather(\n            *[self.recurse(recurse_level - 1) for _ in range(NUM_RECURSE_BRANCHES)]\n        )\n\n    async def run(self):\n        with get_tracker():\n            await self.recurse(NUM_RECURSE_LEVELS)\n\n\nclass NoneAsyncTree(AsyncTree):\n    async def workload_func(self):\n        return\n\n\nclass IOAsyncTree(AsyncTree):\n    async def workload_func(self):\n        await self.mock_io_call()\n\n\nclass MemoizationAsyncTree(AsyncTree):\n    async def workload_func(self):\n        # deterministic random, seed set in AsyncTree.__init__()\n        data = random.randint(1, 100)\n\n        if data <= MEMOIZABLE_PERCENTAGE:\n            if self.cache.get(data):\n                return data\n\n            self.cache[data] = True\n\n        await self.mock_io_call()\n        return data\n\n\nclass CpuIoMixedAsyncTree(MemoizationAsyncTree):\n    async def workload_func(self):\n        # deterministic random, seed set in AsyncTree.__init__()\n        if random.random() < CPU_PROBABILITY:\n            # mock cpu-bound call\n            return math.factorial(FACTORIAL_N)\n        else:\n            return await MemoizationAsyncTree.workload_func(self)\n\n\ndef add_metadata(runner):\n    runner.metadata[\"description\"] = \"Async tree workloads.\"\n    runner.metadata[\"async_tree_recurse_levels\"] = NUM_RECURSE_LEVELS\n    runner.metadata[\"async_tree_recurse_branches\"] = NUM_RECURSE_BRANCHES\n    runner.metadata[\"async_tree_random_seed\"] = RANDOM_SEED\n    runner.metadata[\"async_tree_io_sleep_time\"] = IO_SLEEP_TIME\n    runner.metadata[\"async_tree_memoizable_percentage\"] = MEMOIZABLE_PERCENTAGE\n    runner.metadata[\"async_tree_cpu_probability\"] = CPU_PROBABILITY\n    runner.metadata[\"async_tree_factorial_n\"] = FACTORIAL_N\n\n\ndef add_cmdline_args(cmd, args):\n    cmd.append(args.benchmark)\n\n\ndef add_parser_args(parser):\n    parser.add_argument(\n        \"benchmark\",\n        choices=BENCHMARKS,\n        help=\"\"\"\\\nDetermines which benchmark to run. Options:\n1) \"none\": No actual async work in the async tree.\n2) \"io\": All leaf nodes simulate async IO workload (async sleep 50ms).\n3) \"memoization\": All leaf nodes simulate async IO workload with 90% of \n                  the data memoized\n4) \"cpu_io_mixed\": Half of the leaf nodes simulate CPU-bound workload and \n                   the other half simulate the same workload as the \n                   \"memoization\" variant.\n\"\"\",\n    )\n\n\nBENCHMARKS = {\n    \"none\": NoneAsyncTree,\n    \"io\": IOAsyncTree,\n    \"memoization\": MemoizationAsyncTree,\n    \"cpu_io_mixed\": CpuIoMixedAsyncTree,\n}\n\n\nif __name__ == \"__main__\":\n    runner = pyperf.Runner(add_cmdline_args=add_cmdline_args)\n    add_metadata(runner)\n    add_parser_args(runner.argparser)\n    args = runner.parse_args()\n    benchmark = args.benchmark\n\n    async_tree_class = BENCHMARKS[benchmark]\n    async_tree = async_tree_class()\n    runner.bench_async_func(f\"async_tree_{benchmark}\", async_tree.run)\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/deltablue_base.py",
    "content": "\"\"\"\ndeltablue.py\n============\n\nPorted for the PyPy project.\nContributed by Daniel Lindsley\n\nThis implementation of the DeltaBlue benchmark was directly ported\nfrom the `V8's source code`_, which was in turn derived\nfrom the Smalltalk implementation by John Maloney and Mario\nWolczko. The original Javascript implementation was licensed under the GPL.\n\nIt's been updated in places to be more idiomatic to Python (for loops over\ncollections, a couple magic methods, ``OrderedCollection`` being a list & things\naltering those collections changed to the builtin methods) but largely retains\nthe layout & logic from the original. (Ugh.)\n\n.. _`V8's source code`: (https://github.com/v8/v8/blob/master/benchmarks/deltablue.js)\n\"\"\"\n\n# The JS variant implements \"OrderedCollection\", which basically completely\n# overlaps with ``list``. So we'll cheat. :D\nclass OrderedCollection(list):\n    pass\n\n\nclass Strength(object):\n    REQUIRED = None\n    STRONG_PREFERRED = None\n    PREFERRED = None\n    STRONG_DEFAULT = None\n    NORMAL = None\n    WEAK_DEFAULT = None\n    WEAKEST = None\n\n    def __init__(self, strength, name):\n        super(Strength, self).__init__()\n        self.strength = strength\n        self.name = name\n\n    @classmethod\n    def stronger(cls, s1, s2):\n        return s1.strength < s2.strength\n\n    @classmethod\n    def weaker(cls, s1, s2):\n        return s1.strength > s2.strength\n\n    @classmethod\n    def weakest_of(cls, s1, s2):\n        if cls.weaker(s1, s2):\n            return s1\n\n        return s2\n\n    @classmethod\n    def strongest(cls, s1, s2):\n        if cls.stronger(s1, s2):\n            return s1\n\n        return s2\n\n    def next_weaker(self):\n        strengths = {\n            0: self.__class__.WEAKEST,\n            1: self.__class__.WEAK_DEFAULT,\n            2: self.__class__.NORMAL,\n            3: self.__class__.STRONG_DEFAULT,\n            4: self.__class__.PREFERRED,\n            # TODO: This looks like a bug in the original code. Shouldn't this be\n            #       ``STRONG_PREFERRED? Keeping for porting sake...\n            5: self.__class__.REQUIRED,\n        }\n        return strengths[self.strength]\n\n\n# This is a terrible pattern IMO, but true to the original JS implementation.\nStrength.REQUIRED = Strength(0, \"required\")\nStrength.STRONG_PREFERRED = Strength(1, \"strongPreferred\")\nStrength.PREFERRED = Strength(2, \"preferred\")\nStrength.STRONG_DEFAULT = Strength(3, \"strongDefault\")\nStrength.NORMAL = Strength(4, \"normal\")\nStrength.WEAK_DEFAULT = Strength(5, \"weakDefault\")\nStrength.WEAKEST = Strength(6, \"weakest\")\n\n\nclass Constraint(object):\n    def __init__(self, strength):\n        super(Constraint, self).__init__()\n        self.strength = strength\n\n    def add_constraint(self):\n        global planner\n        self.add_to_graph()\n        planner.incremental_add(self)\n\n    def satisfy(self, mark):\n        global planner\n        self.choose_method(mark)\n\n        if not self.is_satisfied():\n            if self.strength == Strength.REQUIRED:\n                print(\"Could not satisfy a required constraint!\")\n\n            return None\n\n        self.mark_inputs(mark)\n        out = self.output()\n        overridden = out.determined_by\n\n        if overridden is not None:\n            overridden.mark_unsatisfied()\n\n        out.determined_by = self\n\n        if not planner.add_propagate(self, mark):\n            print(\"Cycle encountered\")\n\n        out.mark = mark\n        return overridden\n\n    def destroy_constraint(self):\n        global planner\n        if self.is_satisfied():\n            planner.incremental_remove(self)\n        else:\n            self.remove_from_graph()\n\n    def is_input(self):\n        return False\n\n\nclass UrnaryConstraint(Constraint):\n    def __init__(self, v, strength):\n        super(UrnaryConstraint, self).__init__(strength)\n        self.my_output = v\n        self.satisfied = False\n        self.add_constraint()\n\n    def add_to_graph(self):\n        self.my_output.add_constraint(self)\n        self.satisfied = False\n\n    def choose_method(self, mark):\n        if self.my_output.mark != mark and Strength.stronger(\n            self.strength, self.my_output.walk_strength\n        ):\n            self.satisfied = True\n        else:\n            self.satisfied = False\n\n    def is_satisfied(self):\n        return self.satisfied\n\n    def mark_inputs(self, mark):\n        # No-ops.\n        pass\n\n    def output(self):\n        # Ugh. Keeping it for consistency with the original. So much for\n        # \"we're all adults here\"...\n        return self.my_output\n\n    def recalculate(self):\n        self.my_output.walk_strength = self.strength\n        self.my_output.stay = not self.is_input()\n\n        if self.my_output.stay:\n            self.execute()\n\n    def mark_unsatisfied(self):\n        self.satisfied = False\n\n    def inputs_known(self, mark):\n        return True\n\n    def remove_from_graph(self):\n        if self.my_output is not None:\n            self.my_output.remove_constraint(self)\n            self.satisfied = False\n\n\nclass StayConstraint(UrnaryConstraint):\n    def __init__(self, v, string):\n        super(StayConstraint, self).__init__(v, string)\n\n    def execute(self):\n        # The methods, THEY DO NOTHING.\n        pass\n\n\nclass EditConstraint(UrnaryConstraint):\n    def __init__(self, v, string):\n        super(EditConstraint, self).__init__(v, string)\n\n    def is_input(self):\n        return True\n\n    def execute(self):\n        # This constraint also does nothing.\n        pass\n\n\nclass Direction(object):\n    # Hooray for things that ought to be structs!\n    NONE = 0\n    FORWARD = 1\n    BACKWARD = -1\n\n\nclass BinaryConstraint(Constraint):\n    def __init__(self, v1, v2, strength):\n        super(BinaryConstraint, self).__init__(strength)\n        self.v1 = v1\n        self.v2 = v2\n        self.direction = Direction.NONE\n        self.add_constraint()\n\n    def choose_method(self, mark):\n        if self.v1.mark == mark:\n            if self.v2.mark != mark and Strength.stronger(\n                self.strength, self.v2.walk_strength\n            ):\n                self.direction = Direction.FORWARD\n            else:\n                self.direction = Direction.BACKWARD\n\n        if self.v2.mark == mark:\n            if self.v1.mark != mark and Strength.stronger(\n                self.strength, self.v1.walk_strength\n            ):\n                self.direction = Direction.BACKWARD\n            else:\n                self.direction = Direction.NONE\n\n        if Strength.weaker(self.v1.walk_strength, self.v2.walk_strength):\n            if Strength.stronger(self.strength, self.v1.walk_strength):\n                self.direction = Direction.BACKWARD\n            else:\n                self.direction = Direction.NONE\n        else:\n            if Strength.stronger(self.strength, self.v2.walk_strength):\n                self.direction = Direction.FORWARD\n            else:\n                self.direction = Direction.BACKWARD\n\n    def add_to_graph(self):\n        self.v1.add_constraint(self)\n        self.v2.add_constraint(self)\n        self.direction = Direction.NONE\n\n    def is_satisfied(self):\n        return self.direction != Direction.NONE\n\n    def mark_inputs(self, mark):\n        self.input().mark = mark\n\n    def input(self):\n        if self.direction == Direction.FORWARD:\n            return self.v1\n\n        return self.v2\n\n    def output(self):\n        if self.direction == Direction.FORWARD:\n            return self.v2\n\n        return self.v1\n\n    def recalculate(self):\n        ihn = self.input()\n        out = self.output()\n        out.walk_strength = Strength.weakest_of(self.strength, ihn.walk_strength)\n        out.stay = ihn.stay\n\n        if out.stay:\n            self.execute()\n\n    def mark_unsatisfied(self):\n        self.direction = Direction.NONE\n\n    def inputs_known(self, mark):\n        i = self.input()\n        return i.mark == mark or i.stay or i.determined_by is None\n\n    def remove_from_graph(self):\n        if self.v1 is not None:\n            self.v1.remove_constraint(self)\n\n        if self.v2 is not None:\n            self.v2.remove_constraint(self)\n\n        self.direction = Direction.NONE\n\n\nclass ScaleConstraint(BinaryConstraint):\n    def __init__(self, src, scale, offset, dest, strength):\n        self.direction = Direction.NONE\n        self.scale = scale\n        self.offset = offset\n        super(ScaleConstraint, self).__init__(src, dest, strength)\n\n    def add_to_graph(self):\n        super(ScaleConstraint, self).add_to_graph()\n        self.scale.add_constraint(self)\n        self.offset.add_constraint(self)\n\n    def remove_from_graph(self):\n        super(ScaleConstraint, self).remove_from_graph()\n\n        if self.scale is not None:\n            self.scale.remove_constraint(self)\n\n        if self.offset is not None:\n            self.offset.remove_constraint(self)\n\n    def mark_inputs(self, mark):\n        super(ScaleConstraint, self).mark_inputs(mark)\n        self.scale.mark = mark\n        self.offset.mark = mark\n\n    def execute(self):\n        if self.direction == Direction.FORWARD:\n            self.v2.value = self.v1.value * self.scale.value + self.offset.value\n        else:\n            self.v1.value = (self.v2.value - self.offset.value) / self.scale.value\n\n    def recalculate(self):\n        ihn = self.input()\n        out = self.output()\n        out.walk_strength = Strength.weakest_of(self.strength, ihn.walk_strength)\n        out.stay = ihn.stay and self.scale.stay and self.offset.stay\n\n        if out.stay:\n            self.execute()\n\n\nclass EqualityConstraint(BinaryConstraint):\n    def execute(self):\n        self.output().value = self.input().value\n\n\nclass Variable(object):\n    def __init__(self, name, initial_value=0):\n        super(Variable, self).__init__()\n        self.name = name\n        self.value = initial_value\n        self.constraints = OrderedCollection()\n        self.determined_by = None\n        self.mark = 0\n        self.walk_strength = Strength.WEAKEST\n        self.stay = True\n\n    def __repr__(self):\n        # To make debugging this beast from pdb easier...\n        return \"<Variable: %s - %s>\" % (self.name, self.value)\n\n    def add_constraint(self, constraint):\n        self.constraints.append(constraint)\n\n    def remove_constraint(self, constraint):\n        self.constraints.remove(constraint)\n\n        if self.determined_by == constraint:\n            self.determined_by = None\n\n\nclass Planner(object):\n    def __init__(self):\n        super(Planner, self).__init__()\n        self.current_mark = 0\n\n    def incremental_add(self, constraint):\n        mark = self.new_mark()\n        overridden = constraint.satisfy(mark)\n\n        while overridden is not None:\n            overridden = overridden.satisfy(mark)\n\n    def incremental_remove(self, constraint):\n        out = constraint.output()\n        constraint.mark_unsatisfied()\n        constraint.remove_from_graph()\n        unsatisfied = self.remove_propagate_from(out)\n        strength = Strength.REQUIRED\n        # Do-while, the Python way.\n        repeat = True\n\n        while repeat:\n            for u in unsatisfied:\n                if u.strength == strength:\n                    self.incremental_add(u)\n\n                strength = strength.next_weaker()\n\n            repeat = strength != Strength.WEAKEST\n\n    def new_mark(self):\n        self.current_mark += 1\n        return self.current_mark\n\n    def make_plan(self, sources):\n        mark = self.new_mark()\n        plan = Plan()\n        todo = sources\n\n        while len(todo):\n            c = todo.pop(0)\n\n            if c.output().mark != mark and c.inputs_known(mark):\n                plan.add_constraint(c)\n                c.output().mark = mark\n                self.add_constraints_consuming_to(c.output(), todo)\n\n        return plan\n\n    def extract_plan_from_constraints(self, constraints):\n        sources = OrderedCollection()\n\n        for c in constraints:\n            if c.is_input() and c.is_satisfied():\n                sources.append(c)\n\n        return self.make_plan(sources)\n\n    def add_propagate(self, c, mark):\n        todo = OrderedCollection()\n        todo.append(c)\n\n        while len(todo):\n            d = todo.pop(0)\n\n            if d.output().mark == mark:\n                self.incremental_remove(c)\n                return False\n\n            d.recalculate()\n            self.add_constraints_consuming_to(d.output(), todo)\n\n        return True\n\n    def remove_propagate_from(self, out):\n        out.determined_by = None\n        out.walk_strength = Strength.WEAKEST\n        out.stay = True\n        unsatisfied = OrderedCollection()\n        todo = OrderedCollection()\n        todo.append(out)\n\n        while len(todo):\n            v = todo.pop(0)\n\n            for c in v.constraints:\n                if not c.is_satisfied():\n                    unsatisfied.append(c)\n\n            determining = v.determined_by\n\n            for c in v.constraints:\n                if c != determining and c.is_satisfied():\n                    c.recalculate()\n                    todo.append(c.output())\n\n        return unsatisfied\n\n    def add_constraints_consuming_to(self, v, coll):\n        determining = v.determined_by\n        cc = v.constraints\n\n        for c in cc:\n            if c != determining and c.is_satisfied():\n                # I guess we're just updating a reference (``coll``)? Seems\n                # inconsistent with the rest of the implementation, where they\n                # return the lists...\n                coll.append(c)\n\n\nclass Plan(object):\n    def __init__(self):\n        super(Plan, self).__init__()\n        self.v = OrderedCollection()\n\n    def add_constraint(self, c):\n        self.v.append(c)\n\n    def __len__(self):\n        return len(self.v)\n\n    def __getitem__(self, index):\n        return self.v[index]\n\n    def execute(self):\n        for c in self.v:\n            c.execute()\n\n\n# Main\n\n\ndef chain_test(n):\n    \"\"\"\n    This is the standard DeltaBlue benchmark. A long chain of equality\n    constraints is constructed with a stay constraint on one end. An\n    edit constraint is then added to the opposite end and the time is\n    measured for adding and removing this constraint, and extracting\n    and executing a constraint satisfaction plan. There are two cases.\n    In case 1, the added constraint is stronger than the stay\n    constraint and values must propagate down the entire length of the\n    chain. In case 2, the added constraint is weaker than the stay\n    constraint so it cannot be accomodated. The cost in this case is,\n    of course, very low. Typical situations lie somewhere between these\n    two extremes.\n    \"\"\"\n    global planner\n    planner = Planner()\n    prev, first, last = None, None, None\n\n    # We need to go up to n inclusively.\n    for i in range(n + 1):\n        name = \"v%s\" % i\n        v = Variable(name)\n\n        if prev is not None:\n            EqualityConstraint(prev, v, Strength.REQUIRED)\n\n        if i == 0:\n            first = v\n\n        if i == n:\n            last = v\n\n        prev = v\n\n    StayConstraint(last, Strength.STRONG_DEFAULT)\n    edit = EditConstraint(first, Strength.PREFERRED)\n    edits = OrderedCollection()\n    edits.append(edit)\n    plan = planner.extract_plan_from_constraints(edits)\n\n    for i in range(100):\n        first.value = i\n        plan.execute()\n\n        if last.value != i:\n            print(\"Chain test failed.\")\n\n\ndef projection_test(n):\n    \"\"\"\n    This test constructs a two sets of variables related to each\n    other by a simple linear transformation (scale and offset). The\n    time is measured to change a variable on either side of the\n    mapping and to change the scale and offset factors.\n    \"\"\"\n    global planner\n    planner = Planner()\n    scale = Variable(\"scale\", 10)\n    offset = Variable(\"offset\", 1000)\n    src = None\n\n    dests = OrderedCollection()\n\n    for i in range(n):\n        src = Variable(\"src%s\" % i, i)\n        dst = Variable(\"dst%s\" % i, i)\n        dests.append(dst)\n        StayConstraint(src, Strength.NORMAL)\n        ScaleConstraint(src, scale, offset, dst, Strength.REQUIRED)\n\n    change(src, 17)\n\n    if dst.value != 1170:\n        print(\"Projection 1 failed\")\n\n    change(dst, 1050)\n\n    if src.value != 5:\n        print(\"Projection 2 failed\")\n\n    change(scale, 5)\n\n    for i in range(n - 1):\n        if dests[i].value != (i * 5 + 1000):\n            print(\"Projection 3 failed\")\n\n    change(offset, 2000)\n\n    for i in range(n - 1):\n        if dests[i].value != (i * 5 + 2000):\n            print(\"Projection 4 failed\")\n\n\ndef change(v, new_value):\n    global planner\n    edit = EditConstraint(v, Strength.PREFERRED)\n    edits = OrderedCollection()\n    edits.append(edit)\n\n    plan = planner.extract_plan_from_constraints(edits)\n\n    for i in range(10):\n        v.value = new_value\n        plan.execute()\n\n    edit.destroy_constraint()\n\n\n# HOORAY FOR GLOBALS... Oh wait.\n# In spirit of the original, we'll keep it, but ugh.\nplanner = None\n\n\ndef delta_blue(n):\n    chain_test(n)\n    projection_test(n)\n\n\ndef run_benchmark():\n    delta_blue(1000)\n\n\nif __name__ == \"__main__\":\n    run_benchmark()\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/deltablue_memray.py",
    "content": "\"\"\"\ndeltablue.py\n============\n\nPorted for the PyPy project.\nContributed by Daniel Lindsley\n\nThis implementation of the DeltaBlue benchmark was directly ported\nfrom the `V8's source code`_, which was in turn derived\nfrom the Smalltalk implementation by John Maloney and Mario\nWolczko. The original Javascript implementation was licensed under the GPL.\n\nIt's been updated in places to be more idiomatic to Python (for loops over\ncollections, a couple magic methods, ``OrderedCollection`` being a list & things\naltering those collections changed to the builtin methods) but largely retains\nthe layout & logic from the original. (Ugh.)\n\n.. _`V8's source code`: (https://github.com/v8/v8/blob/master/benchmarks/deltablue.js)\n\"\"\"\n\nimport pyperf\nfrom memray_helper import get_tracker\n\n# The JS variant implements \"OrderedCollection\", which basically completely\n# overlaps with ``list``. So we'll cheat. :D\nclass OrderedCollection(list):\n    pass\n\n\nclass Strength(object):\n    REQUIRED = None\n    STRONG_PREFERRED = None\n    PREFERRED = None\n    STRONG_DEFAULT = None\n    NORMAL = None\n    WEAK_DEFAULT = None\n    WEAKEST = None\n\n    def __init__(self, strength, name):\n        super(Strength, self).__init__()\n        self.strength = strength\n        self.name = name\n\n    @classmethod\n    def stronger(cls, s1, s2):\n        return s1.strength < s2.strength\n\n    @classmethod\n    def weaker(cls, s1, s2):\n        return s1.strength > s2.strength\n\n    @classmethod\n    def weakest_of(cls, s1, s2):\n        if cls.weaker(s1, s2):\n            return s1\n\n        return s2\n\n    @classmethod\n    def strongest(cls, s1, s2):\n        if cls.stronger(s1, s2):\n            return s1\n\n        return s2\n\n    def next_weaker(self):\n        strengths = {\n            0: self.__class__.WEAKEST,\n            1: self.__class__.WEAK_DEFAULT,\n            2: self.__class__.NORMAL,\n            3: self.__class__.STRONG_DEFAULT,\n            4: self.__class__.PREFERRED,\n            # TODO: This looks like a bug in the original code. Shouldn't this be\n            #       ``STRONG_PREFERRED? Keeping for porting sake...\n            5: self.__class__.REQUIRED,\n        }\n        return strengths[self.strength]\n\n\n# This is a terrible pattern IMO, but true to the original JS implementation.\nStrength.REQUIRED = Strength(0, \"required\")\nStrength.STRONG_PREFERRED = Strength(1, \"strongPreferred\")\nStrength.PREFERRED = Strength(2, \"preferred\")\nStrength.STRONG_DEFAULT = Strength(3, \"strongDefault\")\nStrength.NORMAL = Strength(4, \"normal\")\nStrength.WEAK_DEFAULT = Strength(5, \"weakDefault\")\nStrength.WEAKEST = Strength(6, \"weakest\")\n\n\nclass Constraint(object):\n    def __init__(self, strength):\n        super(Constraint, self).__init__()\n        self.strength = strength\n\n    def add_constraint(self):\n        global planner\n        self.add_to_graph()\n        planner.incremental_add(self)\n\n    def satisfy(self, mark):\n        global planner\n        self.choose_method(mark)\n\n        if not self.is_satisfied():\n            if self.strength == Strength.REQUIRED:\n                print(\"Could not satisfy a required constraint!\")\n\n            return None\n\n        self.mark_inputs(mark)\n        out = self.output()\n        overridden = out.determined_by\n\n        if overridden is not None:\n            overridden.mark_unsatisfied()\n\n        out.determined_by = self\n\n        if not planner.add_propagate(self, mark):\n            print(\"Cycle encountered\")\n\n        out.mark = mark\n        return overridden\n\n    def destroy_constraint(self):\n        global planner\n        if self.is_satisfied():\n            planner.incremental_remove(self)\n        else:\n            self.remove_from_graph()\n\n    def is_input(self):\n        return False\n\n\nclass UrnaryConstraint(Constraint):\n    def __init__(self, v, strength):\n        super(UrnaryConstraint, self).__init__(strength)\n        self.my_output = v\n        self.satisfied = False\n        self.add_constraint()\n\n    def add_to_graph(self):\n        self.my_output.add_constraint(self)\n        self.satisfied = False\n\n    def choose_method(self, mark):\n        if self.my_output.mark != mark and Strength.stronger(\n            self.strength, self.my_output.walk_strength\n        ):\n            self.satisfied = True\n        else:\n            self.satisfied = False\n\n    def is_satisfied(self):\n        return self.satisfied\n\n    def mark_inputs(self, mark):\n        # No-ops.\n        pass\n\n    def output(self):\n        # Ugh. Keeping it for consistency with the original. So much for\n        # \"we're all adults here\"...\n        return self.my_output\n\n    def recalculate(self):\n        self.my_output.walk_strength = self.strength\n        self.my_output.stay = not self.is_input()\n\n        if self.my_output.stay:\n            self.execute()\n\n    def mark_unsatisfied(self):\n        self.satisfied = False\n\n    def inputs_known(self, mark):\n        return True\n\n    def remove_from_graph(self):\n        if self.my_output is not None:\n            self.my_output.remove_constraint(self)\n            self.satisfied = False\n\n\nclass StayConstraint(UrnaryConstraint):\n    def __init__(self, v, string):\n        super(StayConstraint, self).__init__(v, string)\n\n    def execute(self):\n        # The methods, THEY DO NOTHING.\n        pass\n\n\nclass EditConstraint(UrnaryConstraint):\n    def __init__(self, v, string):\n        super(EditConstraint, self).__init__(v, string)\n\n    def is_input(self):\n        return True\n\n    def execute(self):\n        # This constraint also does nothing.\n        pass\n\n\nclass Direction(object):\n    # Hooray for things that ought to be structs!\n    NONE = 0\n    FORWARD = 1\n    BACKWARD = -1\n\n\nclass BinaryConstraint(Constraint):\n    def __init__(self, v1, v2, strength):\n        super(BinaryConstraint, self).__init__(strength)\n        self.v1 = v1\n        self.v2 = v2\n        self.direction = Direction.NONE\n        self.add_constraint()\n\n    def choose_method(self, mark):\n        if self.v1.mark == mark:\n            if self.v2.mark != mark and Strength.stronger(\n                self.strength, self.v2.walk_strength\n            ):\n                self.direction = Direction.FORWARD\n            else:\n                self.direction = Direction.BACKWARD\n\n        if self.v2.mark == mark:\n            if self.v1.mark != mark and Strength.stronger(\n                self.strength, self.v1.walk_strength\n            ):\n                self.direction = Direction.BACKWARD\n            else:\n                self.direction = Direction.NONE\n\n        if Strength.weaker(self.v1.walk_strength, self.v2.walk_strength):\n            if Strength.stronger(self.strength, self.v1.walk_strength):\n                self.direction = Direction.BACKWARD\n            else:\n                self.direction = Direction.NONE\n        else:\n            if Strength.stronger(self.strength, self.v2.walk_strength):\n                self.direction = Direction.FORWARD\n            else:\n                self.direction = Direction.BACKWARD\n\n    def add_to_graph(self):\n        self.v1.add_constraint(self)\n        self.v2.add_constraint(self)\n        self.direction = Direction.NONE\n\n    def is_satisfied(self):\n        return self.direction != Direction.NONE\n\n    def mark_inputs(self, mark):\n        self.input().mark = mark\n\n    def input(self):\n        if self.direction == Direction.FORWARD:\n            return self.v1\n\n        return self.v2\n\n    def output(self):\n        if self.direction == Direction.FORWARD:\n            return self.v2\n\n        return self.v1\n\n    def recalculate(self):\n        ihn = self.input()\n        out = self.output()\n        out.walk_strength = Strength.weakest_of(self.strength, ihn.walk_strength)\n        out.stay = ihn.stay\n\n        if out.stay:\n            self.execute()\n\n    def mark_unsatisfied(self):\n        self.direction = Direction.NONE\n\n    def inputs_known(self, mark):\n        i = self.input()\n        return i.mark == mark or i.stay or i.determined_by is None\n\n    def remove_from_graph(self):\n        if self.v1 is not None:\n            self.v1.remove_constraint(self)\n\n        if self.v2 is not None:\n            self.v2.remove_constraint(self)\n\n        self.direction = Direction.NONE\n\n\nclass ScaleConstraint(BinaryConstraint):\n    def __init__(self, src, scale, offset, dest, strength):\n        self.direction = Direction.NONE\n        self.scale = scale\n        self.offset = offset\n        super(ScaleConstraint, self).__init__(src, dest, strength)\n\n    def add_to_graph(self):\n        super(ScaleConstraint, self).add_to_graph()\n        self.scale.add_constraint(self)\n        self.offset.add_constraint(self)\n\n    def remove_from_graph(self):\n        super(ScaleConstraint, self).remove_from_graph()\n\n        if self.scale is not None:\n            self.scale.remove_constraint(self)\n\n        if self.offset is not None:\n            self.offset.remove_constraint(self)\n\n    def mark_inputs(self, mark):\n        super(ScaleConstraint, self).mark_inputs(mark)\n        self.scale.mark = mark\n        self.offset.mark = mark\n\n    def execute(self):\n        if self.direction == Direction.FORWARD:\n            self.v2.value = self.v1.value * self.scale.value + self.offset.value\n        else:\n            self.v1.value = (self.v2.value - self.offset.value) / self.scale.value\n\n    def recalculate(self):\n        ihn = self.input()\n        out = self.output()\n        out.walk_strength = Strength.weakest_of(self.strength, ihn.walk_strength)\n        out.stay = ihn.stay and self.scale.stay and self.offset.stay\n\n        if out.stay:\n            self.execute()\n\n\nclass EqualityConstraint(BinaryConstraint):\n    def execute(self):\n        self.output().value = self.input().value\n\n\nclass Variable(object):\n    def __init__(self, name, initial_value=0):\n        super(Variable, self).__init__()\n        self.name = name\n        self.value = initial_value\n        self.constraints = OrderedCollection()\n        self.determined_by = None\n        self.mark = 0\n        self.walk_strength = Strength.WEAKEST\n        self.stay = True\n\n    def __repr__(self):\n        # To make debugging this beast from pdb easier...\n        return \"<Variable: %s - %s>\" % (self.name, self.value)\n\n    def add_constraint(self, constraint):\n        self.constraints.append(constraint)\n\n    def remove_constraint(self, constraint):\n        self.constraints.remove(constraint)\n\n        if self.determined_by == constraint:\n            self.determined_by = None\n\n\nclass Planner(object):\n    def __init__(self):\n        super(Planner, self).__init__()\n        self.current_mark = 0\n\n    def incremental_add(self, constraint):\n        mark = self.new_mark()\n        overridden = constraint.satisfy(mark)\n\n        while overridden is not None:\n            overridden = overridden.satisfy(mark)\n\n    def incremental_remove(self, constraint):\n        out = constraint.output()\n        constraint.mark_unsatisfied()\n        constraint.remove_from_graph()\n        unsatisfied = self.remove_propagate_from(out)\n        strength = Strength.REQUIRED\n        # Do-while, the Python way.\n        repeat = True\n\n        while repeat:\n            for u in unsatisfied:\n                if u.strength == strength:\n                    self.incremental_add(u)\n\n                strength = strength.next_weaker()\n\n            repeat = strength != Strength.WEAKEST\n\n    def new_mark(self):\n        self.current_mark += 1\n        return self.current_mark\n\n    def make_plan(self, sources):\n        mark = self.new_mark()\n        plan = Plan()\n        todo = sources\n\n        while len(todo):\n            c = todo.pop(0)\n\n            if c.output().mark != mark and c.inputs_known(mark):\n                plan.add_constraint(c)\n                c.output().mark = mark\n                self.add_constraints_consuming_to(c.output(), todo)\n\n        return plan\n\n    def extract_plan_from_constraints(self, constraints):\n        sources = OrderedCollection()\n\n        for c in constraints:\n            if c.is_input() and c.is_satisfied():\n                sources.append(c)\n\n        return self.make_plan(sources)\n\n    def add_propagate(self, c, mark):\n        todo = OrderedCollection()\n        todo.append(c)\n\n        while len(todo):\n            d = todo.pop(0)\n\n            if d.output().mark == mark:\n                self.incremental_remove(c)\n                return False\n\n            d.recalculate()\n            self.add_constraints_consuming_to(d.output(), todo)\n\n        return True\n\n    def remove_propagate_from(self, out):\n        out.determined_by = None\n        out.walk_strength = Strength.WEAKEST\n        out.stay = True\n        unsatisfied = OrderedCollection()\n        todo = OrderedCollection()\n        todo.append(out)\n\n        while len(todo):\n            v = todo.pop(0)\n\n            for c in v.constraints:\n                if not c.is_satisfied():\n                    unsatisfied.append(c)\n\n            determining = v.determined_by\n\n            for c in v.constraints:\n                if c != determining and c.is_satisfied():\n                    c.recalculate()\n                    todo.append(c.output())\n\n        return unsatisfied\n\n    def add_constraints_consuming_to(self, v, coll):\n        determining = v.determined_by\n        cc = v.constraints\n\n        for c in cc:\n            if c != determining and c.is_satisfied():\n                # I guess we're just updating a reference (``coll``)? Seems\n                # inconsistent with the rest of the implementation, where they\n                # return the lists...\n                coll.append(c)\n\n\nclass Plan(object):\n    def __init__(self):\n        super(Plan, self).__init__()\n        self.v = OrderedCollection()\n\n    def add_constraint(self, c):\n        self.v.append(c)\n\n    def __len__(self):\n        return len(self.v)\n\n    def __getitem__(self, index):\n        return self.v[index]\n\n    def execute(self):\n        for c in self.v:\n            c.execute()\n\n\n# Main\n\n\ndef chain_test(n):\n    \"\"\"\n    This is the standard DeltaBlue benchmark. A long chain of equality\n    constraints is constructed with a stay constraint on one end. An\n    edit constraint is then added to the opposite end and the time is\n    measured for adding and removing this constraint, and extracting\n    and executing a constraint satisfaction plan. There are two cases.\n    In case 1, the added constraint is stronger than the stay\n    constraint and values must propagate down the entire length of the\n    chain. In case 2, the added constraint is weaker than the stay\n    constraint so it cannot be accomodated. The cost in this case is,\n    of course, very low. Typical situations lie somewhere between these\n    two extremes.\n    \"\"\"\n    global planner\n    planner = Planner()\n    prev, first, last = None, None, None\n\n    # We need to go up to n inclusively.\n    for i in range(n + 1):\n        name = \"v%s\" % i\n        v = Variable(name)\n\n        if prev is not None:\n            EqualityConstraint(prev, v, Strength.REQUIRED)\n\n        if i == 0:\n            first = v\n\n        if i == n:\n            last = v\n\n        prev = v\n\n    StayConstraint(last, Strength.STRONG_DEFAULT)\n    edit = EditConstraint(first, Strength.PREFERRED)\n    edits = OrderedCollection()\n    edits.append(edit)\n    plan = planner.extract_plan_from_constraints(edits)\n\n    for i in range(100):\n        first.value = i\n        plan.execute()\n\n        if last.value != i:\n            print(\"Chain test failed.\")\n\n\ndef projection_test(n):\n    \"\"\"\n    This test constructs a two sets of variables related to each\n    other by a simple linear transformation (scale and offset). The\n    time is measured to change a variable on either side of the\n    mapping and to change the scale and offset factors.\n    \"\"\"\n    global planner\n    planner = Planner()\n    scale = Variable(\"scale\", 10)\n    offset = Variable(\"offset\", 1000)\n    src = None\n\n    dests = OrderedCollection()\n\n    for i in range(n):\n        src = Variable(\"src%s\" % i, i)\n        dst = Variable(\"dst%s\" % i, i)\n        dests.append(dst)\n        StayConstraint(src, Strength.NORMAL)\n        ScaleConstraint(src, scale, offset, dst, Strength.REQUIRED)\n\n    change(src, 17)\n\n    if dst.value != 1170:\n        print(\"Projection 1 failed\")\n\n    change(dst, 1050)\n\n    if src.value != 5:\n        print(\"Projection 2 failed\")\n\n    change(scale, 5)\n\n    for i in range(n - 1):\n        if dests[i].value != (i * 5 + 1000):\n            print(\"Projection 3 failed\")\n\n    change(offset, 2000)\n\n    for i in range(n - 1):\n        if dests[i].value != (i * 5 + 2000):\n            print(\"Projection 4 failed\")\n\n\ndef change(v, new_value):\n    global planner\n    edit = EditConstraint(v, Strength.PREFERRED)\n    edits = OrderedCollection()\n    edits.append(edit)\n\n    plan = planner.extract_plan_from_constraints(edits)\n\n    for i in range(10):\n        v.value = new_value\n        plan.execute()\n\n    edit.destroy_constraint()\n\n\n# HOORAY FOR GLOBALS... Oh wait.\n# In spirit of the original, we'll keep it, but ugh.\nplanner = None\n\n\ndef delta_blue(n):\n    chain_test(n)\n    projection_test(n)\n\n\ndef bench_deltablue(loops, n):\n    with get_tracker():\n        t0 = pyperf.perf_counter()\n        for _ in range(loops):\n            delta_blue(n)\n    return pyperf.perf_counter() - t0\n\n\nif __name__ == \"__main__\":\n    runner = pyperf.Runner()\n    runner.metadata[\"description\"] = \"DeltaBlue benchmark\"\n\n    n = 100\n    runner.bench_time_func(\"deltablue\", bench_deltablue, n)\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/docutils_data/docs/api/publisher.txt",
    "content": "========================\n The Docutils Publisher\n========================\n\n:Author: David Goodger\n:Contact: docutils-develop@lists.sourceforge.net\n:Date: $Date$\n:Revision: $Revision$\n:Copyright: This document has been placed in the public domain.\n\n.. contents::\n\n\nThe ``docutils.core.Publisher`` class is the core of Docutils,\nmanaging all the processing and relationships between components.  See\n`PEP 258`_ for an overview of Docutils components.\n\nThe ``docutils.core.publish_*`` convenience functions are the normal\nentry points for using Docutils as a library.\n\nSee `Inside A Docutils Command-Line Front-End Tool`_ for an overview\nof a typical Docutils front-end tool, including how the Publisher\nclass is used.\n\n.. _PEP 258: ../peps/pep-0258.html\n.. _Inside A Docutils Command-Line Front-End Tool: ../howto/cmdline-tool.html\n\n\nPublisher Convenience Functions\n===============================\n\nEach of these functions set up a ``docutils.core.Publisher`` object,\nthen call its ``publish`` method.  ``docutils.core.Publisher.publish``\nhandles everything else.  There are several convenience functions in\nthe ``docutils.core`` module:\n\n:_`publish_cmdline()`: for command-line front-end tools, like\n  ``rst2html.py``.  There are several examples in the ``tools/``\n  directory.  A detailed analysis of one such tool is in `Inside A\n  Docutils Command-Line Front-End Tool`_\n\n:_`publish_file()`: for programmatic use with file-like I/O.  In\n  addition to writing the encoded output to a file, also returns the\n  encoded output as a string.\n\n:_`publish_string()`: for programmatic use with string I/O.  Returns\n  the encoded output as a string.\n\n:_`publish_parts()`: for programmatic use with string input; returns a\n  dictionary of document parts.  Dictionary keys are the names of\n  parts, and values are Unicode strings; encoding is up to the client.\n  Useful when only portions of the processed document are desired.\n  See `publish_parts() Details`_ below.\n\n  There are usage examples in the `docutils/examples.py`_ module.\n\n:_`publish_doctree()`: for programmatic use with string input; returns a\n  Docutils document tree data structure (doctree).  The doctree can be\n  modified, pickled & unpickled, etc., and then reprocessed with\n  `publish_from_doctree()`_.\n\n:_`publish_from_doctree()`: for programmatic use to render from an\n  existing document tree data structure (doctree); returns the encoded\n  output as a string.\n\n:_`publish_programmatically()`: for custom programmatic use.  This\n  function implements common code and is used by ``publish_file``,\n  ``publish_string``, and ``publish_parts``.  It returns a 2-tuple:\n  the encoded string output and the Publisher object.\n\n.. _Inside A Docutils Command-Line Front-End Tool: ../howto/cmdline-tool.html\n.. _docutils/examples.py: ../../docutils/examples.py\n\n\nConfiguration\n-------------\n\nTo pass application-specific setting defaults to the Publisher\nconvenience functions, use the ``settings_overrides`` parameter.  Pass\na dictionary of setting names & values, like this::\n\n    overrides = {'input_encoding': 'ascii',\n                 'output_encoding': 'latin-1'}\n    output = publish_string(..., settings_overrides=overrides)\n\nSettings from command-line options override configuration file\nsettings, and they override application defaults.  For details, see\n`Docutils Runtime Settings`_.  See `Docutils Configuration`_ for\ndetails about individual settings.\n\n.. _Docutils Runtime Settings: ./runtime-settings.html\n.. _Docutils Configuration: ../user/config.html\n\n\nEncodings\n---------\n\nThe default output encoding of Docutils is UTF-8.\nDocutils may introduce some non-ASCII text if you use\n`auto-symbol footnotes`_ or the `\"contents\" directive`_.\n\n.. _auto-symbol footnotes:\n   ../ref/rst/restructuredtext.html#auto-symbol-footnotes\n.. _\"contents\" directive:\n   ../ref/rst/directives.html#table-of-contents\n\n\n``publish_parts()`` Details\n===========================\n\nThe ``docutils.core.publish_parts()`` convenience function returns a\ndictionary of document parts.  Dictionary keys are the names of parts,\nand values are Unicode strings.\n\nEach Writer component may publish a different set of document parts,\ndescribed below.  Not all writers implement all parts.\n\n\nParts Provided By All Writers\n-----------------------------\n\n_`encoding`\n    The output encoding setting.\n\n_`version`\n    The version of Docutils used.\n\n_`whole`\n    ``parts['whole']`` contains the entire formatted document.\n\n\nParts Provided By the HTML Writers\n----------------------------------\n\nHTML4 Writer\n````````````\n\n_`body`\n    ``parts['body']`` is equivalent to parts['fragment_'].  It is\n    *not* equivalent to parts['html_body_'].\n\n_`body_prefix`\n    ``parts['body_prefix']`` contains::\n\n        </head>\n        <body>\n        <div class=\"document\" ...>\n\n    and, if applicable::\n\n        <div class=\"header\">\n        ...\n        </div>\n\n_`body_pre_docinfo`\n    ``parts['body_pre_docinfo]`` contains (as applicable)::\n\n        <h1 class=\"title\">...</h1>\n        <h2 class=\"subtitle\" id=\"...\">...</h2>\n\n_`body_suffix`\n    ``parts['body_suffix']`` contains::\n\n        </div>\n\n    (the end-tag for ``<div class=\"document\">``), the footer division\n    if applicable::\n\n        <div class=\"footer\">\n        ...\n        </div>\n\n    and::\n\n        </body>\n        </html>\n\n_`docinfo`\n    ``parts['docinfo']`` contains the document bibliographic data, the\n    docinfo field list rendered as a table.\n\n_`footer`\n    ``parts['footer']`` contains the document footer content, meant to\n    appear at the bottom of a web page, or repeated at the bottom of\n    every printed page.\n\n_`fragment`\n    ``parts['fragment']`` contains the document body (*not* the HTML\n    ``<body>``).  In other words, it contains the entire document,\n    less the document title, subtitle, docinfo, header, and footer.\n\n_`head`\n    ``parts['head']`` contains ``<meta ... />`` tags and the document\n    ``<title>...</title>``.\n\n_`head_prefix`\n    ``parts['head_prefix']`` contains the XML declaration, the DOCTYPE\n    declaration, the ``<html ...>`` start tag and the ``<head>`` start\n    tag.\n\n_`header`\n    ``parts['header']`` contains the document header content, meant to\n    appear at the top of a web page, or repeated at the top of every\n    printed page.\n\n_`html_body`\n    ``parts['html_body']`` contains the HTML ``<body>`` content, less\n    the ``<body>`` and ``</body>`` tags themselves.\n\n_`html_head`\n    ``parts['html_head']`` contains the HTML ``<head>`` content, less\n    the stylesheet link and the ``<head>`` and ``</head>`` tags\n    themselves.  Since ``publish_parts`` returns Unicode strings and\n    does not know about the output encoding, the \"Content-Type\" meta\n    tag's \"charset\" value is left unresolved, as \"%s\"::\n\n        <meta http-equiv=\"Content-Type\" content=\"text/html; charset=%s\" />\n\n    The interpolation should be done by client code.\n\n_`html_prolog`\n    ``parts['html_prolog]`` contains the XML declaration and the\n    doctype declaration.  The XML declaration's \"encoding\" attribute's\n    value is left unresolved, as \"%s\"::\n\n        <?xml version=\"1.0\" encoding=\"%s\" ?>\n\n    The interpolation should be done by client code.\n\n_`html_subtitle`\n    ``parts['html_subtitle']`` contains the document subtitle,\n    including the enclosing ``<h2 class=\"subtitle\">`` & ``</h2>``\n    tags.\n\n_`html_title`\n    ``parts['html_title']`` contains the document title, including the\n    enclosing ``<h1 class=\"title\">`` & ``</h1>`` tags.\n\n_`meta`\n    ``parts['meta']`` contains all ``<meta ... />`` tags.\n\n_`stylesheet`\n    ``parts['stylesheet']`` contains the embedded stylesheet or\n    stylesheet link.\n\n_`subtitle`\n    ``parts['subtitle']`` contains the document subtitle text and any\n    inline markup.  It does not include the enclosing ``<h2>`` &\n    ``</h2>`` tags.\n\n_`title`\n    ``parts['title']`` contains the document title text and any inline\n    markup.  It does not include the enclosing ``<h1>`` & ``</h1>``\n    tags.\n\n\nPEP/HTML Writer\n```````````````\n\nThe PEP/HTML writer provides the same parts as the `HTML4 writer`_,\nplus the following:\n\n_`pepnum`\n    ``parts['pepnum']`` contains\n\n\nS5/HTML Writer\n``````````````\n\nThe S5/HTML writer provides the same parts as the `HTML4 writer`_.\n\n\nHTML5 Writer\n````````````\n\nThe HTML5 writer provides the same parts as the `HTML4 writer`_.\nHowever, it uses semantic HTML5 elements for the document, header and\nfooter.\n\n\nParts Provided by the LaTeX2e Writer\n------------------------------------\n\nSee the template files for examples how these parts can be combined\ninto a valid LaTeX document.\n\nabstract\n    ``parts['abstract']`` contains the formatted content of the\n    'abstract' docinfo field.\n\nbody\n    ``parts['body']`` contains the document's content. In other words, it\n    contains the entire document, except the document title, subtitle, and\n    docinfo.\n\n    This part can be included into another LaTeX document body using the\n    ``\\input{}`` command.\n\nbody_pre_docinfo\n    ``parts['body_pre_docinfo]`` contains the ``\\maketitle`` command.\n\ndedication\n    ``parts['dedication']`` contains the formatted content of the\n    'dedication' docinfo field.\n\ndocinfo\n    ``parts['docinfo']`` contains the document bibliographic data, the\n    docinfo field list rendered as a table.\n\n    With ``--use-latex-docinfo`` 'author', 'organization', 'contact',\n    'address' and 'date' info is moved to titledata.\n\n    'dedication' and 'abstract' are always moved to separate parts.\n\nfallbacks\n    ``parts['fallbacks']`` contains fallback definitions for\n    Docutils-specific commands and environments.\n\nhead_prefix\n    ``parts['head_prefix']`` contains the declaration of\n    documentclass and document options.\n\nlatex_preamble\n    ``parts['latex_preamble']`` contains the argument of the\n    ``--latex-preamble`` option.\n\npdfsetup\n     ``parts['pdfsetup']`` contains the PDF properties\n     (\"hyperref\" package setup).\n\nrequirements\n    ``parts['requirements']`` contains required packages and setup\n    before the stylesheet inclusion.\n\nstylesheet\n    ``parts['stylesheet']`` contains the embedded stylesheet(s) or\n    stylesheet loading command(s).\n\nsubtitle\n    ``parts['subtitle']`` contains the document subtitle text and any\n    inline markup.\n\ntitle\n    ``parts['title']`` contains the document title text and any inline\n    markup.\n\ntitledata\n    ``parts['titledata]`` contains the combined title data in\n    ``\\title``, ``\\author``, and ``\\data`` macros.\n\n    With ``--use-latex-docinfo``, this includes the 'author',\n    'organization', 'contact', 'address' and 'date' docinfo items.\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/docutils_data/docs/api/runtime-settings.txt",
    "content": "===========================\n Docutils Runtime Settings\n===========================\n\n:Author: David Goodger, Günter Milde\n:Contact: docutils-develop@lists.sourceforge.net\n:Date: $Date$\n:Revision: $Revision$\n:Copyright: This document has been placed in the public domain.\n\n.. contents::\n\n\nIntroduction\n============\n\nDocutils runtime settings are assembled from several sources:\n\n* Settings specifications of the selected components_,\n* `configuration files`_ (if enabled), and\n* command-line options (if enabled).\n\nDocutils overlays default and explicitly specified values from these\nsources such that settings behave the way we want and expect them to\nbehave.\n\n\nSettings priority\n=================\n\nThe sources are overlaid in the following order (later sources\noverwrite earlier ones):\n\n1. Defaults specified in the `settings_spec`__ and\n   `settings_defaults`__ attributes for each component_.\n\n   __ SettingsSpec.settings_spec_\n   __ SettingsSpec.settings_defaults_\n\n2. Defaults specified in the `settings_default_overrides`__ attribute\n   for each component_.\n\n   __ SettingsSpec.settings_default_overrides_\n\n3. Settings specified in the `settings_overrides`__ parameter of the\n   `convenience functions`_ resp. the `settings_overrides` attribute of\n   a `Publisher`_ instance.\n\n   __ `settings_overrides parameter`_\n\n4. Settings specified in `active sections`_ of the `configuration files`_\n   in the order described in `Configuration File Sections & Entries`_\n   (if enabled).\n\n5. Command line options (if enabled).\n\nFor details see the ``docutils/__init__.py``, ``docutils/core.py``, and\n``docutils.frontend.py`` modules and the implementation description in\n`Runtime Settings Processing`_.\n\n\n.. _SettingsSpec:\n\nSettingsSpec base class\n=======================\n\n.. note::\n   Implementation details will change with the move to replace the\n   deprecated optparse_ module with argparse_.\n\nThe `docutils.SettingsSpec` base class is inherited by Docutils\ncomponents_ and `frontend.OptionParser`.\nIt defines the following six **attributes**:\n\n.. _SettingsSpec.settings_spec:\n\n`settings_spec`\n   a sequence of\n\n   1. option group title (string or None)\n\n   2. description (string or None)\n\n   3. option tuples with\n\n      a) help text\n      b) options string(s)\n      c) dictionary with keyword arguments for `OptionParser.add_option()`_\n         and an optional \"validator\", a `frontend.validate_*()` function\n         that processes the values (e.g. convert to other data types).\n\n   For examples, see the source of ``frontend.OptionParser.settings_spec``\n   or the `settings_spec` attributes of the Docutils components_.\n\n   .. _SettingsSpec.settings_defaults:\n\n`settings_defaults`\n   for purely programmatic settings\n   (not accessible from command line and configuration files).\n\n   .. _SettingsSpec.settings_default_overrides:\n\n`settings_default_overrides`\n   to override defaults for settings\n   defined in other components' `setting_specs`.\n\n`relative_path_settings`\n   listing settings containing filesystem paths.\n\n   .. _active sections:\n\n`config_section`\n   the configuration file section specific to this\n   component.\n\n`config_section_dependencies`\n   lists configuration files sections\n   that should also be read (before the `config_section`).\n\nThe last two attributes define which configuration file sections are\n\"active\". See also `Configuration File Sections & Entries`_.\n\n\nGlossary\n========\n\n.. _component:\n\ncomponents\n----------\n\nDocutils front-ends and applications combine a selection of\n*components* of the `Docutils Project Model`_.\n\nAll components inherit the `SettingsSpec`_ base class.\nThis means that all instances of ``readers.Reader``, ``parsers.Parser``, and\n``writers.Writer`` are also instances of ``docutils.SettingsSpec``.\n\nFor the determination of runtime settings, ``frontend.OptionParser`` and\nthe `settings_spec parameter`_ in application settings specifications\nare treated as components as well.\n\n\n.. _convenience function:\n\nconvenience functions\n---------------------\n\nApplications usually deploy Docutils by one of the\n`Publisher convenience functions`_.\n\nAll convenience functions accept the following optional parameters:\n\n.. _settings parameter:\n\n`settings`\n  a ``frontend.Values`` instance.\n  If present, it must be complete.\n\n  No further runtime settings processing is done and the\n  following parameters have no effect.\n\n  .. _settings_spec parameter:\n\n`settings_spec`\n  a `SettingsSpec`_ subclass or instance containing the settings\n  specification for the \"Application\" itself.\n  The instance is added to the components_ (after the generic\n  settings, parser, reader, and writer).\n\n  .. _settings_overrides parameter:\n\n`settings_overrides`\n  a dictionary which is used to update the\n  defaults of the components' settings specifications.\n\n  .. _config_section parameter:\n\n`config_section`\n  the name of an application-specific\n  `configuration file section`_ for this application.\n\n  Can be specified instead of a `settings_spec` (a new SettingsSpec_\n  instance that just defines a configuration section will be created)\n  or in addition to a `settings_spec`\n  (overriding its `config_section` attribute).\n\n\nsettings_spec\n-------------\n\nThe name ``settings_spec`` may refer to\n\na) an instance of the SettingsSpec_ class, or\nb) the data structure `SettingsSpec.settings_spec`_ which is used to\n   store settings details.\n\n\n.. References:\n\n.. _Publisher: publisher.html\n.. _Publisher convenience functions:\n    publisher.html#publisher-convenience-functions\n.. _front-end tools: ../user/tools.html\n.. _configuration files:\n.. _Docutils Configuration: ../user/config.html#configuration-files\n.. _configuration file section:\n.. _Configuration File Sections & Entries:\n    ../user/config.html#configuration-file-sections-entries\n.. _Docutils Project Model: ../peps/pep-0258.html#docutils-project-model\n.. _Reader: ../peps/pep-0258.html#reader\n.. _Runtime Settings Processing: ../dev/runtime-settings-processing.html\n\n.. _optparse: https://docs.python.org/dev/library/optparse.html\n.. _argparse: https://docs.python.org/dev/library/argparse.html\n.. _OptionParser.add_option():\n    https://docs.python.org/dev/library/optparse.html\n    #optparse.OptionParser.add_option\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/docutils_data/docs/api/transforms.txt",
    "content": "=====================\n Docutils Transforms\n=====================\n\n:Author: David Goodger\n:Contact: docutils-develop@lists.sourceforge.net\n:Revision: $Revision$\n:Date: $Date$\n:Copyright: This document has been placed in the public domain.\n\n\n.. contents::\n\nTransforms change the document tree in-place, add to the tree, or prune it.\nTransforms resolve references and footnote numbers, process interpreted\ntext, and do other context-sensitive processing. Each transform is a\nsubclass of ``docutils.transforms.Transform``.\n\nThere are `transforms added by components`_, others (e.g.\n``parts.Contents``) are added by the parser, if a corresponding directive is\nfound in the document.\n\nTo add a transform, components (objects inheriting from\nDocutils.Component like Readers, Parsers, Writers, Input, Output) overwrite\nthe ``get_transforms()`` method of their base class. After the Reader has\nfinished processing, the Publisher calls\n``Transformer.populate_from_components()`` with a list of components and all\ntransforms returned by the component's ``get_transforms()`` method are\nstored in a `transformer object` attached to the document tree.\n\n\nFor more about transforms and the Transformer object, see also `PEP\n258`_. (The ``default_transforms()`` attribute of component classes mentioned\nthere is deprecated. Use the ``get_transforms()`` method instead.)\n\n.. _PEP 258: ../peps/pep-0258.html#transformer\n\n\nTransforms Listed in Priority Order\n===================================\n\nTransform classes each have a default_priority attribute which is used by\nthe Transformer to apply transforms in order (low to high). The default\npriority can be overridden when adding transforms to the Transformer object.\n\n\n==============================  ============================  ========\nTransform: module.Class         Added By                      Priority\n==============================  ============================  ========\nmisc.class                      \"class\" (d/p)                 210\n\nreferences.Substitutions        standalone (r), pep (r)       220\n\nreferences.PropagateTargets     standalone (r), pep (r)       260\n\nfrontmatter.DocTitle            standalone (r)                320\n\nfrontmatter.DocInfo             standalone (r)                340\n\nfrontmatter.SectSubTitle        standalone (r)                350\n\npeps.Headers                    pep (r)                       360\n\npeps.Contents                   pep (r)                       380\n\nuniversal.StripClasses...       Writer (w)                    420\n\nreferences.AnonymousHyperlinks  standalone (r), pep (r)       440\n\nreferences.IndirectHyperlinks   standalone (r), pep (r)       460\n\npeps.TargetNotes                pep (r)                       520\n\nreferences.TargetNotes          peps.TargetNotes (t/p)        0\n\nmisc.CallBack                   peps.TargetNotes (t/p)        1\n\nreferences.TargetNotes          \"target-notes\" (d/p)          540\n\nreferences.Footnotes            standalone (r), pep (r)       620\n\nreferences.ExternalTargets      standalone (r), pep (r)       640\n\nreferences.InternalTargets      standalone (r), pep (r)       660\n\nparts.SectNum                   \"sectnum\" (d/p)               710\n\nparts.Contents                  \"contents\" (d/p),             720\n                                peps.Contents (t/p)\n\nuniversal.StripComments         Reader (r)                    740\n\npeps.PEPZero                    peps.Headers (t/p)            760\n\ncomponents.Filter               *not used*                    780\n\nuniversal.Decorations           Reader (r)                    820\n\nmisc.Transitions                standalone (r), pep (r)       830\n\nuniversal.ExposeInternals       Reader (r)                    840\n\nreferences.DanglingReferences   standalone (r), pep (r)       850\n\nuniversal.SmartQuotes           Parser                        855\n\nuniversal.Messages              Writer (w)                    860\n\nuniversal.FilterMessages        Writer (w)                    870\n\nuniversal.TestMessages          DocutilsTestSupport           880\n\nwriter_aux.Compound             *not used, to be removed*     910\n\nwriter_aux.Admonitions          html4css1 (w),                920\n                                latex2e (w)\n\nmisc.CallBack                   n/a                           990\n==============================  ============================  ========\n\nKey:\n\n* (r): Reader\n* (w): Writer\n* (d): Directive\n* (t): Transform\n* (/p): Via a \"pending\" node\n\n\nTransform Priority Range Categories\n===================================\n\n====  ====  ================================================\n Priority\n----------  ------------------------------------------------\nFrom   To   Category\n====  ====  ================================================\n   0    99  immediate execution (added by another transform)\n 100   199  very early (non-standard)\n 200   299  very early\n 300   399  early\n 400   699  main\n 700   799  late\n 800   899  very late\n 900   999  very late (non-standard)\n====  ====  ================================================\n\n\nTransforms added by components\n===============================\n\n\nreaders.Reader:\n  | universal.Decorations,\n  | universal.ExposeInternals,\n  | universal.StripComments\n\nreaders.ReReader:\n  None\n\nreaders.standalone.Reader:\n  | references.Substitutions,\n  | references.PropagateTargets,\n  | frontmatter.DocTitle,\n  | frontmatter.SectionSubTitle,\n  | frontmatter.DocInfo,\n  | references.AnonymousHyperlinks,\n  | references.IndirectHyperlinks,\n  | references.Footnotes,\n  | references.ExternalTargets,\n  | references.InternalTargets,\n  | references.DanglingReferences,\n  | misc.Transitions\n\nreaders.pep.Reader:\n  | references.Substitutions,\n  | references.PropagateTargets,\n  | references.AnonymousHyperlinks,\n  | references.IndirectHyperlinks,\n  | references.Footnotes,\n  | references.ExternalTargets,\n  | references.InternalTargets,\n  | references.DanglingReferences,\n  | misc.Transitions,\n  | peps.Headers,\n  | peps.Contents,\n  | peps.TargetNotes\n\nparsers.rst.Parser\n  universal.SmartQuotes\n\nwriters.Writer:\n  | universal.Messages,\n  | universal.FilterMessages,\n  | universal.StripClassesAndElements\n\nwriters.UnfilteredWriter\n  None\n\nwriters.latex2e.Writer\n  writer_aux.Admonitions\n\nwriters.html4css1.Writer:\n  writer_aux.Admonitions\n\nwriters.odf_odt.Writer:\n  removes references.DanglingReferences\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/docutils_data/docs/dev/distributing.txt",
    "content": "===============================\n Docutils_ Distributor's Guide\n===============================\n\n:Author: Lea Wiemann\n:Contact: docutils-develop@lists.sourceforge.net\n:Revision: $Revision$\n:Date: $Date$\n:Copyright: This document has been placed in the public domain.\n\n.. _Docutils: https://docutils.sourceforge.io/\n\n.. contents::\n\nThis document describes how to create packages of Docutils (e.g. for\nshipping with a Linux distribution).  If you have any questions,\nplease direct them to the Docutils-develop_ mailing list.\n\nFirst, please download the most current `release tarball`_ and unpack\nit.\n\n.. _Docutils-develop: ../user/mailing-lists.html#docutils-develop\n.. _release tarball: https://docutils.sourceforge.io/#download\n\n\nDependencies\n============\n\nDocutils has the following dependencies:\n\n* Python 3.7 or later is required.\n  Use \">= Python 3.7\" in the dependencies.\n\n* Docutils may optionally make use of the PIL (`Python Imaging\n  Library`_ or Pillow_).  If PIL is present, it is automatically\n  detected by Docutils.\n\n* Docutils recommends the `Pygments`_ syntax hightlighter. If available, it\n  is used for highlighting the content of `code directives`_ and roles as\n  well as included source code files (with the \"code\" option to the include_\n  directive).\n\n* Docutils can use the `recommonmark`_ parser to parse input in\n  the Markdown format (new in 0.17).\n\n.. _Python Imaging Library:\n    https://en.wikipedia.org/wiki/Python_Imaging_Library\n.. _Pillow: https://pypi.org/project/Pillow/\n.. _Pygments: https://pygments.org/\n.. _recommonmark: https://pypi.org/project/recommonmark/\n\n.. _code directives: ../ref/rst/directives.html#code\n.. _include: ../ref/rst/directives.html#include\n\n\nPython Files\n============\n\nThe Docutils Python files must be installed into the\n``site-packages/`` directory of Python.  Running ``python setup.py\ninstall`` should do the trick, but if you want to place the files\nyourself, you can just install the ``docutils/`` directory of the\nDocutils tarball to ``/usr/lib/python/site-packages/docutils/``.  In\nthis case you should also compile the Python files to ``.pyc`` and/or\n``.pyo`` files so that Docutils doesn't need to be recompiled every\ntime it's executed.\n\n\nExecutables\n===========\n\nThe executable front-end tools are located in the ``tools/`` directory\nof the Docutils tarball.\n\nThe ``rst2*.py`` tools are intended for end-users. You should install them\nto ``/usr/bin/``.  You do not need to change the names (e.g. to\n``docutils-rst2html.py``) because the ``rst2`` prefix is unique.\n\n\nDocumentation\n=============\n\nThe documentation should be generated using ``buildhtml.py``.  To\ngenerate HTML for all documentation files, go to the ``tools/``\ndirectory and run::\n\n    # Place html4css1.css in base directory.\n    cp ../docutils/writers/html4css1/html4css1.css ..\n    ./buildhtml.py --stylesheet-path=../html4css1.css ..\n\nThen install the following files to ``/usr/share/doc/docutils/`` (or\nwherever you install documentation):\n\n* All ``.html`` and ``.txt`` files in the base directory.\n\n* The ``docs/`` directory.\n\n  Do not install the contents of the ``docs/`` directory directly to\n  ``/usr/share/doc/docutils/``; it's incomplete and would contain\n  invalid references!\n\n* The ``licenses/`` directory.\n\n* ``html4css1.css`` in the base directory.\n\n\nRemoving the ``.txt`` Files\n---------------------------\n\nIf you are tight with disk space, you can remove all ``.txt`` files in\nthe tree except for:\n\n* those in the ``licenses/`` directory because they have not been\n  processed to HTML and\n\n* ``user/rst/cheatsheet.txt`` and ``user/rst/demo.txt``, which should\n  be readable in source form.\n\nBefore you remove the ``.txt`` files you should rerun ``buildhtml.py``\nwith the ``--no-source-link`` switch to avoid broken references to the\nsource files.\n\n\nOther Files\n===========\n\nYou may want to install the Emacs-Lisp files\n``tools/editors/emacs/*.el`` into the appropriate directory.\n\n\nConfiguration File\n==================\n\nIt is possible to have a system-wide configuration file at\n``/etc/docutils.conf``.  However, this is usually not necessary.  You\nshould *not* install ``tools/docutils.conf`` into ``/etc/``.\n\n\nTests\n=====\n\nWhile you probably do not need to ship the tests with your\ndistribution, you can test your package by installing it and then\nrunning ``alltests.py`` from the ``tests/`` directory of the Docutils\ntarball.\n\nFor more information on testing, view the `Docutils Testing`_ page.\n\n.. _Docutils Testing: https://docutils.sourceforge.io/docs/dev/testing.html\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/docutils_data/docs/dev/enthought-plan.txt",
    "content": "===========================================\n Plan for Enthought API Documentation Tool\n===========================================\n\n:Author: David Goodger\n:Contact: docutils-develop@lists.sourceforge.net\n:Date: $Date$\n:Revision: $Revision$\n:Copyright: 2004 by `Enthought, Inc. <http://www.enthought.com>`_\n:License: `Enthought License`_ (BSD-style)\n\n.. _Enthought License: https://docutils.sourceforge.io/licenses/enthought.txt\n\nThis document should be read in conjunction with the `Enthought API\nDocumentation Tool RFP`__ prepared by Janet Swisher.\n\n__ enthought-rfp.html\n\n.. contents::\n.. sectnum::\n\n\nIntroduction\n============\n\nIn March 2004 at I met Eric Jones, president and CTO of `Enthought,\nInc.`_, at `PyCon 2004`_ in Washington DC.  He told me that Enthought\nwas using reStructuredText_ for source code documentation, but they\nhad some issues.  He asked if I'd be interested in doing some work on\na customized API documentation tool.  Shortly after PyCon, Janet\nSwisher, Enthought's senior technical writer, contacted me to work out\ndetails.  Some email, a trip to Austin in May, and plenty of Texas\nhospitality later, we had a project.  This document will record the\ndetails, milestones, and evolution of the project.\n\nIn a nutshell, Enthought is sponsoring the implementation of an open\nsource API documentation tool that meets their needs.  Fortuitously,\ntheir needs coincide well with the \"Python Source Reader\" description\nin `PEP 258`_.  In other words, Enthought is funding some significant\nimprovements to Docutils, improvements that were planned but never\nimplemented due to time and other constraints.  The implementation\nwill take place gradually over several months, on a part-time basis.\n\nThis is an ideal example of cooperation between a corporation and an\nopen-source project.  The corporation, the project, I personally, and\nthe community all benefit.  Enthought, whose commitment to open source\nis also evidenced by their sponsorship of SciPy_, benefits by\nobtaining a useful piece of software, much more quickly than would\nhave been possible without their support.  Docutils benefits directly\nfrom the implementation of one of its core subsystems.  I benefit from\nthe funding, which allows me to justify the long hours to my wife and\nfamily.  All the corporations, projects, and individuals that make up\nthe community will benefit from the end result, which will be great.\n\nAll that's left now is to actually do the work!\n\n.. _PyCon 2004: http://pycon.org/dc2004/\n.. _reStructuredText: https://docutils.sourceforge.io/rst.html\n.. _SciPy: http://www.scipy.org/\n\n\nDevelopment Plan\n================\n\n1. Analyze prior art, most notably Epydoc_ and HappyDoc_, to see how\n   they do what they do.  I have no desire to reinvent wheels\n   unnecessarily.  I want to take the best ideas from each tool,\n   combined with the outline in `PEP 258`_ (which will evolve), and\n   build at least the foundation of the definitive Python\n   auto-documentation tool.\n\n   .. _Epydoc: http://epydoc.sourceforge.net/\n   .. _HappyDoc: http://happydoc.sourceforge.net/\n   .. _PEP 258:\n      https://docutils.sourceforge.io/docs/peps/pep-0258.html#python-source-reader\n\n2. Decide on a base platform.  The best way to achieve Enthought's\n   goals in a reasonable time frame may be to extend Epydoc or\n   HappyDoc.  Or it may be necessary to start fresh.\n\n3. Extend the reStructuredText parser.  See `Proposed Changes to\n   reStructuredText`_ below.\n\n4. Depending on the base platform chosen, build or extend the\n   docstring & doc comment extraction tool.  This may be the biggest\n   part of the project, but I won't be able to break it down into\n   details until more is known.\n\n\nRepository\n==========\n\nIf possible, all software and documentation files will be stored in\nthe Subversion repository of Docutils and/or the base project, which\nare all publicly-available via anonymous pserver access.\n\nThe Docutils project is very open about granting Subversion write\naccess; so far, everyone who asked has been given access.  Any\nEnthought staff member who would like Subversion write access will get\nit.\n\nIf either Epydoc or HappyDoc is chosen as the base platform, I will\nask the project's administrator for CVS access for myself and any\nEnthought staff member who wants it.  If sufficient access is not\ngranted -- although I doubt that there would be any problem -- we may\nhave to begin a fork, which could be hosted on SourceForge, on\nEnthought's Subversion server, or anywhere else deemed appropriate.\n\n\nCopyright & License\n===================\n\nMost existing Docutils files have been placed in the public domain, as\nfollows::\n\n    :Copyright: This document has been placed in the public domain.\n\nThis is in conjunction with the \"Public Domain Dedication\" section of\nCOPYING.txt__.\n\n__ https://docutils.sourceforge.io/COPYING.html\n\nThe code and documentation originating from Enthought funding will\nhave Enthought's copyright and license declaration.  While I will try\nto keep Enthought-specific code and documentation separate from the\nexisting files, there will inevitably be cases where it makes the most\nsense to extend existing files.\n\nI propose the following:\n\n1. New files related to this Enthought-funded work will be identified\n   with the following field-list headers::\n\n       :Copyright: 2004 by Enthought, Inc.\n       :License: Enthought License (BSD Style)\n\n   The license field text will be linked to the license file itself.\n\n2. For significant or major changes to an existing file (more than 10%\n   change), the headers shall change as follows (for example)::\n\n       :Copyright: 2001-2004 by David Goodger\n       :Copyright: 2004 by Enthought, Inc.\n       :License: BSD-style\n\n   If the Enthought-funded portion becomes greater than the previously\n   existing portion, Enthought's copyright line will be shown first.\n\n3. In cases of insignificant or minor changes to an existing file\n   (less than 10% change), the public domain status shall remain\n   unchanged.\n\nA section describing all of this will be added to the Docutils\n`COPYING`__ instructions file.\n\nIf another project is chosen as the base project, similar changes\nwould be made to their files, subject to negotiation.\n\n__ https://docutils.sourceforge.io/COPYING.html\n\n\nProposed Changes to reStructuredText\n====================================\n\nDoc Comment Syntax\n------------------\n\nThe \"traits\" construct is implemented as dictionaries, where\nstandalone strings would be Python syntax errors.  Therefore traits\nrequire documentation in comments.  We also need a way to\ndifferentiate between ordinary \"internal\" comments and documentation\ncomments (doc comments).\n\nJavadoc uses the following syntax for doc comments::\n\n    /**\n     * The first line of a multi-line doc comment begins with a slash\n     * and *two* asterisks.  The doc comment ends normally.\n     */\n\nPython doesn't have multi-line comments; only single-line.  A similar\nconvention in Python might look like this::\n\n    ##\n    # The first line of a doc comment begins with *two* hash marks.\n    # The doc comment ends with the first non-comment line.\n    'data' : AnyValue,\n\n    ## The double-hash-marks could occur on the first line of text,\n    #  saving a line in the source.\n    'data' : AnyValue,\n\nHow to indicate the end of the doc comment? ::\n\n    ##\n    # The first line of a doc comment begins with *two* hash marks.\n    # The doc comment ends with the first non-comment line, or another\n    # double-hash-mark.\n    ##\n    # This is an ordinary, internal, non-doc comment.\n    'data' : AnyValue,\n\n    ## First line of a doc comment, terse syntax.\n    #  Second (and last) line.  Ends here: ##\n    # This is an ordinary, internal, non-doc comment.\n    'data' : AnyValue,\n\nOr do we even need to worry about this case?  A simple blank line\ncould be used::\n\n    ## First line of a doc comment, terse syntax.\n    #  Second (and last) line.  Ends with a blank line.\n\n    # This is an ordinary, internal, non-doc comment.\n    'data' : AnyValue,\n\nOther possibilities::\n\n    #\" Instead of double-hash-marks, we could use a hash mark and a\n    #  quotation mark to begin the doc comment.\n    'data' : AnyValue,\n\n    ## We could require double-hash-marks on every line.  This has the\n    ## added benefit of delimiting the *end* of the doc comment, as\n    ## well as working well with line wrapping in Emacs\n    ## (\"fill-paragraph\" command).\n    # Ordinary non-doc comment.\n    'data' : AnyValue,\n\n    #\" A hash mark and a quotation mark on each line looks funny, and\n    #\" it doesn't work well with line wrapping in Emacs.\n    'data' : AnyValue,\n\nThese styles (repeated on each line) work well with line wrapping in\nEmacs::\n\n    ##  #>  #|  #-  #%  #!  #*\n\nThese styles do *not* work well with line wrapping in Emacs::\n\n    #\"  #'  #:  #)  #.  #/  #@  #$  #^  #=  #+  #_  #~\n\nThe style of doc comment indicator used could be a runtime, global\nand/or per-module setting.  That may add more complexity than it's\nworth though.\n\n\nRecommendation\n``````````````\n\nI recommend adopting \"#*\" on every line::\n\n    # This is an ordinary non-doc comment.\n\n    #* This is a documentation comment, with an asterisk after the\n    #* hash marks on every line.\n    'data' : AnyValue,\n\nI initially recommended adopting double-hash-marks::\n\n    # This is an ordinary non-doc comment.\n\n    ## This is a documentation comment, with double-hash-marks on\n    ## every line.\n    'data' : AnyValue,\n\nBut Janet Swisher rightly pointed out that this could collide with\nordinary comments that are then block-commented.  This applies to\ndouble-hash-marks on the first line only as well.  So they're out.\n\nOn the other hand, the JavaDoc-comment style (\"##\" on the first line\nonly, \"#\" after that) is used in Fredrik Lundh's PythonDoc_.  It may\nbe worthwhile to conform to this syntax, reinforcing it as a standard.\nPythonDoc does not support terse doc comments (text after \"##\" on the\nfirst line).\n\n.. _PythonDoc: http://effbot.org/zone/pythondoc.htm\n\n\nUpdate\n``````\n\nEnthought's Traits system has switched to a metaclass base, and traits\nare now defined via ordinary attributes.  Therefore doc comments are\nno longer absolutely necessary; attribute docstrings will suffice.\nDoc comments may still be desirable though, since they allow\ndocumentation to precede the thing being documented.\n\n\nDocstring Density & Whitespace Minimization\n-------------------------------------------\n\nOne problem with extensively documented classes & functions, is that\nthere is a lot of screen space wasted on whitespace.  Here's some\ncurrent Enthought code (from lib/cp/fluids/gassmann.py)::\n\n    def max_gas(temperature, pressure, api, specific_gravity=.56):\n        \"\"\"\n        Computes the maximum dissolved gas in oil using Batzle and\n        Wang (1992).\n\n        Parameters\n        ----------\n        temperature : sequence\n            Temperature in degrees Celsius\n        pressure : sequence\n            Pressure in MPa\n        api : sequence\n            Stock tank oil API\n        specific_gravity : sequence\n            Specific gravity of gas at STP, default is .56\n\n        Returns\n        -------\n        max_gor : sequence\n            Maximum dissolved gas in liters/liter\n\n        Description\n        -----------\n        This estimate is based on equations given by Mavko, Mukerji,\n        and Dvorkin, (1998, pp. 218-219, or 2003, p. 236) obtained\n        originally from Batzle and Wang (1992).\n        \"\"\"\n        code...\n\nThe docstring is 24 lines long.\n\nRather than using subsections, field lists (which exist now) can save\n6 lines::\n\n    def max_gas(temperature, pressure, api, specific_gravity=.56):\n        \"\"\"\n        Computes the maximum dissolved gas in oil using Batzle and\n        Wang (1992).\n\n        :Parameters:\n            temperature : sequence\n                Temperature in degrees Celsius\n            pressure : sequence\n                Pressure in MPa\n            api : sequence\n                Stock tank oil API\n            specific_gravity : sequence\n                Specific gravity of gas at STP, default is .56\n        :Returns:\n            max_gor : sequence\n                Maximum dissolved gas in liters/liter\n        :Description: This estimate is based on equations given by\n            Mavko, Mukerji, and Dvorkin, (1998, pp. 218-219, or 2003,\n            p. 236) obtained originally from Batzle and Wang (1992).\n        \"\"\"\n        code...\n\nAs with the \"Description\" field above, field bodies may begin on the\nsame line as the field name, which also saves space.\n\nThe output for field lists is typically a table structure.  For\nexample:\n\n    :Parameters:\n        temperature : sequence\n            Temperature in degrees Celsius\n        pressure : sequence\n            Pressure in MPa\n        api : sequence\n            Stock tank oil API\n        specific_gravity : sequence\n            Specific gravity of gas at STP, default is .56\n    :Returns:\n        max_gor : sequence\n            Maximum dissolved gas in liters/liter\n    :Description:\n        This estimate is based on equations given by Mavko,\n        Mukerji, and Dvorkin, (1998, pp. 218-219, or 2003, p. 236)\n        obtained originally from Batzle and Wang (1992).\n\nBut the definition lists describing the parameters and return values\nare still wasteful of space.  There are a lot of half-filled lines.\n\nDefinition lists are currently defined as::\n\n    term : classifier\n        definition\n\nWhere the classifier part is optional.  Ideas for improvements:\n\n1. We could allow multiple classifiers::\n\n       term : classifier one : two : three ...\n           definition\n\n2. We could allow the definition on the same line as the term, using\n   some embedded/inline markup:\n\n   * \"--\" could be used, but only in limited and well-known contexts::\n\n         term -- definition\n\n     This is the syntax used by StructuredText (one of\n     reStructuredText's predecessors).  It was not adopted for\n     reStructuredText because it is ambiguous -- people often use \"--\"\n     in their text, as I just did.  But given a constrained context,\n     the ambiguity would be acceptable (or would it?).  That context\n     would be: in docstrings, within a field list, perhaps only with\n     certain well-defined field names (parameters, returns).\n\n   * The \"constrained context\" above isn't really enough to make the\n     ambiguity acceptable.  Instead, a slightly more verbose but far\n     less ambiguous syntax is possible::\n\n         term === definition\n\n     This syntax has advantages.  Equals signs lend themselves to the\n     connotation of \"definition\".  And whereas one or two equals signs\n     are commonly used in program code, three equals signs in a row\n     have no conflicting meanings that I know of.  (Update: there\n     *are* uses out there.)\n\n   The problem with this approach is that using inline markup for\n   structure is inherently ambiguous in reStructuredText.  For\n   example, writing *about* definition lists would be difficult::\n\n       ``term === definition`` is an example of a compact definition list item\n\n   The parser checks for structural markup before it does inline\n   markup processing.  But the \"===\" should be protected by its inline\n   literal context.\n\n3. We could allow the definition on the same line as the term, using\n   structural markup.  A variation on bullet lists would work well::\n\n       : term :: definition\n       : another term :: and a definition that\n         wraps across lines\n\n   Some ambiguity remains::\n\n       : term ``containing :: double colons`` :: definition\n\n   But the likelihood of such cases is negligible, and they can be\n   covered in the documentation.\n\n   Other possibilities for the definition delimiter include::\n\n       : term : classifier -- definition\n       : term : classifier --- definition\n       : term : classifier : : definition\n       : term : classifier === definition\n\nThe third idea currently has the best chance of being adopted and\nimplemented.\n\n\nRecommendation\n``````````````\n\nCombining these ideas, the function definition becomes::\n\n    def max_gas(temperature, pressure, api, specific_gravity=.56):\n        \"\"\"\n        Computes the maximum dissolved gas in oil using Batzle and\n        Wang (1992).\n\n        :Parameters:\n            : temperature : sequence :: Temperature in degrees Celsius\n            : pressure : sequence :: Pressure in MPa\n            : api : sequence :: Stock tank oil API\n            : specific_gravity : sequence :: Specific gravity of gas at\n              STP, default is .56\n        :Returns:\n            : max_gor : sequence :: Maximum dissolved gas in liters/liter\n        :Description: This estimate is based on equations given by\n            Mavko, Mukerji, and Dvorkin, (1998, pp. 218-219, or 2003,\n            p. 236) obtained originally from Batzle and Wang (1992).\n        \"\"\"\n        code...\n\nThe docstring is reduced to 14 lines, from the original 24.  For\nlonger docstrings with many parameters and return values, the\ndifference would be more significant.\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/docutils_data/docs/dev/enthought-rfp.txt",
    "content": "==================================\n Enthought API Documentation Tool\n==================================\n-----------------------\n Request for Proposals\n-----------------------\n\n:Author: Janet Swisher, Senior Technical Writer\n:Organization: `Enthought, Inc. <http://www.enthought.com>`_\n:Copyright: 2004 by Enthought, Inc.\n:License: `Enthought License`_ (BSD Style)\n\n.. _Enthought License: https://docutils.sourceforge.io/licenses/enthought.txt\n\nThe following is excerpted from the full RFP, and is published here\nwith permission from `Enthought, Inc.`_  See the `Plan for Enthought\nAPI Documentation Tool`__.\n\n__ enthought-plan.html\n\n.. contents::\n.. sectnum::\n\n\nRequirements\n============\n\nThe documentation tool will address the following high-level goals:\n\n\nDocumentation Extraction\n------------------------\n\n1. Documentation will be generated directly from Python source code,\n   drawing from the code structure, docstrings, and possibly other\n   comments.\n\n2. The tool will extract logical constructs as appropriate, minimizing\n   the need for comments that are redundant with the code structure.\n   The output should reflect both documented and undocumented\n   elements.\n\n\nSource Format\n-------------\n\n1. The docstrings will be formatted in as terse syntax as possible.\n   Required tags, syntax, and white space should be minimized.\n\n2. The tool must support the use of Traits.  Special comment syntax\n   for Traits may be necessary.  Information about the Traits package\n   is available at http://code.enthought.com/traits/.  In the\n   following example, each trait definition is prefaced by a plain\n   comment::\n\n       __traits__ = {\n\n       # The current selection within the frame.\n       'selection' : Trait([], TraitInstance(list)),\n\n       # The frame has been activated or deactivated.\n       'activated' : TraitEvent(),\n\n       'closing' : TraitEvent(),\n\n       # The frame is closed.\n       'closed' : TraitEvent(),\n       }\n\n3. Support for ReStructuredText (ReST) format is desirable, because\n   much of the existing docstrings uses ReST.  However, the complete\n   ReST specification need not be supported, if a subset can achieve\n   the project goals.  If the tool does not support ReST, the\n   contractor should also provide a tool or path to convert existing\n   docstrings.\n\n\nOutput Format\n-------------\n\n1. Documentation will be output as a navigable suite of HTML\n   files.\n\n2. The style of the HTML files will be customizable by a cascading\n   style sheet and/or a customizable template.\n\n3. Page elements such as headers and footer should be customizable, to\n   support differing requirements from one documentation project to\n   the next.\n\n\nOutput Structure and Navigation\n-------------------------------\n\n1. The navigation scheme for the HTML files should not rely on frames,\n   and should harmonize with conversion to Microsoft HTML Help (.chm)\n   format.\n\n2. The output should be structured to make navigable the architecture\n   of the Python code.  Packages, modules, classes, traits, and\n   functions should be presented in clear, logical hierarchies.\n   Diagrams or trees for inheritance, collaboration, sub-packaging,\n   etc. are desirable but not required.\n\n3. The output must include indexes that provide a comprehensive view\n   of all packages, modules, and classes.  These indexes will provide\n   readers with a clear and exhaustive view of the code base.  These\n   indexes should be presented in a way that is easily accessible and\n   allows easy navigation.\n\n4. Cross-references to other documented elements will be used\n   throughout the documentation, to enable the reader to move quickly\n   relevant information.  For example, where type information for an\n   element is available, the type definition should be\n   cross-referenced.\n\n5. The HTML suite should provide consistent navigation back to the\n   home page, which will include the following information:\n\n   * Bibliographic information\n\n     - Author\n     - Copyright\n     - Release date\n     - Version number\n\n   * Abstract\n\n   * References\n\n     - Links to related internal docs (i.e., other docs for the same\n       product)\n\n     - Links to related external docs (e.g., supporting development\n       docs, Python support docs, docs for included packages)\n\n   It should be possible to specify similar information at the top\n   level of each package, so that packages can be included as\n   appropriate for a given application.\n\n\nLicense\n=======\n\nEnthought intends to release the software under an open-source\n(\"BSD-style\") license.\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/docutils_data/docs/dev/hacking.txt",
    "content": "==========================\n Docutils_ Hacker's Guide\n==========================\n\n:Author: Lea Wiemann\n:Contact: docutils-develop@lists.sourceforge.net\n:Revision: $Revision$\n:Date: $Date$\n:Copyright: This document has been placed in the public domain.\n\n:Abstract: This is the introduction to Docutils for all persons who\n    want to extend Docutils in some way.\n:Prerequisites: You have used reStructuredText_ and played around with\n    the `Docutils front-end tools`_ before.  Some (basic) Python\n    knowledge is certainly helpful (though not necessary, strictly\n    speaking).\n\n.. _Docutils: https://docutils.sourceforge.io/\n.. _reStructuredText: https://docutils.sourceforge.io/rst.html\n.. _Docutils front-end tools: ../user/tools.html\n\n.. contents::\n\n\nOverview of the Docutils Architecture\n=====================================\n\nTo give you an understanding of the Docutils architecture, we'll dive\nright into the internals using a practical example.\n\nConsider the following reStructuredText file::\n\n    My *favorite* language is Python_.\n\n    .. _Python: https://www.python.org/\n\nUsing the ``rst2html.py`` front-end tool, you would get an HTML output\nwhich looks like this::\n\n    [uninteresting HTML code removed]\n    <body>\n    <div class=\"document\">\n    <p>My <em>favorite</em> language is <a class=\"reference\" href=\"https://www.python.org/\">Python</a>.</p>\n    </div>\n    </body>\n    </html>\n\nWhile this looks very simple, it's enough to illustrate all internal\nprocessing stages of Docutils.  Let's see how this document is\nprocessed from the reStructuredText source to the final HTML output:\n\n\nReading the Document\n--------------------\n\nThe **Reader** reads the document from the source file and passes it\nto the parser (see below).  The default reader is the standalone\nreader (``docutils/readers/standalone.py``) which just reads the input\ndata from a single text file.  Unless you want to do really fancy\nthings, there is no need to change that.\n\nSince you probably won't need to touch readers, we will just move on\nto the next stage:\n\n\nParsing the Document\n--------------------\n\nThe **Parser** analyzes the the input document and creates a **node\ntree** representation.  In this case we are using the\n**reStructuredText parser** (``docutils/parsers/rst/__init__.py``).\nTo see what that node tree looks like, we call ``quicktest.py`` (which\ncan be found in the ``tools/`` directory of the Docutils distribution)\nwith our example file (``test.txt``) as first parameter (Windows users\nmight need to type ``python quicktest.py test.txt``)::\n\n    $ quicktest.py test.txt\n    <document source=\"test.txt\">\n        <paragraph>\n            My\n            <emphasis>\n                favorite\n             language is\n            <reference name=\"Python\" refname=\"python\">\n                Python\n            .\n        <target ids=\"python\" names=\"python\" refuri=\"https://www.python.org/\">\n\nLet us now examine the node tree:\n\nThe top-level node is ``document``.  It has a ``source`` attribute\nwhose value is ``text.txt``.  There are two children: A ``paragraph``\nnode and a ``target`` node.  The ``paragraph`` in turn has children: A\ntext node (\"My \"), an ``emphasis`` node, a text node (\" language is \"),\na ``reference`` node, and again a ``Text`` node (\".\").\n\nThese node types (``document``, ``paragraph``, ``emphasis``, etc.) are\nall defined in ``docutils/nodes.py``.  The node types are internally\narranged as a class hierarchy (for example, both ``emphasis`` and\n``reference`` have the common superclass ``Inline``).  To get an\noverview of the node class hierarchy, use epydoc (type ``epydoc\nnodes.py``) and look at the class hierarchy tree.\n\n\nTransforming the Document\n-------------------------\n\nIn the node tree above, the ``reference`` node does not contain the\ntarget URI (``https://www.python.org/``) yet.\n\nAssigning the target URI (from the ``target`` node) to the\n``reference`` node is *not* done by the parser (the parser only\ntranslates the input document into a node tree).\n\nInstead, it's done by a **Transform**.  In this case (resolving a\nreference), it's done by the ``ExternalTargets`` transform in\n``docutils/transforms/references.py``.\n\nIn fact, there are quite a lot of Transforms, which do various useful\nthings like creating the table of contents, applying substitution\nreferences or resolving auto-numbered footnotes.\n\nThe Transforms are applied after parsing.  To see how the node tree\nhas changed after applying the Transforms, we use the\n``rst2pseudoxml.py`` tool:\n\n.. parsed-literal::\n\n    $ rst2pseudoxml.py test.txt\n    <document source=\"test.txt\">\n        <paragraph>\n            My\n            <emphasis>\n                favorite\n             language is\n            <reference name=\"Python\" **refuri=\"https://www.python.org/\"**>\n                Python\n            .\n        <target ids=\"python\" names=\"python\" ``refuri=\"https://www.python.org/\"``>\n\nFor our small test document, the only change is that the ``refname``\nattribute of the reference has been replaced by a ``refuri``\nattribute |---| the reference has been resolved.\n\nWhile this does not look very exciting, transforms are a powerful tool\nto apply any kind of transformation on the node tree.\n\nBy the way, you can also get a \"real\" XML representation of the node\ntree by using ``rst2xml.py`` instead of ``rst2pseudoxml.py``.\n\n\nWriting the Document\n--------------------\n\nTo get an HTML document out of the node tree, we use a **Writer**, the\nHTML writer in this case (``docutils/writers/html4css1.py``).\n\nThe writer receives the node tree and returns the output document.\nFor HTML output, we can test this using the ``rst2html.py`` tool::\n\n    $ rst2html.py --link-stylesheet test.txt\n    <?xml version=\"1.0\" encoding=\"utf-8\" ?>\n    <!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n    <html xmlns=\"https://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n    <head>\n    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n    <meta name=\"generator\" content=\"Docutils 0.3.10: https://docutils.sourceforge.io/\" />\n    <title></title>\n    <link rel=\"stylesheet\" href=\"../docutils/writers/html4css1/html4css1.css\" type=\"text/css\" />\n    </head>\n    <body>\n    <div class=\"document\">\n    <p>My <em>favorite</em> language is <a class=\"reference\" href=\"https://www.python.org/\">Python</a>.</p>\n    </div>\n    </body>\n    </html>\n\nSo here we finally have our HTML output.  The actual document contents\nare in the fourth-last line.  Note, by the way, that the HTML writer\ndid not render the (invisible) ``target`` node |---| only the\n``paragraph`` node and its children appear in the HTML output.\n\n\nExtending Docutils\n==================\n\nNow you'll ask, \"how do I actually extend Docutils?\"\n\nFirst of all, once you are clear about *what* you want to achieve, you\nhave to decide *where* to implement it |---| in the Parser (e.g. by\nadding a directive or role to the reStructuredText parser), as a\nTransform, or in the Writer.  There is often one obvious choice among\nthose three (Parser, Transform, Writer).  If you are unsure, ask on\nthe Docutils-develop_ mailing list.\n\nIn order to find out how to start, it is often helpful to look at\nsimilar features which are already implemented.  For example, if you\nwant to add a new directive to the reStructuredText parser, look at\nthe implementation of a similar directive in\n``docutils/parsers/rst/directives/``.\n\n\nModifying the Document Tree Before It Is Written\n------------------------------------------------\n\nYou can modify the document tree right before the writer is called.\nOne possibility is to use the publish_doctree_ and\npublish_from_doctree_ functions.\n\nTo retrieve the document tree, call::\n\n    document = docutils.core.publish_doctree(...)\n\nPlease see the docstring of publish_doctree for a list of parameters.\n\n.. XXX Need to write a well-readable list of (commonly used) options\n   of the publish_* functions.  Probably in api/publisher.txt.\n\n``document`` is the root node of the document tree.  You can now\nchange the document by accessing the ``document`` node and its\nchildren |---| see `The Node Interface`_ below.\n\nWhen you're done with modifying the document tree, you can write it\nout by calling::\n\n    output = docutils.core.publish_from_doctree(document, ...)\n\n.. _publish_doctree: ../api/publisher.html#publish_doctree\n.. _publish_from_doctree: ../api/publisher.html#publish_from_doctree\n\n\nThe Node Interface\n------------------\n\nAs described in the overview above, Docutils' internal representation\nof a document is a tree of nodes.  We'll now have a look at the\ninterface of these nodes.\n\n(To be completed.)\n\n\nWhat Now?\n=========\n\nThis document is not complete.  Many topics could (and should) be\ncovered here.  To find out with which topics we should write about\nfirst, we are awaiting *your* feedback.  So please ask your questions\non the Docutils-develop_ mailing list.\n\n\n.. _Docutils-develop: ../user/mailing-lists.html#docutils-develop\n\n\n.. |---| unicode:: 8212 .. em-dash\n   :trim:\n\n\f\n..\n   Local Variables:\n   mode: indented-text\n   indent-tabs-mode: nil\n   sentence-end-double-space: t\n   fill-column: 70\n   End:\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/docutils_data/docs/dev/policies.txt",
    "content": "===========================\n Docutils Project Policies\n===========================\n\n:Author: David Goodger; open to all Docutils developers\n:Contact: docutils-develop@lists.sourceforge.net\n:Date: $Date$\n:Revision: $Revision$\n:Copyright: This document has been placed in the public domain.\n\n.. contents::\n\nThe Docutils project group is a meritocracy based on code contribution\nand lots of discussion [#bcs]_.  A few quotes sum up the policies of\nthe Docutils project.  The IETF's classic credo (by MIT professor Dave\nClark) is an ideal we can aspire to:\n\n    We reject: kings, presidents, and voting.  We believe in: rough\n    consensus and running code.\n\nAs architect, chief cook and bottle-washer, David Goodger currently\nfunctions as BDFN (Benevolent Dictator For Now).  (But he would\nhappily abdicate the throne given a suitable candidate.  Any takers?)\n\nEric S. Raymond, anthropologist of the hacker subculture, writes in\nhis essay `The Magic Cauldron`_:\n\n    The number of contributors [to] projects is strongly and inversely\n    correlated with the number of hoops each project makes a user go\n    through to contribute.\n\nWe will endeavour to keep the barrier to entry as low as possible.\nThe policies below should not be thought of as barriers, but merely as\na codification of experience to date.  These are \"best practices\";\nguidelines, not absolutes.  Exceptions are expected, tolerated, and\nused as a source of improvement.  Feedback and criticism is welcome.\n\nAs for control issues, Emmett Plant (CEO of the Xiph.org Foundation,\noriginators of Ogg Vorbis) put it well when he said:\n\n    Open source dictates that you lose a certain amount of control\n    over your codebase, and that's okay with us.\n\n.. [#bcs] Phrase borrowed from `Ben Collins-Sussman of the Subversion\n   project <http://www.red-bean.com/sussman/svn-anti-fud.html>`__.\n\n.. _The Magic Cauldron:\n   http://www.catb.org/~esr/writings/magic-cauldron/\n\n\nPython Coding Conventions\n=========================\n\nContributed code will not be refused merely because it does not\nstrictly adhere to these conditions; as long as it's internally\nconsistent, clean, and correct, it probably will be accepted.  But\ndon't be surprised if the \"offending\" code gets fiddled over time to\nconform to these conventions.\n\nThe Docutils project shall follow the generic coding conventions as\nspecified in the `Style Guide for Python Code`_ and `Docstring\nConventions`_ PEPs, summarized, clarified, and extended as follows:\n\n* 4 spaces per indentation level.  No hard tabs.\n\n* Use only 7-bit ASCII, no 8-bit strings.  See `Docutils\n  Internationalization`_.\n\n* No one-liner compound statements (i.e., no ``if x: return``: use two\n  lines & indentation), except for degenerate class or method\n  definitions (i.e., ``class X: pass`` is OK.).\n\n* Lines should be no more than 78 characters long.\n\n* Use \"StudlyCaps\" for class names (except for element classes in\n  docutils.nodes).\n\n* Use \"lowercase\" or \"lowercase_with_underscores\" for function,\n  method, and variable names.  For short names, maximum two words,\n  joined lowercase may be used (e.g. \"tagname\").  For long names with\n  three or more words, or where it's hard to parse the split between\n  two words, use lowercase_with_underscores (e.g.,\n  \"note_explicit_target\", \"explicit_target\").  If in doubt, use\n  underscores.\n\n* Avoid lambda expressions, which are inherently difficult to\n  understand.  Named functions are preferable and superior: they're\n  faster (no run-time compilation), and well-chosen names serve to\n  document and aid understanding.\n\n* Avoid functional constructs (filter, map, etc.).  Use list\n  comprehensions instead.\n\n* Avoid ``from __future__ import`` constructs.  They are inappropriate\n  for production code.\n\n* Use 'single quotes' for string literals, and \"\"\"triple double\n  quotes\"\"\" for docstrings.\n\n.. _Style Guide for Python Code:\n   https://peps.python.org/pep-0008\n.. _Docstring Conventions: https://peps.python.org/pep-0257\n.. _Docutils Internationalization: ../howto/i18n.html#python-code\n\n\nDocumentation Conventions\n=========================\n\n* Docutils documentation is written using reStructuredText, of course.\n\n* Use 7-bit ASCII if at all possible, and Unicode substitutions when\n  necessary.\n\n* Use the following section title adornment styles::\n\n      ================\n       Document Title\n      ================\n\n      --------------------------------------------\n       Document Subtitle, or Major Division Title\n      --------------------------------------------\n\n      Section\n      =======\n\n      Subsection\n      ----------\n\n      Sub-Subsection\n      ``````````````\n\n      Sub-Sub-Subsection\n      ..................\n\n* Use two blank lines before each section/subsection/etc. title.  One\n  blank line is sufficient between immediately adjacent titles.\n\n* Add a bibliographic field list immediately after the document\n  title/subtitle.  See the beginning of this document for an example.\n\n* Add an Emacs \"local variables\" block in a comment at the end of the\n  document.  See the end of this document for an example.\n\n\nCopyrights and Licensing\n========================\n\nThe majority of the Docutils project code and documentation has been\nplaced in the public domain (see `Copying Docutils`_).\n\nUnless clearly and explicitly indicated\notherwise, any patches (modifications to existing files) submitted to\nthe project for inclusion (via Subversion, SourceForge trackers,\nmailing lists, or private email) are assumed to be in the public\ndomain as well.\n\nAny new files contributed to the project should clearly state their\nintentions regarding copyright, in one of the following ways:\n\n* Public domain (preferred): include the statement \"This\n  module/document has been placed in the public domain.\"\n\n* Copyright & open source license: include a copyright notice, along\n  with either an embedded license statement, a reference to an\n  accompanying license file, or a license URL.\n\n  The license should be well known, simple and compatible with other\n  open source software licenses. To keep the number of different\n  licenses at a minimum, using the `2-Clause BSD license`_\n  (`local copy`__) is recommended.\n\n  .. Rationale:\n     + clear wording, structured text\n     + license used by the closely related Sphinx project\n\n.. _Copying Docutils: ../../COPYING.html\n.. _2-Clause BSD license: http://opensource.org/licenses/BSD-2-Clause\n__ ../../licenses/BSD-2-Clause.txt\n\n\n.. _Subversion Repository:\n\nRepository\n==========\n\nPlease see the `repository documentation`_ for details on how to\naccess Docutils' Subversion repository.  Anyone can access the\nrepository anonymously.  Only project developers can make changes.\n(If you would like to become a project developer, just ask!)  Also see\n`Setting Up For Docutils Development`_ below for some useful info.\n\nUnless you really *really* know what you're doing, please do *not* use\n``svn import``.  It's quite easy to mess up the repository with an\nimport.\n\n.. _repository documentation: repository.html\n\n\nBranches\n--------\n\n(These branch policies go into effect with Docutils 0.4.)\n\nThe \"docutils\" directory of the **trunk** (a.k.a. the **Docutils\ncore**) is used for active -- but stable, fully tested, and reviewed\n-- development.\n\nIf we need to cut a bugfix release, we'll create a **maintenance branch**\nbased on the latest feature release.  For example, when Docutils 0.5 is\nreleased, this would be ``branches/docutils-0.5``, and any existing 0.4.x\nmaintenance branches may be retired.  Maintenance branches will receive bug\nfixes only; no new features will be allowed here.\n\nObvious and uncontroversial bug fixes *with tests* can be checked in\ndirectly to the core and to the maintenance branches.  Don't forget to\nadd test cases!  Many (but not all) bug fixes will be applicable both\nto the core and to the maintenance branches; these should be applied\nto both.  No patches or dedicated branches are required for bug fixes,\nbut they may be used.  It is up to the discretion of project\ndevelopers to decide which mechanism to use for each case.\n\n.. _feature branches:\n.. _feature branch:\n\nFeature additions and API changes will be done in **feature\nbranches**.  Feature branches will not be managed in any way.\nFrequent small check-ins are encouraged here.  Feature branches must be\ndiscussed on the `docutils-develop mailing list`_ and reviewed before\nbeing merged into the core.\n\n.. _docutils-develop mailing list:\n   https://lists.sourceforge.net/lists/listinfo/docutils-develop\n\n\nReview Criteria\n```````````````\n\nBefore a new feature, an API change, or a complex, disruptive, or\ncontroversial bug fix can be checked in to the core or into a\nmaintenance branch, it must undergo review.  These are the criteria:\n\n* The branch must be complete, and include full documentation and\n  tests.\n\n* There should ideally be one branch merge commit per feature or\n  change.  In other words, each branch merge should represent a\n  coherent change set.\n\n* The code must be stable and uncontroversial.  Moving targets and\n  features under debate are not ready to be merged.\n\n* The code must work.  The test suite must complete with no failures.\n  See `Docutils Testing`_.\n\nThe review process will ensure that at least one other set of eyeballs\n& brains sees the code before it enters the core.  In addition to the\nabove, the general `Check-ins`_ policy (below) also applies.\n\n.. _Docutils testing: testing.html\n\n\nCheck-ins\n---------\n\nChanges or additions to the Docutils core and maintenance branches\ncarry a commitment to the Docutils user community.  Developers must be\nprepared to fix and maintain any code they have committed.\n\nThe Docutils core (``trunk/docutils`` directory) and maintenance\nbranches should always be kept in a stable state (usable and as\nproblem-free as possible).  All changes to the Docutils core or\nmaintenance branches must be in `good shape`_, usable_, documented_,\ntested_, and `reasonably complete`_. Starting with version 1.0, they must\nalso comply with the `backwards compatibility policy`_.\n\n* _`Good shape` means that the code is clean, readable, and free of\n  junk code (unused legacy code; by analogy to \"junk DNA\").\n\n* _`Usable` means that the code does what it claims to do.  An \"XYZ\n  Writer\" should produce reasonable XYZ output.\n\n* _`Documented`: The more complete the documentation the better.\n  Modules & files must be at least minimally documented internally.\n  `Docutils Front-End Tools`_ should have a new section for any\n  front-end tool that is added.  `Docutils Configuration Files`_\n  should be modified with any settings/options defined.  For any\n  non-trivial change, the HISTORY.txt_ file should be updated.\n\n* _`Tested` means that unit and/or functional tests, that catch all\n  bugs fixed and/or cover all new functionality, have been added to\n  the test suite.  These tests must be checked by running the test\n  suite under all supported Python versions, and the entire test suite\n  must pass.  See `Docutils Testing`_.\n\n* _`Reasonably complete` means that the code must handle all input.\n  Here \"handle\" means that no input can cause the code to fail (cause\n  an exception, or silently and incorrectly produce nothing).\n  \"Reasonably complete\" does not mean \"finished\" (no work left to be\n  done).  For example, a writer must handle every standard element\n  from the Docutils document model; for unimplemented elements, it\n  must *at the very least* warn that \"Output for element X is not yet\n  implemented in writer Y\".\n\nIf you really want to check code directly into the Docutils core,\nyou can, but you must ensure that it fulfills the above criteria\nfirst.  People will start to use it and they will expect it to work!\nIf there are any issues with your code, or if you only have time for\ngradual development, you should put it on a branch or in the sandbox\nfirst.  It's easy to move code over to the Docutils core once it's\ncomplete.\n\nIt is the responsibility and obligation of all developers to keep the\nDocutils core and maintenance branches stable.  If a commit is made to\nthe core or maintenance branch which breaks any test, the solution is\nsimply to revert the change.  This is not vindictive; it's practical.\nWe revert first, and discuss later.\n\nDocutils will pursue an open and trusting policy for as long as\npossible, and deal with any aberrations if (and hopefully not when)\nthey happen.  We'd rather see a torrent of loose contributions than\njust a trickle of perfect-as-they-stand changes.  The occasional\nmistake is easy to fix.  That's what version control is for!\n\n.. _Docutils Front-End Tools: ../user/tools.html\n.. _Docutils Configuration Files: ../user/config.html\n.. _HISTORY.txt: ../../HISTORY.txt\n\n\n.. _`Version Numbering`:\n\nVersion Identification\n======================\n\nThe state of development of the current Docutils codebase is stored in\ntwo forms: the sequence `docutils.__version_info__`_ and the\n`PEP 440`_ conformant text string `docutils.__version__`_.\nSee also the `Docutils Release Procedure`_\n\n.. _Docutils Release Procedure: release.html#version-numbers\n\n\n``docutils.__version_info__``\n-----------------------------\n\n``docutils.__version_info__`` is an instance of ``docutils.VersionInfo``\nbased on collections.namedtuple_. It is modelled on `sys.version_info`_\nand has the following attributes:\n\nmajor : non-negative integer\n    **Major releases** (x.0, e.g. 1.0) will be rare, and will\n    represent major changes in API, functionality, or commitment.  The\n    major number will be bumped to 1 when the project is\n    feature-complete, and may be incremented later if there is a major\n    change in the design or API.  When Docutils reaches version 1.0,\n    the major APIs will be considered frozen.\n    For details, see the `backwards compatibility policy`_.\n\nminor : non-negative integer\n    Releases that change the minor number (x.y, e.g. 0.5) will be\n    **feature releases**; new features from the `Docutils core`_ will\n    be included.\n\nmicro : non-negative integer\n    Releases that change the micro number (x.y.z, e.g. 0.4.1) will be\n    **bug-fix releases**.  No new features will be introduced in these\n    releases; only bug fixes will be included.\n\n    The micro number is omitted from `docutils.__version__`_ when it\n    equals zero.\n\n_`releaselevel` : text string\n    The release level indicates the `development status`_ (or phase)\n    of the project's codebase:\n\n    =============  ==========  ===============================================\n    Release Level  Label [#]_  Description\n    =============  ==========  ===============================================\n    alpha          ``a``       Reserved for use after major experimental\n                               changes, to indicate an unstable codebase.\n\n    beta           ``b``       Indicates active development, between releases.\n\n    candidate      ``rc``      Release candidate: indicates that the\n                               codebase is ready to release unless\n                               significant bugs emerge.\n\n    final                      Indicates an official project release.\n    =============  ==========  ===============================================\n\n    .. [#] The labels are used in the `docutils.__version__`_ pre-release\n       segment.\n\n    .. _development status:\n       https://en.wikipedia.org/wiki/Software_release_life_cycle\n\n_`serial` : non-negative integer\n    The serial number is zero for final releases and incremented\n    whenever a new pre-release is begun.\n\n_`release` : boolean\n    True for official releases and pre-releases, False during\n    development.\n\n* One of *{major, minor, micro, serial}* is incremented after each\n  release, and the lower-order numbers are reset to 0.\n\n* The default state of the repository during active development is\n  release level = \"beta\", serial = 0, release = False.\n\n``docutils.__version_info__`` can be used to test for a minimally\nrequired version, e.g. ::\n\n    docutils.__version_info__ >= (0, 13)\n\nis True for all versions after ``\"0.13\"``.\n\n.. _collections.namedtuple:\n   https://docs.python.org/3/library/collections.html#collections.namedtuple\n.. _sys.version_info:\n   https://docs.python.org/3/library/sys.html#sys.version_info\n\n``docutils.__version__``\n------------------------\n\nThe text string ``docutils.__version__`` is a human readable,\n`PEP 440`_-conforming version specifier.  For version comparison\noperations, use `docutils.__version_info__`_.\n\n``docutils.__version__`` takes the following form::\n\n    \"<major>.<minor>[.<micro>][<releaselevel>[<serial>]][.dev]\"\n     <--- release segment ---><-- pre-release segment -><- development ->\n\n* The *pre-release segment* contains a label representing the\n  releaselevel_ (\"a\", \"b\", or \"rc\") and eventually a serial_ number\n  (omitted, if zero).\n\n* The *development segment* is ``\".dev\"`` during active development\n  (release_ == False) and omitted for official releases and pre-releases.\n\nExamples of ``docutils.__version__`` identifiers, over the course of\nnormal development (without branches), in ascending order:\n\n==============================  =============================\nRelease Level                   Version Identifier\n==============================  =============================\nfinal (release)                 0.14\nbeta (development) [#dev]_      0.15b.dev\nbeta (release)  [#skip]_        0.15b\ncandidate 1 (dev.)              0.15rc1.dev\ncandidate 1 (release)           0.15rc1\ncandidate 2 (dev.) [#skip]_     0.15rc2.dev\ncandidate 2 (release) [#skip]_  0.15rc2\n...\nfinal (release)                 0.15\nbeta (development) [#dev]_      0.16b.dev\n==============================  =============================\n\n.. [#dev] Default active development state between releases.\n.. [#skip] These steps may be skipped.\n\n.. _PEP 440: https://peps.python.org/pep-0440/\n\nPolicy History\n--------------\n\n* Prior to version 0.4, Docutils didn't have an official version\n  numbering policy, and micro releases contained both bug fixes and\n  new features.\n\n* An earlier version of this policy was adopted in October 2005, and\n  took effect with Docutils version 0.4.\n\n* This policy was updated in June 2017 for Docutils version 0.14. See\n  `Feature Request #50`_ and the `discussion on docutils-devel`__ from\n  May 28 to June 20 2017.\n\n  .. _Feature Request #50:\n     https://sourceforge.net/p/docutils/feature-requests/50/\n  __ https://sourceforge.net/p/docutils/mailman/message/35903816/\n\n\nBackwards Compatibility Policy\n==============================\n\n.. note:: The backwards compatibility policy outlined below is a stub.\n\nDocutils' backwards compatibility policy follows the rules for Python in\n:PEP:`387`.\n\n* The scope of the public API is laid out at the start of the `backwards\n  compatibility rules`_.\n\n* The rules for `making incompatible changes`_ apply.\n\nA majority of projects depends on Docutils indirectly, via the Sphinx_\ndocument processor.\n\n* Sphinx developers should be given the chance to fix or work around a\n  DeprecationWarning_ in the Sphinx development version before a new\n  Docutils version is released. Otherwise, use a PendingDeprecationWarning_.\n\nChanges that may affect end-users (e.g. by requiring changes to the\nconfiguration file or potentially breaking custom style sheets) should be\nannounced with a FutureWarning_.\n\n.. _backwards compatibility rules:\n   https://peps.python.org/pep-0387/#backwards-compatibility-rules\n.. _making incompatible changes:\n   https://peps.python.org/pep-0387/#making-incompatible-changes\n.. _Sphinx: https://www.sphinx-doc.org/\n.. _DeprecationWarning:\n   https://docs.python.org/3/library/exceptions.html#DeprecationWarning\n.. _PendingDeprecationWarning:\n   https://docs.python.org/3/library/exceptions.html#PendingDeprecationWarning\n.. _FutureWarning:\n   https://docs.python.org/3/library/exceptions.html#FutureWarning\n\n\nSnapshots\n=========\n\nSnapshot tarballs can be downloaded from the repository (see the \"download\nsnapshot\" button in the head of the code listing table).\n\n* the `Docutils core`_, representing the current cutting-edge state of\n  development;\n\n* the `sandbox directory`_ with contributed projects and extensions from\n  `the Sandbox`_;\n\n.. * maintenance branches, for bug fixes;\n\n   TODO: do we have active maintenance branches?\n   (the only branch looking like a maintenance branch is\n   https://sourceforge.net/p/docutils/code/HEAD/tree/branches/docutils-0.4)\n\n* `development branches`_, representing ongoing development efforts to bring\n  new features into Docutils.\n\n.. _Docutils core:\n   https://sourceforge.net/p/docutils/code/HEAD/tree/trunk/docutils\n.. _development branches:\n   https://sourceforge.net/p/docutils/code/HEAD/tree/branches/\n\n\nSetting Up For Docutils Development\n===================================\n\nWhen making changes to the code, testing_ is a must.  The code should\nbe run to verify that it produces the expected results, and the entire\ntest suite should be run too.  The modified Docutils code has to be\naccessible to Python for the tests to have any meaning.\nSee `editable installs`_ for ways to keep the Docutils code\naccessible during development.\n\n.. _testing: tested_\n.. _editable installs: repository.html#editable-installs\n\n\nMailing Lists\n=============\n\nDevelopers are recommended to subscribe to all `Docutils mailing\nlists`_.\n\n.. _Docutils mailing lists: ../user/mailing-lists.html\n\n\nThe Wiki\n========\n\nThere is a development wiki at http://docutils.python-hosting.com/ as\na scratchpad for transient notes.  Please use the repository for\npermanent document storage.\n\nExtensions and Related Projects\n===============================\n\nThe Sandbox\n-----------\n\nThe `sandbox directory`_ is a place to play around, to try out and\nshare ideas.  It's a part of the Subversion repository but it isn't\ndistributed as part of Docutils releases.  Feel free to check in code\nto the sandbox; that way people can try it out but you won't have to\nworry about it working 100% error-free, as is the goal of the Docutils\ncore.  A project-specific subdirectory should be created for each new\nproject.  Any developer who wants to play in the sandbox may do so,\nbut project directories are recommended over personal directories,\nwhich discourage collaboration.  It's OK to make a mess in the\nsandbox!  But please, play nice.\n\nPlease update the `sandbox README`_ file with links and a brief\ndescription of your work.\n\nIn order to minimize the work necessary for others to install and try\nout new, experimental components, the following sandbox directory\nstructure is recommended::\n\n    sandbox/\n        project_name/ # For a collaborative project.\n            README.txt  # Describe the requirements, purpose/goals, usage,\n                        # and list the maintainers.\n            docs/\n                ...\n            component.py    # The component is a single module.\n                            # *OR* (but *not* both)\n            component/      # The component is a package.\n                __init__.py  # Contains the Reader/Writer class.\n                other1.py    # Other modules and data files used\n                data.txt     # by this component.\n                ...\n            test/       # Test suite.\n                ...\n            tools/      # For front ends etc.\n                ...\n            setup.py    # Install the component code and tools/ files\n                        # into the right places.\n        userid/       # For *temporary* personal space.\n\nSome sandbox projects are destined to move to the Docutils core once\ncompleted.  Others, such as add-ons to Docutils or applications of\nDocutils, may graduate to become `parallel projects`_.\n\n.. _sandbox README: https://docutils.sourceforge.io/sandbox/README.html\n.. _sandbox directory:\n   https://sourceforge.net/p/docutils/code/HEAD/tree/trunk/sandbox/\n\n\n.. _parallel project:\n\nParallel Projects\n-----------------\n\nParallel projects contain useful code that is not central to the\nfunctioning of Docutils.  Examples are specialized add-ons or\nplug-ins, and applications of Docutils.  They use Docutils, but\nDocutils does not require their presence to function.\n\nAn official parallel project will have its own directory beside (or\nparallel to) the main ``docutils`` directory in the Subversion\nrepository.  It can have its own web page in the\ndocutils.sourceforge.io domain, its own file releases and\ndownloadable snapshots, and even a mailing list if that proves useful.\nHowever, an official parallel project has implications: it is expected\nto be maintained and continue to work with changes to the core\nDocutils.\n\nA parallel project requires a project leader, who must commit to\ncoordinate and maintain the implementation:\n\n* Answer questions from users and developers.\n* Review suggestions, bug reports, and patches.\n* Monitor changes and ensure the quality of the code and\n  documentation.\n* Coordinate with Docutils to ensure interoperability.\n* Put together official project releases.\n\nOf course, related projects may be created independently of Docutils.\nThe advantage of a parallel project is that the SourceForge\nenvironment and the developer and user communities are already\nestablished.  Core Docutils developers are available for consultation\nand may contribute to the parallel project.  It's easier to keep the\nprojects in sync when there are changes made to the core Docutils\ncode.\n\nOther related projects\n----------------------\n\nMany related but independent projects are listed in the Docutils\n`link list`_. If you want your project to appear there, drop a note at\nthe Docutils-develop_ mailing list.\n\n.. _link list: https://docutils.sourceforge.io/docs/user/links.html\n.. _docutils-develop: docs/user/mailing-lists.html#docutils-develop\n\n\f\n..\n   Local Variables:\n   mode: indented-text\n   indent-tabs-mode: nil\n   sentence-end-double-space: t\n   fill-column: 70\n   End:\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/docutils_data/docs/dev/pysource.txt",
    "content": "======================\n Python Source Reader\n======================\n:Author: David Goodger\n:Contact: docutils-develop@lists.sourceforge.net\n:Revision: $Revision$\n:Date: $Date$\n:Copyright: This document has been placed in the public domain.\n\nThis document explores issues around extracting and processing\ndocstrings from Python modules.\n\nFor definitive element hierarchy details, see the \"Python Plaintext\nDocument Interface DTD\" XML document type definition, pysource.dtd_\n(which modifies the generic docutils.dtd_).  Descriptions below list\n'DTD elements' (XML 'generic identifiers' or tag names) corresponding\nto syntax constructs.\n\n\n.. contents::\n\n\nModel\n=====\n\nThe Python Source Reader (\"PySource\") model that's evolving in my mind\ngoes something like this:\n\n1. Extract the docstring/namespace [#]_ tree from the module(s) and/or\n   package(s).\n\n   .. [#] See `Docstring Extractor`_ below.\n\n2. Run the parser on each docstring in turn, producing a forest of\n   doctrees (per nodes.py).\n\n3. Join the docstring trees together into a single tree, running\n   transforms:\n\n   - merge hyperlinks\n   - merge namespaces\n   - create various sections like \"Module Attributes\", \"Functions\",\n     \"Classes\", \"Class Attributes\", etc.; see pysource.dtd_\n   - convert the above special sections to ordinary doctree nodes\n\n4. Run transforms on the combined doctree.  Examples: resolving\n   cross-references/hyperlinks (including interpreted text on Python\n   identifiers); footnote auto-numbering; first field list ->\n   bibliographic elements.\n\n   (Or should step 4's transforms come before step 3?)\n\n5. Pass the resulting unified tree to the writer/builder.\n\nI've had trouble reconciling the roles of input parser and output\nwriter with the idea of modes (\"readers\" or \"directors\").  Does the\nmode govern the transformation of the input, the output, or both?\nPerhaps the mode should be split into two.\n\nFor example, say the source of our input is a Python module.  Our\n\"input mode\" should be the \"Python Source Reader\".  It discovers (from\n``__docformat__``) that the input parser is \"reStructuredText\".  If we\nwant HTML, we'll specify the \"HTML\" output formatter.  But there's a\npiece missing.  What *kind* or *style* of HTML output do we want?\nPyDoc-style, LibRefMan style, etc.  (many people will want to specify\nand control their own style).  Is the output style specific to a\nparticular output format (XML, HTML, etc.)?  Is the style specific to\nthe input mode?  Or can/should they be independent?\n\nI envision interaction between the input parser, an \"input mode\" , and\nthe output formatter.  The same intermediate data format would be used\nbetween each of these, being transformed as it progresses.\n\n\nDocstring Extractor\n===================\n\nWe need code that scans a parsed Python module, and returns an ordered\ntree containing the names, docstrings (including attribute and\nadditional docstrings), and additional info (in parentheses below) of\nall of the following objects:\n\n- packages\n- modules\n- module attributes (+ values)\n- classes (+ inheritance)\n- class attributes (+ values)\n- instance attributes (+ values)\n- methods (+ formal parameters & defaults)\n- functions (+ formal parameters & defaults)\n\n(Extract comments too?  For example, comments at the start of a module\nwould be a good place for bibliographic field lists.)\n\nIn order to evaluate interpreted text cross-references, namespaces for\neach of the above will also be required.\n\nSee python-dev/docstring-develop thread \"AST mining\", started on\n2001-08-14.\n\n\nInterpreted Text\n================\n\nDTD elements: package, module, class, method, function,\nmodule_attribute, class_attribute, instance_attribute, variable,\nparameter, type, exception_class, warning_class.\n\nTo classify identifiers explicitly, the role is given along with the\nidentifier in either prefix or suffix form::\n\n    Use :method:`Keeper.storedata` to store the object's data in\n    `Keeper.data`:instance_attribute:.\n\nThe role may be one of 'package', 'module', 'class', 'method',\n'function', 'module_attribute', 'class_attribute',\n'instance_attribute', 'variable', 'parameter', 'type',\n'exception_class', 'exception', 'warning_class', or 'warning'.  Other\nroles may be defined.\n\n.. _pysource.dtd: pysource.dtd\n.. _docutils.dtd: ../ref/docutils.dtd\n\n\n\f\n..\n   Local Variables:\n   mode: indented-text\n   indent-tabs-mode: nil\n   fill-column: 70\n   End:\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/docutils_data/docs/dev/release.txt",
    "content": "=============================\n Docutils_ Release Procedure\n=============================\n\n:Authors: David Goodger; Lea Wiemann; open to all Docutils developers\n:Contact: docutils-develop@lists.sourceforge.net\n:Date: $Date$\n:Revision: $Revision$\n:Copyright: This document has been placed in the public domain.\n\n.. _Docutils: https://docutils.sourceforge.io/\n\nReleasing (post 2020)\n---------------------\n\n* Announce the upcoming release on docutils-develop list.\n\n  Consider **feature freeze** or/and **check-in freeze** .\n\n* Update RELEASE-NOTES.txt add section ``Release <version>``.\n\n  Consult HISTORY.txt for important changes.\n\n* Change HISTORY.txt title ``Changes Since <previous release>`` to ``Release <version>``.\n\n* Set new version with ``sandbox/infrastructure/set_version.sh <version>``\n\n  Check what was changed with version control system by ``set_version.sh``\n\n  Run tests ::\n\n    export PYTHONWARNINGS=default\n    python3 test/alltests.py\n\n  or use tox.\n    \n  ``export PYTHONWARNINGS=default`` prints DeprecationWarnings in python3.\n\n* Generate universal wheel and source-distribution::\n\n    python3 setup.py sdist\n    python3 setup.py bdist_wheel --universal\n\n* Upload universal wheel and source to test.pypi::\n\n    python3 -m twine upload --repository-url https://test.pypi.org/legacy/ dist/*\n\n  Test in venv ::\n\n    python3 -m venv du3 ; cd du3\n    export PYTHONPATH= ; . bin/activate\n\n    python -m pip install --index-url https://test.pypi.org/simple/ --no-deps docutils\n\n    cp -Lr ../docutils-code/docutils/test .\n    python test/alltests.py\n\n    python -m pip uninstall docutils\n    deactivate ; cd .. ; rm -r du3\n\n* Commit changes ... the changed version number.\n\n* tag 0.## (Note: only directory docutils is copied)::\n\n    svn copy svn+ssh://grubert@svn.code.sf.net/p/docutils/code/trunk/docutils \\\n             svn+ssh://grubert@svn.code.sf.net/p/docutils/code/tags/docutils-0.## \\\n             -m \"tagging release 0.##\"\n\n* Update your source directory. \n* Rebuild universal wheel and source-distribution ::\n\n    python3 setup.py sdist\n    python3 setup.py bdist_wheel --universal\n\n* Now upload to pypi::\n\n    python3 -m twine upload  dist/docutils-0.##*\n\n* Remove previous package from local cache::\n\n    find .cache/pip/wheels -name docutils\\*whl -exec rm -v -i {} \\;\n\n* and test::\n\n    python3 -m venv du3 ; cd du3\n    export PYTHONPATH= ; . bin/activate\n\n    pip install --no-deps docutils\n    cp -Lr ../docutils-code/docutils/test .\n    python test/alltests.py\n\n    deactivate ; cd .. ; rm -r du3\n\n* Notify to docutils-developer and user.\n\n* upload source and generated html to sf-htdocs/0.## ::\n\n    mkdir tmp1\n    cd tmp1\n    tar xzvf ../dist/docutils-0.##.tar.gz\n    cd docutils-0.##/\n    tools/buildhtml.py .\n    find . -name \\*.pyc -exec rm -v {} \\;\n    find . -name __pycache__ -exec rmdir -v {} \\;\n    rm -r docutils.egg-info\n    rsync -e ssh -r -t ./ web.sourceforge.net:/home/project-web/docutils/htdocs/0.##\n\n* Check web/index.txt for necessary corrections.\n* Run sandbox/infrastructure/docutils-update.local to update web-content.\n* Release to sourceforge.\n\n  - Upload tar.gz and 0.16 release notes to sourceforge.\n  - Select docutils-0.16.tar.gz as default for all OS.  \n\n* set_version 0.#.#+1b.dev\n* test with py3\n* docutils/HISTORY.txt: add title \"Changes Since 0.##\"\n* run sandbox/infrastructure/docutils-update.local\n\n\f\n..\n   Local Variables:\n   mode: indented-text\n   indent-tabs-mode: nil\n   sentence-end-double-space: t\n   fill-column: 70\n   End:\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/docutils_data/docs/dev/repository.txt",
    "content": "=====================================\n The Docutils_ Version Repository\n=====================================\n\n:Author: Lea Wiemann, Docutils developers\n:Contact: docutils-develop@lists.sourceforge.net\n:Revision: $Revision$\n:Date: $Date$\n:Copyright: This document has been placed in the public domain.\n\n.. _Docutils: https://docutils.sourceforge.io/\n\n.. admonition:: Quick Instructions\n\n   To get a checkout of the Docutils source tree (with the\n   sandboxes) with SVN_, type ::\n\n       svn checkout https://svn.code.sf.net/p/docutils/code/trunk docutils-code\n\n   Users of Git_ can clone a mirror of the docutils repository with ::\n\n      git clone git://repo.or.cz/docutils.git\n\n   If you are going to commit changes to the repository, please read\n   the **whole document**, especially the section \"`Information for\n   Developers`_\"!\n\nDocutils uses a Subversion_ (SVN) repository located at\n``docutils.svn.sourceforge.net``.\n\nWhile Unix and Mac OS X users will probably prefer the standard\nSubversion command line interface, Windows user may want to try\nTortoiseSVN_, a convenient explorer extension.  The instructions apply\nanalogously.\n\nThere is a Git_ mirror at http://repo.or.cz/docutils.git providing\n`web access`_ and the base for `creating a local Git clone`_.\n[#github-mirrors]_\n\nFor the project policy on repository use (check-in requirements,\nbranching, etc.), please see the `Docutils Project Policies`__.\n\n__ policies.html#subversion-repository\n\n.. _SVN:\n.. _Subversion: https://subversion.apache.org/\n.. _TortoiseSVN: https://tortoisesvn.net/\n.. _SourceForge.net: https://sourceforge.net/\n.. _Git: http://git-scm.com/\n\n.. contents::\n\n\nAccessing the Repository\n========================\n\nWeb Access\n----------\n\nThe repository can be browsed and examined via the web at\nhttps://sourceforge.net/p/docutils/code.\n\nAlternatively, use the web interface at http://repo.or.cz/docutils.git.\n[#github-mirrors]_\n\n.. [#github-mirrors] There are also 3rd-party mirrors and forks at\n   GitHub, some of them orphaned. At the time of this writing (2021-11-03),\n   https://github.com/live-clones/docutils/tree/master/docutils\n   provides an hourly updated clone.\n\nRepository Access Methods\n-------------------------\n\nTo get a checkout, first determine the root of the repository depending\non your preferred protocol:\n\nanonymous access: (read only)\n    Subversion_: ``https://svn.code.sf.net/p/docutils/code``\n\n    Git_: ``git://repo.or.cz/docutils.git``\n\n`developer access`_: (read and write)\n    ``svn+ssh://<USERNAME>@svn.code.sf.net/p/docutils/code``\n\nChecking Out the Repository\n---------------------------\n\n.. _creating a local Git clone:\n\nGit_ users can clone a mirror of the docutils repository with ::\n\n      git clone git://repo.or.cz/docutils.git\n\nand proceed according to the `Git documentation`_.\nDeveloper access (read and write) is possible with `git svn`_.\n\n.. _Git documentation: https://git.wiki.kernel.org/index.php/GitDocumentation\n.. _git svn: https://git.wiki.kernel.org/index.php/Git-svn\n\nSubversion_ users can use the following commands\n(substitute your preferred repository root for ROOT):\n\n* To check out only the current main source tree of Docutils, type ::\n\n    svn checkout ROOT/trunk/docutils\n\n* To check out everything (main tree, sandboxes, web site, and parallel\n  projects), type ::\n\n    svn checkout ROOT/trunk docutils\n\n  This will create a working copy of the whole trunk in a new directory\n  called ``docutils``.\n\nNote that you probably do *not* want to check out the ROOT itself\n(without \"/trunk\"), because then you'd end up fetching the whole\nDocutils tree for every branch and tag over and over again.\n\nTo update your working copy later on, ``cd`` into the working copy and\ntype ::\n\n    svn update\n\nSwitching the Repository Root\n-----------------------------\n\nIf you changed your mind and want to use a different repository root,\n``cd`` into your working copy and type::\n\n    svn switch --relocate OLDROOT NEWROOT\n\n\nEditable installs\n=================\n\nThere are several ways to ensure that edits to the Docutils code are\npicked up by Python.\nWe'll assume that the Docutils \"trunk\" is checked out under the\n``~/projects/`` directory.\n\n1. Do an `editable install`__ with pip_::\n\n     python3 -m pip install -e ~/projects/docutils/docutils\n\n   __ https://pip.pypa.io/en/stable/cli/pip_install/#editable-installs\n\n2. Install in `development mode`__ with setuptools_.\n\n   __ https://setuptools.pypa.io/en/latest/userguide/development_mode.html\n      #development-mode\n\n   .. _install manually:\n\n3. Install \"manually\".\n\n   Ensure that the \"docutils\" package is in ``sys.path`` by\n   one of the following actions:\n\n   * Set the ``PYTHONPATH`` environment variable so that Python\n     picks up your local working copy of the code.\n\n     For the bash shell, add this to your ``~/.profile``::\n\n         PYTHONPATH=$HOME/projects/docutils/docutils\n         export PYTHONPATH\n\n     The first line points to the directory containing the ``docutils``\n     package.  The second line exports the environment variable.\n\n   * Create a symlink to the docutils package directory somewhere in the\n     module search path (``sys.path``), e.g., ::\n\n         ln -s ~/projects/docutils/docutils \\\n               /usr/local/lib/python3.9/dist-packages/\n\n   * Use a `path configuration file`__.\n\n     __ https://docs.python.org/library/site.html\n\n   Optionally, add some or all `front-end tools`_\n   to the binary search path, e.g.,\n   add the ``tools`` directory to the ``PATH`` variable::\n\n         PATH=$PATH:$HOME/projects/docutils/docutils/tools\n         export PATH\n\n   or link idividual front-end tools to a suitable place\n   in the binary path::\n\n         ln -s ~/projects/docutils/docutils/tools/docutils-cli.py \\\n               /usr/local/bin/docutils\n\n5. Reinstall Docutils after any change::\n\n       python3 setup.py install\n\n   .. CAUTION::\n\n      This method is **not** recommended for day-to-day development;\n      it's too easy to forget.  Confusion inevitably ensues.\n\n      If you install Docutils this way, Python will always pick up the\n      last-installed copy of the code.  If you ever forget to\n      reinstall the \"docutils\" package, Python won't see your latest\n      changes.\n\nA useful addition to the ``docutils`` top-level directory in branches\nand alternate copies of the code is a ``set-PATHS`` file\ncontaining the following lines::\n\n    # source this file\n    export PYTHONPATH=$PWD:$PWD\n    export PATH=$PWD/tools:$PATH\n\nOpen a shell for this branch, ``cd`` to the ``docutils`` top-level\ndirectory, and \"source\" this file.  For example, using the bash\nshell::\n\n    $ cd some-branch/docutils\n    $ . set-PATHS\n\n.. _pip: https://pypi.org/project/pip/\n.. _setuptools: https://pypi.org/project/setuptools/\n.. _front-end tools: ../user/tools.html\n\n\n.. _developer access:\n\nInformation for Developers\n==========================\n\nIf you would like to have write access to the repository, register\nwith SourceForge.net_ and send your SourceForge.net\nuser names to docutils-develop@lists.sourceforge.net.\n(Note that there may be a delay of several hours until you can commit\nchanges to the repository.)\n\nSourceforge SVN access is documented `here`__\n\n__ https://sourceforge.net/p/forge/documentation/svn/\n\n\nEnsure any changes comply with the `Docutils Project Policies`_\nbefore `checking in`_,\n\n.. _Docutils Project Policies: policies.html\n.. _checking in: policies.html#check-ins\n\n\nSetting Up Your Subversion Client For Development\n-------------------------------------------------\n\nBefore committing changes to the repository, please ensure that the\nfollowing lines are contained (and uncommented) in your local\n~/.subversion/config file, so that new files are added with the\ncorrect properties set::\n\n    [miscellany]\n    # For your convenience:\n    global-ignores = ... *.pyc ...\n    # For correct properties:\n    enable-auto-props = yes\n\n    [auto-props]\n    *.py = svn:eol-style=native;svn:keywords=Author Date Id Revision\n    *.txt = svn:eol-style=native;svn:keywords=Author Date Id Revision\n    *.html = svn:eol-style=native;svn:keywords=Author Date Id Revision\n    *.xml = svn:eol-style=native;svn:keywords=Author Date Id Revision\n    *.tex = svn:eol-style=native;svn:keywords=Author Date Id Revision\n    *.css = svn:eol-style=native;svn:keywords=Author Date Id Revision\n    *.patch = svn:eol-style=native\n    *.sh = svn:eol-style=native;svn:executable;svn:keywords=Author Date Id Revision\n    *.png = svn:mime-type=image/png\n    *.jpg = svn:mime-type=image/jpeg\n    *.gif = svn:mime-type=image/gif\n\n\nRepository Layout\n=================\n\nThe following tree shows the repository layout::\n\n    docutils/\n    |-- branches/\n    |   |-- branch1/\n    |   |   |-- docutils/\n    |   |   |-- sandbox/\n    |   |   `-- web/\n    |   `-- branch2/\n    |       |-- docutils/\n    |       |-- sandbox/\n    |       `-- web/\n    |-- tags/\n    |   |-- tag1/\n    |   |   |-- docutils/\n    |   |   |-- sandbox/\n    |   |   `-- web/\n    |   `-- tag2/\n    |       |-- docutils/\n    |       |-- sandbox/\n    |       `-- web/\n    `-- trunk/\n        |-- docutils/\n        |-- sandbox/\n        `-- web/\n\nThe main source tree lives at ``docutils/trunk/docutils/``, next to\nthe sandboxes (``docutils/trunk/sandbox/``) and the web site files\n(``docutils/trunk/web/``).\n\n``docutils/branches/`` and ``docutils/tags/`` contain (shallow) copies\nof either the whole trunk or only the main source tree\n(``docutils/trunk/docutils``).\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/docutils_data/docs/dev/rst/alternatives.txt",
    "content": "==================================================\n A Record of reStructuredText Syntax Alternatives\n==================================================\n\n:Author: David Goodger\n:Contact: docutils-develop@lists.sourceforge.net\n:Revision: $Revision$\n:Date: $Date$\n:Copyright: This document has been placed in the public domain.\n\nThe following are ideas, alternatives, and justifications that were\nconsidered for reStructuredText syntax, which did not originate with\nSetext_ or StructuredText_.  For an analysis of constructs which *did*\noriginate with StructuredText or Setext, please see `Problems With\nStructuredText`_.  See the `reStructuredText Markup Specification`_\nfor full details of the established syntax.\n\nThe ideas are divided into sections:\n\n* Implemented_: already done.  The issues and alternatives are\n  recorded here for posterity.\n\n* `Not Implemented`_: these ideas won't be implemented.\n\n* Tabled_: these ideas should be revisited in the future.\n\n* `To Do`_: these ideas should be implemented.  They're just waiting\n  for a champion to resolve issues and get them done.\n\n* `... Or Not To Do?`_: possible but questionable.  These probably\n  won't be implemented, but you never know.\n\n.. _Setext: https://docutils.sourceforge.io/mirror/setext.html\n.. _StructuredText: https://zopestructuredtext.readthedocs.org/\n.. _Problems with StructuredText: problems.html\n.. _reStructuredText Markup Specification:\n   ../../ref/rst/restructuredtext.html\n\n\n.. contents::\n\n-------------\n Implemented\n-------------\n\nField Lists\n===========\n\nPrior to the syntax for field lists being finalized, several\nalternatives were proposed.\n\n1. Unadorned RFC822_ everywhere::\n\n       Author: Me\n       Version: 1\n\n   Advantages: clean, precedent (RFC822-compliant).  Disadvantage:\n   ambiguous (these paragraphs are a prime example).\n\n   Conclusion: rejected.\n\n2. Special case: use unadorned RFC822_ for the very first or very last\n   text block of a document::\n\n       \"\"\"\n       Author: Me\n       Version: 1\n\n       The rest of the document...\n       \"\"\"\n\n   Advantages: clean, precedent (RFC822-compliant).  Disadvantages:\n   special case, flat (unnested) field lists only, still ambiguous::\n\n       \"\"\"\n       Usage: cmdname [options] arg1 arg2 ...\n\n       We obviously *don't* want the like above to be interpreted as a\n       field list item.  Or do we?\n       \"\"\"\n\n   Conclusion: rejected for the general case, accepted for specific\n   contexts (PEPs, email).\n\n3. Use a directive::\n\n       .. fields::\n\n          Author: Me\n          Version: 1\n\n   Advantages: explicit and unambiguous, RFC822-compliant.\n   Disadvantage: cumbersome.\n\n   Conclusion: rejected for the general case (but such a directive\n   could certainly be written).\n\n4. Use Javadoc-style::\n\n       @Author: Me\n       @Version: 1\n       @param a: integer\n\n   Advantages: unambiguous, precedent, flexible.  Disadvantages:\n   non-intuitive, ugly, not RFC822-compliant.\n\n   Conclusion: rejected.\n\n5. Use leading colons::\n\n       :Author: Me\n       :Version: 1\n\n   Advantages: unambiguous, obvious (*almost* RFC822-compliant),\n   flexible, perhaps even elegant.  Disadvantages: no precedent, not\n   quite RFC822-compliant.\n\n   Conclusion: accepted!\n\n6. Use double colons::\n\n       Author:: Me\n       Version:: 1\n\n   Advantages: unambiguous, obvious? (*almost* RFC822-compliant),\n   flexible, similar to syntax already used for literal blocks and\n   directives.  Disadvantages: no precedent, not quite\n   RFC822-compliant, similar to syntax already used for literal blocks\n   and directives.\n\n   Conclusion: rejected because of the syntax similarity & conflicts.\n\nWhy is RFC822 compliance important?  It's a universal Internet\nstandard, and super obvious.  Also, I'd like to support the PEP format\n(ulterior motive: get PEPs to use reStructuredText as their standard).\nBut it *would* be easy to get used to an alternative (easy even to\nconvert PEPs; probably harder to convert python-deviants ;-).\n\nUnfortunately, without well-defined context (such as in email headers:\nRFC822 only applies before any blank lines), the RFC822 format is\nambiguous.  It is very common in ordinary text.  To implement field\nlists unambiguously, we need explicit syntax.\n\nThe following question was posed in a footnote:\n\n   Should \"bibliographic field lists\" be defined at the parser level,\n   or at the DPS transformation level?  In other words, are they\n   reStructuredText-specific, or would they also be applicable to\n   another (many/every other?) syntax?\n\nThe answer is that bibliographic fields are a\nreStructuredText-specific markup convention.  Other syntaxes may\nimplement the bibliographic elements explicitly.  For example, there\nwould be no need for such a transformation for an XML-based markup\nsyntax.\n\n.. _RFC822: https://www.rfc-editor.org/rfc/rfc822.txt\n\n\nInterpreted Text \"Roles\"\n========================\n\nThe original purpose of interpreted text was as a mechanism for\ndescriptive markup, to describe the nature or role of a word or\nphrase.  For example, in XML we could say \"<function>len</function>\"\nto mark up \"len\" as a function.  It is envisaged that within Python\ndocstrings (inline documentation in Python module source files, the\nprimary market for reStructuredText) the role of a piece of\ninterpreted text can be inferred implicitly from the context of the\ndocstring within the program source.  For other applications, however,\nthe role may have to be indicated explicitly.\n\nInterpreted text is enclosed in single backquotes (`).\n\n1. Initially, it was proposed that an explicit role could be indicated\n   as a word or phrase within the enclosing backquotes:\n\n   - As a prefix, separated by a colon and whitespace::\n\n         `role: interpreted text`\n\n   - As a suffix, separated by whitespace and a colon::\n\n         `interpreted text :role`\n\n   There are problems with the initial approach:\n\n   - There could be ambiguity with interpreted text containing colons.\n     For example, an index entry of \"Mission: Impossible\" would\n     require a backslash-escaped colon.\n\n   - The explicit role is descriptive markup, not content, and will\n     not be visible in the processed output.  Putting it inside the\n     backquotes doesn't feel right; the *role* isn't being quoted.\n\n2. Tony Ibbs suggested that the role be placed outside the\n   backquotes::\n\n       role:`prefix` or `suffix`:role\n\n   This removes the embedded-colons ambiguity, but limits the role\n   identifier to be a single word (whitespace would be illegal).\n   Since roles are not meant to be visible after processing, the lack\n   of whitespace support is not important.\n\n   The suggested syntax remains ambiguous with respect to ratios and\n   some writing styles.  For example, suppose there is a \"signal\"\n   identifier, and we write::\n\n       ...calculate the `signal`:noise ratio.\n\n   \"noise\" looks like a role.\n\n3. As an improvement on #2, we can bracket the role with colons::\n\n       :role:`prefix` or `suffix`:role:\n\n   This syntax is similar to that of field lists, which is fine since\n   both are doing similar things: describing.\n\n   This is the syntax chosen for reStructuredText.\n\n4. Another alternative is two colons instead of one::\n\n       role::`prefix` or `suffix`::role\n\n   But this is used for analogies (\"A:B::C:D\": \"A is to B as C is to\n   D\").\n\n   Both alternative #2 and #4 lack delimiters on both sides of the\n   role, making it difficult to parse (by the reader).\n\n5. Some kind of bracketing could be used:\n\n   - Parentheses::\n\n         (role)`prefix` or `suffix`(role)\n\n   - Braces::\n\n         {role}`prefix` or `suffix`{role}\n\n   - Square brackets::\n\n         [role]`prefix` or `suffix`[role]\n\n   - Angle brackets::\n\n         <role>`prefix` or `suffix`<role>\n\n     (The overlap of \\*ML tags with angle brackets would be too\n     confusing and precludes their use.)\n\nSyntax #3 was chosen for reStructuredText.\n\n\nComments\n========\n\nA problem with comments (actually, with all indented constructs) is\nthat they cannot be followed by an indented block -- a block quote --\nwithout swallowing it up.\n\nI thought that perhaps comments should be one-liners only.  But would\nthis mean that footnotes, hyperlink targets, and directives must then\nalso be one-liners?  Not a good solution.\n\nTony Ibbs suggested a \"comment\" directive.  I added that we could\nlimit a comment to a single text block, and that a \"multi-block\ncomment\" could use \"comment-start\" and \"comment-end\" directives.  This\nwould remove the indentation incompatibility.  A \"comment\" directive\nautomatically suggests \"footnote\" and (hyperlink) \"target\" directives\nas well.  This could go on forever!  Bad choice.\n\nGarth Kidd suggested that an \"empty comment\", a \"..\" explicit markup\nstart with nothing on the first line (except possibly whitespace) and\na blank line immediately following, could serve as an \"unindent\".  An\nempty comment does **not** swallow up indented blocks following it,\nso block quotes are safe.  \"A tiny but practical wart.\"  Accepted.\n\n\nAnonymous Hyperlinks\n====================\n\nAlan Jaffray came up with this idea, along with the following syntax::\n\n    Search the `Python DOC-SIG mailing list archives`{}_.\n\n    .. _: https://mail.python.org/pipermail/doc-sig/\n\nThe idea is sound and useful.  I suggested a \"double underscore\"\nsyntax::\n\n    Search the `Python DOC-SIG mailing list archives`__.\n\n    .. __: https://mail.python.org/pipermail/doc-sig/\n\nBut perhaps single underscores are okay?  The syntax looks better, but\nthe hyperlink itself doesn't explicitly say \"anonymous\"::\n\n    Search the `Python DOC-SIG mailing list archives`_.\n\n    .. _: https://mail.python.org/pipermail/doc-sig/\n\nMixing anonymous and named hyperlinks becomes confusing.  The order of\ntargets is not significant for named hyperlinks, but it is for\nanonymous hyperlinks::\n\n    Hyperlinks: anonymous_, named_, and another anonymous_.\n\n    .. _named: named\n    .. _: anonymous1\n    .. _: anonymous2\n\nWithout the extra syntax of double underscores, determining which\nhyperlink references are anonymous may be difficult.  We'd have to\ncheck which references don't have corresponding targets, and match\nthose up with anonymous targets.  Keeping to a simple consistent\nordering (as with auto-numbered footnotes) seems simplest.\n\nreStructuredText will use the explicit double-underscore syntax for\nanonymous hyperlinks.  An alternative (see `Reworking Explicit Markup\n(Round 1)`_ below) for the somewhat awkward \".. __:\" syntax is \"__\"::\n\n    An anonymous__ reference.\n\n    __ http://anonymous\n\n\nReworking Explicit Markup (Round 1)\n===================================\n\nAlan Jaffray came up with the idea of `anonymous hyperlinks`_, added\nto reStructuredText.  Subsequently it was asserted that hyperlinks\n(especially anonymous hyperlinks) would play an increasingly important\nrole in reStructuredText documents, and therefore they require a\nsimpler and more concise syntax.  This prompted a review of the\ncurrent and proposed explicit markup syntaxes with regards to\nimproving usability.\n\n1. Original syntax::\n\n       .. _blah:                     internal hyperlink target\n       .. _blah: http://somewhere    external hyperlink target\n       .. _blah: blahblah_           indirect hyperlink target\n       .. __:                        anonymous internal target\n       .. __: http://somewhere       anonymous external target\n       .. __: blahblah_              anonymous indirect target\n       .. [blah] http://somewhere    footnote\n       .. blah:: http://somewhere    directive\n       .. blah: http://somewhere     comment\n\n   .. Note::\n\n      The comment text was intentionally made to look like a hyperlink\n      target.\n\n   Origins:\n\n   * Except for the colon (a delimiter necessary to allow for\n     phrase-links), hyperlink target ``.. _blah:`` comes from Setext.\n   * Comment syntax from Setext.\n   * Footnote syntax from StructuredText (\"named links\").\n   * Directives and anonymous hyperlinks original to reStructuredText.\n\n   Advantages:\n\n   + Consistent explicit markup indicator: \"..\".\n   + Consistent hyperlink syntax: \".. _\" & \":\".\n\n   Disadvantages:\n\n   - Anonymous target markup is awkward: \".. __:\".\n   - The explicit markup indicator (\"..\") is excessively overloaded?\n   - Comment text is limited (can't look like a footnote, hyperlink,\n     or directive).  But this is probably not important.\n\n2. Alan Jaffray's proposed syntax #1::\n\n       __ _blah                      internal hyperlink target\n       __ blah: http://somewhere     external hyperlink target\n       __ blah: blahblah_            indirect hyperlink target\n       __                            anonymous internal target\n       __ http://somewhere           anonymous external target\n       __ blahblah_                  anonymous indirect target\n       __ [blah] http://somewhere    footnote\n       .. blah:: http://somewhere    directive\n       .. blah: http://somewhere     comment\n\n   The hyperlink-connoted underscores have become first-level syntax.\n\n   Advantages:\n\n   + Anonymous targets are simpler.\n   + All hyperlink targets are one character shorter.\n\n   Disadvantages:\n\n   - Inconsistent internal hyperlink targets.  Unlike all other named\n     hyperlink targets, there's no colon.  There's an extra leading\n     underscore, but we can't drop it because without it, \"blah\" looks\n     like a relative URI.  Unless we restore the colon::\n\n         __ blah:                      internal hyperlink target\n\n   - Obtrusive markup?\n\n3. Alan Jaffray's proposed syntax #2::\n\n       .. _blah                      internal hyperlink target\n       .. blah: http://somewhere     external hyperlink target\n       .. blah: blahblah_            indirect hyperlink target\n       ..                            anonymous internal target\n       .. http://somewhere           anonymous external target\n       .. blahblah_                  anonymous indirect target\n       .. [blah] http://somewhere    footnote\n       !! blah: http://somewhere     directive\n       ## blah: http://somewhere     comment\n\n   Leading underscores have been (almost) replaced by \"..\", while\n   comments and directives have gained their own syntax.\n\n   Advantages:\n\n   + Anonymous hyperlinks are simpler.\n   + Unique syntax for comments.  Connotation of \"comment\" from\n     some programming languages (including our favorite).\n   + Unique syntax for directives.  Connotation of \"action!\".\n\n   Disadvantages:\n\n   - Inconsistent internal hyperlink targets.  Again, unlike all other\n     named hyperlink targets, there's no colon.  There's a leading\n     underscore, matching the trailing underscores of references,\n     which no other hyperlink targets have.  We can't drop that one\n     leading underscore though: without it, \"blah\" looks like a\n     relative URI.  Again, unless we restore the colon::\n\n         .. blah:                      internal hyperlink target\n\n   - All (except for internal) hyperlink targets lack their leading\n     underscores, losing the \"hyperlink\" connotation.\n\n   - Obtrusive syntax for comments.  Alternatives::\n\n         ;; blah: http://somewhere\n            (also comment syntax in Lisp & others)\n         ,, blah: http://somewhere\n            (\"comma comma\": sounds like \"comment\"!)\n\n   - Iffy syntax for directives.  Alternatives?\n\n4. Tony Ibbs' proposed syntax::\n\n       .. _blah:                     internal hyperlink target\n       .. _blah: http://somewhere    external hyperlink target\n       .. _blah: blahblah_           indirect hyperlink target\n       ..                            anonymous internal target\n       .. http://somewhere           anonymous external target\n       .. blahblah_                  anonymous indirect target\n       .. [blah] http://somewhere    footnote\n       .. blah:: http://somewhere    directive\n       .. blah: http://somewhere     comment\n\n   This is the same as the current syntax, except for anonymous\n   targets which drop their \"__: \".\n\n   Advantage:\n\n   + Anonymous targets are simpler.\n\n   Disadvantages:\n\n   - Anonymous targets lack their leading underscores, losing the\n     \"hyperlink\" connotation.\n   - Anonymous targets are almost indistinguishable from comments.\n     (Better to know \"up front\".)\n\n5. David Goodger's proposed syntax: Perhaps going back to one of\n   Alan's earlier suggestions might be the best solution.  How about\n   simply adding \"__ \" as a synonym for \".. __: \" in the original\n   syntax?  These would become equivalent::\n\n       .. __:                        anonymous internal target\n       .. __: http://somewhere       anonymous external target\n       .. __: blahblah_              anonymous indirect target\n\n       __                            anonymous internal target\n       __ http://somewhere           anonymous external target\n       __ blahblah_                  anonymous indirect target\n\nAlternative 5 has been adopted.\n\n\nBackquotes in Phrase-Links\n==========================\n\n[From a 2001-06-05 Doc-SIG post in reply to questions from Doug\nHellmann.]\n\nThe first draft of the spec, posted to the Doc-SIG in November 2000,\nused square brackets for phrase-links.  I changed my mind because:\n\n1. In the first draft, I had already decided on single-backquotes for\n   inline literal text.\n\n2. However, I wanted to minimize the necessity for backslash escapes,\n   for example when quoting Python repr-equivalent syntax that uses\n   backquotes.\n\n3. The processing of identifiers (function/method/attribute/module\n   etc. names) into hyperlinks is a useful feature.  PyDoc recognizes\n   identifiers heuristically, but it doesn't take much imagination to\n   come up with counter-examples where PyDoc's heuristics would result\n   in embarrassing failure.  I wanted to do it deterministically, and\n   that called for syntax.  I called this construct \"interpreted\n   text\".\n\n4. Leveraging off the ``*emphasis*/**strong**`` syntax, lead to the\n   idea of using double-backquotes as syntax.\n\n5. I worked out some rules for inline markup recognition.\n\n6. In combination with #5, double backquotes lent themselves to inline\n   literals, neatly satisfying #2, minimizing backslash escapes.  In\n   fact, the spec says that no interpretation of any kind is done\n   within double-backquote inline literal text; backslashes do *no*\n   escaping within literal text.\n\n7. Single backquotes are then freed up for interpreted text.\n\n8. I already had square brackets required for footnote references.\n\n9. Since interpreted text will typically turn into hyperlinks, it was\n   a natural fit to use backquotes as the phrase-quoting syntax for\n   trailing-underscore hyperlinks.\n\nThe original inspiration for the trailing underscore hyperlink syntax\nwas Setext.  But for phrases Setext used a very cumbersome\n``underscores_between_words_like_this_`` syntax.\n\nThe underscores can be viewed as if they were right-pointing arrows:\n``-->``.  So ``hyperlink_`` points away from the reference, and\n``.. _hyperlink:`` points toward the target.\n\n\nSubstitution Mechanism\n======================\n\nSubstitutions arose out of a Doc-SIG thread begun on 2001-10-28 by\nAlan Jaffray, \"reStructuredText inline markup\".  It reminded me of a\nmissing piece of the reStructuredText puzzle, first referred to in my\ncontribution to \"Documentation markup & processing / PEPs\" (Doc-SIG\n2001-06-21).\n\nSubstitutions allow the power and flexibility of directives to be\nshared by inline text.  They are a way to allow arbitrarily complex\ninline objects, while keeping the details out of the flow of text.\nThey are the equivalent of SGML/XML's named entities.  For example, an\ninline image (using reference syntax alternative 4d (vertical bars)\nand definition alternative 3, the alternatives chosen for inclusion in\nthe spec)::\n\n    The |biohazard| symbol must be used on containers used to dispose\n    of medical waste.\n\n    .. |biohazard| image:: biohazard.png\n       [height=20 width=20]\n\nThe ``|biohazard|`` substitution reference will be replaced in-line by\nwhatever the ``.. |biohazard|`` substitution definition generates (in\nthis case, an image).  A substitution definition contains the\nsubstitution text bracketed with vertical bars, followed by a an\nembedded inline-compatible directive, such as \"image\".  A transform is\nrequired to complete the substitution.\n\nSyntax alternatives for the reference:\n\n1. Use the existing interpreted text syntax, with a predefined role\n   such as \"sub\"::\n\n       The `biohazard`:sub: symbol...\n\n   Advantages: existing syntax, explicit.  Disadvantages: verbose,\n   obtrusive.\n\n2. Use a variant of the interpreted text syntax, with a new suffix\n   akin to the underscore in phrase-link references::\n\n       (a) `name`@\n       (b) `name`#\n       (c) `name`&\n       (d) `name`/\n       (e) `name`<\n       (f) `name`::\n       (g) `name`:\n\n\n   Due to incompatibility with other constructs and ordinary text\n   usage, (f) and (g) are not possible.\n\n3. Use interpreted text syntax with a fixed internal format::\n\n       (a) `:name:`\n       (b) `name:`\n       (c) `name::`\n       (d) `::name::`\n       (e) `%name%`\n       (f) `#name#`\n       (g) `/name/`\n       (h) `&name&`\n       (i) `|name|`\n       (j) `[name]`\n       (k) `<name>`\n       (l) `&name;`\n       (m) `'name'`\n\n   To avoid ML confusion (k) and (l) are definitely out.  Square\n   brackets (j) won't work in the target (the substitution definition\n   would be indistinguishable from a footnote).\n\n   The ```/name/``` syntax (g) is reminiscent of \"s/find/sub\"\n   substitution syntax in ed-like languages.  However, it may have a\n   misleading association with regexps, and looks like an absolute\n   POSIX path.  (i) is visually equivalent and lacking the\n   connotations.\n\n   A disadvantage of all of these is that they limit interpreted text,\n   albeit only slightly.\n\n4. Use specialized syntax, something new::\n\n       (a) #name#\n       (b) @name@\n       (c) /name/\n       (d) |name|\n       (e) <<name>>\n       (f) //name//\n       (g) ||name||\n       (h) ^name^\n       (i) [[name]]\n       (j) ~name~\n       (k) !name!\n       (l) =name=\n       (m) ?name?\n       (n) >name<\n\n   \"#\" (a) and \"@\" (b) are obtrusive.  \"/\" (c) without backquotes\n   looks just like a POSIX path; it is likely for such usage to appear\n   in text.\n\n   \"|\" (d) and \"^\" (h) are feasible.\n\n5. Redefine the trailing underscore syntax.  See definition syntax\n   alternative 4, below.\n\nSyntax alternatives for the definition:\n\n1. Use the existing directive syntax, with a predefined directive such\n   as \"sub\".  It contains a further embedded directive resolving to an\n   inline-compatible object::\n\n       .. sub:: biohazard\n          .. image:: biohazard.png\n             [height=20 width=20]\n\n       .. sub:: parrot\n          That bird wouldn't *voom* if you put 10,000,000 volts\n          through it!\n\n   The advantages and disadvantages are the same as in inline\n   alternative 1.\n\n2. Use syntax as in #1, but with an embedded directivecompressed::\n\n       .. sub:: biohazard image:: biohazard.png\n          [height=20 width=20]\n\n   This is a bit better than alternative 1, but still too much.\n\n3. Use a variant of directive syntax, incorporating the substitution\n   text, obviating the need for a special \"sub\" directive name.  If we\n   assume reference alternative 4d (vertical bars), the matching\n   definition would look like this::\n\n       .. |biohazard| image:: biohazard.png\n          [height=20 width=20]\n\n4. (Suggested by Alan Jaffray on Doc-SIG from 2001-11-06.)\n\n   Instead of adding new syntax, redefine the trailing underscore\n   syntax to mean \"substitution reference\" instead of \"hyperlink\n   reference\".  Alan's example::\n\n       I had lunch with Jonathan_ today.  We talked about Zope_.\n\n       .. _Jonathan: lj [user=jhl]\n       .. _Zope: https://www.zope.dev/\n\n   A problem with the proposed syntax is that URIs which look like\n   simple reference names (alphanum plus \".\", \"-\", \"_\") would be\n   indistinguishable from substitution directive names.  A more\n   consistent syntax would be::\n\n       I had lunch with Jonathan_ today.  We talked about Zope_.\n\n       .. _Jonathan: lj:: user=jhl\n       .. _Zope: https://www.zope.dev/\n\n   (``::`` after ``.. _Jonathan: lj``.)\n\n   The \"Zope\" target is a simple external hyperlink, but the\n   \"Jonathan\" target contains a directive.  Alan proposed is that the\n   reference text be replaced by whatever the referenced directive\n   (the \"directive target\") produces.  A directive reference becomes a\n   hyperlink reference if the contents of the directive target resolve\n   to a hyperlink.  If the directive target resolves to an icon, the\n   reference is replaced by an inline icon.  If the directive target\n   resolves to a hyperlink, the directive reference becomes a\n   hyperlink reference.\n\n   This seems too indirect and complicated for easy comprehension.\n\n   The reference in the text will sometimes become a link, sometimes\n   not.  Sometimes the reference text will remain, sometimes not.  We\n   don't know *at the reference*::\n\n       This is a `hyperlink reference`_; its text will remain.\n       This is an `inline icon`_; its text will disappear.\n\n   That's a problem.\n\nThe syntax that has been incorporated into the spec and parser is\nreference alternative 4d with definition alternative 3::\n\n    The |biohazard| symbol...\n\n    .. |biohazard| image:: biohazard.png\n       [height=20 width=20]\n\nWe can also combine substitution references with hyperlink references,\nby appending a \"_\" (named hyperlink reference) or \"__\" (anonymous\nhyperlink reference) suffix to the substitution reference.  This\nallows us to click on an image-link::\n\n    The |biohazard|_ symbol...\n\n    .. |biohazard| image:: biohazard.png\n       [height=20 width=20]\n    .. _biohazard: https://www.cdc.gov/\n\nThere have been several suggestions for the naming of these\nconstructs, originally called \"substitution references\" and\n\"substitutions\".\n\n1. Candidate names for the reference construct:\n\n   (a) substitution reference\n   (b) tagging reference\n   (c) inline directive reference\n   (d) directive reference\n   (e) indirect inline directive reference\n   (f) inline directive placeholder\n   (g) inline directive insertion reference\n   (h) directive insertion reference\n   (i) insertion reference\n   (j) directive macro reference\n   (k) macro reference\n   (l) substitution directive reference\n\n2. Candidate names for the definition construct:\n\n   (a) substitution\n   (b) substitution directive\n   (c) tag\n   (d) tagged directive\n   (e) directive target\n   (f) inline directive\n   (g) inline directive definition\n   (h) referenced directive\n   (i) indirect directive\n   (j) indirect directive definition\n   (k) directive definition\n   (l) indirect inline directive\n   (m) named directive definition\n   (n) inline directive insertion definition\n   (o) directive insertion definition\n   (p) insertion definition\n   (q) insertion directive\n   (r) substitution definition\n   (s) directive macro definition\n   (t) macro definition\n   (u) substitution directive definition\n   (v) substitution definition\n\n\"Inline directive reference\" (1c) seems to be an appropriate term at\nfirst, but the term \"inline\" is redundant in the case of the\nreference.  Its counterpart \"inline directive definition\" (2g) is\nawkward, because the directive definition itself is not inline.\n\n\"Directive reference\" (1d) and \"directive definition\" (2k) are too\nvague.  \"Directive definition\" could be used to refer to any\ndirective, not just those used for inline substitutions.\n\nOne meaning of the term \"macro\" (1k, 2s, 2t) is too\nprogramming-language-specific.  Also, macros are typically simple text\nsubstitution mechanisms: the text is substituted first and evaluated\nlater.  reStructuredText substitution definitions are evaluated in\nplace at parse time and substituted afterwards.\n\n\"Insertion\" (1h, 1i, 2n-2q) is almost right, but it implies that\nsomething new is getting added rather than one construct being\nreplaced by another.\n\nWhich brings us back to \"substitution\".  The overall best names are\n\"substitution reference\" (1a) and \"substitution definition\" (2v).  A\nlong way to go to add one word!\n\n\nInline External Targets\n=======================\n\nCurrently reStructuredText has two hyperlink syntax variations:\n\n* Named hyperlinks::\n\n      This is a named reference_ of one word (\"reference\").  Here is\n      a `phrase reference`_.  Phrase references may even cross `line\n      boundaries`_.\n\n      .. _reference: https://www.example.org/reference/\n      .. _phrase reference: https://www.example.org/phrase_reference/\n      .. _line boundaries: https://www.example.org/line_boundaries/\n\n  + Advantages:\n\n    - The plaintext is readable.\n    - Each target may be reused multiple times (e.g., just write\n      ``\"reference_\"`` again).\n    - No synchronized ordering of references and targets is necessary.\n\n  + Disadvantages:\n\n    - The reference text must be repeated as target names; could lead\n      to mistakes.\n    - The target URLs may be located far from the references, and hard\n      to find in the plaintext.\n\n* Anonymous hyperlinks (in current reStructuredText)::\n\n      This is an anonymous reference__.  Here is an anonymous\n      `phrase reference`__.  Phrase references may even cross `line\n      boundaries`__.\n\n      __ https://www.example.org/reference/\n      __ https://www.example.org/phrase_reference/\n      __ https://www.example.org/line_boundaries/\n\n  + Advantages:\n\n    - The plaintext is readable.\n    - The reference text does not have to be repeated.\n\n  + Disadvantages:\n\n    - References and targets must be kept in sync.\n    - Targets cannot be reused.\n    - The target URLs may be located far from the references.\n\nFor comparison and historical background, StructuredText also has two\nsyntaxes for hyperlinks:\n\n* First, ``\"reference text\":URL``::\n\n      This is a \"reference\":https://www.example.org/reference/\n      of one word (\"reference\").  Here is a \"phrase\n      reference\":https://www.example.org/phrase_reference/.\n\n* Second, ``\"reference text\", https://example.org/absolute_URL``::\n\n      This is a \"reference\", https://www.example.org/reference/\n      of one word (\"reference\").  Here is a \"phrase reference\",\n      https://www.example.org/phrase_reference/.\n\nBoth syntaxes share advantages and disadvantages:\n\n+ Advantages:\n\n  - The target is specified immediately adjacent to the reference.\n\n+ Disadvantages:\n\n  - Poor plaintext readability.\n  - Targets cannot be reused.\n  - Both syntaxes use double quotes, common in ordinary text.\n  - In the first syntax, the URL and the last word are stuck\n    together, exacerbating the line wrap problem.\n  - The second syntax is too magical; text could easily be written\n    that way by accident (although only absolute URLs are recognized\n    here, perhaps because of the potential for ambiguity).\n\nA new type of \"inline external hyperlink\" has been proposed.\n\n1. On 2002-06-28, Simon Budig proposed__ a new syntax for\n   reStructuredText hyperlinks::\n\n       This is a reference_(https://www.example.org/reference/) of one\n       word (\"reference\").  Here is a `phrase\n       reference`_(https://www.example.org/phrase_reference/).  Are\n       these examples, (single-underscore), named?  If so, `anonymous\n       references`__(https://www.example.org/anonymous/) using two\n       underscores would probably be preferable.\n\n   __ https://mail.python.org/pipermail/doc-sig/2002-June/002648.html\n\n   The syntax, advantages, and disadvantages are similar to those of\n   StructuredText.\n\n   + Advantages:\n\n     - The target is specified immediately adjacent to the reference.\n\n   + Disadvantages:\n\n     - Poor plaintext readability.\n     - Targets cannot be reused (unless named, but the semantics are\n       unclear).\n\n   + Problems:\n\n     - The ``\"`ref`_(URL)\"`` syntax forces the last word of the\n       reference text to be joined to the URL, making a potentially\n       very long word that can't be wrapped (URLs can be very long).\n       The reference and the URL should be separate.  This is a\n       symptom of the following point:\n\n     - The syntax produces a single compound construct made up of two\n       equally important parts, *with syntax in the middle*, *between*\n       the reference and the target.  This is unprecedented in\n       reStructuredText.\n\n     - The \"inline hyperlink\" text is *not* a named reference (there's\n       no lookup by name), so it shouldn't look like one.\n\n     - According to the IETF standards RFC 2396 and RFC 2732,\n       parentheses are legal URI characters and curly braces are legal\n       email characters, making their use prohibitively difficult.\n\n     - The named/anonymous semantics are unclear.\n\n2. After an analysis__ of the syntax of (1) above, we came up with the\n   following compromise syntax::\n\n       This is an anonymous reference__\n       __<https://www.example.org/reference/> of one word\n       (\"reference\").  Here is a `phrase reference`__\n       __<https://www.example.org/phrase_reference/>.  `Named\n       references`_ _<https://www.example.org/anonymous/> use single\n       underscores.\n\n   __ https://mail.python.org/pipermail/doc-sig/2002-July/002670.html\n\n   The syntax builds on that of the existing \"inline internal\n   targets\": ``an _`inline internal target`.``\n\n   + Advantages:\n\n     - The target is specified immediately adjacent to the reference,\n       improving maintainability:\n\n       - References and targets are easily kept in sync.\n       - The reference text does not have to be repeated.\n\n     - The construct is executed in two parts: references identical to\n       existing references, and targets that are new but not too big a\n       stretch from current syntax.\n\n     - There's overwhelming precedent for quoting URLs with angle\n       brackets [#]_.\n\n   + Disadvantages:\n\n     - Poor plaintext readability.\n     - Lots of \"line noise\".\n     - Targets cannot be reused (unless named; see below).\n\n   To alleviate the readability issue slightly, we could allow the\n   target to appear later, such as after the end of the sentence::\n\n       This is a named reference__ of one word (\"reference\").\n       __<https://www.example.org/reference/>  Here is a `phrase\n       reference`__.  __<https://www.example.org/phrase_reference/>\n\n   Problem: this could only work for one reference at a time\n   (reference/target pairs must be proximate [refA trgA refB trgB],\n   not interleaved [refA refB trgA trgB] or nested [refA refB trgB\n   trgA]).  This variation is too problematic; references and inline\n   external targets will have to be kept immediately adjacent (see (3)\n   below).\n\n   The ``\"reference__ __<target>\"`` syntax is actually for \"anonymous\n   inline external targets\", emphasized by the double underscores.  It\n   follows that single trailing and leading underscores would lead to\n   *implicitly named* inline external targets.  This would allow the\n   reuse of targets by name.  So after ``\"reference_ _<target>\"``,\n   another ``\"reference_\"`` would point to the same target.\n\n   .. [#]\n      From RFC 2396 (URI syntax):\n\n          The angle-bracket \"<\" and \">\" and double-quote (\")\n          characters are excluded [from URIs] because they are often\n          used as the delimiters around URI in text documents and\n          protocol fields.\n\n          Using <> angle brackets around each URI is especially\n          recommended as a delimiting style for URI that contain\n          whitespace.\n\n      From RFC 822 (email headers):\n\n          Angle brackets (\"<\" and \">\") are generally used to indicate\n          the presence of a one machine-usable reference (e.g.,\n          delimiting mailboxes), possibly including source-routing to\n          the machine.\n\n3. If it is best for references and inline external targets to be\n   immediately adjacent, then they might as well be integrated.\n   Here's an alternative syntax embedding the target URL in the\n   reference::\n\n       This is an anonymous `reference <https://www.example.org\n       /reference/>`__ of one word (\"reference\").  Here is a `phrase\n       reference <https://www.example.org/phrase_reference/>`__.\n\n   Advantages and disadvantages are similar to those in (2).\n   Readability is still an issue, but the syntax is a bit less\n   heavyweight (reduced line noise).  Backquotes are required, even\n   for one-word references; the target URL is included within the\n   reference text, forcing a phrase context.\n\n   We'll call this variant \"embedded URIs\".\n\n   Problem: how to refer to a title like \"HTML Anchors: <a>\" (which\n   ends with an HTML/SGML/XML tag)?  We could either require more\n   syntax on the target (like ``\"`reference text\n   __<https://example.org/>`__\"``), or require the odd conflicting\n   title to be escaped (like ``\"`HTML Anchors: \\<a>`__\"``).  The\n   latter seems preferable, and not too onerous.\n\n   Similarly to (2) above, a single trailing underscore would convert\n   the reference & inline external target from anonymous to implicitly\n   named, allowing reuse of targets by name.\n\n   I think this is the least objectionable of the syntax alternatives.\n\nOther syntax variations have been proposed (by Brett Cannon and Benja\nFallenstein)::\n\n    `phrase reference`->https://www.example.org\n\n    `phrase reference`@https://www.example.org\n\n    `phrase reference`__ ->https://www.example.org\n\n    `phrase reference` [-> https://www.example.org]\n\n    `phrase reference`__ [-> https://www.example.org]\n\n    `phrase reference` <https://www.example.org>_\n\nNone of these variations are clearly superior to #3 above.  Some have\nproblems that exclude their use.\n\nWith any kind of inline external target syntax it comes down to the\nconflict between maintainability and plaintext readability.  I don't\nsee a major problem with reStructuredText's maintainability, and I\ndon't want to sacrifice plaintext readability to \"improve\" it.\n\nThe proponents of inline external targets want them for easily\nmaintainable web pages.  The arguments go something like this:\n\n- Named hyperlinks are difficult to maintain because the reference\n  text is duplicated as the target name.\n\n  To which I said, \"So use anonymous hyperlinks.\"\n\n- Anonymous hyperlinks are difficult to maintain because the\n  references and targets have to be kept in sync.\n\n  \"So keep the targets close to the references, grouped after each\n  paragraph.  Maintenance is trivial.\"\n\n- But targets grouped after paragraphs break the flow of text.\n\n  \"Surely less than URLs embedded in the text!  And if the intent is\n  to produce web pages, not readable plaintext, then who cares about\n  the flow of text?\"\n\nMany participants have voiced their objections to the proposed syntax:\n\n    Garth Kidd: \"I strongly prefer the current way of doing it.\n    Inline is spectactularly messy, IMHO.\"\n\n    Tony Ibbs: \"I vehemently agree... that the inline alternatives\n    being suggested look messy - there are/were good reasons they've\n    been taken out...  I don't believe I would gain from the new\n    syntaxes.\"\n\n    Paul Moore: \"I agree as well.  The proposed syntax is far too\n    punctuation-heavy, and any of the alternatives discussed are\n    ambiguous or too subtle.\"\n\nOthers have voiced their support:\n\n    fantasai: \"I agree with Simon.  In many cases, though certainly\n    not in all, I find parenthesizing the url in plain text flows\n    better than relegating it to a footnote.\"\n\n    Ken Manheimer: \"I'd like to weigh in requesting some kind of easy,\n    direct inline reference link.\"\n\n(Interesting that those *against* the proposal have been using\nreStructuredText for a while, and those *for* the proposal are either\nnew to the list [\"fantasai\", background unknown] or longtime\nStructuredText users [Ken Manheimer].)\n\nI was initially ambivalent/against the proposed \"inline external\ntargets\".  I value reStructuredText's readability very highly, and\nalthough the proposed syntax offers convenience, I don't know if the\nconvenience is worth the cost in ugliness.  Does the proposed syntax\ncompromise readability too much, or should the choice be left up to\nthe author?  Perhaps if the syntax is *allowed* but its use strongly\n*discouraged*, for aesthetic/readability reasons?\n\nAfter a great deal of thought and much input from users, I've decided\nthat there are reasonable use cases for this construct.  The\ndocumentation should strongly caution against its use in most\nsituations, recommending independent block-level targets instead.\nSyntax #3 above (\"embedded URIs\") will be used.\n\n\nDoctree Representation of Transitions\n=====================================\n\n(Although not reStructuredText-specific, this section fits best in\nthis document.)\n\nHaving added the \"horizontal rule\" construct to the `reStructuredText\nMarkup Specification`_, a decision had to be made as to how to reflect\nthe construct in the implementation of the document tree.  Given this\nsource::\n\n    Document\n    ========\n\n    Paragraph 1\n\n    --------\n\n    Paragraph 2\n\nThe horizontal rule indicates a \"transition\" (in prose terms) or the\nstart of a new \"division\".  Before implementation, the parsed document\ntree would be::\n\n    <document>\n        <section names=\"document\">\n            <title>\n                Document\n            <paragraph>\n                Paragraph 1\n            --------               <--- error here\n            <paragraph>\n                Paragraph 2\n\nThere are several possibilities for the implementation:\n\n1. Implement horizontal rules as \"divisions\" or segments.  A\n   \"division\" is a title-less, non-hierarchical section.  The first\n   try at an implementation looked like this::\n\n       <document>\n           <section names=\"document\">\n               <title>\n                   Document\n               <paragraph>\n                   Paragraph 1\n               <division>\n                   <paragraph>\n                       Paragraph 2\n\n   But the two paragraphs are really at the same level; they shouldn't\n   appear to be at different levels.  There's really an invisible\n   \"first division\".  The horizontal rule splits the document body\n   into two segments, which should be treated uniformly.\n\n2. Treating \"divisions\" uniformly brings us to the second\n   possibility::\n\n       <document>\n           <section names=\"document\">\n               <title>\n                   Document\n               <division>\n                   <paragraph>\n                       Paragraph 1\n               <division>\n                   <paragraph>\n                       Paragraph 2\n\n   With this change, documents and sections will directly contain\n   divisions and sections, but not body elements.  Only divisions will\n   directly contain body elements.  Even without a horizontal rule\n   anywhere, the body elements of a document or section would be\n   contained within a division element.  This makes the document tree\n   deeper.  This is similar to the way HTML_ treats document contents:\n   grouped within a ``<body>`` element.\n\n3. Implement them as \"transitions\", empty elements::\n\n       <document>\n           <section names=\"document\">\n               <title>\n                   Document\n               <paragraph>\n                   Paragraph 1\n               <transition>\n               <paragraph>\n                   Paragraph 2\n\n   A transition would be a \"point element\", not containing anything,\n   only identifying a point within the document structure.  This keeps\n   the document tree flatter, but the idea of a \"point element\" like\n   \"transition\" smells bad.  A transition isn't a thing itself, it's\n   the space between two divisions.  However, transitions are a\n   practical solution.\n\nSolution 3 was chosen for incorporation into the document tree model.\n\n.. _HTML: https://www.w3.org/MarkUp/\n\n\nSyntax for Line Blocks\n======================\n\n* An early idea: How about a literal-block-like prefix, perhaps\n  \"``;;``\"?  (It is, after all, a *semi-literal* literal block, no?)\n  Example::\n\n      Take it away, Eric the Orchestra Leader!  ;;\n\n          A one, two, a one two three four\n\n          Half a bee, philosophically,\n          must, *ipso facto*, half not be.\n          But half the bee has got to be,\n          *vis a vis* its entity.  D'you see?\n\n          But can a bee be said to be\n          or not to be an entire bee,\n          when half the bee is not a bee,\n          due to some ancient injury?\n\n          Singing...\n\n  Kinda lame.\n\n* Another idea: in an ordinary paragraph, if the first line ends with\n  a backslash (escaping the newline), interpret the entire paragraph\n  as a verse block?  For example::\n\n      Add just one backslash\\\n      And this paragraph becomes\n      An awful haiku\n\n  (Awful, and arguably invalid, since in Japanese the word \"haiku\"\n  contains three syllables not two.)\n\n  This idea was superseded by the rules for escaped whitespace, useful\n  for `character-level inline markup`_.\n\n* In a `2004-02-22 docutils-develop message`__, Jarno Elonen proposed\n  a \"plain list\" syntax (and also provided a patch)::\n\n       | John Doe\n       | President, SuperDuper Corp.\n       | jdoe@example.org\n\n  __ https://thread.gmane.org/gmane.text.docutils.devel/1187\n\n  This syntax is very natural.  However, these \"plain lists\" seem very\n  similar to line blocks, and I see so little intrinsic \"list-ness\"\n  that I'm loathe to add a new object.  I used the term \"blurbs\" to\n  remove the \"list\" connotation from the originally proposed name.\n  Perhaps line blocks could be refined to add the two properties they\n  currently lack:\n\n  A) long lines wrap nicely\n  B) HTML output doesn't look like program code in non-CSS web\n     browsers\n\n  (A) is an issue of all 3 aspects of Docutils: syntax (construct\n  behaviour), internal representation, and output.  (B) is partly an\n  issue of internal representation but mostly of output.\n\nReStructuredText will redefine line blocks with the \"|\"-quoting\nsyntax.  The following is my current thinking.\n\n\nSyntax\n------\n\nPerhaps line block syntax like this would do::\n\n     | M6: James Bond\n     | MIB: Mr. J.\n     | IMF: not decided yet, but probably one of the following:\n     |   Ethan Hunt\n     |   Jim Phelps\n     |   Claire Phelps\n     | CIA: Lea Leiter\n\nNote that the \"nested\" list does not have nested syntax (the \"|\" are\nnot further indented); the leading whitespace would still be\nsignificant somehow (more below).  As for long lines in the input,\nthis could suffice::\n\n     | John Doe\n     | Founder, President, Chief Executive Officer, Cook, Bottle\n       Washer, and All-Round Great Guy\n     | SuperDuper Corp.\n     | jdoe@example.org\n\nThe lack of \"|\" on the third line indicates that it's a continuation\nof the second line, wrapped.\n\nI don't see much point in allowing arbitrary nested content.  Multiple\nparagraphs or bullet lists inside a \"blurb\" doesn't make sense to me.\nSimple nested line blocks should suffice.\n\n\nInternal Representation\n-----------------------\n\nLine blocks are currently represented as text blobs as follows::\n\n     <!ELEMENT line_block %text.model;>\n     <!ATTLIST line_block\n         %basic.atts;\n         %fixedspace.att;>\n\nInstead, we could represent each line by a separate element::\n\n     <!ELEMENT line_block (line+)>\n     <!ATTLIST line_block %basic.atts;>\n\n     <!ELEMENT line %text.model;>\n     <!ATTLIST line %basic.atts;>\n\nWe'd keep the significance of the leading whitespace of each line\neither by converting it to non-breaking spaces at output, or with a\nper-line margin.  Non-breaking spaces are simpler (for HTML, anyway)\nbut kludgey, and wouldn't support indented long lines that wrap.  But\nshould inter-word whitespace (i.e., not leading whitespace) be\npreserved?  Currently it is preserved in line blocks.\n\nRepresenting a more complex line block may be tricky::\n\n     | But can a bee be said to be\n     |     or not to be an entire bee,\n     |         when half the bee is not a bee,\n     |             due to some ancient injury?\n\nPerhaps the representation could allow for nested line blocks::\n\n     <!ELEMENT line_block (line | line_block)+>\n\nWith this model, leading whitespace would no longer be significant.\nInstead, left margins are implied by the nesting.  The example above\ncould be represented as follows::\n\n     <line_block>\n         <line>\n             But can a bee be said to be\n         <line_block>\n             <line>\n                  or not to be an entire bee,\n             <line_block>\n                 <line>\n                     when half the bee is not a bee,\n                 <line_block>\n                     <line>\n                         due to some ancient injury?\n\nI wasn't sure what to do about even more complex line blocks::\n\n     |     Indented\n     | Not indented\n     |   Indented a bit\n     |     A bit more\n     |  Only one space\n\nHow should that be parsed and nested?  Should the first line have\nthe same nesting level (== indentation in the output) as the fourth\nline, or the same as the last line?  Mark Nodine suggested that such\nline blocks be parsed similarly to complexly-nested block quotes,\nwhich seems reasonable.  In the example above, this would result in\nthe nesting of first line matching the last line's nesting.  In\nother words, the nesting would be relative to neighboring lines\nonly.\n\n\nOutput\n------\n\nIn HTML, line blocks are currently output as \"<pre>\" blocks, which\ngives us significant whitespace and line breaks, but doesn't allow\nlong lines to wrap and causes monospaced output without stylesheets.\nInstead, we could output \"<div>\" elements parallelling the\nrepresentation above, where each nested <div class=\"line_block\"> would\nhave an increased left margin (specified in the stylesheet).\n\nJarno suggested the following HTML output::\n\n    <div class=\"line_block\">\n       <span class=\"line\">First, top level line</span><br class=\"hidden\"/>\n       <div class=\"line_block\"><span class=\"hidden\">&nbsp;</span>\n          <span class=\"line\">Second, once nested</span><br class=\"hidden\"/>\n          <span class=\"line\">Third, once nested</span><br class=\"hidden\"/>\n          ...\n       </div>\n       ...\n    </div>\n\nThe ``<br class=\"hidden\" />`` and ``<span\nclass=\"hidden\">&nbsp;</span>`` are meant to support non-CSS and\nnon-graphical browsers.  I understand the case for \"br\", but I'm not\nso sure about hidden \"&nbsp;\".  I question how much effort should be\nput toward supporting non-graphical and especially non-CSS browsers,\nat least for html4css1.py output.\n\nShould the lines themselves be ``<span>`` or ``<div>``?  I don't like\nmixing inline and block-level elements.\n\n\nImplementation Plan\n-------------------\n\nWe'll leave the old implementation in place (via the \"line-block\"\ndirective only) until all Writers have been updated to support the new\nsyntax & implementation.  The \"line-block\" directive can then be\nupdated to use the new internal representation, and its documentation\nwill be updated to recommend the new syntax.\n\n\nList-Driven Tables\n==================\n\nThe original idea came from Dylan Jay:\n\n    ... to use a two level bulleted list with something to\n    indicate it should be rendered as a table ...\n\nIt's an interesting idea.  It could be implemented in as a directive\nwhich transforms a uniform two-level list into a table.  Using a\ndirective would allow the author to explicitly set the table's\norientation (by column or by row), the presence of row headers, etc.\n\nAlternatives:\n\n1. (Implemented in Docutils 0.3.8).\n\n   Bullet-list-tables might look like this::\n\n       .. list-table::\n\n          * - Treat\n            - Quantity\n            - Description\n          * - Albatross!\n            - 299\n            - On a stick!\n          * - Crunchy Frog!\n            - 1499\n            - If we took the bones out, it wouldn't be crunchy,\n              now would it?\n          * - Gannet Ripple!\n            - 199\n            - On a stick!\n\n   This list must be written in two levels.  This wouldn't work::\n\n       .. list-table::\n\n          * Treat\n          * Albatross!\n          * Gannet!\n          * Crunchy Frog!\n\n          * Quantity\n          * 299\n          * 199\n          * 1499\n\n          * Description\n          * On a stick!\n          * On a stick!\n          * If we took the bones out...\n\n   The above is a single list of 12 items.  The blank lines are not\n   significant to the markup.  We'd have to explicitly specify how\n   many columns or rows to use, which isn't a good idea.\n\n2. Beni Cherniavsky suggested a field list alternative.  It could look\n   like this::\n\n       .. field-list-table::\n          :headrows: 1\n\n          - :treat: Treat\n            :quantity: Quantity\n            :descr: Description\n\n          - :treat: Albatross!\n            :quantity: 299\n            :descr: On a stick!\n\n          - :treat: Crunchy Frog!\n            :quantity: 1499\n            :descr: If we took the bones out, it wouldn't be\n                    crunchy, now would it?\n\n   Column order is determined from the order of fields in the first\n   row.  Field order in all other rows is ignored.  As a side-effect,\n   this allows trivial re-arrangement of columns.  By using named\n   fields, it becomes possible to omit fields in some rows without\n   losing track of things, which is important for spans.\n\n3. An alternative to two-level bullet lists would be to use enumerated\n   lists for the table cells::\n\n       .. list-table::\n\n           * 1. Treat\n             2. Quantity\n             3. Description\n           * 1. Albatross!\n             2. 299\n             3. On a stick!\n           * 1. Crunchy Frog!\n             2. 1499\n             3. If we took the bones out, it wouldn't be crunchy,\n                now would it?\n\n   That provides better correspondence between cells in the same\n   column than does bullet-list syntax, but not as good as field list\n   syntax.  I think that were only field-list-tables available, a lot\n   of users would use the equivalent degenerate case::\n\n       .. field-list-table::\n           - :1: Treat\n             :2: Quantity\n             :3: Description\n           ...\n\n4. Another natural variant is to allow a description list with field\n   lists as descriptions::\n\n       .. list-table::\n           :headrows: 1\n\n           Treat\n               :quantity: Quantity\n               :descr: Description\n           Albatross!\n               :quantity: 299\n               :descr: On a stick!\n           Crunchy Frog!\n               :quantity: 1499\n               :descr: If we took the bones out, it wouldn't be\n                       crunchy, now would it?\n\n   This would make the whole first column a header column (\"stub\").\n   It's limited to a single column and a single paragraph fitting on\n   one source line.  Also it wouldn't allow for empty cells or row\n   spans in the first column.  But these are limitations that we could\n   live with, like those of simple tables.\n\nThe List-driven table feature could be done in many ways.  Each user\nwill have their preferred usage.  Perhaps a single \"list-table\"\ndirective could handle them all, depending on which options and\ncontent are present.\n\nIssues:\n\n* How to indicate that there's 1 header row?  Perhaps two lists?  ::\n\n      .. list-table::\n\n         + - Treat\n           - Quantity\n           - Description\n\n         * - Albatross!\n           - 299\n           - On a stick!\n\n  This is probably too subtle though.  Better would be a directive\n  option, like ``:headrows: 1``.  An early suggestion for the header\n  row(s) was to use a directive option::\n\n      .. field-list-table::\n         :header:\n             - :treat: Treat\n               :quantity: Quantity\n               :descr: Description\n         - :treat: Albatross!\n           :quantity: 299\n           :descr: On a stick!\n\n  But the table data is at two levels and looks inconsistent.\n\n  In general, we cannot extract the header row from field lists' field\n  names because field names cannot contain everything one might put in\n  a table cell.  A separate header row also allows shorter field names\n  and doesn't force one to rewrite the whole table when the header\n  text changes.  But for simpler cases, we can offer a \":header:\n  fields\" option, which does extract header cells from field names::\n\n      .. field-list-table::\n          :header: fields\n\n          - :Treat: Albatross!\n            :Quantity: 299\n            :Description: On a stick!\n\n* How to indicate the column widths?  A directive option? ::\n\n      .. list-table::\n         :widths: 15 10 35\n\n  Automatic defaults from the text used?\n\n* How to handle row and/or column spans?\n\n  In a field list, column-spans can be indicated by specifying the\n  first and last fields, separated by space-dash-space or ellipsis::\n\n      - :foo - baz: quuux\n      - :foo ... baz: quuux\n\n  Commas were proposed for column spans::\n\n      - :foo, bar: quux\n\n  But non-adjacent columns become problematic.  Should we report an\n  error, or duplicate the value into each span of adjacent columns (as\n  was suggested)?  The latter suggestion is appealing but may be too\n  clever.  Best perhaps to simply specify the two ends.\n\n  It was suggested that comma syntax should be allowed, too, in order\n  to allow the user to avoid trouble when changing the column order.\n  But changing the column order of a table with spans is not trivial;\n  we shouldn't make it easier to mess up.\n\n  One possible syntax for row-spans is to simply treat any row where a\n  field is missing as a row-span from the last row where it appeared.\n  Leaving a field empty would still be possible by writing a field\n  with empty content.  But this is too implicit.\n\n  Another way would be to require an explicit continuation marker\n  (``...``/``-\"-``/``\"``?) in all but the first row of a spanned\n  field.  Empty comments could work (\"..\").  If implemented, the same\n  marker could also be supported in simple tables, which lack\n  row-spanning abilities.\n\n  Explicit markup like \":rowspan:\" and \":colspan:\" was also suggested.\n\n  Sometimes in a table, the first header row contains spans.  It may\n  be necessary to provide a way to specify the column field names\n  independently of data rows.  A directive option would do it.\n\n* We could specify \"column-wise\" or \"row-wise\" ordering, with the same\n  markup structure.  For example, with definition data::\n\n      .. list-table::\n         :column-wise:\n\n         Treat\n             - Albatross!\n             - Crunchy Frog!\n         Quantity\n             - 299\n             - 1499\n         Description\n             - On a stick!\n             - If we took the bones out, it wouldn't be\n               crunchy, now would it?\n\n* A syntax for _`stubs in grid tables` is easy to imagine::\n\n      +------------------------++------------+----------+\n      | Header row, column 1   || Header 2   | Header 3 |\n      +========================++============+==========+\n      | body row 1, column 1   || column 2   | column 3 |\n      +------------------------++------------+----------+\n\n  Or this idea from Nick Moffitt::\n\n      +-----+---+---+\n      | XOR # T | F |\n      +=====+===+===+\n      |   T # F | T |\n      +-----+---+---+\n      |   F # T | F |\n      +-----+---+---+\n\n\nAuto-Enumerated Lists\n=====================\n\nImplemented 2005-03-24: combination of variation 1 & 2.\n\nThe advantage of auto-numbered enumerated lists would be similar to\nthat of auto-numbered footnotes: lists could be written and rearranged\nwithout having to manually renumber them.  The disadvantages are also\nthe same: input and output wouldn't match exactly; the markup may be\nugly or confusing (depending on which alternative is chosen).\n\n1. Use the \"#\" symbol.  Example::\n\n       #. Item 1.\n       #. Item 2.\n       #. Item 3.\n\n   Advantages: simple, explicit.  Disadvantage: enumeration sequence\n   cannot be specified (limited to arabic numerals); ugly.\n\n2. As a variation on #1, first initialize the enumeration sequence?\n   For example::\n\n       a) Item a.\n       #) Item b.\n       #) Item c.\n\n   Advantages: simple, explicit, any enumeration sequence possible.\n   Disadvantages: ugly; perhaps confusing with mixed concrete/abstract\n   enumerators.\n\n3. Alternative suggested by Fred Bremmer, from experience with MoinMoin::\n\n       1. Item 1.\n       1. Item 2.\n       1. Item 3.\n\n   Advantages: enumeration sequence is explicit (could be multiple\n   \"a.\" or \"(I)\" tokens).  Disadvantages: perhaps confusing; otherwise\n   erroneous input (e.g., a duplicate item \"1.\") would pass silently,\n   either causing a problem later in the list (if no blank lines\n   between items) or creating two lists (with blanks).\n\n   Take this input for example::\n\n       1. Item 1.\n\n       1. Unintentional duplicate of item 1.\n\n       2. Item 2.\n\n   Currently the parser will produce two list, \"1\" and \"1,2\" (no\n   warnings, because of the presence of blank lines).  Using Fred's\n   notation, the current behavior is \"1,1,2 -> 1 1,2\" (without blank\n   lines between items, it would be \"1,1,2 -> 1 [WARNING] 1,2\").  What\n   should the behavior be with auto-numbering?\n\n   Fred has produced a patch__, whose initial behavior is as follows::\n\n       1,1,1   -> 1,2,3\n       1,2,2   -> 1,2,3\n       3,3,3   -> 3,4,5\n       1,2,2,3 -> 1,2,3 [WARNING] 3\n       1,1,2   -> 1,2 [WARNING] 2\n\n   (After the \"[WARNING]\", the \"3\" would begin a new list.)\n\n   I have mixed feelings about adding this functionality to the spec &\n   parser.  It would certainly be useful to some users (myself\n   included; I often have to renumber lists).  Perhaps it's too\n   clever, asking the parser to guess too much.  What if you *do* want\n   three one-item lists in a row, each beginning with \"1.\"?  You'd\n   have to use empty comments to force breaks.  Also, I question\n   whether \"1,2,2 -> 1,2,3\" is optimal behavior.\n\n   In response, Fred came up with \"a stricter and more explicit rule\n   [which] would be to only auto-number silently if *all* the\n   enumerators of a list were identical\".  In that case::\n\n       1,1,1   -> 1,2,3\n       1,2,2   -> 1,2 [WARNING] 2\n       3,3,3   -> 3,4,5\n       1,2,2,3 -> 1,2 [WARNING] 2,3\n       1,1,2   -> 1,2 [WARNING] 2\n\n   Should any start-value be allowed (\"3,3,3\"), or should\n   auto-numbered lists be limited to begin with ordinal-1 (\"1\", \"A\",\n   \"a\", \"I\", or \"i\")?\n\n   __ https://sourceforge.net/tracker/index.php?func=detail&aid=548802\n      &group_id=38414&atid=422032\n\n4. Alternative proposed by Tony Ibbs::\n\n       #1. First item.\n       #3. Aha - I edited this in later.\n       #2. Second item.\n\n   The initial proposal required unique enumerators within a list, but\n   this limits the convenience of a feature of already limited\n   applicability and convenience.  Not a useful requirement; dropped.\n\n   Instead, simply prepend a \"#\" to a standard list enumerator to\n   indicate auto-enumeration.  The numbers (or letters) of the\n   enumerators themselves are not significant, except:\n\n   - as a sequence indicator (arabic, roman, alphabetic; upper/lower),\n\n   - and perhaps as a start value (first list item).\n\n   Advantages: explicit, any enumeration sequence possible.\n   Disadvantages: a bit ugly.\n\n\nAdjacent citation references\n============================\n\nA special case for inline markup was proposed and implemented:\nmultiple citation references could be joined into one::\n\n   [cite1]_[cite2]_ instead of requiring [cite1]_ [cite2]_\n\nHowever, this was rejected as an unwarranted exception to the rules\nfor inline markup.\n(The main motivation for the proposal, grouping citations in the latex writer,\nwas implemented by recognising the second group in the example above and\ntransforming it into ``\\cite{cite1,cite2}``.)\n\n\nInline markup recognition\n=========================\n\nImplemented 2011-12-05 (version 0.9):\nExtended `inline markup recognition rules`_.\n\nNon-ASCII whitespace, punctuation characters and \"international\" quotes are\nallowed around inline markup (based on `Unicode categories`_). The rules for\nASCII characters were not changed.\n\nRejected alternatives:\n\na) Use `Unicode categories`_ for all chars (ASCII or not)\n\n   +1  comprehensible, standards based,\n   -1  many \"false positives\" need escaping,\n   -1  not backwards compatible.\n\nb) full backwards compatibility\n\n   :Pi: only before start-string\n   :Pf: only behind end-string\n   :Po: \"conservative\" sorting of other punctuation:\n\n        :``.,;!?\\\\``: Close\n        :``¡¿``:   Open\n\n   +1  backwards compatible,\n   +1  logical extension of the existing rules,\n   -1  exception list for \"other\" punctuation needed,\n   -1  rules even more complicated,\n   -1  not clear how to sort \"other\" punctuation that is currently not\n       recognized,\n   -2  international quoting convention like\n       »German ›angular‹ quotes« not recognized.\n\n.. _Inline markup recognition rules:\n   ../../ref/rst/restructuredtext.html#inline-markup-recognition-rules\n.. _Unicode categories:\n   https://www.unicode.org/Public/5.1.0/ucd/UCD.html#General_Category_Values\n\n\n-----------------\n Not Implemented\n-----------------\n\nReworking Footnotes\n===================\n\nAs a further wrinkle (see `Reworking Explicit Markup (Round 1)`_\nabove), in the wee hours of 2002-02-28 I posted several ideas for\nchanges to footnote syntax:\n\n    - Change footnote syntax from ``.. [1]`` to ``_[1]``? ...\n    - Differentiate (with new DTD elements) author-date \"citations\"\n      (``[GVR2002]``) from numbered footnotes? ...\n    - Render footnote references as superscripts without \"[]\"? ...\n\nThese ideas are all related, and suggest changes in the\nreStructuredText syntax as well as the docutils tree model.\n\nThe footnote has been used for both true footnotes (asides expanding\non points or defining terms) and for citations (references to external\nworks).  Rather than dealing with one amalgam construct, we could\nseparate the current footnote concept into strict footnotes and\ncitations.  Citations could be interpreted and treated differently\nfrom footnotes.  Footnotes would be limited to numerical labels:\nmanual (\"1\") and auto-numbered (anonymous \"#\", named \"#label\").\n\nThe footnote is the only explicit markup construct (starts with \".. \")\nthat directly translates to a visible body element.  I've always been\na little bit uncomfortable with the \".. \" marker for footnotes because\nof this; \".. \" has a connotation of \"special\", but footnotes aren't\nespecially \"special\".  Printed texts often put footnotes at the bottom\nof the page where the reference occurs (thus \"foot note\").  Some HTML\ndesigns would leave footnotes to be rendered the same positions where\nthey're defined.  Other online and printed designs will gather\nfootnotes into a section near the end of the document, converting them\nto \"endnotes\" (perhaps using a directive in our case); but this\n\"special processing\" is not an intrinsic property of the footnote\nitself, but a decision made by the document author or processing\nsystem.\n\nCitations are almost invariably collected in a section at the end of a\ndocument or section.  Citations \"disappear\" from where they are\ndefined and are magically reinserted at some well-defined point.\nThere's more of a connection to the \"special\" connotation of the \".. \"\nsyntax.  The point at which the list of citations is inserted could be\ndefined manually by a directive (e.g., \".. citations::\"), and/or have\ndefault behavior (e.g., a section automatically inserted at the end of\nthe document) that might be influenced by options to the Writer.\n\nSyntax proposals:\n\n+ Footnotes:\n\n  - Current syntax::\n\n        .. [1] Footnote 1\n        .. [#] Auto-numbered footnote.\n        .. [#label] Auto-labeled footnote.\n\n  - The syntax proposed in the original 2002-02-28 Doc-SIG post:\n    remove the \".. \", prefix a \"_\"::\n\n        _[1] Footnote 1\n        _[#] Auto-numbered footnote.\n        _[#label] Auto-labeled footnote.\n\n    The leading underscore syntax (earlier dropped because\n    ``.. _[1]:`` was too verbose) is a useful reminder that footnotes\n    are hyperlink targets.\n\n  - Minimal syntax: remove the \".. [\" and \"]\", prefix a \"_\", and\n    suffix a \".\"::\n\n        _1. Footnote 1.\n        _#. Auto-numbered footnote.\n        _#label. Auto-labeled footnote.\n\n                 ``_1.``, ``_#.``, and ``_#label.`` are markers,\n                 like list markers.\n\n    Footnotes could be rendered something like this in HTML\n\n        | 1. This is a footnote.  The brackets could be dropped\n        |    from the label, and a vertical bar could set them\n        |    off from the rest of the document in the HTML.\n\n    Two-way hyperlinks on the footnote marker (\"1.\" above) would also\n    help to differentiate footnotes from enumerated lists.\n\n    If converted to endnotes (by a directive/transform), a horizontal\n    half-line might be used instead.  Page-oriented output formats\n    would typically use the horizontal line for true footnotes.\n\n+ Footnote references:\n\n  - Current syntax::\n\n        [1]_, [#]_, [#label]_\n\n  - Minimal syntax to match the minimal footnote syntax above::\n\n        1_, #_, #label_\n\n    As a consequence, pure-numeric hyperlink references would not be\n    possible; they'd be interpreted as footnote references.\n\n+ Citation references: no change is proposed from the current footnote\n  reference syntax::\n\n      [GVR2001]_\n\n+ Citations:\n\n  - Current syntax (footnote syntax)::\n\n        .. [GVR2001] Python Documentation; van Rossum, Drake, et al.;\n           https://www.python.org/doc/\n\n  - Possible new syntax::\n\n        _[GVR2001] Python Documentation; van Rossum, Drake, et al.;\n                   https://www.python.org/doc/\n\n        _[DJG2002]\n            Docutils: Python Documentation Utilities project; Goodger\n            et al.; https://docutils.sourceforge.io/\n\n    Without the \".. \" marker, subsequent lines would either have to\n    align as in one of the above, or we'd have to allow loose\n    alignment (I'd rather not)::\n\n        _[GVR2001] Python Documentation; van Rossum, Drake, et al.;\n            https://www.python.org/doc/\n\nI proposed adopting the \"minimal\" syntax for footnotes and footnote\nreferences, and adding citations and citation references to\nreStructuredText's repertoire.  The current footnote syntax for\ncitations is better than the alternatives given.\n\nFrom a reply by Tony Ibbs on 2002-03-01:\n\n    However, I think easier with examples, so let's create one::\n\n        Fans of Terry Pratchett are perhaps more likely to use\n        footnotes [1]_ in their own writings than other people\n        [2]_.  Of course, in *general*, one only sees footnotes\n        in academic or technical writing - it's use in fiction\n        and letter writing is not normally considered good\n        style [4]_, particularly in emails (not a medium that\n        lends itself to footnotes).\n\n        .. [1] That is, little bits of referenced text at the\n           bottom of the page.\n        .. [2] Because Terry himself does, of course [3]_.\n        .. [3] Although he has the distinction of being\n           *funny* when he does it, and his fans don't always\n           achieve that aim.\n        .. [4] Presumably because it detracts from linear\n           reading of the text - this is, of course, the point.\n\n    and look at it with the second syntax proposal::\n\n        Fans of Terry Pratchett are perhaps more likely to use\n        footnotes [1]_ in their own writings than other people\n        [2]_.  Of course, in *general*, one only sees footnotes\n        in academic or technical writing - it's use in fiction\n        and letter writing is not normally considered good\n        style [4]_, particularly in emails (not a medium that\n        lends itself to footnotes).\n\n        _[1] That is, little bits of referenced text at the\n             bottom of the page.\n        _[2] Because Terry himself does, of course [3]_.\n        _[3] Although he has the distinction of being\n             *funny* when he does it, and his fans don't always\n             achieve that aim.\n        _[4] Presumably because it detracts from linear\n             reading of the text - this is, of course, the point.\n\n    (I note here that if I have gotten the indentation of the\n    footnotes themselves correct, this is clearly not as nice.  And if\n    the indentation should be to the left margin instead, I like that\n    even less).\n\n    and the third (new) proposal::\n\n        Fans of Terry Pratchett are perhaps more likely to use\n        footnotes 1_ in their own writings than other people\n        2_.  Of course, in *general*, one only sees footnotes\n        in academic or technical writing - it's use in fiction\n        and letter writing is not normally considered good\n        style 4_, particularly in emails (not a medium that\n        lends itself to footnotes).\n\n        _1. That is, little bits of referenced text at the\n            bottom of the page.\n        _2. Because Terry himself does, of course 3_.\n        _3. Although he has the distinction of being\n            *funny* when he does it, and his fans don't always\n            achieve that aim.\n        _4. Presumably because it detracts from linear\n            reading of the text - this is, of course, the point.\n\n    I think I don't, in practice, mind the targets too much (the use\n    of a dot after the number helps a lot here), but I do have a\n    problem with the body text, in that I don't naturally separate out\n    the footnotes as different than the rest of the text - instead I\n    keep wondering why there are numbers interspered in the text.  The\n    use of brackets around the numbers ([ and ]) made me somehow parse\n    the footnote references as \"odd\" - i.e., not part of the body text\n    - and thus both easier to skip, and also (paradoxically) easier to\n    pick out so that I could follow them.\n\n    Thus, for the moment (and as always susceptable to argument), I'd\n    say -1 on the new form of footnote reference (i.e., I much prefer\n    the existing ``[1]_`` over the proposed ``1_``), and ambivalent\n    over the proposed target change.\n\n    That leaves David's problem of wanting to distinguish footnotes\n    and citations - and the only thing I can propose there is that\n    footnotes are numeric or # and citations are not (which, as a\n    human being, I can probably cope with!).\n\nFrom a reply by Paul Moore on 2002-03-01:\n\n    I think the current footnote syntax ``[1]_`` is *exactly* the\n    right balance of distinctness vs unobtrusiveness.  I very\n    definitely don't think this should change.\n\n    On the target change, it doesn't matter much to me.\n\nFrom a further reply by Tony Ibbs on 2002-03-01, referring to the\n\"[1]\" form and actual usage in email:\n\n    Clearly this is a form people are used to, and thus we should\n    consider it strongly (in the same way that the usage of ``*..*``\n    to mean emphasis was taken partly from email practise).\n\n    Equally clearly, there is something \"magical\" for people in the\n    use of a similar form (i.e., ``[1]``) for both footnote reference\n    and footnote target - it seems natural to keep them similar.\n\n    ...\n\n    I think that this established plaintext usage leads me to strongly\n    believe we should retain square brackets at both ends of a\n    footnote.  The markup of the reference end (a single trailing\n    underscore) seems about as minimal as we can get away with.  The\n    markup of the target end depends on how one envisages the thing -\n    if \"..\" means \"I am a target\" (as I tend to see it), then that's\n    good, but one can also argue that the \"_[1]\" syntax has a neat\n    symmetry with the footnote reference itself, if one wishes (in\n    which case \"..\" presumably means \"hidden/special\" as David seems\n    to think, which is why one needs a \"..\" *and* a leading underline\n    for hyperlink targets.\n\nGiven the persuading arguments voiced, we'll leave footnote & footnote\nreference syntax alone.  Except that these discussions gave rise to\nthe \"auto-symbol footnote\" concept, which has been added.  Citations\nand citation references have also been added.\n\n\nSyntax for Questions & Answers\n==============================\n\nImplement as a generic two-column marked list?  As a standalone\n(non-directive) construct?  (Is the markup ambiguous?)  Add support to\nparts.contents?\n\nNew elements would be required.  Perhaps::\n\n    <!ELEMENT question_list (question_list_item+)>\n    <!ATTLIST question_list\n        numbering  (none | local | global)\n                            #IMPLIED\n        start     NUMBER    #IMPLIED>\n    <!ELEMENT question_list_item (question, answer*)>\n    <!ELEMENT question %text.model;>\n    <!ELEMENT answer (%body.elements;)+>\n\nOriginally I thought of implementing a Q&A list with special syntax::\n\n    Q: What am I?\n\n    A: You are a question-and-answer\n       list.\n\n    Q: What are you?\n\n    A: I am the omniscient \"we\".\n\nWhere each \"Q\" and \"A\" could also be numbered (e.g., \"Q1\").  However,\na simple enumerated or bulleted list will do just fine for syntax.  A\ndirective could treat the list specially; e.g. the first paragraph\ncould be treated as a question, the remainder as the answer (multiple\nanswers could be represented by nested lists).  Without special\nsyntax, this directive becomes low priority.\n\nAs described in the FAQ__, no special syntax or directive is needed\nfor this application.\n\n__ https://docutils.sourceforge.io/FAQ.html\n   #how-can-i-mark-up-a-faq-or-other-list-of-questions-answers\n\n\n--------\n Tabled\n--------\n\nReworking Explicit Markup (Round 2)\n===================================\n\nSee `Reworking Explicit Markup (Round 1)`_ for an earlier discussion.\n\nIn April 2004, a new thread becan on docutils-develop: `Inconsistency\nin RST markup`__.  Several arguments were made; the first argument\nbegat later arguments.  Below, the arguments are paraphrased \"in\nquotes\", with responses.\n\n__ https://thread.gmane.org/gmane.text.docutils.devel/1386\n\n1. References and targets take this form::\n\n       targetname_\n\n       .. _targetname: stuff\n\n   But footnotes, \"which generate links just like targets do\", are\n   written as::\n\n       [1]_\n\n       .. [1] stuff\n\n   \"Footnotes should be written as\"::\n\n       [1]_\n\n       .. _[1]: stuff\n\n   But they're not the same type of animal.  That's not a \"footnote\n   target\", it's a *footnote*.  Being a target is not a footnote's\n   primary purpose (an arguable point).  It just happens to grow a\n   target automatically, for convenience.  Just as a section title::\n\n       Title\n       =====\n\n   isn't a \"title target\", it's a *title*, which happens to grow a\n   target automatically.  The consistency is there, it's just deeper\n   than at first glance.\n\n   Also, \".. [1]\" was chosen for footnote syntax because it closely\n   resembles one form of actual footnote rendering.  \".. _[1]:\" is too\n   verbose; excessive punctuation is required to get the job done.\n\n   For more of the reasoning behind the syntax, see `Problems With\n   StructuredText (Hyperlinks) <problems.html#hyperlinks>`__ and\n   `Reworking Footnotes`_.\n\n2. \"I expect directives to also look like ``.. this:`` [one colon]\n   because that also closely parallels the link and footnote target\n   markup.\"\n\n   There are good reasons for the two-colon syntax:\n\n       Two colons are used after the directive type for these reasons:\n\n       - Two colons are distinctive, and unlikely to be used in common\n         text.\n\n       - Two colons avoids clashes with common comment text like::\n\n             .. Danger: modify at your own risk!\n\n       - If an implementation of reStructuredText does not recognize a\n         directive (i.e., the directive-handler is not installed), a\n         level-3 (error) system message is generated, and the entire\n         directive block (including the directive itself) will be\n         included as a literal block.  Thus \"::\" is a natural choice.\n\n       -- `restructuredtext.html#directives\n       <../../ref/rst/restructuredtext.html#directives>`__\n\n   The last reason is not particularly compelling; it's more of a\n   convenient coincidence or mnemonic.\n\n3. \"Comments always seemed too easy.  I almost never write comments.\n   I'd have no problem writing '.. comment:' in front of my comments.\n   In fact, it would probably be more readable, as comments *should*\n   be set off strongly, because they are very different from normal\n   text.\"\n\n   Many people do use comments though, and some applications of\n   reStructuredText require it.  For example, all reStructuredText\n   PEPs (and this document!) have an Emacs stanza at the bottom, in a\n   comment.  Having to write \".. comment::\" would be very obtrusive.\n\n   Comments *should* be dirt-easy to do.  It should be easy to\n   \"comment out\" a block of text.  Comments in programming languages\n   and other markup languages are invariably easy.\n\n   Any author is welcome to preface their comments with \"Comment:\" or\n   \"Do Not Print\" or \"Note to Editor\" or anything they like.  A\n   \"comment\" directive could easily be implemented.  It might be\n   confused with admonition directives, like \"note\" and \"caution\"\n   though.  In unrelated (and unpublished and unfinished) work, adding\n   a \"comment\" directive as a true document element was considered::\n\n       If structure is necessary, we could use a \"comment\" directive\n       (to avoid nonsensical DTD changes, the \"comment\" directive\n       could produce an untitled topic element).\n\n4. \"One of the goals of reStructuredText is to be *readable* by people\n   who don't know it.  This construction violates that: it is not at\n   all obvious to the uninitiated that text marked by '..' is a\n   comment.  On the other hand, '.. comment:' would be totally\n   transparent.\"\n\n   Totally transparent, perhaps, but also very obtrusive.  Another of\n   `reStructuredText's goals`_ is to be unobtrusive, and\n   \".. comment::\" would violate that.  The goals of reStructuredText\n   are many, and they conflict.  Determining the right set of goals\n   and finding solutions that best fit is done on a case-by-case\n   basis.\n\n   Even readability is has two aspects.  Being readable without any\n   prior knowledge is one.  Being as easily read in raw form as in\n   processed form is the other.  \"..\" may not contribute to the former\n   aspect, but \".. comment::\" would certainly detract from the latter.\n\n   .. _author's note:\n   .. _reStructuredText's goals: ../../ref/rst/introduction.html#goals\n\n5. \"Recently I sent someone an rst document, and they got confused; I\n   had to explain to them that '..' marks comments, *unless* it's a\n   directive, etc...\"\n\n   The explanation of directives *is* roundabout, defining comments in\n   terms of not being other things.  That's definitely a wart.\n\n6. \"Under the current system, a mistyped directive (with ':' instead\n   of '::') will be silently ignored.  This is an error that could\n   easily go unnoticed.\"\n\n   A parser option/setting like \"--comments-on-stderr\" would help.\n\n7. \"I'd prefer to see double-dot-space / command / double-colon as the\n   standard Docutils markup-marker.  It's unusual enough to avoid\n   being accidentally used.  Everything that starts with a double-dot\n   should end with a double-colon.\"\n\n   That would increase the punctuation verbosity of some constructs\n   considerably.\n\n8. Edward Loper proposed the following plan for backwards\n   compatibility:\n\n       1. \".. foo\" will generate a deprecation warning to stderr, and\n          nothing in the output (no system messages).\n       2. \".. foo: bar\" will be treated as a directive foo.  If there\n          is no foo directive, then do the normal error output.\n       3. \".. foo:: bar\" will generate a deprecation warning to\n          stderr, and be treated as a directive.  Or leave it valid?\n\n       So some existing documents might start printing deprecation\n       warnings, but the only existing documents that would *break*\n       would be ones that say something like::\n\n           .. warning: this should be a comment\n\n       instead of::\n\n           .. warning:: this should be a comment\n\n       Here, we're trading fairly common a silent error (directive\n       falsely treated as a comment) for a fairly uncommon explicitly\n       flagged error (comment falsely treated as directive).  To make\n       things even easier, we could add a sentence to the\n       unknown-directive error.  Something like \"If you intended to\n       create a comment, please use '.. comment:' instead\".\n\nOn one hand, I understand and sympathize with the points raised.  On\nthe other hand, I think the current syntax strikes the right balance\n(but I acknowledge a possible lack of objectivity).  On the gripping\nhand, the comment and directive syntax has become well established, so\neven if it's a wart, it may be a wart we have to live with.\n\nMaking any of these changes would cause a lot of breakage or at least\ndeprecation warnings.  I'm not sure the benefit is worth the cost.\n\nFor now, we'll treat this as an unresolved legacy issue.\n\n\n-------\n To Do\n-------\n\nNested Inline Markup\n====================\n\nThese are collected notes on a long-discussed issue.  The original\nmailing list messages should be referred to for details.\n\n* In a 2001-10-31 discussion I wrote:\n\n      Try, for example, `Ed Loper's 2001-03-21 post`_, which details\n      some rules for nested inline markup. I think the complexity is\n      prohibitive for the marginal benefit. (And if you can understand\n      that tree without going mad, you're a better man than I. ;-)\n\n      Inline markup is already fragile. Allowing nested inline markup\n      would only be asking for trouble IMHO. If it proves absolutely\n      necessary, it can be added later. The rules for what can appear\n      inside what must be well thought out first though.\n\n      .. _Ed Loper's 2001-03-21 post:\n         https://mail.python.org/pipermail/doc-sig/2001-March/001487.html\n\n      -- https://mail.python.org/pipermail/doc-sig/2001-October/002354.html\n\n* In a 2001-11-09 Doc-SIG post, I wrote:\n\n      The problem is that in the\n      what-you-see-is-more-or-less-what-you-get markup language that\n      is reStructuredText, the symbols used for inline markup (\"*\",\n      \"**\", \"`\", \"``\", etc.) may preclude nesting.\n\n  I've rethought this position.  Nested markup is not precluded, just\n  tricky.  People and software parse \"double and 'single' quotes\" all\n  the time.  Continuing,\n\n      I've thought over how we might implement nested inline\n      markup. The first algorithm (\"first identify the outer inline\n      markup as we do now, then recursively scan for nested inline\n      markup\") won't work; counterexamples were given in my `last post\n      <https://mail.python.org/pipermail/doc-sig/2001-November/002363.html>`__.\n\n      The second algorithm makes my head hurt::\n\n          while 1:\n              scan for start-string\n              if found:\n                  push on stack\n                  scan for start or end string\n                  if new start string found:\n                      recurse\n                  elif matching end string found:\n                      pop stack\n                  elif non-matching end string found:\n                      if its a markup error:\n                          generate warning\n                      elif the initial start-string was misinterpreted:\n                          # e.g. in this case: ***strong** in emphasis*\n                          restart with the other interpretation\n                          # but it might be several layers back ...\n              ...\n\n      This is similar to how the parser does section title\n      recognition, but sections are much more regular and\n      deterministic.\n\n      Bottom line is, I don't think the benefits are worth the effort,\n      even if it is possible. I'm not going to try to write the code,\n      at least not now. If somebody codes up a consistent, working,\n      general solution, I'll be happy to consider it.\n\n      -- https://mail.python.org/pipermail/doc-sig/2001-November/002388.html\n\n* In a `2003-05-06 Docutils-Users post`__ Paul Tremblay proposed a new\n  syntax to allow for easier nesting.  It eventually evolved into\n  this::\n\n      :role:[inline text]\n\n  The duplication with the existing interpreted text syntax is\n  problematic though.\n\n  __ https://article.gmane.org/gmane.text.docutils.user/317\n\n* Could the parser be extended to parse nested interpreted text? ::\n\n      :emphasis:`Some emphasized text with :strong:`some more\n      emphasized text` in it and **perhaps** :reference:`a link``\n\n* In a `2003-06-18 Docutils-Develop post`__, Mark Nodine reported on\n  his implementation of a form of nested inline markup in his\n  Perl-based parser (unpublished).  He brought up some interesting\n  ideas.  The implementation was flawed, however, by the change in\n  semantics required for backslash escapes.\n\n  __ https://article.gmane.org/gmane.text.docutils.devel/795\n\n* Docutils-develop threads between David Abrahams, David Goodger, and\n  Mark Nodine (beginning 2004-01-16__ and 2004-01-19__) hashed out\n  many of the details of a potentially successful implementation, as\n  described below.  David Abrahams checked in code to the \"nesting\"\n  branch of CVS, awaiting thorough review.\n\n  __ https://thread.gmane.org/gmane.text.docutils.devel/1102\n  __ https://thread.gmane.org/gmane.text.docutils.devel/1125\n\nIt may be possible to accomplish nested inline markup in general with\na more powerful inline markup parser.  There may be some issues, but\nI'm not averse to the idea of nested inline markup in general.  I just\ndon't have the time or inclination to write a new parser now.  Of\ncourse, a good patch would be welcome!\n\nI envisage something like this.  Explicit-role interpreted text must\nbe nestable.  Prefix-based is probably preferred, since suffix-based\nwill look like inline literals::\n\n    ``text`:role1:`:role2:\n\nBut it can be disambiguated, so it ought to be left up to the author::\n\n    `\\ `text`:role1:`:role2:\n\nIn addition, other forms of inline markup may be nested if\nunambiguous::\n\n    *emphasized ``literal`` and |substitution ref| and link_*\n\nIOW, the parser ought to be as permissive as possible.\n\n\nIndex Entries & Indexes\n=======================\n\nWere I writing a book with an index, I guess I'd need two\ndifferent kinds of index targets: inline/implicit and\nout-of-line/explicit.  For example::\n\n    In this `paragraph`:index:, several words are being\n    `marked`:index: inline as implicit `index`:index:\n    entries.\n\n    .. index:: markup\n    .. index:: syntax\n\n    The explicit index directives above would refer to\n    this paragraph.  It might also make sense to allow multiple\n    entries in an ``index`` directive:\n\n    .. index::\n        markup\n        syntax\n\nThe words \"paragraph\", \"marked\", and \"index\" would become index\nentries pointing at the words in the first paragraph.  The index\nentry words appear verbatim in the text.  (Don't worry about the\nugly \":index:\" part; if indexing is the only/main application of\ninterpreted text in your documents, it can be implicit and\nomitted.)  The two directives provide manual indexing, where the\nindex entry words (\"markup\" and \"syntax\") do not appear in the\nmain text.  We could combine the two directives into one::\n\n    .. index:: markup; syntax\n\nSemicolons instead of commas because commas could *be* part of the\nindex target, like::\n\n    .. index:: van Rossum, Guido\n\nAnother reason for index directives is because other inline markup\nwouldn't be possible within inline index targets.\n\nSometimes index entries have multiple levels.  Given::\n\n    .. index:: statement syntax: expression statements\n\nIn a hypothetical index, combined with other entries, it might\nlook like this::\n\n    statement syntax\n        expression statements ..... 56\n        assignment ................ 57\n        simple statements ......... 58\n        compound statements ....... 60\n\nInline multi-level index targets could be done too.  Perhaps\nsomething like::\n\n    When dealing with `expression statements <statement syntax:>`,\n    we must remember ...\n\nThe opposite sense could also be possible::\n\n    When dealing with `index entries <:multi-level>`, there are\n    many permutations to consider.\n\nAlso \"see / see also\" index entries.\n\nGiven::\n\n    Here's a paragraph.\n\n    .. index:: paragraph\n\n(The \"index\" directive above actually targets the *preceding*\nobject.)  The directive should produce something like this XML::\n\n    <paragraph>\n    <index_entry text=\"paragraph\"/>\n    Here's a paragraph.\n    </paragraph>\n\nThis kind of content model would also allow true inline\nindex-entries::\n\n    Here's a `paragraph`:index:.\n\nIf the \"index\" role were the default for the application, it could be\ndropped::\n\n    Here's a `paragraph`.\n\nBoth of these would result in this XML::\n\n    <paragraph>\n    Here's a <index_entry>paragraph</index_entry>.\n    </paragraph>\n\n\nfrom 2002-06-24 docutils-develop posts\n--------------------------------------\n\n    If all of your index entries will appear verbatim in the text,\n    this should be sufficient.  If not (e.g., if you want \"Van Rossum,\n    Guido\" in the index but \"Guido van Rossum\" in the text), we'll\n    have to figure out a supplemental mechanism, perhaps using\n    substitutions.\n\nI've thought a bit more on this, and I came up with two possibilities:\n\n1. Using interpreted text, embed the index entry text within the\n   interpreted text::\n\n       ... by `Guido van Rossum [Van Rossum, Guido]` ...\n\n   The problem with this is obvious: the text becomes cluttered and\n   hard to read.  The processed output would drop the text in\n   brackets, which goes against the spirit of interpreted text.\n\n2. Use substitutions::\n\n       ... by |Guido van Rossum| ...\n\n       .. |Guido van Rossum| index:: Van Rossum, Guido\n\n   A problem with this is that each substitution definition must have\n   a unique name.  A subsequent ``.. |Guido van Rossum| index:: BDFL``\n   would be illegal.  Some kind of anonymous substitution definition\n   mechanism would be required, but I think that's going too far.\n\nBoth of these alternatives are flawed.  Any other ideas?\n\n\n-------------------\n ... Or Not To Do?\n-------------------\n\nThis is the realm of the possible but questionably probable.  These\nideas are kept here as a record of what has been proposed, for\nposterity and in case any of them prove to be useful.\n\n\nCompound Enumerated Lists\n=========================\n\nAllow for compound enumerators, such as \"1.1.\" or \"1.a.\" or \"1(a)\", to\nallow for nested enumerated lists without indentation?\n\n\nIndented Lists\n==============\n\nAllow for variant styles by interpreting indented lists as if they\nweren't indented?  For example, currently the list below will be\nparsed as a list within a block quote::\n\n    paragraph\n\n      * list item 1\n      * list item 2\n\nBut a lot of people seem to write that way, and HTML browsers make it\nlook as if that's the way it should be.  The parser could check the\ncontents of block quotes, and if they contain only a single list,\nremove the block quote wrapper.  There would be two problems:\n\n1. What if we actually *do* want a list inside a block quote?\n\n2. What if such a list comes immediately after an indented construct,\n   such as a literal block?\n\nBoth could be solved using empty comments (problem 2 already exists\nfor a block quote after a literal block).  But that's a hack.\n\nPerhaps a runtime setting, allowing or disabling this convenience,\nwould be appropriate.  But that raises issues too:\n\n    User A, who writes lists indented (and their config file is set up\n    to allow it), sends a file to user B, who doesn't (and their\n    config file disables indented lists).  The result of processing by\n    the two users will be different.\n\nIt may seem minor, but it adds ambiguity to the parser, which is bad.\n\nSee the `Doc-SIG discussion starting 2001-04-18`__ with Ed Loper's\n\"Structuring: a summary; and an attempt at EBNF\", item 4 (and\nfollow-ups, here__ and here__).  Also `docutils-users, 2003-02-17`__\nand `beginning 2003-08-04`__.\n\n__ https://mail.python.org/pipermail/doc-sig/2001-April/001776.html\n__ https://mail.python.org/pipermail/doc-sig/2001-April/001789.html\n__ https://mail.python.org/pipermail/doc-sig/2001-April/001793.html\n__ https://sourceforge.net/mailarchive/message.php?msg_id=3838913\n__ https://sf.net/mailarchive/forum.php?thread_id=2957175&forum_id=11444\n\n\nSloppy Indentation of List Items\n================================\n\nPerhaps the indentation shouldn't be so strict.  Currently, this is\nrequired::\n\n    1. First line,\n       second line.\n\nAnything wrong with this? ::\n\n    1. First line,\n     second line.\n\nProblem? ::\n\n    1. First para.\n\n       Block quote.  (no good: requires some indent relative to first\n       para)\n\n     Second Para.\n\n    2. Have to carefully define where the literal block ends::\n\n         Literal block\n\n       Literal block?\n\nHmm...  Non-strict indentation isn't such a good idea.\n\n\nLazy Indentation of List Items\n==============================\n\nAnother approach: Going back to the first draft of reStructuredText\n(2000-11-27 post to Doc-SIG)::\n\n    - This is the fourth item of the main list (no blank line above).\n    The second line of this item is not indented relative to the\n    bullet, which precludes it from having a second paragraph.\n\nChange that to *require* a blank line above and below, to reduce\nambiguity.  This \"loosening\" may be added later, once the parser's\nbeen nailed down.  However, a serious drawback of this approach is to\nlimit the content of each list item to a single paragraph.\n\n\nDavid's Idea for Lazy Indentation\n---------------------------------\n\nConsider a paragraph in a word processor.  It is a single logical line\nof text which ends with a newline, soft-wrapped arbitrarily at the\nright edge of the page or screen.  We can think of a plaintext\nparagraph in the same way, as a single logical line of text, ending\nwith two newlines (a blank line) instead of one, and which may contain\narbitrary line breaks (newlines) where it was accidentally\nhard-wrapped by an application.  We can compensate for the accidental\nhard-wrapping by \"unwrapping\" every unindented second and subsequent\nline.  The indentation of the first line of a paragraph or list item\nwould determine the indentation for the entire element.  Blank lines\nwould be required between list items when using lazy indentation.\n\nThe following example shows the lazy indentation of multiple body\nelements::\n\n    - This is the first paragraph\n    of the first list item.\n\n      Here is the second paragraph\n    of the first list item.\n\n    - This is the first paragraph\n    of the second list item.\n\n      Here is the second paragraph\n    of the second list item.\n\nA more complex example shows the limitations of lazy indentation::\n\n    - This is the first paragraph\n    of the first list item.\n\n      Next is a definition list item:\n\n      Term\n          Definition.  The indentation of the term is\n    required, as is the indentation of the definition's\n    first line.\n\n          When the definition extends to more than\n    one line, lazy indentation may occur.  (This is the second\n    paragraph of the definition.)\n\n    - This is the first paragraph\n    of the second list item.\n\n      - Here is the first paragraph of\n    the first item of a nested list.\n\n      So this paragraph would be outside of the nested list,\n    but inside the second list item of the outer list.\n\n    But this paragraph is not part of the list at all.\n\nAnd the ambiguity remains::\n\n    - Look at the hyphen at the beginning of the next line\n    - is it a second list item marker, or a dash in the text?\n\n    Similarly, we may want to refer to numbers inside enumerated\n    lists:\n\n    1. How many socks in a pair? There are\n    2. How many pants in a pair? Exactly\n    1. Go figure.\n\nLiteral blocks and block quotes would still require consistent\nindentation for all their lines.  For block quotes, we might be able\nto get away with only requiring that the first line of each contained\nelement be indented.  For example::\n\n    Here's a paragraph.\n\n        This is a paragraph inside a block quote.\n    Second and subsequent lines need not be indented at all.\n\n        - A bullet list inside\n    the block quote.\n\n          Second paragraph of the\n    bullet list inside the block quote.\n\nAlthough feasible, this form of lazy indentation has problems.  The\ndocument structure and hierarchy is not obvious from the indentation,\nmaking the source plaintext difficult to read.  This will also make\nkeeping track of the indentation while writing difficult and\nerror-prone.  However, these problems may be acceptable for Wikis and\nemail mode, where we may be able to rely on less complex structure\n(few nested lists, for example).\n\n\nMultiple Roles in Interpreted Text\n==================================\n\nIn reStructuredText, inline markup cannot be nested (yet; `see\nabove`__).  This also applies to interpreted text.  In order to\nsimultaneously combine multiple roles for a single piece of text, a\nsyntax extension would be necessary.  Ideas:\n\n1. Initial idea::\n\n       `interpreted text`:role1,role2:\n\n2. Suggested by Jason Diamond::\n\n       `interpreted text`:role1:role2:\n\nIf a document is so complex as to require nested inline markup,\nperhaps another markup system should be considered.  By design,\nreStructuredText does not have the flexibility of XML.\n\n__ `Nested Inline Markup`_\n\n\nParameterized Interpreted Text\n==============================\n\nIn some cases it may be expedient to pass parameters to interpreted\ntext, analogous to function calls.  Ideas:\n\n1. Parameterize the interpreted text role itself (suggested by Jason\n   Diamond)::\n\n       `interpreted text`:role1(foo=bar):\n\n   Positional parameters could also be supported::\n\n       `CSS`:acronym(Cascading Style Sheets): is used for HTML, and\n       `CSS`:acronym(Content Scrambling System): is used for DVDs.\n\n   Technical problem: current interpreted text syntax does not\n   recognize roles containing whitespace.  Design problem: this smells\n   like programming language syntax, but reStructuredText is not a\n   programming language.\n\n2. Put the parameters inside the interpreted text::\n\n       `CSS (Cascading Style Sheets)`:acronym: is used for HTML, and\n       `CSS (Content Scrambling System)`:acronym: is used for DVDs.\n\n   Although this could be defined on an individual basis (per role),\n   we ought to have a standard.  Hyperlinks with embedded URIs already\n   use angle brackets; perhaps they could be used here too::\n\n       `CSS <Cascading Style Sheets>`:acronym: is used for HTML, and\n       `CSS <Content Scrambling System>`:acronym: is used for DVDs.\n\n   Do angle brackets connote URLs too much for this to be acceptable?\n   How about the \"tag\" connotation -- does it save them or doom them?\n\n3. `Nested inline markup`_ could prove useful here::\n\n       `CSS :def:`Cascading Style Sheets``:acronym: is used for HTML,\n       and `CSS :def:`Content Scrambling System``:acronym: is used for\n       DVDs.\n\n   Inline markup roles could even define the default roles of nested\n   inline markup, allowing this cleaner syntax::\n\n       `CSS `Cascading Style Sheets``:acronym: is used for HTML, and\n       `CSS `Content Scrambling System``:acronym: is used for DVDs.\n\nDoes this push inline markup too far?  Readability becomes a serious\nissue.  Substitutions may provide a better alternative (at the expense\nof verbosity and duplication) by pulling the details out of the text\nflow::\n\n    |CSS| is used for HTML, and |CSS-DVD| is used for DVDs.\n\n    .. |CSS| acronym:: Cascading Style Sheets\n    .. |CSS-DVD| acronym:: Content Scrambling System\n       :text: CSS\n\n----------------------------------------------------------------------\n\nThis whole idea may be going beyond the scope of reStructuredText.\nDocuments requiring this functionality may be better off using XML or\nanother markup system.\n\nThis argument comes up regularly when pushing the envelope of\nreStructuredText syntax.  I think it's a useful argument in that it\nprovides a check on creeping featurism.  In many cases, the resulting\nverbosity produces such unreadable plaintext that there's a natural\ndesire *not* to use it unless absolutely necessary.  It's a matter of\nfinding the right balance.\n\n\nSyntax for Interpreted Text Role Bindings\n=========================================\n\nThe following syntax (idea from Jeffrey C. Jacobs) could be used to\nassociate directives with roles::\n\n    .. :rewrite: class:: rewrite\n\n    `She wore ribbons in her hair and it lay with streaks of\n    grey`:rewrite:\n\nThe syntax is similar to that of substitution declarations, and the\ndirective/role association may resolve implementation issues.  The\nsemantics, ramifications, and implementation details would need to be\nworked out.\n\nThe example above would implement the \"rewrite\" role as adding a\n``class=\"rewrite\"`` attribute to the interpreted text (\"inline\"\nelement).  The stylesheet would then pick up on the \"class\" attribute\nto do the actual formatting.\n\nThe advantage of the new syntax would be flexibility.  Uses other than\n\"class\" may present themselves.  The disadvantage is complexity:\nhaving to implement new syntax for a relatively specialized operation,\nand having new semantics in existing directives (\"class::\" would do\nsomething different).\n\nThe `\"role\" directive`__ has been implemented.\n\n__ ../../ref/rst/directives.html#role\n\n\nCharacter Processing\n====================\n\nSeveral people have suggested adding some form of character processing\nto reStructuredText:\n\n* Some sort of automated replacement of ASCII sequences:\n\n  - ``--`` to em-dash (or ``--`` to en-dash, and ``---`` to em-dash).\n  - Convert quotes to curly quote entities.  (Essentially impossible\n    for HTML?  Unnecessary for TeX.)\n  - Various forms of ``:-)`` to smiley icons.\n  - ``\"\\ \"`` to &nbsp;.  Problem with line-wrapping though: it could\n    end up escaping the newline.\n  - Escaped newlines to <BR>.\n  - Escaped period or quote or dash as a disappearing catalyst to\n    allow character-level inline markup?\n\n* XML-style character entities, such as \"&copy;\" for the copyright\n  symbol.\n\nDocutils has no need of a character entity subsystem.  Supporting\nUnicode and text encodings, character entities should be directly\nrepresented in the text: a copyright symbol should be represented by\nthe copyright symbol character.  If this is not possible in an\nauthoring environment, a pre-processing stage can be added, or a table\nof substitution definitions can be devised.\n\nA \"unicode\" directive has been implemented to allow direct\nspecification of esoteric characters.  In combination with the\nsubstitution construct, \"include\" files defining common sets of\ncharacter entities can be defined and used.  `A set of character\nentity set definition files have been defined`__ (`tarball`__).\nThere's also `a description and instructions for use`__.\n\n__ https://docutils.sourceforge.io/tmp/charents/\n__ https://docutils.sourceforge.io/tmp/charents.tgz\n__ https://docutils.sourceforge.io/tmp/charents/README.html\n\nTo allow for `character-level inline markup`_, a limited form of\ncharacter processing has been added to the spec and parser: escaped\nwhitespace characters are removed from the processed document.  Any\nfurther character processing will be of this functional type, rather\nthan of the character-encoding type.\n\n.. _character-level inline markup:\n   ../../ref/rst/restructuredtext.html#character-level-inline-markup\n\n* Directive idea::\n\n      .. text-replace:: \"pattern\" \"replacement\"\n\n  - Support Unicode \"U+XXXX\" codes.\n  - Support regexps, perhaps with alternative \"regexp-replace\"\n    directive.\n  - Flags for regexps; \":flags:\" option, or individuals.\n  - Specifically, should the default be case-sensistive or\n    -insensitive?\n\n\nPage Or Line Breaks\n===================\n\n* Should ^L (or something else in reST) be defined to mean\n  force/suggest page breaks in whatever output we have?\n\n  A \"break\" or \"page-break\" directive would be easy to add.  A new\n  doctree element would be required though (perhaps \"break\").  The\n  final behavior would be up to the Writer.  The directive argument\n  could be one of page/column/recto/verso for added flexibility.\n\n  Currently ^L (Python's ``\\f``) characters are treated as whitespace.\n  They're converted to single spaces, actually, as are vertical tabs\n  (^K, Python's ``\\v``).  It would be possible to recognize form feeds\n  as markup, but it requires some thought and discussion first.  Are\n  there any downsides?  Many editing environments do not allow the\n  insertion of control characters.  Will it cause any harm?  It would\n  be useful as a shorthand for the directive.\n\n  It's common practice to use ^L before Emacs \"Local Variables\"\n  lists::\n\n      ^L\n      ..\n         Local Variables:\n         mode: indented-text\n         indent-tabs-mode: nil\n         sentence-end-double-space: t\n         fill-column: 70\n         End:\n\n  These are already present in many PEPs and Docutils project\n  documents.  From the Emacs manual (info):\n\n      A \"local variables list\" goes near the end of the file, in the\n      last page.  (It is often best to put it on a page by itself.)\n\n  It would be unfortunate if this construct caused a final blank page\n  to be generated (for those Writers that recognize the page breaks).\n  We'll have to add a transform that looks for a \"break\" plus zero or\n  more comments at the end of a document, and removes them.\n\n  Probably a bad idea because there is no such thing as a page in a\n  generic document format.\n\n* Could the \"break\" concept above be extended to inline forms?\n  E.g. \"^L\" in the middle of a sentence could cause a line break.\n  Only recognize it at the end of a line (i.e., ``\\f\\n``)?\n\n  Or is formfeed inappropriate?  Perhaps vertical tab (``\\v``), but\n  even that's a stretch.  Can't use carriage returns, since they're\n  commonly used for line endings.\n\n  Probably a bad idea as well because we do not want to use control\n  characters for well-readable and well-writable markup, and after all\n  we have the line block syntax for line breaks.\n\n\nSuperscript Markup\n==================\n\nAdd ``^superscript^`` inline markup?  The only common non-markup uses\nof \"^\" I can think of are as short hand for \"superscript\" itself and\nfor describing control characters (\"^C to cancel\").  The former\nsupports the proposed syntax, and it could be argued that the latter\nought to be literal text anyhow (e.g. \"``^C`` to cancel\").\n\nHowever, superscripts are seldom needed, and new syntax would break\nexisting documents.  When it's needed, the ``:superscript:``\n(``:sup:``) role can we used as well.\n\n\nCode Execution\n==============\n\nAdd the following directives?\n\n- \"exec\": Execute Python code & insert the results.  Call it\n  \"python\" to allow for other languages?\n\n- \"system\": Execute an ``os.system()`` call, and insert the results\n  (possibly as a literal block).  Definitely dangerous!  How to make\n  it safe?  Perhaps such processing should be left outside of the\n  document, in the user's production system (a makefile or a script or\n  whatever).  Or, the directive could be disabled by default and only\n  enabled with an explicit command-line option or config file setting.\n  Even then, an interactive prompt may be useful, such as:\n\n      The file.txt document you are processing contains a \"system\"\n      directive requesting that the ``sudo rm -rf /`` command be\n      executed.  Allow it to execute?  (y/N)\n\n- \"eval\": Evaluate an expression & insert the text.  At parse\n  time or at substitution time?  Dangerous?  Perhaps limit to canned\n  macros; see text.date_.\n\n  .. _text.date: ../todo.html#text-date\n\nIt's too dangerous (or too complicated in the case of \"eval\").  We do\nnot want to have such things in the core.\n\n\n``encoding`` Directive\n======================\n\nAdd an \"encoding\" directive to specify the character encoding of the\ninput data?  Not a good idea for the following reasons:\n\n- When it sees the directive, the parser will already have read the\n  input data, and encoding determination will already have been done.\n\n- If a file with an \"encoding\" directive is edited and saved with\n  a different encoding, the directive may cause data corruption.\n\n\nSupport for Annotations\n=======================\n\nAdd an \"annotation\" role, as the equivalent of the HTML \"title\"\nattribute?  This is secondary information that may \"pop up\" when the\npointer hovers over the main text.  A corresponding directive would be\nrequired to associate annotations with the original text (by name, or\npositionally as in anonymous targets?).\n\nThere have not been many requests for such feature, though.  Also,\ncluttering WYSIWYG plaintext with annotations may not seem like a good\nidea, and there is no \"tool tip\" in formats other than HTML.\n\n\n``term`` Role\n=============\n\nAdd a \"term\" role for unfamiliar or specialized terminology?  Probably\nnot; there is no real use case, and emphasis is enough for most cases.\n\n\nObject references\n=================\n\nWe need syntax for `object references`_.\n\n  - Parameterized substitutions?  For example::\n\n        See |figure (figure name)| on |page (figure name)|.\n\n        .. |figure (name)| figure-ref:: (name)\n        .. |page (name)| page-ref:: (name)\n\n    The result would be::\n\n        See figure 3.11 on page 157.\n\n    But this would require substitution directives to be processed at\n    reference-time, not at definition-time as they are now.  Or,\n    perhaps the directives could just leave ``pending`` elements\n    behind, and the transforms do the work?  How to pass the data\n    through? Too complicated. Use interpreted text roles.\n\n.. _object references:\n   ../todo.html#object-numbering-and-object-references\n\n\f\n..\n   Local Variables:\n   mode: indented-text\n   indent-tabs-mode: nil\n   sentence-end-double-space: t\n   fill-column: 70\n   End:\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/docutils_data/docs/dev/rst/problems.txt",
    "content": "==============================\n Problems With StructuredText\n==============================\n:Author: David Goodger\n:Contact: docutils-develop@lists.sourceforge.net\n:Revision: $Revision$\n:Date: $Date$\n:Copyright: This document has been placed in the public domain.\n\nThere are several problems, unresolved issues, and areas of\ncontroversy within StructuredText_ (Classic and Next Generation).  In\norder to resolve all these issues, this analysis brings all of the\nissues out into the open, enumerates all the alternatives, and\nproposes solutions to be incorporated into the reStructuredText_\nspecification.\n\n\n.. contents::\n\n\nFormal Specification\n====================\n\nThe description in the original StructuredText.py has been criticized\nfor being vague.  For practical purposes, \"the code *is* the spec.\"\nTony Ibbs has been working on deducing a `detailed description`_ from\nthe documentation and code of StructuredTextNG_.  Edward Loper's\nSTMinus_ is another attempt to formalize a spec.\n\nFor this kind of a project, the specification should always precede\nthe code.  Otherwise, the markup is a moving target which can never be\nadopted as a standard.  Of course, a specification may be revised\nduring lifetime of the code, but without a spec there is no visible\ncontrol and thus no confidence.\n\n\nUnderstanding and Extending the Code\n====================================\n\nThe original StructuredText_ is a dense mass of sparsely commented\ncode and inscrutable regular expressions.  It was not designed to be\nextended and is very difficult to understand.  StructuredTextNG_ has\nbeen designed to allow input (syntax) and output extensions, but its\ndocumentation (both internal [comments & docstrings], and external) is\ninadequate for the complexity of the code itself.\n\nFor reStructuredText to become truly useful, perhaps even part of\nPython's standard library, it must have clear, understandable\ndocumentation and implementation code.  For the implementation of\nreStructuredText to be taken seriously, it must be a sterling example\nof the potential of docstrings; the implementation must practice what\nthe specification preaches.\n\n\nSection Structure via Indentation\n=================================\n\nSetext_ required that body text be indented by 2 spaces.  The original\nStructuredText_ and StructuredTextNG_ require that section structure\nbe indicated through indentation, as \"inspired by Python\".  For\ncertain structures with a very limited, local extent (such as lists,\nblock quotes, and literal blocks), indentation naturally indicates\nstructure or hierarchy.  For sections (which may have a very large\nextent), structure via indentation is unnecessary, unnatural and\nambiguous.  Rather, the syntax of the section title *itself* should\nindicate that it is a section title.\n\nThe original StructuredText states that \"A single-line paragraph whose\nimmediately succeeding paragraphs are lower level is treated as a\nheader.\" Requiring indentation in this way is:\n\n- Unnecessary.  The vast majority of docstrings and standalone\n  documents will have no more than one level of section structure.\n  Requiring indentation for such docstrings is unnecessary and\n  irritating.\n\n- Unnatural.  Most published works use title style (type size, face,\n  weight, and position) and/or section/subsection numbering rather\n  than indentation to indicate hierarchy.  This is a tradition with a\n  very long history.\n\n- Ambiguous.  A StructuredText header is indistinguishable from a\n  one-line paragraph followed by a block quote (precluding the use of\n  block quotes).  Enumerated section titles are ambiguous (is it a\n  header? is it a list item?).  Some additional adornment must be\n  required to confirm the line's role as a title, both to a parser and\n  to the human reader of the source text.\n\nPython's use of significant whitespace is a wonderful (if not\noriginal) innovation, however requiring indentation in ordinary\nwritten text is hypergeneralization.\n\nreStructuredText_ indicates section structure through title adornment\nstyle (as exemplified by this document).  This is far more natural.\nIn fact, it is already in widespread use in plain text documents,\nincluding in Python's standard distribution (such as the toplevel\nREADME_ file).\n\n\nCharacter Escaping Mechanism\n============================\n\nNo matter what characters are chosen for markup, some day someone will\nwant to write documentation *about* that markup or using markup\ncharacters in a non-markup context.  Therefore, any complete markup\nlanguage must have an escaping or encoding mechanism.  For a\nlightweight markup system, encoding mechanisms like SGML/XML's '&ast;'\nare out.  So an escaping mechanism is in.  However, with carefully\nchosen markup, it should be necessary to use the escaping mechanism\nonly infrequently.\n\nreStructuredText_ needs an escaping mechanism: a way to treat\nmarkup-significant characters as the characters themselves.  Currently\nthere is no such mechanism (although ZWiki uses '!').  What are the\ncandidates?\n\n1. ``!``\n   (http://www.zope.org/DevHome/Members/jim/StructuredTextWiki/NGEscaping)\n2. ``\\``\n3. ``~``\n4. doubling of characters\n\nThe best choice for this is the backslash (``\\``).  It's \"the single\nmost popular escaping character in the world!\", therefore familiar and\nunsurprising.  Since characters only need to be escaped under special\ncircumstances, which are typically those explaining technical\nprogramming issues, the use of the backslash is natural and\nunderstandable.  Python docstrings can be raw (prefixed with an 'r',\nas in 'r\"\"'), which would obviate the need for gratuitous doubling-up\nof backslashes.\n\n(On 2001-03-29 on the Doc-SIG mailing list, GvR endorsed backslash\nescapes, saying, \"'nuff said.  Backslash it is.\" Although neither\nlegally binding nor irrevocable nor any kind of guarantee of anything,\nit is a good sign.)\n\nThe rule would be: An unescaped backslash followed by any markup\ncharacter escapes the character.  The escaped character represents the\ncharacter itself, and is prevented from playing a role in any markup\ninterpretation.  The backslash is removed from the output.  A literal\nbackslash is represented by an \"escaped backslash,\" two backslashes in\na row.\n\nA carefully constructed set of recognition rules for inline markup\nwill obviate the need for backslash-escapes in almost all cases; see\n`Delimitation of Inline Markup`_ below.\n\nWhen an expression (requiring backslashes and other characters used\nfor markup) becomes too complicated and therefore unreadable, a\nliteral block may be used instead.  Inside literal blocks, no markup\nis recognized, therefore backslashes (for the purpose of escaping\nmarkup) become unnecessary.\n\nWe could allow backslashes preceding non-markup characters to remain\nin the output.  This would make describing regular expressions and\nother uses of backslashes easier.  However, this would complicate the\nmarkup rules and would be confusing.\n\n\nBlank Lines in Lists\n====================\n\nOft-requested in Doc-SIG (the earliest reference is dated 1996-08-13)\nis the ability to write lists without requiring blank lines between\nitems.  In docstrings, space is at a premium.  Authors want to convey\ntheir API or usage information in as compact a form as possible.\nStructuredText_ requires blank lines between all body elements,\nincluding list items, even when boundaries are obvious from the markup\nitself.\n\nIn reStructuredText, blank lines are optional between list items.\nHowever, in order to eliminate ambiguity, a blank line is required\nbefore the first list item and after the last.  Nested lists also\nrequire blank lines before the list start and after the list end.\n\n\nBullet List Markup\n==================\n\nStructuredText_ includes 'o' as a bullet character.  This is dangerous\nand counter to the language-independent nature of the markup.  There\nare many languages in which 'o' is a word.  For example, in Spanish::\n\n    Llamame a la casa\n    o al trabajo.\n\n    (Call me at home or at work.)\n\nAnd in Japanese (when romanized)::\n\n    Senshuu no doyoubi ni tegami\n    o kakimashita.\n\n    ([I] wrote a letter on Saturday last week.)\n\nIf a paragraph containing an 'o' word wraps such that the 'o' is the\nfirst text on a line, or if a paragraph begins with such a word, it\ncould be misinterpreted as a bullet list.\n\nIn reStructuredText_, 'o' is not used as a bullet character.  '-',\n'*', and '+' are the possible bullet characters.\n\n\nEnumerated List Markup\n======================\n\nStructuredText enumerated lists are allowed to begin with numbers and\nletters followed by a period or right-parenthesis, then whitespace.\nThis has surprising consequences for writing styles.  For example,\nthis is recognized as an enumerated list item by StructuredText::\n\n    Mr. Creosote.\n\nPeople will write enumerated lists in all different ways.  It is folly\nto try to come up with the \"perfect\" format for an enumerated list,\nand limit the docstring parser's recognition to that one format only.\n\nRather, the parser should recognize a variety of enumerator styles.\nIt is also recommended that the enumerator of the first list item be\nordinal-1 ('1', 'A', 'a', 'I', or 'i'), as output formats may not be\nable to begin a list at an arbitrary enumeration.\n\nAn initial idea was to require two or more consistent enumerated list\nitems in a row.  This idea proved impractical and was dropped.  In\npractice, the presence of a proper enumerator is enough to reliably\nrecognize an enumerated list item; any ambiguities are reported by the\nparser.  Here's the original idea for posterity:\n\n    The parser should recognize a variety of enumerator styles, mark\n    each block as a potential enumerated list item (PELI), and\n    interpret the enumerators of adjacent PELIs to decide whether they\n    make up a consistent enumerated list.\n\n    If a PELI is labeled with a \"1.\", and is immediately followed by a\n    PELI labeled with a \"2.\", we've got an enumerated list.  Or \"(A)\"\n    followed by \"(B)\".  Or \"i)\" followed by \"ii)\", etc.  The chances\n    of accidentally recognizing two adjacent and consistently labeled\n    PELIs, are acceptably small.\n\n    For an enumerated list to be recognized, the following must be\n    true:\n\n    - the list must consist of multiple adjacent list items (2 or\n      more)\n    - the enumerators must all have the same format\n    - the enumerators must be sequential\n\n\nDefinition List Markup\n======================\n\nStructuredText uses ' -- ' (whitespace, two hyphens, whitespace) on\nthe first line of a paragraph to indicate a definition list item.  The\n' -- ' serves to separate the term (on the left) from the definition\n(on the right).\n\nMany people use ' -- ' as an em-dash in their text, conflicting with\nthe StructuredText usage.  Although the Chicago Manual of Style says\nthat spaces should not be used around an em-dash, Peter Funk pointed\nout that this is standard usage in German (according to the Duden, the\nofficial German reference), and possibly in other languages as well.\nThe widespread use of ' -- ' precludes its use for definition lists;\nit would violate the \"unsurprising\" criterion.\n\nA simpler, and at least equally visually distinctive construct\n(proposed by Guido van Rossum, who incidentally is a frequent user of\n' -- ') would do just as well::\n\n    term 1\n        Definition.\n\n    term 2\n        Definition 2, paragraph 1.\n\n        Definition 2, paragraph 2.\n\nA reStructuredText definition list item consists of a term and a\ndefinition.  A term is a simple one-line paragraph.  A definition is a\nblock indented relative to the term, and may contain multiple\nparagraphs and other body elements.  No blank line precedes a\ndefinition (this distinguishes definition lists from block quotes).\n\n\nLiteral Blocks\n==============\n\nThe StructuredText_ specification has literal blocks indicated by\n'example', 'examples', or '::' ending the preceding paragraph.  STNG\nonly recognizes '::'; 'example'/'examples' are not implemented.  This\nis good; it fixes an unnecessary language dependency.  The problem is\nwhat to do with the sometimes- unwanted '::'.\n\nIn reStructuredText_ '::' at the end of a paragraph indicates that\nsubsequent *indented* blocks are treated as literal text.  No further\nmarkup interpretation is done within literal blocks (not even\nbackslash-escapes).  If the '::' is preceded by whitespace, '::' is\nomitted from the output; if '::' was the sole content of a paragraph,\nthe entire paragraph is removed (no 'empty' paragraph remains).  If\n'::' is preceded by a non-whitespace character, '::' is replaced by\n':' (i.e., the extra colon is removed).\n\nThus, a section could begin with a literal block as follows::\n\n    Section Title\n    -------------\n\n    ::\n\n        print \"this is example literal\"\n\n\nTables\n======\n\nThe table markup scheme in classic StructuredText was horrible.  Its\nomission from StructuredTextNG is welcome, and its markup will not be\nrepeated here.  However, tables themselves are useful in\ndocumentation.  Alternatives:\n\n1. This format is the most natural and obvious.  It was independently\n   invented (no great feat of creation!), and later found to be the\n   format supported by the `Emacs table mode`_::\n\n       +------------+------------+------------+--------------+\n       |  Header 1  |  Header 2  |  Header 3  |  Header 4    |\n       +============+============+============+==============+\n       |  Column 1  |  Column 2  | Column 3 & 4 span (Row 1) |\n       +------------+------------+------------+--------------+\n       |    Column 1 & 2 span    |  Column 3  | - Column 4   |\n       +------------+------------+------------+ - Row 2 & 3  |\n       |      1     |      2     |      3     | - span       |\n       +------------+------------+------------+--------------+\n\n   Tables are described with a visual outline made up of the\n   characters '-', '=', '|', and '+':\n\n   - The hyphen ('-') is used for horizontal lines (row separators).\n   - The equals sign ('=') is optionally used as a header separator\n     (as of version 1.5.24, this is not supported by the Emacs table\n     mode).\n   - The vertical bar ('|') is used for for vertical lines (column\n     separators).\n   - The plus sign ('+') is used for intersections of horizontal and\n     vertical lines.\n\n   Row and column spans are possible simply by omitting the column or\n   row separators, respectively.  The header row separator must be\n   complete; in other words, a header cell may not span into the table\n   body.  Each cell contains body elements, and may have multiple\n   paragraphs, lists, etc.  Initial spaces for a left margin are\n   allowed; the first line of text in a cell determines its left\n   margin.\n\n2. Below is a simpler table structure.  It may be better suited to\n   manual input than alternative #1, but there is no Emacs editing\n   mode available.  One disadvantage is that it resembles section\n   titles; a one-column table would look exactly like section &\n   subsection titles. ::\n\n       ============ ============ ============ ==============\n         Header 1     Header 2     Header 3     Header 4\n       ============ ============ ============ ==============\n         Column 1     Column 2    Column 3 & 4 span (Row 1)\n       ------------ ------------ ---------------------------\n           Column 1 & 2 span       Column 3    - Column 4\n       ------------------------- ------------  - Row 2 & 3\n             1            2            3       - span\n       ============ ============ ============ ==============\n\n   The table begins with a top border of equals signs with a space at\n   each column boundary (regardless of spans).  Each row is\n   underlined.  Internal row separators are underlines of '-', with\n   spaces at column boundaries.  The last of the optional head rows is\n   underlined with '=', again with spaces at column boundaries.\n   Column spans have no spaces in their underline.  Row spans simply\n   lack an underline at the row boundary.  The bottom boundary of the\n   table consists of '=' underlines.  A blank line is required\n   following a table.\n\n3. A minimalist alternative is as follows::\n\n       ====  =====  ========  ========  =======  ====  =====  =====\n       Old State    Input     Action             New State    Notes\n       -----------  --------  -----------------  -----------\n       ids   types  new type  sys.msg.  dupname  ids   types\n       ====  =====  ========  ========  =======  ====  =====  =====\n       --    --     explicit  --        --       new   True\n       --    --     implicit  --        --       new   False\n       None  False  explicit  --        --       new   True\n       old   False  explicit  implicit  old      new   True\n       None  True   explicit  explicit  new      None  True\n       old   True   explicit  explicit  new,old  None  True   [1]\n       None  False  implicit  implicit  new      None  False\n       old   False  implicit  implicit  new,old  None  False\n       None  True   implicit  implicit  new      None  True\n       old   True   implicit  implicit  new      old   True\n       ====  =====  ========  ========  =======  ====  =====  =====\n\n   The table begins with a top border of equals signs with one or more\n   spaces at each column boundary (regardless of spans).  There must\n   be at least two columns in the table (to differentiate it from\n   section headers).  Each line starts a new row.  The rightmost\n   column is unbounded; text may continue past the edge of the table.\n   Each row/line must contain spaces at column boundaries, except for\n   explicit column spans.  Underlines of '-' can be used to indicate\n   column spans, but should be used sparingly if at all.  Lines\n   containing column span underlines may not contain any other text.\n   The last of the optional head rows is underlined with '=', again\n   with spaces at column boundaries.  The bottom boundary of the table\n   consists of '=' underlines.  A blank line is required following a\n   table.\n\n   This table sums up the features.  Using all the features in such a\n   small space is not pretty though::\n\n       ========  ========  ========\n                 Header 2 & 3 Span\n                 ------------------\n       Header 1  Header 2  Header 3\n       ========  ========  ========\n       Each      line is   a new row.\n       Each row  consists  of one line only.\n       Row       spans     are not possible.\n       The last  column    may spill over to the right.\n       Column spans are possible with an underline joining columns.\n       ----------------------------\n       The span  is        limited to the row above the underline.\n       ========  ========  ========\n\n4. As a variation of alternative 3, bullet list syntax in the first\n   column could be used to indicate row starts.  Multi-line rows are\n   possible, but row spans are not.  For example::\n\n       ===== =====\n       col 1 col 2\n       ===== =====\n       - 1   Second column of row 1.\n       - 2   Second column of row 2.\n             Second line of paragraph.\n       - 3   Second column of row 3.\n\n             Second paragraph of row 3,\n             column 2\n       ===== =====\n\n   Column spans would be indicated on the line after the last line of\n   the row.  To indicate a real bullet list within a first-column\n   cell, simply nest the bullets.\n\n5. In a further variation, we could simply assume that whitespace in\n   the first column implies a multi-line row; the text in other\n   columns is continuation text.  For example::\n\n       ===== =====\n       col 1 col 2\n       ===== =====\n       1     Second column of row 1.\n       2     Second column of row 2.\n             Second line of paragraph.\n       3     Second column of row 3.\n\n             Second paragraph of row 3,\n             column 2\n       ===== =====\n\n   Limitations of this approach:\n\n   - Cells in the first column are limited to one line of text.\n\n   - Cells in the first column *must* contain some text; blank cells\n     would lead to a misinterpretation.  An empty comment (\"..\") is\n     sufficient.\n\n6. Combining alternative 3 and 4, a bullet list in the first column\n   could mean multi-line rows, and no bullet list means single-line\n   rows only.\n\nAlternatives 1 and 5 has been adopted by reStructuredText.\n\n\nDelimitation of Inline Markup\n=============================\n\nStructuredText specifies that inline markup must begin with\nwhitespace, precluding such constructs as parenthesized or quoted\nemphatic text::\n\n    \"**What?**\" she cried.  (*exit stage left*)\n\nThe `reStructuredText markup specification`_ allows for such\nconstructs and disambiguates inline markup through a set of\nrecognition rules.  These recognition rules define the context of\nmarkup start-strings and end-strings, allowing markup characters to be\nused in most non-markup contexts without a problem (or a backslash).\nSo we can say, \"Use asterisks (*) around words or phrases to\n*emphasisze* them.\" The '(*)' will not be recognized as markup.  This\nreduces the need for markup escaping to the point where an escape\ncharacter is *almost* (but not quite!) unnecessary.\n\n\nUnderlining\n===========\n\nStructuredText uses '_text_' to indicate underlining.  To quote David\nAscher in his 2000-01-21 Doc-SIG mailing list post, \"Docstring\ngrammar: a very revised proposal\":\n\n    The tagging of underlined text with _'s is suboptimal.  Underlines\n    shouldn't be used from a typographic perspective (underlines were\n    designed to be used in manuscripts to communicate to the\n    typesetter that the text should be italicized -- no well-typeset\n    book ever uses underlines), and conflict with double-underscored\n    Python variable names (__init__ and the like), which would get\n    truncated and underlined when that effect is not desired.  Note\n    that while *complete* markup would prevent that truncation\n    ('__init__'), I think of docstring markups much like I think of\n    type annotations -- they should be optional and above all do no\n    harm.  In this case the underline markup does harm.\n\nUnderlining is not part of the reStructuredText specification.\n\n\nInline Literals\n===============\n\nStructuredText's markup for inline literals (text left as-is,\nverbatim, usually in a monospaced font; as in HTML <TT>) is single\nquotes ('literals').  The problem with single quotes is that they are\ntoo often used for other purposes:\n\n- Apostrophes: \"Don't blame me, 'cause it ain't mine, it's Chris'.\";\n\n- Quoting text:\n\n      First Bruce: \"Well Bruce, I heard the prime minister use it.\n      'S'hot enough to boil a monkey's bum in 'ere your Majesty,' he\n      said, and she smiled quietly to herself.\"\n\n  In the UK, single quotes are used for dialogue in published works.\n\n- String literals: s = ''\n\nAlternatives::\n\n    'text'    \\'text\\'    ''text''    \"text\"    \\\"text\\\"    \"\"text\"\"\n    #text#     @text@      `text`     ^text^    ``text''    ``text``\n\nThe examples below contain inline literals, quoted text, and\napostrophes.  Each example should evaluate to the following HTML::\n\n    Some <TT>code</TT>, with a 'quote', \"double\", ain't it grand?\n    Does <TT>a[b] = 'c' + \"d\" + `2^3`</TT> work?\n\n    0. Some code, with a quote, double, ain't it grand?\n       Does a[b] = 'c' + \"d\" + `2^3` work?\n    1. Some 'code', with a \\'quote\\', \"double\", ain\\'t it grand?\n       Does 'a[b] = \\'c\\' + \"d\" + `2^3`' work?\n    2. Some \\'code\\', with a 'quote', \"double\", ain't it grand?\n       Does \\'a[b] = 'c' + \"d\" + `2^3`\\' work?\n    3. Some ''code'', with a 'quote', \"double\", ain't it grand?\n       Does ''a[b] = 'c' + \"d\" + `2^3`'' work?\n    4. Some \"code\", with a 'quote', \\\"double\\\", ain't it grand?\n       Does \"a[b] = 'c' + \"d\" + `2^3`\" work?\n    5. Some \\\"code\\\", with a 'quote', \"double\", ain't it grand?\n       Does \\\"a[b] = 'c' + \"d\" + `2^3`\\\" work?\n    6. Some \"\"code\"\", with a 'quote', \"double\", ain't it grand?\n       Does \"\"a[b] = 'c' + \"d\" + `2^3`\"\" work?\n    7. Some #code#, with a 'quote', \"double\", ain't it grand?\n       Does #a[b] = 'c' + \"d\" + `2^3`# work?\n    8. Some @code@, with a 'quote', \"double\", ain't it grand?\n       Does @a[b] = 'c' + \"d\" + `2^3`@ work?\n    9. Some `code`, with a 'quote', \"double\", ain't it grand?\n       Does `a[b] = 'c' + \"d\" + \\`2^3\\`` work?\n    10. Some ^code^, with a 'quote', \"double\", ain't it grand?\n        Does ^a[b] = 'c' + \"d\" + `2\\^3`^ work?\n    11. Some ``code'', with a 'quote', \"double\", ain't it grand?\n        Does ``a[b] = 'c' + \"d\" + `2^3`'' work?\n    12. Some ``code``, with a 'quote', \"double\", ain't it grand?\n        Does ``a[b] = 'c' + \"d\" + `2^3\\``` work?\n\nBackquotes (#9 & #12) are the best choice.  They are unobtrusive and\nrelatviely rarely used (more rarely than ' or \", anyhow).  Backquotes\nhave the connotation of 'quotes', which other options (like carets,\n#10) don't.\n\nAnalogously with ``*emph*`` & ``**strong**``, double-backquotes (#12)\ncould be used for inline literals.  If single-backquotes are used for\n'interpreted text' (context-sensitive domain-specific descriptive\nmarkup) such as function name hyperlinks in Python docstrings, then\ndouble-backquotes could be used for absolute-literals, wherein no\nprocessing whatsoever takes place.  An advantage of double-backquotes\nwould be that backslash-escaping would no longer be necessary for\nembedded single-backquotes; however, embedded double-backquotes (in an\nend-string context) would be illegal.  See `Backquotes in\nPhrase-Links`__ in `Record of reStructuredText Syntax Alternatives`__.\n\n__ alternatives.html#backquotes-in-phrase-links\n__ alternatives.html\n\nAlternative choices are carets (#10) and TeX-style quotes (#11).  For\nexamples of TeX-style quoting, see\nhttp://www.zope.org/Members/jim/StructuredTextWiki/CustomizingTheDocumentProcessor.\n\nSome existing uses of backquotes:\n\n1. As a synonym for repr() in Python.\n2. For command-interpolation in shell scripts.\n3. Used as open-quotes in TeX code (and carried over into plaintext\n   by TeXies).\n\nThe inline markup start-string and end-string recognition rules\ndefined by the `reStructuredText markup specification`_ would allow\nall of these cases inside inline literals, with very few exceptions.\nAs a fallback, literal blocks could handle all cases.\n\nOutside of inline literals, the above uses of backquotes would require\nbackslash-escaping.  However, these are all prime examples of text\nthat should be marked up with inline literals.\n\nIf either backquotes or straight single-quotes are used as markup,\nTeX-quotes are too troublesome to support, so no special-casing of\nTeX-quotes should be done (at least at first).  If TeX-quotes have to\nbe used outside of literals, a single backslash-escaped would suffice:\n\\``TeX quote''.  Ugly, true, but very infrequently used.\n\nUsing literal blocks is a fallback option which removes the need for\nbackslash-escaping::\n\n    like this::\n\n        Here, we can do ``absolutely'' anything `'`'\\|/|\\ we like!\n\nNo mechanism for inline literals is perfect, just as no escaping\nmechanism is perfect.  No matter what we use, complicated inline\nexpressions involving the inline literal quote and/or the backslash\nwill end up looking ugly.  We can only choose the least often ugly\noption.\n\nreStructuredText will use double backquotes for inline literals, and\nsingle backqoutes for interpreted text.\n\n\nHyperlinks\n==========\n\nThere are three forms of hyperlink currently in StructuredText_:\n\n1. (Absolute & relative URIs.)  Text enclosed by double quotes\n   followed by a colon, a URI, and concluded by punctuation plus white\n   space, or just white space, is treated as a hyperlink::\n\n       \"Python\":http://www.python.org/\n\n2. (Absolute URIs only.)  Text enclosed by double quotes followed by a\n   comma, one or more spaces, an absolute URI and concluded by\n   punctuation plus white space, or just white space, is treated as a\n   hyperlink::\n\n       \"mail me\", mailto:me@mail.com\n\n3. (Endnotes.)  Text enclosed by brackets link to an endnote at the\n   end of the document: at the beginning of the line, two dots, a\n   space, and the same text in brackets, followed by the end note\n   itself::\n\n       Please refer to the fine manual [GVR2001].\n\n       .. [GVR2001] Python Documentation, Release 2.1, van Rossum,\n          Drake, et al., http://www.python.org/doc/\n\nThe problem with forms 1 and 2 is that they are neither intuitive nor\nunobtrusive (they break design goals 5 & 2).  They overload\ndouble-quotes, which are too often used in ordinary text (potentially\nbreaking design goal 4).  The brackets in form 3 are also too common\nin ordinary text (such as [nested] asides and Python lists like [12]).\n\nAlternatives:\n\n1. Have no special markup for hyperlinks.\n\n2. A. Interpret and mark up hyperlinks as any contiguous text\n      containing '://' or ':...@' (absolute URI) or '@' (email\n      address) after an alphanumeric word.  To de-emphasize the URI,\n      simply enclose it in parentheses:\n\n          Python (http://www.python.org/)\n\n   B. Leave special hyperlink markup as a domain-specific extension.\n      Hyperlinks in ordinary reStructuredText documents would be\n      required to be standalone (i.e. the URI text inline in the\n      document text).  Processed hyperlinks (where the URI text is\n      hidden behind the link) are important enough to warrant syntax.\n\n3. The original Setext_ introduced a mechanism of indirect hyperlinks.\n   A source link word ('hot word') in the text was given a trailing\n   underscore::\n\n       Here is some text with a hyperlink_ built in.\n\n   The hyperlink itself appeared at the end of the document on a line\n   by itself, beginning with two dots, a space, the link word with a\n   leading underscore, whitespace, and the URI itself::\n\n       .. _hyperlink http://www.123.xyz\n\n   Setext used ``underscores_instead_of_spaces_`` for phrase links.\n\nWith some modification, alternative 3 best satisfies the design goals.\nIt has the advantage of being readable and relatively unobtrusive.\nSince each source link must match up to a target, the odd variable\nending in an underscore can be spared being marked up (although it\nshould generate a \"no such link target\" warning).  The only\ndisadvantage is that phrase-links aren't possible without some\nobtrusive syntax.\n\nWe could achieve phrase-links if we enclose the link text:\n\n1. in double quotes::\n\n       \"like this\"_\n\n2. in brackets::\n\n       [like this]_\n\n3. or in backquotes::\n\n       `like this`_\n\nEach gives us somewhat obtrusive markup, but that is unavoidable.  The\nbracketed syntax (#2) is reminiscent of links on many web pages\n(intuitive), although it is somewhat obtrusive.  Alternative #3 is\nmuch less obtrusive, and is consistent with interpreted text: the\ntrailing underscore indicates the interpretation of the phrase, as a\nhyperlink.  #3 also disambiguates hyperlinks from footnote references.\nAlternative #3 wins.\n\nThe same trailing underscore markup can also be used for footnote and\ncitation references, removing the problem with ordinary bracketed text\nand Python lists::\n\n    Please refer to the fine manual [GVR2000]_.\n\n    .. [GVR2000] Python Documentation, van Rossum, Drake, et al.,\n       http://www.python.org/doc/\n\nThe two-dots-and-a-space syntax was generalized by Setext for\ncomments, which are removed from the (visible) processed output.\nreStructuredText uses this syntax for comments, footnotes, and link\ntarget, collectively termed \"explicit markup\".  For link targets, in\norder to eliminate ambiguity with comments and footnotes,\nreStructuredText specifies that a colon always follow the link target\nword/phrase.  The colon denotes 'maps to'.  There is no reason to\nrestrict target links to the end of the document; they could just as\neasily be interspersed.\n\nInternal hyperlinks (links from one point to another within a single\ndocument) can be expressed by a source link as before, and a target\nlink with a colon but no URI.  In effect, these targets 'map to' the\nelement immediately following.\n\nAs an added bonus, we now have a perfect candidate for\nreStructuredText directives, a simple extension mechanism: explicit\nmarkup containing a single word followed by two colons and whitespace.\nThe interpretation of subsequent data on the directive line or\nfollowing is directive-dependent.\n\nTo summarize::\n\n    .. This is a comment.\n\n    .. The line below is an example of a directive.\n    .. version:: 1\n\n    This is a footnote [1]_.\n\n    This internal hyperlink will take us to the footnotes_ area below.\n\n    Here is a one-word_ external hyperlink.\n\n    Here is `a hyperlink phrase`_.\n\n    .. _footnotes:\n    .. [1] Footnote text goes here.\n\n    .. external hyperlink target mappings:\n    .. _one-word: http://www.123.xyz\n    .. _a hyperlink phrase: http://www.123.xyz\n\nThe presence or absence of a colon after the target link\ndifferentiates an indirect hyperlink from a footnote, respectively.  A\nfootnote requires brackets.  Backquotes around a target link word or\nphrase are required if the phrase contains a colon, optional\notherwise.\n\nBelow are examples using no markup, the two StructuredText hypertext\nstyles, and the reStructuredText hypertext style.  Each example\ncontains an indirect link, a direct link, a footnote/endnote, and\nbracketed text.  In HTML, each example should evaluate to::\n\n    <P>A <A HREF=\"http://spam.org\">URI</A>, see <A HREF=\"#eggs2000\">\n    [eggs2000]</A> (in Bacon [Publisher]).  Also see\n    <A HREF=\"http://eggs.org\">http://eggs.org</A>.</P>\n\n    <P><A NAME=\"eggs2000\">[eggs2000]</A> \"Spam, Spam, Spam, Eggs,\n    Bacon, and Spam\"</P>\n\n1. No markup::\n\n       A URI http://spam.org, see eggs2000 (in Bacon [Publisher]).\n       Also see http://eggs.org.\n\n       eggs2000 \"Spam, Spam, Spam, Eggs, Bacon, and Spam\"\n\n2. StructuredText absolute/relative URI syntax\n   (\"text\":http://www.url.org)::\n\n       A \"URI\":http://spam.org, see [eggs2000] (in Bacon [Publisher]).\n       Also see \"http://eggs.org\":http://eggs.org.\n\n       .. [eggs2000] \"Spam, Spam, Spam, Eggs, Bacon, and Spam\"\n\n   Note that StructuredText does not recognize standalone URIs,\n   forcing doubling up as shown in the second line of the example\n   above.\n\n3. StructuredText absolute-only URI syntax\n   (\"text\", mailto:you@your.com)::\n\n       A \"URI\", http://spam.org, see [eggs2000] (in Bacon\n       [Publisher]).  Also see \"http://eggs.org\", http://eggs.org.\n\n       .. [eggs2000] \"Spam, Spam, Spam, Eggs, Bacon, and Spam\"\n\n4. reStructuredText syntax::\n\n    4. A URI_, see [eggs2000]_ (in Bacon [Publisher]).\n       Also see http://eggs.org.\n\n       .. _URI: http:/spam.org\n       .. [eggs2000] \"Spam, Spam, Spam, Eggs, Bacon, and Spam\"\n\nThe bracketed text '[Publisher]' may be problematic with\nStructuredText (syntax 2 & 3).\n\nreStructuredText's syntax (#4) is definitely the most readable.  The\ntext is separated from the link URI and the footnote, resulting in\ncleanly readable text.\n\n.. _StructuredText: https://zopestructuredtext.readthedocs.org/\n.. _Setext: https://docutils.sourceforge.io/mirror/setext.html\n.. _reStructuredText: https://docutils.sourceforge.io/rst.html\n.. _detailed description:\n   http://homepage.ntlworld.com/tibsnjoan/docutils/STNG-format.html\n.. _STMinus: http://www.cis.upenn.edu/~edloper/pydoc/stminus.html\n.. _StructuredTextNG:\n   http://www.zope.org/DevHome/Members/jim/StructuredTextWiki/StructuredTextNG\n.. _README: http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/~checkout~/\n   python/python/dist/src/README\n.. _Emacs table mode: http://table.sourceforge.net/\n.. _reStructuredText Markup Specification:\n   ../../ref/rst/restructuredtext.html\n\n\f\n..\n   Local Variables:\n   mode: indented-text\n   indent-tabs-mode: nil\n   sentence-end-double-space: t\n   fill-column: 70\n   End:\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/docutils_data/docs/dev/runtime-settings-processing.txt",
    "content": "=============================\n Runtime Settings Processing\n=============================\n\n:Author: David Goodger, Günter Milde\n:Contact: docutils-develop@lists.sourceforge.net\n:Date: $Date$\n:Revision: $Revision$\n:Copyright: This document has been placed in the public domain.\n\n:Abstract: A detailled description of Docutil's settings processing\n           framework.\n\n.. contents::\n\n\nThe ``docutils/__init__.py``, ``docutils/core.py``, and\n``docutils.frontend.py`` modules are described.\nFollowing along with the actual code is recommended.\n\nSee `Docutils Runtime Settings`_ for a high-level description of the core\nAPI and `Docutils Configuration`_ for a description of the individual\nsettings.\n\n.. note::\n   This document is informal.\n   It describes the state in Docutils 0.18.1.\n   Implementation details will change with the move to replace the\n   deprecated optparse_ module with argparse_.\n\n\nSettings priority\n=================\n\nDocutils overlays default and explicitly specified values from various\nsources such that settings behave the way we want and expect them to\nbehave.\n\nThe souces are overlaid in the following order (later sources\noverwrite earlier ones):\n\n1. Defaults specified in `settings_spec`__ and\n   `settings_defaults`__ attributes for each component_.\n   (details__)\n\n   __ ../api/runtime-settings.html#settingsspec-settings-spec\n   __ ../api/runtime-settings.html#settingsspec-settings-defaults\n   __ `OptionParser.populate_from_components()`_\n\n2. Defaults specified in `settings_default_overrides`__ attribute for\n   each component_.\n   (details__)\n\n   __ ../api/runtime-settings.html#settingsspec-settings-default-overrides\n   __ component.settings_default_overrides_\n\n3. Settings specified in the `settings_overrides parameter`_ of the\n   `convenience functions`_ rsp. the `settings_overrides` attribute of\n   a `core.Publisher` instance.\n   (details__)\n\n   __ OptionParser.defaults_\n\n4. If enabled, settings specified in `active sections`_ of the\n   `configuration files`_ in the order described in\n   `Configuration File Sections & Entries`_. (details__)\n\n   See also `Configuration File Sections & Entries`_.\n\n   __ `OptionParser.get_standard_config_settings()`_\n\n5. If enabled, command line arguments (details__).\n\n   __ `Publisher.process_command_line()`_\n\n\nSettings assigned to the `settings parameter`_ of the\n`convenience functions`_ or the ``Publisher.settings`` attribute\nare used **instead of** the above sources\n(see below for details for `command-line tools`__ and\n`other applications`__).\n\n__ `publisher.publish()`_\n__ `publisher.process_programmatic_settings()`_\n\n.. _command-line tools:\n\nRuntime settings processing for command-line tools\n==================================================\n\nThe command-line `front-end tools`_ usually import and call\nthe `convenience function`_ ``docutils.core.publish_cmdline()``.\n\n1. ``docutils.core.publish_cmdline()`` creates a `Publisher`_ instance::\n\n       publisher = core.Publisher(…, settings)\n\n   eventually sets the components_ from the respective names, and calls ::\n\n       publisher.publish(argv, …, settings_spec,\n                         settings_overrides, config_section, …)\n\n   .. _publisher.publish():\n\n2. If `publisher.settings` is None, ``publisher.publish()`` calls::\n\n       publisher.process_command_line(…,\n           settings_spec, config_section, **defaults)\n\n   with `defaults` taken from `publisher.settings_overrides`.\n\n   If `publisher.settings` is defined, steps 3 to 5 are skipped.\n\n3. ``publisher.process_command_line()`` calls::\n\n       optpar = publisher.setup_option_parser(…,\n                    settings_spec, config_section, **defaults)\n\n   .. _publisher.setup_option_parser():\n\n4. ``publisher.setup_option_parser()``\n\n   - merges the value of the `config_section parameter`_ into\n     `settings_spec` and\n\n   - creates an `OptionParser` instance ::\n\n        optpar = docutils.frontend.OptionParser(components, defaults)\n\n     with `components` the tuple of the `SettingsSpec`_ instances\n     ``(publisher.parser, publisher.reader, publisher.writer, settings_spec)``\n\n   .. _OptionParser.populate_from_components():\n\n5. The `OptionParser` instance prepends itself to the `components` tuple\n   and calls ``self.populate_from_components(components)``, which updates\n   the attribute ``self.defaults`` in two steps:\n\n   a) For each component passed, ``component.settings_spec`` is processed\n      and ``component.settings_defaults`` is applied.\n\n      .. _component.settings_default_overrides:\n\n   b) In a second loop, for each component\n      ``component.settings_default_overrides`` is applied. This way,\n      ``component.settings_default_overrides`` can override the default\n      settings of any other component.\n\n   .. _OptionParser.defaults:\n\n6. Back in ``OptionParser.__init__()``, ``self.defaults`` is updated with\n   the `defaults` argument passed to ``OptionParser(…)`` in step 5.\n\n   This means that the `settings_overrides` argument of the\n   `convenience functions`_ has priority over all\n   ``SettingsSpec.settings_spec`` defaults.\n\n   .. _OptionParser.get_standard_config_settings():\n\n7. If configuration files are enabled,\n   ``self.get_standard_config_settings()`` is called.\n\n   This reads the Docutils `configuration files`_, and returns a\n   dictionary of settings in `active sections`_ which is used to update\n   ``optpar.defaults``. So configuration file settings have priority over\n   all software-defined defaults.\n\n   .. _Publisher.process_command_line():\n\n8. ``publisher.process_command_line()`` calls ``optpar.parse_args()``.\n   The OptionParser parses all command line options and returns a\n   `docutils.frontend.Values` object.\n   This is assigned to ``publisher.settings``.\n   So command-line options have priority over configuration file\n   settings.\n\n9. The `<source>` and `<destination>` command-line arguments\n   are also parsed, and assigned to ``publisher.settings._source``\n   and ``publisher.settings._destination`` respectively.\n\n10. ``publisher.publish()`` calls ``publisher.set_io()`` with no arguments.\n    If either ``publisher.source`` or ``publisher.destination`` are not\n    set, the corresponding ``publisher.set_source()`` and\n    ``publisher.set_destination()`` are called:\n\n    ``publisher.set_source()``\n      checks for a ``source_path`` argument, and if there is none (which\n      is the case for command-line use), it is taken from\n      ``publisher.settings._source``.  ``publisher.source`` is set by\n      instantiating a ``publisher.source_class`` object.\n      For command-line front-end tools, the default\n      ``publisher.source_class`` (i.e. ``docutils.io.FileInput``)\n      is used.\n\n    ``publisher.set_destination()``\n      does the same job for the destination. (the default\n      ``publisher.destination_class`` is ``docutils.io.FileOutput``).\n\n    .. _accessing the runtime settings:\n\n11. ``publisher.publish()`` passes ``publisher.settings`` to the reader_\n    component's ``read()`` method.\n\n12. The reader component creates a new `document root node`__.\n    ``nodes.document.__init__()`` adds the settings to the internal\n    attributes.\n\n    __ ../ref/doctree.html#document\n\n    All components acting on the Document Tree are handed the\n    ``document`` root node and can access the runtime settings as\n    ``document.settings``.\n\n\nRuntime settings processing for other applications\n==================================================\n\nThe `convenience functions`_ , ``core.publish_file()``,\n``core.publish_string()``, or ``core.publish_parts()`` do not parse the\ncommand line for settings.\n\n1. The convenience functions call the generic programmatic interface\n   function ``core.publish_programmatically()`` that creates a\n   `core.Publisher` instance ::\n\n       pub = core.Publisher(…, settings)\n\n   eventually sets the components_ from the respective names, and calls ::\n\n       publisher.process_programmatic_settings(\n           settings_spec, settings_overrides, config_section)\n\n   .. _publisher.process_programmatic_settings():\n\n2. If `publisher.settings` is None,\n   ``publisher.process_programmatic_settings()`` calls::\n\n       publisher.get_settings(settings_spec, config_section, **defaults)\n\n   with `defaults` taken from `publisher.settings_overrides`.\n\n   If `publisher.settings` is defined, the following steps are skipped.\n\n3. ``publisher.get_settings()`` calls::\n\n       optpar = publisher.setup_option_parser(…,\n                    settings_spec, config_section, **defaults)\n\n4. The OptionParser instance determines setting defaults\n   as described in `steps 4 to 7`__ in the previous section.\n\n   __ `publisher.setup_option_parser()`_\n\n5. Back in ``publisher.get_settings()``, the ``frontend.Values`` instance\n   returned by ``optpar.get_default_values()`` is stored in\n   ``publisher.settings``.\n\n6. ``publish_programmatically()`` continues with setting\n   ``publisher.source`` and ``publisher.destination``.\n\n7. Finally, ``publisher.publish()`` is called. As ``publisher.settings``\n   is not None, no further command line processing takes place.\n\n8. All components acting on the Document Tree are handed the\n   ``document`` root node and can access the runtime settings as\n   ``document.settings`` (cf. `steps 11 and 12`__ in the previous section).\n\n   __ `accessing the runtime settings`_\n\n\n.. References:\n\n.. _optparse: https://docs.python.org/dev/library/optparse.html\n.. _argparse: https://docs.python.org/dev/library/argparse.html\n\n.. _Docutils Runtime Settings:\n   ../api/runtime-settings.html\n.. _active sections:\n   ../api/runtime-settings.html#active-sections\n.. _SettingsSpec:\n   ../api/runtime-settings.html#settingsspec\n.. _component:\n.. _components:\n    ../api/runtime-settings.html#components\n.. _application settings specifications:\n.. _convenience function:\n.. _convenience functions:\n    ../api/runtime-settings.html#convenience-functions\n.. _settings_overrides parameter:\n    ../api/runtime-settings.html#settings-overrides-parameter\n.. _settings parameter:\n   ../api/runtime-settings.html#settings-parameter\n.. _config_section parameter:\n   ../api/runtime-settings.html#config-section-parameter\n\n.. _Publisher convenience functions:\n    ../api/publisher.html#publisher-convenience-functions\n.. _front-end tools: ../user/tools.html\n.. _configuration file:\n.. _configuration files:\n.. _Docutils Configuration: ../user/config.html#configuration-files\n.. _Configuration File Sections & Entries:\n    ../user/config.html#configuration-file-sections-entries\n.. _Docutils Project Model: ../peps/pep-0258.html#docutils-project-model\n.. _Publisher: ../peps/pep-0258.html#publisher\n.. _Reader: ../peps/pep-0258.html#reader\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/docutils_data/docs/dev/semantics.txt",
    "content": "=====================\n Docstring Semantics\n=====================\n:Author: David Goodger\n:Contact: docutils-develop@lists.sourceforge.net\n:Revision: $Revision$\n:Date: $Date$\n:Copyright: This document has been placed in the public domain.\n\nThese are notes for a possible future PEP providing the final piece of\nthe Python docstring puzzle: docstring semantics or documentation\nmethodology.  `PEP 257`_, Docstring Conventions, sketches out some\nguidelines, but does not get into methodology details.\n\nI haven't explored documentation methodology more because, in my\nopinion, it is a completely separate issue from syntax, and it's even\nmore controversial than syntax.  Nobody wants to be told how to lay\nout their documentation, a la JavaDoc_.  I think the JavaDoc way is\nbutt-ugly, but it *is* an established standard for the Java world.\nAny standard documentation methodology has to be formal enough to be\nuseful but remain light enough to be usable.  If the methodology is\ntoo strict, too heavy, or too ugly, many/most will not want to use it.\n\nI think a standard methodology could benefit the Python community, but\nit would be a hard sell.  A PEP would be the place to start.  For most\nhuman-readable documentation needs, the free-form text approach is\nadequate.  We'd only need a formal methodology if we want to extract\nthe parameters into a data dictionary, index, or summary of some kind.\n\n\nPythonDoc\n=========\n\n(Not to be confused with Daniel Larsson's pythondoc_ project.)\n\nA Python version of the JavaDoc_ semantics (not syntax).  A set of\nconventions which are understood by the Docutils.  What JavaDoc has\ndone is to establish a syntax that enables a certain documentation\nmethodology, or standard *semantics*.  JavaDoc is not just syntax; it\nprescribes a methodology.\n\n- Use field lists or definition lists for \"tagged blocks\".  By this I\n  mean that field lists can be used similarly to JavaDoc's ``@tag``\n  syntax.  That's actually one of the motivators behind field lists.\n  For example, we could have::\n\n      \"\"\"\n      :Parameters:\n          - `lines`: a list of one-line strings without newlines.\n          - `until_blank`: Stop collecting at the first blank line if\n            true (1).\n          - `strip_indent`: Strip common leading indent if true (1,\n            default).\n\n      :Return:\n          - a list of indented lines with minimum indent removed;\n          - the amount of the indent;\n          - whether or not the block finished with a blank line or at\n            the end of `lines`.\n      \"\"\"\n\n  This is taken straight out of docutils/statemachine.py, in which I\n  experimented with a simple documentation methodology.  Another\n  variation I've thought of exploits the Grouch_-compatible\n  \"classifier\" element of definition lists.  For example::\n\n      :Parameters:\n          `lines` : [string]\n              List of one-line strings without newlines.\n          `until_blank` : boolean\n              Stop collecting at the first blank line if true (1).\n          `strip_indent` : boolean\n              Strip common leading indent if true (1, default).\n\n- Field lists could even be used in a one-to-one correspondence with\n  JavaDoc ``@tags``, although I doubt if I'd recommend it.  Several\n  ports of JavaDoc's ``@tag`` methodology exist in Python, most\n  recently Ed Loper's \"epydoc_\".\n\n\nOther Ideas\n===========\n\n- Can we extract comments from parsed modules?  Could be handy for\n  documenting function/method parameters::\n\n      def method(self,\n                 source,        # path of input file\n                 dest           # path of output file\n                ):\n\n  This would save having to repeat parameter names in the docstring.\n\n  Idea from Mark Hammond's 1998-06-23 Doc-SIG post, \"Re: [Doc-SIG]\n  Documentation tool\":\n\n      it would be quite hard to add a new param to this method without\n      realising you should document it\n\n- Frederic Giacometti's `iPhrase Python documentation conventions`_ is\n  an attachment to his Doc-SIG post of 2001-05-30.\n\n\n.. _PEP 257: https://peps.python.org/pep-0257\n.. _JavaDoc: http://java.sun.com/j2se/javadoc/\n.. _pythondoc: http://starship.python.net/crew/danilo/pythondoc/\n.. _Grouch: http://www.mems-exchange.org/software/grouch/\n.. _epydoc: http://epydoc.sourceforge.net/\n.. _iPhrase Python documentation conventions:\n   https://mail.python.org/pipermail/doc-sig/2001-May/001840.html\n\n\f\n..\n   Local Variables:\n   mode: indented-text\n   indent-tabs-mode: nil\n   sentence-end-double-space: t\n   fill-column: 70\n   End:\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/docutils_data/docs/dev/testing.txt",
    "content": "===================\n Docutils_ Testing\n===================\n\n:Authors: Lea Wiemann <LeWiemann@gmail.com>;\n          David Goodger <goodger@python.org>;\n          Docutils developers <docutils-developers@lists.sourceforge.net>\n:Revision: $Revision$\n:Date: $Date$\n:Copyright: This document has been placed in the public domain.\n\n.. _Docutils: https://docutils.sourceforge.io/\n\n.. contents::\n\nWhen adding new functionality (or fixing bugs), be sure to add test\ncases to the test suite.  Practise test-first programming; it's fun,\nit's addictive, and it works!\n\nThis document describes how to run the Docutils test suite, how the\ntests are organized and how to add new tests or modify existing tests.\n\n\nRunning the Test Suite\n======================\n\nBefore checking in any changes, run the entire Docutils test suite to\nbe sure that you haven't broken anything.  From a shell do [#]_::\n\n    cd docutils/test\n    python -u alltests.py\n\nBefore `checking in`__ changes to the Docutils core, run the tests on\nall `supported Python versions`_ (see below for details).\nIn a pinch, the edge cases should cover most of it.\n\n__ policies.html#check-ins\n\n.. note::\n   Due to incompatible customization of the standard unittest_\n   framework, the test suite does not work with popular test frameworks\n   like pytest_ or nose_.\n\n   .. _unittest: https://docs.python.org/3/library/unittest.html\n   .. _pytest: https://pypi.org/project/pytest/\n   .. _nose: https://pypi.org/project/nose3/\n\n   .. cf. https://sourceforge.net/p/docutils/feature-requests/81/\n\n.. [#] When using the `Python launcher for Windows`__, make sure to\n   specify a Python version, e.g., ``py -3.9 -u alltests.py`` for\n   Python 3.9.\n\n   __ https://docs.python.org/3/using/windows.html#python-launcher-for-windows\n\n   .. cf. https://sourceforge.net/p/docutils/bugs/434/\n\n\n.. _Python versions:\n\nTesting across multiple Python versions\n---------------------------------------\n\nA Docutils release has a commitment to support a minimum Python version [#]_\nand beyond. Before a release is cut, tests must pass in all\n`supported versions`_.\n\nYou can use `tox`_ to test with all supported versions in one go.\nFrom the shell::\n\n    cd docutils\n    tox\n\nTo test a specific version, use the ``pyNN`` environment. For example::\n\n    tox -e py37\n\n`pyenv`_ can be installed and configured (see `installing pyenv`_) to\nget multiple Python versions::\n\n    # assuming your system runs 3.9.x\n    pyenv install 3.7.12\n    pyenv install 3.8.12\n    pyenv install 3.10.1\n    pyenv global system 3.7.12 3.8.12 3.10.1\n\n    # reset your shims\n    rm -rf ~/.pyenv/shims && pyenv rehash\n\nThis will give you ``python3.7`` through ``python3.10``.\nThen run::\n\n    python3.7 -u alltests.py\n    [...]\n    python3.10 -u alltests.py\n\n.. [#] Good resources covering the differences between Python versions\n   are the `What's New` documents (`What's New in Python 3.10`__ and\n   similar).\n\n__ https://docs.python.org/3/whatsnew/3.10.html\n\n\n.. _supported versions:\n.. _supported Python versions: ../../README.html#requirements\n.. _pyenv: https://github.com/yyuu/pyenv\n.. _installing pyenv: https://github.com/yyuu/pyenv#installation\n.. _tox: https://pypi.org/project/tox/\n\n\nUnit Tests\n==========\n\nUnit tests test single functions or modules (i.e. whitebox testing).\n\nIf you are implementing a new feature, be sure to write a test case\ncovering its functionality.  It happens very frequently that your\nimplementation (or even only a part of it) doesn't work with an older\n(or even newer) Python version, and the only reliable way to detect\nthose cases is using tests.\n\nOften, it's easier to write the test first and then implement the\nfunctionality required to make the test pass.\n\n\nWriting New Tests\n-----------------\n\nWhen writing new tests, it very often helps to see how a similar test\nis implemented.  For example, the files in the\n``test_parsers/test_rst/`` directory all look very similar.  So when\nadding a test, you don't have to reinvent the wheel.\n\nIf there is no similar test, you can write a new test from scratch\nusing Python's ``unittest`` module.  For an example, please have a\nlook at the following imaginary ``test_square.py``::\n\n    #! /usr/bin/env python\n\n    # $Id$\n    # Author: Your Name <your_email_address@example.org>\n    # Copyright: This module has been placed in the public domain.\n\n    \"\"\"\n    Test module for docutils.square.\n    \"\"\"\n\n    import unittest\n    import docutils.square\n\n\n    class SquareTest(unittest.TestCase):\n\n        def test_square(self):\n            self.assertEqual(docutils.square.square(0), 0)\n            self.assertEqual(docutils.square.square(5), 25)\n            self.assertEqual(docutils.square.square(7), 49)\n\n        def test_square_root(self):\n            self.assertEqual(docutils.square.sqrt(49), 7)\n            self.assertEqual(docutils.square.sqrt(0), 0)\n            self.assertRaises(docutils.square.SquareRootError,\n                              docutils.square.sqrt, 20)\n\n\n    if __name__ == '__main__':\n        unittest.main()\n\nFor more details on how to write tests, please refer to the\ndocumentation of the ``unittest`` module.\n\n.. Note::\n\n   Unit tests and functional test should generally set ::\n\n     settings_overrides['_disable_config'] = True\n\n   in order to be independent on the users local configuration.\n\n.. _functional:\n\nFunctional Tests\n================\n\nThe directory ``test/functional/`` contains data for functional tests.\n\nPerforming functional testing means testing the Docutils system as a\nwhole (i.e. blackbox testing).\n\n\nDirectory Structure\n-------------------\n\n+ ``functional/`` The main data directory.\n\n  + ``input/`` The input files.\n\n    - ``some_test.txt``, for example.\n\n  + ``output/`` The actual output.\n\n    - ``some_test.html``, for example.\n\n  + ``expected/`` The expected output.\n\n    - ``some_test.html``, for example.\n\n  + ``tests/`` The config files for processing the input files.\n\n    - ``some_test.py``, for example.\n\n    - ``_default.py``, the `default configuration file`_.\n\n\nThe Testing Process\n-------------------\n\nWhen running ``test_functional.py``, all config files in\n``functional/tests/`` are processed.  (Config files whose names begin\nwith an underscore are ignored.)  The current working directory is\nalways Docutils' main test directory (``test/``).\n\nFor example, ``functional/tests/some_test.py`` could read like this::\n\n    # Source and destination file names.\n    test_source = \"some_test.txt\"\n    test_destination = \"some_test.html\"\n\n    # Keyword parameters passed to publish_file.\n    reader_name = \"standalone\"\n    parser_name = \"rst\"\n    writer_name = \"html\"\n    settings_overrides['output-encoding'] = 'utf-8'\n    # Relative to main ``test/`` directory.\n    settings_overrides['stylesheet_path'] = '../docutils/writers/html4css1/html4css1.css'\n\nThe two variables ``test_source`` and ``test_destination`` contain the\ninput file name (relative to ``functional/input/``) and the output\nfile name (relative to ``functional/output/`` and\n``functional/expected/``).  Note that the file names can be chosen\narbitrarily.  However, the file names in ``functional/output/`` *must*\nmatch the file names in ``functional/expected/``.\n\nIf defined, ``_test_more`` must be a function with the following\nsignature::\n\n    def _test_more(expected_dir, output_dir, test_case, parameters):\n\nThis function is called from the test case to perform tests beyond the\nsimple comparison of expected and actual output files.\n\n``test_source`` and ``test_destination`` are removed from the\nnamespace, as are all variables whose names begin with an underscore\n(\"_\").  The remaining names are passed as keyword arguments to\n``docutils.core.publish_file``, so you can set reader, parser, writer\nand anything else you want to configure.  Note that\n``settings_overrides`` is already initialized as a dictionary *before*\nthe execution of the config file.\n\n\nCreating New Tests\n------------------\n\nIn order to create a new test, put the input test file into\n``functional/input/``.  Then create a config file in\n``functional/tests/`` which sets at least input and output file names,\nreader, parser and writer.\n\nNow run ``test_functional.py``.  The test will fail, of course,\nbecause you do not have an expected output yet.  However, an output\nfile will have been generated in ``functional/output/``.  Check this\noutput file for validity [#]_ and correctness.  Then copy the file to\n``functional/expected/``.\n\nIf you rerun ``test_functional.py`` now, it should pass.\n\nIf you run ``test_functional.py`` later and the actual output doesn't\nmatch the expected output anymore, the test will fail.\n\nIf this is the case and you made an intentional change, check the\nactual output for validity and correctness, copy it to\n``functional/expected/`` (overwriting the old expected output), and\ncommit the change.\n\n.. [#] The validity of `Docutils XML` can be tested with\n   ``xmllint <document-referencing-local-Docutils-DTD>.xml --valid --noout``.\n\n   .. note: the ``--dtdvalid`` and ``--nonet`` options did not help override\n     a reference to the PUBLIC \"docutils.dtd\" if there is a local version\n     on the system (e.g. /usr/share/xml/docutils/docutils.dtd in Debian).\n\n\n.. _default configuration file:\n\nThe Default Configuration File\n------------------------------\n\nThe file ``functional/tests/_default.py`` contains default settings.\nIt is executed just before the actual configuration files, which has\nthe same effect as if the contents of ``_default.py`` were prepended\nto every configuration file.\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/docutils_data/docs/dev/todo.txt",
    "content": "======================\n Docutils_ To Do List\n======================\n\n:Author: David Goodger (with input from many); open to all Docutils\n         developers\n:Contact: docutils-develop@lists.sourceforge.net\n:Date: $Date$\n:Revision: $Revision$\n:Copyright: This document has been placed in the public domain.\n\n.. _Docutils: https://docutils.sourceforge.io/\n\n.. contents::\n\n\nPriority items are marked with \"@\" symbols.  The more @s, the higher\nthe priority.  Items in question form (containing \"?\") are ideas which\nrequire more thought and debate; they are potential to-do's.\n\nMany of these items are awaiting champions.  If you see something\nyou'd like to tackle, please do!\nPlease see also the Bugs_ document for a list of bugs in Docutils.\n\n.. _bugs: ../../BUGS.html\n\n\nMinimum Requirements for Python Standard Library Candidacy\n==========================================================\n\nBelow are action items that must be added and issues that must be\naddressed before Docutils can be considered suitable to be proposed\nfor inclusion in the Python standard library.\n\nMany of these are now handled by Sphinx_\n\n* Support for `document splitting`_.  May require some major code\n  rework.\n\n* Support for subdocuments (see `large documents`_).\n\n* `Object numbering and object references`_.\n\n* `Nested inline markup`_.\n\n* `Python Source Reader`_.\n\n* The HTML writer needs to be rewritten (or a second HTML writer\n  added) to allow for custom classes, and for arbitrary splitting\n  (stack-based?).\n\n* Documentation_ of the architecture.  Other docs too.\n\n* Plugin support.\n\n* Suitability for `Python module documentation\n  <https://docutils.sourceforge.io/sandbox/README.html#documenting-python>`_.\n\n.. _Sphinx: http://www.sphinx-doc.org/\n\nRepository\n==========\n\nMove to a Git repository.\n\n* This is a long standing `feature request`__\n  (with pointers to Sphinx issues and discussion).\n\n  __ https://sourceforge.net/p/docutils/feature-requests/58/\n\n* From a `post by David Goodger`__\n\n    An absolute requirement, for me, is that such a change be complete.\n    We can't lose any data or have to refer to the old system as an\n    \"archive\". So all the SVN history, all branches, and the full sandbox\n    need to be converted at the same time.\n\n  __ https://sourceforge.net/p/docutils/mailman/message/31878077/\n\nConvert with reposurgeon_?\n\n  If you are doing a full import rather than gatewaying, reposurgeon is\n  probably what you want. It has been tested against a lot of large, old,\n  nasty repositories and is thus known to be robust in the presence of\n  repository malformations (a property regularly checked by a test suite\n  that is a rogue's gallery of Subversion botches).\n\n  -- `Git Wiki`__\n\nThe comprehensive `Reposurgeon documentation`_ comes with\n`a guide to repository conversion`__\nas well as info about `reading Subversion repositories`__.\nConverting from an SVN dump file is faster than from a checkout.\n\n.. _reposurgeon: http://www.catb.org/esr/reposurgeon/\n.. _reposurgeon documentation:\n    http://www.catb.org/esr/reposurgeon/repository-editing.html\n__ https://git.wiki.kernel.org/index.php/\n   Interfaces,_frontends,_and_tools#Subversion\n__ http://www.catb.org/esr/reposurgeon/repository-editing.html#conversion   \n__ http://www.catb.org/esr/reposurgeon/repository-editing.html\n   #_reading_subversion_repositories   \n\n\nAdam Turner wrote a conversion Makefile and ``.lift`` scripts that\ndownloads the repo from SF with rsync, converts it to a SVN mirror and\nfinally to Git, splitting sandbox, prest, and web from docutils.\n\n\nSourceforge supports multiple Git repositories per project, so we can\nswitch the version control system independent of the decision on an\neventual switch of the host.\nCf. https://sourceforge.net/p/forge/documentation/Git/\n\n\nGeneral\n=======\n\nMiscellaneous\n-------------\n\nCode cleanup and modernization:\n  Use flake8_? See also the configuration in `<../../tox.ini>`__.\n\n  Check and solve issue from  :PEP:`290` - Code Migration and Modernization.\n  (Covers issues up to Python 2.4, is there an equivalent for more recent\n  modernizations?)\n\n  Ensure `backwards compatibility`_!\n\n  .. _flake8: https://pypi.org/project/flake8/\n  .. _backwards compatibility: policies.html#backwards-compatibility-policy\n\n* Encoding of command line arguments can only be guessed:\n\n  * try UTF-8/strict first, then try the locale's encoding with\n    strict error handling, then ASCII/replace?\n\n    UTF-8 is almost 100% safe to try first; false positives are rare,\n    The locale's encoding with strict error handling may be a\n    reasonable compromise, but any error would indicate that the\n    locale's encoding is inappropriate.  The only safe fallback is\n    ASCII/replace.\n\n  * Do not decode argv before option parsing but individual string\n    values?\n\n    +1  Allows for separate command-line vs. filesystem encodings,\n        respectively to keep file names encoded.\n    +1  Allows to configure command-line encoding in a config file,\n    -1  More complicated.\n\n  Cf. <http://thread.gmane.org/gmane.text.docutils.user/2890/focus=2957>.\n\n* Improve handling on Windows:\n\n  - Get graphical installer.\n  - Make rst2html.py an .exe file using py2exe.\n\n* .. _GUI:\n\n  The user interface is very difficult to use for most Windows users;\n  you can't really expect them to use the command line.  We need some\n  kind of GUI that can launch rst2html.py, and save the HTML output to\n  a file, and launch a browser.  What's important is that we get\n  settings to work with the GUI.  So we need some way to dynamically\n  generate a list of settings for the GUI.  The current settings_spec\n  for OptionParser doesn't seem to be usable for this for the\n  following reasons:\n\n  - It's biased toward the command line -- there are *two* options for\n    one boolean setting.\n\n  - You cannot have both a one-line description and a longer\n    description for tooltips/help-texts.\n\n  - It doesn't provide hints for the input type.  You cannot easily\n    infer the type of a setting from its validator, because any\n    component can add new validators.  In fact, it may be necessary to\n    have both a hint about the input type (e.g. string) and a\n    validator (valid ID), or it may be necessary to have a different\n    set of choices for the CLI (1, INFO, 2, ...) and for the GUI\n    (INFO, WARNING, ...).\n\n  - It's coupled to the OptionParser.  We want to be able to change\n    the underlying system without breaking everything.\n\n  - It's a bunch of primitive structures.  We want an extensible (thus\n    object-oriented) interface.\n\n  So we probably need to create a class for storing all the settings,\n  and auto-generate the OptionParser data from that.\n\n  I talked to Stephan Deibel about getting Docutils integrated into\n  Wing IDE.  He said it's possible, and he'd be willing to help.\n  There's a scripting interface to Wing, which we'd use.  We can\n  dynamically generate a list of preferences and not worry too much\n  about the rendering (from what I understood); Wing's whole GUI is\n  dynamic anyway.  The interface could be made usable for other GUIs.\n  For example, we could try to get option support for DocFactory.  //\n  FW\n\n* Allow different report levels for STDERR and system_messages inside\n  the document?\n\n* Change the docutils-update script (in sandbox/infrastructure), to\n  support arbitrary branch snapshots.\n\n* Move some general-interest sandboxes out of individuals'\n  directories, into subprojects?\n\n* Add option for file (and URL) access restriction to make Docutils\n  usable in Wikis and similar applications.\n\n  2005-03-21: added ``file_insertion_enabled`` & ``raw_enabled``\n  settings.  These partially solve the problem, allowing or disabling\n  **all** file accesses, but not limited access.\n\n* Configuration_ file handling needs discussion:\n\n  - There should be some error checking on the contents of config\n    files.  How much checking should be done?  How loudly should\n    Docutils complain if it encounters an error/problem?\n\n  - Docutils doesn't complain when it doesn't find a configuration\n    file supplied with the ``--config`` option.  Should it?  (If yes,\n    error or warning?)\n\n* Internationalization:\n\n  - I18n needs refactoring, the language dictionaries are difficult to\n    maintain.  Maybe have a look at gettext or similar tools.\n\n    (This would make a nice Google Summer of Code project)\n\n  - Language modules: in accented languages it may be useful to have\n    both accented and unaccented entries in the\n    ``bibliographic_fields`` mapping for versatility.\n\n  - Add a \"--strict-language\" option & setting: no English fallback\n    for language-dependent features.\n\n    Make this the default for output (as opposed to input)?\n    Throw an error with a helpful message, e.g.\n\n      Default \"contents\" title for language %s missing, please specify\n      an explicit title.\n\n    or\n\n     \"attention\" title for language %s missing, please use a generic\n     admonition with explicit title.\n\n  - Add internationalization to _`footer boilerplate text` (resulting\n    from \"--generator\", \"--source-link\", and \"--date\" etc.), allowing\n    translations.\n\n\n* Add validation?  See http://pytrex.sourceforge.net, RELAX NG, pyRXP.\n\n* In ``docutils.readers.get_reader_class`` (& ``parsers`` &\n  ``writers`` too), should we be importing \"standalone\" or\n  \"docutils.readers.standalone\"?  (This would avoid importing\n  top-level modules if the module name is not in docutils/readers.\n  Potential nastiness.)\n\n* Perhaps store a _`name-to-id mapping file`?  This could be stored\n  permanently, read by subsequent processing runs, and updated with\n  new entries.  (\"Persistent ID mapping\"?)\n\n* Perhaps the ``Component.supports`` method should deal with\n  individual features (\"meta\" etc.) instead of formats (\"html\" etc.)?\n  Currently, it is not used at all.\n\n  Do we need it at all?  Or rather let the writers just ignore some\n  nodes (like we already do for \"class\" values)?\n\n  The current implementation of the framework also leads to bug\n  `bug #241`__ \"doctree-based publishing != publish_string\".\n  The \"components.Filter\" transform is run by publish_doctree(). When\n  filtering based on the output format, it should be run by\n  publish_from_doctree() instead because only then the writer is\n  known.\n\n  So we need to either remove or fix the framework.\n\n  __ https://sourceforge.net/p/docutils/bugs/241/\n\n\n* Think about _`large documents` made up of multiple subdocument\n  files.  Issues: continuity (`persistent sequences`_ above),\n  cross-references (`name-to-id mapping file`_ above and `targets in\n  other documents`_ below), splitting (`document splitting`_ below).\n\n  When writing a book, the author probably wants to split it up into\n  files, perhaps one per chapter (but perhaps even more detailed).\n  However, we'd like to be able to have references from one chapter to\n  another, and have continuous numbering (pages and chapters, as\n  applicable).  Of course, none of this is implemented yet.  There has\n  been some thought put into some aspects; see `the \"include\"\n  directive`__ and the `Reference Merging`_ transform below.\n\n  When I was working with SGML in Japan, we had a system where there\n  was a top-level coordinating file, book.sgml, which contained the\n  top-level structure of a book: the <book> element, containing the\n  book <title> and empty component elements (<preface>, <chapter>,\n  <appendix>, etc.), each with filename attributes pointing to the\n  actual source for the component.  Something like this::\n\n      <book id=\"bk01\">\n      <title>Title of the Book</title>\n      <preface inrefid=\"pr01\"></preface>\n      <chapter inrefid=\"ch01\"></chapter>\n      <chapter inrefid=\"ch02\"></chapter>\n      <chapter inrefid=\"ch03\"></chapter>\n      <appendix inrefid=\"ap01\"></appendix>\n      </book>\n\n  (The \"inrefid\" attribute stood for \"insertion reference ID\".)\n\n  The processing system would process each component separately, but\n  it would recognize and use the book file to coordinate chapter and\n  page numbering, and keep a persistent ID to (title, page number)\n  mapping database for cross-references.  Docutils could use a similar\n  system for large-scale, multipart documents.\n\n  __ ../ref/rst/directives.html#including-an-external-document-fragment\n\n  Aahz's idea:\n\n      First the ToC::\n\n          .. ToC-list::\n              Introduction.txt\n              Objects.txt\n              Data.txt\n              Control.txt\n\n      Then a sample use::\n\n          .. include:: ToC.txt\n\n          As I said earlier in chapter :chapter:`Objects.txt`, the\n          reference count gets increased every time a binding is made.\n\n      Which produces::\n\n          As I said earlier in chapter 2, the\n          reference count gets increased every time a binding is made.\n\n      The ToC in this form doesn't even need to be references to actual\n      reST documents; I'm simply doing it that way for a minimum of\n      future-proofing, in case I do want to add the ability to pick up\n      references within external chapters.\n\n  Perhaps, instead of ToC (which would overload the \"contents\"\n  directive concept already in use), we could use \"manifest\".  A\n  \"manifest\" directive might associate local reference names with\n  files::\n\n      .. manifest::\n         intro: Introduction.txt\n         objects: Objects.txt\n         data: Data.txt\n         control: Control.txt\n\n  Then the sample becomes::\n\n      .. include:: manifest.txt\n\n      As I said earlier in chapter :chapter:`objects`, the\n      reference count gets increased every time a binding is made.\n\n* Add support for _`multiple output files` and _`generic data\n  handling`:\n\n  It should be possible for a component to **emit or reference** data\n  to be either **included or referenced** in the output document.\n  Examples of such data are stylesheets or images.\n\n  For this, we need a \"data\" object which stores the data either\n  inline or by referring to a file.  The Docutils framework is\n  responsible for either:\n\n  * storing the data in the appropriate location (e.g. in the\n    directory of the output file, or in a user-specified directory)\n    and providing the paths of the stored files to the writer, *or*\n\n  * providing the data itself to the writer so that it can be embedded\n    in the output document.\n\n  This approach decouples data handling from the data source (which\n  can either be embedded or referenced) and the destination (which can\n  either be embedded or referenced as well).\n\n  See <http://article.gmane.org/gmane.text.docutils.devel/3631>.\n\n* Add testing for Docutils' front end tools?\n\n* Publisher: \"Ordinary setup\" shouldn't require specific ordering; at\n  the very least, there ought to be error checking higher up in the\n  call chain.  [Aahz]\n\n  ``Publisher.get_settings`` requires that all components be set up\n  before it's called.  Perhaps the I/O *objects* shouldn't be set, but\n  I/O *classes*.  Then options are set up (``.set_options``), and\n  ``Publisher.set_io`` (or equivalent code) is called with source &\n  destination paths, creating the I/O objects.\n\n  Perhaps I/O objects shouldn't be instantiated until required.  For\n  split output, the Writer may be called multiple times, once for each\n  doctree, and each doctree should have a separate Output object (with\n  a different path).  Is the \"Builder\" pattern applicable here?\n\n* Perhaps I/O objects should become full-fledged components (i.e.\n  subclasses of ``docutils.Component``, as are Readers, Parsers, and\n  Writers now), and thus have associated option/setting specs and\n  transforms.\n\n* Multiple file I/O suggestion from Michael Hudson: use a file-like\n  object or something you can iterate over to get file-like objects.\n\n* Add an \"--input-language\" option & setting?  Specify a different\n  language module for input (bibliographic fields, directives) than\n  for output.  The \"--language\" option would set both input & output\n  languages.\n\n* Auto-generate reference tables for language-dependent features?\n  Could be generated from the source modules.  A special command-line\n  option could be added to Docutils front ends to do this.  (Idea from\n  Engelbert Gruber.)\n\n* Enable feedback of some kind from internal decisions, such as\n  reporting the successful input encoding.  Modify runtime settings?\n  System message?  Simple stderr output?\n\n* Rationalize Writer settings (HTML/LaTeX/PEP) -- share settings.\n\n* Add an \"--include file\" command-line option (config setting too?),\n  equivalent to \".. include:: file\" as the first line of the doc text?\n  Especially useful for character entity sets, text transform specs,\n  boilerplate, etc.\n\n* Support \"include\" as embedded inline-compatible directive in substitution\n  definitions, e.g. ::\n\n    .. |version| include:: version.txt\n\n    This document describes version |version| of ...\n\n  (cf. Grzegorz Adam Hankiewicz's post from 2014-10-01 in docutils-devel)\n\n* Add an ``:optional: <replacement text>`` option to the \"include\"\n  directive? This would not throw an error for a missing file, instead a\n  warning is given and ``<replacement text>`` is used instead. It would be\n  the responsibility of the author to ensure the missing file does not lead\n  to problems later in the document.\n\n  Use cases:\n\n  + Standard rST syntax to replace Sphinx's \"literalinclude\"::\n\n      .. include:: blah.cpp\n         :literal:\n         :optional: file ``blah.cpp`` not found\n\n  + Variable content taken from a file, e.g.\n\n    version.txt::\n\n       .. |version| replace:: 3.1\n\n    optionally used as::\n\n       .. include:: version.txt\n          :optional: .. |version| replace:: unknown\n\n       This document describes version |version| of ...\n\n    (cf. Grzegorz Adam Hankiewicz's post from 2014-10-01 in docutils-devel)\n\n* Parameterize the Reporter object or class?  See the `2004-02-18\n  \"rest checking and source path\"`_ thread.\n\n  .. _2004-02-18 \"rest checking and source path\":\n     http://thread.gmane.org/gmane.text.docutils.user/1112\n\n* Add a \"disable_transforms\" setting? Would allow for easy syntax\n  checking. Where (\"null\" writer, generic, parser(s))?\n  Cf. the `2004-02-18 \"rest checking and source path\"`_ thread.\n\n* Add a generic meta-stylesheet mechanism?  An external file could\n  associate style names (\"class\" attributes) with specific elements.\n  Could be generalized to arbitrary output attributes; useful for HTML\n  & XMLs.  Aahz implemented something like this in\n  sandbox/aahz/Effective/EffMap.py.\n\n* .. _classes for table cells:\n\n  William Dode suggested that table cells be assigned \"class\"\n  attributes by columns, so that stylesheets can affect text\n  alignment.  Unfortunately, there doesn't seem to be a way (in HTML\n  at least) to leverage the \"colspec\" elements (HTML \"col\" tags) by\n  adding classes to them.  The resulting HTML is very verbose::\n\n      <td class=\"col1\">111</td>\n      <td class=\"col2\">222</td>\n      ...\n\n  At the very least, it should be an option.  People who don't use it\n  shouldn't be penalized by increases in their HTML file sizes.\n\n  Table rows could also be assigned classes (like odd/even).  That\n  would be easier to implement.\n\n  How should it be implemented?\n\n  * There could be writer options (column classes & row classes) with\n    standard values.\n\n  * The table directive could grow some options.  Something like\n    \":cell-classes: col1 col2 col3\" (either must match the number of\n    columns, or repeat to fill?)  and \":row-classes: odd even\" (repeat\n    to fill; body rows only, or header rows too?).\n\n  Probably per-table directive options are best.  The \"class\" values\n  could be used by any writer, and applying such classes to all tables\n  in a document with writer options is too broad.\n\n  See also the `table_styling Sphinx extension`_ which defines\n\n  :widths: also in Docutils core (but different implementation)\n  :column-alignment: Sets per-column text alignment\n  :column-wrapping:  Sets per-column text wrapping\n  :column-dividers:  Add dividers between columns\n  :column-classes:   Add per-column css classes.\n  :header-columns:   Specify number of “stub” columns\n\n  .. _table_styling Sphinx extension: https://pythonhosted.org/cloud_sptheme/\n                                      lib/cloud_sptheme.ext.table_styling.html\n\n* Add file-specific settings support to config files, like::\n\n      [file index.txt]\n      compact-lists: no\n\n  Is this even possible?  Should the criterion be the name of the\n  input file or the output file?  Alternative (more explicit) syntax::\n\n      [source_file index.txt]\n      ...\n\n      [dest_file index.html]\n      ...\n\n  Or rather allow settings configuration from the rst source file\n  (see misc.settings_ directive)?\n\n* The \"validator\" support added to OptionParser is very similar to\n  \"traits_\" in SciPy_.  Perhaps something could be done with them?\n  (Had I known about traits when I was implementing docutils.frontend,\n  I may have used them instead of rolling my own.)\n\n  .. _traits: http://code.enthought.com/traits/\n  .. _SciPy: http://www.scipy.org/\n\n* tools/buildhtml.py: Extend the --prune option (\"prune\" config\n  setting) to accept file names (generic path) in addition to\n  directories (e.g. --prune=docs/user/rst/cheatsheet.txt, which should\n  *not* be converted to HTML).\n\n* Add support for _`plugins`.\n\n* _`Config directories`: Currently, ~/.docutils, ./docutils.conf/, &\n  /etc/docutils.conf are read as configuration_ files.  Proposal: allow\n  ~/.docutils to be a a configuration *directory*, along with\n  /etc/docutils/ and ./docutils.conf/.  Within these directories,\n  check for config.txt files.  We can also have subdirectories here,\n  for plugins, S5 themes, components (readers/writers/parsers) etc.\n\n  Docutils will continue to support configuration files for backwards\n  compatibility.\n\n* Add support for document decorations other than headers & footers?\n  For example, top/bottom/side navigation bars for web pages.  Generic\n  decorations?\n\n  Seems like a bad idea as long as it isn't independent from the output\n  format (for example, navigation bars are only useful for web pages).\n\n* docutils_update: Check for a ``Makefile`` in a directory, and run\n  ``make`` if found?  This would allow for variant processing on\n  specific source files, such as running rst2s5.py instead of\n  rst2html.py.\n\n* Add a \"disable table of contents\" setting?  The S5 writer could set\n  it as a default.  Rationale:\n\n      The ``contents`` (table of contents) directive must not be used\n      [in S5/HTML documents].  It changes the CSS class of headings\n      and they won't show up correctly in the screen presentation.\n\n      -- `Easy Slide Shows With reStructuredText & S5\n      <../user/slide-shows.html>`_\n\n  Analogue to the ``sectnum_xform`` setting, it could be used by the\n  latex writer to switch to a LaTeX generated ToC (currently, the latex\n  writer calls it \"use_latex_toc\").\n\nobject numbering and object references\n--------------------------------------\n\nFor equations, tables & figures.\n\nThese would be the equivalent of DocBook's \"formal\" elements.\n\nIn LaTeX, automatic counters are implemented for sections, equations and\nfloats (figures, tables) (configurable via stylesheets or in the\nlatex-preamble). Objects can be given `reference names`_ with the\n``\\label{<refname}`` command, ``\\ref{<refname>}`` inserts the\ncorresponding number.\n\nNo such mechanism exists in HTML.\n\n* We need _`persistent sequences`, similar to chapter and footnote\n  numbers. See `OpenOffice.org XML`_ \"fields\".\n\n  - Should the sequences be automatic or manual (user-specifyable)?\n\n* It is already possible to give `reference names`_ to objects via\n  internal hyperlink targets or the \"name\" directive option::\n\n      .. _figure name:\n\n      .. figure:: image.png\n\n  or ::\n\n      .. figure:: image.png\n         :name: figure name\n\n  Improve the mapping of \"phrase references\" to IDs/labels with Literal\n  transcription (i.e. ü -> ue, ß -> ss, å -> aa) instead of just\n  stripping the accents and other non-ASCII chars. See also the feature\n  request `allow more characters when transforming \"names\" to \"ids\"`__.\n\n  A \"table\" directive has been implemented, supporting table titles.\n\n  Perhaps the name could derive from the title/caption?\n\n  .. _reference names: ../ref/rst/restructuredtext.html#reference-names\n  __ https://sourceforge.net/p/docutils/feature-requests/66/\n\n* We need syntax for object references.  Cf. `OpenOffice.org XML`_\n  \"reference fields\":\n\n  - Parameterized substitutions are too complicated\n    (cf. `or not to do`: `object references`_)\n\n  - An interpreted text approach is simpler and better::\n\n      See Figure :ref:`figure name` and Equation :ref:`eq:identity`.\n\n  - \"equation\", \"figure\", and \"page\" roles could generate appropriate\n    boilerplate text::\n\n        See :figure:`figure name` on :page:`figure name`.\n\n    See `Interpreted Text`_ below.\n\n    Reference boilerplate could be specified in the document\n    (defaulting to nothing)::\n\n        .. fignum::\n           :prefix-ref: \"Figure \"\n           :prefix-caption: \"Fig. \"\n           :suffix-caption: :\n\n    The position of the role (prefix or suffix) could also be utilized\n\n  .. _OpenOffice.org XML: http://xml.openoffice.org/\n  .. _object references: rst/alternatives.html#object-references\n\nSee also the `Modified rst2html\n<http://www.loria.fr/~rougier/coding/article/rst2html.py>`__\nby Nicolas Rougier for a sample implementation.\n\n\nDocumentation\n=============\n\nUser Docs\n---------\n\n* Add a FAQ entry about using Docutils (with reStructuredText) on a\n  server and that it's terribly slow.  See the first paragraphs in\n  <http://article.gmane.org/gmane.text.docutils.user/1584>.\n\n* Add document about what Docutils has previously been used for\n  (web/use-cases.txt?).\n\n* Improve index in docs/user/config.txt.\n\n\nDeveloper Docs\n--------------\n\n* Improve the internal module documentation (docstrings in the code).\n  Specific deficiencies listed below.\n\n  - docutils.parsers.rst.states.State.build_table: data structure\n    required (including StringList).\n\n  - docutils.parsers.rst.states: more complete documentation of parser\n    internals.\n\n* docs/ref/doctree.txt: DTD element structural relationships,\n  semantics, and attributes.  In progress; element descriptions to be\n  completed.\n\n* Document the ``pending`` elements, how they're generated and what\n  they do.\n\n* Document the transforms_ (perhaps in docstrings?): how they're used,\n  what they do, dependencies & order considerations.\n\n* Document the HTML classes used by html4css1.py.\n\n* Write an overview of the Docutils architecture, as an introduction\n  for developers.  What connects to what, why, and how.  Either update\n  PEP 258 (see PEPs_ below) or as a separate doc.\n\n* Give information about unit tests.  Maybe as a howto?\n\n* Document the docutils.nodes APIs.\n\n* Complete the docs/api/publisher.txt docs.\n\n\nHow-Tos\n-------\n\n* Creating Docutils Writers\n\n* Creating Docutils Readers\n\n* Creating Docutils Transforms_\n\n* Creating Docutils Parsers\n\n* Using Docutils as a Library\n\n\nPEPs\n----\n\n* Complete PEP 258 Docutils Design Specification.\n\n  - Fill in the blanks in API details.\n\n  - Specify the nodes.py internal data structure implementation?\n\n        [Tibs:] Eventually we need to have direct documentation in\n        there on how it all hangs together - the DTD is not enough\n        (indeed, is it still meant to be correct?  [Yes, it is.\n        --DG]).\n\n* Rework PEP 257, separating style from spec from tools, wrt Docutils?\n  See Doc-SIG from 2001-06-19/20.\n\n\nPython Source Reader\n====================\n\nGeneral:\n\n* Analyze Tony Ibbs' PySource code.\n\n* Analyze Doug Hellmann's HappyDoc project.\n\n* Investigate how POD handles literate programming.\n\n* Take the best ideas and integrate them into Docutils.\n\nMiscellaneous ideas:\n\n* Ask Python-dev for opinions (GvR for a pronouncement) on special\n  variables (__author__, __version__, etc.): convenience vs. namespace\n  pollution.  Ask opinions on whether or not Docutils should recognize\n  & use them.\n\n* If we can detect that a comment block begins with ``##``, a la\n  JavaDoc, it might be useful to indicate interspersed section headers\n  & explanatory text in a module.  For example::\n\n      \"\"\"Module docstring.\"\"\"\n\n      ##\n      # Constants\n      # =========\n\n      a = 1\n      b = 2\n\n      ##\n      # Exception Classes\n      # =================\n\n      class MyException(Exception): pass\n\n      # etc.\n\n* Should standalone strings also become (module/class) docstrings?\n  Under what conditions?  We want to prevent arbitrary strings from\n  becoming docstrings of prior attribute assignments etc.  Assume\n  that there must be no blank lines between attributes and attribute\n  docstrings?  (Use lineno of NEWLINE token.)\n\n  Triple-quotes are sometimes used for multi-line comments (such as\n  commenting out blocks of code).  How to reconcile?\n\n* HappyDoc's idea of using comment blocks when there's no docstring\n  may be useful to get around the conflict between `additional\n  docstrings`_ and ``from __future__ import`` for module docstrings.\n  A module could begin like this::\n\n      #!/usr/bin/env python\n      # :Author: Me\n      # :Copyright: whatever\n\n      \"\"\"This is the public module docstring (``__doc__``).\"\"\"\n\n      # More docs, in comments.\n      # All comments at the beginning of a module could be\n      # accumulated as docstrings.\n      # We can't have another docstring here, because of the\n      # ``__future__`` statement.\n\n      from __future__ import division\n\n  Using the JavaDoc convention of a doc-comment block beginning with\n  ``##`` is useful though.  It allows doc-comments and implementation\n  comments.\n\n  .. _additional docstrings:\n     ../peps/pep-0258.html#additional-docstrings\n\n* HappyDoc uses an initial comment block to set \"parser configuration\n  values\".  Do the same thing for Docutils, to set runtime settings on\n  a per-module basis?  I.e.::\n\n      # Docutils:setting=value\n\n  Could be used to turn on/off function parameter comment recognition\n  & other marginal features.  Could be used as a general mechanism to\n  augment config files and command-line options (but which takes\n  precedence?).\n\n* Multi-file output should be divisible at arbitrary level.\n\n* Support all forms of ``import`` statements:\n\n  - ``import module``: listed as \"module\"\n  - ``import module as alias``: \"alias (module)\"\n  - ``from module import identifier``: \"identifier (from module)\"\n  - ``from module import identifier as alias``: \"alias (identifier\n    from module)\"\n  - ``from module import *``: \"all identifiers (``*``) from module\"\n\n* Have links to colorized Python source files from API docs?  And\n  vice-versa: backlinks from the colorized source files to the API\n  docs!\n\n* In summaries, use the first *sentence* of a docstring if the first\n  line is not followed by a blank line.\n\n\nreStructuredText Parser\n=======================\n\nAlso see the `... Or Not To Do?`__ list.\n\n__ rst/alternatives.html#or-not-to-do\n\nBugs\n----\n\n* A container directive with ``:class:`` option gets the spurious\n  class value \"class\".\n\nMisc\n----\n\n* Another list problem::\n\n      * foo\n            * bar\n            * baz\n\n  This ends up as a definition list.  This is more of a usability\n  issue.\n\n* This case is probably meant to be a nested list, but it ends up as a\n  list inside a block-quote without an error message::\n\n      - foo\n\n       - bar\n\n  It should probably just be an error.\n\n  The problem with this is that you don't notice easily in HTML that\n  it's not a nested list but a block-quote -- there's not much of a\n  visual difference.\n\n* Treat enumerated lists that are not arabic and consist of only one\n  item in a single line as ordinary paragraphs.  See\n  <http://article.gmane.org/gmane.text.docutils.user/2635>.\n\n* The citation syntax could use some improvements.  See\n  <http://thread.gmane.org/gmane.text.docutils.user/2499> (and the\n  sub-thread at\n  <http://thread.gmane.org/gmane.text.docutils.user/2499/focus=3028>,\n  and the follow-ups at\n  <http://thread.gmane.org/gmane.text.docutils.user/3087>,\n  <http://thread.gmane.org/gmane.text.docutils.user/3110>,\n  <http://thread.gmane.org/gmane.text.docutils.user/3114>),\n  <http://thread.gmane.org/gmane.text.docutils.user/2443>,\n  <http://thread.gmane.org/gmane.text.docutils.user/2715>,\n  <http://thread.gmane.org/gmane.text.docutils.user/3027>,\n  <http://thread.gmane.org/gmane.text.docutils.user/3120>,\n  <http://thread.gmane.org/gmane.text.docutils.user/3253>.\n\n* The current list-recognition logic has too many false positives, as\n  in ::\n\n      * Aorta\n      * V. cava superior\n      * V. cava inferior\n\n  Here ``V.`` is recognized as an enumerator, which leads to\n  confusion.  We need to find a solution that resolves such problems\n  without complicating the spec to much.\n\n  See <http://thread.gmane.org/gmane.text.docutils.user/2524>.\n\n* Add indirect links via citation references & footnote references.\n  Example::\n\n      `Goodger (2005)`_ is helpful.\n\n      .. _Goodger (2005): [goodger2005]_\n      .. [goodger2005] citation text\n\n  See <http://thread.gmane.org/gmane.text.docutils.user/2499>.\n\n* Complain about bad URI characters\n  (http://article.gmane.org/gmane.text.docutils.user/2046) and\n  disallow internal whitespace\n  (http://article.gmane.org/gmane.text.docutils.user/2214).\n\n* Create ``info``-level system messages for unnecessarily\n  backslash-escaped characters (as in ``\"\\something\"``, rendered as\n  \"something\") to allow checking for errors which silently slipped\n  through.\n\n* Add (functional) tests for untested roles.\n\n* Add test for \":figwidth: image\" option of \"figure\" directive.  (Test\n  code needs to check if PIL is available on the system.)\n\n* Add support for CJK double-width whitespace (indentation) &\n  punctuation characters (markup; e.g. double-width \"*\", \"-\", \"+\")?\n\n* Add motivation sections for constructs in spec.\n\n* Support generic hyperlink references to _`targets in other\n  documents`?  Not in an HTML-centric way, though (it's trivial to say\n  ``https://www.example.org/doc#name``, and useless in non-HTML\n  contexts).  XLink/XPointer?  ``.. baseref::``?  See Doc-SIG\n  2001-08-10.\n\n* Implement the header row separator modification to table.el.  (Wrote\n  to Takaaki Ota & the table.el mailing list on 2001-08-12, suggesting\n  support for \"=====\" header rows.  On 2001-08-17 he replied, saying\n  he'd put it on his to-do list, but \"don't hold your breath\".)\n\n* Fix the parser's indentation handling to conform with the stricter\n  definition in the spec.  (Explicit markup blocks should be strict or\n  forgiving?)\n\n  .. XXX What does this mean?  Can you elaborate, David?\n\n* Make the parser modular.  Allow syntax constructs to be added or\n  disabled at run-time.  Subclassing is probably not enough because it\n  makes it difficult to apply multiple extensions.\n\n* Generalize the \"doctest block\" construct (which is overly\n  Python-centric) to other interactive sessions?  \"Doctest block\"\n  could be renamed to \"I/O block\" or \"interactive block\", and each of\n  these could also be recognized as such by the parser:\n\n  - Shell sessions::\n\n        $ cat example1.txt\n        A block beginning with a \"$ \" prompt is interpreted as a shell\n        session interactive block.  As with Doctest blocks, the\n        interactive block ends with the first blank line, and wouldn't\n        have to be indented.\n\n  - Root shell sessions::\n\n        # cat example2.txt\n        A block beginning with a \"# \" prompt is interpreted as a root\n        shell session (the user is or has to be logged in as root)\n        interactive block.  Again, the block ends with a blank line.\n\n  Other standard (and unambiguous) interactive session prompts could\n  easily be added (such as \"> \" for WinDOS).\n\n  Tony Ibbs spoke out against this idea (2002-06-14 Doc-SIG thread\n  \"docutils feedback\").\n\n* Add support for pragma (syntax-altering) directives.\n\n  Some pragma directives could be local-scope unless explicitly\n  specified as global/pragma using \":global:\" options.\n\n* Support whitespace in angle-bracketed standalone URLs according to\n  Appendix E (\"Recommendations for Delimiting URI in Context\") of `RFC\n  2396`_.\n\n  .. _RFC 2396: https://www.rfc-editor.org/rfc/rfc2396.txt\n\n* Use the vertical spacing of the source text to determine the\n  corresponding vertical spacing of the output?\n\n* [From Mark Nodine]  For cells in simple tables that comprise a\n  single line, the justification can be inferred according to the\n  following rules:\n\n  1. If the text begins at the leftmost column of the cell,\n     then left justification, ELSE\n  2. If the text begins at the rightmost column of the cell,\n     then right justification, ELSE\n  3. Center justification.\n\n  The onus is on the author to make the text unambiguous by adding\n  blank columns as necessary.  There should be a parser setting to\n  turn off justification-recognition (normally on would be fine).\n\n  Decimal justification?\n\n  All this shouldn't be done automatically.  Only when it's requested\n  by the user, e.g. with something like this::\n\n      .. table::\n         :auto-indent:\n\n         (Table goes here.)\n\n  Otherwise it will break existing documents.\n\n* Generate a warning or info message for paragraphs which should have\n  been lists, like this one::\n\n      1. line one\n      3. line two\n\n* Generalize the \"target-notes\" directive into a command-line option\n  somehow?  See docutils-develop 2003-02-13.\n\n* Allow a \"::\"-only paragraph (first line, actually) to introduce a\n  _`literal block without a blank line`?  (Idea from Paul Moore.) ::\n\n      ::\n          This is a literal block\n\n  Is indentation enough to make the separation between a paragraph\n  which contains just a ``::`` and the literal text unambiguous?\n  (There's one problem with this concession: If one wants a definition\n  list item which defines the term \"::\", we'd have to escape it.)  It\n  would only be reasonable to apply it to \"::\"-only paragraphs though.\n  I think the blank line is visually necessary if there's text before\n  the \"::\"::\n\n      The text in this paragraph needs separation\n      from the literal block following::\n          This doesn't look right.\n\n* Add new syntax for _`nested inline markup`?  Or extend the parser to\n  parse nested inline markup somehow?  See the `collected notes\n  <rst/alternatives.html#nested-inline-markup>`__.\n\n* Drop the backticks from embedded URIs with omitted reference text?\n  Should the angle brackets be kept in the output or not? ::\n\n      <file_name>_\n\n  Probably not worth the trouble.\n\n* How about a syntax for alternative hyperlink behavior, such as \"open\n  in a new window\" (as in HTML's ``<a target=\"_blank\">``)?\n\n  The MoinMoin wiki uses a caret (\"^\") at the beginning of the URL\n  (\"^\" is not a legal URI character).  That could work for both inline\n  and explicit targets::\n\n      The `reference docs <^url>`__ may be handy.\n\n      .. _name: ^url\n\n  This may be too specific to HTML.  It hasn't been requested very\n  often either.\n\n* Add an option to add URI schemes at runtime.\n\n* _`Segmented lists`::\n\n      : segment : segment : segment\n      : segment : segment : very long\n        segment\n      : segment : segment : segment\n\n  The initial colon (\":\") can be thought of as a type of bullet\n\n  We could even have segment titles::\n\n      :: title  : title   : title\n      : segment : segment : segment\n      : segment : segment : segment\n\n  This would correspond well to DocBook's SegmentedList.  Output could\n  be tabular or \"name: value\" pairs, as described in DocBook's docs.\n\n* Enable grid _`tables inside XML comments`, where \"``--``\" ends comments.\n\n  Implementation possibilities:\n\n  1. Make the table syntax characters into \"table\" directive options.\n     This is the most flexible but most difficult, and we probably\n     don't need that much flexibility.\n\n  2. Substitute \"~\" for \"-\" with a specialized directive option\n     (e.g. \":tildes:\").\n\n  3. Make the standard table syntax recognize \"~\" as well as \"-\", even\n     without a directive option.  Individual tables would have to be\n     internally consistent.\n\n  4. Allow Unicode box characters for table markup\n     (`feature request [6]`_)\n\n  Directive options are preferable to configuration settings, because\n  tables are document-specific.  A pragma directive would be another\n  approach, to set the syntax once for a whole document.\n\n  Unicode box character markup would kill two birds with one stone.\n\n  In the meantime, the list-table_ directive is a good replacement for\n  grid tables inside XML comments.\n\n  .. _feature request [6]:\n      https://sourceforge.net/p/docutils/feature-requests/6\n  .. _list-table: ../ref/rst/directives.html#list-table\n\n\n* Generalize docinfo contents (bibliographic fields): remove specific\n  fields, and have only a single generic \"field\"?\n\n* _`Line numbers` and \"source\" in system messages:\n\n  - Add \"source\" and \"line\" keyword arguments to all Reporter calls?\n    This would require passing source/line arguments along all\n    intermediate functions (where currently only `line` is used).\n\n    Or rather specify \"line\" only if actually needed?\n\n    Currently, `document.reporter` uses a state machine instance to\n    determine the \"source\" and \"line\" info from\n    `statemachine.input_lines` if not given explicitly. Except for\n    special cases, the \"line\" argument is not needed because,\n    `document.statemachine` keeps record of the current line number.\n\n  - For system messages generated after the parsing is completed (i.e. by\n    transforms or the writer) \"line\" info must be present in the doctree\n    elements.\n\n    Elements' .line assignments should be checked.  (Assign to .source\n    too?  Add a set_info method?  To what?)\n\n    The \"source\" (and line number in the source) can either be added\n    explicitly to the elements or determined from the “raw” line\n    number by `document.statemachine.get_source_and_line`.\n\n  - Some line numbers in elements are not being set properly\n    (explicitly), just implicitly/automatically.  See rev. 1.74 of\n    docutils/parsers/rst/states.py for an example of how to set.\n\n  - The line numbers of definition list items are wrong::\n\n        $ rst2pseudoxml.py --expose-internal-attribute line\n        1\n          2\n          3\n\n        5\n          6\n          7\n\n        <document source=\"<stdin>\">\n            <definition_list>\n                <definition_list_item internal:line=\"3\">\n                    <term>\n                        1\n                    <definition>\n                        <paragraph internal:line=\"2\">\n                            2\n                            3\n                <definition_list_item internal:line=\"6\">\n                    <term>\n                        5\n                    <definition>\n                        <paragraph internal:line=\"6\">\n                            6\n                            7\n\n* .. _none source:\n\n  Quite a few nodes are getting a \"None\" source attribute as well.  In\n  particular, see the bodies of definition lists.\n\n\nAdaptable file extensions\n-------------------------\n\nQuestions\n`````````\n\nShould Docutils support adaptable file extensions in hyperlinks?\n\n  In the rST source, sister documents are \".txt\" files. If we're\n  generating HTML, then \".html\" is appropriate; if PDF, then \".pdf\";\n  etc.\n\nHandle documents only, or objects (images, etc.) also?\n\n  Different output formats support different sets of image formats (HTML\n  supports \".svg\" but not \".pdf\", pdfLaTeX supports \".pdf\" but not \".svg\",\n  LaTeX supports only \".eps\").\n\n  This is less urgent 2020 than 2004, as `pdflatex` and `lualatex` are\n  now standard and support most image formats. Also, a wrapper like\n  `rubber`__ that provides on-the-fly image conversion depends on the\n  \"wrong\" extension in the LaTeX source.\n\n  __ https://pypi.org/project/rubber/\n\nAt what point should the extensions be substituted?\n\n  Transforms_:\n    Fits well in the `Reader → Transformer → Writer`__ processing framework.\n\n    * Filename/URL extension replacement can be done walking over the\n      Document tree transforming the document tree from a valid state\n      to another valid state.\n\n    * Writer-specific configuration is still possible in the\n      respective sections of the configuration_ file.\n\n    __ ../peps/pep-0258.html#id24\n\n  Pre- or post-processing:\n    Can be implemented independent of Docutils -- keeps Docutils simple.\n\n      ... those who need more sophisticated filename extension\n      tweaking can simply use regular expressions, which isn't too\n      difficult due to the determinability of the writers.  So there\n      is no need to add a complex filename-extension-handling feature\n      to Docutils.\n\n      --- `Lea Wiemann in docutils-users 2004-06-04`__\n\n  __ https://sourceforge.net/p/docutils/mailman/message/6918089/\n\n\nProposals\n`````````\n\nHow about using \".*\" to indicate \"choose the most appropriate filename\nextension\"?  For example::\n\n    .. _Another Document: another.*\n\n* My point about using ``.*`` is that any other mechanism inside reST\n  leads to too many ambiguities in reading reST documents; at least\n  with ``.*`` it's clear that some kind of substitution is going on.\n\n  --- Aahz\n\n* What is to be done for output formats that don't *have* hyperlinks?\n  For example, LaTeX targeted at print.  Hyperlinks may be \"called\n  out\", as footnotes with explicit URLs.  (Don't convert the links.)\n\n  But then there's also LaTeX targeted at PDFs, which *can* have\n  links.  Perhaps a runtime setting for \"*\" could explicitly provide\n  the extension, defaulting to the output file's extension.\n\n* If this handles images also, how to differentiate between document\n  and image links?  Element context (within \"image\")?  Which image\n  extension to use for which document format? For HTML output, there\n  is no reliable way of determining which extension to use (svg, png,\n  jpg, jpeg, gif, ...).\n\n  Should the system check for existing files?  No, not practical (the\n  image files may be not available when the document is processed to HTML).\n\n  Mailing list threads: `Images in both HTML and LaTeX`__ (especially\n  `this summary of Lea's objections`__).\n\n  __ https://sourceforge.net/p/docutils/mailman/docutils-users/thread/40BAA4B7.5020801%40python.org/#msg6918066\n  __ https://sourceforge.net/p/docutils/mailman/message/6918089/\n\nChris Liechti suggests a new ``:link:`` role in `more-universal\nlinks?`__::\n\n    .. role:: link(rewrite)\n       :transform: .txt|.html\n\n  and then to use it::\n\n    for more information see :link:`README.txt`\n\n  it would be useful if it supported an additional option\n  ``:format: html`` so that separate rules for each format can be\n  defined. (like the \"raw\" role)\n\n__ https://sourceforge.net/p/docutils/mailman/message/6919484/\n\n\nIdea from Jim Fulton: an external lookup table of targets:\n\n    I would like to specify the extension (e.g. .txt) [in the\n    source, rather than ``filename.*``], but tell the converter to\n    change references to the files anticipating that the files will\n    be converted too.\n\n    For example::\n\n      .. _Another Document: another.txt\n\n      rst2html.py --convert-links \"another.txt bar.txt\" foo.txt\n\n    That is, name the files for which extensions should be converted.\n\n    Note that I want to refer to original files in the original text\n    (another.txt rather than another.*) because I want the\n    unconverted text to stand on its own.\n\n    Note that in most cases, people will be able to use globs::\n\n      rst2html.py --convert-link-extensions-for \"`echo *.txt`\" foo.txt\n\n    It might be nice to be able to use multiple arguments, as in::\n\n      rst2html.py --convert-link-extensions-for *.txt -- foo.txt\n\n    > Handle documents only, or objects (images, etc.) also?\n\n    No, documents only, but there really is no need for guesswork.\n    Just get the file names as command-line arguments.  EIBTI\n    [explicit is better than implicit].\n\nIn `Patch #169`__ `Hyperlink extension rewriting`, John L. Clark\nsuggests command line options that map to-be-changed file extensions, e.g.::\n\n     rst2html --map-extension rst html --map-extension jpg png \\\n        input-filename.rst\n\n__ https://sourceforge.net/p/docutils/patches/169/\n\n  Specifying the mapping as regular expressions would make this\n  approach more generic and easier to implement (use ``re.replace``\n  and refer to the \"re\" module's documentation instead of coding and\n  documenting a home-grown extraction and mapping procedure).\n\n\nMath Markup\n-----------\n\nSince Docutils 0.8, a \"math\" role and directive using LaTeX math\nsyntax as input format is part of reStructuredText.\n\nOpen issues:\n\n* Use a \"Transform\" for math format conversions as extensively discussed in\n  the \"math directive issues\" thread in May 2008\n  (http://osdir.com/ml/text.docutils.devel/2008-05/threads.html)?\n\n* Generic `math-output setting`_ (currently specific to HTML).\n  (List of math-output preferences?)\n\n* Try to be compatible with `Math support in Sphinx`_?\n\n  * The ``:label:`` option selects a label for the equation, by which it\n    can be cross-referenced, and causes an equation number to be issued.\n    In Docutils, the option ``:name:`` sets the label.\n    Equation numbering is not implemented yet.\n\n  * Option ``:nowrap:`` prevents wrapping of the given math in a\n    math environment (you have to specify the math environment in the\n    content).\n\n  .. _Math support in Sphinx: http://sphinx.pocoo.org/ext/math.html\n\n* Equation numbering and references. (see the section on\n  `object numbering and object references` for equations,\n  formal tables, and images.)\n\n.. _math-output setting: ../user/config.html#math-output\n\n\nalternative input formats\n`````````````````````````\n\nUse a directive option to specify an alternative input format, e.g. (but not\nlimited to):\n\nMathML_\n  Not for hand-written code but maybe useful when pasted in (or included\n  from a file)\n\n  For an overview of MathML implementations and tests, see, e.g.,\n  the `mathweb wiki`_ or the `ConTeXT MathML page`_.\n\n  .. _MathML: https://www.w3.org/TR/MathML2/\n  .. _mathweb wiki: http://www.mathweb.org/wiki/MathML\n  .. _ConTeXT MathML page: http://wiki.contextgarden.net/MathML\n\n  A MathML to LaTeX XSLT sheet:\n  https://github.com/davidcarlisle/web-xslt/tree/master/pmml2tex\n\n\nASCIIMath_\n  Simple, ASCII based math input language (see also `ASCIIMath tutorial`_).\n\n  * The Python module ASCIIMathML_ translates a string with ASCIIMath into a\n    MathML tree. Used, e.g., by MultiMarkdown__.\n\n    A more comprehensive implementation is ASCIIMathPython_ by\n    Paul Trembley (also used in his sandbox projects).\n\n  * For conversion to LaTeX, there is\n\n    - a JavaScript script at\n      http://dlippman.imathas.com/asciimathtex/ASCIIMath2TeX.js\n\n    - The javascript `asciimath-to-latex` AsciiMath to LaTex converter at\n      the node package manager\n      https://www.npmjs.com/package/asciimath-to-latex\n      and at GitHub https://github.com/tylerlong/asciimath-to-latex\n\n    - a javascript and a PHP converter script at GitHub\n      https://github.com/asciimath/asciimathml/tree/master/asciimath-based\n\n  .. _ASCIIMath: http://www1.chapman.edu/~jipsen/mathml/asciimath.html\n  .. _ASCIIMath tutorial:\n     http://www.wjagray.co.uk/maths/ASCIIMathTutorial.html\n  .. _ASCIIMathML: http://pypi.python.org/pypi/asciimathml/\n  .. _ASCIIMathPython: https://github.com/paulhtremblay/asciimathml\n  __ http://fletcherpenney.net/multimarkdown/\n\n`Unicode Nearly Plain Text Encoding of Mathematics`_\n   format for lightly marked-up representation of mathematical\n   expressions in Unicode.\n\n   (Unicode Technical Note. Sole responsibility for its contents rests\n   with the author(s). Publication does not imply any endorsement by\n   the Unicode Consortium.)\n\n   .. _Unicode Nearly Plain Text Encoding of Mathematics:\n      https://www.unicode.org/notes/tn28/\n\nitex\n  See `the culmination of a relevant discussion in 2003\n  <http://article.gmane.org/gmane.text.docutils.user/118>`__.\n\n\n\nLaTeX output\n````````````\n\nWhich equation environments should be supported by the math directive?\n\n* one line:\n\n  + numbered: `equation`\n  + unnumbered: `equation*`\n\n* multiline (test for ``\\\\`` outside of a nested environment\n  (e.g. `array` or `cases`)\n\n  + numbered: `align` (number every line)\n\n    (To give one common number to all lines, put them in a `split`\n    environment. Docutils then places it in an `equation` environment.)\n\n  + unnumbered: `align*`\n\n  + Sphinx math also supports `gather` (checking for blank lines in\n    the content). Docutils puts content blocks separated by blank\n    lines in separate math-block doctree nodes. (The only difference of\n    `gather` to two consecutive \"normal\" environments seems to be that\n    page-breaks between the two are prevented.)\n\nSee http://www.math.uiuc.edu/~hildebr/tex/displays.html.\n\n\nHTML output\n```````````\n\nThere is no native math support in HTML.\nFor supported math output variants see the `math-output setting`_.\nAdd more/better alternatives?\n\nMathML_\n  Converters from LaTeX to MathML include\n\n  * TtM_ (C), ``--math-output=MathML ttm``, undocumented, may be removed.\n\n    No \"matrix\", \"align\" and  \"cases\" environments.\n\n  * MathToWeb_ (Java)\n  * TeX4ht_ (TeX based)\n  * itex_ (also `used in Abiword`__)\n  * `Steve’s LATEX-to-MathML translator`_\n    ('mini-language', javascript, Python)\n  * `MathJax for Node`_\n\n  * Write a new converter? E.g. based on:\n\n    * a generic tokenizer (see e.g. a `latex-codec recipe`_,\n      `updated latex-codec`_, )\n    * the Unicode-Char <-> LaTeX mappings database unimathsymbols_\n\n  __ http://msevior.livejournal.com/26377.html\n  .. _MathML: https://www.w3.org/TR/MathML2/\n  .. _ttm: http://hutchinson.belmont.ma.us/tth/mml/\n  .. _TeX4ht: http://www.tug.org/applications/tex4ht/mn.html\n  .. _MathToWeb:  http://www.mathtoweb.com/\n  .. _itex: http://golem.ph.utexas.edu/~distler/blog/itex2MMLcommands.html\n  .. _Steve’s LATEX-to-MathML translator:\n     http://www.gold-saucer.org/mathml/greasemonkey/dist/display-latex\n  .. _latex-codec recipe:\n     http://code.activestate.com/recipes/252124-latex-codec/\n  .. _updated latex-codec:\n     http://mirror.ctan.org/biblio/bibtex/utils/mab2bib/latex.py\n  .. _unimathsymbols: http://milde.users.sourceforge.net/LUCR/Math/\n  .. _MathJax for Node: https://github.com/mathjax/MathJax-node\n\n.. URL seems down:\n   .. _itex: http://pear.math.pitt.edu/mathzilla/itex2mmlItex.html\n\n\nHTML/CSS\n  format math in standard HTML enhanced by CSS rules\n  (Overview__, `Examples and experiments`__).\n  The ``math-output=html`` option uses the converter from eLyXer_\n  (included with Docutils).\n\n  Alternatives: LaTeX-math to HTML/CSS converters include\n\n  * TtH_ (C)\n  * Hevea_ (Objective Caml)\n  * `MathJax for Node`_\n  * KaTeX_\n\n  __ http://www.cs.tut.fi/~jkorpela/math/\n  __ http://www.zipcon.net/~swhite/docs/math/math.html\n  .. _elyxer: http://elyxer.nongnu.org/\n  .. _TtH: ttp://hutchinson.belmont.ma.us/tth/index.html\n  .. _Hevea: http://para.inria.fr/~maranget/hevea/\n  .. _KaTeX: https://katex.org\n\nimages\n  (PNG or SVG) like e.g. Wikipedia.\n\n  * dvisvgm_\n  * the pure-python MathML->SVG converter SVGMath_)\n  * `MathJax for Node`_\n\n  .. _dvisvgm: http://dvisvgm.sourceforge.net/\n  .. _SVGMath: http://www.grigoriev.ru/svgmath/\n\n\nclient side JavaScript conversion\n  Use TeX notation in the web page and JavaScript in the displaying browser.\n  (implemented as `math-output setting`_ \"mathjax\").\n\n  * jqMath_ (faster and lighter than MathJax_)\n\n  .. _MathJax: http://www.mathjax.org/\n  .. _jqMath: http://mathscribe.com/author/jqmath.html\n\nOpenOffice output\n`````````````````\n\n* The `OpenDocument standard`_ version 1.1 says:\n\n    Mathematical content is represented by MathML 2.0\n\n  However, putting MathML into an ODP file seems tricky as these\n  (maybe outdated) links suppose:\n  http://idippedut.dk/post/2008/01/25/Do-your-math-ODF-and-MathML.aspx\n  http://idippedut.dk/post/2008/03/03/Now-I-get-it-ODF-and-MathML.aspx\n\n  .. _OpenDocument standard:\n    http://www.oasis-open.org/standards#opendocumentv1.1\n\n* OOoLaTeX__:  \"a set of macros designed to bring the power of LaTeX\n  into OpenOffice.\"\n\n  __ http://ooolatex.sourceforge.net/\n\n\nDirectives\n----------\n\nDirectives below are often referred to as \"module.directive\", the\ndirective function.  The \"module.\" is not part of the directive name\nwhen used in a document.\n\n* Allow for field lists in list tables.  See\n  <http://thread.gmane.org/gmane.text.docutils.devel/3392>.\n\n* .. _unify tables:\n\n  Unify table implementations and unify options of table directives\n  (http://article.gmane.org/gmane.text.docutils.user/1857).\n\n* Allow directives to be added at run-time?\n\n* Use the language module for directive option names?\n\n* Add \"substitution_only\" and \"substitution_ok\" function attributes,\n  and automate context checking?\n\n* Implement options or features on existing directives:\n\n  - All directives that produce titled elements should grow implicit\n    reference names based on the titles.\n\n  - Allow the _`:trim:` option for all directives when they occur in a\n    substitution definition, not only the unicode_ directive.\n\n    .. _unicode: ../ref/rst/directives.html#unicode-character-codes\n\n  - Add the \"class\" option to the unicode_ directive.  For example, you\n    might want to get characters or strings with borders around them.\n\n  - _`images.figure`: \"title\" and \"number\", to indicate a formal\n    figure?\n\n  - _`parts.sectnum`: \"local\"?, \"refnum\"\n\n    A \"local\" option could enable numbering for sections from a\n    certain point down, and sections in the rest of the document are\n    not numbered.  For example, a reference section of a manual might\n    be numbered, but not the rest.  OTOH, an all-or-nothing approach\n    would probably be enough.\n\n    The \"sectnum\" directive should be usable multiple times in a\n    single document.  For example, in a long document with \"chapter\"\n    and \"appendix\" sections, there could be a second \"sectnum\" before\n    the first appendix, changing the sequence used (from 1,2,3... to\n    A,B,C...).  This is where the \"local\" concept comes in.  This part\n    of the implementation can be left for later.\n\n    A \"refnum\" option (better name?) would insert reference names\n    (targets) consisting of the reference number.  Then a URL could be\n    of the form ``http://host/document.html#2.5`` (or \"2-5\"?).  Allow\n    internal references by number?  Allow name-based *and*\n    number-based ids at the same time, or only one or the other (which\n    would the table of contents use)?  Usage issue: altering the\n    section structure of a document could render hyperlinks invalid.\n\n  - _`parts.contents`: Add a \"suppress\" or \"prune\" option?  It would\n    suppress contents display for sections in a branch from that point\n    down.  Or a new directive, like \"prune-contents\"?\n\n    Add an option to include topics in the TOC?  Another for sidebars?\n    The \"topic\" directive could have a \"contents\" option, or the\n    \"contents\" directive\" could have an \"include-topics\" option.  See\n    docutils-develop 2003-01-29.\n\n  - _`parts.header` & _`parts.footer`: Support multiple, named headers\n    & footers?  For example, separate headers & footers for odd, even,\n    and the first page of a document.\n\n    This may be too specific to output formats which have a notion of\n    \"pages\".\n\n  - _`misc.class`:\n\n    - Add a ``:parent:`` option for setting the parent's class\n      (http://article.gmane.org/gmane.text.docutils.devel/3165).\n\n  - _`misc.include`:\n\n    - Option to label lines?\n\n    - How about an environment variable, say RSTINCLUDEPATH or\n      RSTPATH, for standard includes (as in ``.. include:: <name>``)?\n      This could be combined with a setting/option to allow\n      user-defined include directories.\n\n    - Add support for inclusion by URL? ::\n\n          .. include::\n             :url: https://www.example.org/inclusion.txt\n\n    - Strip blank lines from begin and end of a literal included file or\n      file section. This would correspond to the way a literal block is\n      handled.\n\n      As nodes.literal_block expects (and we have) the text as a string\n      (rather than a list of lines), using a regexp seems the way.\n\n  - _`misc.raw`: add a \"destination\" option to the \"raw\" directive? ::\n\n        .. raw:: html\n           :destination: head\n\n           <link ...>\n\n    It needs thought & discussion though, to come up with a consistent\n    set of destination labels and consistent behavior.\n\n    And placing HTML code inside the <head> element of an HTML\n    document is rather the job of a templating system.\n\n  - _`body.sidebar`: Allow internal section structure?  Adornment\n    styles would be independent of the main document.\n\n    That is really complicated, however, and the document model\n    greatly benefits from its simplicity.\n\n* Implement directives.  Each of the list items below begins with an\n  identifier of the form, \"module_name.directive_function_name\".  The\n  directive name itself could be the same as the\n  directive_function_name, or it could differ.\n\n  - _`html.imagemap`\n\n    It has the disadvantage that it's only easily implementable for\n    HTML, so it's specific to one output format.\n\n    (For non-HTML writers, the imagemap would have to be replaced with\n    the image only.)\n\n  - _`parts.endnotes` (or \"footnotes\"): See `Footnote & Citation Gathering`_.\n\n  - _`parts.citations`: See `Footnote & Citation Gathering`_.\n\n  - _`misc.language`: Specify (= change) the language of a document at\n    parse time?\n\n    * The misc.settings_ directive suggested below offers a more generic\n      approach.\n\n    * The language of document parts can be indicated by the \"special class\n      value\" ``\"language-\"`` + `BCP 47`_ language code. Class arguments to\n      the title are attached to the document's base node - hence titled\n      documents can be given a different language at parse time. However,\n      \"language by class attribute\" does not change parsing (localized\n      directives etc.), only supporting writers.\n\n    .. _BCP 47: https://www.rfc-editor.org/rfc/bcp/bcp47.txt\n\n\n  - _`misc.settings`: Set any(?) Docutils runtime setting from within\n    a document?  Needs much thought and discussion.\n\n    Security concerns need to be taken into account (it shouldn't be\n    possible to enable ``file_insertion_enabled`` from within a\n    document), and settings that only would have taken effect before\n    the directive (like ``tab-width``) shouldn't be accessible either.\n\n    See this sub-thread:\n    <http://thread.gmane.org/gmane.text.docutils.user/3620/focus=3649>\n\n  - _`misc.gather`: Gather (move, or copy) all instances of a specific\n    element.  A generalization of the `Footnote & Citation Gathering`_\n    ideas.\n\n  - Add a custom \"directive\" directive, equivalent to \"role\"?  For\n    example::\n\n        .. directive:: incr\n\n           .. class:: incremental\n\n        .. incr::\n\n        \"``.. incr::``\" above is equivalent to \"``.. class:: incremental``\".\n\n    Another example::\n\n        .. directive:: printed-links\n\n           .. topic:: Links\n              :class: print-block\n\n              .. target-notes::\n                 :class: print-inline\n\n    This acts like macros.  The directive contents will have to be\n    evaluated when referenced, not when defined.\n\n    * Needs a better name?  \"Macro\", \"substitution\"?\n    * What to do with directive arguments & options when the\n      macro/directive is referenced?\n\n  - Make the meaning of block quotes overridable?  Only a 1-shot\n    though; doesn't solve the general problem.\n\n  - _`conditional directives`:\n\n    .. note:: See also the implementation in Sphinx_.\n\n    Docutils already has the ability to say \"use this content for\n    Writer X\" via the \"raw\" directive. It also does have the ability\n    to say \"use this content for any Writer other than X\" via the\n    \"strip-elements with class\" config value.  However, using \"raw\"\n    input just to select a special writer is inconvenient in many\n    cases.\n    It wouldn't be difficult to get more straightforward support, though.\n\n    My first idea would be to add a set of conditional directives.\n    Let's call them \"writer-is\" and \"writer-is-not\" for discussion\n    purposes (don't worry about implementation details).  We might\n    have::\n\n         .. writer-is:: text-only\n\n            ::\n\n                +----------+\n                |   SNMP   |\n                +----------+\n                |   UDP    |\n                +----------+\n                |    IP    |\n                +----------+\n                | Ethernet |\n                +----------+\n\n         .. writer-is:: pdf\n\n            .. figure:: protocol_stack.eps\n\n         .. writer-is-not:: text-only pdf\n\n            .. figure:: protocol_stack.png\n\n    This could be an interface to the Filter transform\n    (docutils.transforms.components.Filter).\n\n    The ideas in the `adaptable file extensions`_ section above may\n    also be applicable here.\n\n    SVG's \"switch\" statement may provide inspiration.\n\n    Here's an example of a directive that could produce multiple\n    outputs (*both* raw troff pass-through *and* a GIF, for example)\n    and allow the Writer to select. ::\n\n        .. eqn::\n\n           .EQ\n           delim %%\n           .EN\n           %sum from i=o to inf c sup i~=~lim from {m -> inf}\n           sum from i=0 to m sup i%\n           .EQ\n           delim off\n           .EN\n\n  - _`body.example`: Examples; suggested by Simon Hefti.  Semantics as\n    per Docbook's \"example\"; admonition-style, numbered, reference,\n    with a caption/title.\n\n  - _`body.index`: Index targets.\n\n    See `Index Entries & Indexes\n    <./rst/alternatives.html#index-entries-indexes>`__.\n\n  - _`body.literal`: Literal block, possibly \"formal\" (see `object\n    numbering and object references`_ above).  Possible options:\n\n    - \"highlight\" a range of lines\n\n    - include only a specified range of lines\n\n    - \"number\" or \"line-numbers\"? (since 0.9 available with \"code\" directive)\n\n    - \"styled\" could indicate that the directive should check for\n      style comments at the end of lines to indicate styling or\n      markup.\n\n      Specific derivatives (i.e., a \"python-interactive\" directive)\n      could interpret style based on cues, like the \">>> \" prompt and\n      \"input()\"/\"raw_input()\" calls.\n\n    See docutils-users 2003-03-03.\n\n  - _`body.listing`: Code listing with title (to be numbered\n    eventually), equivalent of \"figure\" and \"table\" directives.\n\n  - _`pysource.usage`: Extract a usage message from the program,\n    either by running it at the command line with a ``--help`` option\n    or through an exposed API.  [Suggestion for Optik.]\n\n  - _`body.float`: Generic float that can be used for figures, tables,\n    code listings, flowcharts, ...\n\n    There is a Sphinx extension by Ignacio Fernández Galván <jellby@gmail.com>\n\n       I implemented something for generic floats in sphinx, and submitted a\n       pull request that is still waiting::\n\n        .. float::\n           :type: figure\n           :caption: My caption\n\n      https://github.com/sphinx-doc/sphinx/pull/1858\n\n\nInterpreted Text\n----------------\n\nInterpreted text is entirely a reStructuredText markup construct, a\nway to get around built-in limitations of the medium.  Some roles are\nintended to introduce new doctree elements, such as \"title-reference\".\nOthers are merely convenience features, like \"RFC\".\n\nAll supported interpreted text roles must already be known to the\nParser when they are encountered in a document.  Whether pre-defined\nin core/client code, or in the document, doesn't matter; the roles\njust need to have already been declared.  Adding a new role may\ninvolve adding a new element to the DTD and may require extensive\nsupport, therefore such additions should be well thought-out.  There\nshould be a limited number of roles.\n\nThe only place where no limit is placed on variation is at the start,\nat the Reader/Parser interface.  Transforms are inserted by the Reader\ninto the Transformer's queue, where non-standard elements are\nconverted.  Once past the Transformer, no variation from the standard\nDocutils doctree is possible.\n\nAn example is the Python Source Reader, which will use interpreted\ntext extensively.  The default role will be \"Python identifier\", which\nwill be further interpreted by namespace context into <class>,\n<method>, <module>, <attribute>, etc. elements (see pysource.dtd),\nwhich will be transformed into standard hyperlink references, which\nwill be processed by the various Writers.  No Writer will need to have\nany knowledge of the Python-Reader origin of these elements.\n\n* Add explicit interpreted text roles for the rest of the implicit\n  inline markup constructs: named-reference, anonymous-reference,\n  footnote-reference, citation-reference, substitution-reference,\n  target, uri-reference (& synonyms).\n\n* Add directives for each role as well?  This would allow indirect\n  nested markup::\n\n      This text contains |nested inline markup|.\n\n      .. |nested inline markup| emphasis::\n\n         nested ``inline`` markup\n\n* Implement roles:\n\n  - \"_`raw-wrapped`\" (or \"_`raw-wrap`\"): Base role to wrap raw text\n    around role contents.\n\n    For example, the following reStructuredText source ... ::\n\n        .. role:: red(raw-formatting)\n           :prefix:\n               :html: <font color=\"red\">\n               :latex: {\\color{red}\n           :suffix:\n               :html: </font>\n               :latex: }\n\n        colored :red:`text`\n\n    ... will yield the following document fragment::\n\n        <paragraph>\n            colored\n            <inline classes=\"red\">\n                <raw format=\"html\">\n                    <font color=\"red\">\n                <raw format=\"latex\">\n                    {\\color{red}\n                <inline classes=\"red\">\n                    text\n                <raw format=\"html\">\n                    </font>\n                <raw format=\"latex\">\n                    }\n\n    Possibly without the intermediate \"inline\" node.\n\n  - _`\"acronym\" and \"abbreviation\"`: Associate the full text with a\n    short form.  Jason Diamond's description:\n\n        I want to translate ```reST`:acronym:`` into ``<acronym\n        title='reStructuredText'>reST</acronym>``.  The value of the\n        title attribute has to be defined out-of-band since you can't\n        parameterize interpreted text.  Right now I have them in a\n        separate file but I'm experimenting with creating a directive\n        that will use some form of reST syntax to let you define them.\n\n    Should Docutils complain about undefined acronyms or\n    abbreviations?\n\n    What to do if there are multiple definitions?  How to\n    differentiate between CSS (Content Scrambling System) and CSS\n    (Cascading Style Sheets) in a single document?  David Priest\n    responds,\n\n        The short answer is: you don't.  Anyone who did such a thing\n        would be writing very poor documentation indeed.  (Though I\n        note that `somewhere else in the docs`__, there's mention of\n        allowing replacement text to be associated with the\n        abbreviation.  That takes care of the duplicate\n        acronyms/abbreviations problem, though a writer would be\n        foolish to ever need it.)\n\n        __ `inline parameter syntax`_\n\n    How to define the full text?  Possibilities:\n\n    1. With a directive and a definition list? ::\n\n           .. acronyms::\n\n              reST\n                  reStructuredText\n              DPS\n                  Docstring Processing System\n\n       Would this list remain in the document as a glossary, or would\n       it simply build an internal lookup table?  A \"glossary\"\n       directive could be used to make the intention clear.\n       Acronyms/abbreviations and glossaries could work together.\n\n       Then again, a glossary could be formed by gathering individual\n       definitions from around the document.\n\n    2. Some kind of `inline parameter syntax`_? ::\n\n           `reST <reStructuredText>`:acronym: is `WYSIWYG <what you\n           see is what you get>`:acronym: plaintext markup.\n\n       .. _inline parameter syntax:\n          rst/alternatives.html#parameterized-interpreted-text\n\n    3. A combination of 1 & 2?\n\n       The multiple definitions issue could be handled by establishing\n       rules of priority.  For example, directive-based lookup tables\n       have highest priority, followed by the first inline definition.\n       Multiple definitions in directive-based lookup tables would\n       trigger warnings, similar to the rules of `implicit hyperlink\n       targets`__.\n\n       __ ../ref/rst/restructuredtext.html#implicit-hyperlink-targets\n\n    4. Using substitutions? ::\n\n           .. |reST| acronym:: reST\n              :text: reStructuredText\n\n    What do we do for other formats than HTML which do not support\n    tool tips?  Put the full text in parentheses?\n\n  - \"figure\", \"table\", \"listing\", \"chapter\", \"page\", etc: See `object\n    numbering and object references`_ above.\n\n  - \"glossary-term\": This would establish a link to a glossary.  It\n    would require an associated \"glossary-entry\" directive, whose\n    contents could be a definition list::\n\n        .. glossary-entry::\n\n           term1\n               definition1\n           term2\n               definition2\n\n    This would allow entries to be defined anywhere in the document,\n    and collected (via a \"glossary\" directive perhaps) at one point.\n\n\nDoctree pruning\n---------------\n\n[DG 2017-01-02: These are not definitive to-dos, just one developer's\nopinion. Added 2009-10-13 by Günter Milde, in r6178.]\n[Updated by GM 2017-02-04]\n\nThe number of doctree nodes can be reduced by \"normalizing\" some related\nnodes. This makes the document model and the writers somewhat simpler.\n\n* The \"doctest\" element can be replaced by literal blocks with a class\n  attribute (similar to the \"code\" directive output).\n  The syntax shall be left in reST.\n\n  [DG 2017-01-02:] +0.\n\n  Discussion\n    The syntax could be left in reST (for a set period of time?).\n\n    [DG 2017-01-02:] The syntax must be left in reST, practically\n    forever. Removing it would introduce a huge backwards\n    incompatibility. Any syntax removal must be preceded by a thorough\n    review and planning, including a deprecation warning process. My\n    opinion: it's not worth it.\n\n* \"Normalize\" special admonitions (note, hint, warning, ...) during parsing\n  (similar to _`transforms.writer_aux.Admonitions`). There is no need to\n  keep them as distinct elements in the doctree specification.\n\n  [DG 2017-01-02:] -1: <note>{body}</> is much more concise and\n  expressive than <admonition><title>Note</>{body}</>, and the title\n  translation can be put off until much later in the process.\n\n  [GM 2017-02-04]:\n\n  -0 for <admonition class=note><title>Note</>... instead of <note>:\n     a document is rarely printed/used as doctree or XML.\n\n  +1 reduce the complexity of the doctree\n     (there is no 1:1 rST syntax element <-> doctree node mapping anyway).\n\n  +2 every writer needs 9 visit_*/depart_* method pairs to handle the 9\n     subtypes of an admonition, i.e. we could but also remove 36 redundant\n     methods (HTML, LaTeX, Manpage, ODF).\n\n  -1 the most unfortunately named of these directives will survive. [#]_\n\n     .. [#] with \"biblical touch\" and hard to translate:\n\n            :admonition: | Ermahnung; Verweis; Warnung; Rüge\n                         | (exhortation; censure; warning; reprimand, rebuke)\n\n\n  Keep the special admonition directives in reStructuredText syntax.\n\n  [DG 2017-01-02:] We must definitely keep the syntax. Removing it\n  would introduce a huge backwards incompatibility.\n\n\nUnimplemented Transforms\n========================\n\n* _`Footnote & Citation Gathering`\n\n  Collect and move footnotes & citations to the end of a document or the\n  place of a \"footnotes\" or \"citations\" directive\n  (see `<./ref/rst/directives.html>_`)\n\n  Footnotes:\n    Collect all footnotes that are referenced in the document before the\n    directive (and after an eventually preceding ``.. footnotes::``\n    directive) and insert at this place.\n\n    Allows \"endnotes\" at a configurable place.\n\n  Citations:\n    Collect citations that are referenced ...\n\n    Citations can be:\n\n    a) defined in the document as citation elements\n\n    b) auto-generated from entries in a bibliographic database.\n\n       + based on bibstuff_?\n       + also have a look at\n\n         * CrossTeX_, a backwards-compatible, improved bibtex\n           re-implementation in Python (including HTML export).\n           (development stalled since 2 years)\n\n         * Pybtex_,a drop-in replacement for BibTeX written in Python.\n\n           * BibTeX styles & (experimental) pythonic style API.\n           * Database in BibTeX, BibTeXML and YAML formats.\n           * full Unicode support.\n           * Write to TeX, HTML and plain text.\n\n         * `Zotero plain <http://e6h.org/%7Eegh/hg/zotero-plain/>`__\n           supports Zotero databases and CSL_ styles with Docutils with an\n           ``xcite`` role.\n\n         * `sphinxcontrib-bibtex`_ Sphinx extension with \"bibliography\"\n           directive and \"cite\" role supporting BibTeX databases.\n\n         * `Modified rst2html\n           <http://www.loria.fr/~rougier/coding/article/rst2html.py>`__ by\n           Nicolas Rougier.\n\n\n    * Automatically insert a \"References\" heading?\n\n.. _CrossTeX: http://www.cs.cornell.edu/people/egs/crosstex/\n.. _Pybtex:   http://pybtex.sourceforge.net/\n.. _CSL: http://www.citationstyles.org/\n.. _sphinxcontrib-bibtex: http://sphinxcontrib-bibtex.readthedocs.org/\n\n* _`Reference Merging`\n\n  When merging two or more subdocuments (such as docstrings),\n  conflicting references may need to be resolved.  There may be:\n\n  * duplicate reference and/or substitution names that need to be made\n    unique; and/or\n  * duplicate footnote numbers that need to be renumbered.\n\n  Should this be done before or after reference-resolving transforms\n  are applied?  What about references from within one subdocument to\n  inside another?\n\n* _`Document Splitting`\n\n  If the processed document is written to multiple files (possibly in\n  a directory tree), it will need to be split up.  Internal references\n  will have to be adjusted.\n\n  (HTML only?  Initially, yes.  Eventually, anything should be\n  splittable.)\n\n  Ideas:\n\n  - Insert a \"destination\" attribute into the root element of each\n    split-out document, containing the path/filename.  The Output\n    object or Writer will recognize this attribute and split out the\n    files accordingly.  Must allow for common headers & footers,\n    prev/next, breadcrumbs, etc.\n\n  - Transform a single-root document into a document containing\n    multiple subdocuments, recursively.  The content model of the\n    \"document\" element would have to change to::\n\n        <!ELEMENT document\n            ( (title, subtitle?)?,\n              decoration?,\n              (docinfo, transition?)?,\n              %structure.model;,\n              document* )>\n\n    (I.e., add the last line -- 0 or more document elements.)\n\n    Let's look at the case of hierarchical (directories and files)\n    HTML output.  Each document element containing further document\n    elements would correspond to a directory (with an index.html file\n    for the content preceding the subdocuments).  Each document\n    element containing no subdocuments (i.e., structure model elements\n    only) corresponds to a concrete file with no directory.\n\n    The natural transform would be to map sections to subdocuments,\n    but possibly only a given number of levels deep.\n\n* _`Navigation`\n\n  If a document is split up, each segment will need navigation links:\n  parent, children (small TOC), previous (preorder), next (preorder).\n  Part of `Document Splitting`_?\n\n* _`List of System Messages`\n\n  The ``system_message`` elements are inserted into the document tree,\n  adjacent to the problems themselves where possible.  Some (those\n  generated post-parse) are kept until later, in\n  ``document.messages``, and added as a special final section,\n  \"Docutils System Messages\".\n\n  Docutils could be made to generate hyperlinks to all known\n  system_messages and add them to the document, perhaps to the end of\n  the \"Docutils System Messages\" section.\n\n  Fred L. Drake, Jr. wrote:\n\n      I'd like to propose that both parse- and transformation-time\n      messages are included in the \"Docutils System Messages\" section.\n      If there are no objections, I can make the change.\n\n  The advantage of the current way of doing things is that parse-time\n  system messages don't require a transform; they're already in the\n  document.  This is valuable for testing (unit tests,\n  tools/quicktest.py).  So if we do decide to make a change, I think\n  the insertion of parse-time system messages ought to remain as-is\n  and the Messages transform ought to move all parse-time system\n  messages (remove from their originally inserted positions, insert in\n  System Messages section).\n\n* _`Index Generation`\n\n\nHTML Writer\n===========\n\n* Make the _`list compacting` logic more generic: For example, allow\n  for literal blocks or line blocks inside of compact list items.\n\n  This is not implementable as long as list compacting is done by\n  omitting ``<p>`` tags.  List compacting would need to be done by\n  adjusting CSS margins instead.\n\n  :2015-04-02: The new html writer no longer strips <p> tags but adds the\n               class value ``simple`` to the list.\n               Formatting is done by CSS --- configurable by a custom style\n               sheet.\n\n               Auto-compactization can be overridden by the ``open`` vs.\n               ``compact`` class arguments.\n\n* Idea for field-list rendering: hanging indent::\n\n      Field name (bold): First paragraph of field body begins\n          with the field name inline.\n\n          If the first item of a field body is not a paragraph,\n          it would begin on the following line.\n\n  :2015-04-02: The new html writer writes field-lists as definition lists\n               with class ``field-list``.\n               Formatting is done by CSS --- configurable by a custom style\n               sheet. The default style sheet has some examples, including a\n               run-in field-list style.\n\n* Add more support for <link> elements, especially for navigation\n  bars.\n\n  The framework does not have a notion of document relationships, so\n  probably raw.destination_ should be used.\n\n  We'll have framework support for document relationships when support\n  for `multiple output files`_ is added.  The HTML writer could\n  automatically generate <link> elements then.\n\n  .. _raw.destination: misc.raw_\n\n* Base list compaction on the spacing of source list?  Would require\n  parser support.  (Idea: fantasai, 16 Dec 2002, doc-sig.)\n\n* Add a tool tip (\"title\" attribute?) to footnote back-links\n  identifying them as such.  Text in Docutils language module.\n\n\nPEP/HTML Writer\n===============\n\n* Remove the generic style information (duplicated from html4css1.css)\n  from pep.css to avoid redundancy.\n\n  Set ``stylesheet-path`` to \"html4css.css,pep.css\" and the\n  ``stylesheet-dirs`` accordingly instead. (See the xhtml11 writer for an\n  example.)\n\n\nS5/HTML Writer\n==============\n\n* Add a way to begin an untitled slide.\n\n* Add a way to begin a new slide, continuation, using the same title\n  as the previous slide?  (Unnecessary?)  You need that if you have a\n  lot of items in one section which don't fit on one slide.\n\n  Maybe either this item or the previous one can be realized using\n  transitions.\n\n* Have a timeout on incremental items, so the colour goes away after 1\n  second.\n\n* Add an empty, black last slide (optionally).  Currently the handling\n  of the last slide is not very nice, it re-cycles through the\n  incremental items on the last slide if you hit space-bar after the\n  last item.\n\n* Add a command-line option to disable advance-on-click.\n\n* Add a speaker's master document, which would contain a small version\n  of the slide text with speaker's notes interspersed.  The master\n  document could use ``target=\"whatever\"`` to direct links to a\n  separate window on a second monitor (e.g., a projector).\n\n  .. Note:: This item and the following items are partially\n     accomplished by the S5 1.2 code (currently in alpha), which has\n     not yet been integrated into Docutils.\n\n* Speaker's notes -- how to intersperse?  Could use reST comments\n  (\"..\"), but make them visible in the speaker's master document.  If\n  structure is necessary, we could use a \"comment\" directive (to avoid\n  nonsensical DTD changes, the \"comment\" directive could produce an\n  untitled topic element).\n\n  The speaker's notes could (should?) be separate from S5's handout\n  content.\n\n* The speaker's master document could use frames for easy navigation:\n  TOC on the left, content on the right.\n\n  - It would be nice if clicking in the TOC frame simultaneously\n    linked to both the speaker's notes frame and to the slide window,\n    synchronizing both.  Needs JavaScript?\n\n  - TOC would have to be tightly formatted -- minimal indentation.\n\n  - TOC auto-generated, as in the PEP Reader.  (What if there already\n    is a \"contents\" directive in the document?)\n\n  - There could be another frame on the left (top-left or bottom-left)\n    containing a single \"Next\" link, always pointing to the next slide\n    (synchronized, of course).  Also \"Previous\" link?  FF/Rew go to\n    the beginning of the next/current parent section?  First/Last\n    also?  Tape-player-style buttons like ``|<<  <<  <  >  >>  >>|``?\n\nEpub/HTML Writer\n================\n\nAdd epub as an output format.\n\n  epub is an open file format for ebooks based on HTML, specified by the\n  `International Digital Publishing Forum`_. Thus, documents in epub\n  format are suited to be read with `electronic reading devices`_.\n\nPack the output of a HTML writer and supporting files (e.g. images)\ninto one single epub document.\n\nThere are `links to two 3rd party ePub writers`__ in the Docutils link list.\nTest and consider moving the better one into the docutils core.\n\n__ ../user/links.html#ePub\n.. _International Digital Publishing Forum: http://www.idpf.org/\n.. _electronic reading devices:\n   https://en.wikipedia.org/wiki/List_of_e-book_readers\n\n\nLaTeX writer\n============\n\nAlso see the Problems__ section in the `latex writer documentation`_.\n\n__ ../user/latex.html#problems\n\n.. _latex writer documentation: ../user/latex.html\n\n.. _latex-variants:\n   ../../../sandbox/latex-variants/README.html\n\nBug fixes\n---------\n\n* Too deeply nested lists fail: generate a warning and provide\n  a workaround.\n\n  2017-02-09 this is fixed for enumeration in 0.13.1\n\n  for others, cf. sandbox/latex-variants/tests/rst-levels.txt\n\n* File names of included graphics (see also `grffile` package).\n\n* Paragraph following field-list or table in compound is indented.\n\n  This is a problem with the current DUfieldlist definition and with the\n  use of \"longtable\" for tables. See `other LaTeX constructs and packages\n  instead of re-implementations`_ for alternatives.\n\n\nGenerate clean and configurable LaTeX source\n----------------------------------------------\n\nWhich packages do we want to use?\n\n+ base and \"recommended\" packages\n\n  (packages that should be in a \"reasonably sized and reasonably modern\n  LaTeX installation like the `texlive-latex-recommended` Debian package,\n  say):\n\n+ No \"fancy\" or \"exotic\" requirements.\n\n+ pointers to advanced packages and their use in the `latex writer\n  documentation`_.\n\nConfigurable placement of figure and table floats\n`````````````````````````````````````````````````\n\n* Special class argument to individually place figures?\n\n  Example::\n\n    .. figure:: foo.pdf\n       :class: place-here-if-possible place-top place-bottom\n\n  would be written as ``\\figure[htb]{...}`` with\n  the optional args:\n\n  :H: place-here\n  :h: place-here-if-possible\n  :t: place-top\n  :b: place-bottom\n  :p: place-on-extra-page\n\n  Alternative: class value = \"place-\" + optional arg, e.g. ``:class:\n  place-htb``.\n\nFootnotes\n`````````\n\n+ True footnotes with LaTeX auto-numbering (as option ``--latex-footnotes``)\n  (also for target-footnotes):\n  Write ``\\footnote{<footnote content>}`` at the place of the\n  ``<footnote_reference>`` node.\n\n+ Open questions:\n\n  - Load hyperref_ with option \"hyperfootnotes\" and/or\n    package footnotebackref_ or leave this to the user?\n\n  - Consider cases where LaTeX does not support footnotes\n    (inside tables__, headings__, caption, ...).\n    Use ftnxtra_, tabularx_, tabulary_, longtable_?\n\n    __ http://www.tex.ac.uk/cgi-bin/texfaq2html?label=footintab\n    __ http://www.tex.ac.uk/cgi-bin/texfaq2html?label=ftnsect\n\n  - Consider `multiple footnote refs to common footnote text`__.\n\n    KOMA-script classes and the KOMA scrextend_ package provide\n    ``\\footref`` that can be used for additional references to a\n    ``\\label``-ed footnote. Since 2021-05-01, ``\\footref`` is provided\n    by the LaTeX core, too.\n\n    __ http://www.tex.ac.uk/cgi-bin/texfaq2html?label=multfoot\n\n  - Consider numbered vs. symbolic footnotes.\n\n+ document customization (links to how-to and packages)\n\n.. Footnote packages at CTAN (www.ctan.org/pkg/<packagename>):\n\n   :footnote: provides a \"savenotes\" environment which collects all\n              footnotes and emits them at ``end{savenotes}``\n              (texlive-latex-recommended)\n\n   :ftnxtra_: fixes the issue of footnote inside \\caption{},\n             tabular environment and \\section{} like commands.\n\n   :footnotebackref_: bidirectional links to/from footnote mark to\n                      footnote text.\n\n.. Footnote Discussion:\n\n   `German tutorial\n   <http://www2.informatik.hu-berlin.de/~ahamann/studies/footnotes.pdf>`__\n\n   `wikibooks: footnote workarounds\n   <https://en.wikibooks.org/wiki/LaTeX/Footnotes_and_Margin_Notes#Common_problems_and_workarounds>`__\n\n.. _footnotebackref: https://www.ctan.org/pkg/footnotebackref\n.. _ftnxtra: https://www.ctan.org/pkg/ftnxtra\n.. _hyperref: https://www.ctan.org/pkg/hyperref\n.. _longtable: https://www.ctan.org/pkg/longtable\n.. _scrextend: https://www.ctan.org/pkg/longtable\n.. _tabularx: https://www.ctan.org/pkg/tabularx\n\n\nOther LaTeX constructs and packages instead of re-implementations\n`````````````````````````````````````````````````````````````````\n\n* Check the generated source with package `nag`.\n\n* enumitem_ (texlive-latex-extra) for field-lists?\n\n.. _enumitem: https://www.ctan.org/pkg/enumitem\n\nDefault layout\n--------------\n\n* Use italic instead of slanted for titlereference?\n\n* Start a new paragraph after lists (as currently)\n  or continue (no blank line in source, no parindent in output)?\n\n  Overriding:\n\n  * continue if the `compound paragraph`_ directive is used (as currently),\n    or\n  * force a new paragraph with an empty comment.\n\n* Sidebar handling (environment with `framed`, `marginnote`, `wrapfig`,\n  ...)?\n\n* Use optionlist for docinfo?\n\n* Keep literal-blocks together on a page, avoid pagebreaks.\n\n  Failed experiments up to now: samepage, minipage, pagebreak 1 to 4 before\n  the block.\n\n  Should be possible with ``--literal-block-env==lstlistings`` and some\n  configuration...\n\n* More space between title and subtitle? ::\n\n     -  \\\\ % subtitle%\n     +  \\\\[0.5em] % subtitle%\n\n.. _compound paragraph:\n   ../ref/rst/directives.html#compound-paragraph\n\nTables\n``````\n\n* Improve/simplify logic to set the column width in the output.\n\n  + Assumed reST line length for table width setting configurable, or\n  + use `ltxtable` (a combination of `tabularx` (auto-width) and\n    `longtable` (page breaks)), or\n  + use tabularx column type ``X`` and let LaTeX decide width, or\n  + use tabulary_?\n\n  .. _tabulary: https://www.ctan.org/pkg/tabulary\n\n* From comp.text.tex (13. 4. 2011):\n\n    When using fixed width columns, you should ensure that the total\n    width does not exceed \\linewidth: if the first column is p{6cm}\n    the second one should be p{\\dimexpr\\linewidth-6cm-4\\tabcolsep}\n    because the glue \\tabcolsep is added twice at every column edge.\n    You may also consider to set \\tabcolsep to a different value...\n\n* csv-tables do not have a colwidth.\n\n* Add more classes or options, e.g. for\n\n  + horizontal alignment and rules.\n  + long table vs. tabular (see next item).\n\n* Use tabular instead of longtable for tables in legends or generally\n  inside a float?\n\n  Alternatively, default to tabular and use longtable only if specified\n  by config setting or class argument (analogue to booktable)?\n\n* Table heads and footer for longtable (firstpage lastpage ..)?\n\n* In tools.txt the option tables right column, there should be some more\n  spacing between the description and the next paragraph \"Default:\".\n\n* Paragraph separation in tables is hairy.\n  see http://www.tex.ac.uk/cgi-bin/texfaq2html?label=struttab\n\n  - The strut solution did not work.\n  - setting extrarowheight added ad top of row not between paragraphs in\n    a cell. ALTHOUGH i set it to 2pt because, text is too close to the topline.\n  - baselineskip/stretch does not help.\n\n* Should there be two hlines after table head and on table end?\n\n* Place titled tables in a float ('table' environment)?\n\n  The 'table', 'csv-table', and 'list-table' directives support an (optional)\n  table title. In analogy to the 'figure' directive this should map to a\n  table float.\n\nImage and figure directives\n```````````````````````````\n\n* compare the test case in:\n\n  + `<../../test/functional/input/data/standard.txt>`__\n  + `<../../test/functional/expected/standalone_rst_html4css1.html>`__\n  + `<../../test/functional/expected/standalone_rst_latex.tex>`__\n\n* The default CSS styling for HTML output (plain.css, default.css) lets\n  text following a right- or left-aligned image float to the side of the\n  image/figure.\n\n  + Use this default also for LaTeX?\n\n  + Wrap text around figures/images with class argument \"wrap\"\n    (like the odt writer)?\n\n  Use `wrapfig` (or other recommended) package.\n\n* support more graphic formats (especially SVG, the only standard\n  vector format for HTML)\n\n\nMissing features\n----------------\n\n* support \"figwidth\" argument for figures.\n\n  As the 'figwidth' argument is still ignored and the \"natural width\" of\n  a figure in LaTeX is 100 % of the text width, setting the 'align'\n  argument has currently no effect on the LaTeX output.\n\n* Multiple author entries in docinfo (same thing as in html).\n\n* Consider supporting the \"compact\" option and class argument (from\n  rst2html) as some lists look better compact and others need the space.\n\n* Better citation support\n  (see `Footnote & Citation Gathering`_).\n\n* If ``use-latex-citations`` is used, a bibliography is inserted right at the\n  end of the document.\n\n  Put in place of the to-be-implemented \"citations\" directive\n  (see `Footnote & Citation Gathering`_).\n\n\nUnicode to LaTeX\n````````````````\n\nThe `LyX <http://www.lyx.org>`_ document processor has a comprehensive\nUnicode to LaTeX conversion feature with a file called ``unicodesymbols``\nthat lists LaTeX counterparts for a wide range of Unicode characters.\n\n* Use this in the LaTeXTranslator?\n  Think of copyright issues!\n\n* The \"ucs\" package has many translations in ...doc/latex/ucs/config/\n\n* The bibstuff_ tool ships a `latex_codec` Python module!\n\n.. _bibstuff: http://code.google.com/p/bibstuff/\n\n\nXeTeX writer\n````````````\n\n* Glyphs missing in the font are left out in the PDF without warning\n  (e.g. ⇔ left-right double arrow in the functional test output).\n\n* Disable word-wrap (hyphenation) in literal text locally with\n  ``providecommand{\\nohyphenation}{\\addfontfeatures{HyphenChar=None}}``?\n\n\nproblematic URLs\n````````````````\n\n* ^^ LaTeX's special syntax for characters results in \"strange\" replacements\n  (both with \\href and \\url).\n\n  `file with ^^ <../strange^^name>`__:\n  `<../strange^^name>`__\n\n* Unbalanced braces, { or }, will fail (both with \\href and \\url)::\n\n    `file with { <../strange{name>`__\n    `<../strange{name>`__\n\nCurrently, a warning is written to the error output stream.\n\nFor correct printing, we can\n\n* use the \\href command with \"normal\" escaped name argument, or\n* define a url-command in the preamble ::\n\n    \\urldef{\\fragileURLi}\\nolinkurl{myself%node@gateway.net}\n\nbut need to find a way to insert it as href argument.\n\nThe following fails::\n\n    \\href{https://www.w3.org/XML/Schema^^dev}{\\fragileURLi}\n\nUse %-replacement like http://nowhere/url_with%28parens%29 ?\n\n-> does not work for file paths (with pdflatex and xpdf).\n\n\nadd-stylesheet option\n`````````````````````\n\nFrom http://article.gmane.org/gmane.text.docutils.devel/3429/\n\nThe problem is that since we have a default value, we have to\ndifferentiate between adding another stylesheet and replacing the\ndefault.  I suggest that the existing --stylesheet & --stylesheet-path\noptions keep their semantics to replace the existing settings.  We\ncould introduce new --add-stylesheet & --add-stylesheet-path options,\nwhich accumulate; further --stylesheet/--stylesheet-path options would\nclear these lists.  The stylesheet or stylesheet_path setting (only\none may be set), plus the added_stylesheets and added_stylesheet_paths\nsettings, describe the combined styles.\n\nFor example, this run will have only one custom stylesheet:\n\n    rstpep2html.py --stylesheet-path custom.css ...\n\nThis run will use the default stylesheet, and the custom one:\n\n    rstpep2html.py --add-stylesheet-path custom.css ...\n\nThis run will use the default stylesheet, a custom local stylesheet,\nand an external stylesheet:\n\n    rstpep2html.py --add-stylesheet-path custom.css \\\n        --add-stylesheet https://www.example.org/external.css ...\n\nThis run will use only the second custom stylesheet:\n\n    rstpep2html.py --add-stylesheet-path custom.css \\\n        --stylesheet-path second.css ...\n\n\n\n\nFront-End Tools\n===============\n\n* Parameterize help text & defaults somehow?  Perhaps a callback?  Or\n  initialize ``settings_spec`` in ``__init__`` or ``init_options``?\n\n* Disable common options that don't apply?\n  (This should now be easier with ``frontend.filter_settings_spec``.)\n\n* Add ``--section-numbering`` command line option.  The \"sectnum\"\n  directive should override the ``--no-section-numbering`` command\n  line option then.\n\n* Implement the following suggestions from clig.dev?\n\n     Display output on success, but keep it brief.\n     provide a --quiet option to suppress all non-essential output.\n   \n     Consider chaining several args as input and use --output\n     (or redirection) for output.\n   \n     -- https://clig.dev/#help\n\n.. _partial parsing:\n   https://docs.python.org/3/library/argparse.html#partial-parsing\n\n.. _configuration: ../user/config.html\n.. _transforms: ../api/transforms.html\n\n\n\f\n..\n   Local Variables:\n   mode: indented-text\n   indent-tabs-mode: nil\n   sentence-end-double-space: t\n   fill-column: 70\n   End:\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/docutils_data/docs/dev/website.txt",
    "content": "===================\n Docutils Web Site\n===================\n\n:Author: David Goodger; open to all Docutils developers\n:Contact: docutils-develop@lists.sourceforge.net\n:Date: $Date$\n:Revision: $Revision$\n:Copyright: This document has been placed in the public domain.\n\nThe Docutils web site, <https://docutils.sourceforge.io/>, is\nmaintained by the ``docutils-update.local`` script, run by project\nmaintainers on their local machines.  The script\nwill process any .txt file which is newer than the corresponding .html\nfile in the local copy of the project's web directory and upload the changes\nto the web site at SourceForge.\n\n..  .. old instructions, for cron job:\n\n    The Docutils web site, <https://docutils.sourceforge.io/>, is\n    maintained automatically by the ``docutils-update`` script, run as an\n    hourly cron job on shell.berlios.de (by user \"wiemann\").  The script\n    will process any .txt file which is newer than the corresponding .html\n    file in the project's web directory on shell.berlios.de\n    (``/home/groups/docutils/htdocs/aux/htdocs/``) and upload the changes\n    to the web site at SourceForge.\n\nPlease **do not** add any generated .html files to the Docutils\nrepository.  They will be generated automatically after a one-time\nsetup (`described below`__).\n\n__ `Adding .txt Files`_\n\nThe docutils-update.local__ script is located at\n``sandbox/infrastructure/docutils-update.local``.\n\n__ https://docutils.sourceforge.io/sandbox/infrastructure/docutils-update.local\n\nIf you want to share files via the web, you can upload them using the\nuploaddocutils.sh__ script\n(``sandbox/infrastructure/uploaddocutils.sh``).\n\n__ https://docutils.sourceforge.io/sandbox/infrastructure/uploaddocutils.sh\n\n\nSetting Up\n==========\n\n(TBA)\n\n.. hint::\n  Anyone with checkin privileges can be a web-site maintainer. You need to\n  set up the directories for a local website build.\n\n  The procedure for that was on the docutils-devel list a while ago.\n\n\nAdding .txt Files\n=================\n\nUser/Contributor\n----------------\n\nWhen adding a new .txt file that should be converted to HTML:\n\n#. Edit sandbox/infrastructure/htmlfiles.lst, and add the .html file\n   corresponding to the new .txt file (please keep the sorted order).\n\n#. Commit the edited version to the SVN repository.\n\nMaintainer\n----------\n\n#. If there are new directories in the SVN, allow the update script to run\n   once to create the directories in the filesystem before preparing for\n   HTML processing.\n\n#. Run the sandbox/infrastructure/update-htmlfiles shell script to generate\n   .html files::\n\n      cd <DOCUTILS-ROOT>/docutils/\n      sandbox/infrastructure/update-htmlfiles \\\n      sandbox/infrastructure/htmlfiles.lst\n\n   (Maybe this should become part of docutils-update.local.)\n\n\nRemoving Files & Directories\n============================\n\n#. Remove from SVN\n\n#. Remove to-be-generated HTML files from\n   ``sandbox/infrastructure/htmlfiles.lst``.\n\n#. Removing files and directories from SVN will not trigger their removal\n   from the web site.  Files and directories must be manually removed from\n   sourceforge.net (under ``/home/project-web/docutils/htdocs/``).\n\n\f\n..\n   Local Variables:\n   mode: indented-text\n   indent-tabs-mode: nil\n   sentence-end-double-space: t\n   fill-column: 70\n   End:\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/docutils_data/docs/index.txt",
    "content": "==========================================\n Docutils Project Documentation Overview\n==========================================\n\n:Author: David Goodger\n:Contact: docutils-develop@lists.sourceforge.net\n:Date: $Date$\n:Revision: $Revision$\n:Copyright: This document has been placed in the public domain.\n\nThe latest working documents may be accessed individually below, or\nfrom the ``docs`` directory of the `Docutils distribution`_.\n\n.. _Docutils: https://docutils.sourceforge.io/\n.. _Docutils distribution: https://docutils.sourceforge.io/#download\n\n.. header::\n   Docutils_ | Overview | About__ | Users__ | Reference__ | Developers__\n\n__ `project fundamentals`_\n__ user_\n__ ref_\n__ howto_\n\n\n.. contents::\n\n\nDocutils Stakeholders\n=====================\n\nDocutils stakeholders can be categorized in several groups:\n\n1. End-users: users of reStructuredText and the Docutils tools.\n   Although some are developers (e.g. Python developers utilizing\n   reStructuredText for docstrings in their source), many are not.\n\n2. Client-developers: developers using Docutils as a library,\n   programmers developing *with* Docutils.\n\n3. Component-developers: those who implement application-specific\n   components, directives, and/or roles, separately from Docutils.\n\n4. Core-developers: developers of the Docutils codebase and\n   participants in the Docutils project community.\n\n5. Re-implementers: developers of alternate implementations of\n   Docutils.\n\nThere's a lot of overlap between these groups.  Most (perhaps all)\ncore-developers, component-developers, client-developers, and\nre-implementers are also end-users.  Core-developers are also\nclient-developers, and may also be component-developers in other\nprojects.  Component-developers are also client-developers.\n\n\nProject Fundamentals\n====================\n\nThese files are for all Docutils stakeholders.  They are kept at the\ntop level of the Docutils project directory.\n\n.. class:: narrow run-in\n    \n:README_:  Project overview: quick-start, requirements,\n           installation, and usage.\n:COPYING_: Conditions for Docutils redistribution, with links to\n           licenses.\n:FAQ_:     Docutils Frequently Asked Questions.  If you have a\n           question or issue, there's a good chance it's already\n           answered here.\n:BUGS_:    A list of known bugs, and how to report a bug.\n:RELEASE-NOTES_: Summary of the major changes in recent releases and\n           notice of future incompatible changes.\n:HISTORY_: Detailed change history log.\n:THANKS_:  Acknowledgements.\n\n.. _README: ../README.html\n.. _BUGS: ../BUGS.html\n.. _COPYING: ../COPYING.html\n.. _Docutils FAQ:\n.. _FAQ: ../FAQ.html\n.. _RELEASE-NOTES: ../RELEASE-NOTES.html\n.. _HISTORY: ../HISTORY.html\n.. _THANKS: ../THANKS.html\n\n\n.. _user:\n\nIntroductory & Tutorial Material for End-Users\n==============================================\n\nDocutils-general:\n  * `Docutils Front-End Tools <user/tools.html>`__\n  * `Docutils Configuration <user/config.html>`__\n  * `Docutils Mailing Lists <user/mailing-lists.html>`__\n  * `Docutils Link List <user/links.html>`__\n\nWriter-specific:\n  * `Docutils HTML Writers <user/html.html>`__\n  * `Easy Slide Shows With reStructuredText & S5 <user/slide-shows.html>`__\n  * `Docutils LaTeX Writer <user/latex.html>`__\n  * `Man Page Writer for Docutils <user/manpage.html>`__\n  * `Docutils ODF/OpenOffice/odt Writer <user/odt.html>`__\n\n`reStructuredText <https://docutils.sourceforge.io/rst.html>`_:\n  * `A ReStructuredText Primer <user/rst/quickstart.html>`__\n    (see also the `text source <user/rst/quickstart.txt>`__)\n  * `Quick reStructuredText <user/rst/quickref.html>`__ (user reference)\n  * `reStructuredText Cheat Sheet <user/rst/cheatsheet.txt>`__ (text\n    only; 1 page for syntax, 1 page directive & role reference)\n  * `Demonstration <user/rst/demo.html>`_ \n    of most reStructuredText features\n    (see also the `text source <user/rst/demo.txt>`__)\n\nEditor support:\n  * `Emacs support for reStructuredText <user/emacs.html>`_\n\n\n.. _ref:\n\nReference Material for All Groups\n=================================\n\nMany of these files began as developer specifications, but now that\nthey're mature and used by end-users and client-developers, they have\nbecome reference material.  Successful specs evolve into refs.\n\nDocutils-general:\n  * `The Docutils Document Tree <ref/doctree.html>`__ (incomplete)\n  * `Docutils Generic DTD <ref/docutils.dtd>`__\n  * `OASIS XML Exchange Table Model Declaration Module\n    <ref/soextblx.dtd>`__ (CALS tables DTD module)\n  * `Docutils Design Specification`_ (PEP 258)\n\nreStructuredText_:\n  * `An Introduction to reStructuredText <ref/rst/introduction.html>`__\n    (includes the `Goals <ref/rst/introduction.html#goals>`__ and\n    `History <ref/rst/introduction.html#history>`__ of reStructuredText)\n  * `reStructuredText Markup Specification <ref/rst/restructuredtext.html>`__\n  * `reStructuredText Directives <ref/rst/directives.html>`__\n  * `reStructuredText Interpreted Text Roles <ref/rst/roles.html>`__\n  * `reStructuredText Standard Definition Files\n    <ref/rst/definitions.html>`_\n  * `LaTeX syntax for mathematics <ref/rst/mathematics.html>`__\n    (syntax used in \"math\" directive and role)\n\n.. _peps:\n\nPython Enhancement Proposals\n  * `PEP 256: Docstring Processing System Framework`__ is a high-level\n    generic proposal.  [:PEP:`256` in the `master repository`_]\n  * `PEP 257: Docstring Conventions`__ addresses docstring style and\n    touches on content.  [:PEP:`257` in the `master repository`_]\n  * `PEP 258: Docutils Design Specification`__ is an overview of the\n    architecture of Docutils.  It documents design issues and\n    implementation details.  [:PEP:`258` in the `master repository`_]\n  * `PEP 287: reStructuredText Docstring Format`__ proposes a standard\n    markup syntax.  [:PEP:`287` in the `master repository`_]\n  \n  Please note that PEPs in the `master repository`_ developed\n  independent from the local versions after submission.\n\n  __ peps/pep-0256.html\n  __ peps/pep-0257.html\n  .. _PEP 258:\n  .. _Docutils Design Specification:\n  __ peps/pep-0258.html\n  __ peps/pep-0287.html\n  .. _master repository: https://peps.python.org\n\nPrehistoric:\n  `Setext Documents Mirror`__\n  \n  __ https://docutils.sourceforge.io/mirror/setext.html\n\n\n.. _api:\n\nAPI Reference Material for Client-Developers\n============================================\n\n* `The Docutils Publisher <api/publisher.html>`__\n* `Docutils Runtime Settings <api/runtime-settings.html>`__\n* `Docutils Transforms <api/transforms.html>`__ \n  \nThe `Docutils Design Specification`_ (PEP 258) is a must-read for any\nDocutils developer.\n\n\n.. _howto:\n\nInstructions for Developers\n===========================\n\n:Security: `Deploying Docutils Securely <howto/security.html>`__\n\n* `Inside A Docutils Command-Line Front-End Tool <howto/cmdline-tool.html>`__\n* `Writing HTML (CSS) Stylesheets for Docutils\n  <howto/html-stylesheets.html>`__\n* `Docutils Internationalization <howto/i18n.html>`__\n* `Creating reStructuredText Directives <howto/rst-directives.html>`__\n* `Creating reStructuredText Interpreted Text Roles\n  <howto/rst-roles.html>`__\n\n\n.. _dev:\n\nDevelopment Notes and Plans for Core-Developers\n===============================================\n\nDocutils-general:\n  * `Docutils Hacker's Guide <dev/hacking.html>`__\n  * `Docutils Distributor's Guide <dev/distributing.html>`__\n  * `Docutils To Do List <dev/todo.html>`__\n  * `Docutils Project Policies <dev/policies.html>`__\n  * `Docutils Web Site <dev/website.html>`__\n  * `Docutils Release Procedure <dev/release.html>`__\n  * `The Docutils Subversion Repository <dev/repository.html>`__\n  * `Docutils Testing <dev/testing.html>`__\n  * `Docstring Semantics <dev/semantics.html>`__ (incomplete)\n  * `Python Source Reader <dev/pysource.html>`_ (incomplete)\n  * `Docutils Python DTD <dev/pysource.dtd>`_\n  * `Plan for Enthought API Documentation Tool <dev/enthought-plan.html>`_\n  * `Enthought API Documentation Tool RFP <dev/enthought-rfp.html>`_\n\nreStructuredText_:\n  * `A Record of reStructuredText Syntax Alternatives\n    <dev/rst/alternatives.html>`__\n  * `Problems With StructuredText <dev/rst/problems.html>`__\n\n\f\n..\n   Local Variables:\n   mode: indented-text\n   indent-tabs-mode: nil\n   sentence-end-double-space: t\n   fill-column: 70\n   End:\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/docutils_html_base.py",
    "content": "\"\"\"\nConvert Docutils' documentation from reStructuredText to <format>.\n\"\"\"\n\nimport contextlib\nfrom pathlib import Path\nimport time\n\nimport docutils\nfrom docutils import core\nimport pyperf\nimport memray\nimport contextlib\n\ntry:\n    from docutils.utils.math.math2html import Trace\nexcept ImportError:\n    pass\nelse:\n    Trace.show = lambda message, channel: ...  # don't print to console\n\nDOC_ROOT = (Path(__file__).parent / \"docutils_data\" / \"docs\").resolve()\n\n\ndef build_html(doc_root):\n    elapsed = 0\n    for file in doc_root.rglob(\"*.txt\"):\n        file_contents = file.read_text(encoding=\"utf-8\")\n        t0 = pyperf.perf_counter()\n        with contextlib.nullcontext():\n            with contextlib.suppress(docutils.ApplicationError):\n                core.publish_string(\n                    source=file_contents,\n                    reader_name=\"standalone\",\n                    parser_name=\"restructuredtext\",\n                    writer_name=\"html5\",\n                    settings_overrides={\n                        \"input_encoding\": \"unicode\",\n                        \"output_encoding\": \"unicode\",\n                        \"report_level\": 5,\n                    },\n                )\n        elapsed += pyperf.perf_counter() - t0\n    return elapsed\n\n\ndef bench_docutils(loops, doc_root):\n    runs_total = 0\n    for _ in range(loops):\n        runs_total += build_html(doc_root)\n    return runs_total\n\n\ndef run_benchmark():\n    bench_docutils(1, DOC_ROOT)\n\n\nif __name__ == \"__main__\":\n    run_benchmark()\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/docutils_html_memray.py",
    "content": "\"\"\"\nConvert Docutils' documentation from reStructuredText to <format>.\n\"\"\"\n\nimport contextlib\nfrom pathlib import Path\n\nimport docutils\nfrom docutils import core\nimport pyperf\nfrom memray_helper import get_tracker\n\nfrom docutils.utils.math.math2html import Trace\n\nTrace.show = lambda message, channel: ...  # don't print to console\n\nDOC_ROOT = (Path(__file__).parent / \"docutils_data\" / \"docs\").resolve()\n\n\ndef build_html(doc_root):\n    elapsed = 0.0\n    for file in doc_root.rglob(\"*.txt\"):\n        file_contents = file.read_text(encoding=\"utf-8\")\n        t0 = pyperf.perf_counter()\n        with get_tracker():\n            with contextlib.suppress(docutils.ApplicationError):\n                core.publish_string(\n                    source=file_contents,\n                    reader_name=\"standalone\",\n                    parser_name=\"restructuredtext\",\n                    writer_name=\"html5\",\n                    settings_overrides={\n                        \"input_encoding\": \"unicode\",\n                        \"output_encoding\": \"unicode\",\n                        \"report_level\": 5,\n                    },\n                )\n        elapsed += pyperf.perf_counter() - t0\n    return elapsed\n\n\ndef bench_docutils(loops, doc_root):\n    runs_total = 0\n    for _ in range(loops):\n        runs_total += build_html(doc_root)\n    return runs_total\n\n\ndef add_cmdline_args(cmd, args):\n    cmd.append(\"--doc_root=%s\" % args.doc_root)\n\n\nif __name__ == \"__main__\":\n    runner = pyperf.Runner(add_cmdline_args=add_cmdline_args)\n    runner.metadata[\"description\"] = \"Render documentation with Docutils\"\n    runner.argparser.add_argument(\"--doc_root\", default=DOC_ROOT)\n\n    args = runner.parse_args()\n    runner.bench_time_func(\"docutils\", bench_docutils, Path(args.doc_root))\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/fannkuch_base.py",
    "content": "\"\"\"\nThe Computer Language Benchmarks Game\nhttp://benchmarksgame.alioth.debian.org/\n\nContributed by Sokolov Yura, modified by Tupteq.\n\"\"\"\n\nDEFAULT_ARG = 9\n\n\ndef fannkuch(n):\n    count = list(range(1, n + 1))\n    max_flips = 0\n    m = n - 1\n    r = n\n    perm1 = list(range(n))\n    perm = list(range(n))\n    perm1_ins = perm1.insert\n    perm1_pop = perm1.pop\n\n    while 1:\n        while r != 1:\n            count[r - 1] = r\n            r -= 1\n\n        if perm1[0] != 0 and perm1[m] != m:\n            perm = perm1[:]\n            flips_count = 0\n            k = perm[0]\n            while k:\n                perm[: k + 1] = perm[k::-1]\n                flips_count += 1\n                k = perm[0]\n\n            if flips_count > max_flips:\n                max_flips = flips_count\n\n        while r != n:\n            perm1_ins(r, perm1_pop(0))\n            count[r] -= 1\n            if count[r] > 0:\n                break\n            r += 1\n        else:\n            return max_flips\n\n\ndef run_benchmark():\n    arg = DEFAULT_ARG\n    fannkuch(arg)\n\n\nif __name__ == \"__main__\":\n    run_benchmark()\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/fannkuch_memray.py",
    "content": "\"\"\"\nThe Computer Language Benchmarks Game\nhttp://benchmarksgame.alioth.debian.org/\n\nContributed by Sokolov Yura, modified by Tupteq.\n\"\"\"\n\nimport pyperf\nfrom memray_helper import get_tracker\n\n\nDEFAULT_ARG = 9\n\n\ndef fannkuch(n):\n    with get_tracker():\n        return _fannkuch(n)\n\n\ndef _fannkuch(n):\n    count = list(range(1, n + 1))\n    max_flips = 0\n    m = n - 1\n    r = n\n    perm1 = list(range(n))\n    perm = list(range(n))\n    perm1_ins = perm1.insert\n    perm1_pop = perm1.pop\n\n    while 1:\n        while r != 1:\n            count[r - 1] = r\n            r -= 1\n\n        if perm1[0] != 0 and perm1[m] != m:\n            perm = perm1[:]\n            flips_count = 0\n            k = perm[0]\n            while k:\n                perm[: k + 1] = perm[k::-1]\n                flips_count += 1\n                k = perm[0]\n\n            if flips_count > max_flips:\n                max_flips = flips_count\n\n        while r != n:\n            perm1_ins(r, perm1_pop(0))\n            count[r] -= 1\n            if count[r] > 0:\n                break\n            r += 1\n        else:\n            return max_flips\n\n\nif __name__ == \"__main__\":\n    runner = pyperf.Runner()\n    arg = DEFAULT_ARG\n    runner.bench_func(\"fannkuch\", fannkuch, arg)\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/go_base.py",
    "content": "\"\"\"\nGo board game\n\"\"\"\nimport math\nimport random\n\nSIZE = 9\nGAMES = 200\nKOMI = 7.5\nEMPTY, WHITE, BLACK = 0, 1, 2\nSHOW = {EMPTY: \".\", WHITE: \"o\", BLACK: \"x\"}\nPASS = -1\nMAXMOVES = SIZE * SIZE * 3\nTIMESTAMP = 0\nMOVES = 0\n\n\ndef to_pos(x, y):\n    return y * SIZE + x\n\n\ndef to_xy(pos):\n    y, x = divmod(pos, SIZE)\n    return x, y\n\n\nclass Square:\n    def __init__(self, board, pos):\n        self.board = board\n        self.pos = pos\n        self.timestamp = TIMESTAMP\n        self.removestamp = TIMESTAMP\n        self.zobrist_strings = [random.randrange(9223372036854775807) for i in range(3)]\n\n    def set_neighbours(self):\n        x, y = self.pos % SIZE, self.pos // SIZE\n        self.neighbours = []\n        for dx, dy in [(-1, 0), (1, 0), (0, -1), (0, 1)]:\n            newx, newy = x + dx, y + dy\n            if 0 <= newx < SIZE and 0 <= newy < SIZE:\n                self.neighbours.append(self.board.squares[to_pos(newx, newy)])\n\n    def move(self, color):\n        global TIMESTAMP, MOVES\n        TIMESTAMP += 1\n        MOVES += 1\n        self.board.zobrist.update(self, color)\n        self.color = color\n        self.reference = self\n        self.ledges = 0\n        self.used = True\n        for neighbour in self.neighbours:\n            neighcolor = neighbour.color\n            if neighcolor == EMPTY:\n                self.ledges += 1\n            else:\n                neighbour_ref = neighbour.find(update=True)\n                if neighcolor == color:\n                    if neighbour_ref.reference.pos != self.pos:\n                        self.ledges += neighbour_ref.ledges\n                        neighbour_ref.reference = self\n                    self.ledges -= 1\n                else:\n                    neighbour_ref.ledges -= 1\n                    if neighbour_ref.ledges == 0:\n                        neighbour.remove(neighbour_ref)\n        self.board.zobrist.add()\n\n    def remove(self, reference, update=True):\n        self.board.zobrist.update(self, EMPTY)\n        self.removestamp = TIMESTAMP\n        if update:\n            self.color = EMPTY\n            self.board.emptyset.add(self.pos)\n        #            if color == BLACK:\n        #                self.board.black_dead += 1\n        #            else:\n        #                self.board.white_dead += 1\n        for neighbour in self.neighbours:\n            if neighbour.color != EMPTY and neighbour.removestamp != TIMESTAMP:\n                neighbour_ref = neighbour.find(update)\n                if neighbour_ref.pos == reference.pos:\n                    neighbour.remove(reference, update)\n                else:\n                    if update:\n                        neighbour_ref.ledges += 1\n\n    def find(self, update=False):\n        reference = self.reference\n        if reference.pos != self.pos:\n            reference = reference.find(update)\n            if update:\n                self.reference = reference\n        return reference\n\n    def __repr__(self):\n        return repr(to_xy(self.pos))\n\n\nclass EmptySet:\n    def __init__(self, board):\n        self.board = board\n        self.empties = list(range(SIZE * SIZE))\n        self.empty_pos = list(range(SIZE * SIZE))\n\n    def random_choice(self):\n        choices = len(self.empties)\n        while choices:\n            i = int(random.random() * choices)\n            pos = self.empties[i]\n            if self.board.useful(pos):\n                return pos\n            choices -= 1\n            self.set(i, self.empties[choices])\n            self.set(choices, pos)\n        return PASS\n\n    def add(self, pos):\n        self.empty_pos[pos] = len(self.empties)\n        self.empties.append(pos)\n\n    def remove(self, pos):\n        self.set(self.empty_pos[pos], self.empties[len(self.empties) - 1])\n        self.empties.pop()\n\n    def set(self, i, pos):\n        self.empties[i] = pos\n        self.empty_pos[pos] = i\n\n\nclass ZobristHash:\n    def __init__(self, board):\n        self.board = board\n        self.hash_set = set()\n        self.hash = 0\n        for square in self.board.squares:\n            self.hash ^= square.zobrist_strings[EMPTY]\n        self.hash_set.clear()\n        self.hash_set.add(self.hash)\n\n    def update(self, square, color):\n        self.hash ^= square.zobrist_strings[square.color]\n        self.hash ^= square.zobrist_strings[color]\n\n    def add(self):\n        self.hash_set.add(self.hash)\n\n    def dupe(self):\n        return self.hash in self.hash_set\n\n\nclass Board:\n    def __init__(self):\n        self.squares = [Square(self, pos) for pos in range(SIZE * SIZE)]\n        for square in self.squares:\n            square.set_neighbours()\n        self.reset()\n\n    def reset(self):\n        for square in self.squares:\n            square.color = EMPTY\n            square.used = False\n        self.emptyset = EmptySet(self)\n        self.zobrist = ZobristHash(self)\n        self.color = BLACK\n        self.finished = False\n        self.lastmove = -2\n        self.history = []\n        self.white_dead = 0\n        self.black_dead = 0\n\n    def move(self, pos):\n        square = self.squares[pos]\n        if pos != PASS:\n            square.move(self.color)\n            self.emptyset.remove(square.pos)\n        elif self.lastmove == PASS:\n            self.finished = True\n        if self.color == BLACK:\n            self.color = WHITE\n        else:\n            self.color = BLACK\n        self.lastmove = pos\n        self.history.append(pos)\n\n    def random_move(self):\n        return self.emptyset.random_choice()\n\n    def useful_fast(self, square):\n        if not square.used:\n            for neighbour in square.neighbours:\n                if neighbour.color == EMPTY:\n                    return True\n        return False\n\n    def useful(self, pos):\n        global TIMESTAMP\n        TIMESTAMP += 1\n        square = self.squares[pos]\n        if self.useful_fast(square):\n            return True\n        old_hash = self.zobrist.hash\n        self.zobrist.update(square, self.color)\n        empties = opps = weak_opps = neighs = weak_neighs = 0\n        for neighbour in square.neighbours:\n            neighcolor = neighbour.color\n            if neighcolor == EMPTY:\n                empties += 1\n                continue\n            neighbour_ref = neighbour.find()\n            if neighbour_ref.timestamp != TIMESTAMP:\n                if neighcolor == self.color:\n                    neighs += 1\n                else:\n                    opps += 1\n                neighbour_ref.timestamp = TIMESTAMP\n                neighbour_ref.temp_ledges = neighbour_ref.ledges\n            neighbour_ref.temp_ledges -= 1\n            if neighbour_ref.temp_ledges == 0:\n                if neighcolor == self.color:\n                    weak_neighs += 1\n                else:\n                    weak_opps += 1\n                    neighbour_ref.remove(neighbour_ref, update=False)\n        dupe = self.zobrist.dupe()\n        self.zobrist.hash = old_hash\n        strong_neighs = neighs - weak_neighs\n        strong_opps = opps - weak_opps\n        return not dupe and (\n            empties or weak_opps or (strong_neighs and (strong_opps or weak_neighs))\n        )\n\n    def useful_moves(self):\n        return [pos for pos in self.emptyset.empties if self.useful(pos)]\n\n    def replay(self, history):\n        for pos in history:\n            self.move(pos)\n\n    def score(self, color):\n        if color == WHITE:\n            count = KOMI + self.black_dead\n        else:\n            count = self.white_dead\n        for square in self.squares:\n            squarecolor = square.color\n            if squarecolor == color:\n                count += 1\n            elif squarecolor == EMPTY:\n                surround = 0\n                for neighbour in square.neighbours:\n                    if neighbour.color == color:\n                        surround += 1\n                if surround == len(square.neighbours):\n                    count += 1\n        return count\n\n    def check(self):\n        for square in self.squares:\n            if square.color == EMPTY:\n                continue\n\n            members1 = set([square])\n            changed = True\n            while changed:\n                changed = False\n                for member in members1.copy():\n                    for neighbour in member.neighbours:\n                        if (\n                            neighbour.color == square.color\n                            and neighbour not in members1\n                        ):\n                            changed = True\n                            members1.add(neighbour)\n            ledges1 = 0\n            for member in members1:\n                for neighbour in member.neighbours:\n                    if neighbour.color == EMPTY:\n                        ledges1 += 1\n\n            root = square.find()\n\n            # print 'members1', square, root, members1\n            # print 'ledges1', square, ledges1\n\n            members2 = set()\n            for square2 in self.squares:\n                if square2.color != EMPTY and square2.find() == root:\n                    members2.add(square2)\n\n            ledges2 = root.ledges\n            # print 'members2', square, root, members1\n            # print 'ledges2', square, ledges2\n\n            assert members1 == members2\n            assert ledges1 == ledges2, \"ledges differ at %r: %d %d\" % (\n                square,\n                ledges1,\n                ledges2,\n            )\n\n            set(self.emptyset.empties)\n\n            empties2 = set()\n            for square in self.squares:\n                if square.color == EMPTY:\n                    empties2.add(square.pos)\n\n    def __repr__(self):\n        result = []\n        for y in range(SIZE):\n            start = to_pos(0, y)\n            result.append(\n                \"\".join(\n                    [\n                        SHOW[square.color] + \" \"\n                        for square in self.squares[start : start + SIZE]\n                    ]\n                )\n            )\n        return \"\\n\".join(result)\n\n\nclass UCTNode:\n    def __init__(self):\n        self.bestchild = None\n        self.pos = -1\n        self.wins = 0\n        self.losses = 0\n        self.pos_child = [None for x in range(SIZE * SIZE)]\n        self.parent = None\n\n    def play(self, board):\n        \"\"\"uct tree search\"\"\"\n        color = board.color\n        node = self\n        path = [node]\n        while True:\n            pos = node.select(board)\n            if pos == PASS:\n                break\n            board.move(pos)\n            child = node.pos_child[pos]\n            if not child:\n                child = node.pos_child[pos] = UCTNode()\n                child.unexplored = board.useful_moves()\n                child.pos = pos\n                child.parent = node\n                path.append(child)\n                break\n            path.append(child)\n            node = child\n        self.random_playout(board)\n        self.update_path(board, color, path)\n\n    def select(self, board):\n        \"\"\"select move; unexplored children first, then according to uct value\"\"\"\n        if self.unexplored:\n            i = random.randrange(len(self.unexplored))\n            pos = self.unexplored[i]\n            self.unexplored[i] = self.unexplored[len(self.unexplored) - 1]\n            self.unexplored.pop()\n            return pos\n        elif self.bestchild:\n            return self.bestchild.pos\n        else:\n            return PASS\n\n    def random_playout(self, board):\n        \"\"\"random play until both players pass\"\"\"\n        for x in range(MAXMOVES):  # XXX while not self.finished?\n            if board.finished:\n                break\n            board.move(board.random_move())\n\n    def update_path(self, board, color, path):\n        \"\"\"update win/loss count along path\"\"\"\n        wins = board.score(BLACK) >= board.score(WHITE)\n        for node in path:\n            if color == BLACK:\n                color = WHITE\n            else:\n                color = BLACK\n            if wins == (color == BLACK):\n                node.wins += 1\n            else:\n                node.losses += 1\n            if node.parent:\n                node.parent.bestchild = node.parent.best_child()\n\n    def score(self):\n        winrate = self.wins / float(self.wins + self.losses)\n        parentvisits = self.parent.wins + self.parent.losses\n        if not parentvisits:\n            return winrate\n        nodevisits = self.wins + self.losses\n        return winrate + math.sqrt((math.log(parentvisits)) / (5 * nodevisits))\n\n    def best_child(self):\n        maxscore = -1\n        maxchild = None\n        for child in self.pos_child:\n            if child and child.score() > maxscore:\n                maxchild = child\n                maxscore = child.score()\n        return maxchild\n\n    def best_visited(self):\n        maxvisits = -1\n        maxchild = None\n        for child in self.pos_child:\n            #            if child:\n            # print to_xy(child.pos), child.wins, child.losses, child.score()\n            if child and (child.wins + child.losses) > maxvisits:\n                maxvisits, maxchild = (child.wins + child.losses), child\n        return maxchild\n\n\n# def user_move(board):\n#     while True:\n#         text = input('?').strip()\n#         if text == 'p':\n#             return PASS\n#         if text == 'q':\n#             raise EOFError\n#         try:\n#             x, y = [int(i) for i in text.split()]\n#         except ValueError:\n#             continue\n#         if not (0 <= x < SIZE and 0 <= y < SIZE):\n#             continue\n#         pos = to_pos(x, y)\n#         if board.useful(pos):\n#             return pos\n\n\ndef computer_move(board):\n    pos = board.random_move()\n    if pos == PASS:\n        return PASS\n    tree = UCTNode()\n    tree.unexplored = board.useful_moves()\n    nboard = Board()\n    for game in range(GAMES):\n        node = tree\n        nboard.reset()\n        nboard.replay(board.history)\n        node.play(nboard)\n    return tree.best_visited().pos\n\n\ndef versus_cpu():\n    random.seed(1)\n    board = Board()\n    return computer_move(board)\n\n\ndef run_benchmark():\n    versus_cpu()\n\n\nif __name__ == \"__main__\":\n    run_benchmark()\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/go_memray.py",
    "content": "\"\"\"\nGo board game\n\"\"\"\nimport math\nimport random\n\nimport pyperf\nfrom memray_helper import get_tracker\n\n\nSIZE = 9\nGAMES = 200\nKOMI = 7.5\nEMPTY, WHITE, BLACK = 0, 1, 2\nSHOW = {EMPTY: \".\", WHITE: \"o\", BLACK: \"x\"}\nPASS = -1\nMAXMOVES = SIZE * SIZE * 3\nTIMESTAMP = 0\nMOVES = 0\n\n\ndef to_pos(x, y):\n    return y * SIZE + x\n\n\ndef to_xy(pos):\n    y, x = divmod(pos, SIZE)\n    return x, y\n\n\nclass Square:\n    def __init__(self, board, pos):\n        self.board = board\n        self.pos = pos\n        self.timestamp = TIMESTAMP\n        self.removestamp = TIMESTAMP\n        self.zobrist_strings = [random.randrange(9223372036854775807) for i in range(3)]\n\n    def set_neighbours(self):\n        x, y = self.pos % SIZE, self.pos // SIZE\n        self.neighbours = []\n        for dx, dy in [(-1, 0), (1, 0), (0, -1), (0, 1)]:\n            newx, newy = x + dx, y + dy\n            if 0 <= newx < SIZE and 0 <= newy < SIZE:\n                self.neighbours.append(self.board.squares[to_pos(newx, newy)])\n\n    def move(self, color):\n        global TIMESTAMP, MOVES\n        TIMESTAMP += 1\n        MOVES += 1\n        self.board.zobrist.update(self, color)\n        self.color = color\n        self.reference = self\n        self.ledges = 0\n        self.used = True\n        for neighbour in self.neighbours:\n            neighcolor = neighbour.color\n            if neighcolor == EMPTY:\n                self.ledges += 1\n            else:\n                neighbour_ref = neighbour.find(update=True)\n                if neighcolor == color:\n                    if neighbour_ref.reference.pos != self.pos:\n                        self.ledges += neighbour_ref.ledges\n                        neighbour_ref.reference = self\n                    self.ledges -= 1\n                else:\n                    neighbour_ref.ledges -= 1\n                    if neighbour_ref.ledges == 0:\n                        neighbour.remove(neighbour_ref)\n        self.board.zobrist.add()\n\n    def remove(self, reference, update=True):\n        self.board.zobrist.update(self, EMPTY)\n        self.removestamp = TIMESTAMP\n        if update:\n            self.color = EMPTY\n            self.board.emptyset.add(self.pos)\n        #            if color == BLACK:\n        #                self.board.black_dead += 1\n        #            else:\n        #                self.board.white_dead += 1\n        for neighbour in self.neighbours:\n            if neighbour.color != EMPTY and neighbour.removestamp != TIMESTAMP:\n                neighbour_ref = neighbour.find(update)\n                if neighbour_ref.pos == reference.pos:\n                    neighbour.remove(reference, update)\n                else:\n                    if update:\n                        neighbour_ref.ledges += 1\n\n    def find(self, update=False):\n        reference = self.reference\n        if reference.pos != self.pos:\n            reference = reference.find(update)\n            if update:\n                self.reference = reference\n        return reference\n\n    def __repr__(self):\n        return repr(to_xy(self.pos))\n\n\nclass EmptySet:\n    def __init__(self, board):\n        self.board = board\n        self.empties = list(range(SIZE * SIZE))\n        self.empty_pos = list(range(SIZE * SIZE))\n\n    def random_choice(self):\n        choices = len(self.empties)\n        while choices:\n            i = int(random.random() * choices)\n            pos = self.empties[i]\n            if self.board.useful(pos):\n                return pos\n            choices -= 1\n            self.set(i, self.empties[choices])\n            self.set(choices, pos)\n        return PASS\n\n    def add(self, pos):\n        self.empty_pos[pos] = len(self.empties)\n        self.empties.append(pos)\n\n    def remove(self, pos):\n        self.set(self.empty_pos[pos], self.empties[len(self.empties) - 1])\n        self.empties.pop()\n\n    def set(self, i, pos):\n        self.empties[i] = pos\n        self.empty_pos[pos] = i\n\n\nclass ZobristHash:\n    def __init__(self, board):\n        self.board = board\n        self.hash_set = set()\n        self.hash = 0\n        for square in self.board.squares:\n            self.hash ^= square.zobrist_strings[EMPTY]\n        self.hash_set.clear()\n        self.hash_set.add(self.hash)\n\n    def update(self, square, color):\n        self.hash ^= square.zobrist_strings[square.color]\n        self.hash ^= square.zobrist_strings[color]\n\n    def add(self):\n        self.hash_set.add(self.hash)\n\n    def dupe(self):\n        return self.hash in self.hash_set\n\n\nclass Board:\n    def __init__(self):\n        self.squares = [Square(self, pos) for pos in range(SIZE * SIZE)]\n        for square in self.squares:\n            square.set_neighbours()\n        self.reset()\n\n    def reset(self):\n        for square in self.squares:\n            square.color = EMPTY\n            square.used = False\n        self.emptyset = EmptySet(self)\n        self.zobrist = ZobristHash(self)\n        self.color = BLACK\n        self.finished = False\n        self.lastmove = -2\n        self.history = []\n        self.white_dead = 0\n        self.black_dead = 0\n\n    def move(self, pos):\n        square = self.squares[pos]\n        if pos != PASS:\n            square.move(self.color)\n            self.emptyset.remove(square.pos)\n        elif self.lastmove == PASS:\n            self.finished = True\n        if self.color == BLACK:\n            self.color = WHITE\n        else:\n            self.color = BLACK\n        self.lastmove = pos\n        self.history.append(pos)\n\n    def random_move(self):\n        return self.emptyset.random_choice()\n\n    def useful_fast(self, square):\n        if not square.used:\n            for neighbour in square.neighbours:\n                if neighbour.color == EMPTY:\n                    return True\n        return False\n\n    def useful(self, pos):\n        global TIMESTAMP\n        TIMESTAMP += 1\n        square = self.squares[pos]\n        if self.useful_fast(square):\n            return True\n        old_hash = self.zobrist.hash\n        self.zobrist.update(square, self.color)\n        empties = opps = weak_opps = neighs = weak_neighs = 0\n        for neighbour in square.neighbours:\n            neighcolor = neighbour.color\n            if neighcolor == EMPTY:\n                empties += 1\n                continue\n            neighbour_ref = neighbour.find()\n            if neighbour_ref.timestamp != TIMESTAMP:\n                if neighcolor == self.color:\n                    neighs += 1\n                else:\n                    opps += 1\n                neighbour_ref.timestamp = TIMESTAMP\n                neighbour_ref.temp_ledges = neighbour_ref.ledges\n            neighbour_ref.temp_ledges -= 1\n            if neighbour_ref.temp_ledges == 0:\n                if neighcolor == self.color:\n                    weak_neighs += 1\n                else:\n                    weak_opps += 1\n                    neighbour_ref.remove(neighbour_ref, update=False)\n        dupe = self.zobrist.dupe()\n        self.zobrist.hash = old_hash\n        strong_neighs = neighs - weak_neighs\n        strong_opps = opps - weak_opps\n        return not dupe and (\n            empties or weak_opps or (strong_neighs and (strong_opps or weak_neighs))\n        )\n\n    def useful_moves(self):\n        return [pos for pos in self.emptyset.empties if self.useful(pos)]\n\n    def replay(self, history):\n        for pos in history:\n            self.move(pos)\n\n    def score(self, color):\n        if color == WHITE:\n            count = KOMI + self.black_dead\n        else:\n            count = self.white_dead\n        for square in self.squares:\n            squarecolor = square.color\n            if squarecolor == color:\n                count += 1\n            elif squarecolor == EMPTY:\n                surround = 0\n                for neighbour in square.neighbours:\n                    if neighbour.color == color:\n                        surround += 1\n                if surround == len(square.neighbours):\n                    count += 1\n        return count\n\n    def check(self):\n        for square in self.squares:\n            if square.color == EMPTY:\n                continue\n\n            members1 = set([square])\n            changed = True\n            while changed:\n                changed = False\n                for member in members1.copy():\n                    for neighbour in member.neighbours:\n                        if (\n                            neighbour.color == square.color\n                            and neighbour not in members1\n                        ):\n                            changed = True\n                            members1.add(neighbour)\n            ledges1 = 0\n            for member in members1:\n                for neighbour in member.neighbours:\n                    if neighbour.color == EMPTY:\n                        ledges1 += 1\n\n            root = square.find()\n\n            # print 'members1', square, root, members1\n            # print 'ledges1', square, ledges1\n\n            members2 = set()\n            for square2 in self.squares:\n                if square2.color != EMPTY and square2.find() == root:\n                    members2.add(square2)\n\n            ledges2 = root.ledges\n            # print 'members2', square, root, members1\n            # print 'ledges2', square, ledges2\n\n            assert members1 == members2\n            assert ledges1 == ledges2, \"ledges differ at %r: %d %d\" % (\n                square,\n                ledges1,\n                ledges2,\n            )\n\n            set(self.emptyset.empties)\n\n            empties2 = set()\n            for square in self.squares:\n                if square.color == EMPTY:\n                    empties2.add(square.pos)\n\n    def __repr__(self):\n        result = []\n        for y in range(SIZE):\n            start = to_pos(0, y)\n            result.append(\n                \"\".join(\n                    [\n                        SHOW[square.color] + \" \"\n                        for square in self.squares[start : start + SIZE]\n                    ]\n                )\n            )\n        return \"\\n\".join(result)\n\n\nclass UCTNode:\n    def __init__(self):\n        self.bestchild = None\n        self.pos = -1\n        self.wins = 0\n        self.losses = 0\n        self.pos_child = [None for x in range(SIZE * SIZE)]\n        self.parent = None\n\n    def play(self, board):\n        \"\"\"uct tree search\"\"\"\n        color = board.color\n        node = self\n        path = [node]\n        while True:\n            pos = node.select(board)\n            if pos == PASS:\n                break\n            board.move(pos)\n            child = node.pos_child[pos]\n            if not child:\n                child = node.pos_child[pos] = UCTNode()\n                child.unexplored = board.useful_moves()\n                child.pos = pos\n                child.parent = node\n                path.append(child)\n                break\n            path.append(child)\n            node = child\n        self.random_playout(board)\n        self.update_path(board, color, path)\n\n    def select(self, board):\n        \"\"\"select move; unexplored children first, then according to uct value\"\"\"\n        if self.unexplored:\n            i = random.randrange(len(self.unexplored))\n            pos = self.unexplored[i]\n            self.unexplored[i] = self.unexplored[len(self.unexplored) - 1]\n            self.unexplored.pop()\n            return pos\n        elif self.bestchild:\n            return self.bestchild.pos\n        else:\n            return PASS\n\n    def random_playout(self, board):\n        \"\"\"random play until both players pass\"\"\"\n        for x in range(MAXMOVES):  # XXX while not self.finished?\n            if board.finished:\n                break\n            board.move(board.random_move())\n\n    def update_path(self, board, color, path):\n        \"\"\"update win/loss count along path\"\"\"\n        wins = board.score(BLACK) >= board.score(WHITE)\n        for node in path:\n            if color == BLACK:\n                color = WHITE\n            else:\n                color = BLACK\n            if wins == (color == BLACK):\n                node.wins += 1\n            else:\n                node.losses += 1\n            if node.parent:\n                node.parent.bestchild = node.parent.best_child()\n\n    def score(self):\n        winrate = self.wins / float(self.wins + self.losses)\n        parentvisits = self.parent.wins + self.parent.losses\n        if not parentvisits:\n            return winrate\n        nodevisits = self.wins + self.losses\n        return winrate + math.sqrt((math.log(parentvisits)) / (5 * nodevisits))\n\n    def best_child(self):\n        maxscore = -1\n        maxchild = None\n        for child in self.pos_child:\n            if child and child.score() > maxscore:\n                maxchild = child\n                maxscore = child.score()\n        return maxchild\n\n    def best_visited(self):\n        maxvisits = -1\n        maxchild = None\n        for child in self.pos_child:\n            #            if child:\n            # print to_xy(child.pos), child.wins, child.losses, child.score()\n            if child and (child.wins + child.losses) > maxvisits:\n                maxvisits, maxchild = (child.wins + child.losses), child\n        return maxchild\n\n\n# def user_move(board):\n#     while True:\n#         text = input('?').strip()\n#         if text == 'p':\n#             return PASS\n#         if text == 'q':\n#             raise EOFError\n#         try:\n#             x, y = [int(i) for i in text.split()]\n#         except ValueError:\n#             continue\n#         if not (0 <= x < SIZE and 0 <= y < SIZE):\n#             continue\n#         pos = to_pos(x, y)\n#         if board.useful(pos):\n#             return pos\n\n\ndef computer_move(board):\n    pos = board.random_move()\n    if pos == PASS:\n        return PASS\n    tree = UCTNode()\n    tree.unexplored = board.useful_moves()\n    nboard = Board()\n    for game in range(GAMES):\n        node = tree\n        nboard.reset()\n        nboard.replay(board.history)\n        node.play(nboard)\n    return tree.best_visited().pos\n\n\ndef versus_cpu():\n    with get_tracker():\n        random.seed(1)\n        board = Board()\n        return computer_move(board)\n\n\nif __name__ == \"__main__\":\n    kw = {}\n    if pyperf.python_has_jit():\n        # PyPy needs to compute more warmup values to warmup its JIT\n        kw[\"warmups\"] = 50\n    runner = pyperf.Runner(**kw)\n    runner.metadata[\"description\"] = \"Test the performance of the Go benchmark\"\n    runner.bench_func(\"go\", versus_cpu)\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/hexion_base.py",
    "content": "\"\"\"\nSolver of Hexiom board game.\n\nBenchmark from Laurent Vaucher.\n\nSource: https://github.com/slowfrog/hexiom : hexiom2.py, level36.txt\n\n(Main function tweaked by Armin Rigo.)\n\"\"\"\n\nimport io\n\n# 2016-07-07: CPython 3.6 takes ~25 ms to solve the board level 25\nDEFAULT_LEVEL = 25\n\n\n##################################\nclass Dir(object):\n    def __init__(self, x, y):\n        self.x = x\n        self.y = y\n\n\nDIRS = [Dir(1, 0), Dir(-1, 0), Dir(0, 1), Dir(0, -1), Dir(1, 1), Dir(-1, -1)]\n\nEMPTY = 7\n\n##################################\n\n\nclass Done(object):\n    MIN_CHOICE_STRATEGY = 0\n    MAX_CHOICE_STRATEGY = 1\n    HIGHEST_VALUE_STRATEGY = 2\n    FIRST_STRATEGY = 3\n    MAX_NEIGHBORS_STRATEGY = 4\n    MIN_NEIGHBORS_STRATEGY = 5\n\n    def __init__(self, count, empty=False):\n        self.count = count\n        self.cells = (\n            None if empty else [[0, 1, 2, 3, 4, 5, 6, EMPTY] for i in range(count)]\n        )\n\n    def clone(self):\n        ret = Done(self.count, True)\n        ret.cells = [self.cells[i][:] for i in range(self.count)]\n        return ret\n\n    def __getitem__(self, i):\n        return self.cells[i]\n\n    def set_done(self, i, v):\n        self.cells[i] = [v]\n\n    def already_done(self, i):\n        return len(self.cells[i]) == 1\n\n    def remove(self, i, v):\n        if v in self.cells[i]:\n            self.cells[i].remove(v)\n            return True\n        else:\n            return False\n\n    def remove_all(self, v):\n        for i in range(self.count):\n            self.remove(i, v)\n\n    def remove_unfixed(self, v):\n        changed = False\n        for i in range(self.count):\n            if not self.already_done(i):\n                if self.remove(i, v):\n                    changed = True\n        return changed\n\n    def filter_tiles(self, tiles):\n        for v in range(8):\n            if tiles[v] == 0:\n                self.remove_all(v)\n\n    def next_cell_min_choice(self):\n        minlen = 10\n        mini = -1\n        for i in range(self.count):\n            if 1 < len(self.cells[i]) < minlen:\n                minlen = len(self.cells[i])\n                mini = i\n        return mini\n\n    def next_cell_max_choice(self):\n        maxlen = 1\n        maxi = -1\n        for i in range(self.count):\n            if maxlen < len(self.cells[i]):\n                maxlen = len(self.cells[i])\n                maxi = i\n        return maxi\n\n    def next_cell_highest_value(self):\n        maxval = -1\n        maxi = -1\n        for i in range(self.count):\n            if not self.already_done(i):\n                maxvali = max(k for k in self.cells[i] if k != EMPTY)\n                if maxval < maxvali:\n                    maxval = maxvali\n                    maxi = i\n        return maxi\n\n    def next_cell_first(self):\n        for i in range(self.count):\n            if not self.already_done(i):\n                return i\n        return -1\n\n    def next_cell_max_neighbors(self, pos):\n        maxn = -1\n        maxi = -1\n        for i in range(self.count):\n            if not self.already_done(i):\n                cells_around = pos.hex.get_by_id(i).links\n                n = sum(\n                    1 if (self.already_done(nid) and (self[nid][0] != EMPTY)) else 0\n                    for nid in cells_around\n                )\n                if n > maxn:\n                    maxn = n\n                    maxi = i\n        return maxi\n\n    def next_cell_min_neighbors(self, pos):\n        minn = 7\n        mini = -1\n        for i in range(self.count):\n            if not self.already_done(i):\n                cells_around = pos.hex.get_by_id(i).links\n                n = sum(\n                    1 if (self.already_done(nid) and (self[nid][0] != EMPTY)) else 0\n                    for nid in cells_around\n                )\n                if n < minn:\n                    minn = n\n                    mini = i\n        return mini\n\n    def next_cell(self, pos, strategy=HIGHEST_VALUE_STRATEGY):\n        if strategy == Done.HIGHEST_VALUE_STRATEGY:\n            return self.next_cell_highest_value()\n        elif strategy == Done.MIN_CHOICE_STRATEGY:\n            return self.next_cell_min_choice()\n        elif strategy == Done.MAX_CHOICE_STRATEGY:\n            return self.next_cell_max_choice()\n        elif strategy == Done.FIRST_STRATEGY:\n            return self.next_cell_first()\n        elif strategy == Done.MAX_NEIGHBORS_STRATEGY:\n            return self.next_cell_max_neighbors(pos)\n        elif strategy == Done.MIN_NEIGHBORS_STRATEGY:\n            return self.next_cell_min_neighbors(pos)\n        else:\n            raise Exception(\"Wrong strategy: %d\" % strategy)\n\n\n##################################\n\n\nclass Node(object):\n    def __init__(self, pos, id, links):\n        self.pos = pos\n        self.id = id\n        self.links = links\n\n\n##################################\n\n\nclass Hex(object):\n    def __init__(self, size):\n        self.size = size\n        self.count = 3 * size * (size - 1) + 1\n        self.nodes_by_id = self.count * [None]\n        self.nodes_by_pos = {}\n        id = 0\n        for y in range(size):\n            for x in range(size + y):\n                pos = (x, y)\n                node = Node(pos, id, [])\n                self.nodes_by_pos[pos] = node\n                self.nodes_by_id[node.id] = node\n                id += 1\n        for y in range(1, size):\n            for x in range(y, size * 2 - 1):\n                ry = size + y - 1\n                pos = (x, ry)\n                node = Node(pos, id, [])\n                self.nodes_by_pos[pos] = node\n                self.nodes_by_id[node.id] = node\n                id += 1\n\n    def link_nodes(self):\n        for node in self.nodes_by_id:\n            (x, y) = node.pos\n            for dir in DIRS:\n                nx = x + dir.x\n                ny = y + dir.y\n                if self.contains_pos((nx, ny)):\n                    node.links.append(self.nodes_by_pos[(nx, ny)].id)\n\n    def contains_pos(self, pos):\n        return pos in self.nodes_by_pos\n\n    def get_by_pos(self, pos):\n        return self.nodes_by_pos[pos]\n\n    def get_by_id(self, id):\n        return self.nodes_by_id[id]\n\n\n##################################\nclass Pos(object):\n    def __init__(self, hex, tiles, done=None):\n        self.hex = hex\n        self.tiles = tiles\n        self.done = Done(hex.count) if done is None else done\n\n    def clone(self):\n        return Pos(self.hex, self.tiles, self.done.clone())\n\n\n##################################\n\n\ndef constraint_pass(pos, last_move=None):\n    changed = False\n    left = pos.tiles[:]\n    done = pos.done\n\n    # Remove impossible values from free cells\n    free_cells = (\n        range(done.count) if last_move is None else pos.hex.get_by_id(last_move).links\n    )\n    for i in free_cells:\n        if not done.already_done(i):\n            vmax = 0\n            vmin = 0\n            cells_around = pos.hex.get_by_id(i).links\n            for nid in cells_around:\n                if done.already_done(nid):\n                    if done[nid][0] != EMPTY:\n                        vmin += 1\n                        vmax += 1\n                else:\n                    vmax += 1\n\n            for num in range(7):\n                if (num < vmin) or (num > vmax):\n                    if done.remove(i, num):\n                        changed = True\n\n    # Computes how many of each value is still free\n    for cell in done.cells:\n        if len(cell) == 1:\n            left[cell[0]] -= 1\n\n    for v in range(8):\n        # If there is none, remove the possibility from all tiles\n        if (pos.tiles[v] > 0) and (left[v] == 0):\n            if done.remove_unfixed(v):\n                changed = True\n        else:\n            possible = sum((1 if v in cell else 0) for cell in done.cells)\n            # If the number of possible cells for a value is exactly the number of available tiles\n            # put a tile in each cell\n            if pos.tiles[v] == possible:\n                for i in range(done.count):\n                    cell = done.cells[i]\n                    if (not done.already_done(i)) and (v in cell):\n                        done.set_done(i, v)\n                        changed = True\n\n    # Force empty or non-empty around filled cells\n    filled_cells = range(done.count) if last_move is None else [last_move]\n    for i in filled_cells:\n        if done.already_done(i):\n            num = done[i][0]\n            empties = 0\n            filled = 0\n            unknown = []\n            cells_around = pos.hex.get_by_id(i).links\n            for nid in cells_around:\n                if done.already_done(nid):\n                    if done[nid][0] == EMPTY:\n                        empties += 1\n                    else:\n                        filled += 1\n                else:\n                    unknown.append(nid)\n            if len(unknown) > 0:\n                if num == filled:\n                    for u in unknown:\n                        if EMPTY in done[u]:\n                            done.set_done(u, EMPTY)\n                            changed = True\n                        # else:\n                        #    raise Exception(\"Houston, we've got a problem\")\n                elif num == filled + len(unknown):\n                    for u in unknown:\n                        if done.remove(u, EMPTY):\n                            changed = True\n\n    return changed\n\n\nASCENDING = 1\nDESCENDING = -1\n\n\ndef find_moves(pos, strategy, order):\n    done = pos.done\n    cell_id = done.next_cell(pos, strategy)\n    if cell_id < 0:\n        return []\n\n    if order == ASCENDING:\n        return [(cell_id, v) for v in done[cell_id]]\n    else:\n        # Try higher values first and EMPTY last\n        moves = list(reversed([(cell_id, v) for v in done[cell_id] if v != EMPTY]))\n        if EMPTY in done[cell_id]:\n            moves.append((cell_id, EMPTY))\n        return moves\n\n\ndef play_move(pos, move):\n    (cell_id, i) = move\n    pos.done.set_done(cell_id, i)\n\n\ndef print_pos(pos, output):\n    hex = pos.hex\n    done = pos.done\n    size = hex.size\n    for y in range(size):\n        print(\" \" * (size - y - 1), end=\"\", file=output)\n        for x in range(size + y):\n            pos2 = (x, y)\n            id = hex.get_by_pos(pos2).id\n            if done.already_done(id):\n                c = str(done[id][0]) if done[id][0] != EMPTY else \".\"\n            else:\n                c = \"?\"\n            print(\"%s \" % c, end=\"\", file=output)\n        print(end=\"\\n\", file=output)\n    for y in range(1, size):\n        print(\" \" * y, end=\"\", file=output)\n        for x in range(y, size * 2 - 1):\n            ry = size + y - 1\n            pos2 = (x, ry)\n            id = hex.get_by_pos(pos2).id\n            if done.already_done(id):\n                c = str(done[id][0]) if done[id][0] != EMPTY else \".\"\n            else:\n                c = \"?\"\n            print(\"%s \" % c, end=\"\", file=output)\n        print(end=\"\\n\", file=output)\n\n\nOPEN = 0\nSOLVED = 1\nIMPOSSIBLE = -1\n\n\ndef solved(pos, output, verbose=False):\n    hex = pos.hex\n    tiles = pos.tiles[:]\n    done = pos.done\n    exact = True\n    all_done = True\n    for i in range(hex.count):\n        if len(done[i]) == 0:\n            return IMPOSSIBLE\n        elif done.already_done(i):\n            num = done[i][0]\n            tiles[num] -= 1\n            if tiles[num] < 0:\n                return IMPOSSIBLE\n            vmax = 0\n            vmin = 0\n            if num != EMPTY:\n                cells_around = hex.get_by_id(i).links\n                for nid in cells_around:\n                    if done.already_done(nid):\n                        if done[nid][0] != EMPTY:\n                            vmin += 1\n                            vmax += 1\n                    else:\n                        vmax += 1\n\n                if (num < vmin) or (num > vmax):\n                    return IMPOSSIBLE\n                if num != vmin:\n                    exact = False\n        else:\n            all_done = False\n\n    if (not all_done) or (not exact):\n        return OPEN\n\n    print_pos(pos, output)\n    return SOLVED\n\n\ndef solve_step(prev, strategy, order, output, first=False):\n    if first:\n        pos = prev.clone()\n        while constraint_pass(pos):\n            pass\n    else:\n        pos = prev\n\n    moves = find_moves(pos, strategy, order)\n    if len(moves) == 0:\n        return solved(pos, output)\n    else:\n        for move in moves:\n            # print(\"Trying (%d, %d)\" % (move[0], move[1]))\n            ret = OPEN\n            new_pos = pos.clone()\n            play_move(new_pos, move)\n            # print_pos(new_pos)\n            while constraint_pass(new_pos, move[0]):\n                pass\n            cur_status = solved(new_pos, output)\n            if cur_status != OPEN:\n                ret = cur_status\n            else:\n                ret = solve_step(new_pos, strategy, order, output)\n            if ret == SOLVED:\n                return SOLVED\n    return IMPOSSIBLE\n\n\ndef check_valid(pos):\n    hex = pos.hex\n    tiles = pos.tiles\n    # fill missing entries in tiles\n    tot = 0\n    for i in range(8):\n        if tiles[i] > 0:\n            tot += tiles[i]\n        else:\n            tiles[i] = 0\n    # check total\n    if tot != hex.count:\n        raise Exception(\"Invalid input. Expected %d tiles, got %d.\" % (hex.count, tot))\n\n\ndef solve(pos, strategy, order, output):\n    check_valid(pos)\n    return solve_step(pos, strategy, order, output, first=True)\n\n\n# TODO Write an 'iterator' to go over all x,y positions\n\n\ndef read_file(file):\n    lines = [line.strip(\"\\r\\n\") for line in file.splitlines()]\n    size = int(lines[0])\n    hex = Hex(size)\n    linei = 1\n    tiles = 8 * [0]\n    done = Done(hex.count)\n    for y in range(size):\n        line = lines[linei][size - y - 1 :]\n        p = 0\n        for x in range(size + y):\n            tile = line[p : p + 2]\n            p += 2\n            if tile[1] == \".\":\n                inctile = EMPTY\n            else:\n                inctile = int(tile)\n            tiles[inctile] += 1\n            # Look for locked tiles\n            if tile[0] == \"+\":\n                # print(\"Adding locked tile: %d at pos %d, %d, id=%d\" %\n                #      (inctile, x, y, hex.get_by_pos((x, y)).id))\n                done.set_done(hex.get_by_pos((x, y)).id, inctile)\n\n        linei += 1\n    for y in range(1, size):\n        ry = size - 1 + y\n        line = lines[linei][y:]\n        p = 0\n        for x in range(y, size * 2 - 1):\n            tile = line[p : p + 2]\n            p += 2\n            if tile[1] == \".\":\n                inctile = EMPTY\n            else:\n                inctile = int(tile)\n            tiles[inctile] += 1\n            # Look for locked tiles\n            if tile[0] == \"+\":\n                # print(\"Adding locked tile: %d at pos %d, %d, id=%d\" %\n                #      (inctile, x, ry, hex.get_by_pos((x, ry)).id))\n                done.set_done(hex.get_by_pos((x, ry)).id, inctile)\n        linei += 1\n    hex.link_nodes()\n    done.filter_tiles(tiles)\n    return Pos(hex, tiles, done)\n\n\ndef solve_file(file, strategy, order, output):\n    pos = read_file(file)\n    solve(pos, strategy, order, output)\n\n\nLEVELS = {}\n\nLEVELS[2] = (\n    \"\"\"\n2\n  . 1\n . 1 1\n  1 .\n\"\"\",\n    \"\"\"\\\n 1 1\n. . .\n 1 1\n\"\"\",\n)\n\nLEVELS[10] = (\n    \"\"\"\n3\n  +.+. .\n +. 0 . 2\n . 1+2 1 .\n  2 . 0+.\n   .+.+.\n\"\"\",\n    \"\"\"\\\n  . . 1\n . 1 . 2\n0 . 2 2 .\n . . . .\n  0 . .\n\"\"\",\n)\n\nLEVELS[20] = (\n    \"\"\"\n3\n   . 5 4\n  . 2+.+1\n . 3+2 3 .\n +2+. 5 .\n   . 3 .\n\"\"\",\n    \"\"\"\\\n  3 3 2\n 4 5 . 1\n3 5 2 . .\n 2 . . .\n  . . .\n\"\"\",\n)\n\nLEVELS[25] = (\n    \"\"\"\n3\n   4 . .\n  . . 2 .\n 4 3 2 . 4\n  2 2 3 .\n   4 2 4\n\"\"\",\n    \"\"\"\\\n  3 4 2\n 2 4 4 .\n. . . 4 2\n . 2 4 3\n  . 2 .\n\"\"\",\n)\n\nLEVELS[30] = (\n    \"\"\"\n4\n    5 5 . .\n   3 . 2+2 6\n  3 . 2 . 5 .\n . 3 3+4 4 . 3\n  4 5 4 . 5 4\n   5+2 . . 3\n    4 . . .\n\"\"\",\n    \"\"\"\\\n   3 4 3 .\n  4 6 5 2 .\n 2 5 5 . . 2\n. . 5 4 . 4 3\n . 3 5 4 5 4\n  . 2 . 3 3\n   . . . .\n\"\"\",\n)\n\nLEVELS[36] = (\n    \"\"\"\n4\n    2 1 1 2\n   3 3 3 . .\n  2 3 3 . 4 .\n . 2 . 2 4 3 2\n  2 2 . . . 2\n   4 3 4 . .\n    3 2 3 3\n\"\"\",\n    \"\"\"\\\n   3 4 3 2\n  3 4 4 . 3\n 2 . . 3 4 3\n2 . 1 . 3 . 2\n 3 3 . 2 . 2\n  3 . 2 . 2\n   2 2 . 1\n\"\"\",\n)\n\n\ndef main(loops, level):\n    board, solution = LEVELS[level]\n    order = DESCENDING\n    strategy = Done.FIRST_STRATEGY\n    stream = io.StringIO()\n\n    board = board.strip()\n    expected = solution.rstrip()\n\n    range_it = range(loops)\n\n    for _ in range_it:\n        stream = io.StringIO()\n        solve_file(board, strategy, order, stream)\n        output = stream.getvalue()\n        stream = None\n\n    output = \"\\n\".join(line.rstrip() for line in output.splitlines())\n    if output != expected:\n        raise AssertionError(\n            \"got a wrong answer:\\n%s\\nexpected: %s\" % (output, expected)\n        )\n\n\ndef run_benchmark():\n    main(1, DEFAULT_LEVEL)\n\n\nif __name__ == \"__main__\":\n    run_benchmark()\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/hexion_memray.py",
    "content": "\"\"\"\nSolver of Hexiom board game.\n\nBenchmark from Laurent Vaucher.\n\nSource: https://github.com/slowfrog/hexiom : hexiom2.py, level36.txt\n\n(Main function tweaked by Armin Rigo.)\n\"\"\"\n\nimport io\n\nimport pyperf\nfrom memray_helper import get_tracker\n\n# 2016-07-07: CPython 3.6 takes ~25 ms to solve the board level 25\nDEFAULT_LEVEL = 25\n\n\n##################################\nclass Dir(object):\n    def __init__(self, x, y):\n        self.x = x\n        self.y = y\n\n\nDIRS = [Dir(1, 0), Dir(-1, 0), Dir(0, 1), Dir(0, -1), Dir(1, 1), Dir(-1, -1)]\n\nEMPTY = 7\n\n##################################\n\n\nclass Done(object):\n    MIN_CHOICE_STRATEGY = 0\n    MAX_CHOICE_STRATEGY = 1\n    HIGHEST_VALUE_STRATEGY = 2\n    FIRST_STRATEGY = 3\n    MAX_NEIGHBORS_STRATEGY = 4\n    MIN_NEIGHBORS_STRATEGY = 5\n\n    def __init__(self, count, empty=False):\n        self.count = count\n        self.cells = (\n            None if empty else [[0, 1, 2, 3, 4, 5, 6, EMPTY] for i in range(count)]\n        )\n\n    def clone(self):\n        ret = Done(self.count, True)\n        ret.cells = [self.cells[i][:] for i in range(self.count)]\n        return ret\n\n    def __getitem__(self, i):\n        return self.cells[i]\n\n    def set_done(self, i, v):\n        self.cells[i] = [v]\n\n    def already_done(self, i):\n        return len(self.cells[i]) == 1\n\n    def remove(self, i, v):\n        if v in self.cells[i]:\n            self.cells[i].remove(v)\n            return True\n        else:\n            return False\n\n    def remove_all(self, v):\n        for i in range(self.count):\n            self.remove(i, v)\n\n    def remove_unfixed(self, v):\n        changed = False\n        for i in range(self.count):\n            if not self.already_done(i):\n                if self.remove(i, v):\n                    changed = True\n        return changed\n\n    def filter_tiles(self, tiles):\n        for v in range(8):\n            if tiles[v] == 0:\n                self.remove_all(v)\n\n    def next_cell_min_choice(self):\n        minlen = 10\n        mini = -1\n        for i in range(self.count):\n            if 1 < len(self.cells[i]) < minlen:\n                minlen = len(self.cells[i])\n                mini = i\n        return mini\n\n    def next_cell_max_choice(self):\n        maxlen = 1\n        maxi = -1\n        for i in range(self.count):\n            if maxlen < len(self.cells[i]):\n                maxlen = len(self.cells[i])\n                maxi = i\n        return maxi\n\n    def next_cell_highest_value(self):\n        maxval = -1\n        maxi = -1\n        for i in range(self.count):\n            if not self.already_done(i):\n                maxvali = max(k for k in self.cells[i] if k != EMPTY)\n                if maxval < maxvali:\n                    maxval = maxvali\n                    maxi = i\n        return maxi\n\n    def next_cell_first(self):\n        for i in range(self.count):\n            if not self.already_done(i):\n                return i\n        return -1\n\n    def next_cell_max_neighbors(self, pos):\n        maxn = -1\n        maxi = -1\n        for i in range(self.count):\n            if not self.already_done(i):\n                cells_around = pos.hex.get_by_id(i).links\n                n = sum(\n                    1 if (self.already_done(nid) and (self[nid][0] != EMPTY)) else 0\n                    for nid in cells_around\n                )\n                if n > maxn:\n                    maxn = n\n                    maxi = i\n        return maxi\n\n    def next_cell_min_neighbors(self, pos):\n        minn = 7\n        mini = -1\n        for i in range(self.count):\n            if not self.already_done(i):\n                cells_around = pos.hex.get_by_id(i).links\n                n = sum(\n                    1 if (self.already_done(nid) and (self[nid][0] != EMPTY)) else 0\n                    for nid in cells_around\n                )\n                if n < minn:\n                    minn = n\n                    mini = i\n        return mini\n\n    def next_cell(self, pos, strategy=HIGHEST_VALUE_STRATEGY):\n        if strategy == Done.HIGHEST_VALUE_STRATEGY:\n            return self.next_cell_highest_value()\n        elif strategy == Done.MIN_CHOICE_STRATEGY:\n            return self.next_cell_min_choice()\n        elif strategy == Done.MAX_CHOICE_STRATEGY:\n            return self.next_cell_max_choice()\n        elif strategy == Done.FIRST_STRATEGY:\n            return self.next_cell_first()\n        elif strategy == Done.MAX_NEIGHBORS_STRATEGY:\n            return self.next_cell_max_neighbors(pos)\n        elif strategy == Done.MIN_NEIGHBORS_STRATEGY:\n            return self.next_cell_min_neighbors(pos)\n        else:\n            raise Exception(\"Wrong strategy: %d\" % strategy)\n\n\n##################################\n\n\nclass Node(object):\n    def __init__(self, pos, id, links):\n        self.pos = pos\n        self.id = id\n        self.links = links\n\n\n##################################\n\n\nclass Hex(object):\n    def __init__(self, size):\n        self.size = size\n        self.count = 3 * size * (size - 1) + 1\n        self.nodes_by_id = self.count * [None]\n        self.nodes_by_pos = {}\n        id = 0\n        for y in range(size):\n            for x in range(size + y):\n                pos = (x, y)\n                node = Node(pos, id, [])\n                self.nodes_by_pos[pos] = node\n                self.nodes_by_id[node.id] = node\n                id += 1\n        for y in range(1, size):\n            for x in range(y, size * 2 - 1):\n                ry = size + y - 1\n                pos = (x, ry)\n                node = Node(pos, id, [])\n                self.nodes_by_pos[pos] = node\n                self.nodes_by_id[node.id] = node\n                id += 1\n\n    def link_nodes(self):\n        for node in self.nodes_by_id:\n            (x, y) = node.pos\n            for dir in DIRS:\n                nx = x + dir.x\n                ny = y + dir.y\n                if self.contains_pos((nx, ny)):\n                    node.links.append(self.nodes_by_pos[(nx, ny)].id)\n\n    def contains_pos(self, pos):\n        return pos in self.nodes_by_pos\n\n    def get_by_pos(self, pos):\n        return self.nodes_by_pos[pos]\n\n    def get_by_id(self, id):\n        return self.nodes_by_id[id]\n\n\n##################################\nclass Pos(object):\n    def __init__(self, hex, tiles, done=None):\n        self.hex = hex\n        self.tiles = tiles\n        self.done = Done(hex.count) if done is None else done\n\n    def clone(self):\n        return Pos(self.hex, self.tiles, self.done.clone())\n\n\n##################################\n\n\ndef constraint_pass(pos, last_move=None):\n    changed = False\n    left = pos.tiles[:]\n    done = pos.done\n\n    # Remove impossible values from free cells\n    free_cells = (\n        range(done.count) if last_move is None else pos.hex.get_by_id(last_move).links\n    )\n    for i in free_cells:\n        if not done.already_done(i):\n            vmax = 0\n            vmin = 0\n            cells_around = pos.hex.get_by_id(i).links\n            for nid in cells_around:\n                if done.already_done(nid):\n                    if done[nid][0] != EMPTY:\n                        vmin += 1\n                        vmax += 1\n                else:\n                    vmax += 1\n\n            for num in range(7):\n                if (num < vmin) or (num > vmax):\n                    if done.remove(i, num):\n                        changed = True\n\n    # Computes how many of each value is still free\n    for cell in done.cells:\n        if len(cell) == 1:\n            left[cell[0]] -= 1\n\n    for v in range(8):\n        # If there is none, remove the possibility from all tiles\n        if (pos.tiles[v] > 0) and (left[v] == 0):\n            if done.remove_unfixed(v):\n                changed = True\n        else:\n            possible = sum((1 if v in cell else 0) for cell in done.cells)\n            # If the number of possible cells for a value is exactly the number of available tiles\n            # put a tile in each cell\n            if pos.tiles[v] == possible:\n                for i in range(done.count):\n                    cell = done.cells[i]\n                    if (not done.already_done(i)) and (v in cell):\n                        done.set_done(i, v)\n                        changed = True\n\n    # Force empty or non-empty around filled cells\n    filled_cells = range(done.count) if last_move is None else [last_move]\n    for i in filled_cells:\n        if done.already_done(i):\n            num = done[i][0]\n            empties = 0\n            filled = 0\n            unknown = []\n            cells_around = pos.hex.get_by_id(i).links\n            for nid in cells_around:\n                if done.already_done(nid):\n                    if done[nid][0] == EMPTY:\n                        empties += 1\n                    else:\n                        filled += 1\n                else:\n                    unknown.append(nid)\n            if len(unknown) > 0:\n                if num == filled:\n                    for u in unknown:\n                        if EMPTY in done[u]:\n                            done.set_done(u, EMPTY)\n                            changed = True\n                        # else:\n                        #    raise Exception(\"Houston, we've got a problem\")\n                elif num == filled + len(unknown):\n                    for u in unknown:\n                        if done.remove(u, EMPTY):\n                            changed = True\n\n    return changed\n\n\nASCENDING = 1\nDESCENDING = -1\n\n\ndef find_moves(pos, strategy, order):\n    done = pos.done\n    cell_id = done.next_cell(pos, strategy)\n    if cell_id < 0:\n        return []\n\n    if order == ASCENDING:\n        return [(cell_id, v) for v in done[cell_id]]\n    else:\n        # Try higher values first and EMPTY last\n        moves = list(reversed([(cell_id, v) for v in done[cell_id] if v != EMPTY]))\n        if EMPTY in done[cell_id]:\n            moves.append((cell_id, EMPTY))\n        return moves\n\n\ndef play_move(pos, move):\n    (cell_id, i) = move\n    pos.done.set_done(cell_id, i)\n\n\ndef print_pos(pos, output):\n    hex = pos.hex\n    done = pos.done\n    size = hex.size\n    for y in range(size):\n        print(\" \" * (size - y - 1), end=\"\", file=output)\n        for x in range(size + y):\n            pos2 = (x, y)\n            id = hex.get_by_pos(pos2).id\n            if done.already_done(id):\n                c = str(done[id][0]) if done[id][0] != EMPTY else \".\"\n            else:\n                c = \"?\"\n            print(\"%s \" % c, end=\"\", file=output)\n        print(end=\"\\n\", file=output)\n    for y in range(1, size):\n        print(\" \" * y, end=\"\", file=output)\n        for x in range(y, size * 2 - 1):\n            ry = size + y - 1\n            pos2 = (x, ry)\n            id = hex.get_by_pos(pos2).id\n            if done.already_done(id):\n                c = str(done[id][0]) if done[id][0] != EMPTY else \".\"\n            else:\n                c = \"?\"\n            print(\"%s \" % c, end=\"\", file=output)\n        print(end=\"\\n\", file=output)\n\n\nOPEN = 0\nSOLVED = 1\nIMPOSSIBLE = -1\n\n\ndef solved(pos, output, verbose=False):\n    hex = pos.hex\n    tiles = pos.tiles[:]\n    done = pos.done\n    exact = True\n    all_done = True\n    for i in range(hex.count):\n        if len(done[i]) == 0:\n            return IMPOSSIBLE\n        elif done.already_done(i):\n            num = done[i][0]\n            tiles[num] -= 1\n            if tiles[num] < 0:\n                return IMPOSSIBLE\n            vmax = 0\n            vmin = 0\n            if num != EMPTY:\n                cells_around = hex.get_by_id(i).links\n                for nid in cells_around:\n                    if done.already_done(nid):\n                        if done[nid][0] != EMPTY:\n                            vmin += 1\n                            vmax += 1\n                    else:\n                        vmax += 1\n\n                if (num < vmin) or (num > vmax):\n                    return IMPOSSIBLE\n                if num != vmin:\n                    exact = False\n        else:\n            all_done = False\n\n    if (not all_done) or (not exact):\n        return OPEN\n\n    print_pos(pos, output)\n    return SOLVED\n\n\ndef solve_step(prev, strategy, order, output, first=False):\n    if first:\n        pos = prev.clone()\n        while constraint_pass(pos):\n            pass\n    else:\n        pos = prev\n\n    moves = find_moves(pos, strategy, order)\n    if len(moves) == 0:\n        return solved(pos, output)\n    else:\n        for move in moves:\n            # print(\"Trying (%d, %d)\" % (move[0], move[1]))\n            ret = OPEN\n            new_pos = pos.clone()\n            play_move(new_pos, move)\n            # print_pos(new_pos)\n            while constraint_pass(new_pos, move[0]):\n                pass\n            cur_status = solved(new_pos, output)\n            if cur_status != OPEN:\n                ret = cur_status\n            else:\n                ret = solve_step(new_pos, strategy, order, output)\n            if ret == SOLVED:\n                return SOLVED\n    return IMPOSSIBLE\n\n\ndef check_valid(pos):\n    hex = pos.hex\n    tiles = pos.tiles\n    # fill missing entries in tiles\n    tot = 0\n    for i in range(8):\n        if tiles[i] > 0:\n            tot += tiles[i]\n        else:\n            tiles[i] = 0\n    # check total\n    if tot != hex.count:\n        raise Exception(\"Invalid input. Expected %d tiles, got %d.\" % (hex.count, tot))\n\n\ndef solve(pos, strategy, order, output):\n    check_valid(pos)\n    return solve_step(pos, strategy, order, output, first=True)\n\n\n# TODO Write an 'iterator' to go over all x,y positions\n\n\ndef read_file(file):\n    lines = [line.strip(\"\\r\\n\") for line in file.splitlines()]\n    size = int(lines[0])\n    hex = Hex(size)\n    linei = 1\n    tiles = 8 * [0]\n    done = Done(hex.count)\n    for y in range(size):\n        line = lines[linei][size - y - 1 :]\n        p = 0\n        for x in range(size + y):\n            tile = line[p : p + 2]\n            p += 2\n            if tile[1] == \".\":\n                inctile = EMPTY\n            else:\n                inctile = int(tile)\n            tiles[inctile] += 1\n            # Look for locked tiles\n            if tile[0] == \"+\":\n                # print(\"Adding locked tile: %d at pos %d, %d, id=%d\" %\n                #      (inctile, x, y, hex.get_by_pos((x, y)).id))\n                done.set_done(hex.get_by_pos((x, y)).id, inctile)\n\n        linei += 1\n    for y in range(1, size):\n        ry = size - 1 + y\n        line = lines[linei][y:]\n        p = 0\n        for x in range(y, size * 2 - 1):\n            tile = line[p : p + 2]\n            p += 2\n            if tile[1] == \".\":\n                inctile = EMPTY\n            else:\n                inctile = int(tile)\n            tiles[inctile] += 1\n            # Look for locked tiles\n            if tile[0] == \"+\":\n                # print(\"Adding locked tile: %d at pos %d, %d, id=%d\" %\n                #      (inctile, x, ry, hex.get_by_pos((x, ry)).id))\n                done.set_done(hex.get_by_pos((x, ry)).id, inctile)\n        linei += 1\n    hex.link_nodes()\n    done.filter_tiles(tiles)\n    return Pos(hex, tiles, done)\n\n\ndef solve_file(file, strategy, order, output):\n    pos = read_file(file)\n    solve(pos, strategy, order, output)\n\n\nLEVELS = {}\n\nLEVELS[2] = (\n    \"\"\"\n2\n  . 1\n . 1 1\n  1 .\n\"\"\",\n    \"\"\"\\\n 1 1\n. . .\n 1 1\n\"\"\",\n)\n\nLEVELS[10] = (\n    \"\"\"\n3\n  +.+. .\n +. 0 . 2\n . 1+2 1 .\n  2 . 0+.\n   .+.+.\n\"\"\",\n    \"\"\"\\\n  . . 1\n . 1 . 2\n0 . 2 2 .\n . . . .\n  0 . .\n\"\"\",\n)\n\nLEVELS[20] = (\n    \"\"\"\n3\n   . 5 4\n  . 2+.+1\n . 3+2 3 .\n +2+. 5 .\n   . 3 .\n\"\"\",\n    \"\"\"\\\n  3 3 2\n 4 5 . 1\n3 5 2 . .\n 2 . . .\n  . . .\n\"\"\",\n)\n\nLEVELS[25] = (\n    \"\"\"\n3\n   4 . .\n  . . 2 .\n 4 3 2 . 4\n  2 2 3 .\n   4 2 4\n\"\"\",\n    \"\"\"\\\n  3 4 2\n 2 4 4 .\n. . . 4 2\n . 2 4 3\n  . 2 .\n\"\"\",\n)\n\nLEVELS[30] = (\n    \"\"\"\n4\n    5 5 . .\n   3 . 2+2 6\n  3 . 2 . 5 .\n . 3 3+4 4 . 3\n  4 5 4 . 5 4\n   5+2 . . 3\n    4 . . .\n\"\"\",\n    \"\"\"\\\n   3 4 3 .\n  4 6 5 2 .\n 2 5 5 . . 2\n. . 5 4 . 4 3\n . 3 5 4 5 4\n  . 2 . 3 3\n   . . . .\n\"\"\",\n)\n\nLEVELS[36] = (\n    \"\"\"\n4\n    2 1 1 2\n   3 3 3 . .\n  2 3 3 . 4 .\n . 2 . 2 4 3 2\n  2 2 . . . 2\n   4 3 4 . .\n    3 2 3 3\n\"\"\",\n    \"\"\"\\\n   3 4 3 2\n  3 4 4 . 3\n 2 . . 3 4 3\n2 . 1 . 3 . 2\n 3 3 . 2 . 2\n  3 . 2 . 2\n   2 2 . 1\n\"\"\",\n)\n\n\ndef main(loops, level):\n    board, solution = LEVELS[level]\n    order = DESCENDING\n    strategy = Done.FIRST_STRATEGY\n    stream = io.StringIO()\n\n    board = board.strip()\n    expected = solution.rstrip()\n\n    range_it = range(loops)\n    with get_tracker():\n        t0 = pyperf.perf_counter()\n        for _ in range_it:\n            stream = io.StringIO()\n            solve_file(board, strategy, order, stream)\n            output = stream.getvalue()\n            stream = None\n\n        dt = pyperf.perf_counter() - t0\n\n    output = \"\\n\".join(line.rstrip() for line in output.splitlines())\n    if output != expected:\n        raise AssertionError(\n            \"got a wrong answer:\\n%s\\nexpected: %s\" % (output, expected)\n        )\n\n    return dt\n\n\ndef add_cmdline_args(cmd, args):\n    cmd.extend((\"--level\", str(args.level)))\n\n\nif __name__ == \"__main__\":\n    kw = {\"add_cmdline_args\": add_cmdline_args}\n    if pyperf.python_has_jit():\n        # PyPy needs to compute more warmup values to warmup its JIT\n        kw[\"warmups\"] = 15\n    runner = pyperf.Runner(**kw)\n    levels = sorted(LEVELS)\n    runner.argparser.add_argument(\n        \"--level\",\n        type=int,\n        choices=levels,\n        default=DEFAULT_LEVEL,\n        help=\"Hexiom board level (default: %s)\" % DEFAULT_LEVEL,\n    )\n\n    args = runner.parse_args()\n    runner.metadata[\"description\"] = \"Solver of Hexiom board game\"\n    runner.metadata[\"hexiom_level\"] = args.level\n\n    runner.bench_time_func(\"hexiom\", main, args.level)\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/json_dumps_base.py",
    "content": "import json\nimport sys\n\n\nEMPTY = ({}, 2000)\nSIMPLE_DATA = {\n    \"key1\": 0,\n    \"key2\": True,\n    \"key3\": \"value\",\n    \"key4\": \"foo\",\n    \"key5\": \"string\",\n}\nSIMPLE = (SIMPLE_DATA, 1000)\nNESTED_DATA = {\n    \"key1\": 0,\n    \"key2\": SIMPLE[0],\n    \"key3\": \"value\",\n    \"key4\": SIMPLE[0],\n    \"key5\": SIMPLE[0],\n    \"key\": \"\\u0105\\u0107\\u017c\",\n}\nNESTED = (NESTED_DATA, 1000)\nHUGE = ([NESTED[0]] * 1000, 1)\n\nCASES = [\"EMPTY\", \"SIMPLE\", \"NESTED\", \"HUGE\"]\n\n\ndef bench_json_dumps(data):\n    for obj, count_it in data:\n        for _ in count_it:\n            json.dumps(obj)\n\n\ndef add_cmdline_args(cmd, args):\n    if args.cases:\n        cmd.extend((\"--cases\", args.cases))\n\n\ndef run_benchmark():\n    data = []\n    for case in CASES:\n        obj, count = globals()[case]\n        data.append((obj, range(count)))\n    bench_json_dumps(data)\n\n\ndef main():\n    run_benchmark()\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/json_dumps_memray.py",
    "content": "import json\nimport sys\n\nimport pyperf\nfrom memray_helper import get_tracker\n\n\nEMPTY = ({}, 2000)\nSIMPLE_DATA = {\n    \"key1\": 0,\n    \"key2\": True,\n    \"key3\": \"value\",\n    \"key4\": \"foo\",\n    \"key5\": \"string\",\n}\nSIMPLE = (SIMPLE_DATA, 1000)\nNESTED_DATA = {\n    \"key1\": 0,\n    \"key2\": SIMPLE[0],\n    \"key3\": \"value\",\n    \"key4\": SIMPLE[0],\n    \"key5\": SIMPLE[0],\n    \"key\": \"\\u0105\\u0107\\u017c\",\n}\nNESTED = (NESTED_DATA, 1000)\nHUGE = ([NESTED[0]] * 1000, 1)\n\nCASES = [\"EMPTY\", \"SIMPLE\", \"NESTED\", \"HUGE\"]\n\n\ndef bench_json_dumps(data):\n    with get_tracker():\n        for obj, count_it in data:\n            for _ in count_it:\n                json.dumps(obj)\n\n\ndef add_cmdline_args(cmd, args):\n    if args.cases:\n        cmd.extend((\"--cases\", args.cases))\n\n\ndef main():\n    runner = pyperf.Runner(add_cmdline_args=add_cmdline_args)\n    runner.argparser.add_argument(\n        \"--cases\",\n        help=\"Comma separated list of cases. Available cases: %s. By default, run all cases.\"\n        % \", \".join(CASES),\n    )\n    runner.metadata[\"description\"] = \"Benchmark json.dumps()\"\n\n    args = runner.parse_args()\n    if args.cases:\n        cases = []\n        for case in args.cases.split(\",\"):\n            case = case.strip()\n            if case:\n                cases.append(case)\n        if not cases:\n            print(\"ERROR: empty list of cases\")\n            sys.exit(1)\n    else:\n        cases = CASES\n\n    data = []\n    for case in cases:\n        obj, count = globals()[case]\n        data.append((obj, range(count)))\n\n    runner.bench_func(\"json_dumps\", bench_json_dumps, data)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/json_loads_base.py",
    "content": "\"\"\"Script for testing the performance of json parsing and serialization.\n\nThis will dump/load several real world-representative objects a few\nthousand times. The methodology below was chosen for was chosen to be similar\nto real-world scenarios which operate on single objects at a time.\n\"\"\"\n\n# Python imports\nimport json\nimport random\nimport sys\n\n# Local imports\n\n\nDICT = {\n    \"ads_flags\": 0,\n    \"age\": 18,\n    \"bulletin_count\": 0,\n    \"comment_count\": 0,\n    \"country\": \"BR\",\n    \"encrypted_id\": \"G9urXXAJwjE\",\n    \"favorite_count\": 9,\n    \"first_name\": \"\",\n    \"flags\": 412317970704,\n    \"friend_count\": 0,\n    \"gender\": \"m\",\n    \"gender_for_display\": \"Male\",\n    \"id\": 302935349,\n    \"is_custom_profile_icon\": 0,\n    \"last_name\": \"\",\n    \"locale_preference\": \"pt_BR\",\n    \"member\": 0,\n    \"tags\": [\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"],\n    \"profile_foo_id\": 827119638,\n    \"secure_encrypted_id\": \"Z_xxx2dYx3t4YAdnmfgyKw\",\n    \"session_number\": 2,\n    \"signup_id\": \"201-19225-223\",\n    \"status\": \"A\",\n    \"theme\": 1,\n    \"time_created\": 1225237014,\n    \"time_updated\": 1233134493,\n    \"unread_message_count\": 0,\n    \"user_group\": \"0\",\n    \"username\": \"collinwinter\",\n    \"play_count\": 9,\n    \"view_count\": 7,\n    \"zip\": \"\",\n}\n\nTUPLE = (\n    [\n        265867233,\n        265868503,\n        265252341,\n        265243910,\n        265879514,\n        266219766,\n        266021701,\n        265843726,\n        265592821,\n        265246784,\n        265853180,\n        45526486,\n        265463699,\n        265848143,\n        265863062,\n        265392591,\n        265877490,\n        265823665,\n        265828884,\n        265753032,\n    ],\n    60,\n)\n\n\ndef mutate_dict(orig_dict, random_source):\n    new_dict = dict(orig_dict)\n    for key, value in new_dict.items():\n        rand_val = random_source.random() * sys.maxsize\n        if isinstance(key, (int, bytes, str)):\n            new_dict[key] = type(key)(rand_val)\n    return new_dict\n\n\nrandom_source = random.Random(5)  # Fixed seed.\nDICT_GROUP = [mutate_dict(DICT, random_source) for _ in range(3)]\n\n\ndef bench_json_loads(objs):\n    for obj in objs:\n        # 20 loads\n        json.loads(obj)\n        json.loads(obj)\n        json.loads(obj)\n        json.loads(obj)\n        json.loads(obj)\n        json.loads(obj)\n        json.loads(obj)\n        json.loads(obj)\n        json.loads(obj)\n        json.loads(obj)\n        json.loads(obj)\n        json.loads(obj)\n        json.loads(obj)\n        json.loads(obj)\n        json.loads(obj)\n        json.loads(obj)\n        json.loads(obj)\n        json.loads(obj)\n        json.loads(obj)\n        json.loads(obj)\n\n\ndef run_benchmark():\n    json_dict = json.dumps(DICT)\n    json_tuple = json.dumps(TUPLE)\n    json_dict_group = json.dumps(DICT_GROUP)\n    objs = (json_dict, json_tuple, json_dict_group)\n    bench_json_loads(objs)\n\n\nif __name__ == \"__main__\":\n    run_benchmark()\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/json_loads_memray.py",
    "content": "\"\"\"Script for testing the performance of json parsing and serialization.\n\nThis will dump/load several real world-representative objects a few\nthousand times. The methodology below was chosen for was chosen to be similar\nto real-world scenarios which operate on single objects at a time.\n\"\"\"\n\n# Python imports\nimport json\nimport random\nimport sys\n\n# Local imports\nimport pyperf\nfrom memray_helper import get_tracker\n\n\nDICT = {\n    \"ads_flags\": 0,\n    \"age\": 18,\n    \"bulletin_count\": 0,\n    \"comment_count\": 0,\n    \"country\": \"BR\",\n    \"encrypted_id\": \"G9urXXAJwjE\",\n    \"favorite_count\": 9,\n    \"first_name\": \"\",\n    \"flags\": 412317970704,\n    \"friend_count\": 0,\n    \"gender\": \"m\",\n    \"gender_for_display\": \"Male\",\n    \"id\": 302935349,\n    \"is_custom_profile_icon\": 0,\n    \"last_name\": \"\",\n    \"locale_preference\": \"pt_BR\",\n    \"member\": 0,\n    \"tags\": [\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"],\n    \"profile_foo_id\": 827119638,\n    \"secure_encrypted_id\": \"Z_xxx2dYx3t4YAdnmfgyKw\",\n    \"session_number\": 2,\n    \"signup_id\": \"201-19225-223\",\n    \"status\": \"A\",\n    \"theme\": 1,\n    \"time_created\": 1225237014,\n    \"time_updated\": 1233134493,\n    \"unread_message_count\": 0,\n    \"user_group\": \"0\",\n    \"username\": \"collinwinter\",\n    \"play_count\": 9,\n    \"view_count\": 7,\n    \"zip\": \"\",\n}\n\nTUPLE = (\n    [\n        265867233,\n        265868503,\n        265252341,\n        265243910,\n        265879514,\n        266219766,\n        266021701,\n        265843726,\n        265592821,\n        265246784,\n        265853180,\n        45526486,\n        265463699,\n        265848143,\n        265863062,\n        265392591,\n        265877490,\n        265823665,\n        265828884,\n        265753032,\n    ],\n    60,\n)\n\n\ndef mutate_dict(orig_dict, random_source):\n    new_dict = dict(orig_dict)\n    for key, value in new_dict.items():\n        rand_val = random_source.random() * sys.maxsize\n        if isinstance(key, (int, bytes, str)):\n            new_dict[key] = type(key)(rand_val)\n    return new_dict\n\n\nrandom_source = random.Random(5)  # Fixed seed.\nDICT_GROUP = [mutate_dict(DICT, random_source) for _ in range(3)]\n\n\ndef bench_json_loads(loops, objs):\n    with get_tracker():\n        t0 = pyperf.perf_counter()\n        for _ in range(loops):\n            for obj in objs:\n                # 20 loads\n                json.loads(obj)\n                json.loads(obj)\n                json.loads(obj)\n                json.loads(obj)\n                json.loads(obj)\n                json.loads(obj)\n                json.loads(obj)\n                json.loads(obj)\n                json.loads(obj)\n                json.loads(obj)\n                json.loads(obj)\n                json.loads(obj)\n                json.loads(obj)\n                json.loads(obj)\n                json.loads(obj)\n                json.loads(obj)\n                json.loads(obj)\n                json.loads(obj)\n                json.loads(obj)\n                json.loads(obj)\n        dt = pyperf.perf_counter() - t0\n    return dt\n\n\nif __name__ == \"__main__\":\n    runner = pyperf.Runner()\n    runner.metadata[\"description\"] = \"Benchmark json.loads()\"\n\n    json_dict = json.dumps(DICT)\n    json_tuple = json.dumps(TUPLE)\n    json_dict_group = json.dumps(DICT_GROUP)\n    objs = (json_dict, json_tuple, json_dict_group)\n\n    runner.bench_time_func(\"json_loads\", bench_json_loads, objs)\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/mdp_base.py",
    "content": "import collections\nfrom collections import defaultdict\nfrom fractions import Fraction\n\n\ndef topoSort(roots, getParents):\n    \"\"\"Return a topological sorting of nodes in a graph.\n\n    roots - list of root nodes to search from\n    getParents - function which returns the parents of a given node\n    \"\"\"\n\n    results = []\n    visited = set()\n\n    # Use iterative version to avoid stack limits for large datasets\n    stack = [(node, 0) for node in roots]\n    while stack:\n        current, state = stack.pop()\n        if state == 0:\n            # before recursing\n            if current not in visited:\n                visited.add(current)\n                stack.append((current, 1))\n                stack.extend((parent, 0) for parent in getParents(current))\n        else:\n            # after recursing\n            assert current in visited\n            results.append(current)\n    return results\n\n\ndef getDamages(L, A, D, B, stab, te):\n    x = (2 * L) // 5\n    x = ((x + 2) * A * B) // (D * 50) + 2\n    if stab:\n        x += x // 2\n    x = int(x * te)\n    return [(x * z) // 255 for z in range(217, 256)]\n\n\ndef getCritDist(L, p, A1, A2, D1, D2, B, stab, te):\n    p = min(p, Fraction(1))\n    norm = getDamages(L, A1, D1, B, stab, te)\n    crit = getDamages(L * 2, A2, D2, B, stab, te)\n\n    dist = defaultdict(Fraction)\n    for mult, vals in zip([1 - p, p], [norm, crit]):\n        mult /= len(vals)\n        for x in vals:\n            dist[x] += mult\n    return dist\n\n\ndef plus12(x):\n    return x + x // 8\n\n\nstats_t = collections.namedtuple(\"stats_t\", [\"atk\", \"df\", \"speed\", \"spec\"])\nNOMODS = stats_t(0, 0, 0, 0)\n\n\nfixeddata_t = collections.namedtuple(\n    \"fixeddata_t\", [\"maxhp\", \"stats\", \"lvl\", \"badges\", \"basespeed\"]\n)\nhalfstate_t = collections.namedtuple(\n    \"halfstate_t\", [\"fixed\", \"hp\", \"status\", \"statmods\", \"stats\"]\n)\n\n\ndef applyHPChange(hstate, change):\n    hp = min(hstate.fixed.maxhp, max(0, hstate.hp + change))\n    return hstate._replace(hp=hp)\n\n\ndef applyBadgeBoosts(badges, stats):\n    return stats_t(*[(plus12(x) if b else x) for x, b in zip(stats, badges)])\n\n\nattack_stats_t = collections.namedtuple(\n    \"attack_stats_t\", [\"power\", \"isspec\", \"stab\", \"te\", \"crit\"]\n)\nattack_data = {\n    \"Ember\": attack_stats_t(40, True, True, 0.5, False),\n    \"Dig\": attack_stats_t(100, False, False, 1, False),\n    \"Slash\": attack_stats_t(70, False, False, 1, True),\n    \"Water Gun\": attack_stats_t(40, True, True, 2, False),\n    \"Bubblebeam\": attack_stats_t(65, True, True, 2, False),\n}\n\n\ndef _applyActionSide1(state, act):\n    me, them, extra = state\n\n    if act == \"Super Potion\":\n        me = applyHPChange(me, 50)\n        return {(me, them, extra): Fraction(1)}\n\n    mdata = attack_data[act]\n    aind = 3 if mdata.isspec else 0\n    dind = 3 if mdata.isspec else 1\n    pdiv = 64 if mdata.crit else 512\n    dmg_dist = getCritDist(\n        me.fixed.lvl,\n        Fraction(me.fixed.basespeed, pdiv),\n        me.stats[aind],\n        me.fixed.stats[aind],\n        them.stats[dind],\n        them.fixed.stats[dind],\n        mdata.power,\n        mdata.stab,\n        mdata.te,\n    )\n\n    dist = defaultdict(Fraction)\n    for dmg, p in dmg_dist.items():\n        them2 = applyHPChange(them, -dmg)\n        dist[me, them2, extra] += p\n    return dist\n\n\ndef _applyAction(state, side, act):\n    if side == 0:\n        return _applyActionSide1(state, act)\n    else:\n        me, them, extra = state\n        dist = _applyActionSide1((them, me, extra), act)\n        return {(k[1], k[0], k[2]): v for k, v in dist.items()}\n\n\nclass Battle(object):\n    def __init__(self):\n        self.successors = {}\n        self.min = defaultdict(float)\n        self.max = defaultdict(lambda: 1.0)\n        self.frozen = set()\n\n        self.win = 4, True\n        self.loss = 4, False\n        self.max[self.loss] = 0.0\n        self.min[self.win] = 1.0\n        self.frozen.update([self.win, self.loss])\n\n    def _getSuccessorsA(self, statep):\n        st, state = statep\n        for action in [\"Dig\", \"Super Potion\"]:\n            yield (1, state, action)\n\n    def _applyActionPair(self, state, side1, act1, side2, act2, dist, pmult):\n        for newstate, p in _applyAction(state, side1, act1).items():\n            if newstate[0].hp == 0:\n                newstatep = self.loss\n            elif newstate[1].hp == 0:\n                newstatep = self.win\n            else:\n                newstatep = 2, newstate, side2, act2\n            dist[newstatep] += p * pmult\n\n    def _getSuccessorsB(self, statep):\n        st, state, action = statep\n        dist = defaultdict(Fraction)\n        for eact, p in [\n            (\"Water Gun\", Fraction(64, 130)),\n            (\"Bubblebeam\", Fraction(66, 130)),\n        ]:\n            priority1 = state[0].stats.speed + 10000 * (action == \"Super Potion\")\n            priority2 = state[1].stats.speed + 10000 * (action == \"X Defend\")\n\n            if priority1 > priority2:\n                self._applyActionPair(state, 0, action, 1, eact, dist, p)\n            elif priority1 < priority2:\n                self._applyActionPair(state, 1, eact, 0, action, dist, p)\n            else:\n                self._applyActionPair(state, 0, action, 1, eact, dist, p / 2)\n                self._applyActionPair(state, 1, eact, 0, action, dist, p / 2)\n\n        return {k: float(p) for k, p in dist.items() if p > 0}\n\n    def _getSuccessorsC(self, statep):\n        st, state, side, action = statep\n        dist = defaultdict(Fraction)\n        for newstate, p in _applyAction(state, side, action).items():\n            if newstate[0].hp == 0:\n                newstatep = self.loss\n            elif newstate[1].hp == 0:\n                newstatep = self.win\n            else:\n                newstatep = 0, newstate\n            dist[newstatep] += p\n        return {k: float(p) for k, p in dist.items() if p > 0}\n\n    def getSuccessors(self, statep):\n        try:\n            return self.successors[statep]\n        except KeyError:\n            st = statep[0]\n        if st == 0:\n            result = list(self._getSuccessorsA(statep))\n        else:\n            if st == 1:\n                dist = self._getSuccessorsB(statep)\n            elif st == 2:\n                dist = self._getSuccessorsC(statep)\n            result = sorted(dist.items(), key=lambda t: (-t[1], t[0]))\n        self.successors[statep] = result\n        return result\n\n    def getSuccessorsList(self, statep):\n        if statep[0] == 4:\n            return []\n        temp = self.getSuccessors(statep)\n        if statep[0] != 0:\n            temp = list(zip(*temp))[0] if temp else []\n        return temp\n\n    def evaluate(self, tolerance=0.15):\n        badges = 1, 0, 0, 0\n\n        starfixed = fixeddata_t(59, stats_t(40, 44, 56, 50), 11, NOMODS, 115)\n        starhalf = halfstate_t(starfixed, 59, 0, NOMODS, stats_t(40, 44, 56, 50))\n        charfixed = fixeddata_t(63, stats_t(39, 34, 46, 38), 26, badges, 65)\n        charhalf = halfstate_t(\n            charfixed, 63, 0, NOMODS, applyBadgeBoosts(badges, stats_t(39, 34, 46, 38))\n        )\n        initial_state = charhalf, starhalf, 0\n        initial_statep = 0, initial_state\n\n        dmin, dmax, frozen = self.min, self.max, self.frozen\n        stateps = topoSort([initial_statep], self.getSuccessorsList)\n\n        itercount = 0\n        while dmax[initial_statep] - dmin[initial_statep] > tolerance:\n            itercount += 1\n\n            for sp in stateps:\n                if sp in frozen:\n                    continue\n\n                if sp[0] == 0:\n                    # choice node\n                    dmin[sp] = max(dmin[sp2] for sp2 in self.getSuccessors(sp))\n                    dmax[sp] = max(dmax[sp2] for sp2 in self.getSuccessors(sp))\n                else:\n                    dmin[sp] = sum(dmin[sp2] * p for sp2, p in self.getSuccessors(sp))\n                    dmax[sp] = sum(dmax[sp2] * p for sp2, p in self.getSuccessors(sp))\n\n                if dmin[sp] >= dmax[sp]:\n                    dmax[sp] = dmin[sp] = (dmin[sp] + dmax[sp]) / 2\n                    frozen.add(sp)\n        return (dmax[initial_statep] + dmin[initial_statep]) / 2\n\n\ndef bench_mdp(loops):\n    expected = 0.89873589887\n    max_diff = 1e-6\n    range_it = range(loops)\n\n    for _ in range_it:\n        result = Battle().evaluate(0.192)\n\n    if abs(result - expected) > max_diff:\n        raise Exception(\n            \"invalid result: got %s, expected %s \"\n            \"(diff: %s, max diff: %s)\" % (result, expected, result - expected, max_diff)\n        )\n\n\ndef run_benchmark():\n    bench_mdp(1)\n\n\nif __name__ == \"__main__\":\n    run_benchmark()\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/mdp_memray.py",
    "content": "import collections\nfrom collections import defaultdict\nfrom fractions import Fraction\nfrom memray_helper import get_tracker\n\nimport pyperf\n\n\ndef topoSort(roots, getParents):\n    \"\"\"Return a topological sorting of nodes in a graph.\n\n    roots - list of root nodes to search from\n    getParents - function which returns the parents of a given node\n    \"\"\"\n\n    results = []\n    visited = set()\n\n    # Use iterative version to avoid stack limits for large datasets\n    stack = [(node, 0) for node in roots]\n    while stack:\n        current, state = stack.pop()\n        if state == 0:\n            # before recursing\n            if current not in visited:\n                visited.add(current)\n                stack.append((current, 1))\n                stack.extend((parent, 0) for parent in getParents(current))\n        else:\n            # after recursing\n            assert current in visited\n            results.append(current)\n    return results\n\n\ndef getDamages(L, A, D, B, stab, te):\n    x = (2 * L) // 5\n    x = ((x + 2) * A * B) // (D * 50) + 2\n    if stab:\n        x += x // 2\n    x = int(x * te)\n    return [(x * z) // 255 for z in range(217, 256)]\n\n\ndef getCritDist(L, p, A1, A2, D1, D2, B, stab, te):\n    p = min(p, Fraction(1))\n    norm = getDamages(L, A1, D1, B, stab, te)\n    crit = getDamages(L * 2, A2, D2, B, stab, te)\n\n    dist = defaultdict(Fraction)\n    for mult, vals in zip([1 - p, p], [norm, crit]):\n        mult /= len(vals)\n        for x in vals:\n            dist[x] += mult\n    return dist\n\n\ndef plus12(x):\n    return x + x // 8\n\n\nstats_t = collections.namedtuple(\"stats_t\", [\"atk\", \"df\", \"speed\", \"spec\"])\nNOMODS = stats_t(0, 0, 0, 0)\n\n\nfixeddata_t = collections.namedtuple(\n    \"fixeddata_t\", [\"maxhp\", \"stats\", \"lvl\", \"badges\", \"basespeed\"]\n)\nhalfstate_t = collections.namedtuple(\n    \"halfstate_t\", [\"fixed\", \"hp\", \"status\", \"statmods\", \"stats\"]\n)\n\n\ndef applyHPChange(hstate, change):\n    hp = min(hstate.fixed.maxhp, max(0, hstate.hp + change))\n    return hstate._replace(hp=hp)\n\n\ndef applyBadgeBoosts(badges, stats):\n    return stats_t(*[(plus12(x) if b else x) for x, b in zip(stats, badges)])\n\n\nattack_stats_t = collections.namedtuple(\n    \"attack_stats_t\", [\"power\", \"isspec\", \"stab\", \"te\", \"crit\"]\n)\nattack_data = {\n    \"Ember\": attack_stats_t(40, True, True, 0.5, False),\n    \"Dig\": attack_stats_t(100, False, False, 1, False),\n    \"Slash\": attack_stats_t(70, False, False, 1, True),\n    \"Water Gun\": attack_stats_t(40, True, True, 2, False),\n    \"Bubblebeam\": attack_stats_t(65, True, True, 2, False),\n}\n\n\ndef _applyActionSide1(state, act):\n    me, them, extra = state\n\n    if act == \"Super Potion\":\n        me = applyHPChange(me, 50)\n        return {(me, them, extra): Fraction(1)}\n\n    mdata = attack_data[act]\n    aind = 3 if mdata.isspec else 0\n    dind = 3 if mdata.isspec else 1\n    pdiv = 64 if mdata.crit else 512\n    dmg_dist = getCritDist(\n        me.fixed.lvl,\n        Fraction(me.fixed.basespeed, pdiv),\n        me.stats[aind],\n        me.fixed.stats[aind],\n        them.stats[dind],\n        them.fixed.stats[dind],\n        mdata.power,\n        mdata.stab,\n        mdata.te,\n    )\n\n    dist = defaultdict(Fraction)\n    for dmg, p in dmg_dist.items():\n        them2 = applyHPChange(them, -dmg)\n        dist[me, them2, extra] += p\n    return dist\n\n\ndef _applyAction(state, side, act):\n    if side == 0:\n        return _applyActionSide1(state, act)\n    else:\n        me, them, extra = state\n        dist = _applyActionSide1((them, me, extra), act)\n        return {(k[1], k[0], k[2]): v for k, v in dist.items()}\n\n\nclass Battle(object):\n    def __init__(self):\n        self.successors = {}\n        self.min = defaultdict(float)\n        self.max = defaultdict(lambda: 1.0)\n        self.frozen = set()\n\n        self.win = 4, True\n        self.loss = 4, False\n        self.max[self.loss] = 0.0\n        self.min[self.win] = 1.0\n        self.frozen.update([self.win, self.loss])\n\n    def _getSuccessorsA(self, statep):\n        st, state = statep\n        for action in [\"Dig\", \"Super Potion\"]:\n            yield (1, state, action)\n\n    def _applyActionPair(self, state, side1, act1, side2, act2, dist, pmult):\n        for newstate, p in _applyAction(state, side1, act1).items():\n            if newstate[0].hp == 0:\n                newstatep = self.loss\n            elif newstate[1].hp == 0:\n                newstatep = self.win\n            else:\n                newstatep = 2, newstate, side2, act2\n            dist[newstatep] += p * pmult\n\n    def _getSuccessorsB(self, statep):\n        st, state, action = statep\n        dist = defaultdict(Fraction)\n        for eact, p in [\n            (\"Water Gun\", Fraction(64, 130)),\n            (\"Bubblebeam\", Fraction(66, 130)),\n        ]:\n            priority1 = state[0].stats.speed + 10000 * (action == \"Super Potion\")\n            priority2 = state[1].stats.speed + 10000 * (action == \"X Defend\")\n\n            if priority1 > priority2:\n                self._applyActionPair(state, 0, action, 1, eact, dist, p)\n            elif priority1 < priority2:\n                self._applyActionPair(state, 1, eact, 0, action, dist, p)\n            else:\n                self._applyActionPair(state, 0, action, 1, eact, dist, p / 2)\n                self._applyActionPair(state, 1, eact, 0, action, dist, p / 2)\n\n        return {k: float(p) for k, p in dist.items() if p > 0}\n\n    def _getSuccessorsC(self, statep):\n        st, state, side, action = statep\n        dist = defaultdict(Fraction)\n        for newstate, p in _applyAction(state, side, action).items():\n            if newstate[0].hp == 0:\n                newstatep = self.loss\n            elif newstate[1].hp == 0:\n                newstatep = self.win\n            else:\n                newstatep = 0, newstate\n            dist[newstatep] += p\n        return {k: float(p) for k, p in dist.items() if p > 0}\n\n    def getSuccessors(self, statep):\n        try:\n            return self.successors[statep]\n        except KeyError:\n            st = statep[0]\n        if st == 0:\n            result = list(self._getSuccessorsA(statep))\n        else:\n            if st == 1:\n                dist = self._getSuccessorsB(statep)\n            elif st == 2:\n                dist = self._getSuccessorsC(statep)\n            result = sorted(dist.items(), key=lambda t: (-t[1], t[0]))\n        self.successors[statep] = result\n        return result\n\n    def getSuccessorsList(self, statep):\n        if statep[0] == 4:\n            return []\n        temp = self.getSuccessors(statep)\n        if statep[0] != 0:\n            temp = list(zip(*temp))[0] if temp else []\n        return temp\n\n    def evaluate(self, tolerance=0.15):\n        badges = 1, 0, 0, 0\n\n        starfixed = fixeddata_t(59, stats_t(40, 44, 56, 50), 11, NOMODS, 115)\n        starhalf = halfstate_t(starfixed, 59, 0, NOMODS, stats_t(40, 44, 56, 50))\n        charfixed = fixeddata_t(63, stats_t(39, 34, 46, 38), 26, badges, 65)\n        charhalf = halfstate_t(\n            charfixed, 63, 0, NOMODS, applyBadgeBoosts(badges, stats_t(39, 34, 46, 38))\n        )\n        initial_state = charhalf, starhalf, 0\n        initial_statep = 0, initial_state\n\n        dmin, dmax, frozen = self.min, self.max, self.frozen\n        stateps = topoSort([initial_statep], self.getSuccessorsList)\n\n        itercount = 0\n        while dmax[initial_statep] - dmin[initial_statep] > tolerance:\n            itercount += 1\n\n            for sp in stateps:\n                if sp in frozen:\n                    continue\n\n                if sp[0] == 0:\n                    # choice node\n                    dmin[sp] = max(dmin[sp2] for sp2 in self.getSuccessors(sp))\n                    dmax[sp] = max(dmax[sp2] for sp2 in self.getSuccessors(sp))\n                else:\n                    dmin[sp] = sum(dmin[sp2] * p for sp2, p in self.getSuccessors(sp))\n                    dmax[sp] = sum(dmax[sp2] * p for sp2, p in self.getSuccessors(sp))\n\n                if dmin[sp] >= dmax[sp]:\n                    dmax[sp] = dmin[sp] = (dmin[sp] + dmax[sp]) / 2\n                    frozen.add(sp)\n        return (dmax[initial_statep] + dmin[initial_statep]) / 2\n\n\ndef bench_mdp(loops):\n    expected = 0.89873589887\n    max_diff = 1e-6\n    range_it = range(loops)\n\n    t0 = pyperf.perf_counter()\n    for _ in range_it:\n        with get_tracker():\n            result = Battle().evaluate(0.192)\n    dt = pyperf.perf_counter() - t0\n\n    if abs(result - expected) > max_diff:\n        raise Exception(\n            \"invalid result: got %s, expected %s \"\n            \"(diff: %s, max diff: %s)\" % (result, expected, result - expected, max_diff)\n        )\n    return dt\n\n\nif __name__ == \"__main__\":\n    runner = pyperf.Runner()\n    runner.metadata[\"description\"] = \"MDP benchmark\"\n    runner.bench_time_func(\"mdp\", bench_mdp)\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/meteor_context_base.py",
    "content": "\"\"\"\nMeteor Puzzle board:\nhttp://benchmarksgame.alioth.debian.org/u32/meteor-description.html#meteor\n\nThe Computer Language Benchmarks Game\nhttp://benchmarksgame.alioth.debian.org/\n\ncontributed by Daniel Nanz, 2008-08-21\n\"\"\"\n\nfrom bisect import bisect\n\nSOLVE_ARG = 60\n\nWIDTH, HEIGHT = 5, 10\nDIR_NO = 6\nS, E = WIDTH * HEIGHT, 2\nSE = S + (E / 2)\nSW = SE - E\nW, NW, NE = -E, -SE, -SW\n\nSOLUTIONS = [\n    \"00001222012661126155865558633348893448934747977799\",\n    \"00001222012771127148774485464855968596835966399333\",\n    \"00001222012771127148774485494855998596835966366333\",\n    \"00001222012771127148774485994855948596835966366333\",\n    \"00001222012771127166773863384653846538445584959999\",\n    \"00001222012771127183778834833348555446554666969999\",\n    \"00001222012771127183778834833348555446554966699996\",\n    \"00001223012331123166423564455647456775887888979999\",\n    \"00001555015541144177484726877268222683336689399993\",\n    \"00001555015541144177484728677286222863338669399993\",\n    \"00001599015591159148594482224827748276837766366333\",\n    \"00001777017871184155845558449984669662932629322333\",\n    \"00004222042664426774996879687759811598315583153331\",\n    \"00004222042774427384773183331866118615586555969999\",\n    \"00004223042334423784523785771855718566186611969999\",\n    \"00004227042874428774528735833155831566316691169999\",\n    \"00004333045534455384175781777812228116286662969999\",\n    \"00004333045934459384559185991866118612286727267772\",\n    \"00004333047734427384277182221866118615586555969999\",\n    \"00004555045514411224172621768277368736683339899998\",\n    \"00004555045514411224172721777299998966836688368333\",\n    \"00004555045534413334132221177266172677886888969999\",\n    \"00004555045534473334739967792617926192661882211888\",\n    \"00004555045564466694699992288828811233317273177731\",\n    \"00004555045564466694699997773172731233312881122888\",\n    \"00004555045564496664999962288828811233317273177731\",\n    \"00004555045564496664999967773172731233312881122888\",\n    \"00004555045584411884171187722866792679236992369333\",\n    \"00004555045584411884191189999832226333267372677766\",\n    \"00004555045584411884191189999866222623336727367773\",\n    \"13335138551389511895778697869947762446624022240000\",\n    \"13777137271333211882888226999946669446554055540000\",\n    \"13777137271333211882888229999649666446554055540000\",\n    \"27776272768221681166819958195548395443954033340000\",\n    \"33322392623926696648994485554855148117871077710000\",\n    \"33366366773867284772842228449584195119551099510000\",\n    \"33366366953869584955849958447784172117721022210000\",\n    \"33366366953869589955849458447784172117721022210000\",\n    \"33386388663866989999277712727142211441554055540000\",\n    \"33396329963297629766822778117148811448554055540000\",\n    \"33399366953869586955846458447784172117721022210000\",\n    \"37776372763332622266899998119148811448554055540000\",\n    \"39999396683336822268277682748477144114551055510000\",\n    \"39999398663338622286277862748477144114551055510000\",\n    \"66777627376233362223899998119148811448554055540000\",\n    \"69999666945564455584333843887738172117721022210000\",\n    \"88811228816629162971629776993743337443554055540000\",\n    \"88822118821333213727137776999946669446554055540000\",\n    \"88822118821333213727137779999649666446554055540000\",\n    \"89999893338663786377286712627142211441554055540000\",\n    \"99777974743984439884333685556855162116621022210000\",\n    \"99995948554483564835648336837766172117721022210000\",\n    \"99996119661366513855133853782547782447824072240000\",\n    \"99996911668166581755817758732548732443324032240000\",\n    \"99996926668261182221877718757148355443554033340000\",\n    \"99996955568551681166812228177248372443774033340000\",\n    \"99996955568551681166813338137748372447724022240000\",\n    \"99996966645564455584333843887738172117721022210000\",\n    \"99996988868877627166277112223143331443554055540000\",\n    \"99997988878857765474655446532466132113321032210000\",\n]\n\n\ndef rotate(ido, rd={E: NE, NE: NW, NW: W, W: SW, SW: SE, SE: E}):\n    return [rd[o] for o in ido]\n\n\ndef flip(ido, fd={E: E, NE: SE, NW: SW, W: W, SW: NW, SE: NE}):\n    return [fd[o] for o in ido]\n\n\ndef permute(ido, r_ido, rotate=rotate, flip=flip):\n    ps = [ido]\n    for r in range(DIR_NO - 1):\n        ps.append(rotate(ps[-1]))\n        if ido == r_ido:  # C2-symmetry\n            ps = ps[0 : DIR_NO // 2]\n    for pp in ps[:]:\n        ps.append(flip(pp))\n    return ps\n\n\ndef convert(ido):\n    '''incremental direction offsets -> \"coordinate offsets\"'''\n    out = [0]\n    for o in ido:\n        out.append(out[-1] + o)\n    return list(set(out))\n\n\ndef get_footprints(board, cti, pieces):\n    fps = [[[] for p in range(len(pieces))] for ci in range(len(board))]\n    for c in board:\n        for pi, p in enumerate(pieces):\n            for pp in p:\n                fp = frozenset([cti[c + o] for o in pp if (c + o) in cti])\n                if len(fp) == 5:\n                    fps[min(fp)][pi].append(fp)\n    return fps\n\n\ndef get_senh(board, cti):\n    \"\"\"-> south-east neighborhood\"\"\"\n    se_nh = []\n    nh = [E, SW, SE]\n    for c in board:\n        se_nh.append(frozenset([cti[c + o] for o in nh if (c + o) in cti]))\n    return se_nh\n\n\ndef get_puzzle(width, height):\n    board = [E * x + S * y + (y % 2) for y in range(height) for x in range(width)]\n    cti = dict((board[i], i) for i in range(len(board)))\n\n    # Incremental direction offsets\n    idos = [\n        [E, E, E, SE],\n        [SE, SW, W, SW],\n        [W, W, SW, SE],\n        [E, E, SW, SE],\n        [NW, W, NW, SE, SW],\n        [E, E, NE, W],\n        [NW, NE, NE, W],\n        [NE, SE, E, NE],\n        [SE, SE, E, SE],\n        [E, NW, NW, NW],\n    ]\n\n    # Restrict piece 4\n    perms = (permute(p, idos[3]) for p in idos)\n    pieces = [[convert(pp) for pp in p] for p in perms]\n    return (board, cti, pieces)\n\n\ndef solve(\n    n,\n    i_min,\n    free,\n    curr_board,\n    pieces_left,\n    solutions,\n    fps,\n    se_nh,\n    # Hack to use a fast local variable to avoid a global lookup\n    bisect=bisect,\n):\n\n    fp_i_cands = fps[i_min]\n    for p in pieces_left:\n        fp_cands = fp_i_cands[p]\n        for fp in fp_cands:\n            if fp <= free:\n                n_curr_board = curr_board[:]\n                for ci in fp:\n                    n_curr_board[ci] = p\n\n                if len(pieces_left) > 1:\n                    n_free = free - fp\n                    n_i_min = min(n_free)\n                    if len(n_free & se_nh[n_i_min]) > 0:\n                        n_pieces_left = pieces_left[:]\n                        n_pieces_left.remove(p)\n                        solve(\n                            n,\n                            n_i_min,\n                            n_free,\n                            n_curr_board,\n                            n_pieces_left,\n                            solutions,\n                            fps,\n                            se_nh,\n                        )\n                else:\n                    s = \"\".join(map(str, n_curr_board))\n                    solutions.insert(bisect(solutions, s), s)\n                    rs = s[::-1]\n                    solutions.insert(bisect(solutions, rs), rs)\n                    if len(solutions) >= n:\n                        return\n\n        if len(solutions) >= n:\n            return\n\n\ndef bench_meteor_contest(loops, board, pieces, solve_arg, fps, se_nh):\n    range_it = range(loops)\n    for _ in range_it:\n        free = frozenset(range(len(board)))\n        curr_board = [-1] * len(board)\n        pieces_left = list(range(len(pieces)))\n        solutions = []\n        solve(solve_arg, 0, free, curr_board, pieces_left, solutions, fps, se_nh)\n\n    if solutions != SOLUTIONS:\n        raise ValueError(\"unexpected solutions\")\n\n\ndef run_benchmark():\n    board, cti, pieces = get_puzzle(WIDTH, HEIGHT)\n    fps = get_footprints(board, cti, pieces)\n    se_nh = get_senh(board, cti)\n    solve_arg = SOLVE_ARG\n    bench_meteor_contest(1, board, pieces, solve_arg, fps, se_nh)\n\n\nif __name__ == \"__main__\":\n    run_benchmark()\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/meteor_context_memray.py",
    "content": "\"\"\"\nMeteor Puzzle board:\nhttp://benchmarksgame.alioth.debian.org/u32/meteor-description.html#meteor\n\nThe Computer Language Benchmarks Game\nhttp://benchmarksgame.alioth.debian.org/\n\ncontributed by Daniel Nanz, 2008-08-21\n\"\"\"\n\nfrom bisect import bisect\n\nimport pyperf\nfrom memray_helper import get_tracker\n\n\nSOLVE_ARG = 60\n\nWIDTH, HEIGHT = 5, 10\nDIR_NO = 6\nS, E = WIDTH * HEIGHT, 2\nSE = S + (E / 2)\nSW = SE - E\nW, NW, NE = -E, -SE, -SW\n\nSOLUTIONS = [\n    \"00001222012661126155865558633348893448934747977799\",\n    \"00001222012771127148774485464855968596835966399333\",\n    \"00001222012771127148774485494855998596835966366333\",\n    \"00001222012771127148774485994855948596835966366333\",\n    \"00001222012771127166773863384653846538445584959999\",\n    \"00001222012771127183778834833348555446554666969999\",\n    \"00001222012771127183778834833348555446554966699996\",\n    \"00001223012331123166423564455647456775887888979999\",\n    \"00001555015541144177484726877268222683336689399993\",\n    \"00001555015541144177484728677286222863338669399993\",\n    \"00001599015591159148594482224827748276837766366333\",\n    \"00001777017871184155845558449984669662932629322333\",\n    \"00004222042664426774996879687759811598315583153331\",\n    \"00004222042774427384773183331866118615586555969999\",\n    \"00004223042334423784523785771855718566186611969999\",\n    \"00004227042874428774528735833155831566316691169999\",\n    \"00004333045534455384175781777812228116286662969999\",\n    \"00004333045934459384559185991866118612286727267772\",\n    \"00004333047734427384277182221866118615586555969999\",\n    \"00004555045514411224172621768277368736683339899998\",\n    \"00004555045514411224172721777299998966836688368333\",\n    \"00004555045534413334132221177266172677886888969999\",\n    \"00004555045534473334739967792617926192661882211888\",\n    \"00004555045564466694699992288828811233317273177731\",\n    \"00004555045564466694699997773172731233312881122888\",\n    \"00004555045564496664999962288828811233317273177731\",\n    \"00004555045564496664999967773172731233312881122888\",\n    \"00004555045584411884171187722866792679236992369333\",\n    \"00004555045584411884191189999832226333267372677766\",\n    \"00004555045584411884191189999866222623336727367773\",\n    \"13335138551389511895778697869947762446624022240000\",\n    \"13777137271333211882888226999946669446554055540000\",\n    \"13777137271333211882888229999649666446554055540000\",\n    \"27776272768221681166819958195548395443954033340000\",\n    \"33322392623926696648994485554855148117871077710000\",\n    \"33366366773867284772842228449584195119551099510000\",\n    \"33366366953869584955849958447784172117721022210000\",\n    \"33366366953869589955849458447784172117721022210000\",\n    \"33386388663866989999277712727142211441554055540000\",\n    \"33396329963297629766822778117148811448554055540000\",\n    \"33399366953869586955846458447784172117721022210000\",\n    \"37776372763332622266899998119148811448554055540000\",\n    \"39999396683336822268277682748477144114551055510000\",\n    \"39999398663338622286277862748477144114551055510000\",\n    \"66777627376233362223899998119148811448554055540000\",\n    \"69999666945564455584333843887738172117721022210000\",\n    \"88811228816629162971629776993743337443554055540000\",\n    \"88822118821333213727137776999946669446554055540000\",\n    \"88822118821333213727137779999649666446554055540000\",\n    \"89999893338663786377286712627142211441554055540000\",\n    \"99777974743984439884333685556855162116621022210000\",\n    \"99995948554483564835648336837766172117721022210000\",\n    \"99996119661366513855133853782547782447824072240000\",\n    \"99996911668166581755817758732548732443324032240000\",\n    \"99996926668261182221877718757148355443554033340000\",\n    \"99996955568551681166812228177248372443774033340000\",\n    \"99996955568551681166813338137748372447724022240000\",\n    \"99996966645564455584333843887738172117721022210000\",\n    \"99996988868877627166277112223143331443554055540000\",\n    \"99997988878857765474655446532466132113321032210000\",\n]\n\n\ndef rotate(ido, rd={E: NE, NE: NW, NW: W, W: SW, SW: SE, SE: E}):\n    return [rd[o] for o in ido]\n\n\ndef flip(ido, fd={E: E, NE: SE, NW: SW, W: W, SW: NW, SE: NE}):\n    return [fd[o] for o in ido]\n\n\ndef permute(ido, r_ido, rotate=rotate, flip=flip):\n    ps = [ido]\n    for r in range(DIR_NO - 1):\n        ps.append(rotate(ps[-1]))\n        if ido == r_ido:  # C2-symmetry\n            ps = ps[0 : DIR_NO // 2]\n    for pp in ps[:]:\n        ps.append(flip(pp))\n    return ps\n\n\ndef convert(ido):\n    '''incremental direction offsets -> \"coordinate offsets\"'''\n    out = [0]\n    for o in ido:\n        out.append(out[-1] + o)\n    return list(set(out))\n\n\ndef get_footprints(board, cti, pieces):\n    fps = [[[] for p in range(len(pieces))] for ci in range(len(board))]\n    for c in board:\n        for pi, p in enumerate(pieces):\n            for pp in p:\n                fp = frozenset([cti[c + o] for o in pp if (c + o) in cti])\n                if len(fp) == 5:\n                    fps[min(fp)][pi].append(fp)\n    return fps\n\n\ndef get_senh(board, cti):\n    \"\"\"-> south-east neighborhood\"\"\"\n    se_nh = []\n    nh = [E, SW, SE]\n    for c in board:\n        se_nh.append(frozenset([cti[c + o] for o in nh if (c + o) in cti]))\n    return se_nh\n\n\ndef get_puzzle(width, height):\n    board = [E * x + S * y + (y % 2) for y in range(height) for x in range(width)]\n    cti = dict((board[i], i) for i in range(len(board)))\n\n    # Incremental direction offsets\n    idos = [\n        [E, E, E, SE],\n        [SE, SW, W, SW],\n        [W, W, SW, SE],\n        [E, E, SW, SE],\n        [NW, W, NW, SE, SW],\n        [E, E, NE, W],\n        [NW, NE, NE, W],\n        [NE, SE, E, NE],\n        [SE, SE, E, SE],\n        [E, NW, NW, NW],\n    ]\n\n    # Restrict piece 4\n    perms = (permute(p, idos[3]) for p in idos)\n    pieces = [[convert(pp) for pp in p] for p in perms]\n    return (board, cti, pieces)\n\n\ndef solve(\n    n,\n    i_min,\n    free,\n    curr_board,\n    pieces_left,\n    solutions,\n    fps,\n    se_nh,\n    # Hack to use a fast local variable to avoid a global lookup\n    bisect=bisect,\n):\n\n    fp_i_cands = fps[i_min]\n    for p in pieces_left:\n        fp_cands = fp_i_cands[p]\n        for fp in fp_cands:\n            if fp <= free:\n                n_curr_board = curr_board[:]\n                for ci in fp:\n                    n_curr_board[ci] = p\n\n                if len(pieces_left) > 1:\n                    n_free = free - fp\n                    n_i_min = min(n_free)\n                    if len(n_free & se_nh[n_i_min]) > 0:\n                        n_pieces_left = pieces_left[:]\n                        n_pieces_left.remove(p)\n                        solve(\n                            n,\n                            n_i_min,\n                            n_free,\n                            n_curr_board,\n                            n_pieces_left,\n                            solutions,\n                            fps,\n                            se_nh,\n                        )\n                else:\n                    s = \"\".join(map(str, n_curr_board))\n                    solutions.insert(bisect(solutions, s), s)\n                    rs = s[::-1]\n                    solutions.insert(bisect(solutions, rs), rs)\n                    if len(solutions) >= n:\n                        return\n\n        if len(solutions) >= n:\n            return\n\n\ndef bench_meteor_contest(loops, board, pieces, solve_arg, fps, se_nh):\n    range_it = range(loops)\n\n    with get_tracker():\n        t0 = pyperf.perf_counter()\n        for _ in range_it:\n            free = frozenset(range(len(board)))\n            curr_board = [-1] * len(board)\n            pieces_left = list(range(len(pieces)))\n            solutions = []\n            solve(solve_arg, 0, free, curr_board, pieces_left, solutions, fps, se_nh)\n\n        dt = pyperf.perf_counter() - t0\n\n    if solutions != SOLUTIONS:\n        raise ValueError(\"unexpected solutions\")\n\n    return dt\n\n\ndef main():\n    runner = pyperf.Runner()\n    runner.metadata[\"description\"] = \"Solver for Meteor Puzzle board\"\n\n    board, cti, pieces = get_puzzle(WIDTH, HEIGHT)\n    fps = get_footprints(board, cti, pieces)\n    se_nh = get_senh(board, cti)\n\n    solve_arg = SOLVE_ARG\n    runner.bench_time_func(\n        \"meteor_contest\", bench_meteor_contest, board, pieces, solve_arg, fps, se_nh\n    )\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/nbody_base.py",
    "content": "\"\"\"\nN-body benchmark from the Computer Language Benchmarks Game.\n\nThis is intended to support Unladen Swallow's pyperf.py. Accordingly, it has been\nmodified from the Shootout version:\n- Accept standard Unladen Swallow benchmark options.\n- Run report_energy()/advance() in a loop.\n- Reimplement itertools.combinations() to work with older Python versions.\n\nPulled from:\nhttp://benchmarksgame.alioth.debian.org/u64q/program.php?test=nbody&lang=python3&id=1\n\nContributed by Kevin Carson.\nModified by Tupteq, Fredrik Johansson, and Daniel Nanz.\n\"\"\"\n\n__contact__ = \"collinwinter@google.com (Collin Winter)\"\nDEFAULT_ITERATIONS = 20000\nDEFAULT_REFERENCE = \"sun\"\n\n\ndef combinations(l):\n    \"\"\"Pure-Python implementation of itertools.combinations(l, 2).\"\"\"\n    result = []\n    for x in range(len(l) - 1):\n        ls = l[x + 1 :]\n        for y in ls:\n            result.append((l[x], y))\n    return result\n\n\nPI = 3.14159265358979323\nSOLAR_MASS = 4 * PI * PI\nDAYS_PER_YEAR = 365.24\n\nBODIES = {\n    \"sun\": ([0.0, 0.0, 0.0], [0.0, 0.0, 0.0], SOLAR_MASS),\n    \"jupiter\": (\n        [4.84143144246472090e00, -1.16032004402742839e00, -1.03622044471123109e-01],\n        [\n            1.66007664274403694e-03 * DAYS_PER_YEAR,\n            7.69901118419740425e-03 * DAYS_PER_YEAR,\n            -6.90460016972063023e-05 * DAYS_PER_YEAR,\n        ],\n        9.54791938424326609e-04 * SOLAR_MASS,\n    ),\n    \"saturn\": (\n        [8.34336671824457987e00, 4.12479856412430479e00, -4.03523417114321381e-01],\n        [\n            -2.76742510726862411e-03 * DAYS_PER_YEAR,\n            4.99852801234917238e-03 * DAYS_PER_YEAR,\n            2.30417297573763929e-05 * DAYS_PER_YEAR,\n        ],\n        2.85885980666130812e-04 * SOLAR_MASS,\n    ),\n    \"uranus\": (\n        [1.28943695621391310e01, -1.51111514016986312e01, -2.23307578892655734e-01],\n        [\n            2.96460137564761618e-03 * DAYS_PER_YEAR,\n            2.37847173959480950e-03 * DAYS_PER_YEAR,\n            -2.96589568540237556e-05 * DAYS_PER_YEAR,\n        ],\n        4.36624404335156298e-05 * SOLAR_MASS,\n    ),\n    \"neptune\": (\n        [1.53796971148509165e01, -2.59193146099879641e01, 1.79258772950371181e-01],\n        [\n            2.68067772490389322e-03 * DAYS_PER_YEAR,\n            1.62824170038242295e-03 * DAYS_PER_YEAR,\n            -9.51592254519715870e-05 * DAYS_PER_YEAR,\n        ],\n        5.15138902046611451e-05 * SOLAR_MASS,\n    ),\n}\n\n\nSYSTEM = list(BODIES.values())\nPAIRS = combinations(SYSTEM)\n\n\ndef advance(dt, n, bodies=SYSTEM, pairs=PAIRS):\n    for i in range(n):\n        for (([x1, y1, z1], v1, m1), ([x2, y2, z2], v2, m2)) in pairs:\n            dx = x1 - x2\n            dy = y1 - y2\n            dz = z1 - z2\n            mag = dt * ((dx * dx + dy * dy + dz * dz) ** (-1.5))\n            b1m = m1 * mag\n            b2m = m2 * mag\n            v1[0] -= dx * b2m\n            v1[1] -= dy * b2m\n            v1[2] -= dz * b2m\n            v2[0] += dx * b1m\n            v2[1] += dy * b1m\n            v2[2] += dz * b1m\n        for (r, [vx, vy, vz], m) in bodies:\n            r[0] += dt * vx\n            r[1] += dt * vy\n            r[2] += dt * vz\n\n\ndef report_energy(bodies=SYSTEM, pairs=PAIRS, e=0.0):\n    for (((x1, y1, z1), v1, m1), ((x2, y2, z2), v2, m2)) in pairs:\n        dx = x1 - x2\n        dy = y1 - y2\n        dz = z1 - z2\n        e -= (m1 * m2) / ((dx * dx + dy * dy + dz * dz) ** 0.5)\n    for (r, [vx, vy, vz], m) in bodies:\n        e += m * (vx * vx + vy * vy + vz * vz) / 2.0\n    return e\n\n\ndef offset_momentum(ref, bodies=SYSTEM, px=0.0, py=0.0, pz=0.0):\n    for (r, [vx, vy, vz], m) in bodies:\n        px -= vx * m\n        py -= vy * m\n        pz -= vz * m\n    (r, v, m) = ref\n    v[0] = px / m\n    v[1] = py / m\n    v[2] = pz / m\n\n\ndef bench_nbody(loops, reference, iterations):\n    # Set up global state\n    offset_momentum(BODIES[reference])\n\n    range_it = range(loops)\n\n    for _ in range_it:\n        report_energy()\n        advance(0.01, iterations)\n        report_energy()\n\n\ndef add_cmdline_args(cmd, args):\n    cmd.extend((\"--iterations\", str(args.iterations)))\n\n\ndef run_benchmark():\n    bench_nbody(1, DEFAULT_REFERENCE, DEFAULT_ITERATIONS)\n\n\nif __name__ == \"__main__\":\n    run_benchmark()\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/nbody_memray.py",
    "content": "\"\"\"\nN-body benchmark from the Computer Language Benchmarks Game.\n\nThis is intended to support Unladen Swallow's pyperf.py. Accordingly, it has been\nmodified from the Shootout version:\n- Accept standard Unladen Swallow benchmark options.\n- Run report_energy()/advance() in a loop.\n- Reimplement itertools.combinations() to work with older Python versions.\n\nPulled from:\nhttp://benchmarksgame.alioth.debian.org/u64q/program.php?test=nbody&lang=python3&id=1\n\nContributed by Kevin Carson.\nModified by Tupteq, Fredrik Johansson, and Daniel Nanz.\n\"\"\"\n\nimport pyperf\nfrom memray_helper import get_tracker\n\n__contact__ = \"collinwinter@google.com (Collin Winter)\"\nDEFAULT_ITERATIONS = 20000\nDEFAULT_REFERENCE = \"sun\"\n\n\ndef combinations(l):\n    \"\"\"Pure-Python implementation of itertools.combinations(l, 2).\"\"\"\n    result = []\n    for x in range(len(l) - 1):\n        ls = l[x + 1 :]\n        for y in ls:\n            result.append((l[x], y))\n    return result\n\n\nPI = 3.14159265358979323\nSOLAR_MASS = 4 * PI * PI\nDAYS_PER_YEAR = 365.24\n\nBODIES = {\n    \"sun\": ([0.0, 0.0, 0.0], [0.0, 0.0, 0.0], SOLAR_MASS),\n    \"jupiter\": (\n        [4.84143144246472090e00, -1.16032004402742839e00, -1.03622044471123109e-01],\n        [\n            1.66007664274403694e-03 * DAYS_PER_YEAR,\n            7.69901118419740425e-03 * DAYS_PER_YEAR,\n            -6.90460016972063023e-05 * DAYS_PER_YEAR,\n        ],\n        9.54791938424326609e-04 * SOLAR_MASS,\n    ),\n    \"saturn\": (\n        [8.34336671824457987e00, 4.12479856412430479e00, -4.03523417114321381e-01],\n        [\n            -2.76742510726862411e-03 * DAYS_PER_YEAR,\n            4.99852801234917238e-03 * DAYS_PER_YEAR,\n            2.30417297573763929e-05 * DAYS_PER_YEAR,\n        ],\n        2.85885980666130812e-04 * SOLAR_MASS,\n    ),\n    \"uranus\": (\n        [1.28943695621391310e01, -1.51111514016986312e01, -2.23307578892655734e-01],\n        [\n            2.96460137564761618e-03 * DAYS_PER_YEAR,\n            2.37847173959480950e-03 * DAYS_PER_YEAR,\n            -2.96589568540237556e-05 * DAYS_PER_YEAR,\n        ],\n        4.36624404335156298e-05 * SOLAR_MASS,\n    ),\n    \"neptune\": (\n        [1.53796971148509165e01, -2.59193146099879641e01, 1.79258772950371181e-01],\n        [\n            2.68067772490389322e-03 * DAYS_PER_YEAR,\n            1.62824170038242295e-03 * DAYS_PER_YEAR,\n            -9.51592254519715870e-05 * DAYS_PER_YEAR,\n        ],\n        5.15138902046611451e-05 * SOLAR_MASS,\n    ),\n}\n\n\nSYSTEM = list(BODIES.values())\nPAIRS = combinations(SYSTEM)\n\n\ndef advance(dt, n, bodies=SYSTEM, pairs=PAIRS):\n    for i in range(n):\n        for (([x1, y1, z1], v1, m1), ([x2, y2, z2], v2, m2)) in pairs:\n            dx = x1 - x2\n            dy = y1 - y2\n            dz = z1 - z2\n            mag = dt * ((dx * dx + dy * dy + dz * dz) ** (-1.5))\n            b1m = m1 * mag\n            b2m = m2 * mag\n            v1[0] -= dx * b2m\n            v1[1] -= dy * b2m\n            v1[2] -= dz * b2m\n            v2[0] += dx * b1m\n            v2[1] += dy * b1m\n            v2[2] += dz * b1m\n        for (r, [vx, vy, vz], m) in bodies:\n            r[0] += dt * vx\n            r[1] += dt * vy\n            r[2] += dt * vz\n\n\ndef report_energy(bodies=SYSTEM, pairs=PAIRS, e=0.0):\n    for (((x1, y1, z1), v1, m1), ((x2, y2, z2), v2, m2)) in pairs:\n        dx = x1 - x2\n        dy = y1 - y2\n        dz = z1 - z2\n        e -= (m1 * m2) / ((dx * dx + dy * dy + dz * dz) ** 0.5)\n    for (r, [vx, vy, vz], m) in bodies:\n        e += m * (vx * vx + vy * vy + vz * vz) / 2.0\n    return e\n\n\ndef offset_momentum(ref, bodies=SYSTEM, px=0.0, py=0.0, pz=0.0):\n    for (r, [vx, vy, vz], m) in bodies:\n        px -= vx * m\n        py -= vy * m\n        pz -= vz * m\n    (r, v, m) = ref\n    v[0] = px / m\n    v[1] = py / m\n    v[2] = pz / m\n\n\ndef bench_nbody(loops, reference, iterations):\n    # Set up global state\n    offset_momentum(BODIES[reference])\n\n    range_it = range(loops)\n\n    with get_tracker():\n        t0 = pyperf.perf_counter()\n        for _ in range_it:\n            report_energy()\n            advance(0.01, iterations)\n            report_energy()\n\n        return pyperf.perf_counter() - t0\n\n\ndef add_cmdline_args(cmd, args):\n    cmd.extend((\"--iterations\", str(args.iterations)))\n\n\nif __name__ == \"__main__\":\n    runner = pyperf.Runner(add_cmdline_args=add_cmdline_args)\n    runner.metadata[\"description\"] = \"n-body benchmark\"\n    runner.argparser.add_argument(\n        \"--iterations\",\n        type=int,\n        default=DEFAULT_ITERATIONS,\n        help=\"Number of nbody advance() iterations \"\n        \"(default: %s)\" % DEFAULT_ITERATIONS,\n    )\n    runner.argparser.add_argument(\n        \"--reference\",\n        type=str,\n        default=DEFAULT_REFERENCE,\n        help=\"nbody reference (default: %s)\" % DEFAULT_REFERENCE,\n    )\n\n    args = runner.parse_args()\n    runner.bench_time_func(\"nbody\", bench_nbody, args.reference, args.iterations)\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/nqueens_base.py",
    "content": "\"\"\"Simple, brute-force N-Queens solver.\"\"\"\n\n__author__ = \"collinwinter@google.com (Collin Winter)\"\n\n\n# Pure-Python implementation of itertools.permutations().\ndef permutations(iterable, r=None):\n    \"\"\"permutations(range(3), 2) --> (0,1) (0,2) (1,0) (1,2) (2,0) (2,1)\"\"\"\n    pool = tuple(iterable)\n    n = len(pool)\n    if r is None:\n        r = n\n    indices = list(range(n))\n    cycles = list(range(n - r + 1, n + 1))[::-1]\n    yield tuple(pool[i] for i in indices[:r])\n    while n:\n        for i in reversed(range(r)):\n            cycles[i] -= 1\n            if cycles[i] == 0:\n                indices[i:] = indices[i + 1 :] + indices[i : i + 1]\n                cycles[i] = n - i\n            else:\n                j = cycles[i]\n                indices[i], indices[-j] = indices[-j], indices[i]\n                yield tuple(pool[i] for i in indices[:r])\n                break\n        else:\n            return\n\n\n# From http://code.activestate.com/recipes/576647/\ndef n_queens(queen_count):\n    \"\"\"N-Queens solver.\n\n    Args:\n        queen_count: the number of queens to solve for. This is also the\n            board size.\n\n    Yields:\n        Solutions to the problem. Each yielded value is looks like\n        (3, 8, 2, 1, 4, ..., 6) where each number is the column position for the\n        queen, and the index into the tuple indicates the row.\n    \"\"\"\n    cols = range(queen_count)\n    for vec in permutations(cols):\n        if (\n            queen_count\n            == len(set(vec[i] + i for i in cols))\n            == len(set(vec[i] - i for i in cols))\n        ):\n            yield vec\n\n\ndef bench_n_queens(queen_count):\n    list(n_queens(queen_count))\n\n\ndef run_benchmark():\n    bench_n_queens(8)\n\n\nif __name__ == \"__main__\":\n    run_benchmark()\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/nqueens_memray.py",
    "content": "\"\"\"Simple, brute-force N-Queens solver.\"\"\"\n\nimport pyperf\nfrom memray_helper import get_tracker\n\n__author__ = \"collinwinter@google.com (Collin Winter)\"\n\n\n# Pure-Python implementation of itertools.permutations().\ndef permutations(iterable, r=None):\n    \"\"\"permutations(range(3), 2) --> (0,1) (0,2) (1,0) (1,2) (2,0) (2,1)\"\"\"\n    pool = tuple(iterable)\n    n = len(pool)\n    if r is None:\n        r = n\n    indices = list(range(n))\n    cycles = list(range(n - r + 1, n + 1))[::-1]\n    yield tuple(pool[i] for i in indices[:r])\n    while n:\n        for i in reversed(range(r)):\n            cycles[i] -= 1\n            if cycles[i] == 0:\n                indices[i:] = indices[i + 1 :] + indices[i : i + 1]\n                cycles[i] = n - i\n            else:\n                j = cycles[i]\n                indices[i], indices[-j] = indices[-j], indices[i]\n                yield tuple(pool[i] for i in indices[:r])\n                break\n        else:\n            return\n\n\n# From http://code.activestate.com/recipes/576647/\ndef n_queens(queen_count):\n    \"\"\"N-Queens solver.\n\n    Args:\n        queen_count: the number of queens to solve for. This is also the\n            board size.\n\n    Yields:\n        Solutions to the problem. Each yielded value is looks like\n        (3, 8, 2, 1, 4, ..., 6) where each number is the column position for the\n        queen, and the index into the tuple indicates the row.\n    \"\"\"\n    cols = range(queen_count)\n    for vec in permutations(cols):\n        if (\n            queen_count\n            == len(set(vec[i] + i for i in cols))\n            == len(set(vec[i] - i for i in cols))\n        ):\n            yield vec\n\n\ndef bench_n_queens(queen_count):\n    with get_tracker():\n        list(n_queens(queen_count))\n\n\nif __name__ == \"__main__\":\n    runner = pyperf.Runner()\n    runner.metadata[\"description\"] = \"Simple, brute-force N-Queens solver\"\n\n    queen_count = 8\n    runner.bench_func(\"nqueens\", bench_n_queens, queen_count)\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/pickles_base.py",
    "content": "\"\"\"Script for testing the performance of pickling/unpickling.\n\nThis will pickle/unpickle several real world-representative objects a few\nthousand times. The methodology below was chosen for was chosen to be similar\nto real-world scenarios which operate on single objects at a time. Note that if\nwe did something like\n\n    pickle.dumps([dict(some_dict) for _ in range(10000)])\n\nthis isn't equivalent to dumping the dict 10000 times: pickle uses a\nhighly-efficient encoding for the n-1 following copies.\n\"\"\"\n\nimport sys\nimport datetime\nimport random\nimport sys\n\n\n__author__ = \"collinwinter@google.com (Collin Winter)\"\n\n\nDICT = {\n    \"ads_flags\": 0,\n    \"age\": 18,\n    \"birthday\": datetime.date(1980, 5, 7),\n    \"bulletin_count\": 0,\n    \"comment_count\": 0,\n    \"country\": \"BR\",\n    \"encrypted_id\": \"G9urXXAJwjE\",\n    \"favorite_count\": 9,\n    \"first_name\": \"\",\n    \"flags\": 412317970704,\n    \"friend_count\": 0,\n    \"gender\": \"m\",\n    \"gender_for_display\": \"Male\",\n    \"id\": 302935349,\n    \"is_custom_profile_icon\": 0,\n    \"last_name\": \"\",\n    \"locale_preference\": \"pt_BR\",\n    \"member\": 0,\n    \"tags\": [\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"],\n    \"profile_foo_id\": 827119638,\n    \"secure_encrypted_id\": \"Z_xxx2dYx3t4YAdnmfgyKw\",\n    \"session_number\": 2,\n    \"signup_id\": \"201-19225-223\",\n    \"status\": \"A\",\n    \"theme\": 1,\n    \"time_created\": 1225237014,\n    \"time_updated\": 1233134493,\n    \"unread_message_count\": 0,\n    \"user_group\": \"0\",\n    \"username\": \"collinwinter\",\n    \"play_count\": 9,\n    \"view_count\": 7,\n    \"zip\": \"\",\n}\n\nTUPLE = (\n    [\n        265867233,\n        265868503,\n        265252341,\n        265243910,\n        265879514,\n        266219766,\n        266021701,\n        265843726,\n        265592821,\n        265246784,\n        265853180,\n        45526486,\n        265463699,\n        265848143,\n        265863062,\n        265392591,\n        265877490,\n        265823665,\n        265828884,\n        265753032,\n    ],\n    60,\n)\n\n\ndef mutate_dict(orig_dict, random_source):\n    new_dict = dict(orig_dict)\n    for key, value in new_dict.items():\n        rand_val = random_source.random() * sys.maxsize\n        if isinstance(key, (int, bytes, str)):\n            new_dict[key] = type(key)(rand_val)\n    return new_dict\n\n\nrandom_source = random.Random(5)  # Fixed seed.\nDICT_GROUP = [mutate_dict(DICT, random_source) for _ in range(3)]\n\n\ndef bench_pickle(loops, pickle, protocol):\n    range_it = range(loops)\n\n    # micro-optimization: use fast local variables\n    dumps = pickle.dumps\n    objs = (DICT, TUPLE, DICT_GROUP)\n    for _ in range_it:\n        for obj in objs:\n            # 20 dumps\n            dumps(obj, protocol)\n            dumps(obj, protocol)\n            dumps(obj, protocol)\n            dumps(obj, protocol)\n            dumps(obj, protocol)\n            dumps(obj, protocol)\n            dumps(obj, protocol)\n            dumps(obj, protocol)\n            dumps(obj, protocol)\n            dumps(obj, protocol)\n            dumps(obj, protocol)\n            dumps(obj, protocol)\n            dumps(obj, protocol)\n            dumps(obj, protocol)\n            dumps(obj, protocol)\n            dumps(obj, protocol)\n            dumps(obj, protocol)\n            dumps(obj, protocol)\n            dumps(obj, protocol)\n            dumps(obj, protocol)\n\n\ndef bench_unpickle(loops, pickle, protocol):\n    pickled_dict = pickle.dumps(DICT, protocol)\n    pickled_tuple = pickle.dumps(TUPLE, protocol)\n    pickled_dict_group = pickle.dumps(DICT_GROUP, protocol)\n    range_it = range(loops)\n\n    # micro-optimization: use fast local variables\n    loads = pickle.loads\n    objs = (pickled_dict, pickled_tuple, pickled_dict_group)\n\n    for _ in range_it:\n        for obj in objs:\n            # 20 loads dict\n            loads(obj)\n            loads(obj)\n            loads(obj)\n            loads(obj)\n            loads(obj)\n            loads(obj)\n            loads(obj)\n            loads(obj)\n            loads(obj)\n            loads(obj)\n            loads(obj)\n            loads(obj)\n            loads(obj)\n            loads(obj)\n            loads(obj)\n            loads(obj)\n            loads(obj)\n            loads(obj)\n            loads(obj)\n            loads(obj)\n\n\nLIST = [[list(range(10)), list(range(10))] for _ in range(10)]\n\n\ndef bench_pickle_list(loops, pickle, protocol):\n    range_it = range(loops)\n    # micro-optimization: use fast local variables\n    dumps = pickle.dumps\n    obj = LIST\n    protocol = protocol\n\n    for _ in range_it:\n        # 10 dumps list\n        dumps(obj, protocol)\n        dumps(obj, protocol)\n        dumps(obj, protocol)\n        dumps(obj, protocol)\n        dumps(obj, protocol)\n        dumps(obj, protocol)\n        dumps(obj, protocol)\n        dumps(obj, protocol)\n        dumps(obj, protocol)\n        dumps(obj, protocol)\n\n\ndef bench_unpickle_list(loops, pickle, protocol):\n    pickled_list = pickle.dumps(LIST, protocol)\n    range_it = range(loops)\n\n    # micro-optimization: use fast local variables\n    loads = pickle.loads\n\n    for _ in range_it:\n        # 10 loads list\n        loads(pickled_list)\n        loads(pickled_list)\n        loads(pickled_list)\n        loads(pickled_list)\n        loads(pickled_list)\n        loads(pickled_list)\n        loads(pickled_list)\n        loads(pickled_list)\n        loads(pickled_list)\n        loads(pickled_list)\n\n\nMICRO_DICT = dict((key, dict.fromkeys(range(10))) for key in range(100))\n\n\ndef bench_pickle_dict(loops, pickle, protocol):\n    range_it = range(loops)\n    # micro-optimization: use fast local variables\n    protocol = protocol\n    obj = MICRO_DICT\n\n    for _ in range_it:\n        # 5 dumps dict\n        pickle.dumps(obj, protocol)\n        pickle.dumps(obj, protocol)\n        pickle.dumps(obj, protocol)\n        pickle.dumps(obj, protocol)\n        pickle.dumps(obj, protocol)\n\n\nBENCHMARKS = {\n    # 20 inner-loops: don't count the 3 pickled objects\n    \"pickle\": (bench_pickle, 20),\n    # 20 inner-loops: don't count the 3 unpickled objects\n    \"unpickle\": (bench_unpickle, 20),\n    \"pickle_list\": (bench_pickle_list, 10),\n    \"unpickle_list\": (bench_unpickle_list, 10),\n    \"pickle_dict\": (bench_pickle_dict, 5),\n}\n\n\ndef is_accelerated_module(module):\n    return getattr(module.Pickler, \"__module__\", \"<jython>\") != \"pickle\"\n\n\ndef add_cmdline_args(cmd, args):\n    if args.pure_python:\n        cmd.append(\"--pure-python\")\n    cmd.extend((\"--protocol\", str(args.protocol)))\n    cmd.append(args.benchmark)\n\n\ndef run_benchmark_pure_python(benchmark):\n    benchmarks = sorted(BENCHMARKS)\n    benchmark, inner_loops = BENCHMARKS[benchmark]\n    sys.modules[\"_pickle\"] = None\n    import pickle\n\n    if is_accelerated_module(pickle):\n        raise RuntimeError(\"Unexpected C accelerators for pickle\")\n    benchmark(1, pickle, pickle.HIGHEST_PROTOCOL)\n\n\ndef run_benchmark_c(benchmark):\n    benchmarks = sorted(BENCHMARKS)\n    benchmark, inner_loops = BENCHMARKS[benchmark]\n    import pickle\n\n    if not is_accelerated_module(pickle):\n        raise RuntimeError(\"Missing C accelerators for pickle\")\n    benchmark(1, pickle, pickle.HIGHEST_PROTOCOL)\n\n\nif __name__ == \"__main__\":\n    bench = sys.argv[1]\n    if sys.argv[2] == \"--pure-python\":\n        run_benchmark_pure_python(bench)\n    else:\n        run_benchmark_c(bench)\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/pickles_memray.py",
    "content": "\"\"\"Script for testing the performance of pickling/unpickling.\n\nThis will pickle/unpickle several real world-representative objects a few\nthousand times. The methodology below was chosen for was chosen to be similar\nto real-world scenarios which operate on single objects at a time. Note that if\nwe did something like\n\n    pickle.dumps([dict(some_dict) for _ in range(10000)])\n\nthis isn't equivalent to dumping the dict 10000 times: pickle uses a\nhighly-efficient encoding for the n-1 following copies.\n\"\"\"\n\nimport datetime\nimport random\nimport sys\n\nimport pyperf\nfrom memray_helper import get_tracker\n\nIS_PYPY = pyperf.python_implementation() == \"pypy\"\n\n__author__ = \"collinwinter@google.com (Collin Winter)\"\n\n\nDICT = {\n    \"ads_flags\": 0,\n    \"age\": 18,\n    \"birthday\": datetime.date(1980, 5, 7),\n    \"bulletin_count\": 0,\n    \"comment_count\": 0,\n    \"country\": \"BR\",\n    \"encrypted_id\": \"G9urXXAJwjE\",\n    \"favorite_count\": 9,\n    \"first_name\": \"\",\n    \"flags\": 412317970704,\n    \"friend_count\": 0,\n    \"gender\": \"m\",\n    \"gender_for_display\": \"Male\",\n    \"id\": 302935349,\n    \"is_custom_profile_icon\": 0,\n    \"last_name\": \"\",\n    \"locale_preference\": \"pt_BR\",\n    \"member\": 0,\n    \"tags\": [\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\"],\n    \"profile_foo_id\": 827119638,\n    \"secure_encrypted_id\": \"Z_xxx2dYx3t4YAdnmfgyKw\",\n    \"session_number\": 2,\n    \"signup_id\": \"201-19225-223\",\n    \"status\": \"A\",\n    \"theme\": 1,\n    \"time_created\": 1225237014,\n    \"time_updated\": 1233134493,\n    \"unread_message_count\": 0,\n    \"user_group\": \"0\",\n    \"username\": \"collinwinter\",\n    \"play_count\": 9,\n    \"view_count\": 7,\n    \"zip\": \"\",\n}\n\nTUPLE = (\n    [\n        265867233,\n        265868503,\n        265252341,\n        265243910,\n        265879514,\n        266219766,\n        266021701,\n        265843726,\n        265592821,\n        265246784,\n        265853180,\n        45526486,\n        265463699,\n        265848143,\n        265863062,\n        265392591,\n        265877490,\n        265823665,\n        265828884,\n        265753032,\n    ],\n    60,\n)\n\n\ndef mutate_dict(orig_dict, random_source):\n    new_dict = dict(orig_dict)\n    for key, value in new_dict.items():\n        rand_val = random_source.random() * sys.maxsize\n        if isinstance(key, (int, bytes, str)):\n            new_dict[key] = type(key)(rand_val)\n    return new_dict\n\n\nrandom_source = random.Random(5)  # Fixed seed.\nDICT_GROUP = [mutate_dict(DICT, random_source) for _ in range(3)]\n\n\ndef bench_pickle(loops, pickle, options):\n    range_it = range(loops)\n\n    # micro-optimization: use fast local variables\n    dumps = pickle.dumps\n    objs = (DICT, TUPLE, DICT_GROUP)\n    protocol = options.protocol\n\n    with get_tracker():\n        t0 = pyperf.perf_counter()\n        for _ in range_it:\n            for obj in objs:\n                # 20 dumps\n                dumps(obj, protocol)\n                dumps(obj, protocol)\n                dumps(obj, protocol)\n                dumps(obj, protocol)\n                dumps(obj, protocol)\n                dumps(obj, protocol)\n                dumps(obj, protocol)\n                dumps(obj, protocol)\n                dumps(obj, protocol)\n                dumps(obj, protocol)\n                dumps(obj, protocol)\n                dumps(obj, protocol)\n                dumps(obj, protocol)\n                dumps(obj, protocol)\n                dumps(obj, protocol)\n                dumps(obj, protocol)\n                dumps(obj, protocol)\n                dumps(obj, protocol)\n                dumps(obj, protocol)\n                dumps(obj, protocol)\n\n        return pyperf.perf_counter() - t0\n\n\ndef bench_unpickle(loops, pickle, options):\n    pickled_dict = pickle.dumps(DICT, options.protocol)\n    pickled_tuple = pickle.dumps(TUPLE, options.protocol)\n    pickled_dict_group = pickle.dumps(DICT_GROUP, options.protocol)\n    range_it = range(loops)\n\n    # micro-optimization: use fast local variables\n    loads = pickle.loads\n    objs = (pickled_dict, pickled_tuple, pickled_dict_group)\n\n    with get_tracker():\n        t0 = pyperf.perf_counter()\n        for _ in range_it:\n            for obj in objs:\n                # 20 loads dict\n                loads(obj)\n                loads(obj)\n                loads(obj)\n                loads(obj)\n                loads(obj)\n                loads(obj)\n                loads(obj)\n                loads(obj)\n                loads(obj)\n                loads(obj)\n                loads(obj)\n                loads(obj)\n                loads(obj)\n                loads(obj)\n                loads(obj)\n                loads(obj)\n                loads(obj)\n                loads(obj)\n                loads(obj)\n                loads(obj)\n\n        return pyperf.perf_counter() - t0\n\n\nLIST = [[list(range(10)), list(range(10))] for _ in range(10)]\n\n\ndef bench_pickle_list(loops, pickle, options):\n    range_it = range(loops)\n    # micro-optimization: use fast local variables\n    dumps = pickle.dumps\n    obj = LIST\n    protocol = options.protocol\n\n    with get_tracker():\n        t0 = pyperf.perf_counter()\n        for _ in range_it:\n            # 10 dumps list\n            dumps(obj, protocol)\n            dumps(obj, protocol)\n            dumps(obj, protocol)\n            dumps(obj, protocol)\n            dumps(obj, protocol)\n            dumps(obj, protocol)\n            dumps(obj, protocol)\n            dumps(obj, protocol)\n            dumps(obj, protocol)\n            dumps(obj, protocol)\n\n        return pyperf.perf_counter() - t0\n\n\ndef bench_unpickle_list(loops, pickle, options):\n    pickled_list = pickle.dumps(LIST, options.protocol)\n    range_it = range(loops)\n\n    # micro-optimization: use fast local variables\n    loads = pickle.loads\n\n    with get_tracker():\n        t0 = pyperf.perf_counter()\n        for _ in range_it:\n            # 10 loads list\n            loads(pickled_list)\n            loads(pickled_list)\n            loads(pickled_list)\n            loads(pickled_list)\n            loads(pickled_list)\n            loads(pickled_list)\n            loads(pickled_list)\n            loads(pickled_list)\n            loads(pickled_list)\n            loads(pickled_list)\n\n        return pyperf.perf_counter() - t0\n\n\nMICRO_DICT = dict((key, dict.fromkeys(range(10))) for key in range(100))\n\n\ndef bench_pickle_dict(loops, pickle, options):\n    range_it = range(loops)\n    # micro-optimization: use fast local variables\n    protocol = options.protocol\n    obj = MICRO_DICT\n\n    with get_tracker():\n        t0 = pyperf.perf_counter()\n        for _ in range_it:\n            # 5 dumps dict\n            pickle.dumps(obj, protocol)\n            pickle.dumps(obj, protocol)\n            pickle.dumps(obj, protocol)\n            pickle.dumps(obj, protocol)\n            pickle.dumps(obj, protocol)\n\n        return pyperf.perf_counter() - t0\n\n\nBENCHMARKS = {\n    # 20 inner-loops: don't count the 3 pickled objects\n    \"pickle\": (bench_pickle, 20),\n    # 20 inner-loops: don't count the 3 unpickled objects\n    \"unpickle\": (bench_unpickle, 20),\n    \"pickle_list\": (bench_pickle_list, 10),\n    \"unpickle_list\": (bench_unpickle_list, 10),\n    \"pickle_dict\": (bench_pickle_dict, 5),\n}\n\n\ndef is_accelerated_module(module):\n    return getattr(module.Pickler, \"__module__\", \"<jython>\") != \"pickle\"\n\n\ndef add_cmdline_args(cmd, args):\n    if args.pure_python:\n        cmd.append(\"--pure-python\")\n    cmd.extend((\"--protocol\", str(args.protocol)))\n    cmd.append(args.benchmark)\n\n\nif __name__ == \"__main__\":\n    runner = pyperf.Runner(add_cmdline_args=add_cmdline_args)\n    runner.metadata[\"description\"] = \"Test the performance of pickling.\"\n\n    parser = runner.argparser\n    parser.add_argument(\n        \"--pure-python\", action=\"store_true\", help=\"Use the C version of pickle.\"\n    )\n    parser.add_argument(\n        \"--protocol\",\n        action=\"store\",\n        default=None,\n        type=int,\n        help=\"Which protocol to use (default: highest protocol).\",\n    )\n    benchmarks = sorted(BENCHMARKS)\n    parser.add_argument(\"benchmark\", choices=benchmarks)\n\n    options = runner.parse_args()\n    benchmark, inner_loops = BENCHMARKS[options.benchmark]\n\n    name = options.benchmark\n    if options.pure_python:\n        name += \"_pure_python\"\n\n    if not (options.pure_python or IS_PYPY):\n        # C accelerators are enabled by default on 3.x\n        import pickle\n\n        if not is_accelerated_module(pickle):\n            raise RuntimeError(\"Missing C accelerators for pickle\")\n    else:\n        sys.modules[\"_pickle\"] = None\n        import pickle\n\n        if is_accelerated_module(pickle):\n            raise RuntimeError(\"Unexpected C accelerators for pickle\")\n\n    if options.protocol is None:\n        options.protocol = pickle.HIGHEST_PROTOCOL\n    runner.metadata[\"pickle_protocol\"] = str(options.protocol)\n    runner.metadata[\"pickle_module\"] = pickle.__name__\n\n    runner.bench_time_func(name, benchmark, pickle, options, inner_loops=inner_loops)\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/pprint_format_base.py",
    "content": "\"\"\"Test the performance of pprint.PrettyPrinter.\n\nThis benchmark was available as `python -m pprint` until Python 3.12.\n\nAuthors: Fred Drake (original), Oleg Iarygin (pyperformance port).\n\"\"\"\n\nfrom pprint import PrettyPrinter\n\nprintable = [(\"string\", (1, 2), [3, 4], {5: 6, 7: 8})] * 100_000\np = PrettyPrinter()\n\n\ndef run_benchmark():\n    if hasattr(p, \"_safe_repr\"):\n        p._safe_repr(printable, {}, None, 0)\n    p.pformat(printable)\n\n\nif __name__ == \"__main__\":\n    run_benchmark()\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/pprint_format_memray.py",
    "content": "\"\"\"Test the performance of pprint.PrettyPrinter.\n\nThis benchmark was available as `python -m pprint` until Python 3.12.\n\nAuthors: Fred Drake (original), Oleg Iarygin (pyperformance port).\n\"\"\"\n\nimport pyperf\nfrom pprint import PrettyPrinter\nfrom memray_helper import get_tracker\n\n\nprintable = [(\"string\", (1, 2), [3, 4], {5: 6, 7: 8})] * 100_000\np = PrettyPrinter()\n\n\ndef format(*args, **kwrags):\n    with get_tracker():\n        p.pformat(*args, **kwrags)\n\n\ndef safe_repr(*args, **kwargs):\n    with get_tracker():\n        p._safe_repr(*args, **kwargs)\n\n\nif __name__ == \"__main__\":\n    runner = pyperf.Runner()\n    runner.metadata[\"description\"] = \"pprint benchmark\"\n\n    if hasattr(p, \"_safe_repr\"):\n        runner.bench_func(\"pprint_safe_repr\", safe_repr, printable, {}, None, 0)\n    runner.bench_func(\"pprint_pformat\", format, printable)\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/raytrace_base.py",
    "content": "\"\"\"\nThis file contains definitions for a simple raytracer.\nCopyright Callum and Tony Garnock-Jones, 2008.\n\nThis file may be freely redistributed under the MIT license,\nhttp://www.opensource.org/licenses/mit-license.php\n\nFrom http://www.lshift.net/blog/2008/10/29/toy-raytracer-in-python\n\"\"\"\n\nimport array\nimport math\n\n\nDEFAULT_WIDTH = 100\nDEFAULT_HEIGHT = 100\nEPSILON = 0.00001\n\n\nclass Vector(object):\n    def __init__(self, initx, inity, initz):\n        self.x = initx\n        self.y = inity\n        self.z = initz\n\n    def __str__(self):\n        return \"(%s,%s,%s)\" % (self.x, self.y, self.z)\n\n    def __repr__(self):\n        return \"Vector(%s,%s,%s)\" % (self.x, self.y, self.z)\n\n    def magnitude(self):\n        return math.sqrt(self.dot(self))\n\n    def __add__(self, other):\n        if other.isPoint():\n            return Point(self.x + other.x, self.y + other.y, self.z + other.z)\n        else:\n            return Vector(self.x + other.x, self.y + other.y, self.z + other.z)\n\n    def __sub__(self, other):\n        other.mustBeVector()\n        return Vector(self.x - other.x, self.y - other.y, self.z - other.z)\n\n    def scale(self, factor):\n        return Vector(factor * self.x, factor * self.y, factor * self.z)\n\n    def dot(self, other):\n        other.mustBeVector()\n        return (self.x * other.x) + (self.y * other.y) + (self.z * other.z)\n\n    def cross(self, other):\n        other.mustBeVector()\n        return Vector(\n            self.y * other.z - self.z * other.y,\n            self.z * other.x - self.x * other.z,\n            self.x * other.y - self.y * other.x,\n        )\n\n    def normalized(self):\n        return self.scale(1.0 / self.magnitude())\n\n    def negated(self):\n        return self.scale(-1)\n\n    def __eq__(self, other):\n        return (self.x == other.x) and (self.y == other.y) and (self.z == other.z)\n\n    def isVector(self):\n        return True\n\n    def isPoint(self):\n        return False\n\n    def mustBeVector(self):\n        return self\n\n    def mustBePoint(self):\n        raise \"Vectors are not points!\"\n\n    def reflectThrough(self, normal):\n        d = normal.scale(self.dot(normal))\n        return self - d.scale(2)\n\n\nVector.ZERO = Vector(0, 0, 0)\nVector.RIGHT = Vector(1, 0, 0)\nVector.UP = Vector(0, 1, 0)\nVector.OUT = Vector(0, 0, 1)\n\nassert Vector.RIGHT.reflectThrough(Vector.UP) == Vector.RIGHT\nassert Vector(-1, -1, 0).reflectThrough(Vector.UP) == Vector(-1, 1, 0)\n\n\nclass Point(object):\n    def __init__(self, initx, inity, initz):\n        self.x = initx\n        self.y = inity\n        self.z = initz\n\n    def __str__(self):\n        return \"(%s,%s,%s)\" % (self.x, self.y, self.z)\n\n    def __repr__(self):\n        return \"Point(%s,%s,%s)\" % (self.x, self.y, self.z)\n\n    def __add__(self, other):\n        other.mustBeVector()\n        return Point(self.x + other.x, self.y + other.y, self.z + other.z)\n\n    def __sub__(self, other):\n        if other.isPoint():\n            return Vector(self.x - other.x, self.y - other.y, self.z - other.z)\n        else:\n            return Point(self.x - other.x, self.y - other.y, self.z - other.z)\n\n    def isVector(self):\n        return False\n\n    def isPoint(self):\n        return True\n\n    def mustBeVector(self):\n        raise \"Points are not vectors!\"\n\n    def mustBePoint(self):\n        return self\n\n\nclass Sphere(object):\n    def __init__(self, centre, radius):\n        centre.mustBePoint()\n        self.centre = centre\n        self.radius = radius\n\n    def __repr__(self):\n        return \"Sphere(%s,%s)\" % (repr(self.centre), self.radius)\n\n    def intersectionTime(self, ray):\n        cp = self.centre - ray.point\n        v = cp.dot(ray.vector)\n        discriminant = (self.radius * self.radius) - (cp.dot(cp) - v * v)\n        if discriminant < 0:\n            return None\n        else:\n            return v - math.sqrt(discriminant)\n\n    def normalAt(self, p):\n        return (p - self.centre).normalized()\n\n\nclass Halfspace(object):\n    def __init__(self, point, normal):\n        self.point = point\n        self.normal = normal.normalized()\n\n    def __repr__(self):\n        return \"Halfspace(%s,%s)\" % (repr(self.point), repr(self.normal))\n\n    def intersectionTime(self, ray):\n        v = ray.vector.dot(self.normal)\n        if v:\n            return 1 / -v\n        else:\n            return None\n\n    def normalAt(self, p):\n        return self.normal\n\n\nclass Ray(object):\n    def __init__(self, point, vector):\n        self.point = point\n        self.vector = vector.normalized()\n\n    def __repr__(self):\n        return \"Ray(%s,%s)\" % (repr(self.point), repr(self.vector))\n\n    def pointAtTime(self, t):\n        return self.point + self.vector.scale(t)\n\n\nPoint.ZERO = Point(0, 0, 0)\n\n\nclass Canvas(object):\n    def __init__(self, width, height):\n        self.bytes = array.array(\"B\", [0] * (width * height * 3))\n        for i in range(width * height):\n            self.bytes[i * 3 + 2] = 255\n        self.width = width\n        self.height = height\n\n    def plot(self, x, y, r, g, b):\n        i = ((self.height - y - 1) * self.width + x) * 3\n        self.bytes[i] = max(0, min(255, int(r * 255)))\n        self.bytes[i + 1] = max(0, min(255, int(g * 255)))\n        self.bytes[i + 2] = max(0, min(255, int(b * 255)))\n\n    def write_ppm(self, filename):\n        header = \"P6 %d %d 255\\n\" % (self.width, self.height)\n        with open(filename, \"wb\") as fp:\n            fp.write(header.encode(\"ascii\"))\n            fp.write(self.bytes.tobytes())\n\n\ndef firstIntersection(intersections):\n    result = None\n    for i in intersections:\n        candidateT = i[1]\n        if candidateT is not None and candidateT > -EPSILON:\n            if result is None or candidateT < result[1]:\n                result = i\n    return result\n\n\nclass Scene(object):\n    def __init__(self):\n        self.objects = []\n        self.lightPoints = []\n        self.position = Point(0, 1.8, 10)\n        self.lookingAt = Point.ZERO\n        self.fieldOfView = 45\n        self.recursionDepth = 0\n\n    def moveTo(self, p):\n        self.position = p\n\n    def lookAt(self, p):\n        self.lookingAt = p\n\n    def addObject(self, object, surface):\n        self.objects.append((object, surface))\n\n    def addLight(self, p):\n        self.lightPoints.append(p)\n\n    def render(self, canvas):\n        fovRadians = math.pi * (self.fieldOfView / 2.0) / 180.0\n        halfWidth = math.tan(fovRadians)\n        halfHeight = 0.75 * halfWidth\n        width = halfWidth * 2\n        height = halfHeight * 2\n        pixelWidth = width / (canvas.width - 1)\n        pixelHeight = height / (canvas.height - 1)\n\n        eye = Ray(self.position, self.lookingAt - self.position)\n        vpRight = eye.vector.cross(Vector.UP).normalized()\n        vpUp = vpRight.cross(eye.vector).normalized()\n\n        for y in range(canvas.height):\n            for x in range(canvas.width):\n                xcomp = vpRight.scale(x * pixelWidth - halfWidth)\n                ycomp = vpUp.scale(y * pixelHeight - halfHeight)\n                ray = Ray(eye.point, eye.vector + xcomp + ycomp)\n                colour = self.rayColour(ray)\n                canvas.plot(x, y, *colour)\n\n    def rayColour(self, ray):\n        if self.recursionDepth > 3:\n            return (0, 0, 0)\n        try:\n            self.recursionDepth = self.recursionDepth + 1\n            intersections = [(o, o.intersectionTime(ray), s) for (o, s) in self.objects]\n            i = firstIntersection(intersections)\n            if i is None:\n                return (0, 0, 0)  # the background colour\n            else:\n                (o, t, s) = i\n                p = ray.pointAtTime(t)\n                return s.colourAt(self, ray, p, o.normalAt(p))\n        finally:\n            self.recursionDepth = self.recursionDepth - 1\n\n    def _lightIsVisible(self, l, p):\n        for (o, s) in self.objects:\n            t = o.intersectionTime(Ray(p, l - p))\n            if t is not None and t > EPSILON:\n                return False\n        return True\n\n    def visibleLights(self, p):\n        result = []\n        for l in self.lightPoints:\n            if self._lightIsVisible(l, p):\n                result.append(l)\n        return result\n\n\ndef addColours(a, scale, b):\n    return (a[0] + scale * b[0], a[1] + scale * b[1], a[2] + scale * b[2])\n\n\nclass SimpleSurface(object):\n    def __init__(self, **kwargs):\n        self.baseColour = kwargs.get(\"baseColour\", (1, 1, 1))\n        self.specularCoefficient = kwargs.get(\"specularCoefficient\", 0.2)\n        self.lambertCoefficient = kwargs.get(\"lambertCoefficient\", 0.6)\n        self.ambientCoefficient = (\n            1.0 - self.specularCoefficient - self.lambertCoefficient\n        )\n\n    def baseColourAt(self, p):\n        return self.baseColour\n\n    def colourAt(self, scene, ray, p, normal):\n        b = self.baseColourAt(p)\n\n        c = (0, 0, 0)\n        if self.specularCoefficient > 0:\n            reflectedRay = Ray(p, ray.vector.reflectThrough(normal))\n            reflectedColour = scene.rayColour(reflectedRay)\n            c = addColours(c, self.specularCoefficient, reflectedColour)\n\n        if self.lambertCoefficient > 0:\n            lambertAmount = 0\n            for lightPoint in scene.visibleLights(p):\n                contribution = (lightPoint - p).normalized().dot(normal)\n                if contribution > 0:\n                    lambertAmount = lambertAmount + contribution\n            lambertAmount = min(1, lambertAmount)\n            c = addColours(c, self.lambertCoefficient * lambertAmount, b)\n\n        if self.ambientCoefficient > 0:\n            c = addColours(c, self.ambientCoefficient, b)\n\n        return c\n\n\nclass CheckerboardSurface(SimpleSurface):\n    def __init__(self, **kwargs):\n        SimpleSurface.__init__(self, **kwargs)\n        self.otherColour = kwargs.get(\"otherColour\", (0, 0, 0))\n        self.checkSize = kwargs.get(\"checkSize\", 1)\n\n    def baseColourAt(self, p):\n        v = p - Point.ZERO\n        v.scale(1.0 / self.checkSize)\n        if (int(abs(v.x) + 0.5) + int(abs(v.y) + 0.5) + int(abs(v.z) + 0.5)) % 2:\n            return self.otherColour\n        else:\n            return self.baseColour\n\n\ndef bench_raytrace(loops, width, height, filename):\n    range_it = range(loops)\n    for i in range_it:\n        canvas = Canvas(width, height)\n        s = Scene()\n        s.addLight(Point(30, 30, 10))\n        s.addLight(Point(-10, 100, 30))\n        s.lookAt(Point(0, 3, 0))\n        s.addObject(Sphere(Point(1, 3, -10), 2), SimpleSurface(baseColour=(1, 1, 0)))\n        for y in range(6):\n            s.addObject(\n                Sphere(Point(-3 - y * 0.4, 2.3, -5), 0.4),\n                SimpleSurface(baseColour=(y / 6.0, 1 - y / 6.0, 0.5)),\n            )\n        s.addObject(Halfspace(Point(0, 0, 0), Vector.UP), CheckerboardSurface())\n        s.render(canvas)\n\n    if filename:\n        canvas.write_ppm(filename)\n\n\ndef add_cmdline_args(cmd, args):\n    cmd.append(\"--width=%s\" % args.width)\n    cmd.append(\"--height=%s\" % args.height)\n    if args.filename:\n        cmd.extend((\"--filename\", args.filename))\n\n\ndef run_benchmark():\n    bench_raytrace(1, DEFAULT_WIDTH, DEFAULT_HEIGHT, None)\n\n\nif __name__ == \"__main__\":\n    run_benchmark()\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/raytrace_memray.py",
    "content": "\"\"\"\nThis file contains definitions for a simple raytracer.\nCopyright Callum and Tony Garnock-Jones, 2008.\n\nThis file may be freely redistributed under the MIT license,\nhttp://www.opensource.org/licenses/mit-license.php\n\nFrom http://www.lshift.net/blog/2008/10/29/toy-raytracer-in-python\n\"\"\"\n\nimport array\nimport math\n\nimport pyperf\nimport contextlib\nfrom memray_helper import get_tracker\n\nDEFAULT_WIDTH = 100\nDEFAULT_HEIGHT = 100\nEPSILON = 0.00001\n\n\nclass Vector(object):\n    def __init__(self, initx, inity, initz):\n        self.x = initx\n        self.y = inity\n        self.z = initz\n\n    def __str__(self):\n        return \"(%s,%s,%s)\" % (self.x, self.y, self.z)\n\n    def __repr__(self):\n        return \"Vector(%s,%s,%s)\" % (self.x, self.y, self.z)\n\n    def magnitude(self):\n        return math.sqrt(self.dot(self))\n\n    def __add__(self, other):\n        if other.isPoint():\n            return Point(self.x + other.x, self.y + other.y, self.z + other.z)\n        else:\n            return Vector(self.x + other.x, self.y + other.y, self.z + other.z)\n\n    def __sub__(self, other):\n        other.mustBeVector()\n        return Vector(self.x - other.x, self.y - other.y, self.z - other.z)\n\n    def scale(self, factor):\n        return Vector(factor * self.x, factor * self.y, factor * self.z)\n\n    def dot(self, other):\n        other.mustBeVector()\n        return (self.x * other.x) + (self.y * other.y) + (self.z * other.z)\n\n    def cross(self, other):\n        other.mustBeVector()\n        return Vector(\n            self.y * other.z - self.z * other.y,\n            self.z * other.x - self.x * other.z,\n            self.x * other.y - self.y * other.x,\n        )\n\n    def normalized(self):\n        return self.scale(1.0 / self.magnitude())\n\n    def negated(self):\n        return self.scale(-1)\n\n    def __eq__(self, other):\n        return (self.x == other.x) and (self.y == other.y) and (self.z == other.z)\n\n    def isVector(self):\n        return True\n\n    def isPoint(self):\n        return False\n\n    def mustBeVector(self):\n        return self\n\n    def mustBePoint(self):\n        raise \"Vectors are not points!\"\n\n    def reflectThrough(self, normal):\n        d = normal.scale(self.dot(normal))\n        return self - d.scale(2)\n\n\nVector.ZERO = Vector(0, 0, 0)\nVector.RIGHT = Vector(1, 0, 0)\nVector.UP = Vector(0, 1, 0)\nVector.OUT = Vector(0, 0, 1)\n\nassert Vector.RIGHT.reflectThrough(Vector.UP) == Vector.RIGHT\nassert Vector(-1, -1, 0).reflectThrough(Vector.UP) == Vector(-1, 1, 0)\n\n\nclass Point(object):\n    def __init__(self, initx, inity, initz):\n        self.x = initx\n        self.y = inity\n        self.z = initz\n\n    def __str__(self):\n        return \"(%s,%s,%s)\" % (self.x, self.y, self.z)\n\n    def __repr__(self):\n        return \"Point(%s,%s,%s)\" % (self.x, self.y, self.z)\n\n    def __add__(self, other):\n        other.mustBeVector()\n        return Point(self.x + other.x, self.y + other.y, self.z + other.z)\n\n    def __sub__(self, other):\n        if other.isPoint():\n            return Vector(self.x - other.x, self.y - other.y, self.z - other.z)\n        else:\n            return Point(self.x - other.x, self.y - other.y, self.z - other.z)\n\n    def isVector(self):\n        return False\n\n    def isPoint(self):\n        return True\n\n    def mustBeVector(self):\n        raise \"Points are not vectors!\"\n\n    def mustBePoint(self):\n        return self\n\n\nclass Sphere(object):\n    def __init__(self, centre, radius):\n        centre.mustBePoint()\n        self.centre = centre\n        self.radius = radius\n\n    def __repr__(self):\n        return \"Sphere(%s,%s)\" % (repr(self.centre), self.radius)\n\n    def intersectionTime(self, ray):\n        cp = self.centre - ray.point\n        v = cp.dot(ray.vector)\n        discriminant = (self.radius * self.radius) - (cp.dot(cp) - v * v)\n        if discriminant < 0:\n            return None\n        else:\n            return v - math.sqrt(discriminant)\n\n    def normalAt(self, p):\n        return (p - self.centre).normalized()\n\n\nclass Halfspace(object):\n    def __init__(self, point, normal):\n        self.point = point\n        self.normal = normal.normalized()\n\n    def __repr__(self):\n        return \"Halfspace(%s,%s)\" % (repr(self.point), repr(self.normal))\n\n    def intersectionTime(self, ray):\n        v = ray.vector.dot(self.normal)\n        if v:\n            return 1 / -v\n        else:\n            return None\n\n    def normalAt(self, p):\n        return self.normal\n\n\nclass Ray(object):\n    def __init__(self, point, vector):\n        self.point = point\n        self.vector = vector.normalized()\n\n    def __repr__(self):\n        return \"Ray(%s,%s)\" % (repr(self.point), repr(self.vector))\n\n    def pointAtTime(self, t):\n        return self.point + self.vector.scale(t)\n\n\nPoint.ZERO = Point(0, 0, 0)\n\n\nclass Canvas(object):\n    def __init__(self, width, height):\n        self.bytes = array.array(\"B\", [0] * (width * height * 3))\n        for i in range(width * height):\n            self.bytes[i * 3 + 2] = 255\n        self.width = width\n        self.height = height\n\n    def plot(self, x, y, r, g, b):\n        i = ((self.height - y - 1) * self.width + x) * 3\n        self.bytes[i] = max(0, min(255, int(r * 255)))\n        self.bytes[i + 1] = max(0, min(255, int(g * 255)))\n        self.bytes[i + 2] = max(0, min(255, int(b * 255)))\n\n    def write_ppm(self, filename):\n        header = \"P6 %d %d 255\\n\" % (self.width, self.height)\n        with open(filename, \"wb\") as fp:\n            fp.write(header.encode(\"ascii\"))\n            fp.write(self.bytes.tobytes())\n\n\ndef firstIntersection(intersections):\n    result = None\n    for i in intersections:\n        candidateT = i[1]\n        if candidateT is not None and candidateT > -EPSILON:\n            if result is None or candidateT < result[1]:\n                result = i\n    return result\n\n\nclass Scene(object):\n    def __init__(self):\n        self.objects = []\n        self.lightPoints = []\n        self.position = Point(0, 1.8, 10)\n        self.lookingAt = Point.ZERO\n        self.fieldOfView = 45\n        self.recursionDepth = 0\n\n    def moveTo(self, p):\n        self.position = p\n\n    def lookAt(self, p):\n        self.lookingAt = p\n\n    def addObject(self, object, surface):\n        self.objects.append((object, surface))\n\n    def addLight(self, p):\n        self.lightPoints.append(p)\n\n    def render(self, canvas):\n        fovRadians = math.pi * (self.fieldOfView / 2.0) / 180.0\n        halfWidth = math.tan(fovRadians)\n        halfHeight = 0.75 * halfWidth\n        width = halfWidth * 2\n        height = halfHeight * 2\n        pixelWidth = width / (canvas.width - 1)\n        pixelHeight = height / (canvas.height - 1)\n\n        eye = Ray(self.position, self.lookingAt - self.position)\n        vpRight = eye.vector.cross(Vector.UP).normalized()\n        vpUp = vpRight.cross(eye.vector).normalized()\n\n        for y in range(canvas.height):\n            for x in range(canvas.width):\n                xcomp = vpRight.scale(x * pixelWidth - halfWidth)\n                ycomp = vpUp.scale(y * pixelHeight - halfHeight)\n                ray = Ray(eye.point, eye.vector + xcomp + ycomp)\n                colour = self.rayColour(ray)\n                canvas.plot(x, y, *colour)\n\n    def rayColour(self, ray):\n        if self.recursionDepth > 3:\n            return (0, 0, 0)\n        try:\n            self.recursionDepth = self.recursionDepth + 1\n            intersections = [(o, o.intersectionTime(ray), s) for (o, s) in self.objects]\n            i = firstIntersection(intersections)\n            if i is None:\n                return (0, 0, 0)  # the background colour\n            else:\n                (o, t, s) = i\n                p = ray.pointAtTime(t)\n                return s.colourAt(self, ray, p, o.normalAt(p))\n        finally:\n            self.recursionDepth = self.recursionDepth - 1\n\n    def _lightIsVisible(self, l, p):\n        for (o, s) in self.objects:\n            t = o.intersectionTime(Ray(p, l - p))\n            if t is not None and t > EPSILON:\n                return False\n        return True\n\n    def visibleLights(self, p):\n        result = []\n        for l in self.lightPoints:\n            if self._lightIsVisible(l, p):\n                result.append(l)\n        return result\n\n\ndef addColours(a, scale, b):\n    return (a[0] + scale * b[0], a[1] + scale * b[1], a[2] + scale * b[2])\n\n\nclass SimpleSurface(object):\n    def __init__(self, **kwargs):\n        self.baseColour = kwargs.get(\"baseColour\", (1, 1, 1))\n        self.specularCoefficient = kwargs.get(\"specularCoefficient\", 0.2)\n        self.lambertCoefficient = kwargs.get(\"lambertCoefficient\", 0.6)\n        self.ambientCoefficient = (\n            1.0 - self.specularCoefficient - self.lambertCoefficient\n        )\n\n    def baseColourAt(self, p):\n        return self.baseColour\n\n    def colourAt(self, scene, ray, p, normal):\n        b = self.baseColourAt(p)\n\n        c = (0, 0, 0)\n        if self.specularCoefficient > 0:\n            reflectedRay = Ray(p, ray.vector.reflectThrough(normal))\n            reflectedColour = scene.rayColour(reflectedRay)\n            c = addColours(c, self.specularCoefficient, reflectedColour)\n\n        if self.lambertCoefficient > 0:\n            lambertAmount = 0\n            for lightPoint in scene.visibleLights(p):\n                contribution = (lightPoint - p).normalized().dot(normal)\n                if contribution > 0:\n                    lambertAmount = lambertAmount + contribution\n            lambertAmount = min(1, lambertAmount)\n            c = addColours(c, self.lambertCoefficient * lambertAmount, b)\n\n        if self.ambientCoefficient > 0:\n            c = addColours(c, self.ambientCoefficient, b)\n\n        return c\n\n\nclass CheckerboardSurface(SimpleSurface):\n    def __init__(self, **kwargs):\n        SimpleSurface.__init__(self, **kwargs)\n        self.otherColour = kwargs.get(\"otherColour\", (0, 0, 0))\n        self.checkSize = kwargs.get(\"checkSize\", 1)\n\n    def baseColourAt(self, p):\n        v = p - Point.ZERO\n        v.scale(1.0 / self.checkSize)\n        if (int(abs(v.x) + 0.5) + int(abs(v.y) + 0.5) + int(abs(v.z) + 0.5)) % 2:\n            return self.otherColour\n        else:\n            return self.baseColour\n\n\ndef bench_raytrace(loops, width, height, filename):\n    range_it = range(loops)\n    t0 = pyperf.perf_counter()\n\n    with get_tracker():\n        for i in range_it:\n            canvas = Canvas(width, height)\n            s = Scene()\n            s.addLight(Point(30, 30, 10))\n            s.addLight(Point(-10, 100, 30))\n            s.lookAt(Point(0, 3, 0))\n            s.addObject(\n                Sphere(Point(1, 3, -10), 2), SimpleSurface(baseColour=(1, 1, 0))\n            )\n            for y in range(6):\n                s.addObject(\n                    Sphere(Point(-3 - y * 0.4, 2.3, -5), 0.4),\n                    SimpleSurface(baseColour=(y / 6.0, 1 - y / 6.0, 0.5)),\n                )\n            s.addObject(Halfspace(Point(0, 0, 0), Vector.UP), CheckerboardSurface())\n            s.render(canvas)\n\n    dt = pyperf.perf_counter() - t0\n\n    if filename:\n        canvas.write_ppm(filename)\n    return dt\n\n\ndef add_cmdline_args(cmd, args):\n    cmd.append(\"--width=%s\" % args.width)\n    cmd.append(\"--height=%s\" % args.height)\n    if args.filename:\n        cmd.extend((\"--filename\", args.filename))\n\n\nif __name__ == \"__main__\":\n    runner = pyperf.Runner(add_cmdline_args=add_cmdline_args)\n    cmd = runner.argparser\n    cmd.add_argument(\n        \"--width\",\n        type=int,\n        default=DEFAULT_WIDTH,\n        help=\"Image width (default: %s)\" % DEFAULT_WIDTH,\n    )\n    cmd.add_argument(\n        \"--height\",\n        type=int,\n        default=DEFAULT_HEIGHT,\n        help=\"Image height (default: %s)\" % DEFAULT_HEIGHT,\n    )\n    cmd.add_argument(\n        \"--filename\", metavar=\"FILENAME.PPM\", help=\"Output filename of the PPM picture\"\n    )\n\n    args = runner.parse_args()\n    runner.metadata[\"description\"] = \"Simple raytracer\"\n    runner.metadata[\"raytrace_width\"] = args.width\n    runner.metadata[\"raytrace_height\"] = args.height\n\n    runner.bench_time_func(\n        \"raytrace\", bench_raytrace, args.width, args.height, args.filename\n    )\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/regex_dna_base.py",
    "content": "#!/usr/bin/env python\n\"\"\"\nThe Computer Language Benchmarks Game\nhttp://benchmarksgame.alioth.debian.org/\n\nregex-dna Python 3 #5 program:\ncontributed by Dominique Wahli\n2to3\nmodified by Justin Peel\n\nfasta Python 3 #3 program:\nmodified by Ian Osgood\nmodified again by Heinrich Acker\nmodified by Justin Peel\nModified by Christopher Sean Forgeron\n\"\"\"\n\nimport bisect\nimport re\n\n\nDEFAULT_INIT_LEN = 100000\nDEFAULT_RNG_SEED = 42\n\nALU = (\n    \"GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGG\"\n    \"GAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGA\"\n    \"CCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAAT\"\n    \"ACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCA\"\n    \"GCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGG\"\n    \"AGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCC\"\n    \"AGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA\"\n)\n\nIUB = list(zip(\"acgtBDHKMNRSVWY\", [0.27, 0.12, 0.12, 0.27] + [0.02] * 11))\n\nHOMOSAPIENS = [\n    (\"a\", 0.3029549426680),\n    (\"c\", 0.1979883004921),\n    (\"g\", 0.1975473066391),\n    (\"t\", 0.3015094502008),\n]\n\n\ndef make_cumulative(table):\n    P = []\n    C = []\n    prob = 0.0\n    for char, p in table:\n        prob += p\n        P += [prob]\n        C += [ord(char)]\n    return (P, C)\n\n\ndef repeat_fasta(src, n, nprint):\n    width = 60\n\n    is_trailing_line = False\n    count_modifier = 0.0\n\n    len_of_src = len(src)\n    ss = src + src + src[: n % len_of_src]\n    # CSF - It's faster to work with a bytearray than a string\n    s = bytearray(ss, encoding=\"utf8\")\n\n    if n % width:\n        # We don't end on a 60 char wide line\n        is_trailing_line = True\n        count_modifier = 1.0\n\n    # CSF - Here we are stuck with using an int instead of a float for the loop,\n    # but testing showed it still to be faster than a for loop\n    count = 0\n    end = (n / float(width)) - count_modifier\n    while count < end:\n        i = count * 60 % len_of_src\n        nprint(s[i : i + 60] + b\"\\n\")\n        count += 1\n    if is_trailing_line:\n        nprint(s[-(n % width) :] + b\"\\n\")\n\n\ndef random_fasta(table, n, seed, nprint):\n    width = 60\n    r = range(width)\n    bb = bisect.bisect\n\n    # If we don't have a multiple of the width, then we will have a trailing\n    # line, which needs a slightly different approach\n    is_trailing_line = False\n    count_modifier = 0.0\n\n    line = bytearray(width + 1)  # Width of 60 + 1 for the \\n char\n\n    probs, chars = make_cumulative(table)\n\n    # pRNG Vars\n    im = 139968.0\n    seed = float(seed)\n\n    if n % width:\n        # We don't end on a 60 char wide line\n        is_trailing_line = True\n        count_modifier = 1.0\n\n    # CSF - Loops with a high iteration count run faster as a while/float loop.\n    count = 0.0\n    end = (n / float(width)) - count_modifier\n    while count < end:\n        # CSF - Low iteration count loops may run faster as a for loop.\n        for i in r:\n            # CSF - Python is faster for all float math than it is for int, on my\n            # machine at least.\n            seed = (seed * 3877.0 + 29573.0) % 139968.0\n            # CSF - While real values, not variables are faster for most things, on my\n            # machine, it's faster to have 'im' already in a var\n            line[i] = chars[bb(probs, seed / im)]\n\n        line[60] = 10  # End of Line\n        nprint(line)\n        count += 1.0\n\n    if is_trailing_line:\n        for i in range(n % width):\n            seed = (seed * 3877.0 + 29573.0) % 139968.0\n            line[i] = chars[bb(probs, seed / im)]\n\n        nprint(line[: i + 1] + b\"\\n\")\n\n    return seed\n\n\ndef init_benchmarks(n, rng_seed):\n    result = bytearray()\n    nprint = result.extend\n    nprint(b\">ONE Homo sapiens alu\\n\")\n    repeat_fasta(ALU, n * 2, nprint=nprint)\n\n    # We need to keep track of the state of 'seed' so we pass it in, and return\n    # it back so our output can pass the diff test\n    nprint(b\">TWO IUB ambiguity codes\\n\")\n    seed = random_fasta(IUB, n * 3, seed=rng_seed, nprint=nprint)\n\n    nprint(b\">THREE Homo sapiens frequency\\n\")\n    random_fasta(HOMOSAPIENS, n * 5, seed, nprint=nprint)\n\n    return bytes(result)\n\n\nVARIANTS = (\n    b\"agggtaaa|tttaccct\",\n    b\"[cgt]gggtaaa|tttaccc[acg]\",\n    b\"a[act]ggtaaa|tttacc[agt]t\",\n    b\"ag[act]gtaaa|tttac[agt]ct\",\n    b\"agg[act]taaa|ttta[agt]cct\",\n    b\"aggg[acg]aaa|ttt[cgt]ccct\",\n    b\"agggt[cgt]aa|tt[acg]accct\",\n    b\"agggta[cgt]a|t[acg]taccct\",\n    b\"agggtaa[cgt]|[acg]ttaccct\",\n)\n\nSUBST = (\n    (b\"B\", b\"(c|g|t)\"),\n    (b\"D\", b\"(a|g|t)\"),\n    (b\"H\", b\"(a|c|t)\"),\n    (b\"K\", b\"(g|t)\"),\n    (b\"M\", b\"(a|c)\"),\n    (b\"N\", b\"(a|c|g|t)\"),\n    (b\"R\", b\"(a|g)\"),\n    (b\"S\", b\"(c|g)\"),\n    (b\"V\", b\"(a|c|g)\"),\n    (b\"W\", b\"(a|t)\"),\n    (b\"Y\", b\"(c|t)\"),\n)\n\n\ndef run_benchmarks(seq):\n    ilen = len(seq)\n\n    seq = re.sub(b\">.*\\n|\\n\", b\"\", seq)\n    clen = len(seq)\n\n    results = []\n    for f in VARIANTS:\n        results.append(len(re.findall(f, seq)))\n\n    for f, r in SUBST:\n        seq = re.sub(f, r, seq)\n\n    return results, ilen, clen, len(seq)\n\n\ndef bench_regex_dna(loops, seq, expected_res):\n    range_it = range(loops)\n\n    for i in range_it:\n        res = run_benchmarks(seq)\n\n    if (expected_res is not None) and (res != expected_res):\n        raise Exception(\"run_benchmarks() error\")\n\n\ndef run_benchmark():\n    seq = init_benchmarks(DEFAULT_INIT_LEN, DEFAULT_RNG_SEED)\n    expected_res = ([6, 26, 86, 58, 113, 31, 31, 32, 43], 1016745, 1000000, 1336326)\n    bench_regex_dna(1, seq, expected_res)\n\n\nif __name__ == \"__main__\":\n    run_benchmark()\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/regex_dna_memray.py",
    "content": "#!/usr/bin/env python\n\"\"\"\nThe Computer Language Benchmarks Game\nhttp://benchmarksgame.alioth.debian.org/\n\nregex-dna Python 3 #5 program:\ncontributed by Dominique Wahli\n2to3\nmodified by Justin Peel\n\nfasta Python 3 #3 program:\nmodified by Ian Osgood\nmodified again by Heinrich Acker\nmodified by Justin Peel\nModified by Christopher Sean Forgeron\n\"\"\"\n\nimport bisect\nimport re\n\nimport pyperf\nfrom memray_helper import get_tracker\n\n\nDEFAULT_INIT_LEN = 100000\nDEFAULT_RNG_SEED = 42\n\nALU = (\n    \"GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGG\"\n    \"GAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGA\"\n    \"CCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAAT\"\n    \"ACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCA\"\n    \"GCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGG\"\n    \"AGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCC\"\n    \"AGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA\"\n)\n\nIUB = list(zip(\"acgtBDHKMNRSVWY\", [0.27, 0.12, 0.12, 0.27] + [0.02] * 11))\n\nHOMOSAPIENS = [\n    (\"a\", 0.3029549426680),\n    (\"c\", 0.1979883004921),\n    (\"g\", 0.1975473066391),\n    (\"t\", 0.3015094502008),\n]\n\n\ndef make_cumulative(table):\n    P = []\n    C = []\n    prob = 0.0\n    for char, p in table:\n        prob += p\n        P += [prob]\n        C += [ord(char)]\n    return (P, C)\n\n\ndef repeat_fasta(src, n, nprint):\n    width = 60\n\n    is_trailing_line = False\n    count_modifier = 0.0\n\n    len_of_src = len(src)\n    ss = src + src + src[: n % len_of_src]\n    # CSF - It's faster to work with a bytearray than a string\n    s = bytearray(ss, encoding=\"utf8\")\n\n    if n % width:\n        # We don't end on a 60 char wide line\n        is_trailing_line = True\n        count_modifier = 1.0\n\n    # CSF - Here we are stuck with using an int instead of a float for the loop,\n    # but testing showed it still to be faster than a for loop\n    count = 0\n    end = (n / float(width)) - count_modifier\n    while count < end:\n        i = count * 60 % len_of_src\n        nprint(s[i : i + 60] + b\"\\n\")\n        count += 1\n    if is_trailing_line:\n        nprint(s[-(n % width) :] + b\"\\n\")\n\n\ndef random_fasta(table, n, seed, nprint):\n    width = 60\n    r = range(width)\n    bb = bisect.bisect\n\n    # If we don't have a multiple of the width, then we will have a trailing\n    # line, which needs a slightly different approach\n    is_trailing_line = False\n    count_modifier = 0.0\n\n    line = bytearray(width + 1)  # Width of 60 + 1 for the \\n char\n\n    probs, chars = make_cumulative(table)\n\n    # pRNG Vars\n    im = 139968.0\n    seed = float(seed)\n\n    if n % width:\n        # We don't end on a 60 char wide line\n        is_trailing_line = True\n        count_modifier = 1.0\n\n    # CSF - Loops with a high iteration count run faster as a while/float loop.\n    count = 0.0\n    end = (n / float(width)) - count_modifier\n    while count < end:\n        # CSF - Low iteration count loops may run faster as a for loop.\n        for i in r:\n            # CSF - Python is faster for all float math than it is for int, on my\n            # machine at least.\n            seed = (seed * 3877.0 + 29573.0) % 139968.0\n            # CSF - While real values, not variables are faster for most things, on my\n            # machine, it's faster to have 'im' already in a var\n            line[i] = chars[bb(probs, seed / im)]\n\n        line[60] = 10  # End of Line\n        nprint(line)\n        count += 1.0\n\n    if is_trailing_line:\n        for i in range(n % width):\n            seed = (seed * 3877.0 + 29573.0) % 139968.0\n            line[i] = chars[bb(probs, seed / im)]\n\n        nprint(line[: i + 1] + b\"\\n\")\n\n    return seed\n\n\ndef init_benchmarks(n, rng_seed):\n    result = bytearray()\n    nprint = result.extend\n    nprint(b\">ONE Homo sapiens alu\\n\")\n    repeat_fasta(ALU, n * 2, nprint=nprint)\n\n    # We need to keep track of the state of 'seed' so we pass it in, and return\n    # it back so our output can pass the diff test\n    nprint(b\">TWO IUB ambiguity codes\\n\")\n    seed = random_fasta(IUB, n * 3, seed=rng_seed, nprint=nprint)\n\n    nprint(b\">THREE Homo sapiens frequency\\n\")\n    random_fasta(HOMOSAPIENS, n * 5, seed, nprint=nprint)\n\n    return bytes(result)\n\n\nVARIANTS = (\n    b\"agggtaaa|tttaccct\",\n    b\"[cgt]gggtaaa|tttaccc[acg]\",\n    b\"a[act]ggtaaa|tttacc[agt]t\",\n    b\"ag[act]gtaaa|tttac[agt]ct\",\n    b\"agg[act]taaa|ttta[agt]cct\",\n    b\"aggg[acg]aaa|ttt[cgt]ccct\",\n    b\"agggt[cgt]aa|tt[acg]accct\",\n    b\"agggta[cgt]a|t[acg]taccct\",\n    b\"agggtaa[cgt]|[acg]ttaccct\",\n)\n\nSUBST = (\n    (b\"B\", b\"(c|g|t)\"),\n    (b\"D\", b\"(a|g|t)\"),\n    (b\"H\", b\"(a|c|t)\"),\n    (b\"K\", b\"(g|t)\"),\n    (b\"M\", b\"(a|c)\"),\n    (b\"N\", b\"(a|c|g|t)\"),\n    (b\"R\", b\"(a|g)\"),\n    (b\"S\", b\"(c|g)\"),\n    (b\"V\", b\"(a|c|g)\"),\n    (b\"W\", b\"(a|t)\"),\n    (b\"Y\", b\"(c|t)\"),\n)\n\n\ndef run_benchmarks(seq):\n    ilen = len(seq)\n\n    seq = re.sub(b\">.*\\n|\\n\", b\"\", seq)\n    clen = len(seq)\n\n    results = []\n    for f in VARIANTS:\n        results.append(len(re.findall(f, seq)))\n\n    for f, r in SUBST:\n        seq = re.sub(f, r, seq)\n\n    return results, ilen, clen, len(seq)\n\n\ndef bench_regex_dna(loops, seq, expected_res):\n    range_it = range(loops)\n\n    with get_tracker():\n        t0 = pyperf.perf_counter()\n        for i in range_it:\n            res = run_benchmarks(seq)\n\n        dt = pyperf.perf_counter() - t0\n    if (expected_res is not None) and (res != expected_res):\n        raise Exception(\"run_benchmarks() error\")\n\n    return dt\n\n\ndef add_cmdline_args(cmd, args):\n    cmd.extend(\n        (\"--fasta-length\", str(args.fasta_length), \"--rng-seed\", str(args.rng_seed))\n    )\n\n\nif __name__ == \"__main__\":\n    runner = pyperf.Runner(add_cmdline_args=add_cmdline_args)\n    runner.metadata[\"description\"] = (\n        \"Test the performance of regexps \"\n        \"using benchmarks from \"\n        \"The Computer Language Benchmarks Game.\"\n    )\n\n    cmd = runner.argparser\n    cmd.add_argument(\n        \"--fasta-length\",\n        type=int,\n        default=DEFAULT_INIT_LEN,\n        help=\"Length of the fasta sequence \" \"(default: %s)\" % DEFAULT_INIT_LEN,\n    )\n    cmd.add_argument(\n        \"--rng-seed\",\n        type=int,\n        default=DEFAULT_RNG_SEED,\n        help=\"Seed of the random number generator \" \"(default: %s)\" % DEFAULT_RNG_SEED,\n    )\n\n    args = runner.parse_args()\n    if args.fasta_length == 100000:\n        expected_len = 1016745\n        expected_res = ([6, 26, 86, 58, 113, 31, 31, 32, 43], 1016745, 1000000, 1336326)\n    else:\n        expected_len = None\n        expected_res = None\n\n    runner.metadata[\"regex_dna_fasta_len\"] = args.fasta_length\n    runner.metadata[\"regex_dna_rng_seed\"] = args.rng_seed\n\n    seq = init_benchmarks(args.fasta_length, args.rng_seed)\n    if (expected_len is not None) and (len(seq) != expected_len):\n        raise Exception(\"init_benchmarks() error\")\n\n    runner.bench_time_func(\"regex_dna\", bench_regex_dna, seq, expected_res)\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/regex_effbot_base.py",
    "content": "\"\"\"Benchmarks for Python's regex engine.\n\nThese are some of the original benchmarks used to tune Python's regex engine\nin 2000 written by Fredrik Lundh. Retreived from\nhttp://mail.python.org/pipermail/python-dev/2000-August/007797.html and\nintegrated into Unladen Swallow's pyperf.py in 2009 by David Laing.\n\nThese benchmarks are of interest since they helped to guide the original\noptimization of the sre engine, and we shouldn't necessarily ignore them just\nbecause they're \"old\".\n\"\"\"\n\n# Python imports\nimport re\n\n# Local imports\nUSE_BYTES = False\n\n\ndef re_compile(s):\n    if USE_BYTES:\n        return re.compile(s.encode(\"latin1\"))\n    else:\n        return re.compile(s)\n\n\n# These are the regular expressions to be tested. These sync up,\n# index-for-index with the list of strings generated by gen_string_table()\n# below.\n\n\ndef gen_regex_table():\n    return [\n        re_compile(\"Python|Perl\"),\n        re_compile(\"Python|Perl\"),\n        re_compile(\"(Python|Perl)\"),\n        re_compile(\"(?:Python|Perl)\"),\n        re_compile(\"Python\"),\n        re_compile(\"Python\"),\n        re_compile(\".*Python\"),\n        re_compile(\".*Python.*\"),\n        re_compile(\".*(Python)\"),\n        re_compile(\".*(?:Python)\"),\n        re_compile(\"Python|Perl|Tcl\"),\n        re_compile(\"Python|Perl|Tcl\"),\n        re_compile(\"(Python|Perl|Tcl)\"),\n        re_compile(\"(?:Python|Perl|Tcl)\"),\n        re_compile(\"(Python)\\\\1\"),\n        re_compile(\"(Python)\\\\1\"),\n        re_compile(\"([0a-z][a-z0-9]*,)+\"),\n        re_compile(\"(?:[0a-z][a-z0-9]*,)+\"),\n        re_compile(\"([a-z][a-z0-9]*,)+\"),\n        re_compile(\"(?:[a-z][a-z0-9]*,)+\"),\n        re_compile(\".*P.*y.*t.*h.*o.*n.*\"),\n    ]\n\n\ndef gen_string_table(n):\n    \"\"\"Generates the list of strings that will be used in the benchmarks.\n\n    All strings have repeated prefixes and suffices, and n specifies the\n    number of repetitions.\n    \"\"\"\n    strings = []\n\n    def append(s):\n        if USE_BYTES:\n            strings.append(s.encode(\"latin1\"))\n        else:\n            strings.append(s)\n\n    append(\"-\" * n + \"Perl\" + \"-\" * n)\n    append(\"P\" * n + \"Perl\" + \"P\" * n)\n    append(\"-\" * n + \"Perl\" + \"-\" * n)\n    append(\"-\" * n + \"Perl\" + \"-\" * n)\n    append(\"-\" * n + \"Python\" + \"-\" * n)\n    append(\"P\" * n + \"Python\" + \"P\" * n)\n    append(\"-\" * n + \"Python\" + \"-\" * n)\n    append(\"-\" * n + \"Python\" + \"-\" * n)\n    append(\"-\" * n + \"Python\" + \"-\" * n)\n    append(\"-\" * n + \"Python\" + \"-\" * n)\n    append(\"-\" * n + \"Perl\" + \"-\" * n)\n    append(\"P\" * n + \"Perl\" + \"P\" * n)\n    append(\"-\" * n + \"Perl\" + \"-\" * n)\n    append(\"-\" * n + \"Perl\" + \"-\" * n)\n    append(\"-\" * n + \"PythonPython\" + \"-\" * n)\n    append(\"P\" * n + \"PythonPython\" + \"P\" * n)\n    append(\"-\" * n + \"a5,b7,c9,\" + \"-\" * n)\n    append(\"-\" * n + \"a5,b7,c9,\" + \"-\" * n)\n    append(\"-\" * n + \"a5,b7,c9,\" + \"-\" * n)\n    append(\"-\" * n + \"a5,b7,c9,\" + \"-\" * n)\n    append(\"-\" * n + \"Python\" + \"-\" * n)\n    return strings\n\n\ndef init_benchmarks(n_values=None):\n    \"\"\"Initialize the strings we'll run the regexes against.\n\n    The strings used in the benchmark are prefixed and suffixed by\n    strings that are repeated n times.\n\n    The sequence n_values contains the values for n.\n    If n_values is None the values of n from the original benchmark\n    are used.\n\n    The generated list of strings is cached in the string_tables\n    variable, which is indexed by n.\n\n    Returns:\n    A list of string prefix/suffix lengths.\n    \"\"\"\n\n    if n_values is None:\n        n_values = (0, 5, 50, 250, 1000, 5000, 10000)\n\n    string_tables = {n: gen_string_table(n) for n in n_values}\n    regexs = gen_regex_table()\n\n    data = []\n    for n in n_values:\n        for id in range(len(regexs)):\n            regex = regexs[id]\n            string = string_tables[n][id]\n            data.append((regex, string))\n    return data\n\n\ndef bench_regex_effbot(loops):\n    if bench_regex_effbot.data is None:\n        bench_regex_effbot.data = init_benchmarks()\n    data = bench_regex_effbot.data\n\n    range_it = range(loops)\n    search = re.search\n    for _ in range_it:\n        # Runs all of the benchmarks for a given value of n.\n        for regex, string in data:\n            # search 10 times\n            search(regex, string)\n            search(regex, string)\n            search(regex, string)\n            search(regex, string)\n            search(regex, string)\n            search(regex, string)\n            search(regex, string)\n            search(regex, string)\n            search(regex, string)\n            search(regex, string)\n\n\n# cached data, generated at the first call\nbench_regex_effbot.data = None\n\n\ndef run_benchmark():\n    bench_regex_effbot(1)\n\n\nif __name__ == \"__main__\":\n    run_benchmark()\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/regex_effbot_memray.py",
    "content": "\"\"\"Benchmarks for Python's regex engine.\n\nThese are some of the original benchmarks used to tune Python's regex engine\nin 2000 written by Fredrik Lundh. Retreived from\nhttp://mail.python.org/pipermail/python-dev/2000-August/007797.html and\nintegrated into Unladen Swallow's pyperf.py in 2009 by David Laing.\n\nThese benchmarks are of interest since they helped to guide the original\noptimization of the sre engine, and we shouldn't necessarily ignore them just\nbecause they're \"old\".\n\"\"\"\n\n# Python imports\nimport re\n\n# Local imports\nimport pyperf\nfrom memray_helper import get_tracker\n\nUSE_BYTES = False\n\n\ndef re_compile(s):\n    if USE_BYTES:\n        return re.compile(s.encode(\"latin1\"))\n    else:\n        return re.compile(s)\n\n\n# These are the regular expressions to be tested. These sync up,\n# index-for-index with the list of strings generated by gen_string_table()\n# below.\n\n\ndef gen_regex_table():\n    return [\n        re_compile(\"Python|Perl\"),\n        re_compile(\"Python|Perl\"),\n        re_compile(\"(Python|Perl)\"),\n        re_compile(\"(?:Python|Perl)\"),\n        re_compile(\"Python\"),\n        re_compile(\"Python\"),\n        re_compile(\".*Python\"),\n        re_compile(\".*Python.*\"),\n        re_compile(\".*(Python)\"),\n        re_compile(\".*(?:Python)\"),\n        re_compile(\"Python|Perl|Tcl\"),\n        re_compile(\"Python|Perl|Tcl\"),\n        re_compile(\"(Python|Perl|Tcl)\"),\n        re_compile(\"(?:Python|Perl|Tcl)\"),\n        re_compile(\"(Python)\\\\1\"),\n        re_compile(\"(Python)\\\\1\"),\n        re_compile(\"([0a-z][a-z0-9]*,)+\"),\n        re_compile(\"(?:[0a-z][a-z0-9]*,)+\"),\n        re_compile(\"([a-z][a-z0-9]*,)+\"),\n        re_compile(\"(?:[a-z][a-z0-9]*,)+\"),\n        re_compile(\".*P.*y.*t.*h.*o.*n.*\"),\n    ]\n\n\ndef gen_string_table(n):\n    \"\"\"Generates the list of strings that will be used in the benchmarks.\n\n    All strings have repeated prefixes and suffices, and n specifies the\n    number of repetitions.\n    \"\"\"\n    strings = []\n\n    def append(s):\n        if USE_BYTES:\n            strings.append(s.encode(\"latin1\"))\n        else:\n            strings.append(s)\n\n    append(\"-\" * n + \"Perl\" + \"-\" * n)\n    append(\"P\" * n + \"Perl\" + \"P\" * n)\n    append(\"-\" * n + \"Perl\" + \"-\" * n)\n    append(\"-\" * n + \"Perl\" + \"-\" * n)\n    append(\"-\" * n + \"Python\" + \"-\" * n)\n    append(\"P\" * n + \"Python\" + \"P\" * n)\n    append(\"-\" * n + \"Python\" + \"-\" * n)\n    append(\"-\" * n + \"Python\" + \"-\" * n)\n    append(\"-\" * n + \"Python\" + \"-\" * n)\n    append(\"-\" * n + \"Python\" + \"-\" * n)\n    append(\"-\" * n + \"Perl\" + \"-\" * n)\n    append(\"P\" * n + \"Perl\" + \"P\" * n)\n    append(\"-\" * n + \"Perl\" + \"-\" * n)\n    append(\"-\" * n + \"Perl\" + \"-\" * n)\n    append(\"-\" * n + \"PythonPython\" + \"-\" * n)\n    append(\"P\" * n + \"PythonPython\" + \"P\" * n)\n    append(\"-\" * n + \"a5,b7,c9,\" + \"-\" * n)\n    append(\"-\" * n + \"a5,b7,c9,\" + \"-\" * n)\n    append(\"-\" * n + \"a5,b7,c9,\" + \"-\" * n)\n    append(\"-\" * n + \"a5,b7,c9,\" + \"-\" * n)\n    append(\"-\" * n + \"Python\" + \"-\" * n)\n    return strings\n\n\ndef init_benchmarks(n_values=None):\n    \"\"\"Initialize the strings we'll run the regexes against.\n\n    The strings used in the benchmark are prefixed and suffixed by\n    strings that are repeated n times.\n\n    The sequence n_values contains the values for n.\n    If n_values is None the values of n from the original benchmark\n    are used.\n\n    The generated list of strings is cached in the string_tables\n    variable, which is indexed by n.\n\n    Returns:\n    A list of string prefix/suffix lengths.\n    \"\"\"\n\n    if n_values is None:\n        n_values = (0, 5, 50, 250, 1000, 5000, 10000)\n\n    string_tables = {n: gen_string_table(n) for n in n_values}\n    regexs = gen_regex_table()\n\n    data = []\n    for n in n_values:\n        for id in range(len(regexs)):\n            regex = regexs[id]\n            string = string_tables[n][id]\n            data.append((regex, string))\n    return data\n\n\ndef bench_regex_effbot(loops):\n    if bench_regex_effbot.data is None:\n        bench_regex_effbot.data = init_benchmarks()\n    data = bench_regex_effbot.data\n\n    range_it = range(loops)\n    search = re.search\n\n    with get_tracker():\n        t0 = pyperf.perf_counter()\n        for _ in range_it:\n            # Runs all of the benchmarks for a given value of n.\n            for regex, string in data:\n                # search 10 times\n                search(regex, string)\n                search(regex, string)\n                search(regex, string)\n                search(regex, string)\n                search(regex, string)\n                search(regex, string)\n                search(regex, string)\n                search(regex, string)\n                search(regex, string)\n                search(regex, string)\n\n        return pyperf.perf_counter() - t0\n\n\n# cached data, generated at the first call\nbench_regex_effbot.data = None\n\n\ndef add_cmdline_args(cmd, args):\n    if args.force_bytes:\n        cmd.append(\"--force_bytes\")\n\n\nif __name__ == \"__main__\":\n    runner = pyperf.Runner(add_cmdline_args=add_cmdline_args)\n    runner.metadata[\"description\"] = (\n        \"Test the performance of regexps \" \"using Fredik Lundh's benchmarks.\"\n    )\n    runner.argparser.add_argument(\n        \"-B\", \"--force_bytes\", action=\"store_true\", help=\"test bytes regexps\"\n    )\n    options = runner.parse_args()\n    if options.force_bytes:\n        USE_BYTES = True\n\n    runner.bench_time_func(\"regex_effbot\", bench_regex_effbot, inner_loops=10)\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/regex_v8_base.py",
    "content": "# Copyright 2009 the V8 project authors. All rights reserved.\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions are\n# met:\n#\n#     * Redistributions of source code must retain the above copyright\n#       notice, this list of conditions and the following disclaimer.\n#     * Redistributions in binary form must reproduce the above\n#       copyright notice, this list of conditions and the following\n#       disclaimer in the documentation and/or other materials provided\n#       with the distribution.\n#     * Neither the name of Google Inc. nor the names of its\n#       contributors may be used to endorse or promote products derived\n#       from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n# \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n# Automatically generated on 2009-01-30.\n\n# This benchmark is generated by loading 50 of the most popular pages\n# on the web and logging all regexp operations performed.  Each\n# operation is given a weight that is calculated from an estimate of\n# the popularity of the pages where it occurs and the number of times\n# it is executed while loading each page.  Finally the literal\n# letters in the data are encoded using ROT13 in a way that does not\n# affect how the regexps match their input.\n\n\n# Ported to Python for Unladen Swallow. The original JS version can be found at\n# https://github.com/v8/v8/blob/master/benchmarks/regexp.js, r1243.\n\n# Python imports\nimport re\n\n# Third party imports\n\n# The precompiled regexs that were in vars in the V8 code, split into\n# tuples of (regex, flags).\ncompiled_regex_strings = [\n    (r\"^ba\", \"\"),\n    (r\"(((\\w+):\\/\\/)([^\\/:]*)(:(\\d+))?)?([^#?]*)(\\?([^#]*))?(#(.*))?\", \"\"),\n    (r\"^\\s*|\\s*$\", \"g\"),\n    (r\"\\bQBZPbageby_cynprubyqre\\b\", \"\"),\n    (r\",\", \"\"),\n    (r\"\\bQBZPbageby_cynprubyqre\\b\", \"g\"),\n    (r\"^[\\s\\xa0]+|[\\s\\xa0]+$\", \"g\"),\n    (r\"(\\d*)(\\D*)\", \"g\"),\n    (r\"=\", \"\"),\n    (r\"(^|\\s)lhv\\-h(\\s|$)\", \"\"),\n    (r\"\\#\", \"g\"),\n    (r\"\\.\", \"g\"),\n    (r\"\\'\", \"g\"),\n    (r\"\\?[\\w\\W]*(sevraqvq|punaaryvq|tebhcvq)=([^\\&\\?#]*)\", \"i\"),\n    (r\"\\s+\", \"g\"),\n    (r\"^\\s*(\\S*(\\s+\\S+)*)\\s*$\", \"\"),\n    (r\"(-[a-z])\", \"i\"),\n    (r\"(^|[^\\\\])\\\"\\\\\\/Qngr\\((-?[0-9]+)\\)\\\\\\/\\\"\", \"g\"),\n    (r\"^\\s+|\\s+$\", \"g\"),\n    (r\"(?:^|\\s+)ba(?:\\s+|$)\", \"\"),\n    (r\"[+, ]\", \"\"),\n    (r\"ybnqrq|pbzcyrgr\", \"\"),\n    (r\"\\bso_zrah\\b\", \"\"),\n    (r\"^(?:(?:[^:\\/?#]+):)?(?:\\/\\/(?:[^\\/?#]*))?([^?#]*)(?:\\?([^#]*))?(?:#(.*))?\", \"\"),\n    (r\"uggcf?:\\/\\/([^\\/]+\\.)?snprobbx\\.pbz\\/\", \"\"),\n    (r'\"', \"g\"),\n    (r\"^([^?#]+)(?:\\?([^#]*))?(#.*)?\", \"\"),\n    (r\"-\\D\", \"g\"),\n    (r\"\\bnpgvingr\\b\", \"\"),\n    (r\"%2R\", \"gi\"),\n    (r\"%2S\", \"gi\"),\n    (r\"^(mu-(PA|GJ)|wn|xb)$\", \"\"),\n    (r\"\\s?;\\s?\", \"\"),\n    (r\"%\\w?$\", \"\"),\n    (r\"TNQP=([^;]*)\", \"i\"),\n    (r\"[<>]\", \"g\"),\n    (r\"uers|fep|fryrpgrq\", \"\"),\n    (r\"\\s*([+>~\\s])\\s*([a-zA-Z#.*:\\[])\", \"g\"),\n    (r\"^(\\w+|\\*)$\", \"\"),\n    (r\"\\\\\\\\\", \"g\"),\n    (r\" \", \"g\"),\n    (r\"\\/\\xc4\\/t\", \"\"),\n    (r\"\\/\\xd6\\/t\", \"\"),\n    (r\"\\/\\xdc\\/t\", \"\"),\n    (r\"\\/\\xdf\\/t\", \"\"),\n    (r\"\\/\\xe4\\/t\", \"\"),\n    (r\"\\/\\xf6\\/t\", \"\"),\n    (r\"\\/\\xfc\\/t\", \"\"),\n    (r\"\\W\", \"g\"),\n    (r\"uers|fep|fglyr\", \"\"),\n    (r\"(?:^|\\s+)fryrpgrq(?:\\s+|$)\", \"\"),\n    (r\"\\&\", \"g\"),\n    (r\"\\+\", \"g\"),\n    (r\"\\?\", \"g\"),\n    (r\"\\t\", \"g\"),\n    (r\"(\\$\\{nqiHey\\})|(\\$nqiHey\\b)\", \"g\"),\n    (r\"(\\$\\{cngu\\})|(\\$cngu\\b)\", \"g\"),\n    (r\"##yv4##\", \"gi\"),\n    (r\"##yv16##\", \"gi\"),\n    (r\"##yv19##\", \"gi\"),\n    (r\"(?:^|\\s+)bss(?:\\s+|$)\", \"\"),\n    (r\"^(([^:\\/?#]+):)?(\\/\\/([^\\/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?$\", \"\"),\n    (r\"^[^<]*(<(.|\\s)+>)[^>]*$|^#(\\w+)$\", \"\"),\n    (r\"\\{0\\}\", \"g\"),\n    (r\"\\b[a-z]\", \"g\"),\n    (r\"^uggc:\\/\\/\", \"\"),\n    (r\"(?:^|\\s+)qvfnoyrq(?:\\s+|$)\", \"\"),\n    (r\"zrah_byq\", \"g\"),\n    (r\"^([#.]?)((?:[\\w\" + \"\\u0128-\\uffff\" + r\"*_-]|\\\\.)*)\", \"\"),\n    (r\"\\{1\\}\", \"g\"),\n    (r\"\\s+\", \"\"),\n    (r\"(\\$\\{4\\})|(\\$4\\b)\", \"g\"),\n    (r\"(\\$\\{5\\})|(\\$5\\b)\", \"g\"),\n    (r\"\\{2\\}\", \"g\"),\n    (r\"[^+>] [^+>]\", \"\"),\n    (r\"\\bucpyv\\s*=\\s*([^;]*)\", \"i\"),\n    (r\"\\bucuvqr\\s*=\\s*([^;]*)\", \"i\"),\n    (r\"\\bucfie\\s*=\\s*([^;]*)\", \"i\"),\n    (r\"\\bhfucjrn\\s*=\\s*([^;]*)\", \"i\"),\n    (r\"\\bmvc\\s*=\\s*([^;]*)\", \"i\"),\n    (\n        r\"^((?:[\\w\"\n        + \"\\u0128-\\uffff\"\n        + r\"*_-]|\\\\.)+)(#)((?:[\\w\"\n        + \"\\u0128-\\uffff\"\n        + r\"*_-]|\\\\.)+)\",\n        \"\",\n    ),\n    (r\"^([>+~])\\s*(\\w*)\", \"i\"),\n    (r\"^>\\s*((?:[\\w\" + \"\\u0128-\\uffff\" + r\"*_-]|\\\\.)+)\", \"\"),\n    (r\"^[\\s[]?shapgvba\", \"\"),\n    (r\"v\\/g.tvs#(.*)\", \"i\"),\n    (r\"eaq_zbqobkva\", \"\"),\n    (r\";\\s*\", \"\"),\n    (r\"(\\$\\{inyhr\\})|(\\$inyhr\\b)\", \"g\"),\n    (r\"(\\$\\{abj\\})|(\\$abj\\b)\", \"g\"),\n    (r\"\\s+$\", \"\"),\n    (r\"^\\s+\", \"\"),\n    (\n        r\"(\\\\\\\"|\\x00-|\\x1f|\\x7f-|\\x9f|\"\n        + \"\\u00ad|\\u0600-|\\u0604|\\u070f|\\u17b4|\\u17b5|\\u200c-|\\u200f|\\u2028-|\\u202f|\\u2060-|\\u206f|\\ufeff|\\ufff0-|\\uffff\"\n        + r\")\",\n        \"g\",\n    ),\n    (r'^(:)([\\w-]+)\\(\"?\\'?(.*?(\\(.*?\\))?[^(]*?)\"?\\'?\\)', \"\"),\n    (r\"^([:.#]*)((?:[\\w\" + \"\\u0128-\\uffff\" + r\"*_-]|\\\\.)+)\", \"\"),\n    (r'^(\\[) *@?([\\w-]+) *([!*$^~=]*) *(\\'?\"?)(.*?)\\4 *\\]', \"\"),\n]\n\n\n# The V8 javascript engine only does one replacement unless the regexp has\n# the 'g' flag. Python's sub has count = 1 to do 1 replacement and count = 0\n# to replace all matches. We set this up here.\n\nregexs = []\nsubcount = []\n\nfor s in compiled_regex_strings:\n    if \"g\" in s[1]:\n        subcount.append(0)\n    else:\n        subcount.append(1)\n\n    if \"i\" in s[1]:\n        regexs.append(re.compile(s[0], re.IGNORECASE | re.UNICODE))\n    else:\n        regexs.append(re.compile(s[0], re.UNICODE))\n\n# The strings that were in vars in the V8 benchmark\n\nstrings = [\n    r\"Zbmvyyn/5.0 (Jvaqbjf; H; Jvaqbjf AG 5.1; ra-HF) NccyrJroXvg/528.9 (XUGZY, yvxr Trpxb) Puebzr/2.0.157.0 Fnsnev/528.9\",\n    r\"Fubpxjnir Synfu 9.0  e115\",\n    r'{\"anzr\":\"\",\"ahzoreSbezng\":{\"PheeraplQrpvznyQvtvgf\":2,\"PheeraplQrpvznyFrcnengbe\":\".\",\"VfErnqBayl\":gehr,\"PheeraplTebhcFvmrf\":[3],\"AhzoreTebhcFvmrf\":[3],\"CrepragTebhcFvmrf\":[3],\"PheeraplTebhcFrcnengbe\":\",\",\"PheeraplFlzoby\":\"\\xa4\",\"AnAFlzoby\":\"AnA\",\"PheeraplArtngvirCnggrea\":0,\"AhzoreArtngvirCnggrea\":1,\"CrepragCbfvgvirCnggrea\":0,\"CrepragArtngvirCnggrea\":0,\"ArtngvirVasvavglFlzoby\":\"-Vasvavgl\",\"ArtngvirFvta\":\"-\",\"AhzoreQrpvznyQvtvgf\":2,\"AhzoreQrpvznyFrcnengbe\":\".\",\"AhzoreTebhcFrcnengbe\":\",\",\"PheeraplCbfvgvirCnggrea\":0,\"CbfvgvirVasvavglFlzoby\":\"Vasvavgl\",\"CbfvgvirFvta\":\"+\",\"CrepragQrpvznyQvtvgf\":2,\"CrepragQrpvznyFrcnengbe\":\".\",\"CrepragTebhcFrcnengbe\":\",\",\"CrepragFlzoby\":\"%\",\"CreZvyyrFlzoby\":\"\\u2030\",\"AngvirQvtvgf\":[\"0\",\"1\",\"2\",\"3\",\"4\",\"5\",\"6\",\"7\",\"8\",\"9\"],\"QvtvgFhofgvghgvba\":1},\"qngrGvzrSbezng\":{\"NZQrfvtangbe\":\"NZ\",\"Pnyraqne\":{\"ZvaFhccbegrqQngrGvzr\":\"@-62135568000000@\",\"ZnkFhccbegrqQngrGvzr\":\"@253402300799999@\",\"NytbevguzGlcr\":1,\"PnyraqneGlcr\":1,\"Renf\":[1],\"GjbQvtvgLrneZnk\":2029,\"VfErnqBayl\":gehr},\"QngrFrcnengbe\":\"/\",\"SvefgQnlBsJrrx\":0,\"PnyraqneJrrxEhyr\":0,\"ShyyQngrGvzrCnggrea\":\"qqqq, qq ZZZZ llll UU:zz:ff\",\"YbatQngrCnggrea\":\"qqqq, qq ZZZZ llll\",\"YbatGvzrCnggrea\":\"UU:zz:ff\",\"ZbaguQnlCnggrea\":\"ZZZZ qq\",\"CZQrfvtangbe\":\"CZ\",\"ESP1123Cnggrea\":\"qqq, qq ZZZ llll UU\\':\\'zz\\':\\'ff \\'TZG\\'\",\"FubegQngrCnggrea\":\"ZZ/qq/llll\",\"FubegGvzrCnggrea\":\"UU:zz\",\"FbegnoyrQngrGvzrCnggrea\":\"llll\\'-\\'ZZ\\'-\\'qq\\'G\\'UU\\':\\'zz\\':\\'ff\",\"GvzrFrcnengbe\":\":\",\"HavirefnyFbegnoyrQngrGvzrCnggrea\":\"llll\\'-\\'ZZ\\'-\\'qq UU\\':\\'zz\\':\\'ff\\'M\\'\",\"LrneZbaguCnggrea\":\"llll ZZZZ\",\"NooerivngrqQnlAnzrf\":[\"Fha\",\"Zba\",\"Ghr\",\"Jrq\",\"Guh\",\"Sev\",\"Fng\"],\"FubegrfgQnlAnzrf\":[\"Fh\",\"Zb\",\"Gh\",\"Jr\",\"Gu\",\"Se\",\"Fn\"],\"QnlAnzrf\":[\"Fhaqnl\",\"Zbaqnl\",\"Ghrfqnl\",\"Jrqarfqnl\",\"Guhefqnl\",\"Sevqnl\",\"Fngheqnl\"],\"NooerivngrqZbaguAnzrf\":[\"Wna\",\"Sro\",\"Zne\",\"Nce\",\"Znl\",\"Wha\",\"Why\",\"Nht\",\"Frc\",\"Bpg\",\"Abi\",\"Qrp\",\"\"],\"ZbaguAnzrf\":[\"Wnahnel\",\"Sroehnel\",\"Znepu\",\"Ncevy\",\"Znl\",\"Whar\",\"Whyl\",\"Nhthfg\",\"Frcgrzore\",\"Bpgbore\",\"Abirzore\",\"Qrprzore\",\"\"],\"VfErnqBayl\":gehr,\"AngvirPnyraqneAnzr\":\"Tertbevna Pnyraqne\",\"NooerivngrqZbaguTravgvirAnzrf\":[\"Wna\",\"Sro\",\"Zne\",\"Nce\",\"Znl\",\"Wha\",\"Why\",\"Nht\",\"Frc\",\"Bpg\",\"Abi\",\"Qrp\",\"\"],\"ZbaguTravgvirAnzrf\":[\"Wnahnel\",\"Sroehnel\",\"Znepu\",\"Ncevy\",\"Znl\",\"Whar\",\"Whyl\",\"Nhthfg\",\"Frcgrzore\",\"Bpgbore\",\"Abirzore\",\"Qrprzore\",\"\"]}}',\n    r'{\"anzr\":\"ra-HF\",\"ahzoreSbezng\":{\"PheeraplQrpvznyQvtvgf\":2,\"PheeraplQrpvznyFrcnengbe\":\".\",\"VfErnqBayl\":snyfr,\"PheeraplTebhcFvmrf\":[3],\"AhzoreTebhcFvmrf\":[3],\"CrepragTebhcFvmrf\":[3],\"PheeraplTebhcFrcnengbe\":\",\",\"PheeraplFlzoby\":\"$\",\"AnAFlzoby\":\"AnA\",\"PheeraplArtngvirCnggrea\":0,\"AhzoreArtngvirCnggrea\":1,\"CrepragCbfvgvirCnggrea\":0,\"CrepragArtngvirCnggrea\":0,\"ArtngvirVasvavglFlzoby\":\"-Vasvavgl\",\"ArtngvirFvta\":\"-\",\"AhzoreQrpvznyQvtvgf\":2,\"AhzoreQrpvznyFrcnengbe\":\".\",\"AhzoreTebhcFrcnengbe\":\",\",\"PheeraplCbfvgvirCnggrea\":0,\"CbfvgvirVasvavglFlzoby\":\"Vasvavgl\",\"CbfvgvirFvta\":\"+\",\"CrepragQrpvznyQvtvgf\":2,\"CrepragQrpvznyFrcnengbe\":\".\",\"CrepragTebhcFrcnengbe\":\",\",\"CrepragFlzoby\":\"%\",\"CreZvyyrFlzoby\":\"\\u2030\",\"AngvirQvtvgf\":[\"0\",\"1\",\"2\",\"3\",\"4\",\"5\",\"6\",\"7\",\"8\",\"9\"],\"QvtvgFhofgvghgvba\":1},\"qngrGvzrSbezng\":{\"NZQrfvtangbe\":\"NZ\",\"Pnyraqne\":{\"ZvaFhccbegrqQngrGvzr\":\"@-62135568000000@\",\"ZnkFhccbegrqQngrGvzr\":\"@253402300799999@\",\"NytbevguzGlcr\":1,\"PnyraqneGlcr\":1,\"Renf\":[1],\"GjbQvtvgLrneZnk\":2029,\"VfErnqBayl\":snyfr},\"QngrFrcnengbe\":\"/\",\"SvefgQnlBsJrrx\":0,\"PnyraqneJrrxEhyr\":0,\"ShyyQngrGvzrCnggrea\":\"qqqq, ZZZZ qq, llll u:zz:ff gg\",\"YbatQngrCnggrea\":\"qqqq, ZZZZ qq, llll\",\"YbatGvzrCnggrea\":\"u:zz:ff gg\",\"ZbaguQnlCnggrea\":\"ZZZZ qq\",\"CZQrfvtangbe\":\"CZ\",\"ESP1123Cnggrea\":\"qqq, qq ZZZ llll UU\\':\\'zz\\':\\'ff \\'TZG\\'\",\"FubegQngrCnggrea\":\"Z/q/llll\",\"FubegGvzrCnggrea\":\"u:zz gg\",\"FbegnoyrQngrGvzrCnggrea\":\"llll\\'-\\'ZZ\\'-\\'qq\\'G\\'UU\\':\\'zz\\':\\'ff\",\"GvzrFrcnengbe\":\":\",\"HavirefnyFbegnoyrQngrGvzrCnggrea\":\"llll\\'-\\'ZZ\\'-\\'qq UU\\':\\'zz\\':\\'ff\\'M\\'\",\"LrneZbaguCnggrea\":\"ZZZZ, llll\",\"NooerivngrqQnlAnzrf\":[\"Fha\",\"Zba\",\"Ghr\",\"Jrq\",\"Guh\",\"Sev\",\"Fng\"],\"FubegrfgQnlAnzrf\":[\"Fh\",\"Zb\",\"Gh\",\"Jr\",\"Gu\",\"Se\",\"Fn\"],\"QnlAnzrf\":[\"Fhaqnl\",\"Zbaqnl\",\"Ghrfqnl\",\"Jrqarfqnl\",\"Guhefqnl\",\"Sevqnl\",\"Fngheqnl\"],\"NooerivngrqZbaguAnzrf\":[\"Wna\",\"Sro\",\"Zne\",\"Nce\",\"Znl\",\"Wha\",\"Why\",\"Nht\",\"Frc\",\"Bpg\",\"Abi\",\"Qrp\",\"\"],\"ZbaguAnzrf\":[\"Wnahnel\",\"Sroehnel\",\"Znepu\",\"Ncevy\",\"Znl\",\"Whar\",\"Whyl\",\"Nhthfg\",\"Frcgrzore\",\"Bpgbore\",\"Abirzore\",\"Qrprzore\",\"\"],\"VfErnqBayl\":snyfr,\"AngvirPnyraqneAnzr\":\"Tertbevna Pnyraqne\",\"NooerivngrqZbaguTravgvirAnzrf\":[\"Wna\",\"Sro\",\"Zne\",\"Nce\",\"Znl\",\"Wha\",\"Why\",\"Nht\",\"Frc\",\"Bpg\",\"Abi\",\"Qrp\",\"\"],\"ZbaguTravgvirAnzrf\":[\"Wnahnel\",\"Sroehnel\",\"Znepu\",\"Ncevy\",\"Znl\",\"Whar\",\"Whyl\",\"Nhthfg\",\"Frcgrzore\",\"Bpgbore\",\"Abirzore\",\"Qrprzore\",\"\"]}}',\n    r\"HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q\",\n    r\"HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=\",\n    r\"uggc://jjj.snprobbx.pbz/vaqrk.cuc\",\n    r';;jvaqbj.IjPurpxZbhfrCbfvgvbaNQ_VQ=shapgvba(r){vs(!r)ine r=jvaqbj.rirag;ine c=-1;vs(d1)c=d1.EbyybssCnary;ine bo=IjTrgBow(\"IjCnayNQ_VQ_\"+c);vs(bo&&bo.fglyr.ivfvovyvgl==\"ivfvoyr\"){ine fns=IjFns?8:0;ine pheK=r.pyvragK+IjBOFpe(\"U\")+fns,pheL=r.pyvragL+IjBOFpe(\"I\")+fns;ine y=IjBOEC(NQ_VQ,bo,\"Y\"),g=IjBOEC(NQ_VQ,bo,\"G\");ine e=y+d1.Cnaryf[c].Jvqgu,o=g+d1.Cnaryf[c].Urvtug;vs((pheK<y)||(pheK>e)||(pheL<g)||(pheL>o)){vs(jvaqbj.IjBaEbyybssNQ_VQ)IjBaEbyybssNQ_VQ(c);ryfr IjPybfrNq(NQ_VQ,c,gehr,\"\");}ryfr erghea;}IjPnapryZbhfrYvfgrareNQ_VQ();};;jvaqbj.IjFrgEbyybssCnaryNQ_VQ=shapgvba(c){ine z=\"zbhfrzbir\",q=qbphzrag,s=IjPurpxZbhfrCbfvgvbaNQ_VQ;c=IjTc(NQ_VQ,c);vs(d1&&d1.EbyybssCnary>-1)IjPnapryZbhfrYvfgrareNQ_VQ();vs(d1)d1.EbyybssCnary=c;gel{vs(q.nqqRiragYvfgrare)q.nqqRiragYvfgrare(z,s,snyfr);ryfr vs(q.nggnpuRirag)q.nggnpuRirag(\"ba\"+z,s);}pngpu(r){}};;jvaqbj.IjPnapryZbhfrYvfgrareNQ_VQ=shapgvba(){ine z=\"zbhfrzbir\",q=qbphzrag,s=IjPurpxZbhfrCbfvgvbaNQ_VQ;vs(d1)d1.EbyybssCnary=-1;gel{vs(q.erzbirRiragYvfgrare)q.erzbirRiragYvfgrare(z,s,snyfr);ryfr vs(q.qrgnpuRirag)q.qrgnpuRirag(\"ba\"+z,s);}pngpu(r){}};;d1.IjTc=d2(n,c){ine nq=d1;vs(vfAnA(c)){sbe(ine v=0;v<nq.Cnaryf.yratgu;v++)vs(nq.Cnaryf[v].Anzr==c)erghea v;erghea 0;}erghea c;};;d1.IjTpy=d2(n,c,p){ine cn=d1.Cnaryf[IjTc(n,c)];vs(!cn)erghea 0;vs(vfAnA(p)){sbe(ine v=0;v<cn.Pyvpxguehf.yratgu;v++)vs(cn.Pyvpxguehf[v].Anzr==p)erghea v;erghea 0;}erghea p;};;d1.IjGenpr=d2(n,f){gel{vs(jvaqbj[\"Ij\"+\"QtQ\"])jvaqbj[\"Ij\"+\"QtQ\"](n,1,f);}pngpu(r){}};;d1.IjYvzvg1=d2(n,f){ine nq=d1,vh=f.fcyvg(\"/\");sbe(ine v=0,p=0;v<vh.yratgu;v++){vs(vh[v].yratgu>0){vs(nq.FzV.yratgu>0)nq.FzV+=\"/\";nq.FzV+=vh[v];nq.FtZ[nq.FtZ.yratgu]=snyfr;}}};;d1.IjYvzvg0=d2(n,f){ine nq=d1,vh=f.fcyvg(\"/\");sbe(ine v=0;v<vh.yratgu;v++){vs(vh[v].yratgu>0){vs(nq.OvC.yratgu>0)nq.OvC+=\"/\";nq.OvC+=vh[v];}}};;d1.IjRVST=d2(n,c){jvaqbj[\"IjCnayNQ_VQ_\"+c+\"_Bow\"]=IjTrgBow(\"IjCnayNQ_VQ_\"+c+\"_Bow\");vs(jvaqbj[\"IjCnayNQ_VQ_\"+c+\"_Bow\"]==ahyy)frgGvzrbhg(\"IjRVST(NQ_VQ,\"+c+\")\",d1.rvsg);};;d1.IjNavzSHC=d2(n,c){ine nq=d1;vs(c>nq.Cnaryf.yratgu)erghea;ine cna=nq.Cnaryf[c],nn=gehr,on=gehr,yn=gehr,en=gehr,cn=nq.Cnaryf[0],sf=nq.ShF,j=cn.Jvqgu,u=cn.Urvtug;vs(j==\"100%\"){j=sf;en=snyfr;yn=snyfr;}vs(u==\"100%\"){u=sf;nn=snyfr;on=snyfr;}vs(cn.YnY==\"Y\")yn=snyfr;vs(cn.YnY==\"E\")en=snyfr;vs(cn.GnY==\"G\")nn=snyfr;vs(cn.GnY==\"O\")on=snyfr;ine k=0,l=0;fjvgpu(nq.NshP%8){pnfr 0:oernx;pnfr 1:vs(nn)l=-sf;oernx;pnfr 2:k=j-sf;oernx;pnfr 3:vs(en)k=j;oernx;pnfr 4:k=j-sf;l=u-sf;oernx;pnfr 5:k=j-sf;vs(on)l=u;oernx;pnfr 6:l=u-sf;oernx;pnfr 7:vs(yn)k=-sf;l=u-sf;oernx;}vs(nq.NshP++ <nq.NshG)frgGvzrbhg((\"IjNavzSHC(NQ_VQ,\"+c+\")\"),nq.NshC);ryfr{k=-1000;l=k;}cna.YrsgBssfrg=k;cna.GbcBssfrg=l;IjNhErcb(n,c);};;d1.IjTrgErnyCbfvgvba=d2(n,b,j){erghea IjBOEC.nccyl(guvf,nethzragf);};;d1.IjPnapryGvzrbhg=d2(n,c){c=IjTc(n,c);ine cay=d1.Cnaryf[c];vs(cay&&cay.UgU!=\"\"){pyrneGvzrbhg(cay.UgU);}};;d1.IjPnapryNyyGvzrbhgf=d2(n){vs(d1.YbpxGvzrbhgPunatrf)erghea;sbe(ine c=0;c<d1.bac;c++)IjPnapryGvzrbhg(n,c);};;d1.IjFgnegGvzrbhg=d2(n,c,bG){c=IjTc(n,c);ine cay=d1.Cnaryf[c];vs(cay&&((cay.UvqrGvzrbhgInyhr>0)||(nethzragf.yratgu==3&&bG>0))){pyrneGvzrbhg(cay.UgU);cay.UgU=frgGvzrbhg(cay.UvqrNpgvba,(nethzragf.yratgu==3?bG:cay.UvqrGvzrbhgInyhr));}};;d1.IjErfrgGvzrbhg=d2(n,c,bG){c=IjTc(n,c);IjPnapryGvzrbhg(n,c);riny(\"IjFgnegGvzrbhg(NQ_VQ,c\"+(nethzragf.yratgu==3?\",bG\":\"\")+\")\");};;d1.IjErfrgNyyGvzrbhgf=d2(n){sbe(ine c=0;c<d1.bac;c++)IjErfrgGvzrbhg(n,c);};;d1.IjQrgnpure=d2(n,rig,sap){gel{vs(IjQVR5)riny(\"jvaqbj.qrgnpuRirag(\\'ba\"+rig+\"\\',\"+sap+\"NQ_VQ)\");ryfr vs(!IjQVRZnp)riny(\"jvaqbj.erzbirRiragYvfgrare(\\'\"+rig+\"\\',\"+sap+\"NQ_VQ,snyfr)\");}pngpu(r){}};;d1.IjPyrnaHc=d2(n){IjCvat(n,\"G\");ine nq=d1;sbe(ine v=0;v<nq.Cnaryf.yratgu;v++){IjUvqrCnary(n,v,gehr);}gel{IjTrgBow(nq.gya).vaareUGZY=\"\";}pngpu(r){}vs(nq.gya!=nq.gya2)gel{IjTrgBow(nq.gya2).vaareUGZY=\"\";}pngpu(r){}gel{d1=ahyy;}pngpu(r){}gel{IjQrgnpure(n,\"haybnq\",\"IjHayNQ_VQ\");}pngpu(r){}gel{jvaqbj.IjHayNQ_VQ=ahyy;}pngpu(r){}gel{IjQrgnpure(n,\"fpebyy\",\"IjFeNQ_VQ\");}pngpu(r){}gel{jvaqbj.IjFeNQ_VQ=ahyy;}pngpu(r){}gel{IjQrgnpure(n,\"erfvmr\",\"IjEmNQ_VQ\");}pngpu(r){}gel{jvaqbj.IjEmNQ_VQ=ahyy;}pngpu(r){}gel{IjQrgnpure(n',\n    r';;jvaqbj.IjPurpxZbhfrCbfvgvbaNQ_VQ=shapgvba(r){vs(!r)ine r=jvaqbj.rirag;ine c=-1;vs(jvaqbj.IjNqNQ_VQ)c=jvaqbj.IjNqNQ_VQ.EbyybssCnary;ine bo=IjTrgBow(\"IjCnayNQ_VQ_\"+c);vs(bo&&bo.fglyr.ivfvovyvgl==\"ivfvoyr\"){ine fns=IjFns?8:0;ine pheK=r.pyvragK+IjBOFpe(\"U\")+fns,pheL=r.pyvragL+IjBOFpe(\"I\")+fns;ine y=IjBOEC(NQ_VQ,bo,\"Y\"),g=IjBOEC(NQ_VQ,bo,\"G\");ine e=y+jvaqbj.IjNqNQ_VQ.Cnaryf[c].Jvqgu,o=g+jvaqbj.IjNqNQ_VQ.Cnaryf[c].Urvtug;vs((pheK<y)||(pheK>e)||(pheL<g)||(pheL>o)){vs(jvaqbj.IjBaEbyybssNQ_VQ)IjBaEbyybssNQ_VQ(c);ryfr IjPybfrNq(NQ_VQ,c,gehr,\"\");}ryfr erghea;}IjPnapryZbhfrYvfgrareNQ_VQ();};;jvaqbj.IjFrgEbyybssCnaryNQ_VQ=shapgvba(c){ine z=\"zbhfrzbir\",q=qbphzrag,s=IjPurpxZbhfrCbfvgvbaNQ_VQ;c=IjTc(NQ_VQ,c);vs(jvaqbj.IjNqNQ_VQ&&jvaqbj.IjNqNQ_VQ.EbyybssCnary>-1)IjPnapryZbhfrYvfgrareNQ_VQ();vs(jvaqbj.IjNqNQ_VQ)jvaqbj.IjNqNQ_VQ.EbyybssCnary=c;gel{vs(q.nqqRiragYvfgrare)q.nqqRiragYvfgrare(z,s,snyfr);ryfr vs(q.nggnpuRirag)q.nggnpuRirag(\"ba\"+z,s);}pngpu(r){}};;jvaqbj.IjPnapryZbhfrYvfgrareNQ_VQ=shapgvba(){ine z=\"zbhfrzbir\",q=qbphzrag,s=IjPurpxZbhfrCbfvgvbaNQ_VQ;vs(jvaqbj.IjNqNQ_VQ)jvaqbj.IjNqNQ_VQ.EbyybssCnary=-1;gel{vs(q.erzbirRiragYvfgrare)q.erzbirRiragYvfgrare(z,s,snyfr);ryfr vs(q.qrgnpuRirag)q.qrgnpuRirag(\"ba\"+z,s);}pngpu(r){}};;jvaqbj.IjNqNQ_VQ.IjTc=shapgvba(n,c){ine nq=jvaqbj.IjNqNQ_VQ;vs(vfAnA(c)){sbe(ine v=0;v<nq.Cnaryf.yratgu;v++)vs(nq.Cnaryf[v].Anzr==c)erghea v;erghea 0;}erghea c;};;jvaqbj.IjNqNQ_VQ.IjTpy=shapgvba(n,c,p){ine cn=jvaqbj.IjNqNQ_VQ.Cnaryf[IjTc(n,c)];vs(!cn)erghea 0;vs(vfAnA(p)){sbe(ine v=0;v<cn.Pyvpxguehf.yratgu;v++)vs(cn.Pyvpxguehf[v].Anzr==p)erghea v;erghea 0;}erghea p;};;jvaqbj.IjNqNQ_VQ.IjGenpr=shapgvba(n,f){gel{vs(jvaqbj[\"Ij\"+\"QtQ\"])jvaqbj[\"Ij\"+\"QtQ\"](n,1,f);}pngpu(r){}};;jvaqbj.IjNqNQ_VQ.IjYvzvg1=shapgvba(n,f){ine nq=jvaqbj.IjNqNQ_VQ,vh=f.fcyvg(\"/\");sbe(ine v=0,p=0;v<vh.yratgu;v++){vs(vh[v].yratgu>0){vs(nq.FzV.yratgu>0)nq.FzV+=\"/\";nq.FzV+=vh[v];nq.FtZ[nq.FtZ.yratgu]=snyfr;}}};;jvaqbj.IjNqNQ_VQ.IjYvzvg0=shapgvba(n,f){ine nq=jvaqbj.IjNqNQ_VQ,vh=f.fcyvg(\"/\");sbe(ine v=0;v<vh.yratgu;v++){vs(vh[v].yratgu>0){vs(nq.OvC.yratgu>0)nq.OvC+=\"/\";nq.OvC+=vh[v];}}};;jvaqbj.IjNqNQ_VQ.IjRVST=shapgvba(n,c){jvaqbj[\"IjCnayNQ_VQ_\"+c+\"_Bow\"]=IjTrgBow(\"IjCnayNQ_VQ_\"+c+\"_Bow\");vs(jvaqbj[\"IjCnayNQ_VQ_\"+c+\"_Bow\"]==ahyy)frgGvzrbhg(\"IjRVST(NQ_VQ,\"+c+\")\",jvaqbj.IjNqNQ_VQ.rvsg);};;jvaqbj.IjNqNQ_VQ.IjNavzSHC=shapgvba(n,c){ine nq=jvaqbj.IjNqNQ_VQ;vs(c>nq.Cnaryf.yratgu)erghea;ine cna=nq.Cnaryf[c],nn=gehr,on=gehr,yn=gehr,en=gehr,cn=nq.Cnaryf[0],sf=nq.ShF,j=cn.Jvqgu,u=cn.Urvtug;vs(j==\"100%\"){j=sf;en=snyfr;yn=snyfr;}vs(u==\"100%\"){u=sf;nn=snyfr;on=snyfr;}vs(cn.YnY==\"Y\")yn=snyfr;vs(cn.YnY==\"E\")en=snyfr;vs(cn.GnY==\"G\")nn=snyfr;vs(cn.GnY==\"O\")on=snyfr;ine k=0,l=0;fjvgpu(nq.NshP%8){pnfr 0:oernx;pnfr 1:vs(nn)l=-sf;oernx;pnfr 2:k=j-sf;oernx;pnfr 3:vs(en)k=j;oernx;pnfr 4:k=j-sf;l=u-sf;oernx;pnfr 5:k=j-sf;vs(on)l=u;oernx;pnfr 6:l=u-sf;oernx;pnfr 7:vs(yn)k=-sf;l=u-sf;oernx;}vs(nq.NshP++ <nq.NshG)frgGvzrbhg((\"IjNavzSHC(NQ_VQ,\"+c+\")\"),nq.NshC);ryfr{k=-1000;l=k;}cna.YrsgBssfrg=k;cna.GbcBssfrg=l;IjNhErcb(n,c);};;jvaqbj.IjNqNQ_VQ.IjTrgErnyCbfvgvba=shapgvba(n,b,j){erghea IjBOEC.nccyl(guvf,nethzragf);};;jvaqbj.IjNqNQ_VQ.IjPnapryGvzrbhg=shapgvba(n,c){c=IjTc(n,c);ine cay=jvaqbj.IjNqNQ_VQ.Cnaryf[c];vs(cay&&cay.UgU!=\"\"){pyrneGvzrbhg(cay.UgU);}};;jvaqbj.IjNqNQ_VQ.IjPnapryNyyGvzrbhgf=shapgvba(n){vs(jvaqbj.IjNqNQ_VQ.YbpxGvzrbhgPunatrf)erghea;sbe(ine c=0;c<jvaqbj.IjNqNQ_VQ.bac;c++)IjPnapryGvzrbhg(n,c);};;jvaqbj.IjNqNQ_VQ.IjFgnegGvzrbhg=shapgvba(n,c,bG){c=IjTc(n,c);ine cay=jvaqbj.IjNqNQ_VQ.Cnaryf[c];vs(cay&&((cay.UvqrGvzrbhgInyhr>0)||(nethzragf.yratgu==3&&bG>0))){pyrneGvzrbhg(cay.UgU);cay.UgU=frgGvzrbhg(cay.UvqrNpgvba,(nethzragf.yratgu==3?bG:cay.UvqrGvzrbhgInyhr));}};;jvaqbj.IjNqNQ_VQ.IjErfrgGvzrbhg=shapgvba(n,c,bG){c=IjTc(n,c);IjPnapryGvzrbhg(n,c);riny(\"IjFgnegGvzrbhg(NQ_VQ,c\"+(nethzragf.yratgu==3?\",bG\":\"\")+\")\");};;jvaqbj.IjNqNQ_VQ.IjErfrgNyyGvzrbhgf=shapgvba(n){sbe(ine c=0;c<jvaqbj.IjNqNQ_VQ.bac;c++)IjErfrgGvzrbhg(n,c);};;jvaqbj.IjNqNQ_VQ.IjQrgnpure=shapgvba(n,rig,sap){gel{vs(IjQVR5)riny(\"jvaqbj.qrgnpuRirag(\\'ba\"+rig+\"\\',\"+sap+\"NQ_VQ)\");ryfr vs(!IjQVRZnp)riny(\"jvaqbj.erzbir',\n    r';;jvaqbj.IjPurpxZbhfrCbfvgvbaNQ_VQ=shapgvba(r){vs(!r)ine r=jvaqbj.rirag;ine c=-1;vs(jvaqbj.IjNqNQ_VQ)c=jvaqbj.IjNqNQ_VQ.EbyybssCnary;ine bo=IjTrgBow(\"IjCnayNQ_VQ_\"+c);vs(bo&&bo.fglyr.ivfvovyvgl==\"ivfvoyr\"){ine fns=IjFns?8:0;ine pheK=r.pyvragK+IjBOFpe(\"U\")+fns,pheL=r.pyvragL+IjBOFpe(\"I\")+fns;ine y=IjBOEC(NQ_VQ,bo,\"Y\"),g=IjBOEC(NQ_VQ,bo,\"G\");ine e=y+jvaqbj.IjNqNQ_VQ.Cnaryf[c].Jvqgu,o=g+jvaqbj.IjNqNQ_VQ.Cnaryf[c].Urvtug;vs((pheK<y)||(pheK>e)||(pheL<g)||(pheL>o)){vs(jvaqbj.IjBaEbyybssNQ_VQ)IjBaEbyybssNQ_VQ(c);ryfr IjPybfrNq(NQ_VQ,c,gehr,\"\");}ryfr erghea;}IjPnapryZbhfrYvfgrareNQ_VQ();};;jvaqbj.IjFrgEbyybssCnaryNQ_VQ=shapgvba(c){ine z=\"zbhfrzbir\",q=qbphzrag,s=IjPurpxZbhfrCbfvgvbaNQ_VQ;c=IjTc(NQ_VQ,c);vs(jvaqbj.IjNqNQ_VQ&&jvaqbj.IjNqNQ_VQ.EbyybssCnary>-1)IjPnapryZbhfrYvfgrareNQ_VQ();vs(jvaqbj.IjNqNQ_VQ)jvaqbj.IjNqNQ_VQ.EbyybssCnary=c;gel{vs(q.nqqRiragYvfgrare)q.nqqRiragYvfgrare(z,s,snyfr);ryfr vs(q.nggnpuRirag)q.nggnpuRirag(\"ba\"+z,s);}pngpu(r){}};;jvaqbj.IjPnapryZbhfrYvfgrareNQ_VQ=shapgvba(){ine z=\"zbhfrzbir\",q=qbphzrag,s=IjPurpxZbhfrCbfvgvbaNQ_VQ;vs(jvaqbj.IjNqNQ_VQ)jvaqbj.IjNqNQ_VQ.EbyybssCnary=-1;gel{vs(q.erzbirRiragYvfgrare)q.erzbirRiragYvfgrare(z,s,snyfr);ryfr vs(q.qrgnpuRirag)q.qrgnpuRirag(\"ba\"+z,s);}pngpu(r){}};;jvaqbj.IjNqNQ_VQ.IjTc=d2(n,c){ine nq=jvaqbj.IjNqNQ_VQ;vs(vfAnA(c)){sbe(ine v=0;v<nq.Cnaryf.yratgu;v++)vs(nq.Cnaryf[v].Anzr==c)erghea v;erghea 0;}erghea c;};;jvaqbj.IjNqNQ_VQ.IjTpy=d2(n,c,p){ine cn=jvaqbj.IjNqNQ_VQ.Cnaryf[IjTc(n,c)];vs(!cn)erghea 0;vs(vfAnA(p)){sbe(ine v=0;v<cn.Pyvpxguehf.yratgu;v++)vs(cn.Pyvpxguehf[v].Anzr==p)erghea v;erghea 0;}erghea p;};;jvaqbj.IjNqNQ_VQ.IjGenpr=d2(n,f){gel{vs(jvaqbj[\"Ij\"+\"QtQ\"])jvaqbj[\"Ij\"+\"QtQ\"](n,1,f);}pngpu(r){}};;jvaqbj.IjNqNQ_VQ.IjYvzvg1=d2(n,f){ine nq=jvaqbj.IjNqNQ_VQ,vh=f.fcyvg(\"/\");sbe(ine v=0,p=0;v<vh.yratgu;v++){vs(vh[v].yratgu>0){vs(nq.FzV.yratgu>0)nq.FzV+=\"/\";nq.FzV+=vh[v];nq.FtZ[nq.FtZ.yratgu]=snyfr;}}};;jvaqbj.IjNqNQ_VQ.IjYvzvg0=d2(n,f){ine nq=jvaqbj.IjNqNQ_VQ,vh=f.fcyvg(\"/\");sbe(ine v=0;v<vh.yratgu;v++){vs(vh[v].yratgu>0){vs(nq.OvC.yratgu>0)nq.OvC+=\"/\";nq.OvC+=vh[v];}}};;jvaqbj.IjNqNQ_VQ.IjRVST=d2(n,c){jvaqbj[\"IjCnayNQ_VQ_\"+c+\"_Bow\"]=IjTrgBow(\"IjCnayNQ_VQ_\"+c+\"_Bow\");vs(jvaqbj[\"IjCnayNQ_VQ_\"+c+\"_Bow\"]==ahyy)frgGvzrbhg(\"IjRVST(NQ_VQ,\"+c+\")\",jvaqbj.IjNqNQ_VQ.rvsg);};;jvaqbj.IjNqNQ_VQ.IjNavzSHC=d2(n,c){ine nq=jvaqbj.IjNqNQ_VQ;vs(c>nq.Cnaryf.yratgu)erghea;ine cna=nq.Cnaryf[c],nn=gehr,on=gehr,yn=gehr,en=gehr,cn=nq.Cnaryf[0],sf=nq.ShF,j=cn.Jvqgu,u=cn.Urvtug;vs(j==\"100%\"){j=sf;en=snyfr;yn=snyfr;}vs(u==\"100%\"){u=sf;nn=snyfr;on=snyfr;}vs(cn.YnY==\"Y\")yn=snyfr;vs(cn.YnY==\"E\")en=snyfr;vs(cn.GnY==\"G\")nn=snyfr;vs(cn.GnY==\"O\")on=snyfr;ine k=0,l=0;fjvgpu(nq.NshP%8){pnfr 0:oernx;pnfr 1:vs(nn)l=-sf;oernx;pnfr 2:k=j-sf;oernx;pnfr 3:vs(en)k=j;oernx;pnfr 4:k=j-sf;l=u-sf;oernx;pnfr 5:k=j-sf;vs(on)l=u;oernx;pnfr 6:l=u-sf;oernx;pnfr 7:vs(yn)k=-sf;l=u-sf;oernx;}vs(nq.NshP++ <nq.NshG)frgGvzrbhg((\"IjNavzSHC(NQ_VQ,\"+c+\")\"),nq.NshC);ryfr{k=-1000;l=k;}cna.YrsgBssfrg=k;cna.GbcBssfrg=l;IjNhErcb(n,c);};;jvaqbj.IjNqNQ_VQ.IjTrgErnyCbfvgvba=d2(n,b,j){erghea IjBOEC.nccyl(guvf,nethzragf);};;jvaqbj.IjNqNQ_VQ.IjPnapryGvzrbhg=d2(n,c){c=IjTc(n,c);ine cay=jvaqbj.IjNqNQ_VQ.Cnaryf[c];vs(cay&&cay.UgU!=\"\"){pyrneGvzrbhg(cay.UgU);}};;jvaqbj.IjNqNQ_VQ.IjPnapryNyyGvzrbhgf=d2(n){vs(jvaqbj.IjNqNQ_VQ.YbpxGvzrbhgPunatrf)erghea;sbe(ine c=0;c<jvaqbj.IjNqNQ_VQ.bac;c++)IjPnapryGvzrbhg(n,c);};;jvaqbj.IjNqNQ_VQ.IjFgnegGvzrbhg=d2(n,c,bG){c=IjTc(n,c);ine cay=jvaqbj.IjNqNQ_VQ.Cnaryf[c];vs(cay&&((cay.UvqrGvzrbhgInyhr>0)||(nethzragf.yratgu==3&&bG>0))){pyrneGvzrbhg(cay.UgU);cay.UgU=frgGvzrbhg(cay.UvqrNpgvba,(nethzragf.yratgu==3?bG:cay.UvqrGvzrbhgInyhr));}};;jvaqbj.IjNqNQ_VQ.IjErfrgGvzrbhg=d2(n,c,bG){c=IjTc(n,c);IjPnapryGvzrbhg(n,c);riny(\"IjFgnegGvzrbhg(NQ_VQ,c\"+(nethzragf.yratgu==3?\",bG\":\"\")+\")\");};;jvaqbj.IjNqNQ_VQ.IjErfrgNyyGvzrbhgf=d2(n){sbe(ine c=0;c<jvaqbj.IjNqNQ_VQ.bac;c++)IjErfrgGvzrbhg(n,c);};;jvaqbj.IjNqNQ_VQ.IjQrgnpure=d2(n,rig,sap){gel{vs(IjQVR5)riny(\"jvaqbj.qrgnpuRirag(\\'ba\"+rig+\"\\',\"+sap+\"NQ_VQ)\");ryfr vs(!IjQVRZnp)riny(\"jvaqbj.erzbirRiragYvfgrare(\\'\"+rig+\"\\',\"+sap+\"NQ_VQ,snyfr)\");}pngpu(r){}};;jvaqbj.IjNqNQ_VQ.IjPyrna',\n    r\"FrffvbaQQS2=111soqs57qo8o8480qo18sor2011r3n591q7s6s37r120904; ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669315660164980&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=\",\n    r\"FrffvbaQQS2=111soqs57qo8o8480qo18sor2011r3n591q7s6s37r120904; __hgzm=144631658.1231363570.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar); __hgzn=144631658.3426875219718084000.1231363570.1231363570.1231363570.1; __hgzo=144631658.0.10.1231363570; __hgzp=144631658; ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669315660164980&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q\",\n    r\"uggc://tbbtyrnqf.t.qbhoyrpyvpx.arg/cntrnq/nqf?pyvrag=pn-svz_zlfcnpr_zlfcnpr-ubzrcntr_wf&qg=1231363514065&uy=ra&nqfnsr=uvtu&br=hgs8&ahz_nqf=4&bhgchg=wf&nqgrfg=bss&pbeeryngbe=1231363514065&punaary=svz_zlfcnpr_ubzrcntr_abgybttrqva%2Psvz_zlfcnpr_aba_HTP%2Psvz_zlfcnpr_havgrq-fgngrf&hey=uggc%3N%2S%2Subzr.zlfcnpr.pbz%2Svaqrk.psz&nq_glcr=grkg&rvq=6083027&rn=0&sez=0&tn_ivq=1326469221.1231363557&tn_fvq=1231363557&tn_uvq=1114636509&synfu=9.0.115&h_u=768&h_j=1024&h_nu=738&h_nj=1024&h_pq=24&h_gm=-480&h_uvf=2&h_wnin=gehr&h_acyht=7&h_azvzr=22\",\n    r\"ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669315660164980&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q\",\n    r\"ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669315660164980&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=\",\n    r\"FrffvbaQQS2=s6r4579npn4rn2135s904r0s75pp1o5334p6s6pospo12696; ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669316860113296&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=; AFP_zp_dfctwzs-aowb_80=44132r503660\",\n    r\"FrffvbaQQS2=s6r4579npn4rn2135s904r0s75pp1o5334p6s6pospo12696; AFP_zp_dfctwzs-aowb_80=44132r503660; __hgzm=144631658.1231363638.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar); __hgzn=144631658.965867047679498800.1231363638.1231363638.1231363638.1; __hgzo=144631658.0.10.1231363638; __hgzp=144631658; ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669316860113296&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q\",\n    r\"uggc://tbbtyrnqf.t.qbhoyrpyvpx.arg/cntrnq/nqf?pyvrag=pn-svz_zlfcnpr_zlfcnpr-ubzrcntr_wf&qg=1231363621014&uy=ra&nqfnsr=uvtu&br=hgs8&ahz_nqf=4&bhgchg=wf&nqgrfg=bss&pbeeryngbe=1231363621014&punaary=svz_zlfcnpr_ubzrcntr_abgybttrqva%2Psvz_zlfcnpr_aba_HTP%2Psvz_zlfcnpr_havgrq-fgngrf&hey=uggc%3N%2S%2Scebsvyr.zlfcnpr.pbz%2Svaqrk.psz&nq_glcr=grkg&rvq=6083027&rn=0&sez=0&tn_ivq=348699119.1231363624&tn_fvq=1231363624&tn_uvq=895511034&synfu=9.0.115&h_u=768&h_j=1024&h_nu=738&h_nj=1024&h_pq=24&h_gm=-480&h_uvf=2&h_wnin=gehr&h_acyht=7&h_azvzr=22\",\n    r\"uggc://jjj.yrobapbva.se/yv\",\n    r\"ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669316860113296&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q\",\n    r\"ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669316860113296&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=\",\n    r\"FrffvbaQQS2=s15q53p9n372sn76npr13o271n4s3p5r29p235746p908p58; ZFPhygher=VC=66.249.85.130&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669358527244818&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=\",\n    r\"FrffvbaQQS2=s15q53p9n372sn76npr13o271n4s3p5r29p235746p908p58; __hgzm=144631658.1231367822.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar); __hgzn=144631658.4127520630321984500.1231367822.1231367822.1231367822.1; __hgzo=144631658.0.10.1231367822; __hgzp=144631658; ZFPhygher=VC=66.249.85.130&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669358527244818&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q\",\n    r\"uggc://tbbtyrnqf.t.qbhoyrpyvpx.arg/cntrnq/nqf?pyvrag=pn-svz_zlfcnpr_zlfcnpr-ubzrcntr_wf&qg=1231367803797&uy=ra&nqfnsr=uvtu&br=hgs8&ahz_nqf=4&bhgchg=wf&nqgrfg=bss&pbeeryngbe=1231367803797&punaary=svz_zlfcnpr_ubzrcntr_abgybttrqva%2Psvz_zlfcnpr_aba_HTP%2Psvz_zlfcnpr_havgrq-fgngrf&hey=uggc%3N%2S%2Szrffntvat.zlfcnpr.pbz%2Svaqrk.psz&nq_glcr=grkg&rvq=6083027&rn=0&sez=0&tn_ivq=1192552091.1231367807&tn_fvq=1231367807&tn_uvq=1155446857&synfu=9.0.115&h_u=768&h_j=1024&h_nu=738&h_nj=1024&h_pq=24&h_gm=-480&h_uvf=2&h_wnin=gehr&h_acyht=7&h_azvzr=22\",\n    r\"ZFPhygher=VC=66.249.85.130&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669358527244818&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q\",\n    r\"ZFPhygher=VC=66.249.85.130&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669358527244818&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=\",\n    r\"hy.ynat-fryrpgbe\",\n    r'<hy pynff=\"nqi\">##yv4##Cbjreshy Zvpebfbsg grpuabybtl urycf svtug fcnz naq vzcebir frphevgl.##yv19##Trg zber qbar gunaxf gb terngre rnfr naq fcrrq.##yv16##Ybgf bs fgbentr &#40;5 TO&#41; - zber pbby fghss ba gur jnl.##OE## ##OE## ##N##Yrnea zber##/N##</hy>',\n    r'<hy pynff=\"nqi\"><yv vq=\"YvOYG4\" fglyr=\"onpxtebhaq-vzntr:hey(uggc://vzt.jykef.pbz/~Yvir.FvgrPbagrag.VQ/~14.2.1230/~/~/~/oyg4.cat)\">Cbjreshy Zvpebfbsg grpuabybtl urycf svtug fcnz naq vzcebir frphevgl.##yv19##Trg zber qbar gunaxf gb terngre rnfr naq fcrrq.##yv16##Ybgf bs fgbentr &#40;5 TO&#41; - zber pbby fghss ba gur jnl.##OE## ##OE## ##N##Yrnea zber##/N##</hy>',\n    r'<hy pynff=\"nqi\"><yv vq=\"YvOYG4\" fglyr=\"onpxtebhaq-vzntr:hey(uggc://vzt.jykef.pbz/~Yvir.FvgrPbagrag.VQ/~14.2.1230/~/~/~/oyg4.cat)\">Cbjreshy Zvpebfbsg grpuabybtl urycf svtug fcnz naq vzcebir frphevgl.##yv19##Trg zber qbar gunaxf gb terngre rnfr naq fcrrq.<yv vq=\"YvOYG16\" fglyr=\"onpxtebhaq-vzntr:hey(uggc://vzt.jykef.pbz/~Yvir.FvgrPbagrag.VQ/~14.2.1230/~/~/~/oyg16.cat)\">Ybgf bs fgbentr &#40;5 TO&#41; - zber pbby fghss ba gur jnl.##OE## ##OE## ##N##Yrnea zber##/N##</hy>',\n    r'<hy pynff=\"nqi\"><yv vq=\"YvOYG4\" fglyr=\"onpxtebhaq-vzntr:hey(uggc://vzt.jykef.pbz/~Yvir.FvgrPbagrag.VQ/~14.2.1230/~/~/~/oyg4.cat)\">Cbjreshy Zvpebfbsg grpuabybtl urycf svtug fcnz naq vzcebir frphevgl.<yv vq=\"YvOYG19\" fglyr=\"onpxtebhaq-vzntr:hey(uggc://vzt.jykef.pbz/~Yvir.FvgrPbagrag.VQ/~14.2.1230/~/~/~/oyg19.cat)\">Trg zber qbar gunaxf gb terngre rnfr naq fcrrq.<yv vq=\"YvOYG16\" fglyr=\"onpxtebhaq-vzntr:hey(uggc://vzt.jykef.pbz/~Yvir.FvgrPbagrag.VQ/~14.2.1230/~/~/~/oyg16.cat)\">Ybgf bs fgbentr &#40;5 TO&#41; - zber pbby fghss ba gur jnl.##OE## ##OE## ##N##Yrnea zber##/N##</hy>',\n    r'<hy pynff=\"nqi\"><yv vq=\"YvOYG4\" fglyr=\"onpxtebhaq-vzntr:hey(uggc://vzt.jykef.pbz/~Yvir.FvgrPbagrag.VQ/~14.2.1230/~/~/~/oyg4.cat)\">Cbjreshy Zvpebfbsg grpuabybtl urycf svtug fcnz naq vzcebir frphevgl.<yv vq=\"YvOYG19\" fglyr=\"onpxtebhaq-vzntr:hey(uggc://vzt.jykef.pbz/~Yvir.FvgrPbagrag.VQ/~14.2.1230/~/~/~/oyg19.cat)\">Trg zber qbar gunaxf gb terngre rnfr naq fcrrq.<yv vq=\"YvOYG16\" fglyr=\"onpxtebhaq-vzntr:hey(uggc://vzt.jykef.pbz/~Yvir.FvgrPbagrag.VQ/~14.2.1230/~/~/~/oyg16.cat)\">Ybgf bs fgbentr &#40;5 TO&#41; - zber pbby fghss ba gur jnl.<oe> <oe> ##N##Yrnea zber##/N##</hy>',\n    r'<hy pynff=\"nqi\"><yv vq=\"YvOYG4\" fglyr=\"onpxtebhaq-vzntr:hey(uggc://vzt.jykef.pbz/~Yvir.FvgrPbagrag.VQ/~14.2.1230/~/~/~/oyg4.cat)\">Cbjreshy Zvpebfbsg grpuabybtl urycf svtug fcnz naq vzcebir frphevgl.<yv vq=\"YvOYG19\" fglyr=\"onpxtebhaq-vzntr:hey(uggc://vzt.jykef.pbz/~Yvir.FvgrPbagrag.VQ/~14.2.1230/~/~/~/oyg19.cat)\">Trg zber qbar gunaxf gb terngre rnfr naq fcrrq.<yv vq=\"YvOYG16\" fglyr=\"onpxtebhaq-vzntr:hey(uggc://vzt.jykef.pbz/~Yvir.FvgrPbagrag.VQ/~14.2.1230/~/~/~/oyg16.cat)\">Ybgf bs fgbentr &#40;5 TO&#41; - zber pbby fghss ba gur jnl.<oe> <oe> <n uers=\"uggc://znvy.yvir.pbz/znvy/nobhg.nfck\" gnetrg=\"_oynax\">Yrnea zber##/N##</hy>',\n    r\"Bar Jvaqbjf Yvir VQ trgf lbh vagb <o>Ubgznvy</o>, <o>Zrffratre</o>, <o>Kobk YVIR</o> \\u2014 naq bgure cynprf lbh frr #~#argjbexybtb#~#\",\n    r\"${1}://${2}${3}${4}${5}\",\n    r\" O=6gnyg0g4znrrn&o=3&f=gc; Q=_lyu=K3bQZGSxnT4lZzD3OS9GNmV3ZGLkAQxRpTyxNmRlZmRmAmNkAQLRqTImqNZjOUEgpTjQnJ5xMKtgoN--; SCF=qy\",\n    r\"FrffvbaQQS2=4ss747o77904333q374or84qrr1s9r0nprp8r5q81534o94n; ZFPhygher=VC=74.125.75.20&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669321699093060&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=; AFP_zp_tfwsbrg-aowb_80=4413268q3660\",\n    r\"FrffvbaQQS2=4ss747o77904333q374or84qrr1s9r0nprp8r5q81534o94n; AFP_zp_tfwsbrg-aowb_80=4413268q3660; __hgzm=144631658.1231364074.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar); __hgzn=144631658.2294274870215848400.1231364074.1231364074.1231364074.1; __hgzo=144631658.0.10.1231364074; __hgzp=144631658; ZFPhygher=VC=74.125.75.20&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669321699093060&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q\",\n    r\"uggc://tbbtyrnqf.t.qbhoyrpyvpx.arg/cntrnq/nqf?pyvrag=pn-svz_zlfcnpr_zlfcnpr-ubzrcntr_wf&qg=1231364057761&uy=ra&nqfnsr=uvtu&br=hgs8&ahz_nqf=4&bhgchg=wf&nqgrfg=bss&pbeeryngbe=1231364057761&punaary=svz_zlfcnpr_ubzrcntr_abgybttrqva%2Psvz_zlfcnpr_aba_HTP%2Psvz_zlfcnpr_havgrq-fgngrf&hey=uggc%3N%2S%2Ssevraqf.zlfcnpr.pbz%2Svaqrk.psz&nq_glcr=grkg&rvq=6083027&rn=0&sez=0&tn_ivq=1667363813.1231364061&tn_fvq=1231364061&tn_uvq=1917563877&synfu=9.0.115&h_u=768&h_j=1024&h_nu=738&h_nj=1024&h_pq=24&h_gm=-480&h_uvf=2&h_wnin=gehr&h_acyht=7&h_azvzr=22\",\n    r\"ZFPhygher=VC=74.125.75.20&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669321699093060&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q\",\n    r\"ZFPhygher=VC=74.125.75.20&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669321699093060&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=\",\n    r\"uggc://cebsvyr.zlfcnpr.pbz/Zbqhyrf/Nccyvpngvbaf/Cntrf/Pnainf.nfck\",\n    r\"FrffvbaQQS2=473qq1rs0n2r70q9qo1pq48n021s9468ron90nps048p4p29; ZFPhygher=VC=74.125.75.3&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669325184628362&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=\",\n    r\"FrffvbaQQS2=473qq1rs0n2r70q9qo1pq48n021s9468ron90nps048p4p29; __hgzm=144631658.1231364380.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar); __hgzn=144631658.3931862196947939300.1231364380.1231364380.1231364380.1; __hgzo=144631658.0.10.1231364380; __hgzp=144631658; ZFPhygher=VC=74.125.75.3&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669325184628362&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q\",\n    r\"uggc://tbbtyrnqf.t.qbhoyrpyvpx.arg/cntrnq/nqf?pyvrag=pn-svz_zlfcnpr_vzntrf_wf&qg=1231364373088&uy=ra&nqfnsr=uvtu&br=hgs8&ahz_nqf=4&bhgchg=wf&nqgrfg=bss&pbeeryngbe=1231364373088&punaary=svz_zlfcnpr_hfre-ivrj-pbzzragf%2Psvz_zlfcnpr_havgrq-fgngrf&hey=uggc%3N%2S%2Spbzzrag.zlfcnpr.pbz%2Svaqrk.psz&nq_glcr=grkg&rvq=6083027&rn=0&sez=0&tn_ivq=1158737789.1231364375&tn_fvq=1231364375&tn_uvq=415520832&synfu=9.0.115&h_u=768&h_j=1024&h_nu=738&h_nj=1024&h_pq=24&h_gm=-480&h_uvf=2&h_wnin=gehr&h_acyht=7&h_azvzr=22\",\n    r\"ZFPhygher=VC=74.125.75.3&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669325184628362&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q\",\n    r\"ZFPhygher=VC=74.125.75.3&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669325184628362&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=\",\n    r\"#Zbq-Vasb-Vasb-WninFpevcgUvag\",\n    r\",n.svryqOgaPnapry\",\n    r\"FrffvbaQQS2=p98s8o9q42nr21or1r61pqorn1n002nsss569635984s6qp7; ZFPhygher=VC=74.125.75.3&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669357391353591&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=; AFP_zp_kkk-gdzogv_80=4413241q3660\",\n    r\"FrffvbaQQS2=p98s8o9q42nr21or1r61pqorn1n002nsss569635984s6qp7; AFP_zp_kkk-gdzogv_80=4413241q3660; AFP_zp_kkk-aowb_80=4413235p3660; __hgzm=144631658.1231367708.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar); __hgzn=144631658.2770915348920628700.1231367708.1231367708.1231367708.1; __hgzo=144631658.0.10.1231367708; __hgzp=144631658; ZFPhygher=VC=74.125.75.3&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669357391353591&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q\",\n    r\"uggc://tbbtyrnqf.t.qbhoyrpyvpx.arg/cntrnq/nqf?pyvrag=pn-svz_zlfcnpr_zlfcnpr-ubzrcntr_wf&qg=1231367691141&uy=ra&nqfnsr=uvtu&br=hgs8&ahz_nqf=4&bhgchg=wf&nqgrfg=bss&pbeeryngbe=1231367691141&punaary=svz_zlfcnpr_ubzrcntr_abgybttrqva%2Psvz_zlfcnpr_aba_HTP%2Psvz_zlfcnpr_havgrq-fgngrf&hey=uggc%3N%2S%2Sjjj.zlfcnpr.pbz%2S&nq_glcr=grkg&rvq=6083027&rn=0&sez=0&tn_ivq=320757904.1231367694&tn_fvq=1231367694&tn_uvq=1758792003&synfu=9.0.115&h_u=768&h_j=1024&h_nu=738&h_nj=1024&h_pq=24&h_gm=-480&h_uvf=2&h_wnin=gehr&h_acyht=7&h_azvzr=22\",\n    r\"uggc://zfacbegny.112.2b7.arg/o/ff/zfacbegnyubzr/1/U.7-cqi-2/f55332979829981?[NDO]&aqu=1&g=7%2S0%2S2009%2014%3N38%3N42%203%20480&af=zfacbegny&cntrAnzr=HF%20UCZFSGJ&t=uggc%3N%2S%2Sjjj.zfa.pbz%2S&f=1024k768&p=24&x=L&oj=994&ou=634&uc=A&{2}&[NDR]\",\n    r\"cnerag puebzr6 fvatyr1 gno fryrpgrq ovaq qbhoyr2 ps\",\n    r\"ZFPhygher=VC=74.125.75.3&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669357391353591&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q\",\n    r\"ZFPhygher=VC=74.125.75.3&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669357391353591&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=\",\n    r\"ne;ng;nh;or;oe;pn;pu;py;pa;qr;qx;rf;sv;se;to;ux;vq;vr;va;vg;wc;xe;zk;zl;ay;ab;am;cu;cy;cg;eh;fr;ft;gu;ge;gj;mn;\",\n    r\"ZP1=I=3&THVQ=6nnpr9q661804s33nnop45nosqp17q85; zu=ZFSG; PHYGHER=RA-HF; SyvtugTebhcVq=97; SyvtugVq=OnfrCntr; ucfie=Z:5|S:5|G:5|R:5|Q:oyh|J:S; ucpyv=J.U|Y.|F.|E.|H.Y|P.|U.; hfucjrn=jp:HFPN0746; ZHVQ=Q783SN9O14054831N4869R51P0SO8886&GHVQ=1\",\n    r\"ZP1=I=3&THVQ=6nnpr9q661804s33nnop45nosqp17q85; zu=ZFSG; PHYGHER=RA-HF; SyvtugTebhcVq=97; SyvtugVq=OnfrCntr; ucfie=Z:5|S:5|G:5|R:5|Q:oyh|J:S; ucpyv=J.U|Y.|F.|E.|H.Y|P.|U.; hfucjrn=jp:HFPN0746; ZHVQ=Q783SN9O14054831N4869R51P0SO8886\",\n    r\"ZP1=I=3&THVQ=6nnpr9q661804s33nnop45nosqp17q85; zu=ZFSG; PHYGHER=RA-HF; SyvtugTebhcVq=97; SyvtugVq=OnfrCntr; ucfie=Z:5|S:5|G:5|R:5|Q:oyh|J:S; ucpyv=J.U|Y.|F.|E.|H.Y|P.|U.; hfucjrn=jp:HFPN0746; ZHVQ=Q783SN9O14054831N4869R51P0SO8886; mvc=m:94043|yn:37.4154|yb:-122.0585|p:HF|ue:1\",\n    r\"ZP1=I=3&THVQ=6nnpr9q661804s33nnop45nosqp17q85; zu=ZFSG; PHYGHER=RA-HF; SyvtugTebhcVq=97; SyvtugVq=OnfrCntr; ucfie=Z:5|S:5|G:5|R:5|Q:oyh|J:S; ucpyv=J.U|Y.|F.|E.|H.Y|P.|U.; hfucjrn=jp:HFPN0746; ZHVQ=Q783SN9O14054831N4869R51P0SO8886; mvc=m:94043|yn:37.4154|yb:-122.0585|p:HF\",\n    r\"uggc://gx2.fgp.f-zfa.pbz/oe/uc/11/ra-hf/pff/v/g.tvs#uggc://gx2.fgo.f-zfa.pbz/v/29/4RQP4969777N048NPS4RRR3PO2S7S.wct\",\n    r\"uggc://gx2.fgp.f-zfa.pbz/oe/uc/11/ra-hf/pff/v/g.tvs#uggc://gx2.fgo.f-zfa.pbz/v/OQ/63NP9O94NS5OQP1249Q9S1ROP7NS3.wct\",\n    r\"zbmvyyn/5.0 (jvaqbjf; h; jvaqbjf ag 5.1; ra-hf) nccyrjroxvg/528.9 (xugzy, yvxr trpxb) puebzr/2.0.157.0 fnsnev/528.9\",\n    r\"1231365729213\",\n    r\"74.125.75.3-1057165600.29978900\",\n    r\"74.125.75.3-1057165600.29978900.1231365730214\",\n    r\"Frnepu%20Zvpebfbsg.pbz\",\n    r\"FrffvbaQQS2=8sqq78r9n442851q565599o401385sp3s04r92rnn7o19ssn; ZFPhygher=VC=74.125.75.17&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669340386893867&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=\",\n    r\"FrffvbaQQS2=8sqq78r9n442851q565599o401385sp3s04r92rnn7o19ssn; __hgzm=144631658.1231365779.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar); __hgzn=144631658.1877536177953918500.1231365779.1231365779.1231365779.1; __hgzo=144631658.0.10.1231365779; __hgzp=144631658; ZFPhygher=VC=74.125.75.17&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669340386893867&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q\",\n    r\"I=3%26THVQ=757q3ss871q44o7o805n8113n5p72q52\",\n    r\"I=3&THVQ=757q3ss871q44o7o805n8113n5p72q52\",\n    r\"uggc://tbbtyrnqf.t.qbhoyrpyvpx.arg/cntrnq/nqf?pyvrag=pn-svz_zlfcnpr_zlfcnpr-ubzrcntr_wf&qg=1231365765292&uy=ra&nqfnsr=uvtu&br=hgs8&ahz_nqf=4&bhgchg=wf&nqgrfg=bss&pbeeryngbe=1231365765292&punaary=svz_zlfcnpr_ubzrcntr_abgybttrqva%2Psvz_zlfcnpr_aba_HTP%2Psvz_zlfcnpr_havgrq-fgngrf&hey=uggc%3N%2S%2Sohyyrgvaf.zlfcnpr.pbz%2Svaqrk.psz&nq_glcr=grkg&rvq=6083027&rn=0&sez=0&tn_ivq=1579793869.1231365768&tn_fvq=1231365768&tn_uvq=2056210897&synfu=9.0.115&h_u=768&h_j=1024&h_nu=738&h_nj=1024&h_pq=24&h_gm=-480&h_uvf=2&h_wnin=gehr&h_acyht=7&h_azvzr=22\",\n    r\"frnepu.zvpebfbsg.pbz\",\n    r\"frnepu.zvpebfbsg.pbz/\",\n    r\"ZFPhygher=VC=74.125.75.17&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669340386893867&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q\",\n    r\"ZFPhygher=VC=74.125.75.17&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669340386893867&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=\",\n    r\"#fubhgobk .pybfr\",\n    r\"FrffvbaQQS2=102n9o0o9pq60132qn0337rr867p75953502q2s27s2s5r98; ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669341278771470&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=; AFP_zp_dfctwzssrwh-aowb_80=441326q33660\",\n    r\"FrffvbaQQS2=102n9o0o9pq60132qn0337rr867p75953502q2s27s2s5r98; AFP_zp_dfctwzssrwh-aowb_80=441326q33660; __hgzm=144631658.1231365869.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar); __hgzn=144631658.1670816052019209000.1231365869.1231365869.1231365869.1; __hgzo=144631658.0.10.1231365869; __hgzp=144631658; ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669341278771470&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q\",\n    r\"FrffvbaQQS2=9995p6rp12rrnr893334ro7nq70o7p64p69rqn844prs1473; ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669350559478880&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=; AFP_zp_dfctwzs-aowb_80=441327q73660\",\n    r\"FrffvbaQQS2=9995p6rp12rrnr893334ro7nq70o7p64p69rqn844prs1473; AFP_zp_dfctwzs-aowb_80=441327q73660; __hgzm=144631658.1231367054.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar); __hgzn=144631658.1796080716621419500.1231367054.1231367054.1231367054.1; __hgzo=144631658.0.10.1231367054; __hgzp=144631658; ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669350559478880&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q\",\n    r\"[glcr=fhozvg]\",\n    r\"n.svryqOga,n.svryqOgaPnapry\",\n    r\"n.svryqOgaPnapry\",\n    r\"oyvpxchaxg\",\n    r\"qvi.bow-nppbeqvba qg\",\n    r\"uggc://tbbtyrnqf.t.qbhoyrpyvpx.arg/cntrnq/nqf?pyvrag=pn-svz_zlfcnpr_nccf_wf&qg=1231367052227&uy=ra&nqfnsr=uvtu&br=hgs8&ahz_nqf=4&bhgchg=wf&nqgrfg=bss&pbeeryngbe=1231367052227&punaary=svz_zlfcnpr_nccf-pnainf%2Psvz_zlfcnpr_havgrq-fgngrf&hey=uggc%3N%2S%2Scebsvyr.zlfcnpr.pbz%2SZbqhyrf%2SNccyvpngvbaf%2SCntrf%2SPnainf.nfck&nq_glcr=grkg&rvq=6083027&rn=0&sez=1&tn_ivq=716357910.1231367056&tn_fvq=1231367056&tn_uvq=1387206491&synfu=9.0.115&h_u=768&h_j=1024&h_nu=738&h_nj=1024&h_pq=24&h_gm=-480&h_uvf=2&h_wnin=gehr&h_acyht=7&h_azvzr=22\",\n    r\"uggc://tbbtyrnqf.t.qbhoyrpyvpx.arg/cntrnq/nqf?pyvrag=pn-svz_zlfcnpr_zlfcnpr-ubzrcntr_wf&qg=1231365851658&uy=ra&nqfnsr=uvtu&br=hgs8&ahz_nqf=4&bhgchg=wf&nqgrfg=bss&pbeeryngbe=1231365851658&punaary=svz_zlfcnpr_ubzrcntr_abgybttrqva%2Psvz_zlfcnpr_aba_HTP%2Psvz_zlfcnpr_havgrq-fgngrf&hey=uggc%3N%2S%2Scebsvyrrqvg.zlfcnpr.pbz%2Svaqrk.psz&nq_glcr=grkg&rvq=6083027&rn=0&sez=0&tn_ivq=1979828129.1231365855&tn_fvq=1231365855&tn_uvq=2085229649&synfu=9.0.115&h_u=768&h_j=1024&h_nu=738&h_nj=1024&h_pq=24&h_gm=-480&h_uvf=2&h_wnin=gehr&h_acyht=7&h_azvzr=22\",\n    r\"uggc://zfacbegny.112.2b7.arg/o/ff/zfacbegnyubzr/1/U.7-cqi-2/f55023338617756?[NDO]&aqu=1&g=7%2S0%2S2009%2014%3N12%3N47%203%20480&af=zfacbegny&cntrAnzr=HF%20UCZFSGJ&t=uggc%3N%2S%2Sjjj.zfa.pbz%2S&f=0k0&p=43835816&x=A&oj=994&ou=634&uc=A&{2}&[NDR]\",\n    r\"zrgn[anzr=nwnkHey]\",\n    r\"anpuevpugra\",\n    r'b oS={\\'oT\\':1.1};x $8n(B){z(B!=o9)};x $S(B){O(!$8n(B))z A;O(B.4L)z\\'T\\';b S=7t B;O(S==\\'2P\\'&&B.p4){23(B.7f){12 1:z\\'T\\';12 3:z/\\S/.2g(B.8M)?\\'ox\\':\\'oh\\'}}O(S==\\'2P\\'||S==\\'x\\'){23(B.nE){12 2V:z\\'1O\\';12 7I:z\\'5a\\';12 18:z\\'4B\\'}O(7t B.I==\\'4F\\'){O(B.3u)z\\'pG\\';O(B.8e)z\\'1p\\'}}z S};x $2p(){b 4E={};Z(b v=0;v<1p.I;v++){Z(b X 1o 1p[v]){b nc=1p[v][X];b 6E=4E[X];O(6E&&$S(nc)==\\'2P\\'&&$S(6E)==\\'2P\\')4E[X]=$2p(6E,nc);17 4E[X]=nc}}z 4E};b $E=7p.E=x(){b 1d=1p;O(!1d[1])1d=[p,1d[0]];Z(b X 1o 1d[1])1d[0][X]=1d[1][X];z 1d[0]};b $4D=7p.pJ=x(){Z(b v=0,y=1p.I;v<y;v++){1p[v].E=x(1J){Z(b 1I 1o 1J){O(!p.1Y[1I])p.1Y[1I]=1J[1I];O(!p[1I])p[1I]=$4D.6C(1I)}}}};$4D.6C=x(1I){z x(L){z p.1Y[1I].3H(L,2V.1Y.nV.1F(1p,1))}};$4D(7F,2V,6J,nb);b 3l=x(B){B=B||{};B.E=$E;z B};b pK=Y 3l(H);b pZ=Y 3l(C);C.6f=C.35(\\'6f\\')[0];x $2O(B){z!!(B||B===0)};x $5S(B,n8){z $8n(B)?B:n8};x $7K(3c,1m){z 1q.na(1q.7K()*(1m-3c+1)+3c)};x $3N(){z Y 97().os()};x $4M(1U){pv(1U);pa(1U);z 1S};H.43=!!(C.5Z);O(H.nB)H.31=H[H.7q?\\'py\\':\\'nL\\']=1r;17 O(C.9N&&!C.om&&!oy.oZ)H.pF=H.4Z=H[H.43?\\'pt\\':\\'65\\']=1r;17 O(C.po!=1S)H.7J=1r;O(7t 5B==\\'o9\\'){b 5B=x(){};O(H.4Z)C.nd(\"pW\");5B.1Y=(H.4Z)?H[\"[[oN.1Y]]\"]:{}}5B.1Y.4L=1r;O(H.nL)5s{C.oX(\"pp\",A,1r)}4K(r){};b 18=x(1X){b 63=x(){z(1p[0]!==1S&&p.1w&&$S(p.1w)==\\'x\\')?p.1w.3H(p,1p):p};$E(63,p);63.1Y=1X;63.nE=18;z 63};18.1z=x(){};18.1Y={E:x(1X){b 7x=Y p(1S);Z(b X 1o 1X){b nC=7x[X];7x[X]=18.nY(nC,1X[X])}z Y 18(7x)},3d:x(){Z(b v=0,y=1p.I;v<y;v++)$E(p.1Y,1p[v])}};18.nY=x(2b,2n){O(2b&&2b!=2n){b S=$S(2n);O(S!=$S(2b))z 2n;23(S){12\\'x\\':b 7R=x(){p.1e=1p.8e.1e;z 2n.3H(p,1p)};7R.1e=2b;z 7R;12\\'2P\\':z $2p(2b,2n)}}z 2n};b 8o=Y 18({oQ:x(J){p.4w=p.4w||[];p.4w.1x(J);z p},7g:x(){O(p.4w&&p.4w.I)p.4w.9J().2x(10,p)},oP:x(){p.4w=[]}});b 2d=Y 18({1V:x(S,J){O(J!=18.1z){p.$19=p.$19||{};p.$19[S]=p.$19[S]||[];p.$19[S].5j(J)}z p},1v:x(S,1d,2x){O(p.$19&&p.$19[S]){p.$19[S].1b(x(J){J.3n({\\'L\\':p,\\'2x\\':2x,\\'1p\\':1d})()},p)}z p},3M:x(S,J){O(p.$19&&p.$19[S])p.$19[S].2U(J);z p}});b 4v=Y 18({2H:x(){p.P=$2p.3H(1S,[p.P].E(1p));O(!p.1V)z p;Z(b 3O 1o p.P){O($S(p.P[3O]==\\'x\\')&&3O.2g(/^5P[N-M]/))p.1V(3O,p.P[3O])}z p}});2V.E({7y:x(J,L){Z(b v=0,w=p.I;v<w;v++)J.1F(L,p[v],v,p)},3s:x(J,L){b 54=[];Z(b v=0,w=p.I;v<w;v++){O(J.1F(L,p[v],v,p))54.1x(p[v])}z 54},2X:x(J,L){b 54=[];Z(b v=0,w=p.I;v<w;v++)54[v]=J.1F(L,p[v],v,p);z 54},4i:x(J,L){Z(b v=0,w=p.I;v<w;v++){O(!J.1F(L,p[v],v,p))z A}z 1r},ob:x(J,L){Z(b v=0,w=p.I;v<w;v++){O(J.1F(L,p[v],v,p))z 1r}z A},3F:x(3u,15){b 3A=p.I;Z(b v=(15<0)?1q.1m(0,3A+15):15||0;v<3A;v++){O(p[v]===3u)z v}z-1},8z:x(1u,I){1u=1u||0;O(1u<0)1u=p.I+1u;I=I||(p.I-1u);b 89=[];Z(b v=0;v<I;v++)89[v]=p[1u++];z 89},2U:x(3u){b v=0;b 3A=p.I;6L(v<3A){O(p[v]===3u){p.6l(v,1);3A--}17{v++}}z p},1y:x(3u,15){z p.3F(3u,15)!=-1},oz:x(1C){b B={},I=1q.3c(p.I,1C.I);Z(b v=0;v<I;v++)B[1C[v]]=p[v];z B},E:x(1O){Z(b v=0,w=1O.I;v<w;v++)p.1x(1O[v]);z p},2p:x(1O){Z(b v=0,y=1O.I;v<y;v++)p.5j(1O[v]);z p},5j:x(3u){O(!p.1y(3u))p.1x(3u);z p},oc:x(){z p[$7K(0,p.I-1)]||A},7L:x(){z p[p.I-1]||A}});2V.1Y.1b=2V.1Y.7y;2V.1Y.2g=2V.1Y.1y;x $N(1O){z 2V.8z(1O)};x $1b(3J,J,L){O(3J&&7t 3J.I==\\'4F\\'&&$S(3J)!=\\'2P\\')2V.7y(3J,J,L);17 Z(b 1j 1o 3J)J.1F(L||3J,3J[1j],1j)};6J.E({2g:x(6b,2F){z(($S(6b)==\\'2R\\')?Y 7I(6b,2F):6b).2g(p)},3p:x(){z 5K(p,10)},o4:x(){z 69(p)},7A:x(){z p.3y(/-\\D/t,x(2G){z 2G.7G(1).nW()})},9b:x(){z p.3y(/\\w[N-M]/t,x(2G){z(2G.7G(0)+\\'-\\'+2G.7G(1).5O())})},8V:x(){z p.3y(/\\b[n-m]/t,x(2G){z 2G.nW()})},5L:x(){z p.3y(/^\\s+|\\s+$/t,\\'\\')},7j:x(){z p.3y(/\\s{2,}/t,\\' \\').5L()},5V:x(1O){b 1i=p.2G(/\\d{1,3}/t);z(1i)?1i.5V(1O):A},5U:x(1O){b 3P=p.2G(/^#?(\\w{1,2})(\\w{1,2})(\\w{1,2})$/);z(3P)?3P.nV(1).5U(1O):A},1y:x(2R,f){z(f)?(f+p+f).3F(f+2R+f)>-1:p.3F(2R)>-1},nX:x(){z p.3y(/([.*+?^${}()|[\\]\\/\\\\])/t,\\'\\\\$1\\')}});2V.E({5V:x(1O){O(p.I<3)z A;O(p.I==4&&p[3]==0&&!1O)z\\'p5\\';b 3P=[];Z(b v=0;v<3;v++){b 52=(p[v]-0).4h(16);3P.1x((52.I==1)?\\'0\\'+52:52)}z 1O?3P:\\'#\\'+3P.2u(\\'\\')},5U:x(1O){O(p.I!=3)z A;b 1i=[];Z(b v=0;v<3;v++){1i.1x(5K((p[v].I==1)?p[v]+p[v]:p[v],16))}z 1O?1i:\\'1i(\\'+1i.2u(\\',\\')+\\')\\'}});7F.E({3n:x(P){b J=p;P=$2p({\\'L\\':J,\\'V\\':A,\\'1p\\':1S,\\'2x\\':A,\\'4s\\':A,\\'6W\\':A},P);O($2O(P.1p)&&$S(P.1p)!=\\'1O\\')P.1p=[P.1p];z x(V){b 1d;O(P.V){V=V||H.V;1d=[(P.V===1r)?V:Y P.V(V)];O(P.1p)1d.E(P.1p)}17 1d=P.1p||1p;b 3C=x(){z J.3H($5S(P',\n    r\"hagreunyghat\",\n    r\"ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669341278771470&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q\",\n    r\"ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669350559478880&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q\",\n    r\"ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669341278771470&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=\",\n    r\"ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669350559478880&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=\",\n    r\"shapgvba (){Cuk.Nccyvpngvba.Frghc.Pber();Cuk.Nccyvpngvba.Frghc.Nwnk();Cuk.Nccyvpngvba.Frghc.Synfu();Cuk.Nccyvpngvba.Frghc.Zbqhyrf()}\",\n]\n\n# The 12 benchmarking blocks\n\n\ndef block0():\n    for i in range(6511):\n        regexs[0].search(r\"pyvpx\")\n\n    for i in range(1844):\n        regexs[1].search(r\"uggc://jjj.snprobbx.pbz/ybtva.cuc\")\n\n    for i in range(739):\n        regexs[2].sub(r\"\", \"QBZPbageby_cynprubyqre\", subcount[2])\n\n    for i in range(598):\n        regexs[1].search(r\"uggc://jjj.snprobbx.pbz/\")\n\n    for i in range(454):\n        regexs[1].search(r\"uggc://jjj.snprobbx.pbz/fepu.cuc\")\n\n    for i in range(352):\n        re.search(\n            r\"qqqq|qqq|qq|q|ZZZZ|ZZZ|ZZ|Z|llll|ll|l|uu|u|UU|U|zz|z|ff|f|gg|g|sss|ss|s|mmm|mm|m\",\n            \"qqqq, ZZZ q, llll\",\n        )\n\n    for i in range(312):\n        regexs[3].search(r\"vachggrkg QBZPbageby_cynprubyqre\")\n\n    for i in range(282):\n        regexs[4].search(r\"/ZlFcnprUbzrcntr/Vaqrk-FvgrUbzr,10000000\")\n\n    for i in range(177):\n        regexs[5].sub(r\"\", \"vachggrkg\", subcount[5])\n\n    for i in range(170):\n        regexs[6].sub(r\"\", \"528.9\", subcount[6])\n        regexs[7].search(r\"528\")\n\n    for i in range(156):\n        regexs[8].search(r\"VCPhygher=ra-HF\")\n        regexs[8].search(r\"CersreerqPhygher=ra-HF\")\n\n    for i in range(144):\n        regexs[0].search(r\"xrlcerff\")\n\n    for i in range(139):\n        regexs[6].sub(r\"\", \"521\", subcount[6])\n\n        # This has a different output to the V8 version.\n        # It could just be a difference in the engines.\n        regexs[7].search(r\"521\")\n        regexs[9].search(r\"\")\n        re.search(r\"JroXvg\\/(\\S+)\", strings[0])\n\n    for i in range(137):\n        regexs[10].sub(r\"\", \"qvi .so_zrah\", subcount[10])\n        re.sub(r\"\\[\", \"\", \"qvi .so_zrah\", 0)\n        regexs[11].sub(r\"\", \"qvi.so_zrah\", subcount[11])\n\n    for i in range(117):\n        regexs[2].sub(r\"\", \"uvqqra_ryrz\", subcount[2])\n\n    for i in range(95):\n        re.search(\n            r\"(?:^|;)\\s*sevraqfgre_ynat=([^;]*)\",\n            \"sevraqfgre_naba=nvq%3Qn6ss9p85n868ro9s059pn854735956o3%26ers%3Q%26df%3Q%26vpgl%3QHF\",\n        )\n\n    for i in range(93):\n        regexs[12].sub(r\"\", \"uggc://ubzr.zlfcnpr.pbz/vaqrk.psz\", subcount[12])\n        regexs[13].search(r\"uggc://ubzr.zlfcnpr.pbz/vaqrk.psz\")\n\n    for i in range(92):\n        re.sub(r\"([a-zA-Z]|\\s)+\", \"\", strings[1], 1)\n\n    for i in range(85):\n        regexs[14].sub(r\"\", \"svefg\", subcount[14])\n        regexs[15].sub(r\"\", \"svefg\", subcount[15])\n        regexs[12].sub(r\"\", \"uggc://cebsvyr.zlfcnpr.pbz/vaqrk.psz\", subcount[12])\n        regexs[14].sub(r\"\", \"ynfg\", subcount[14])\n        regexs[15].sub(r\"\", \"ynfg\", subcount[15])\n        regexs[16].search(r\"qvfcynl\")\n        regexs[13].search(r\"uggc://cebsvyr.zlfcnpr.pbz/vaqrk.psz\")\n\n\ndef block1():\n    for i in range(81):\n        regexs[8].search(r\"VC=74.125.75.1\")\n\n    for i in range(78):\n        re.sub(r\"(\\s)+e\", \"\", \"9.0  e115\", 1)\n        re.sub(r\".\", \"\", \"k\", 1)\n\n        # This prints a unicode escape where the V8 version prints the\n        # unicode character.\n        regexs[17].sub(r\"\", strings[2], subcount[17])\n\n        # This prints a unicode escape where the V8 version prints the\n        # unicode character.\n        regexs[17].sub(r\"\", strings[3], subcount[17])\n\n        regexs[8].search(r\"144631658\")\n        regexs[8].search(r\"Pbhagel=IIZ%3Q\")\n        regexs[8].search(r\"Pbhagel=IIZ=\")\n        regexs[8].search(r\"CersreerqPhygherCraqvat=\")\n        regexs[8].search(strings[4])\n        regexs[8].search(strings[5])\n        regexs[8].search(r\"__hgzp=144631658\")\n        regexs[8].search(r\"gvzrMbar=-8\")\n        regexs[8].search(r\"gvzrMbar=0\")\n        re.search(r\"Fnsnev\\/(\\d+\\.\\d+)\", strings[0])\n        regexs[3].search(r\"vachggrkg  QBZPbageby_cynprubyqre\")\n        regexs[0].search(r\"xrlqbja\")\n        regexs[0].search(r\"xrlhc\")\n\n    for i in range(77):\n        regexs[12].sub(r\"\", \"uggc://zrffntvat.zlfcnpr.pbz/vaqrk.psz\", subcount[12])\n        regexs[13].search(r\"uggc://zrffntvat.zlfcnpr.pbz/vaqrk.psz\")\n\n    for i in range(73):\n        regexs[18].sub(\n            r\"\",\n            \"FrffvbaFgbentr=%7O%22GnoThvq%22%3N%7O%22thvq%22%3N1231367125017%7Q%7Q\",\n            subcount[18],\n        )\n\n    for i in range(72):\n        regexs[1].search(strings[6])\n\n    for i in range(71):\n        regexs[19].search(r\"\")\n\n    for i in range(70):\n        regexs[11].sub(r\"\", \"3.5.0.0\", subcount[11])\n        re.sub(r\"d1\", \"\", strings[7], 0)\n        re.sub(r\"NQ_VQ\", \"\", strings[8], 0)\n        re.sub(r\"d2\", \"\", strings[9], 0)\n        re.sub(\n            r\"_\", \"\", \"NI%3Q1_CI%3Q1_PI%3Q1_EI%3Q1_HI%3Q1_HP%3Q1_IC%3Q0.0.0.0_IH%3Q0\", 0\n        )\n        regexs[20].split(\n            r\"svz_zlfcnpr_ubzrcntr_abgybttrqva,svz_zlfcnpr_aba_HTP,svz_zlfcnpr_havgrq-fgngrf\"\n        )\n        regexs[21].search(r\"ybnqvat\")\n\n    for i in range(68):\n        regexs[1].search(r\"#\")\n        re.search(\n            r\"(?:ZFVR.(\\d+\\.\\d+))|(?:(?:Sversbk|TenaCnenqvfb|Vprjrnfry).(\\d+\\.\\d+))|(?:Bcren.(\\d+\\.\\d+))|(?:NccyrJroXvg.(\\d+(?:\\.\\d+)?))\",\n            strings[0],\n        )\n        re.search(r\"(Znp BF K)|(Jvaqbjf;)\", strings[0])\n        re.search(r\"Trpxb\\/([0-9]+)\", strings[0])\n        regexs[21].search(r\"ybnqrq\")\n\n    for i in range(49):\n        regexs[16].search(r\"pbybe\")\n\n    for i in range(44):\n        regexs[12].sub(r\"\", \"uggc://sevraqf.zlfcnpr.pbz/vaqrk.psz\", subcount[12])\n        regexs[13].search(r\"uggc://sevraqf.zlfcnpr.pbz/vaqrk.psz\")\n\n\ndef block2():\n    for i in range(40):\n        regexs[14].sub(r\"\", \"fryrpgrq\", subcount[14])\n        regexs[15].sub(r\"\", \"fryrpgrq\", subcount[15])\n\n    for i in range(39):\n        re.sub(r\"\\buvqqra_ryrz\\b\", \"\", \"vachggrkg uvqqra_ryrz\", 0)\n        regexs[3].search(r\"vachggrkg \")\n        regexs[3].search(r\"vachggrkg\")\n        regexs[22].search(r\"HVYvaxOhggba\")\n        regexs[22].search(r\"HVYvaxOhggba_E\")\n        regexs[22].search(r\"HVYvaxOhggba_EJ\")\n        regexs[22].search(r\"zrah_ybtva_pbagnvare\")\n        re.search(r\"\\buvqqra_ryrz\\b\", \"vachgcnffjbeq\")\n\n    for i in range(37):\n        regexs[8].search(r\"111soqs57qo8o8480qo18sor2011r3n591q7s6s37r120904\")\n        regexs[8].search(r\"SbeprqRkcvengvba=633669315660164980\")\n        regexs[8].search(\n            r\"FrffvbaQQS2=111soqs57qo8o8480qo18sor2011r3n591q7s6s37r120904\"\n        )\n\n    for i in range(35):\n        regexs[14].sub(r\"\", \"puvyq p1 svefg\", subcount[14])\n        regexs[15].sub(r\"\", \"puvyq p1 svefg\", subcount[15])\n        regexs[14].sub(r\"\", \"sylbhg pybfrq\", subcount[14])\n        regexs[15].sub(r\"\", \"sylbhg pybfrq\", subcount[15])\n\n    for i in range(34):\n        regexs[19].search(r\"gno2\")\n        regexs[19].search(r\"gno3\")\n        regexs[8].search(r\"44132r503660\")\n        regexs[8].search(r\"SbeprqRkcvengvba=633669316860113296\")\n        regexs[8].search(r\"AFP_zp_dfctwzs-aowb_80=44132r503660\")\n        regexs[8].search(\n            r\"FrffvbaQQS2=s6r4579npn4rn2135s904r0s75pp1o5334p6s6pospo12696\"\n        )\n        regexs[8].search(r\"s6r4579npn4rn2135s904r0s75pp1o5334p6s6pospo12696\")\n\n    for i in range(32):\n        re.search(r\"puebzr\", strings[0], re.IGNORECASE)\n\n    for i in range(31):\n        regexs[23].sub(r\"\", \"uggc://jjj.snprobbx.pbz/\", subcount[23])\n        regexs[8].search(r\"SbeprqRkcvengvba=633669358527244818\")\n        regexs[8].search(r\"VC=66.249.85.130\")\n        regexs[8].search(\n            r\"FrffvbaQQS2=s15q53p9n372sn76npr13o271n4s3p5r29p235746p908p58\"\n        )\n        regexs[8].search(r\"s15q53p9n372sn76npr13o271n4s3p5r29p235746p908p58\")\n        regexs[24].search(r\"uggc://jjj.snprobbx.pbz/\")\n\n    for i in range(30):\n        regexs[6].sub(r\"\", \"419\", subcount[6])\n        re.search(r\"(?:^|\\s+)gvzrfgnzc(?:\\s+|$)\", \"gvzrfgnzc\")\n        regexs[7].search(r\"419\")\n\n    for i in range(29):\n        regexs[23].sub(r\"\", \"uggc://jjj.snprobbx.pbz/ybtva.cuc\", subcount[23])\n\n    for i in range(28):\n        regexs[25].sub(r\"\", \"Funer guvf tnqtrg\", subcount[25])\n        regexs[12].sub(r\"\", \"Funer guvf tnqtrg\", subcount[12])\n        regexs[26].search(r\"uggc://jjj.tbbtyr.pbz/vt/qverpgbel\")\n\n\ndef block3():\n    for i in range(27):\n        re.sub(r\"[A-Za-z]\", \"\", \"e115\", 0)\n\n    for i in range(23):\n        regexs[27].sub(r\"\", \"qvfcynl\", subcount[27])\n        regexs[27].sub(r\"\", \"cbfvgvba\", subcount[27])\n\n    for i in range(22):\n        regexs[14].sub(r\"\", \"unaqyr\", subcount[14])\n        regexs[15].sub(r\"\", \"unaqyr\", subcount[15])\n        regexs[14].sub(r\"\", \"yvar\", subcount[14])\n        regexs[15].sub(r\"\", \"yvar\", subcount[15])\n        regexs[14].sub(r\"\", \"cnerag puebzr6 fvatyr1 gno\", subcount[14])\n        regexs[15].sub(r\"\", \"cnerag puebzr6 fvatyr1 gno\", subcount[15])\n        regexs[14].sub(r\"\", \"fyvqre\", subcount[14])\n        regexs[15].sub(r\"\", \"fyvqre\", subcount[15])\n        regexs[28].search(r\"\")\n\n    for i in range(21):\n        regexs[12].sub(r\"\", \"uggc://jjj.zlfcnpr.pbz/\", subcount[12])\n        regexs[13].search(r\"uggc://jjj.zlfcnpr.pbz/\")\n\n    for i in range(20):\n        regexs[29].sub(r\"\", \"cntrivrj\", subcount[29])\n        regexs[30].sub(r\"\", \"cntrivrj\", subcount[30])\n        regexs[19].search(r\"ynfg\")\n        regexs[19].search(r\"ba svefg\")\n        regexs[8].search(r\"VC=74.125.75.3\")\n\n    for i in range(19):\n        regexs[31].search(r\"ra\")\n\n    for i in range(18):\n        regexs[32].split(strings[10])\n        regexs[32].split(strings[11])\n        regexs[33].sub(r\"\", strings[12], subcount[33])\n        regexs[8].search(r\"144631658.0.10.1231363570\")\n        regexs[8].search(\n            r\"144631658.1231363570.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)\"\n        )\n        regexs[8].search(\n            r\"144631658.3426875219718084000.1231363570.1231363570.1231363570.1\"\n        )\n        regexs[8].search(strings[13])\n        regexs[8].search(strings[14])\n        regexs[8].search(\n            r\"__hgzn=144631658.3426875219718084000.1231363570.1231363570.1231363570.1\"\n        )\n        regexs[8].search(r\"__hgzo=144631658.0.10.1231363570\")\n        regexs[8].search(\n            r\"__hgzm=144631658.1231363570.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)\"\n        )\n        regexs[34].search(strings[10])\n        regexs[34].search(strings[11])\n\n    for i in range(17):\n        re.match(r\"zfvr\", strings[0], re.IGNORECASE)\n        re.match(r\"bcren\", strings[0], re.IGNORECASE)\n        regexs[32].split(strings[15])\n        regexs[32].split(strings[16])\n        regexs[14].sub(r\"\", \"ohggba\", subcount[14])\n        regexs[15].sub(r\"\", \"ohggba\", subcount[15])\n        regexs[14].sub(r\"\", \"puvyq p1 svefg sylbhg pybfrq\", subcount[14])\n        regexs[15].sub(r\"\", \"puvyq p1 svefg sylbhg pybfrq\", subcount[15])\n        regexs[14].sub(r\"\", \"pvgvrf\", subcount[14])\n        regexs[15].sub(r\"\", \"pvgvrf\", subcount[15])\n        regexs[14].sub(r\"\", \"pybfrq\", subcount[14])\n        regexs[15].sub(r\"\", \"pybfrq\", subcount[15])\n        regexs[14].sub(r\"\", \"qry\", subcount[14])\n        regexs[15].sub(r\"\", \"qry\", subcount[15])\n        regexs[14].sub(r\"\", \"uqy_zba\", subcount[14])\n        regexs[15].sub(r\"\", \"uqy_zba\", subcount[15])\n        regexs[33].sub(r\"\", strings[17], subcount[33])\n        re.sub(r\"%3P\", \"\", strings[18], 0)\n        re.sub(r\"%3R\", \"\", strings[18], 0)\n        re.sub(r\"%3q\", \"\", strings[18], 0)\n        regexs[35].sub(r\"\", strings[18], subcount[35])\n        regexs[14].sub(r\"\", \"yvaxyvfg16\", subcount[14])\n        regexs[15].sub(r\"\", \"yvaxyvfg16\", subcount[15])\n        regexs[14].sub(r\"\", \"zvahf\", subcount[14])\n        regexs[15].sub(r\"\", \"zvahf\", subcount[15])\n        regexs[14].sub(r\"\", \"bcra\", subcount[14])\n        regexs[15].sub(r\"\", \"bcra\", subcount[15])\n        regexs[14].sub(r\"\", \"cnerag puebzr5 fvatyr1 ps NU\", subcount[14])\n        regexs[15].sub(r\"\", \"cnerag puebzr5 fvatyr1 ps NU\", subcount[15])\n        regexs[14].sub(r\"\", \"cynlre\", subcount[14])\n        regexs[15].sub(r\"\", \"cynlre\", subcount[15])\n        regexs[14].sub(r\"\", \"cyhf\", subcount[14])\n        regexs[15].sub(r\"\", \"cyhf\", subcount[15])\n        regexs[14].sub(r\"\", \"cb_uqy\", subcount[14])\n        regexs[15].sub(r\"\", \"cb_uqy\", subcount[15])\n        regexs[14].sub(r\"\", \"hyJVzt\", subcount[14])\n        regexs[15].sub(r\"\", \"hyJVzt\", subcount[15])\n        regexs[8].search(r\"144631658.0.10.1231363638\")\n        regexs[8].search(\n            r\"144631658.1231363638.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)\"\n        )\n        regexs[8].search(\n            r\"144631658.965867047679498800.1231363638.1231363638.1231363638.1\"\n        )\n        regexs[8].search(r\"4413268q3660\")\n        regexs[8].search(r\"4ss747o77904333q374or84qrr1s9r0nprp8r5q81534o94n\")\n        regexs[8].search(r\"SbeprqRkcvengvba=633669321699093060\")\n        regexs[8].search(r\"VC=74.125.75.20\")\n        regexs[8].search(strings[19])\n        regexs[8].search(strings[20])\n        regexs[8].search(r\"AFP_zp_tfwsbrg-aowb_80=4413268q3660\")\n        regexs[8].search(\n            r\"FrffvbaQQS2=4ss747o77904333q374or84qrr1s9r0nprp8r5q81534o94n\"\n        )\n        regexs[8].search(\n            r\"__hgzn=144631658.965867047679498800.1231363638.1231363638.1231363638.1\"\n        )\n        regexs[8].search(r\"__hgzo=144631658.0.10.1231363638\")\n        regexs[8].search(\n            r\"__hgzm=144631658.1231363638.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)\"\n        )\n        regexs[34].search(strings[15])\n        regexs[34].search(strings[16])\n\n\ndef block4():\n    for i in range(16):\n        re.sub(r\"\\*\", \"\", \"\", 0)\n        re.search(r\"\\bnpgvir\\b\", \"npgvir\")\n        re.search(r\"sversbk\", strings[0], re.IGNORECASE)\n        regexs[36].search(r\"glcr\")\n        re.search(r\"zfvr\", strings[0], re.IGNORECASE)\n        re.search(r\"bcren\", strings[0], re.IGNORECASE)\n\n    for i in range(15):\n        regexs[32].split(strings[21])\n        regexs[32].split(strings[22])\n        regexs[12].sub(r\"\", \"uggc://ohyyrgvaf.zlfcnpr.pbz/vaqrk.psz\", subcount[12])\n        regexs[33].sub(r\"\", strings[23], subcount[33])\n        regexs[37].sub(r\"\", \"yv\", subcount[37])\n        regexs[18].sub(r\"\", \"yv\", subcount[18])\n        regexs[8].search(r\"144631658.0.10.1231367822\")\n        regexs[8].search(\n            r\"144631658.1231367822.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)\"\n        )\n        regexs[8].search(\n            r\"144631658.4127520630321984500.1231367822.1231367822.1231367822.1\"\n        )\n        regexs[8].search(strings[24])\n        regexs[8].search(strings[25])\n        regexs[8].search(\n            r\"__hgzn=144631658.4127520630321984500.1231367822.1231367822.1231367822.1\"\n        )\n        regexs[8].search(r\"__hgzo=144631658.0.10.1231367822\")\n        regexs[8].search(\n            r\"__hgzm=144631658.1231367822.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)\"\n        )\n        regexs[34].search(strings[21])\n        regexs[34].search(strings[22])\n\n        # FIXME\n        # The \\{0,65534} should be a *\n        # There's a current python bug that will stop the regex compilation\n        # when a * appears there http://bugs.python.org/issue6156.\n        re.search(\n            r'\\.([\\w-]+)|\\[(\\w+)(?:([!*^$~|]?=)[\"\\']?(.*?)[\"\\']?)?\\]|:([\\w-]+)(?:\\([\"\\']?(.\\{0,65534}?)?[\"\\']?\\)|$)',\n            strings[26],\n        )\n\n        regexs[13].search(r\"uggc://ohyyrgvaf.zlfcnpr.pbz/vaqrk.psz\")\n        regexs[38].search(r\"yv\")\n\n    for i in range(14):\n        regexs[18].sub(r\"\", \"\", subcount[18])\n        re.sub(r\"(\\s+e|\\s+o[0-9]+)\", \"\", \"9.0  e115\", 1)\n        re.sub(r\"<\", \"\", \"Funer guvf tnqtrg\", 0)\n        re.sub(r\">\", \"\", \"Funer guvf tnqtrg\", 0)\n        regexs[39].sub(r\"\", \"Funer guvf tnqtrg\", subcount[39])\n        regexs[12].sub(r\"\", \"uggc://cebsvyrrqvg.zlfcnpr.pbz/vaqrk.psz\", subcount[12])\n        regexs[40].sub(r\"\", \"grnfre\", subcount[40])\n        regexs[41].sub(r\"\", \"grnfre\", subcount[41])\n        regexs[42].sub(r\"\", \"grnfre\", subcount[42])\n        regexs[43].sub(r\"\", \"grnfre\", subcount[43])\n        regexs[44].sub(r\"\", \"grnfre\", subcount[44])\n        regexs[45].sub(r\"\", \"grnfre\", subcount[45])\n        regexs[46].sub(r\"\", \"grnfre\", subcount[46])\n        regexs[47].sub(r\"\", \"grnfre\", subcount[47])\n        regexs[48].sub(r\"\", \"grnfre\", subcount[48])\n        regexs[16].search(r\"znetva-gbc\")\n        regexs[16].search(r\"cbfvgvba\")\n        regexs[19].search(r\"gno1\")\n        regexs[9].search(r\"qz\")\n        regexs[9].search(r\"qg\")\n        regexs[9].search(r\"zbqobk\")\n        regexs[9].search(r\"zbqobkva\")\n        regexs[9].search(r\"zbqgvgyr\")\n        regexs[13].search(r\"uggc://cebsvyrrqvg.zlfcnpr.pbz/vaqrk.psz\")\n        regexs[26].search(r\"/vt/znvytnqtrg\")\n        regexs[49].search(r\"glcr\")\n\n\ndef block5():\n    for i in range(13):\n        regexs[14].sub(r\"\", \"purpx\", subcount[14])\n        regexs[15].sub(r\"\", \"purpx\", subcount[15])\n        regexs[14].sub(r\"\", \"pvgl\", subcount[14])\n        regexs[15].sub(r\"\", \"pvgl\", subcount[15])\n        regexs[14].sub(r\"\", \"qrpe fyvqrgrkg\", subcount[14])\n        regexs[15].sub(r\"\", \"qrpe fyvqrgrkg\", subcount[15])\n        regexs[14].sub(r\"\", \"svefg fryrpgrq\", subcount[14])\n        regexs[15].sub(r\"\", \"svefg fryrpgrq\", subcount[15])\n        regexs[14].sub(r\"\", \"uqy_rag\", subcount[14])\n        regexs[15].sub(r\"\", \"uqy_rag\", subcount[15])\n        regexs[14].sub(r\"\", \"vape fyvqrgrkg\", subcount[14])\n        regexs[15].sub(r\"\", \"vape fyvqrgrkg\", subcount[15])\n        regexs[5].sub(r\"\", \"vachggrkg QBZPbageby_cynprubyqre\", subcount[5])\n        regexs[14].sub(r\"\", \"cnerag puebzr6 fvatyr1 gno fryrpgrq\", subcount[14])\n        regexs[15].sub(r\"\", \"cnerag puebzr6 fvatyr1 gno fryrpgrq\", subcount[15])\n        regexs[14].sub(r\"\", \"cb_guz\", subcount[14])\n        regexs[15].sub(r\"\", \"cb_guz\", subcount[15])\n        regexs[14].sub(r\"\", \"fhozvg\", subcount[14])\n        regexs[15].sub(r\"\", \"fhozvg\", subcount[15])\n        regexs[50].search(r\"\")\n        re.search(r\"NccyrJroXvg\\/([^\\s]*)\", strings[0])\n        re.search(r\"XUGZY\", strings[0])\n\n    for i in range(12):\n        re.sub(r\"(\\$\\{cebg\\})|(\\$cebg\\b)\", \"\", \"${cebg}://${ubfg}${cngu}/${dz}\", 0)\n        regexs[40].sub(r\"\", \"1\", subcount[40])\n        regexs[10].sub(r\"\", \"1\", subcount[10])\n        regexs[51].sub(r\"\", \"1\", subcount[51])\n        regexs[52].sub(r\"\", \"1\", subcount[52])\n        regexs[53].sub(r\"\", \"1\", subcount[53])\n        regexs[39].sub(r\"\", \"1\", subcount[39])\n        regexs[54].sub(r\"\", \"1\", subcount[54])\n        re.sub(r\"^(.*)\\..*$\", \"\", \"9.0  e115\", 1)\n        re.sub(r\"^.*e(.*)$\", \"\", \"9.0  e115\", 1)\n        regexs[55].sub(r\"\", \"<!-- ${nqiHey} -->\", subcount[55])\n        regexs[55].sub(\n            r\"\",\n            '<fpevcg glcr=\"grkg/wninfpevcg\" fep=\"${nqiHey}\"></fpevcg>',\n            subcount[55],\n        )\n        re.sub(r\"^.*\\s+(\\S+\\s+\\S+$)\", \"\", strings[1], 1)\n        regexs[30].sub(r\"\", \"tzk%2Subzrcntr%2Sfgneg%2Sqr%2S\", subcount[30])\n        regexs[30].sub(r\"\", \"tzk\", subcount[30])\n        re.sub(r\"(\\$\\{ubfg\\})|(\\$ubfg\\b)\", \"\", \"uggc://${ubfg}${cngu}/${dz}\", 0)\n        regexs[56].sub(r\"\", \"uggc://nqpyvrag.hvzfrei.arg${cngu}/${dz}\", subcount[56])\n        re.sub(r\"(\\$\\{dz\\})|(\\$dz\\b)\", \"\", \"uggc://nqpyvrag.hvzfrei.arg/wf.at/${dz}\", 0)\n        regexs[29].sub(r\"\", \"frpgvba\", subcount[29])\n        regexs[30].sub(r\"\", \"frpgvba\", subcount[30])\n        regexs[29].sub(r\"\", \"fvgr\", subcount[29])\n        regexs[30].sub(r\"\", \"fvgr\", subcount[30])\n        regexs[29].sub(r\"\", \"fcrpvny\", subcount[29])\n        regexs[30].sub(r\"\", \"fcrpvny\", subcount[30])\n        regexs[36].search(r\"anzr\")\n        re.search(r\"e\", \"9.0  e115\")\n\n\ndef block6():\n    for i in range(11):\n        re.sub(r\"(?i)##yv0##\", \"\", strings[27], 0)\n        regexs[57].sub(r\"\", strings[27], subcount[57])\n        regexs[58].sub(r\"\", strings[28], subcount[58])\n        regexs[59].sub(r\"\", strings[29], subcount[59])\n        re.sub(r\"(?i)##\\/o##\", \"\", strings[30], 0)\n        re.sub(r\"(?i)##\\/v##\", \"\", strings[30], 0)\n        re.sub(r\"(?i)##\\/h##\", \"\", strings[30], 0)\n        re.sub(r\"(?i)##o##\", \"\", strings[30], 0)\n        re.sub(r\"(?i)##oe##\", \"\", strings[30], 0)\n        re.sub(r\"(?i)##v##\", \"\", strings[30], 0)\n        re.sub(r\"(?i)##h##\", \"\", strings[30], 0)\n        re.sub(r\"(?i)##n##\", \"\", strings[31], 0)\n        re.sub(r\"(?i)##\\/n##\", \"\", strings[32], 0)\n\n        # This prints a unicode escape where the V8 version\n        # prints the unicode character.\n        re.sub(r\"#~#argjbexybtb#~#\", \"\", strings[33], 0)\n\n        re.search(r\" Zbovyr\\/\", strings[0])\n        re.search(r\"##yv1##\", strings[27], re.IGNORECASE)\n        re.search(r\"##yv10##\", strings[28], re.IGNORECASE)\n        re.search(r\"##yv11##\", strings[28], re.IGNORECASE)\n        re.search(r\"##yv12##\", strings[28], re.IGNORECASE)\n        re.search(r\"##yv13##\", strings[28], re.IGNORECASE)\n        re.search(r\"##yv14##\", strings[28], re.IGNORECASE)\n        re.search(r\"##yv15##\", strings[28], re.IGNORECASE)\n        regexs[58].search(strings[28])\n        re.search(r\"##yv17##\", strings[29], re.IGNORECASE)\n        re.search(r\"##yv18##\", strings[29], re.IGNORECASE)\n        regexs[59].search(strings[29])\n        re.search(r\"##yv2##\", strings[27], re.IGNORECASE)\n        re.search(r\"##yv20##\", strings[30], re.IGNORECASE)\n        re.search(r\"##yv21##\", strings[30], re.IGNORECASE)\n        re.search(r\"##yv22##\", strings[30], re.IGNORECASE)\n        re.search(r\"##yv23##\", strings[30], re.IGNORECASE)\n        re.search(r\"##yv3##\", strings[27], re.IGNORECASE)\n        regexs[57].search(strings[27])\n        re.search(r\"##yv5##\", strings[28], re.IGNORECASE)\n        re.search(r\"##yv6##\", strings[28], re.IGNORECASE)\n        re.search(r\"##yv7##\", strings[28], re.IGNORECASE)\n        re.search(r\"##yv8##\", strings[28], re.IGNORECASE)\n        re.search(r\"##yv9##\", strings[28], re.IGNORECASE)\n        regexs[8].search(r\"473qq1rs0n2r70q9qo1pq48n021s9468ron90nps048p4p29\")\n        regexs[8].search(r\"SbeprqRkcvengvba=633669325184628362\")\n        regexs[8].search(\n            r\"FrffvbaQQS2=473qq1rs0n2r70q9qo1pq48n021s9468ron90nps048p4p29\"\n        )\n        re.search(r\"AbxvnA[^\\/]*\", strings[0])\n\n    for i in range(10):\n        re.sub(r\"(?:^|\\s+)bss(?:\\s+|$)\", \"\", \" bss\", 0)\n        re.sub(r\"(\\$\\{0\\})|(\\$0\\b)\", \"\", strings[34], 0)\n        re.sub(r\"(\\$\\{1\\})|(\\$1\\b)\", \"\", strings[34], 0)\n        re.sub(r\"(\\$\\{pbzcyrgr\\})|(\\$pbzcyrgr\\b)\", \"\", strings[34], 0)\n        re.sub(r\"(\\$\\{sentzrag\\})|(\\$sentzrag\\b)\", \"\", strings[34], 0)\n        re.sub(r\"(\\$\\{ubfgcbeg\\})|(\\$ubfgcbeg\\b)\", \"\", strings[34], 0)\n        regexs[56].sub(r\"\", strings[34], subcount[56])\n        re.sub(r\"(\\$\\{cebgbpby\\})|(\\$cebgbpby\\b)\", \"\", strings[34], 0)\n        re.sub(r\"(\\$\\{dhrel\\})|(\\$dhrel\\b)\", \"\", strings[34], 0)\n        regexs[29].sub(r\"\", \"nqfvmr\", subcount[29])\n        regexs[30].sub(r\"\", \"nqfvmr\", subcount[30])\n        re.sub(r\"(\\$\\{2\\})|(\\$2\\b)\", \"\", \"uggc://${2}${3}${4}${5}\", 0)\n        re.sub(r\"(\\$\\{3\\})|(\\$3\\b)\", \"\", \"uggc://wf.hv-cbegny.qr${3}${4}${5}\", 0)\n        regexs[40].sub(r\"\", \"arjf\", subcount[40])\n        regexs[41].sub(r\"\", \"arjf\", subcount[41])\n        regexs[42].sub(r\"\", \"arjf\", subcount[42])\n        regexs[43].sub(r\"\", \"arjf\", subcount[43])\n        regexs[44].sub(r\"\", \"arjf\", subcount[44])\n        regexs[45].sub(r\"\", \"arjf\", subcount[45])\n        regexs[46].sub(r\"\", \"arjf\", subcount[46])\n        regexs[47].sub(r\"\", \"arjf\", subcount[47])\n        regexs[48].sub(r\"\", \"arjf\", subcount[48])\n        re.search(r\" PC=i=(\\d+)&oe=(.)\", strings[35])\n        regexs[60].search(r\" \")\n        regexs[60].search(r\" bss\")\n        regexs[60].search(r\"\")\n        regexs[19].search(r\" \")\n        regexs[19].search(r\"svefg ba\")\n        regexs[19].search(r\"ynfg vtaber\")\n        regexs[19].search(r\"ba\")\n        regexs[9].search(r\"scnq so \")\n        regexs[9].search(r\"zrqvgobk\")\n        regexs[9].search(r\"hsgy\")\n        regexs[9].search(r\"lhv-h\")\n        re.search(r\"Fnsnev|Xbadhrebe|XUGZY\", strings[0], re.IGNORECASE)\n        regexs[61].search(r\"uggc://wf.hv-cbegny.qr/tzk/ubzr/wf/20080602/onfr.wf\")\n        regexs[62].search(r\"#Ybtva_rznvy\")\n\n\ndef block7():\n    for i in range(9):\n        regexs[40].sub(r\"\", \"0\", subcount[40])\n        regexs[10].sub(r\"\", \"0\", subcount[10])\n        regexs[51].sub(r\"\", \"0\", subcount[51])\n        regexs[52].sub(r\"\", \"0\", subcount[52])\n        regexs[53].sub(r\"\", \"0\", subcount[53])\n        regexs[39].sub(r\"\", \"0\", subcount[39])\n        regexs[54].sub(r\"\", \"0\", subcount[54])\n        regexs[40].sub(r\"\", \"Lrf\", subcount[40])\n        regexs[10].sub(r\"\", \"Lrf\", subcount[10])\n        regexs[51].sub(r\"\", \"Lrf\", subcount[51])\n        regexs[52].sub(r\"\", \"Lrf\", subcount[52])\n        regexs[53].sub(r\"\", \"Lrf\", subcount[53])\n        regexs[39].sub(r\"\", \"Lrf\", subcount[39])\n        regexs[54].sub(r\"\", \"Lrf\", subcount[54])\n\n    for i in range(8):\n        regexs[63].sub(r\"\", \"Pybfr {0}\", subcount[63])\n        regexs[63].sub(r\"\", \"Bcra {0}\", subcount[63])\n        regexs[32].split(strings[36])\n        regexs[32].split(strings[37])\n        regexs[14].sub(r\"\", \"puvyq p1 svefg gnournqref\", subcount[14])\n        regexs[15].sub(r\"\", \"puvyq p1 svefg gnournqref\", subcount[15])\n        regexs[14].sub(r\"\", \"uqy_fcb\", subcount[14])\n        regexs[15].sub(r\"\", \"uqy_fcb\", subcount[15])\n        regexs[14].sub(r\"\", \"uvag\", subcount[14])\n        regexs[15].sub(r\"\", \"uvag\", subcount[15])\n        regexs[33].sub(r\"\", strings[38], subcount[33])\n        regexs[14].sub(r\"\", \"yvfg\", subcount[14])\n        regexs[15].sub(r\"\", \"yvfg\", subcount[15])\n        regexs[30].sub(r\"\", \"at_bhgre\", subcount[30])\n        regexs[14].sub(r\"\", \"cnerag puebzr5 qbhoyr2 NU\", subcount[14])\n        regexs[15].sub(r\"\", \"cnerag puebzr5 qbhoyr2 NU\", subcount[15])\n        regexs[14].sub(r\"\", \"cnerag puebzr5 dhnq5 ps NU osyvax zbarl\", subcount[14])\n        regexs[15].sub(r\"\", \"cnerag puebzr5 dhnq5 ps NU osyvax zbarl\", subcount[15])\n        regexs[14].sub(r\"\", \"cnerag puebzr6 fvatyr1\", subcount[14])\n        regexs[15].sub(r\"\", \"cnerag puebzr6 fvatyr1\", subcount[15])\n        regexs[14].sub(r\"\", \"cb_qrs\", subcount[14])\n        regexs[15].sub(r\"\", \"cb_qrs\", subcount[15])\n        regexs[14].sub(r\"\", \"gnopbagrag\", subcount[14])\n        regexs[15].sub(r\"\", \"gnopbagrag\", subcount[15])\n        regexs[30].sub(r\"\", \"iv_svefg_gvzr\", subcount[30])\n        re.search(\n            r\"(^|.)(ronl|qri-ehf3.wbg)(|fgberf|zbgbef|yvirnhpgvbaf|jvxv|rkcerff|punggre).(pbz(|.nh|.pa|.ux|.zl|.ft|.oe|.zk)|pb(.hx|.xe|.am)|pn|qr|se|vg|ay|or|ng|pu|vr|va|rf|cy|cu|fr)$\",\n            \"cntrf.ronl.pbz\",\n            re.IGNORECASE,\n        )\n        regexs[8].search(r\"144631658.0.10.1231364074\")\n        regexs[8].search(\n            r\"144631658.1231364074.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)\"\n        )\n        regexs[8].search(\n            r\"144631658.2294274870215848400.1231364074.1231364074.1231364074.1\"\n        )\n        regexs[8].search(r\"4413241q3660\")\n        regexs[8].search(r\"SbeprqRkcvengvba=633669357391353591\")\n        regexs[8].search(strings[39])\n        regexs[8].search(strings[40])\n        regexs[8].search(r\"AFP_zp_kkk-gdzogv_80=4413241q3660\")\n        regexs[8].search(\n            r\"FrffvbaQQS2=p98s8o9q42nr21or1r61pqorn1n002nsss569635984s6qp7\"\n        )\n        regexs[8].search(\n            r\"__hgzn=144631658.2294274870215848400.1231364074.1231364074.1231364074.1\"\n        )\n        regexs[8].search(r\"__hgzo=144631658.0.10.1231364074\")\n        regexs[8].search(\n            r\"__hgzm=144631658.1231364074.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)\"\n        )\n        regexs[8].search(r\"p98s8o9q42nr21or1r61pqorn1n002nsss569635984s6qp7\")\n        regexs[34].search(strings[36])\n        regexs[34].search(strings[37])\n\n\ndef block8():\n    for i in range(7):\n        re.match(r\"\\d+\", strings[1])\n        regexs[64].sub(r\"\", \"nsgre\", subcount[64])\n        regexs[64].sub(r\"\", \"orsber\", subcount[64])\n        regexs[64].sub(r\"\", \"obggbz\", subcount[64])\n        regexs[65].sub(r\"\", \"ohvygva_jrngure.kzy\", subcount[65])\n        regexs[37].sub(r\"\", \"ohggba\", subcount[37])\n        regexs[18].sub(r\"\", \"ohggba\", subcount[18])\n        regexs[65].sub(r\"\", \"qngrgvzr.kzy\", subcount[65])\n        regexs[65].sub(r\"\", \"uggc://eff.paa.pbz/eff/paa_gbcfgbevrf.eff\", subcount[65])\n        regexs[37].sub(r\"\", \"vachg\", subcount[37])\n        regexs[18].sub(r\"\", \"vachg\", subcount[18])\n        regexs[64].sub(r\"\", \"vafvqr\", subcount[64])\n        regexs[27].sub(r\"\", \"cbvagre\", subcount[27])\n        re.sub(r\"[A-Z]\", \"\", \"cbfvgvba\", 0)\n        regexs[27].sub(r\"\", \"gbc\", subcount[27])\n        regexs[64].sub(r\"\", \"gbc\", subcount[64])\n        regexs[37].sub(r\"\", \"hy\", subcount[37])\n        regexs[18].sub(r\"\", \"hy\", subcount[18])\n        regexs[37].sub(r\"\", strings[26], subcount[37])\n        regexs[18].sub(r\"\", strings[26], subcount[18])\n        regexs[65].sub(r\"\", \"lbhghor_vtbbtyr/i2/lbhghor.kzy\", subcount[65])\n        regexs[27].sub(r\"\", \"m-vaqrk\", subcount[27])\n        re.search(r\"#([\\w-]+)\", strings[26])\n        regexs[16].search(r\"urvtug\")\n        regexs[16].search(r\"znetvaGbc\")\n        regexs[16].search(r\"jvqgu\")\n        regexs[19].search(r\"gno0 svefg ba\")\n        regexs[19].search(r\"gno0 ba\")\n        regexs[19].search(r\"gno4 ynfg\")\n        regexs[19].search(r\"gno4\")\n        regexs[19].search(r\"gno5\")\n        regexs[19].search(r\"gno6\")\n        regexs[19].search(r\"gno7\")\n        regexs[19].search(r\"gno8\")\n        re.search(r\"NqborNVE\\/([^\\s]*)\", strings[0])\n        re.search(r\"NccyrJroXvg\\/([^ ]*)\", strings[0])\n        re.search(r\"XUGZY\", strings[0], re.IGNORECASE)\n        re.search(r\"^(?:obql|ugzy)$\", \"YV\", re.IGNORECASE)\n        regexs[38].search(r\"ohggba\")\n        regexs[38].search(r\"vachg\")\n        regexs[38].search(r\"hy\")\n        regexs[38].search(strings[26])\n        re.search(r\"^(\\w+|\\*)\", strings[26])\n        re.search(r\"znp|jva|yvahk\", \"Jva32\", re.IGNORECASE)\n        re.search(r\"eton?\\([\\d\\s,]+\\)\", \"fgngvp\")\n\n    for i in range(6):\n        re.sub(r\"\\r\", \"\", \"\", 0)\n        regexs[40].sub(r\"\", \"/\", subcount[40])\n        regexs[10].sub(r\"\", \"/\", subcount[10])\n        regexs[51].sub(r\"\", \"/\", subcount[51])\n        regexs[52].sub(r\"\", \"/\", subcount[52])\n        regexs[53].sub(r\"\", \"/\", subcount[53])\n        regexs[39].sub(r\"\", \"/\", subcount[39])\n        regexs[54].sub(r\"\", \"/\", subcount[54])\n        regexs[63].sub(\n            r\"\",\n            \"uggc://zfacbegny.112.2b7.arg/o/ff/zfacbegnyubzr/1/U.7-cqi-2/{0}?[NDO]&{1}&{2}&[NDR]\",\n            subcount[63],\n        )\n        regexs[12].sub(r\"\", strings[41], subcount[12])\n        regexs[23].sub(r\"\", \"uggc://jjj.snprobbx.pbz/fepu.cuc\", subcount[23])\n        regexs[40].sub(r\"\", \"freivpr\", subcount[40])\n        regexs[41].sub(r\"\", \"freivpr\", subcount[41])\n        regexs[42].sub(r\"\", \"freivpr\", subcount[42])\n        regexs[43].sub(r\"\", \"freivpr\", subcount[43])\n        regexs[44].sub(r\"\", \"freivpr\", subcount[44])\n        regexs[45].sub(r\"\", \"freivpr\", subcount[45])\n        regexs[46].sub(r\"\", \"freivpr\", subcount[46])\n        regexs[47].sub(r\"\", \"freivpr\", subcount[47])\n        regexs[48].sub(r\"\", \"freivpr\", subcount[48])\n        re.search(r\"((ZFVR\\s+([6-9]|\\d\\d)\\.))\", strings[0])\n        regexs[66].search(r\"\")\n        regexs[50].search(r\"fryrpgrq\")\n        regexs[8].search(r\"8sqq78r9n442851q565599o401385sp3s04r92rnn7o19ssn\")\n        regexs[8].search(r\"SbeprqRkcvengvba=633669340386893867\")\n        regexs[8].search(r\"VC=74.125.75.17\")\n        regexs[8].search(\n            r\"FrffvbaQQS2=8sqq78r9n442851q565599o401385sp3s04r92rnn7o19ssn\"\n        )\n        re.search(r\"Xbadhrebe|Fnsnev|XUGZY\", strings[0])\n        regexs[13].search(strings[41])\n        regexs[49].search(r\"unfsbphf\")\n\n\ndef block9():\n    for i in range(5):\n        regexs[32].split(strings[42])\n        regexs[32].split(strings[43])\n        regexs[20].split(r\"svz_zlfcnpr_hfre-ivrj-pbzzragf,svz_zlfcnpr_havgrq-fgngrf\")\n        regexs[33].sub(r\"\", strings[44], subcount[33])\n        regexs[67].sub(r\"\", \"zrah_arj zrah_arj_gbttyr zrah_gbttyr\", subcount[67])\n        regexs[67].sub(r\"\", \"zrah_byq zrah_byq_gbttyr zrah_gbttyr\", subcount[67])\n        regexs[8].search(r\"102n9o0o9pq60132qn0337rr867p75953502q2s27s2s5r98\")\n        regexs[8].search(r\"144631658.0.10.1231364380\")\n        regexs[8].search(\n            r\"144631658.1231364380.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)\"\n        )\n        regexs[8].search(\n            r\"144631658.3931862196947939300.1231364380.1231364380.1231364380.1\"\n        )\n        regexs[8].search(r\"441326q33660\")\n        regexs[8].search(r\"SbeprqRkcvengvba=633669341278771470\")\n        regexs[8].search(strings[45])\n        regexs[8].search(strings[46])\n        regexs[8].search(r\"AFP_zp_dfctwzssrwh-aowb_80=441326q33660\")\n        regexs[8].search(\n            r\"FrffvbaQQS2=102n9o0o9pq60132qn0337rr867p75953502q2s27s2s5r98\"\n        )\n        regexs[8].search(\n            r\"__hgzn=144631658.3931862196947939300.1231364380.1231364380.1231364380.1\"\n        )\n        regexs[8].search(r\"__hgzo=144631658.0.10.1231364380\")\n        regexs[8].search(\n            r\"__hgzm=144631658.1231364380.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)\"\n        )\n\n    for i in range(4):\n        regexs[14].sub(r\"\", \" yvfg1\", subcount[14])\n        regexs[15].sub(r\"\", \" yvfg1\", subcount[15])\n        regexs[14].sub(r\"\", \" yvfg2\", subcount[14])\n        regexs[15].sub(r\"\", \" yvfg2\", subcount[15])\n        regexs[14].sub(r\"\", \" frneputebhc1\", subcount[14])\n        regexs[15].sub(r\"\", \" frneputebhc1\", subcount[15])\n        regexs[68].sub(r\"\", strings[47], subcount[68])\n        regexs[18].sub(r\"\", strings[47], subcount[18])\n        re.sub(r\"&\", \"\", \"\", 0)\n        regexs[35].sub(r\"\", \"\", subcount[35])\n        regexs[63].sub(r\"\", \"(..-{0})(|(d+)|)\", subcount[63])\n        regexs[18].sub(r\"\", strings[48], subcount[18])\n        regexs[56].sub(\n            r\"\", \"//vzt.jro.qr/vij/FC/${cngu}/${anzr}/${inyhr}?gf=${abj}\", subcount[56]\n        )\n        re.sub(\n            r\"(\\$\\{anzr\\})|(\\$anzr\\b)\",\n            \"\",\n            \"//vzt.jro.qr/vij/FC/tzk_uc/${anzr}/${inyhr}?gf=${abj}\",\n            0,\n        )\n        regexs[69].sub(\n            r\"\",\n            '<fcna pynff=\"urnq\"><o>Jvaqbjf Yvir Ubgznvy</o></fcna><fcna pynff=\"zft\">{1}</fcna>',\n            subcount[69],\n        )\n        regexs[63].sub(\n            r\"\",\n            '<fcna pynff=\"urnq\"><o>{0}</o></fcna><fcna pynff=\"zft\">{1}</fcna>',\n            subcount[63],\n        )\n        regexs[69].sub(\n            r\"\",\n            '<fcna pynff=\"fvtahc\"><n uers=uggc://jjj.ubgznvy.pbz><o>{1}</o></n></fcna>',\n            subcount[69],\n        )\n        regexs[63].sub(\n            r\"\", '<fcna pynff=\"fvtahc\"><n uers={0}><o>{1}</o></n></fcna>', subcount[63]\n        )\n        regexs[15].sub(r\"\", \"Vzntrf\", subcount[15])\n        regexs[15].sub(r\"\", \"ZFA\", subcount[15])\n        regexs[15].sub(r\"\", \"Zncf\", subcount[15])\n        regexs[39].sub(r\"\", \"Zbq-Vasb-Vasb-WninFpevcgUvag\", subcount[39])\n        regexs[15].sub(r\"\", \"Arjf\", subcount[15])\n        regexs[32].split(strings[49])\n        regexs[32].split(strings[50])\n        regexs[15].sub(r\"\", \"Ivqrb\", subcount[15])\n        regexs[15].sub(r\"\", \"Jro\", subcount[15])\n        regexs[39].sub(r\"\", \"n\", subcount[39])\n        regexs[70].split(r\"nwnkFgneg\")\n        regexs[70].split(r\"nwnkFgbc\")\n        regexs[14].sub(r\"\", \"ovaq\", subcount[14])\n        regexs[15].sub(r\"\", \"ovaq\", subcount[15])\n        regexs[63].sub(\n            r\"\",\n            \"oevatf lbh zber. Zber fcnpr (5TO), zber frphevgl, fgvyy serr.\",\n            subcount[63],\n        )\n        regexs[14].sub(r\"\", \"puvyq p1 svefg qrpx\", subcount[14])\n        regexs[15].sub(r\"\", \"puvyq p1 svefg qrpx\", subcount[15])\n        regexs[14].sub(r\"\", \"puvyq p1 svefg qbhoyr2\", subcount[14])\n        regexs[15].sub(r\"\", \"puvyq p1 svefg qbhoyr2\", subcount[15])\n        regexs[14].sub(r\"\", \"puvyq p2 ynfg\", subcount[14])\n        regexs[15].sub(r\"\", \"puvyq p2 ynfg\", subcount[15])\n        regexs[14].sub(r\"\", \"puvyq p2\", subcount[14])\n        regexs[15].sub(r\"\", \"puvyq p2\", subcount[15])\n        regexs[14].sub(r\"\", \"puvyq p3\", subcount[14])\n        regexs[15].sub(r\"\", \"puvyq p3\", subcount[15])\n        regexs[14].sub(r\"\", \"puvyq p4 ynfg\", subcount[14])\n        regexs[15].sub(r\"\", \"puvyq p4 ynfg\", subcount[15])\n        regexs[14].sub(r\"\", \"pbclevtug\", subcount[14])\n        regexs[15].sub(r\"\", \"pbclevtug\", subcount[15])\n        regexs[14].sub(r\"\", \"qZFAZR_1\", subcount[14])\n        regexs[15].sub(r\"\", \"qZFAZR_1\", subcount[15])\n        regexs[14].sub(r\"\", \"qbhoyr2 ps\", subcount[14])\n        regexs[15].sub(r\"\", \"qbhoyr2 ps\", subcount[15])\n        regexs[14].sub(r\"\", \"qbhoyr2\", subcount[14])\n        regexs[15].sub(r\"\", \"qbhoyr2\", subcount[15])\n        regexs[14].sub(r\"\", \"uqy_arj\", subcount[14])\n        regexs[15].sub(r\"\", \"uqy_arj\", subcount[15])\n        regexs[30].sub(r\"\", \"uc_fubccvatobk\", subcount[30])\n        regexs[29].sub(r\"\", \"ugzy%2Rvq\", subcount[29])\n        regexs[30].sub(r\"\", \"ugzy%2Rvq\", subcount[30])\n        regexs[33].sub(r\"\", strings[51], subcount[33])\n        regexs[71].sub(\n            r\"\",\n            \"uggc://wf.hv-cbegny.qr/tzk/ubzr/wf/20080602/cebgbglcr.wf${4}${5}\",\n            subcount[71],\n        )\n        regexs[72].sub(\n            r\"\",\n            \"uggc://wf.hv-cbegny.qr/tzk/ubzr/wf/20080602/cebgbglcr.wf${5}\",\n            subcount[72],\n        )\n        regexs[73].sub(r\"\", strings[52], subcount[73])\n        regexs[69].sub(\n            r\"\",\n            \"uggc://zfacbegny.112.2b7.arg/o/ff/zfacbegnyubzr/1/U.7-cqi-2/f55332979829981?[NDO]&{1}&{2}&[NDR]\",\n            subcount[69],\n        )\n        regexs[14].sub(r\"\", \"vztZFSG\", subcount[14])\n        regexs[15].sub(r\"\", \"vztZFSG\", subcount[15])\n        regexs[14].sub(r\"\", \"zfasbbg1 ps\", subcount[14])\n        regexs[15].sub(r\"\", \"zfasbbg1 ps\", subcount[15])\n        regexs[14].sub(r\"\", strings[53], subcount[14])\n        regexs[15].sub(r\"\", strings[53], subcount[15])\n        regexs[14].sub(r\"\", \"cnerag puebzr6 fvatyr1 gno fryrpgrq ovaq\", subcount[14])\n        regexs[15].sub(r\"\", \"cnerag puebzr6 fvatyr1 gno fryrpgrq ovaq\", subcount[15])\n        regexs[14].sub(r\"\", \"cevznel\", subcount[14])\n        regexs[15].sub(r\"\", \"cevznel\", subcount[15])\n        regexs[30].sub(r\"\", \"erpgnatyr\", subcount[30])\n        regexs[14].sub(r\"\", \"frpbaqnel\", subcount[14])\n        regexs[15].sub(r\"\", \"frpbaqnel\", subcount[15])\n        regexs[70].split(r\"haybnq\")\n        regexs[63].sub(r\"\", \"{0}{1}1\", subcount[63])\n        regexs[69].sub(r\"\", \"|{1}1\", subcount[69])\n        re.search(r\"(..-HF)(\\|(\\d+)|)\", \"xb-xe,ra-va,gu-gu\", re.IGNORECASE)\n        regexs[4].search(r\"/ZlFcnprNccf/NccPnainf,45000012\")\n        regexs[8].search(r\"144631658.0.10.1231367708\")\n        regexs[8].search(\n            r\"144631658.1231367708.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)\"\n        )\n        regexs[8].search(\n            r\"144631658.2770915348920628700.1231367708.1231367708.1231367708.1\"\n        )\n        regexs[8].search(r\"4413235p3660\")\n        regexs[8].search(r\"441327q73660\")\n        regexs[8].search(r\"9995p6rp12rrnr893334ro7nq70o7p64p69rqn844prs1473\")\n        regexs[8].search(r\"SbeprqRkcvengvba=633669350559478880\")\n        regexs[8].search(strings[54])\n        regexs[8].search(strings[55])\n        regexs[8].search(r\"AFP_zp_dfctwzs-aowb_80=441327q73660\")\n        regexs[8].search(r\"AFP_zp_kkk-aowb_80=4413235p3660\")\n        regexs[8].search(\n            r\"FrffvbaQQS2=9995p6rp12rrnr893334ro7nq70o7p64p69rqn844prs1473\"\n        )\n        regexs[8].search(\n            r\"__hgzn=144631658.2770915348920628700.1231367708.1231367708.1231367708.1\"\n        )\n        regexs[8].search(r\"__hgzo=144631658.0.10.1231367708\")\n        regexs[8].search(\n            r\"__hgzm=144631658.1231367708.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)\"\n        )\n        regexs[34].search(strings[49])\n        regexs[34].search(strings[50])\n        re.search(r\"ZFVR\\s+5[.]01\", strings[0])\n        re.search(r\"HF(?=;)\", strings[56], re.IGNORECASE)\n        regexs[74].search(strings[47])\n        regexs[28].search(r\"svefg npgvir svefgNpgvir\")\n        regexs[28].search(r\"ynfg\")\n        re.search(r\"\\bp:(..)\", \"m:94043|yn:37.4154|yb:-122.0585|p:HF\", re.IGNORECASE)\n        regexs[75].search(strings[57])\n        regexs[75].search(strings[58])\n        regexs[76].search(strings[57])\n        regexs[76].search(strings[58])\n        regexs[77].search(strings[57])\n        regexs[77].search(strings[58])\n        re.search(r\"\\bhfucce\\s*=\\s*([^;]*)\", strings[59], re.IGNORECASE)\n        regexs[78].search(strings[57])\n        regexs[78].search(strings[58])\n        re.search(r\"\\bjci\\s*=\\s*([^;]*)\", strings[59], re.IGNORECASE)\n        regexs[79].search(strings[58])\n        regexs[79].search(strings[60])\n        regexs[79].search(strings[59])\n        re.search(\n            r\"\\|p:([a-z]{2})\",\n            \"m:94043|yn:37.4154|yb:-122.0585|p:HF|ue:1\",\n            re.IGNORECASE,\n        )\n        regexs[80].search(strings[47])\n        regexs[61].search(r\"cebgbglcr.wf\")\n        regexs[68].search(strings[47])\n        regexs[81].search(strings[47])\n        regexs[82].search(strings[47])\n        re.search(r\"^Fubpxjnir Synfu (\\d)\", strings[1])\n        re.search(r\"^Fubpxjnir Synfu (\\d+)\", strings[1])\n        regexs[83].search(r\"[bowrpg tybony]\")\n        regexs[62].search(strings[47])\n        regexs[84].search(strings[61])\n        regexs[84].search(strings[62])\n        re.search(r\"jroxvg\", strings[63])\n\n\ndef block10():\n    for i in range(3):\n        regexs[39].sub(r\"\", \"%3Szxg=ra-HF\", subcount[39])\n        regexs[40].sub(r\"\", \"-8\", subcount[40])\n        regexs[10].sub(r\"\", \"-8\", subcount[10])\n        regexs[51].sub(r\"\", \"-8\", subcount[51])\n        regexs[52].sub(r\"\", \"-8\", subcount[52])\n        regexs[53].sub(r\"\", \"-8\", subcount[53])\n        regexs[39].sub(r\"\", \"-8\", subcount[39])\n        regexs[54].sub(r\"\", \"-8\", subcount[54])\n        regexs[40].sub(r\"\", \"1.5\", subcount[40])\n        regexs[10].sub(r\"\", \"1.5\", subcount[10])\n        regexs[51].sub(r\"\", \"1.5\", subcount[51])\n        regexs[52].sub(r\"\", \"1.5\", subcount[52])\n        regexs[53].sub(r\"\", \"1.5\", subcount[53])\n        regexs[39].sub(r\"\", \"1.5\", subcount[39])\n        regexs[54].sub(r\"\", \"1.5\", subcount[54])\n        regexs[40].sub(r\"\", \"1024k768\", subcount[40])\n        regexs[10].sub(r\"\", \"1024k768\", subcount[10])\n        regexs[51].sub(r\"\", \"1024k768\", subcount[51])\n        regexs[52].sub(r\"\", \"1024k768\", subcount[52])\n        regexs[53].sub(r\"\", \"1024k768\", subcount[53])\n        regexs[39].sub(r\"\", \"1024k768\", subcount[39])\n        regexs[54].sub(r\"\", \"1024k768\", subcount[54])\n        regexs[40].sub(r\"\", strings[64], subcount[40])\n        regexs[10].sub(r\"\", strings[64], subcount[10])\n        regexs[51].sub(r\"\", strings[64], subcount[51])\n        regexs[52].sub(r\"\", strings[64], subcount[52])\n        regexs[53].sub(r\"\", strings[64], subcount[53])\n        regexs[39].sub(r\"\", strings[64], subcount[39])\n        regexs[54].sub(r\"\", strings[64], subcount[54])\n        regexs[40].sub(r\"\", \"14\", subcount[40])\n        regexs[10].sub(r\"\", \"14\", subcount[10])\n        regexs[51].sub(r\"\", \"14\", subcount[51])\n        regexs[52].sub(r\"\", \"14\", subcount[52])\n        regexs[53].sub(r\"\", \"14\", subcount[53])\n        regexs[39].sub(r\"\", \"14\", subcount[39])\n        regexs[54].sub(r\"\", \"14\", subcount[54])\n        regexs[40].sub(r\"\", \"24\", subcount[40])\n        regexs[10].sub(r\"\", \"24\", subcount[10])\n        regexs[51].sub(r\"\", \"24\", subcount[51])\n        regexs[52].sub(r\"\", \"24\", subcount[52])\n        regexs[53].sub(r\"\", \"24\", subcount[53])\n        regexs[39].sub(r\"\", \"24\", subcount[39])\n        regexs[54].sub(r\"\", \"24\", subcount[54])\n        regexs[40].sub(r\"\", strings[65], subcount[40])\n        regexs[10].sub(r\"\", strings[65], subcount[10])\n        regexs[51].sub(r\"\", strings[65], subcount[51])\n        regexs[52].sub(r\"\", strings[65], subcount[52])\n        regexs[53].sub(r\"\", strings[65], subcount[53])\n        regexs[39].sub(r\"\", strings[65], subcount[39])\n        regexs[54].sub(r\"\", strings[65], subcount[54])\n        regexs[40].sub(r\"\", strings[66], subcount[40])\n        regexs[10].sub(r\"\", strings[66], subcount[10])\n        regexs[51].sub(r\"\", strings[66], subcount[51])\n        regexs[52].sub(r\"\", strings[66], subcount[52])\n        regexs[53].sub(r\"\", strings[66], subcount[53])\n        regexs[39].sub(r\"\", strings[66], subcount[39])\n        regexs[54].sub(r\"\", strings[66], subcount[54])\n        regexs[40].sub(r\"\", \"9.0\", subcount[40])\n        regexs[10].sub(r\"\", \"9.0\", subcount[10])\n        regexs[51].sub(r\"\", \"9.0\", subcount[51])\n        regexs[52].sub(r\"\", \"9.0\", subcount[52])\n        regexs[53].sub(r\"\", \"9.0\", subcount[53])\n        regexs[39].sub(r\"\", \"9.0\", subcount[39])\n        regexs[54].sub(r\"\", \"9.0\", subcount[54])\n        regexs[40].sub(r\"\", \"994k634\", subcount[40])\n        regexs[10].sub(r\"\", \"994k634\", subcount[10])\n        regexs[51].sub(r\"\", \"994k634\", subcount[51])\n        regexs[52].sub(r\"\", \"994k634\", subcount[52])\n        regexs[53].sub(r\"\", \"994k634\", subcount[53])\n        regexs[39].sub(r\"\", \"994k634\", subcount[39])\n        regexs[54].sub(r\"\", \"994k634\", subcount[54])\n        regexs[40].sub(r\"\", \"?zxg=ra-HF\", subcount[40])\n        regexs[10].sub(r\"\", \"?zxg=ra-HF\", subcount[10])\n        regexs[51].sub(r\"\", \"?zxg=ra-HF\", subcount[51])\n        regexs[52].sub(r\"\", \"?zxg=ra-HF\", subcount[52])\n        regexs[53].sub(r\"\", \"?zxg=ra-HF\", subcount[53])\n        regexs[54].sub(r\"\", \"?zxg=ra-HF\", subcount[54])\n        regexs[25].sub(r\"\", \"PAA.pbz\", subcount[25])\n        regexs[12].sub(r\"\", \"PAA.pbz\", subcount[12])\n        regexs[39].sub(r\"\", \"PAA.pbz\", subcount[39])\n        regexs[25].sub(r\"\", \"Qngr & Gvzr\", subcount[25])\n        regexs[12].sub(r\"\", \"Qngr & Gvzr\", subcount[12])\n        regexs[39].sub(r\"\", \"Qngr & Gvzr\", subcount[39])\n        regexs[40].sub(r\"\", \"Frnepu Zvpebfbsg.pbz\", subcount[40])\n        regexs[54].sub(r\"\", \"Frnepu Zvpebfbsg.pbz\", subcount[54])\n        regexs[10].sub(r\"\", strings[67], subcount[10])\n        regexs[51].sub(r\"\", strings[67], subcount[51])\n        regexs[52].sub(r\"\", strings[67], subcount[52])\n        regexs[53].sub(r\"\", strings[67], subcount[53])\n        regexs[39].sub(r\"\", strings[67], subcount[39])\n        regexs[32].split(strings[68])\n        regexs[32].split(strings[69])\n        regexs[52].sub(r\"\", strings[70], subcount[52])\n        regexs[53].sub(r\"\", strings[70], subcount[53])\n        regexs[39].sub(r\"\", strings[70], subcount[39])\n        regexs[40].sub(r\"\", strings[71], subcount[40])\n        regexs[10].sub(r\"\", strings[71], subcount[10])\n        regexs[51].sub(r\"\", strings[71], subcount[51])\n        regexs[54].sub(r\"\", strings[71], subcount[54])\n        regexs[25].sub(r\"\", \"Jrngure\", subcount[25])\n        regexs[12].sub(r\"\", \"Jrngure\", subcount[12])\n        regexs[39].sub(r\"\", \"Jrngure\", subcount[39])\n        regexs[25].sub(r\"\", \"LbhGhor\", subcount[25])\n        regexs[12].sub(r\"\", \"LbhGhor\", subcount[12])\n        regexs[39].sub(r\"\", \"LbhGhor\", subcount[39])\n        regexs[33].sub(r\"\", strings[72], subcount[33])\n        re.sub(r\"^erzbgr_vsenzr_\", \"\", \"erzbgr_vsenzr_1\", 1)\n        regexs[40].sub(r\"\", strings[73], subcount[40])\n        regexs[10].sub(r\"\", strings[73], subcount[10])\n        regexs[51].sub(r\"\", strings[73], subcount[51])\n        regexs[52].sub(r\"\", strings[73], subcount[52])\n        regexs[53].sub(r\"\", strings[73], subcount[53])\n        regexs[39].sub(r\"\", strings[73], subcount[39])\n        regexs[54].sub(r\"\", strings[73], subcount[54])\n        regexs[40].sub(r\"\", strings[74], subcount[40])\n        regexs[10].sub(r\"\", strings[74], subcount[10])\n        regexs[51].sub(r\"\", strings[74], subcount[51])\n        regexs[52].sub(r\"\", strings[74], subcount[52])\n        regexs[53].sub(r\"\", strings[74], subcount[53])\n        regexs[39].sub(r\"\", strings[74], subcount[39])\n        regexs[54].sub(r\"\", strings[74], subcount[54])\n        re.sub(r\"\\-\", \"\", \"lhv-h\", 0)\n        regexs[9].search(r\"p\")\n        regexs[9].search(r\"qz p\")\n        regexs[9].search(r\"zbqynory\")\n        regexs[9].search(r\"lhv-h svefg\")\n        regexs[8].search(r\"144631658.0.10.1231365779\")\n        regexs[8].search(\n            r\"144631658.1231365779.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)\"\n        )\n        regexs[8].search(\n            r\"144631658.1877536177953918500.1231365779.1231365779.1231365779.1\"\n        )\n        regexs[8].search(strings[75])\n        regexs[8].search(strings[76])\n        regexs[8].search(\n            r\"__hgzn=144631658.1877536177953918500.1231365779.1231365779.1231365779.1\"\n        )\n        regexs[8].search(r\"__hgzo=144631658.0.10.1231365779\")\n        regexs[8].search(\n            r\"__hgzm=144631658.1231365779.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)\"\n        )\n        regexs[34].search(strings[68])\n        regexs[34].search(strings[69])\n        re.search(r\"^$\", \"\")\n        regexs[31].search(r\"qr\")\n        re.search(r\"^znk\\d+$\", \"\")\n        re.search(r\"^zva\\d+$\", \"\")\n        re.search(r\"^erfgber$\", \"\")\n        regexs[85].search(r\"zbqobkva zbqobk_abcnqqvat \")\n        regexs[85].search(r\"zbqgvgyr\")\n        regexs[85].search(r\"eaq_zbqobkva \")\n        regexs[85].search(r\"eaq_zbqgvgyr \")\n        re.search(r\"frpgvba\\d+_pbagragf\", \"obggbz_ani\")\n\n\ndef block11():\n    for i in range(2):\n        regexs[18].sub(r\"\", \" .pybfr\", subcount[18])\n        regexs[18].sub(r\"\", \" n.svryqOgaPnapry\", subcount[18])\n        regexs[18].sub(r\"\", \" qg\", subcount[18])\n        regexs[68].sub(r\"\", strings[77], subcount[68])\n        regexs[18].sub(r\"\", strings[77], subcount[18])\n        regexs[39].sub(r\"\", \"\", subcount[39])\n        re.sub(r\"^\", \"\", \"\", 1)\n        regexs[86].split(r\"\")\n        regexs[39].sub(r\"\", \"*\", subcount[39])\n        regexs[68].sub(r\"\", \"*\", subcount[68])\n        regexs[18].sub(r\"\", \"*\", subcount[18])\n        regexs[68].sub(r\"\", \".pybfr\", subcount[68])\n        regexs[18].sub(r\"\", \".pybfr\", subcount[18])\n        regexs[87].sub(\n            r\"\", \"//vzt.jro.qr/vij/FC/tzk_uc/fperra/${inyhr}?gf=${abj}\", subcount[87]\n        )\n        regexs[88].sub(\n            r\"\", \"//vzt.jro.qr/vij/FC/tzk_uc/fperra/1024?gf=${abj}\", subcount[88]\n        )\n        regexs[87].sub(\n            r\"\", \"//vzt.jro.qr/vij/FC/tzk_uc/jvafvmr/${inyhr}?gf=${abj}\", subcount[87]\n        )\n        regexs[88].sub(\n            r\"\", \"//vzt.jro.qr/vij/FC/tzk_uc/jvafvmr/992/608?gf=${abj}\", subcount[88]\n        )\n        regexs[30].sub(r\"\", \"300k120\", subcount[30])\n        regexs[30].sub(r\"\", \"300k250\", subcount[30])\n        regexs[30].sub(r\"\", \"310k120\", subcount[30])\n        regexs[30].sub(r\"\", \"310k170\", subcount[30])\n        regexs[30].sub(r\"\", \"310k250\", subcount[30])\n        re.sub(r\"^.*\\.(.*)\\s.*$\", \"\", \"9.0  e115\", 1)\n        regexs[2].sub(r\"\", \"Nppbeqvba\", subcount[2])\n        regexs[89].sub(r\"\", \"Nxghryy\\x0a\", subcount[89])\n        regexs[90].sub(r\"\", \"Nxghryy\\x0a\", subcount[90])\n        regexs[2].sub(r\"\", \"Nccyvpngvba\", subcount[2])\n        regexs[89].sub(r\"\", \"Oyvpxchaxg\\x0a\", subcount[89])\n        regexs[90].sub(r\"\", \"Oyvpxchaxg\\x0a\", subcount[90])\n        regexs[89].sub(r\"\", \"Svanamra\\x0a\", subcount[89])\n        regexs[90].sub(r\"\", \"Svanamra\\x0a\", subcount[90])\n        regexs[89].sub(r\"\", \"Tnzrf\\x0a\", subcount[89])\n        regexs[90].sub(r\"\", \"Tnzrf\\x0a\", subcount[90])\n        regexs[89].sub(r\"\", \"Ubebfxbc\\x0a\", subcount[89])\n        regexs[90].sub(r\"\", \"Ubebfxbc\\x0a\", subcount[90])\n        regexs[89].sub(r\"\", \"Xvab\\x0a\", subcount[89])\n        regexs[90].sub(r\"\", \"Xvab\\x0a\", subcount[90])\n        regexs[2].sub(r\"\", \"Zbqhyrf\", subcount[2])\n        regexs[89].sub(r\"\", \"Zhfvx\\x0a\", subcount[89])\n        regexs[90].sub(r\"\", \"Zhfvx\\x0a\", subcount[90])\n        regexs[89].sub(r\"\", \"Anpuevpugra\\x0a\", subcount[89])\n        regexs[90].sub(r\"\", \"Anpuevpugra\\x0a\", subcount[90])\n        regexs[2].sub(r\"\", \"Cuk\", subcount[2])\n        regexs[70].split(r\"ErdhrfgSvavfu\")\n        regexs[70].split(r\"ErdhrfgSvavfu.NWNK.Cuk\")\n        regexs[89].sub(r\"\", \"Ebhgr\\x0a\", subcount[89])\n        regexs[90].sub(r\"\", \"Ebhgr\\x0a\", subcount[90])\n        regexs[32].split(strings[78])\n        regexs[32].split(strings[79])\n        regexs[32].split(strings[80])\n        regexs[32].split(strings[81])\n        regexs[89].sub(r\"\", \"Fcbeg\\x0a\", subcount[89])\n        regexs[90].sub(r\"\", \"Fcbeg\\x0a\", subcount[90])\n        regexs[89].sub(r\"\", \"GI-Fcbg\\x0a\", subcount[89])\n        regexs[90].sub(r\"\", \"GI-Fcbg\\x0a\", subcount[90])\n        regexs[89].sub(r\"\", \"Gbhe\\x0a\", subcount[89])\n        regexs[90].sub(r\"\", \"Gbhe\\x0a\", subcount[90])\n        regexs[89].sub(r\"\", \"Hagreunyghat\\x0a\", subcount[89])\n        regexs[90].sub(r\"\", \"Hagreunyghat\\x0a\", subcount[90])\n        regexs[89].sub(r\"\", \"Ivqrb\\x0a\", subcount[89])\n        regexs[90].sub(r\"\", \"Ivqrb\\x0a\", subcount[90])\n        regexs[89].sub(r\"\", \"Jrggre\\x0a\", subcount[89])\n        regexs[90].sub(r\"\", \"Jrggre\\x0a\", subcount[90])\n        regexs[68].sub(r\"\", strings[82], subcount[68])\n        regexs[18].sub(r\"\", strings[82], subcount[18])\n        regexs[68].sub(r\"\", strings[83], subcount[68])\n        regexs[18].sub(r\"\", strings[83], subcount[18])\n        regexs[68].sub(r\"\", strings[84], subcount[68])\n        regexs[18].sub(r\"\", strings[84], subcount[18])\n        regexs[30].sub(r\"\", \"nqiFreivprObk\", subcount[30])\n        regexs[30].sub(r\"\", \"nqiFubccvatObk\", subcount[30])\n        regexs[39].sub(r\"\", \"nwnk\", subcount[39])\n        regexs[40].sub(r\"\", \"nxghryy\", subcount[40])\n        regexs[41].sub(r\"\", \"nxghryy\", subcount[41])\n        regexs[42].sub(r\"\", \"nxghryy\", subcount[42])\n        regexs[43].sub(r\"\", \"nxghryy\", subcount[43])\n        regexs[44].sub(r\"\", \"nxghryy\", subcount[44])\n        regexs[45].sub(r\"\", \"nxghryy\", subcount[45])\n        regexs[46].sub(r\"\", \"nxghryy\", subcount[46])\n        regexs[47].sub(r\"\", \"nxghryy\", subcount[47])\n        regexs[48].sub(r\"\", \"nxghryy\", subcount[48])\n        regexs[40].sub(r\"\", strings[85], subcount[40])\n        regexs[41].sub(r\"\", strings[85], subcount[41])\n        regexs[42].sub(r\"\", strings[85], subcount[42])\n        regexs[43].sub(r\"\", strings[85], subcount[43])\n        regexs[44].sub(r\"\", strings[85], subcount[44])\n        regexs[45].sub(r\"\", strings[85], subcount[45])\n        regexs[46].sub(r\"\", strings[85], subcount[46])\n        regexs[47].sub(r\"\", strings[85], subcount[47])\n        regexs[48].sub(r\"\", strings[85], subcount[48])\n        regexs[29].sub(r\"\", \"pngrtbel\", subcount[29])\n        regexs[30].sub(r\"\", \"pngrtbel\", subcount[30])\n        regexs[39].sub(r\"\", \"pybfr\", subcount[39])\n        regexs[39].sub(r\"\", \"qvi\", subcount[39])\n        regexs[68].sub(r\"\", strings[86], subcount[68])\n        regexs[18].sub(r\"\", strings[86], subcount[18])\n        regexs[39].sub(r\"\", \"qg\", subcount[39])\n        regexs[68].sub(r\"\", \"qg\", subcount[68])\n        regexs[18].sub(r\"\", \"qg\", subcount[18])\n        regexs[39].sub(r\"\", \"rzorq\", subcount[39])\n        regexs[68].sub(r\"\", \"rzorq\", subcount[68])\n        regexs[18].sub(r\"\", \"rzorq\", subcount[18])\n        regexs[39].sub(r\"\", \"svryqOga\", subcount[39])\n        regexs[39].sub(r\"\", \"svryqOgaPnapry\", subcount[39])\n        regexs[20].split(r\"svz_zlfcnpr_nccf-pnainf,svz_zlfcnpr_havgrq-fgngrf\")\n        regexs[40].sub(r\"\", \"svanamra\", subcount[40])\n        regexs[41].sub(r\"\", \"svanamra\", subcount[41])\n        regexs[42].sub(r\"\", \"svanamra\", subcount[42])\n        regexs[43].sub(r\"\", \"svanamra\", subcount[43])\n        regexs[44].sub(r\"\", \"svanamra\", subcount[44])\n        regexs[45].sub(r\"\", \"svanamra\", subcount[45])\n        regexs[46].sub(r\"\", \"svanamra\", subcount[46])\n        regexs[47].sub(r\"\", \"svanamra\", subcount[47])\n        regexs[48].sub(r\"\", \"svanamra\", subcount[48])\n        regexs[70].split(r\"sbphf\")\n        regexs[70].split(r\"sbphf.gno sbphfva.gno\")\n        regexs[70].split(r\"sbphfva\")\n        regexs[39].sub(r\"\", \"sbez\", subcount[39])\n        regexs[68].sub(r\"\", \"sbez.nwnk\", subcount[68])\n        regexs[18].sub(r\"\", \"sbez.nwnk\", subcount[18])\n        regexs[40].sub(r\"\", \"tnzrf\", subcount[40])\n        regexs[41].sub(r\"\", \"tnzrf\", subcount[41])\n        regexs[42].sub(r\"\", \"tnzrf\", subcount[42])\n        regexs[43].sub(r\"\", \"tnzrf\", subcount[43])\n        regexs[44].sub(r\"\", \"tnzrf\", subcount[44])\n        regexs[45].sub(r\"\", \"tnzrf\", subcount[45])\n        regexs[46].sub(r\"\", \"tnzrf\", subcount[46])\n        regexs[47].sub(r\"\", \"tnzrf\", subcount[47])\n        regexs[48].sub(r\"\", \"tnzrf\", subcount[48])\n        regexs[30].sub(r\"\", \"ubzrcntr\", subcount[30])\n        regexs[40].sub(r\"\", \"ubebfxbc\", subcount[40])\n        regexs[41].sub(r\"\", \"ubebfxbc\", subcount[41])\n        regexs[42].sub(r\"\", \"ubebfxbc\", subcount[42])\n        regexs[43].sub(r\"\", \"ubebfxbc\", subcount[43])\n        regexs[44].sub(r\"\", \"ubebfxbc\", subcount[44])\n        regexs[45].sub(r\"\", \"ubebfxbc\", subcount[45])\n        regexs[46].sub(r\"\", \"ubebfxbc\", subcount[46])\n        regexs[47].sub(r\"\", \"ubebfxbc\", subcount[47])\n        regexs[48].sub(r\"\", \"ubebfxbc\", subcount[48])\n        regexs[30].sub(r\"\", \"uc_cebzbobk_ugzy%2Puc_cebzbobk_vzt\", subcount[30])\n        regexs[30].sub(r\"\", \"uc_erpgnatyr\", subcount[30])\n        regexs[33].sub(r\"\", strings[87], subcount[33])\n        regexs[33].sub(r\"\", strings[88], subcount[33])\n        regexs[71].sub(\n            r\"\",\n            \"uggc://wf.hv-cbegny.qr/tzk/ubzr/wf/20080602/onfr.wf${4}${5}\",\n            subcount[71],\n        )\n        regexs[72].sub(\n            r\"\", \"uggc://wf.hv-cbegny.qr/tzk/ubzr/wf/20080602/onfr.wf${5}\", subcount[72]\n        )\n        regexs[71].sub(\n            r\"\",\n            \"uggc://wf.hv-cbegny.qr/tzk/ubzr/wf/20080602/qlaYvo.wf${4}${5}\",\n            subcount[71],\n        )\n        regexs[72].sub(\n            r\"\",\n            \"uggc://wf.hv-cbegny.qr/tzk/ubzr/wf/20080602/qlaYvo.wf${5}\",\n            subcount[72],\n        )\n        regexs[71].sub(\n            r\"\",\n            \"uggc://wf.hv-cbegny.qr/tzk/ubzr/wf/20080602/rssrpgYvo.wf${4}${5}\",\n            subcount[71],\n        )\n        regexs[72].sub(\n            r\"\",\n            \"uggc://wf.hv-cbegny.qr/tzk/ubzr/wf/20080602/rssrpgYvo.wf${5}\",\n            subcount[72],\n        )\n        regexs[73].sub(r\"\", strings[89], subcount[73])\n        regexs[69].sub(\n            r\"\",\n            \"uggc://zfacbegny.112.2b7.arg/o/ff/zfacbegnyubzr/1/U.7-cqi-2/f55023338617756?[NDO]&{1}&{2}&[NDR]\",\n            subcount[69],\n        )\n        regexs[23].sub(r\"\", strings[6], subcount[23])\n        regexs[40].sub(r\"\", \"xvab\", subcount[40])\n        regexs[41].sub(r\"\", \"xvab\", subcount[41])\n        regexs[42].sub(r\"\", \"xvab\", subcount[42])\n        regexs[43].sub(r\"\", \"xvab\", subcount[43])\n        regexs[44].sub(r\"\", \"xvab\", subcount[44])\n        regexs[45].sub(r\"\", \"xvab\", subcount[45])\n        regexs[46].sub(r\"\", \"xvab\", subcount[46])\n        regexs[47].sub(r\"\", \"xvab\", subcount[47])\n        regexs[48].sub(r\"\", \"xvab\", subcount[48])\n        regexs[70].split(r\"ybnq\")\n        regexs[18].sub(r\"\", \"zrqvnzbqgno lhv-anifrg lhv-anifrg-gbc\", subcount[18])\n        regexs[39].sub(r\"\", \"zrgn\", subcount[39])\n        regexs[68].sub(r\"\", strings[90], subcount[68])\n        regexs[18].sub(r\"\", strings[90], subcount[18])\n        regexs[70].split(r\"zbhfrzbir\")\n        regexs[70].split(r\"zbhfrzbir.gno\")\n        re.sub(r\"^.*jroxvg\\/(\\d+(\\.\\d+)?).*$\", \"\", strings[63], 1)\n        regexs[40].sub(r\"\", \"zhfvx\", subcount[40])\n        regexs[41].sub(r\"\", \"zhfvx\", subcount[41])\n        regexs[42].sub(r\"\", \"zhfvx\", subcount[42])\n        regexs[43].sub(r\"\", \"zhfvx\", subcount[43])\n        regexs[44].sub(r\"\", \"zhfvx\", subcount[44])\n        regexs[45].sub(r\"\", \"zhfvx\", subcount[45])\n        regexs[46].sub(r\"\", \"zhfvx\", subcount[46])\n        regexs[47].sub(r\"\", \"zhfvx\", subcount[47])\n        regexs[48].sub(r\"\", \"zhfvx\", subcount[48])\n        regexs[52].sub(r\"\", \"zlfcnpr_nccf_pnainf\", subcount[52])\n        regexs[40].sub(r\"\", strings[91], subcount[40])\n        regexs[41].sub(r\"\", strings[91], subcount[41])\n        regexs[42].sub(r\"\", strings[91], subcount[42])\n        regexs[43].sub(r\"\", strings[91], subcount[43])\n        regexs[44].sub(r\"\", strings[91], subcount[44])\n        regexs[45].sub(r\"\", strings[91], subcount[45])\n        regexs[46].sub(r\"\", strings[91], subcount[46])\n        regexs[47].sub(r\"\", strings[91], subcount[47])\n        regexs[48].sub(r\"\", strings[91], subcount[48])\n        regexs[39].sub(r\"\", \"anzr\", subcount[39])\n\n        # This prints something different to the V8 version\n        # The V8 version is escaping different things in the string that\n        # has the substitutions performed on it.\n        #\n        # V8 treats /\\S/ like / + escaped S + /\n        # Python treats it like / + \\ + S + /\n        re.sub(r\"\\b\\w+\\b\", \"\", strings[92], 0)\n\n        regexs[39].sub(r\"\", \"bow-nppbeqvba\", subcount[39])\n        regexs[39].sub(r\"\", \"bowrpg\", subcount[39])\n        regexs[68].sub(r\"\", \"bowrpg\", subcount[68])\n        regexs[18].sub(r\"\", \"bowrpg\", subcount[18])\n        regexs[29].sub(r\"\", \"cnenzf%2Rfglyrf\", subcount[29])\n        regexs[30].sub(r\"\", \"cnenzf%2Rfglyrf\", subcount[30])\n        regexs[30].sub(r\"\", \"cbchc\", subcount[30])\n        regexs[40].sub(r\"\", \"ebhgr\", subcount[40])\n        regexs[41].sub(r\"\", \"ebhgr\", subcount[41])\n        regexs[42].sub(r\"\", \"ebhgr\", subcount[42])\n        regexs[43].sub(r\"\", \"ebhgr\", subcount[43])\n        regexs[44].sub(r\"\", \"ebhgr\", subcount[44])\n        regexs[45].sub(r\"\", \"ebhgr\", subcount[45])\n        regexs[46].sub(r\"\", \"ebhgr\", subcount[46])\n        regexs[47].sub(r\"\", \"ebhgr\", subcount[47])\n        regexs[48].sub(r\"\", \"ebhgr\", subcount[48])\n        regexs[30].sub(r\"\", \"freivprobk_uc\", subcount[30])\n        regexs[30].sub(r\"\", \"fubccvatobk_uc\", subcount[30])\n        regexs[39].sub(r\"\", \"fubhgobk\", subcount[39])\n        regexs[40].sub(r\"\", \"fcbeg\", subcount[40])\n        regexs[41].sub(r\"\", \"fcbeg\", subcount[41])\n        regexs[42].sub(r\"\", \"fcbeg\", subcount[42])\n        regexs[43].sub(r\"\", \"fcbeg\", subcount[43])\n        regexs[44].sub(r\"\", \"fcbeg\", subcount[44])\n        regexs[45].sub(r\"\", \"fcbeg\", subcount[45])\n        regexs[46].sub(r\"\", \"fcbeg\", subcount[46])\n        regexs[47].sub(r\"\", \"fcbeg\", subcount[47])\n        regexs[48].sub(r\"\", \"fcbeg\", subcount[48])\n        regexs[40].sub(r\"\", \"gbhe\", subcount[40])\n        regexs[41].sub(r\"\", \"gbhe\", subcount[41])\n        regexs[42].sub(r\"\", \"gbhe\", subcount[42])\n        regexs[43].sub(r\"\", \"gbhe\", subcount[43])\n        regexs[44].sub(r\"\", \"gbhe\", subcount[44])\n        regexs[45].sub(r\"\", \"gbhe\", subcount[45])\n        regexs[46].sub(r\"\", \"gbhe\", subcount[46])\n        regexs[47].sub(r\"\", \"gbhe\", subcount[47])\n        regexs[48].sub(r\"\", \"gbhe\", subcount[48])\n        regexs[40].sub(r\"\", \"gi-fcbg\", subcount[40])\n        regexs[41].sub(r\"\", \"gi-fcbg\", subcount[41])\n        regexs[42].sub(r\"\", \"gi-fcbg\", subcount[42])\n        regexs[43].sub(r\"\", \"gi-fcbg\", subcount[43])\n        regexs[44].sub(r\"\", \"gi-fcbg\", subcount[44])\n        regexs[45].sub(r\"\", \"gi-fcbg\", subcount[45])\n        regexs[46].sub(r\"\", \"gi-fcbg\", subcount[46])\n        regexs[47].sub(r\"\", \"gi-fcbg\", subcount[47])\n        regexs[48].sub(r\"\", \"gi-fcbg\", subcount[48])\n        regexs[39].sub(r\"\", \"glcr\", subcount[39])\n        re.sub(r\"\\/\", \"\", \"haqrsvarq\", 0)\n        regexs[40].sub(r\"\", strings[93], subcount[40])\n        regexs[41].sub(r\"\", strings[93], subcount[41])\n        regexs[42].sub(r\"\", strings[93], subcount[42])\n        regexs[43].sub(r\"\", strings[93], subcount[43])\n        regexs[44].sub(r\"\", strings[93], subcount[44])\n        regexs[45].sub(r\"\", strings[93], subcount[45])\n        regexs[46].sub(r\"\", strings[93], subcount[46])\n        regexs[47].sub(r\"\", strings[93], subcount[47])\n        regexs[48].sub(r\"\", strings[93], subcount[48])\n        regexs[40].sub(r\"\", \"ivqrb\", subcount[40])\n        regexs[41].sub(r\"\", \"ivqrb\", subcount[41])\n        regexs[42].sub(r\"\", \"ivqrb\", subcount[42])\n        regexs[43].sub(r\"\", \"ivqrb\", subcount[43])\n        regexs[44].sub(r\"\", \"ivqrb\", subcount[44])\n        regexs[45].sub(r\"\", \"ivqrb\", subcount[45])\n        regexs[46].sub(r\"\", \"ivqrb\", subcount[46])\n        regexs[47].sub(r\"\", \"ivqrb\", subcount[47])\n        regexs[48].sub(r\"\", \"ivqrb\", subcount[48])\n        regexs[86].split(r\"ivfvgf=1\")\n        regexs[40].sub(r\"\", \"jrggre\", subcount[40])\n        regexs[41].sub(r\"\", \"jrggre\", subcount[41])\n        regexs[42].sub(r\"\", \"jrggre\", subcount[42])\n        regexs[43].sub(r\"\", \"jrggre\", subcount[43])\n        regexs[44].sub(r\"\", \"jrggre\", subcount[44])\n        regexs[45].sub(r\"\", \"jrggre\", subcount[45])\n        regexs[46].sub(r\"\", \"jrggre\", subcount[46])\n        regexs[47].sub(r\"\", \"jrggre\", subcount[47])\n        regexs[48].sub(r\"\", \"jrggre\", subcount[48])\n        re.search(r\"#[a-z0-9]+$\", \"uggc://jjj.fpuhryreim.arg/Qrsnhyg\", re.IGNORECASE)\n        regexs[66].search(r\"fryrpgrq\")\n        re.search(r\"(?:^|\\s+)lhv-ani(?:\\s+|$)\", \"sff lhv-ani\")\n        re.search(r\"(?:^|\\s+)lhv-anifrg(?:\\s+|$)\", \"zrqvnzbqgno lhv-anifrg\")\n        re.search(r\"(?:^|\\s+)lhv-anifrg-gbc(?:\\s+|$)\", \"zrqvnzbqgno lhv-anifrg\")\n        regexs[91].search(r\"GnoThvq\")\n        regexs[91].search(r\"thvq\")\n        re.search(r\"(pbzcngvoyr|jroxvg)\", strings[63])\n        re.search(r\".+(?:ei|vg|en|vr)[\\/: ]([\\d.]+)\", strings[63])\n        regexs[8].search(r\"144631658.0.10.1231365869\")\n        regexs[8].search(r\"144631658.0.10.1231367054\")\n        regexs[8].search(\n            r\"144631658.1231365869.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)\"\n        )\n        regexs[8].search(\n            r\"144631658.1231367054.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)\"\n        )\n        regexs[8].search(\n            r\"144631658.1670816052019209000.1231365869.1231365869.1231365869.1\"\n        )\n        regexs[8].search(\n            r\"144631658.1796080716621419500.1231367054.1231367054.1231367054.1\"\n        )\n        regexs[8].search(strings[94])\n        regexs[8].search(strings[95])\n        regexs[8].search(strings[96])\n        regexs[8].search(strings[97])\n        regexs[8].search(\n            r\"__hgzn=144631658.1670816052019209000.1231365869.1231365869.1231365869.1\"\n        )\n        regexs[8].search(\n            r\"__hgzn=144631658.1796080716621419500.1231367054.1231367054.1231367054.1\"\n        )\n        regexs[8].search(r\"__hgzo=144631658.0.10.1231365869\")\n        regexs[8].search(r\"__hgzo=144631658.0.10.1231367054\")\n        regexs[8].search(\n            r\"__hgzm=144631658.1231365869.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)\"\n        )\n        regexs[8].search(\n            r\"__hgzm=144631658.1231367054.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)\"\n        )\n        regexs[34].search(strings[78])\n        regexs[34].search(strings[79])\n        regexs[34].search(strings[81])\n        regexs[74].search(strings[77])\n        regexs[74].search(r\"*\")\n        regexs[74].search(strings[82])\n        regexs[74].search(strings[83])\n        regexs[74].search(strings[86])\n        regexs[74].search(r\"rzorq\")\n        regexs[74].search(r\"sbez.nwnk\")\n        regexs[74].search(strings[90])\n        regexs[74].search(r\"bowrpg\")\n        re.search(\n            r\"\\/onfr.wf(\\?.+)?$\", \"/uggc://wf.hv-cbegny.qr/tzk/ubzr/wf/20080602/onfr.wf\"\n        )\n        regexs[28].search(r\"uvag ynfgUvag ynfg\")\n        regexs[75].search(r\"\")\n        regexs[76].search(r\"\")\n        regexs[77].search(r\"\")\n        regexs[78].search(r\"\")\n        regexs[80].search(strings[77])\n        regexs[80].search(r\"*\")\n        regexs[80].search(r\".pybfr\")\n        regexs[80].search(strings[82])\n        regexs[80].search(strings[83])\n        regexs[80].search(strings[84])\n        regexs[80].search(strings[86])\n        regexs[80].search(r\"qg\")\n        regexs[80].search(r\"rzorq\")\n        regexs[80].search(r\"sbez.nwnk\")\n        regexs[80].search(strings[90])\n        regexs[80].search(r\"bowrpg\")\n        regexs[61].search(r\"qlaYvo.wf\")\n        regexs[61].search(r\"rssrpgYvo.wf\")\n        regexs[61].search(r\"uggc://jjj.tzk.arg/qr/?fgnghf=uvajrvf\")\n        regexs[92].search(r\" .pybfr\")\n        regexs[92].search(r\" n.svryqOgaPnapry\")\n        regexs[92].search(r\" qg\")\n        regexs[92].search(strings[48])\n        regexs[92].search(r\".nwnk\")\n        regexs[92].search(r\".svryqOga,n.svryqOgaPnapry\")\n        regexs[92].search(r\".svryqOgaPnapry\")\n        regexs[92].search(r\".bow-nppbeqvba qg\")\n        regexs[68].search(strings[77])\n        regexs[68].search(r\"*\")\n        regexs[68].search(r\".pybfr\")\n        regexs[68].search(strings[82])\n        regexs[68].search(strings[83])\n        regexs[68].search(strings[84])\n        regexs[68].search(strings[86])\n        regexs[68].search(r\"qg\")\n        regexs[68].search(r\"rzorq\")\n        regexs[68].search(r\"sbez.nwnk\")\n        regexs[68].search(strings[90])\n        regexs[68].search(r\"bowrpg\")\n        regexs[93].search(r\" .pybfr\")\n        regexs[93].search(r\" n.svryqOgaPnapry\")\n        regexs[93].search(r\" qg\")\n        regexs[93].search(strings[48])\n        regexs[93].search(r\".nwnk\")\n        regexs[93].search(r\".svryqOga,n.svryqOgaPnapry\")\n        regexs[93].search(r\".svryqOgaPnapry\")\n        regexs[93].search(r\".bow-nppbeqvba qg\")\n        regexs[81].search(strings[77])\n        regexs[81].search(r\"*\")\n        regexs[81].search(strings[48])\n        regexs[81].search(r\".pybfr\")\n        regexs[81].search(strings[82])\n        regexs[81].search(strings[83])\n        regexs[81].search(strings[84])\n        regexs[81].search(strings[86])\n        regexs[81].search(r\"qg\")\n        regexs[81].search(r\"rzorq\")\n        regexs[81].search(r\"sbez.nwnk\")\n        regexs[81].search(strings[90])\n        regexs[81].search(r\"bowrpg\")\n        regexs[94].search(r\" .pybfr\")\n        regexs[94].search(r\" n.svryqOgaPnapry\")\n        regexs[94].search(r\" qg\")\n        regexs[94].search(strings[48])\n        regexs[94].search(r\".nwnk\")\n        regexs[94].search(r\".svryqOga,n.svryqOgaPnapry\")\n        regexs[94].search(r\".svryqOgaPnapry\")\n        regexs[94].search(r\".bow-nppbeqvba qg\")\n        regexs[94].search(r\"[anzr=nwnkHey]\")\n        regexs[94].search(strings[82])\n        regexs[31].search(r\"rf\")\n        regexs[31].search(r\"wn\")\n        regexs[82].search(strings[77])\n        regexs[82].search(r\"*\")\n        regexs[82].search(strings[48])\n        regexs[82].search(r\".pybfr\")\n        regexs[82].search(strings[82])\n        regexs[82].search(strings[83])\n        regexs[82].search(strings[84])\n        regexs[82].search(strings[86])\n        regexs[82].search(r\"qg\")\n        regexs[82].search(r\"rzorq\")\n        regexs[82].search(r\"sbez.nwnk\")\n        regexs[82].search(strings[90])\n        regexs[82].search(r\"bowrpg\")\n        regexs[83].search(strings[98])\n        regexs[83].search(r\"shapgvba sbphf() { [angvir pbqr] }\")\n        regexs[62].search(r\"#Ybtva\")\n        regexs[62].search(r\"#Ybtva_cnffjbeq\")\n        regexs[62].search(strings[77])\n        regexs[62].search(r\"#fubhgobkWf\")\n        regexs[62].search(r\"#fubhgobkWfReebe\")\n        regexs[62].search(r\"#fubhgobkWfFhpprff\")\n        regexs[62].search(r\"*\")\n        regexs[62].search(strings[82])\n        regexs[62].search(strings[83])\n        regexs[62].search(strings[86])\n        regexs[62].search(r\"rzorq\")\n        regexs[62].search(r\"sbez.nwnk\")\n        regexs[62].search(strings[90])\n        regexs[62].search(r\"bowrpg\")\n        regexs[49].search(r\"pbagrag\")\n        regexs[24].search(strings[6])\n        re.search(r\"xbadhrebe\", strings[63])\n        re.search(r\"znp\", \"jva32\")\n        re.search(r\"zbmvyyn\", strings[63])\n        re.search(r\"zfvr\", strings[63])\n        re.search(r\"ag\\s5\\.1\", strings[63])\n        re.search(r\"bcren\", strings[63])\n        re.search(r\"fnsnev\", strings[63])\n        re.search(r\"jva\", \"jva32\")\n        re.search(r\"jvaqbjf\", strings[63])\n\n\ndef bench_regex_v8(loops):\n    for loops in range(loops):\n        block0()\n        block1()\n        block2()\n        block3()\n        block4()\n        block5()\n        block6()\n        block7()\n        block8()\n        block9()\n        block10()\n        block11()\n\n\ndef run_benchmark():\n    bench_regex_v8(1)\n\n\nif __name__ == \"__main__\":\n    run_benchmark()\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/regex_v8_memray.py",
    "content": "# Copyright 2009 the V8 project authors. All rights reserved.\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions are\n# met:\n#\n#     * Redistributions of source code must retain the above copyright\n#       notice, this list of conditions and the following disclaimer.\n#     * Redistributions in binary form must reproduce the above\n#       copyright notice, this list of conditions and the following\n#       disclaimer in the documentation and/or other materials provided\n#       with the distribution.\n#     * Neither the name of Google Inc. nor the names of its\n#       contributors may be used to endorse or promote products derived\n#       from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n# \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n# Automatically generated on 2009-01-30.\n\n# This benchmark is generated by loading 50 of the most popular pages\n# on the web and logging all regexp operations performed.  Each\n# operation is given a weight that is calculated from an estimate of\n# the popularity of the pages where it occurs and the number of times\n# it is executed while loading each page.  Finally the literal\n# letters in the data are encoded using ROT13 in a way that does not\n# affect how the regexps match their input.\n\n\n# Ported to Python for Unladen Swallow. The original JS version can be found at\n# https://github.com/v8/v8/blob/master/benchmarks/regexp.js, r1243.\n\n# Python imports\nimport re\n\n# Third party imports\nimport pyperf\nfrom memray_helper import get_tracker\n\n\n# The precompiled regexs that were in vars in the V8 code, split into\n# tuples of (regex, flags).\ncompiled_regex_strings = [\n    (r\"^ba\", \"\"),\n    (r\"(((\\w+):\\/\\/)([^\\/:]*)(:(\\d+))?)?([^#?]*)(\\?([^#]*))?(#(.*))?\", \"\"),\n    (r\"^\\s*|\\s*$\", \"g\"),\n    (r\"\\bQBZPbageby_cynprubyqre\\b\", \"\"),\n    (r\",\", \"\"),\n    (r\"\\bQBZPbageby_cynprubyqre\\b\", \"g\"),\n    (r\"^[\\s\\xa0]+|[\\s\\xa0]+$\", \"g\"),\n    (r\"(\\d*)(\\D*)\", \"g\"),\n    (r\"=\", \"\"),\n    (r\"(^|\\s)lhv\\-h(\\s|$)\", \"\"),\n    (r\"\\#\", \"g\"),\n    (r\"\\.\", \"g\"),\n    (r\"\\'\", \"g\"),\n    (r\"\\?[\\w\\W]*(sevraqvq|punaaryvq|tebhcvq)=([^\\&\\?#]*)\", \"i\"),\n    (r\"\\s+\", \"g\"),\n    (r\"^\\s*(\\S*(\\s+\\S+)*)\\s*$\", \"\"),\n    (r\"(-[a-z])\", \"i\"),\n    (r\"(^|[^\\\\])\\\"\\\\\\/Qngr\\((-?[0-9]+)\\)\\\\\\/\\\"\", \"g\"),\n    (r\"^\\s+|\\s+$\", \"g\"),\n    (r\"(?:^|\\s+)ba(?:\\s+|$)\", \"\"),\n    (r\"[+, ]\", \"\"),\n    (r\"ybnqrq|pbzcyrgr\", \"\"),\n    (r\"\\bso_zrah\\b\", \"\"),\n    (r\"^(?:(?:[^:\\/?#]+):)?(?:\\/\\/(?:[^\\/?#]*))?([^?#]*)(?:\\?([^#]*))?(?:#(.*))?\", \"\"),\n    (r\"uggcf?:\\/\\/([^\\/]+\\.)?snprobbx\\.pbz\\/\", \"\"),\n    (r'\"', \"g\"),\n    (r\"^([^?#]+)(?:\\?([^#]*))?(#.*)?\", \"\"),\n    (r\"-\\D\", \"g\"),\n    (r\"\\bnpgvingr\\b\", \"\"),\n    (r\"%2R\", \"gi\"),\n    (r\"%2S\", \"gi\"),\n    (r\"^(mu-(PA|GJ)|wn|xb)$\", \"\"),\n    (r\"\\s?;\\s?\", \"\"),\n    (r\"%\\w?$\", \"\"),\n    (r\"TNQP=([^;]*)\", \"i\"),\n    (r\"[<>]\", \"g\"),\n    (r\"uers|fep|fryrpgrq\", \"\"),\n    (r\"\\s*([+>~\\s])\\s*([a-zA-Z#.*:\\[])\", \"g\"),\n    (r\"^(\\w+|\\*)$\", \"\"),\n    (r\"\\\\\\\\\", \"g\"),\n    (r\" \", \"g\"),\n    (r\"\\/\\xc4\\/t\", \"\"),\n    (r\"\\/\\xd6\\/t\", \"\"),\n    (r\"\\/\\xdc\\/t\", \"\"),\n    (r\"\\/\\xdf\\/t\", \"\"),\n    (r\"\\/\\xe4\\/t\", \"\"),\n    (r\"\\/\\xf6\\/t\", \"\"),\n    (r\"\\/\\xfc\\/t\", \"\"),\n    (r\"\\W\", \"g\"),\n    (r\"uers|fep|fglyr\", \"\"),\n    (r\"(?:^|\\s+)fryrpgrq(?:\\s+|$)\", \"\"),\n    (r\"\\&\", \"g\"),\n    (r\"\\+\", \"g\"),\n    (r\"\\?\", \"g\"),\n    (r\"\\t\", \"g\"),\n    (r\"(\\$\\{nqiHey\\})|(\\$nqiHey\\b)\", \"g\"),\n    (r\"(\\$\\{cngu\\})|(\\$cngu\\b)\", \"g\"),\n    (r\"##yv4##\", \"gi\"),\n    (r\"##yv16##\", \"gi\"),\n    (r\"##yv19##\", \"gi\"),\n    (r\"(?:^|\\s+)bss(?:\\s+|$)\", \"\"),\n    (r\"^(([^:\\/?#]+):)?(\\/\\/([^\\/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?$\", \"\"),\n    (r\"^[^<]*(<(.|\\s)+>)[^>]*$|^#(\\w+)$\", \"\"),\n    (r\"\\{0\\}\", \"g\"),\n    (r\"\\b[a-z]\", \"g\"),\n    (r\"^uggc:\\/\\/\", \"\"),\n    (r\"(?:^|\\s+)qvfnoyrq(?:\\s+|$)\", \"\"),\n    (r\"zrah_byq\", \"g\"),\n    (r\"^([#.]?)((?:[\\w\" + \"\\u0128-\\uffff\" + r\"*_-]|\\\\.)*)\", \"\"),\n    (r\"\\{1\\}\", \"g\"),\n    (r\"\\s+\", \"\"),\n    (r\"(\\$\\{4\\})|(\\$4\\b)\", \"g\"),\n    (r\"(\\$\\{5\\})|(\\$5\\b)\", \"g\"),\n    (r\"\\{2\\}\", \"g\"),\n    (r\"[^+>] [^+>]\", \"\"),\n    (r\"\\bucpyv\\s*=\\s*([^;]*)\", \"i\"),\n    (r\"\\bucuvqr\\s*=\\s*([^;]*)\", \"i\"),\n    (r\"\\bucfie\\s*=\\s*([^;]*)\", \"i\"),\n    (r\"\\bhfucjrn\\s*=\\s*([^;]*)\", \"i\"),\n    (r\"\\bmvc\\s*=\\s*([^;]*)\", \"i\"),\n    (\n        r\"^((?:[\\w\"\n        + \"\\u0128-\\uffff\"\n        + r\"*_-]|\\\\.)+)(#)((?:[\\w\"\n        + \"\\u0128-\\uffff\"\n        + r\"*_-]|\\\\.)+)\",\n        \"\",\n    ),\n    (r\"^([>+~])\\s*(\\w*)\", \"i\"),\n    (r\"^>\\s*((?:[\\w\" + \"\\u0128-\\uffff\" + r\"*_-]|\\\\.)+)\", \"\"),\n    (r\"^[\\s[]?shapgvba\", \"\"),\n    (r\"v\\/g.tvs#(.*)\", \"i\"),\n    (r\"eaq_zbqobkva\", \"\"),\n    (r\";\\s*\", \"\"),\n    (r\"(\\$\\{inyhr\\})|(\\$inyhr\\b)\", \"g\"),\n    (r\"(\\$\\{abj\\})|(\\$abj\\b)\", \"g\"),\n    (r\"\\s+$\", \"\"),\n    (r\"^\\s+\", \"\"),\n    (\n        r\"(\\\\\\\"|\\x00-|\\x1f|\\x7f-|\\x9f|\"\n        + \"\\u00ad|\\u0600-|\\u0604|\\u070f|\\u17b4|\\u17b5|\\u200c-|\\u200f|\\u2028-|\\u202f|\\u2060-|\\u206f|\\ufeff|\\ufff0-|\\uffff\"\n        + r\")\",\n        \"g\",\n    ),\n    (r'^(:)([\\w-]+)\\(\"?\\'?(.*?(\\(.*?\\))?[^(]*?)\"?\\'?\\)', \"\"),\n    (r\"^([:.#]*)((?:[\\w\" + \"\\u0128-\\uffff\" + r\"*_-]|\\\\.)+)\", \"\"),\n    (r'^(\\[) *@?([\\w-]+) *([!*$^~=]*) *(\\'?\"?)(.*?)\\4 *\\]', \"\"),\n]\n\n\n# The V8 javascript engine only does one replacement unless the regexp has\n# the 'g' flag. Python's sub has count = 1 to do 1 replacement and count = 0\n# to replace all matches. We set this up here.\n\nregexs = []\nsubcount = []\n\nfor s in compiled_regex_strings:\n    if \"g\" in s[1]:\n        subcount.append(0)\n    else:\n        subcount.append(1)\n\n    if \"i\" in s[1]:\n        regexs.append(re.compile(s[0], re.IGNORECASE | re.UNICODE))\n    else:\n        regexs.append(re.compile(s[0], re.UNICODE))\n\n# The strings that were in vars in the V8 benchmark\n\nstrings = [\n    r\"Zbmvyyn/5.0 (Jvaqbjf; H; Jvaqbjf AG 5.1; ra-HF) NccyrJroXvg/528.9 (XUGZY, yvxr Trpxb) Puebzr/2.0.157.0 Fnsnev/528.9\",\n    r\"Fubpxjnir Synfu 9.0  e115\",\n    r'{\"anzr\":\"\",\"ahzoreSbezng\":{\"PheeraplQrpvznyQvtvgf\":2,\"PheeraplQrpvznyFrcnengbe\":\".\",\"VfErnqBayl\":gehr,\"PheeraplTebhcFvmrf\":[3],\"AhzoreTebhcFvmrf\":[3],\"CrepragTebhcFvmrf\":[3],\"PheeraplTebhcFrcnengbe\":\",\",\"PheeraplFlzoby\":\"\\xa4\",\"AnAFlzoby\":\"AnA\",\"PheeraplArtngvirCnggrea\":0,\"AhzoreArtngvirCnggrea\":1,\"CrepragCbfvgvirCnggrea\":0,\"CrepragArtngvirCnggrea\":0,\"ArtngvirVasvavglFlzoby\":\"-Vasvavgl\",\"ArtngvirFvta\":\"-\",\"AhzoreQrpvznyQvtvgf\":2,\"AhzoreQrpvznyFrcnengbe\":\".\",\"AhzoreTebhcFrcnengbe\":\",\",\"PheeraplCbfvgvirCnggrea\":0,\"CbfvgvirVasvavglFlzoby\":\"Vasvavgl\",\"CbfvgvirFvta\":\"+\",\"CrepragQrpvznyQvtvgf\":2,\"CrepragQrpvznyFrcnengbe\":\".\",\"CrepragTebhcFrcnengbe\":\",\",\"CrepragFlzoby\":\"%\",\"CreZvyyrFlzoby\":\"\\u2030\",\"AngvirQvtvgf\":[\"0\",\"1\",\"2\",\"3\",\"4\",\"5\",\"6\",\"7\",\"8\",\"9\"],\"QvtvgFhofgvghgvba\":1},\"qngrGvzrSbezng\":{\"NZQrfvtangbe\":\"NZ\",\"Pnyraqne\":{\"ZvaFhccbegrqQngrGvzr\":\"@-62135568000000@\",\"ZnkFhccbegrqQngrGvzr\":\"@253402300799999@\",\"NytbevguzGlcr\":1,\"PnyraqneGlcr\":1,\"Renf\":[1],\"GjbQvtvgLrneZnk\":2029,\"VfErnqBayl\":gehr},\"QngrFrcnengbe\":\"/\",\"SvefgQnlBsJrrx\":0,\"PnyraqneJrrxEhyr\":0,\"ShyyQngrGvzrCnggrea\":\"qqqq, qq ZZZZ llll UU:zz:ff\",\"YbatQngrCnggrea\":\"qqqq, qq ZZZZ llll\",\"YbatGvzrCnggrea\":\"UU:zz:ff\",\"ZbaguQnlCnggrea\":\"ZZZZ qq\",\"CZQrfvtangbe\":\"CZ\",\"ESP1123Cnggrea\":\"qqq, qq ZZZ llll UU\\':\\'zz\\':\\'ff \\'TZG\\'\",\"FubegQngrCnggrea\":\"ZZ/qq/llll\",\"FubegGvzrCnggrea\":\"UU:zz\",\"FbegnoyrQngrGvzrCnggrea\":\"llll\\'-\\'ZZ\\'-\\'qq\\'G\\'UU\\':\\'zz\\':\\'ff\",\"GvzrFrcnengbe\":\":\",\"HavirefnyFbegnoyrQngrGvzrCnggrea\":\"llll\\'-\\'ZZ\\'-\\'qq UU\\':\\'zz\\':\\'ff\\'M\\'\",\"LrneZbaguCnggrea\":\"llll ZZZZ\",\"NooerivngrqQnlAnzrf\":[\"Fha\",\"Zba\",\"Ghr\",\"Jrq\",\"Guh\",\"Sev\",\"Fng\"],\"FubegrfgQnlAnzrf\":[\"Fh\",\"Zb\",\"Gh\",\"Jr\",\"Gu\",\"Se\",\"Fn\"],\"QnlAnzrf\":[\"Fhaqnl\",\"Zbaqnl\",\"Ghrfqnl\",\"Jrqarfqnl\",\"Guhefqnl\",\"Sevqnl\",\"Fngheqnl\"],\"NooerivngrqZbaguAnzrf\":[\"Wna\",\"Sro\",\"Zne\",\"Nce\",\"Znl\",\"Wha\",\"Why\",\"Nht\",\"Frc\",\"Bpg\",\"Abi\",\"Qrp\",\"\"],\"ZbaguAnzrf\":[\"Wnahnel\",\"Sroehnel\",\"Znepu\",\"Ncevy\",\"Znl\",\"Whar\",\"Whyl\",\"Nhthfg\",\"Frcgrzore\",\"Bpgbore\",\"Abirzore\",\"Qrprzore\",\"\"],\"VfErnqBayl\":gehr,\"AngvirPnyraqneAnzr\":\"Tertbevna Pnyraqne\",\"NooerivngrqZbaguTravgvirAnzrf\":[\"Wna\",\"Sro\",\"Zne\",\"Nce\",\"Znl\",\"Wha\",\"Why\",\"Nht\",\"Frc\",\"Bpg\",\"Abi\",\"Qrp\",\"\"],\"ZbaguTravgvirAnzrf\":[\"Wnahnel\",\"Sroehnel\",\"Znepu\",\"Ncevy\",\"Znl\",\"Whar\",\"Whyl\",\"Nhthfg\",\"Frcgrzore\",\"Bpgbore\",\"Abirzore\",\"Qrprzore\",\"\"]}}',\n    r'{\"anzr\":\"ra-HF\",\"ahzoreSbezng\":{\"PheeraplQrpvznyQvtvgf\":2,\"PheeraplQrpvznyFrcnengbe\":\".\",\"VfErnqBayl\":snyfr,\"PheeraplTebhcFvmrf\":[3],\"AhzoreTebhcFvmrf\":[3],\"CrepragTebhcFvmrf\":[3],\"PheeraplTebhcFrcnengbe\":\",\",\"PheeraplFlzoby\":\"$\",\"AnAFlzoby\":\"AnA\",\"PheeraplArtngvirCnggrea\":0,\"AhzoreArtngvirCnggrea\":1,\"CrepragCbfvgvirCnggrea\":0,\"CrepragArtngvirCnggrea\":0,\"ArtngvirVasvavglFlzoby\":\"-Vasvavgl\",\"ArtngvirFvta\":\"-\",\"AhzoreQrpvznyQvtvgf\":2,\"AhzoreQrpvznyFrcnengbe\":\".\",\"AhzoreTebhcFrcnengbe\":\",\",\"PheeraplCbfvgvirCnggrea\":0,\"CbfvgvirVasvavglFlzoby\":\"Vasvavgl\",\"CbfvgvirFvta\":\"+\",\"CrepragQrpvznyQvtvgf\":2,\"CrepragQrpvznyFrcnengbe\":\".\",\"CrepragTebhcFrcnengbe\":\",\",\"CrepragFlzoby\":\"%\",\"CreZvyyrFlzoby\":\"\\u2030\",\"AngvirQvtvgf\":[\"0\",\"1\",\"2\",\"3\",\"4\",\"5\",\"6\",\"7\",\"8\",\"9\"],\"QvtvgFhofgvghgvba\":1},\"qngrGvzrSbezng\":{\"NZQrfvtangbe\":\"NZ\",\"Pnyraqne\":{\"ZvaFhccbegrqQngrGvzr\":\"@-62135568000000@\",\"ZnkFhccbegrqQngrGvzr\":\"@253402300799999@\",\"NytbevguzGlcr\":1,\"PnyraqneGlcr\":1,\"Renf\":[1],\"GjbQvtvgLrneZnk\":2029,\"VfErnqBayl\":snyfr},\"QngrFrcnengbe\":\"/\",\"SvefgQnlBsJrrx\":0,\"PnyraqneJrrxEhyr\":0,\"ShyyQngrGvzrCnggrea\":\"qqqq, ZZZZ qq, llll u:zz:ff gg\",\"YbatQngrCnggrea\":\"qqqq, ZZZZ qq, llll\",\"YbatGvzrCnggrea\":\"u:zz:ff gg\",\"ZbaguQnlCnggrea\":\"ZZZZ qq\",\"CZQrfvtangbe\":\"CZ\",\"ESP1123Cnggrea\":\"qqq, qq ZZZ llll UU\\':\\'zz\\':\\'ff \\'TZG\\'\",\"FubegQngrCnggrea\":\"Z/q/llll\",\"FubegGvzrCnggrea\":\"u:zz gg\",\"FbegnoyrQngrGvzrCnggrea\":\"llll\\'-\\'ZZ\\'-\\'qq\\'G\\'UU\\':\\'zz\\':\\'ff\",\"GvzrFrcnengbe\":\":\",\"HavirefnyFbegnoyrQngrGvzrCnggrea\":\"llll\\'-\\'ZZ\\'-\\'qq UU\\':\\'zz\\':\\'ff\\'M\\'\",\"LrneZbaguCnggrea\":\"ZZZZ, llll\",\"NooerivngrqQnlAnzrf\":[\"Fha\",\"Zba\",\"Ghr\",\"Jrq\",\"Guh\",\"Sev\",\"Fng\"],\"FubegrfgQnlAnzrf\":[\"Fh\",\"Zb\",\"Gh\",\"Jr\",\"Gu\",\"Se\",\"Fn\"],\"QnlAnzrf\":[\"Fhaqnl\",\"Zbaqnl\",\"Ghrfqnl\",\"Jrqarfqnl\",\"Guhefqnl\",\"Sevqnl\",\"Fngheqnl\"],\"NooerivngrqZbaguAnzrf\":[\"Wna\",\"Sro\",\"Zne\",\"Nce\",\"Znl\",\"Wha\",\"Why\",\"Nht\",\"Frc\",\"Bpg\",\"Abi\",\"Qrp\",\"\"],\"ZbaguAnzrf\":[\"Wnahnel\",\"Sroehnel\",\"Znepu\",\"Ncevy\",\"Znl\",\"Whar\",\"Whyl\",\"Nhthfg\",\"Frcgrzore\",\"Bpgbore\",\"Abirzore\",\"Qrprzore\",\"\"],\"VfErnqBayl\":snyfr,\"AngvirPnyraqneAnzr\":\"Tertbevna Pnyraqne\",\"NooerivngrqZbaguTravgvirAnzrf\":[\"Wna\",\"Sro\",\"Zne\",\"Nce\",\"Znl\",\"Wha\",\"Why\",\"Nht\",\"Frc\",\"Bpg\",\"Abi\",\"Qrp\",\"\"],\"ZbaguTravgvirAnzrf\":[\"Wnahnel\",\"Sroehnel\",\"Znepu\",\"Ncevy\",\"Znl\",\"Whar\",\"Whyl\",\"Nhthfg\",\"Frcgrzore\",\"Bpgbore\",\"Abirzore\",\"Qrprzore\",\"\"]}}',\n    r\"HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q\",\n    r\"HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=\",\n    r\"uggc://jjj.snprobbx.pbz/vaqrk.cuc\",\n    r';;jvaqbj.IjPurpxZbhfrCbfvgvbaNQ_VQ=shapgvba(r){vs(!r)ine r=jvaqbj.rirag;ine c=-1;vs(d1)c=d1.EbyybssCnary;ine bo=IjTrgBow(\"IjCnayNQ_VQ_\"+c);vs(bo&&bo.fglyr.ivfvovyvgl==\"ivfvoyr\"){ine fns=IjFns?8:0;ine pheK=r.pyvragK+IjBOFpe(\"U\")+fns,pheL=r.pyvragL+IjBOFpe(\"I\")+fns;ine y=IjBOEC(NQ_VQ,bo,\"Y\"),g=IjBOEC(NQ_VQ,bo,\"G\");ine e=y+d1.Cnaryf[c].Jvqgu,o=g+d1.Cnaryf[c].Urvtug;vs((pheK<y)||(pheK>e)||(pheL<g)||(pheL>o)){vs(jvaqbj.IjBaEbyybssNQ_VQ)IjBaEbyybssNQ_VQ(c);ryfr IjPybfrNq(NQ_VQ,c,gehr,\"\");}ryfr erghea;}IjPnapryZbhfrYvfgrareNQ_VQ();};;jvaqbj.IjFrgEbyybssCnaryNQ_VQ=shapgvba(c){ine z=\"zbhfrzbir\",q=qbphzrag,s=IjPurpxZbhfrCbfvgvbaNQ_VQ;c=IjTc(NQ_VQ,c);vs(d1&&d1.EbyybssCnary>-1)IjPnapryZbhfrYvfgrareNQ_VQ();vs(d1)d1.EbyybssCnary=c;gel{vs(q.nqqRiragYvfgrare)q.nqqRiragYvfgrare(z,s,snyfr);ryfr vs(q.nggnpuRirag)q.nggnpuRirag(\"ba\"+z,s);}pngpu(r){}};;jvaqbj.IjPnapryZbhfrYvfgrareNQ_VQ=shapgvba(){ine z=\"zbhfrzbir\",q=qbphzrag,s=IjPurpxZbhfrCbfvgvbaNQ_VQ;vs(d1)d1.EbyybssCnary=-1;gel{vs(q.erzbirRiragYvfgrare)q.erzbirRiragYvfgrare(z,s,snyfr);ryfr vs(q.qrgnpuRirag)q.qrgnpuRirag(\"ba\"+z,s);}pngpu(r){}};;d1.IjTc=d2(n,c){ine nq=d1;vs(vfAnA(c)){sbe(ine v=0;v<nq.Cnaryf.yratgu;v++)vs(nq.Cnaryf[v].Anzr==c)erghea v;erghea 0;}erghea c;};;d1.IjTpy=d2(n,c,p){ine cn=d1.Cnaryf[IjTc(n,c)];vs(!cn)erghea 0;vs(vfAnA(p)){sbe(ine v=0;v<cn.Pyvpxguehf.yratgu;v++)vs(cn.Pyvpxguehf[v].Anzr==p)erghea v;erghea 0;}erghea p;};;d1.IjGenpr=d2(n,f){gel{vs(jvaqbj[\"Ij\"+\"QtQ\"])jvaqbj[\"Ij\"+\"QtQ\"](n,1,f);}pngpu(r){}};;d1.IjYvzvg1=d2(n,f){ine nq=d1,vh=f.fcyvg(\"/\");sbe(ine v=0,p=0;v<vh.yratgu;v++){vs(vh[v].yratgu>0){vs(nq.FzV.yratgu>0)nq.FzV+=\"/\";nq.FzV+=vh[v];nq.FtZ[nq.FtZ.yratgu]=snyfr;}}};;d1.IjYvzvg0=d2(n,f){ine nq=d1,vh=f.fcyvg(\"/\");sbe(ine v=0;v<vh.yratgu;v++){vs(vh[v].yratgu>0){vs(nq.OvC.yratgu>0)nq.OvC+=\"/\";nq.OvC+=vh[v];}}};;d1.IjRVST=d2(n,c){jvaqbj[\"IjCnayNQ_VQ_\"+c+\"_Bow\"]=IjTrgBow(\"IjCnayNQ_VQ_\"+c+\"_Bow\");vs(jvaqbj[\"IjCnayNQ_VQ_\"+c+\"_Bow\"]==ahyy)frgGvzrbhg(\"IjRVST(NQ_VQ,\"+c+\")\",d1.rvsg);};;d1.IjNavzSHC=d2(n,c){ine nq=d1;vs(c>nq.Cnaryf.yratgu)erghea;ine cna=nq.Cnaryf[c],nn=gehr,on=gehr,yn=gehr,en=gehr,cn=nq.Cnaryf[0],sf=nq.ShF,j=cn.Jvqgu,u=cn.Urvtug;vs(j==\"100%\"){j=sf;en=snyfr;yn=snyfr;}vs(u==\"100%\"){u=sf;nn=snyfr;on=snyfr;}vs(cn.YnY==\"Y\")yn=snyfr;vs(cn.YnY==\"E\")en=snyfr;vs(cn.GnY==\"G\")nn=snyfr;vs(cn.GnY==\"O\")on=snyfr;ine k=0,l=0;fjvgpu(nq.NshP%8){pnfr 0:oernx;pnfr 1:vs(nn)l=-sf;oernx;pnfr 2:k=j-sf;oernx;pnfr 3:vs(en)k=j;oernx;pnfr 4:k=j-sf;l=u-sf;oernx;pnfr 5:k=j-sf;vs(on)l=u;oernx;pnfr 6:l=u-sf;oernx;pnfr 7:vs(yn)k=-sf;l=u-sf;oernx;}vs(nq.NshP++ <nq.NshG)frgGvzrbhg((\"IjNavzSHC(NQ_VQ,\"+c+\")\"),nq.NshC);ryfr{k=-1000;l=k;}cna.YrsgBssfrg=k;cna.GbcBssfrg=l;IjNhErcb(n,c);};;d1.IjTrgErnyCbfvgvba=d2(n,b,j){erghea IjBOEC.nccyl(guvf,nethzragf);};;d1.IjPnapryGvzrbhg=d2(n,c){c=IjTc(n,c);ine cay=d1.Cnaryf[c];vs(cay&&cay.UgU!=\"\"){pyrneGvzrbhg(cay.UgU);}};;d1.IjPnapryNyyGvzrbhgf=d2(n){vs(d1.YbpxGvzrbhgPunatrf)erghea;sbe(ine c=0;c<d1.bac;c++)IjPnapryGvzrbhg(n,c);};;d1.IjFgnegGvzrbhg=d2(n,c,bG){c=IjTc(n,c);ine cay=d1.Cnaryf[c];vs(cay&&((cay.UvqrGvzrbhgInyhr>0)||(nethzragf.yratgu==3&&bG>0))){pyrneGvzrbhg(cay.UgU);cay.UgU=frgGvzrbhg(cay.UvqrNpgvba,(nethzragf.yratgu==3?bG:cay.UvqrGvzrbhgInyhr));}};;d1.IjErfrgGvzrbhg=d2(n,c,bG){c=IjTc(n,c);IjPnapryGvzrbhg(n,c);riny(\"IjFgnegGvzrbhg(NQ_VQ,c\"+(nethzragf.yratgu==3?\",bG\":\"\")+\")\");};;d1.IjErfrgNyyGvzrbhgf=d2(n){sbe(ine c=0;c<d1.bac;c++)IjErfrgGvzrbhg(n,c);};;d1.IjQrgnpure=d2(n,rig,sap){gel{vs(IjQVR5)riny(\"jvaqbj.qrgnpuRirag(\\'ba\"+rig+\"\\',\"+sap+\"NQ_VQ)\");ryfr vs(!IjQVRZnp)riny(\"jvaqbj.erzbirRiragYvfgrare(\\'\"+rig+\"\\',\"+sap+\"NQ_VQ,snyfr)\");}pngpu(r){}};;d1.IjPyrnaHc=d2(n){IjCvat(n,\"G\");ine nq=d1;sbe(ine v=0;v<nq.Cnaryf.yratgu;v++){IjUvqrCnary(n,v,gehr);}gel{IjTrgBow(nq.gya).vaareUGZY=\"\";}pngpu(r){}vs(nq.gya!=nq.gya2)gel{IjTrgBow(nq.gya2).vaareUGZY=\"\";}pngpu(r){}gel{d1=ahyy;}pngpu(r){}gel{IjQrgnpure(n,\"haybnq\",\"IjHayNQ_VQ\");}pngpu(r){}gel{jvaqbj.IjHayNQ_VQ=ahyy;}pngpu(r){}gel{IjQrgnpure(n,\"fpebyy\",\"IjFeNQ_VQ\");}pngpu(r){}gel{jvaqbj.IjFeNQ_VQ=ahyy;}pngpu(r){}gel{IjQrgnpure(n,\"erfvmr\",\"IjEmNQ_VQ\");}pngpu(r){}gel{jvaqbj.IjEmNQ_VQ=ahyy;}pngpu(r){}gel{IjQrgnpure(n',\n    r';;jvaqbj.IjPurpxZbhfrCbfvgvbaNQ_VQ=shapgvba(r){vs(!r)ine r=jvaqbj.rirag;ine c=-1;vs(jvaqbj.IjNqNQ_VQ)c=jvaqbj.IjNqNQ_VQ.EbyybssCnary;ine bo=IjTrgBow(\"IjCnayNQ_VQ_\"+c);vs(bo&&bo.fglyr.ivfvovyvgl==\"ivfvoyr\"){ine fns=IjFns?8:0;ine pheK=r.pyvragK+IjBOFpe(\"U\")+fns,pheL=r.pyvragL+IjBOFpe(\"I\")+fns;ine y=IjBOEC(NQ_VQ,bo,\"Y\"),g=IjBOEC(NQ_VQ,bo,\"G\");ine e=y+jvaqbj.IjNqNQ_VQ.Cnaryf[c].Jvqgu,o=g+jvaqbj.IjNqNQ_VQ.Cnaryf[c].Urvtug;vs((pheK<y)||(pheK>e)||(pheL<g)||(pheL>o)){vs(jvaqbj.IjBaEbyybssNQ_VQ)IjBaEbyybssNQ_VQ(c);ryfr IjPybfrNq(NQ_VQ,c,gehr,\"\");}ryfr erghea;}IjPnapryZbhfrYvfgrareNQ_VQ();};;jvaqbj.IjFrgEbyybssCnaryNQ_VQ=shapgvba(c){ine z=\"zbhfrzbir\",q=qbphzrag,s=IjPurpxZbhfrCbfvgvbaNQ_VQ;c=IjTc(NQ_VQ,c);vs(jvaqbj.IjNqNQ_VQ&&jvaqbj.IjNqNQ_VQ.EbyybssCnary>-1)IjPnapryZbhfrYvfgrareNQ_VQ();vs(jvaqbj.IjNqNQ_VQ)jvaqbj.IjNqNQ_VQ.EbyybssCnary=c;gel{vs(q.nqqRiragYvfgrare)q.nqqRiragYvfgrare(z,s,snyfr);ryfr vs(q.nggnpuRirag)q.nggnpuRirag(\"ba\"+z,s);}pngpu(r){}};;jvaqbj.IjPnapryZbhfrYvfgrareNQ_VQ=shapgvba(){ine z=\"zbhfrzbir\",q=qbphzrag,s=IjPurpxZbhfrCbfvgvbaNQ_VQ;vs(jvaqbj.IjNqNQ_VQ)jvaqbj.IjNqNQ_VQ.EbyybssCnary=-1;gel{vs(q.erzbirRiragYvfgrare)q.erzbirRiragYvfgrare(z,s,snyfr);ryfr vs(q.qrgnpuRirag)q.qrgnpuRirag(\"ba\"+z,s);}pngpu(r){}};;jvaqbj.IjNqNQ_VQ.IjTc=shapgvba(n,c){ine nq=jvaqbj.IjNqNQ_VQ;vs(vfAnA(c)){sbe(ine v=0;v<nq.Cnaryf.yratgu;v++)vs(nq.Cnaryf[v].Anzr==c)erghea v;erghea 0;}erghea c;};;jvaqbj.IjNqNQ_VQ.IjTpy=shapgvba(n,c,p){ine cn=jvaqbj.IjNqNQ_VQ.Cnaryf[IjTc(n,c)];vs(!cn)erghea 0;vs(vfAnA(p)){sbe(ine v=0;v<cn.Pyvpxguehf.yratgu;v++)vs(cn.Pyvpxguehf[v].Anzr==p)erghea v;erghea 0;}erghea p;};;jvaqbj.IjNqNQ_VQ.IjGenpr=shapgvba(n,f){gel{vs(jvaqbj[\"Ij\"+\"QtQ\"])jvaqbj[\"Ij\"+\"QtQ\"](n,1,f);}pngpu(r){}};;jvaqbj.IjNqNQ_VQ.IjYvzvg1=shapgvba(n,f){ine nq=jvaqbj.IjNqNQ_VQ,vh=f.fcyvg(\"/\");sbe(ine v=0,p=0;v<vh.yratgu;v++){vs(vh[v].yratgu>0){vs(nq.FzV.yratgu>0)nq.FzV+=\"/\";nq.FzV+=vh[v];nq.FtZ[nq.FtZ.yratgu]=snyfr;}}};;jvaqbj.IjNqNQ_VQ.IjYvzvg0=shapgvba(n,f){ine nq=jvaqbj.IjNqNQ_VQ,vh=f.fcyvg(\"/\");sbe(ine v=0;v<vh.yratgu;v++){vs(vh[v].yratgu>0){vs(nq.OvC.yratgu>0)nq.OvC+=\"/\";nq.OvC+=vh[v];}}};;jvaqbj.IjNqNQ_VQ.IjRVST=shapgvba(n,c){jvaqbj[\"IjCnayNQ_VQ_\"+c+\"_Bow\"]=IjTrgBow(\"IjCnayNQ_VQ_\"+c+\"_Bow\");vs(jvaqbj[\"IjCnayNQ_VQ_\"+c+\"_Bow\"]==ahyy)frgGvzrbhg(\"IjRVST(NQ_VQ,\"+c+\")\",jvaqbj.IjNqNQ_VQ.rvsg);};;jvaqbj.IjNqNQ_VQ.IjNavzSHC=shapgvba(n,c){ine nq=jvaqbj.IjNqNQ_VQ;vs(c>nq.Cnaryf.yratgu)erghea;ine cna=nq.Cnaryf[c],nn=gehr,on=gehr,yn=gehr,en=gehr,cn=nq.Cnaryf[0],sf=nq.ShF,j=cn.Jvqgu,u=cn.Urvtug;vs(j==\"100%\"){j=sf;en=snyfr;yn=snyfr;}vs(u==\"100%\"){u=sf;nn=snyfr;on=snyfr;}vs(cn.YnY==\"Y\")yn=snyfr;vs(cn.YnY==\"E\")en=snyfr;vs(cn.GnY==\"G\")nn=snyfr;vs(cn.GnY==\"O\")on=snyfr;ine k=0,l=0;fjvgpu(nq.NshP%8){pnfr 0:oernx;pnfr 1:vs(nn)l=-sf;oernx;pnfr 2:k=j-sf;oernx;pnfr 3:vs(en)k=j;oernx;pnfr 4:k=j-sf;l=u-sf;oernx;pnfr 5:k=j-sf;vs(on)l=u;oernx;pnfr 6:l=u-sf;oernx;pnfr 7:vs(yn)k=-sf;l=u-sf;oernx;}vs(nq.NshP++ <nq.NshG)frgGvzrbhg((\"IjNavzSHC(NQ_VQ,\"+c+\")\"),nq.NshC);ryfr{k=-1000;l=k;}cna.YrsgBssfrg=k;cna.GbcBssfrg=l;IjNhErcb(n,c);};;jvaqbj.IjNqNQ_VQ.IjTrgErnyCbfvgvba=shapgvba(n,b,j){erghea IjBOEC.nccyl(guvf,nethzragf);};;jvaqbj.IjNqNQ_VQ.IjPnapryGvzrbhg=shapgvba(n,c){c=IjTc(n,c);ine cay=jvaqbj.IjNqNQ_VQ.Cnaryf[c];vs(cay&&cay.UgU!=\"\"){pyrneGvzrbhg(cay.UgU);}};;jvaqbj.IjNqNQ_VQ.IjPnapryNyyGvzrbhgf=shapgvba(n){vs(jvaqbj.IjNqNQ_VQ.YbpxGvzrbhgPunatrf)erghea;sbe(ine c=0;c<jvaqbj.IjNqNQ_VQ.bac;c++)IjPnapryGvzrbhg(n,c);};;jvaqbj.IjNqNQ_VQ.IjFgnegGvzrbhg=shapgvba(n,c,bG){c=IjTc(n,c);ine cay=jvaqbj.IjNqNQ_VQ.Cnaryf[c];vs(cay&&((cay.UvqrGvzrbhgInyhr>0)||(nethzragf.yratgu==3&&bG>0))){pyrneGvzrbhg(cay.UgU);cay.UgU=frgGvzrbhg(cay.UvqrNpgvba,(nethzragf.yratgu==3?bG:cay.UvqrGvzrbhgInyhr));}};;jvaqbj.IjNqNQ_VQ.IjErfrgGvzrbhg=shapgvba(n,c,bG){c=IjTc(n,c);IjPnapryGvzrbhg(n,c);riny(\"IjFgnegGvzrbhg(NQ_VQ,c\"+(nethzragf.yratgu==3?\",bG\":\"\")+\")\");};;jvaqbj.IjNqNQ_VQ.IjErfrgNyyGvzrbhgf=shapgvba(n){sbe(ine c=0;c<jvaqbj.IjNqNQ_VQ.bac;c++)IjErfrgGvzrbhg(n,c);};;jvaqbj.IjNqNQ_VQ.IjQrgnpure=shapgvba(n,rig,sap){gel{vs(IjQVR5)riny(\"jvaqbj.qrgnpuRirag(\\'ba\"+rig+\"\\',\"+sap+\"NQ_VQ)\");ryfr vs(!IjQVRZnp)riny(\"jvaqbj.erzbir',\n    r';;jvaqbj.IjPurpxZbhfrCbfvgvbaNQ_VQ=shapgvba(r){vs(!r)ine r=jvaqbj.rirag;ine c=-1;vs(jvaqbj.IjNqNQ_VQ)c=jvaqbj.IjNqNQ_VQ.EbyybssCnary;ine bo=IjTrgBow(\"IjCnayNQ_VQ_\"+c);vs(bo&&bo.fglyr.ivfvovyvgl==\"ivfvoyr\"){ine fns=IjFns?8:0;ine pheK=r.pyvragK+IjBOFpe(\"U\")+fns,pheL=r.pyvragL+IjBOFpe(\"I\")+fns;ine y=IjBOEC(NQ_VQ,bo,\"Y\"),g=IjBOEC(NQ_VQ,bo,\"G\");ine e=y+jvaqbj.IjNqNQ_VQ.Cnaryf[c].Jvqgu,o=g+jvaqbj.IjNqNQ_VQ.Cnaryf[c].Urvtug;vs((pheK<y)||(pheK>e)||(pheL<g)||(pheL>o)){vs(jvaqbj.IjBaEbyybssNQ_VQ)IjBaEbyybssNQ_VQ(c);ryfr IjPybfrNq(NQ_VQ,c,gehr,\"\");}ryfr erghea;}IjPnapryZbhfrYvfgrareNQ_VQ();};;jvaqbj.IjFrgEbyybssCnaryNQ_VQ=shapgvba(c){ine z=\"zbhfrzbir\",q=qbphzrag,s=IjPurpxZbhfrCbfvgvbaNQ_VQ;c=IjTc(NQ_VQ,c);vs(jvaqbj.IjNqNQ_VQ&&jvaqbj.IjNqNQ_VQ.EbyybssCnary>-1)IjPnapryZbhfrYvfgrareNQ_VQ();vs(jvaqbj.IjNqNQ_VQ)jvaqbj.IjNqNQ_VQ.EbyybssCnary=c;gel{vs(q.nqqRiragYvfgrare)q.nqqRiragYvfgrare(z,s,snyfr);ryfr vs(q.nggnpuRirag)q.nggnpuRirag(\"ba\"+z,s);}pngpu(r){}};;jvaqbj.IjPnapryZbhfrYvfgrareNQ_VQ=shapgvba(){ine z=\"zbhfrzbir\",q=qbphzrag,s=IjPurpxZbhfrCbfvgvbaNQ_VQ;vs(jvaqbj.IjNqNQ_VQ)jvaqbj.IjNqNQ_VQ.EbyybssCnary=-1;gel{vs(q.erzbirRiragYvfgrare)q.erzbirRiragYvfgrare(z,s,snyfr);ryfr vs(q.qrgnpuRirag)q.qrgnpuRirag(\"ba\"+z,s);}pngpu(r){}};;jvaqbj.IjNqNQ_VQ.IjTc=d2(n,c){ine nq=jvaqbj.IjNqNQ_VQ;vs(vfAnA(c)){sbe(ine v=0;v<nq.Cnaryf.yratgu;v++)vs(nq.Cnaryf[v].Anzr==c)erghea v;erghea 0;}erghea c;};;jvaqbj.IjNqNQ_VQ.IjTpy=d2(n,c,p){ine cn=jvaqbj.IjNqNQ_VQ.Cnaryf[IjTc(n,c)];vs(!cn)erghea 0;vs(vfAnA(p)){sbe(ine v=0;v<cn.Pyvpxguehf.yratgu;v++)vs(cn.Pyvpxguehf[v].Anzr==p)erghea v;erghea 0;}erghea p;};;jvaqbj.IjNqNQ_VQ.IjGenpr=d2(n,f){gel{vs(jvaqbj[\"Ij\"+\"QtQ\"])jvaqbj[\"Ij\"+\"QtQ\"](n,1,f);}pngpu(r){}};;jvaqbj.IjNqNQ_VQ.IjYvzvg1=d2(n,f){ine nq=jvaqbj.IjNqNQ_VQ,vh=f.fcyvg(\"/\");sbe(ine v=0,p=0;v<vh.yratgu;v++){vs(vh[v].yratgu>0){vs(nq.FzV.yratgu>0)nq.FzV+=\"/\";nq.FzV+=vh[v];nq.FtZ[nq.FtZ.yratgu]=snyfr;}}};;jvaqbj.IjNqNQ_VQ.IjYvzvg0=d2(n,f){ine nq=jvaqbj.IjNqNQ_VQ,vh=f.fcyvg(\"/\");sbe(ine v=0;v<vh.yratgu;v++){vs(vh[v].yratgu>0){vs(nq.OvC.yratgu>0)nq.OvC+=\"/\";nq.OvC+=vh[v];}}};;jvaqbj.IjNqNQ_VQ.IjRVST=d2(n,c){jvaqbj[\"IjCnayNQ_VQ_\"+c+\"_Bow\"]=IjTrgBow(\"IjCnayNQ_VQ_\"+c+\"_Bow\");vs(jvaqbj[\"IjCnayNQ_VQ_\"+c+\"_Bow\"]==ahyy)frgGvzrbhg(\"IjRVST(NQ_VQ,\"+c+\")\",jvaqbj.IjNqNQ_VQ.rvsg);};;jvaqbj.IjNqNQ_VQ.IjNavzSHC=d2(n,c){ine nq=jvaqbj.IjNqNQ_VQ;vs(c>nq.Cnaryf.yratgu)erghea;ine cna=nq.Cnaryf[c],nn=gehr,on=gehr,yn=gehr,en=gehr,cn=nq.Cnaryf[0],sf=nq.ShF,j=cn.Jvqgu,u=cn.Urvtug;vs(j==\"100%\"){j=sf;en=snyfr;yn=snyfr;}vs(u==\"100%\"){u=sf;nn=snyfr;on=snyfr;}vs(cn.YnY==\"Y\")yn=snyfr;vs(cn.YnY==\"E\")en=snyfr;vs(cn.GnY==\"G\")nn=snyfr;vs(cn.GnY==\"O\")on=snyfr;ine k=0,l=0;fjvgpu(nq.NshP%8){pnfr 0:oernx;pnfr 1:vs(nn)l=-sf;oernx;pnfr 2:k=j-sf;oernx;pnfr 3:vs(en)k=j;oernx;pnfr 4:k=j-sf;l=u-sf;oernx;pnfr 5:k=j-sf;vs(on)l=u;oernx;pnfr 6:l=u-sf;oernx;pnfr 7:vs(yn)k=-sf;l=u-sf;oernx;}vs(nq.NshP++ <nq.NshG)frgGvzrbhg((\"IjNavzSHC(NQ_VQ,\"+c+\")\"),nq.NshC);ryfr{k=-1000;l=k;}cna.YrsgBssfrg=k;cna.GbcBssfrg=l;IjNhErcb(n,c);};;jvaqbj.IjNqNQ_VQ.IjTrgErnyCbfvgvba=d2(n,b,j){erghea IjBOEC.nccyl(guvf,nethzragf);};;jvaqbj.IjNqNQ_VQ.IjPnapryGvzrbhg=d2(n,c){c=IjTc(n,c);ine cay=jvaqbj.IjNqNQ_VQ.Cnaryf[c];vs(cay&&cay.UgU!=\"\"){pyrneGvzrbhg(cay.UgU);}};;jvaqbj.IjNqNQ_VQ.IjPnapryNyyGvzrbhgf=d2(n){vs(jvaqbj.IjNqNQ_VQ.YbpxGvzrbhgPunatrf)erghea;sbe(ine c=0;c<jvaqbj.IjNqNQ_VQ.bac;c++)IjPnapryGvzrbhg(n,c);};;jvaqbj.IjNqNQ_VQ.IjFgnegGvzrbhg=d2(n,c,bG){c=IjTc(n,c);ine cay=jvaqbj.IjNqNQ_VQ.Cnaryf[c];vs(cay&&((cay.UvqrGvzrbhgInyhr>0)||(nethzragf.yratgu==3&&bG>0))){pyrneGvzrbhg(cay.UgU);cay.UgU=frgGvzrbhg(cay.UvqrNpgvba,(nethzragf.yratgu==3?bG:cay.UvqrGvzrbhgInyhr));}};;jvaqbj.IjNqNQ_VQ.IjErfrgGvzrbhg=d2(n,c,bG){c=IjTc(n,c);IjPnapryGvzrbhg(n,c);riny(\"IjFgnegGvzrbhg(NQ_VQ,c\"+(nethzragf.yratgu==3?\",bG\":\"\")+\")\");};;jvaqbj.IjNqNQ_VQ.IjErfrgNyyGvzrbhgf=d2(n){sbe(ine c=0;c<jvaqbj.IjNqNQ_VQ.bac;c++)IjErfrgGvzrbhg(n,c);};;jvaqbj.IjNqNQ_VQ.IjQrgnpure=d2(n,rig,sap){gel{vs(IjQVR5)riny(\"jvaqbj.qrgnpuRirag(\\'ba\"+rig+\"\\',\"+sap+\"NQ_VQ)\");ryfr vs(!IjQVRZnp)riny(\"jvaqbj.erzbirRiragYvfgrare(\\'\"+rig+\"\\',\"+sap+\"NQ_VQ,snyfr)\");}pngpu(r){}};;jvaqbj.IjNqNQ_VQ.IjPyrna',\n    r\"FrffvbaQQS2=111soqs57qo8o8480qo18sor2011r3n591q7s6s37r120904; ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669315660164980&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=\",\n    r\"FrffvbaQQS2=111soqs57qo8o8480qo18sor2011r3n591q7s6s37r120904; __hgzm=144631658.1231363570.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar); __hgzn=144631658.3426875219718084000.1231363570.1231363570.1231363570.1; __hgzo=144631658.0.10.1231363570; __hgzp=144631658; ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669315660164980&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q\",\n    r\"uggc://tbbtyrnqf.t.qbhoyrpyvpx.arg/cntrnq/nqf?pyvrag=pn-svz_zlfcnpr_zlfcnpr-ubzrcntr_wf&qg=1231363514065&uy=ra&nqfnsr=uvtu&br=hgs8&ahz_nqf=4&bhgchg=wf&nqgrfg=bss&pbeeryngbe=1231363514065&punaary=svz_zlfcnpr_ubzrcntr_abgybttrqva%2Psvz_zlfcnpr_aba_HTP%2Psvz_zlfcnpr_havgrq-fgngrf&hey=uggc%3N%2S%2Subzr.zlfcnpr.pbz%2Svaqrk.psz&nq_glcr=grkg&rvq=6083027&rn=0&sez=0&tn_ivq=1326469221.1231363557&tn_fvq=1231363557&tn_uvq=1114636509&synfu=9.0.115&h_u=768&h_j=1024&h_nu=738&h_nj=1024&h_pq=24&h_gm=-480&h_uvf=2&h_wnin=gehr&h_acyht=7&h_azvzr=22\",\n    r\"ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669315660164980&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q\",\n    r\"ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669315660164980&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=\",\n    r\"FrffvbaQQS2=s6r4579npn4rn2135s904r0s75pp1o5334p6s6pospo12696; ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669316860113296&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=; AFP_zp_dfctwzs-aowb_80=44132r503660\",\n    r\"FrffvbaQQS2=s6r4579npn4rn2135s904r0s75pp1o5334p6s6pospo12696; AFP_zp_dfctwzs-aowb_80=44132r503660; __hgzm=144631658.1231363638.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar); __hgzn=144631658.965867047679498800.1231363638.1231363638.1231363638.1; __hgzo=144631658.0.10.1231363638; __hgzp=144631658; ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669316860113296&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q\",\n    r\"uggc://tbbtyrnqf.t.qbhoyrpyvpx.arg/cntrnq/nqf?pyvrag=pn-svz_zlfcnpr_zlfcnpr-ubzrcntr_wf&qg=1231363621014&uy=ra&nqfnsr=uvtu&br=hgs8&ahz_nqf=4&bhgchg=wf&nqgrfg=bss&pbeeryngbe=1231363621014&punaary=svz_zlfcnpr_ubzrcntr_abgybttrqva%2Psvz_zlfcnpr_aba_HTP%2Psvz_zlfcnpr_havgrq-fgngrf&hey=uggc%3N%2S%2Scebsvyr.zlfcnpr.pbz%2Svaqrk.psz&nq_glcr=grkg&rvq=6083027&rn=0&sez=0&tn_ivq=348699119.1231363624&tn_fvq=1231363624&tn_uvq=895511034&synfu=9.0.115&h_u=768&h_j=1024&h_nu=738&h_nj=1024&h_pq=24&h_gm=-480&h_uvf=2&h_wnin=gehr&h_acyht=7&h_azvzr=22\",\n    r\"uggc://jjj.yrobapbva.se/yv\",\n    r\"ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669316860113296&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q\",\n    r\"ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669316860113296&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=\",\n    r\"FrffvbaQQS2=s15q53p9n372sn76npr13o271n4s3p5r29p235746p908p58; ZFPhygher=VC=66.249.85.130&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669358527244818&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=\",\n    r\"FrffvbaQQS2=s15q53p9n372sn76npr13o271n4s3p5r29p235746p908p58; __hgzm=144631658.1231367822.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar); __hgzn=144631658.4127520630321984500.1231367822.1231367822.1231367822.1; __hgzo=144631658.0.10.1231367822; __hgzp=144631658; ZFPhygher=VC=66.249.85.130&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669358527244818&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q\",\n    r\"uggc://tbbtyrnqf.t.qbhoyrpyvpx.arg/cntrnq/nqf?pyvrag=pn-svz_zlfcnpr_zlfcnpr-ubzrcntr_wf&qg=1231367803797&uy=ra&nqfnsr=uvtu&br=hgs8&ahz_nqf=4&bhgchg=wf&nqgrfg=bss&pbeeryngbe=1231367803797&punaary=svz_zlfcnpr_ubzrcntr_abgybttrqva%2Psvz_zlfcnpr_aba_HTP%2Psvz_zlfcnpr_havgrq-fgngrf&hey=uggc%3N%2S%2Szrffntvat.zlfcnpr.pbz%2Svaqrk.psz&nq_glcr=grkg&rvq=6083027&rn=0&sez=0&tn_ivq=1192552091.1231367807&tn_fvq=1231367807&tn_uvq=1155446857&synfu=9.0.115&h_u=768&h_j=1024&h_nu=738&h_nj=1024&h_pq=24&h_gm=-480&h_uvf=2&h_wnin=gehr&h_acyht=7&h_azvzr=22\",\n    r\"ZFPhygher=VC=66.249.85.130&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669358527244818&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q\",\n    r\"ZFPhygher=VC=66.249.85.130&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669358527244818&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=\",\n    r\"hy.ynat-fryrpgbe\",\n    r'<hy pynff=\"nqi\">##yv4##Cbjreshy Zvpebfbsg grpuabybtl urycf svtug fcnz naq vzcebir frphevgl.##yv19##Trg zber qbar gunaxf gb terngre rnfr naq fcrrq.##yv16##Ybgf bs fgbentr &#40;5 TO&#41; - zber pbby fghss ba gur jnl.##OE## ##OE## ##N##Yrnea zber##/N##</hy>',\n    r'<hy pynff=\"nqi\"><yv vq=\"YvOYG4\" fglyr=\"onpxtebhaq-vzntr:hey(uggc://vzt.jykef.pbz/~Yvir.FvgrPbagrag.VQ/~14.2.1230/~/~/~/oyg4.cat)\">Cbjreshy Zvpebfbsg grpuabybtl urycf svtug fcnz naq vzcebir frphevgl.##yv19##Trg zber qbar gunaxf gb terngre rnfr naq fcrrq.##yv16##Ybgf bs fgbentr &#40;5 TO&#41; - zber pbby fghss ba gur jnl.##OE## ##OE## ##N##Yrnea zber##/N##</hy>',\n    r'<hy pynff=\"nqi\"><yv vq=\"YvOYG4\" fglyr=\"onpxtebhaq-vzntr:hey(uggc://vzt.jykef.pbz/~Yvir.FvgrPbagrag.VQ/~14.2.1230/~/~/~/oyg4.cat)\">Cbjreshy Zvpebfbsg grpuabybtl urycf svtug fcnz naq vzcebir frphevgl.##yv19##Trg zber qbar gunaxf gb terngre rnfr naq fcrrq.<yv vq=\"YvOYG16\" fglyr=\"onpxtebhaq-vzntr:hey(uggc://vzt.jykef.pbz/~Yvir.FvgrPbagrag.VQ/~14.2.1230/~/~/~/oyg16.cat)\">Ybgf bs fgbentr &#40;5 TO&#41; - zber pbby fghss ba gur jnl.##OE## ##OE## ##N##Yrnea zber##/N##</hy>',\n    r'<hy pynff=\"nqi\"><yv vq=\"YvOYG4\" fglyr=\"onpxtebhaq-vzntr:hey(uggc://vzt.jykef.pbz/~Yvir.FvgrPbagrag.VQ/~14.2.1230/~/~/~/oyg4.cat)\">Cbjreshy Zvpebfbsg grpuabybtl urycf svtug fcnz naq vzcebir frphevgl.<yv vq=\"YvOYG19\" fglyr=\"onpxtebhaq-vzntr:hey(uggc://vzt.jykef.pbz/~Yvir.FvgrPbagrag.VQ/~14.2.1230/~/~/~/oyg19.cat)\">Trg zber qbar gunaxf gb terngre rnfr naq fcrrq.<yv vq=\"YvOYG16\" fglyr=\"onpxtebhaq-vzntr:hey(uggc://vzt.jykef.pbz/~Yvir.FvgrPbagrag.VQ/~14.2.1230/~/~/~/oyg16.cat)\">Ybgf bs fgbentr &#40;5 TO&#41; - zber pbby fghss ba gur jnl.##OE## ##OE## ##N##Yrnea zber##/N##</hy>',\n    r'<hy pynff=\"nqi\"><yv vq=\"YvOYG4\" fglyr=\"onpxtebhaq-vzntr:hey(uggc://vzt.jykef.pbz/~Yvir.FvgrPbagrag.VQ/~14.2.1230/~/~/~/oyg4.cat)\">Cbjreshy Zvpebfbsg grpuabybtl urycf svtug fcnz naq vzcebir frphevgl.<yv vq=\"YvOYG19\" fglyr=\"onpxtebhaq-vzntr:hey(uggc://vzt.jykef.pbz/~Yvir.FvgrPbagrag.VQ/~14.2.1230/~/~/~/oyg19.cat)\">Trg zber qbar gunaxf gb terngre rnfr naq fcrrq.<yv vq=\"YvOYG16\" fglyr=\"onpxtebhaq-vzntr:hey(uggc://vzt.jykef.pbz/~Yvir.FvgrPbagrag.VQ/~14.2.1230/~/~/~/oyg16.cat)\">Ybgf bs fgbentr &#40;5 TO&#41; - zber pbby fghss ba gur jnl.<oe> <oe> ##N##Yrnea zber##/N##</hy>',\n    r'<hy pynff=\"nqi\"><yv vq=\"YvOYG4\" fglyr=\"onpxtebhaq-vzntr:hey(uggc://vzt.jykef.pbz/~Yvir.FvgrPbagrag.VQ/~14.2.1230/~/~/~/oyg4.cat)\">Cbjreshy Zvpebfbsg grpuabybtl urycf svtug fcnz naq vzcebir frphevgl.<yv vq=\"YvOYG19\" fglyr=\"onpxtebhaq-vzntr:hey(uggc://vzt.jykef.pbz/~Yvir.FvgrPbagrag.VQ/~14.2.1230/~/~/~/oyg19.cat)\">Trg zber qbar gunaxf gb terngre rnfr naq fcrrq.<yv vq=\"YvOYG16\" fglyr=\"onpxtebhaq-vzntr:hey(uggc://vzt.jykef.pbz/~Yvir.FvgrPbagrag.VQ/~14.2.1230/~/~/~/oyg16.cat)\">Ybgf bs fgbentr &#40;5 TO&#41; - zber pbby fghss ba gur jnl.<oe> <oe> <n uers=\"uggc://znvy.yvir.pbz/znvy/nobhg.nfck\" gnetrg=\"_oynax\">Yrnea zber##/N##</hy>',\n    r\"Bar Jvaqbjf Yvir VQ trgf lbh vagb <o>Ubgznvy</o>, <o>Zrffratre</o>, <o>Kobk YVIR</o> \\u2014 naq bgure cynprf lbh frr #~#argjbexybtb#~#\",\n    r\"${1}://${2}${3}${4}${5}\",\n    r\" O=6gnyg0g4znrrn&o=3&f=gc; Q=_lyu=K3bQZGSxnT4lZzD3OS9GNmV3ZGLkAQxRpTyxNmRlZmRmAmNkAQLRqTImqNZjOUEgpTjQnJ5xMKtgoN--; SCF=qy\",\n    r\"FrffvbaQQS2=4ss747o77904333q374or84qrr1s9r0nprp8r5q81534o94n; ZFPhygher=VC=74.125.75.20&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669321699093060&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=; AFP_zp_tfwsbrg-aowb_80=4413268q3660\",\n    r\"FrffvbaQQS2=4ss747o77904333q374or84qrr1s9r0nprp8r5q81534o94n; AFP_zp_tfwsbrg-aowb_80=4413268q3660; __hgzm=144631658.1231364074.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar); __hgzn=144631658.2294274870215848400.1231364074.1231364074.1231364074.1; __hgzo=144631658.0.10.1231364074; __hgzp=144631658; ZFPhygher=VC=74.125.75.20&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669321699093060&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q\",\n    r\"uggc://tbbtyrnqf.t.qbhoyrpyvpx.arg/cntrnq/nqf?pyvrag=pn-svz_zlfcnpr_zlfcnpr-ubzrcntr_wf&qg=1231364057761&uy=ra&nqfnsr=uvtu&br=hgs8&ahz_nqf=4&bhgchg=wf&nqgrfg=bss&pbeeryngbe=1231364057761&punaary=svz_zlfcnpr_ubzrcntr_abgybttrqva%2Psvz_zlfcnpr_aba_HTP%2Psvz_zlfcnpr_havgrq-fgngrf&hey=uggc%3N%2S%2Ssevraqf.zlfcnpr.pbz%2Svaqrk.psz&nq_glcr=grkg&rvq=6083027&rn=0&sez=0&tn_ivq=1667363813.1231364061&tn_fvq=1231364061&tn_uvq=1917563877&synfu=9.0.115&h_u=768&h_j=1024&h_nu=738&h_nj=1024&h_pq=24&h_gm=-480&h_uvf=2&h_wnin=gehr&h_acyht=7&h_azvzr=22\",\n    r\"ZFPhygher=VC=74.125.75.20&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669321699093060&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q\",\n    r\"ZFPhygher=VC=74.125.75.20&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669321699093060&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=\",\n    r\"uggc://cebsvyr.zlfcnpr.pbz/Zbqhyrf/Nccyvpngvbaf/Cntrf/Pnainf.nfck\",\n    r\"FrffvbaQQS2=473qq1rs0n2r70q9qo1pq48n021s9468ron90nps048p4p29; ZFPhygher=VC=74.125.75.3&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669325184628362&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=\",\n    r\"FrffvbaQQS2=473qq1rs0n2r70q9qo1pq48n021s9468ron90nps048p4p29; __hgzm=144631658.1231364380.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar); __hgzn=144631658.3931862196947939300.1231364380.1231364380.1231364380.1; __hgzo=144631658.0.10.1231364380; __hgzp=144631658; ZFPhygher=VC=74.125.75.3&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669325184628362&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q\",\n    r\"uggc://tbbtyrnqf.t.qbhoyrpyvpx.arg/cntrnq/nqf?pyvrag=pn-svz_zlfcnpr_vzntrf_wf&qg=1231364373088&uy=ra&nqfnsr=uvtu&br=hgs8&ahz_nqf=4&bhgchg=wf&nqgrfg=bss&pbeeryngbe=1231364373088&punaary=svz_zlfcnpr_hfre-ivrj-pbzzragf%2Psvz_zlfcnpr_havgrq-fgngrf&hey=uggc%3N%2S%2Spbzzrag.zlfcnpr.pbz%2Svaqrk.psz&nq_glcr=grkg&rvq=6083027&rn=0&sez=0&tn_ivq=1158737789.1231364375&tn_fvq=1231364375&tn_uvq=415520832&synfu=9.0.115&h_u=768&h_j=1024&h_nu=738&h_nj=1024&h_pq=24&h_gm=-480&h_uvf=2&h_wnin=gehr&h_acyht=7&h_azvzr=22\",\n    r\"ZFPhygher=VC=74.125.75.3&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669325184628362&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q\",\n    r\"ZFPhygher=VC=74.125.75.3&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669325184628362&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=\",\n    r\"#Zbq-Vasb-Vasb-WninFpevcgUvag\",\n    r\",n.svryqOgaPnapry\",\n    r\"FrffvbaQQS2=p98s8o9q42nr21or1r61pqorn1n002nsss569635984s6qp7; ZFPhygher=VC=74.125.75.3&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669357391353591&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=; AFP_zp_kkk-gdzogv_80=4413241q3660\",\n    r\"FrffvbaQQS2=p98s8o9q42nr21or1r61pqorn1n002nsss569635984s6qp7; AFP_zp_kkk-gdzogv_80=4413241q3660; AFP_zp_kkk-aowb_80=4413235p3660; __hgzm=144631658.1231367708.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar); __hgzn=144631658.2770915348920628700.1231367708.1231367708.1231367708.1; __hgzo=144631658.0.10.1231367708; __hgzp=144631658; ZFPhygher=VC=74.125.75.3&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669357391353591&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q\",\n    r\"uggc://tbbtyrnqf.t.qbhoyrpyvpx.arg/cntrnq/nqf?pyvrag=pn-svz_zlfcnpr_zlfcnpr-ubzrcntr_wf&qg=1231367691141&uy=ra&nqfnsr=uvtu&br=hgs8&ahz_nqf=4&bhgchg=wf&nqgrfg=bss&pbeeryngbe=1231367691141&punaary=svz_zlfcnpr_ubzrcntr_abgybttrqva%2Psvz_zlfcnpr_aba_HTP%2Psvz_zlfcnpr_havgrq-fgngrf&hey=uggc%3N%2S%2Sjjj.zlfcnpr.pbz%2S&nq_glcr=grkg&rvq=6083027&rn=0&sez=0&tn_ivq=320757904.1231367694&tn_fvq=1231367694&tn_uvq=1758792003&synfu=9.0.115&h_u=768&h_j=1024&h_nu=738&h_nj=1024&h_pq=24&h_gm=-480&h_uvf=2&h_wnin=gehr&h_acyht=7&h_azvzr=22\",\n    r\"uggc://zfacbegny.112.2b7.arg/o/ff/zfacbegnyubzr/1/U.7-cqi-2/f55332979829981?[NDO]&aqu=1&g=7%2S0%2S2009%2014%3N38%3N42%203%20480&af=zfacbegny&cntrAnzr=HF%20UCZFSGJ&t=uggc%3N%2S%2Sjjj.zfa.pbz%2S&f=1024k768&p=24&x=L&oj=994&ou=634&uc=A&{2}&[NDR]\",\n    r\"cnerag puebzr6 fvatyr1 gno fryrpgrq ovaq qbhoyr2 ps\",\n    r\"ZFPhygher=VC=74.125.75.3&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669357391353591&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q\",\n    r\"ZFPhygher=VC=74.125.75.3&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669357391353591&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=\",\n    r\"ne;ng;nh;or;oe;pn;pu;py;pa;qr;qx;rf;sv;se;to;ux;vq;vr;va;vg;wc;xe;zk;zl;ay;ab;am;cu;cy;cg;eh;fr;ft;gu;ge;gj;mn;\",\n    r\"ZP1=I=3&THVQ=6nnpr9q661804s33nnop45nosqp17q85; zu=ZFSG; PHYGHER=RA-HF; SyvtugTebhcVq=97; SyvtugVq=OnfrCntr; ucfie=Z:5|S:5|G:5|R:5|Q:oyh|J:S; ucpyv=J.U|Y.|F.|E.|H.Y|P.|U.; hfucjrn=jp:HFPN0746; ZHVQ=Q783SN9O14054831N4869R51P0SO8886&GHVQ=1\",\n    r\"ZP1=I=3&THVQ=6nnpr9q661804s33nnop45nosqp17q85; zu=ZFSG; PHYGHER=RA-HF; SyvtugTebhcVq=97; SyvtugVq=OnfrCntr; ucfie=Z:5|S:5|G:5|R:5|Q:oyh|J:S; ucpyv=J.U|Y.|F.|E.|H.Y|P.|U.; hfucjrn=jp:HFPN0746; ZHVQ=Q783SN9O14054831N4869R51P0SO8886\",\n    r\"ZP1=I=3&THVQ=6nnpr9q661804s33nnop45nosqp17q85; zu=ZFSG; PHYGHER=RA-HF; SyvtugTebhcVq=97; SyvtugVq=OnfrCntr; ucfie=Z:5|S:5|G:5|R:5|Q:oyh|J:S; ucpyv=J.U|Y.|F.|E.|H.Y|P.|U.; hfucjrn=jp:HFPN0746; ZHVQ=Q783SN9O14054831N4869R51P0SO8886; mvc=m:94043|yn:37.4154|yb:-122.0585|p:HF|ue:1\",\n    r\"ZP1=I=3&THVQ=6nnpr9q661804s33nnop45nosqp17q85; zu=ZFSG; PHYGHER=RA-HF; SyvtugTebhcVq=97; SyvtugVq=OnfrCntr; ucfie=Z:5|S:5|G:5|R:5|Q:oyh|J:S; ucpyv=J.U|Y.|F.|E.|H.Y|P.|U.; hfucjrn=jp:HFPN0746; ZHVQ=Q783SN9O14054831N4869R51P0SO8886; mvc=m:94043|yn:37.4154|yb:-122.0585|p:HF\",\n    r\"uggc://gx2.fgp.f-zfa.pbz/oe/uc/11/ra-hf/pff/v/g.tvs#uggc://gx2.fgo.f-zfa.pbz/v/29/4RQP4969777N048NPS4RRR3PO2S7S.wct\",\n    r\"uggc://gx2.fgp.f-zfa.pbz/oe/uc/11/ra-hf/pff/v/g.tvs#uggc://gx2.fgo.f-zfa.pbz/v/OQ/63NP9O94NS5OQP1249Q9S1ROP7NS3.wct\",\n    r\"zbmvyyn/5.0 (jvaqbjf; h; jvaqbjf ag 5.1; ra-hf) nccyrjroxvg/528.9 (xugzy, yvxr trpxb) puebzr/2.0.157.0 fnsnev/528.9\",\n    r\"1231365729213\",\n    r\"74.125.75.3-1057165600.29978900\",\n    r\"74.125.75.3-1057165600.29978900.1231365730214\",\n    r\"Frnepu%20Zvpebfbsg.pbz\",\n    r\"FrffvbaQQS2=8sqq78r9n442851q565599o401385sp3s04r92rnn7o19ssn; ZFPhygher=VC=74.125.75.17&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669340386893867&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=\",\n    r\"FrffvbaQQS2=8sqq78r9n442851q565599o401385sp3s04r92rnn7o19ssn; __hgzm=144631658.1231365779.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar); __hgzn=144631658.1877536177953918500.1231365779.1231365779.1231365779.1; __hgzo=144631658.0.10.1231365779; __hgzp=144631658; ZFPhygher=VC=74.125.75.17&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669340386893867&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q\",\n    r\"I=3%26THVQ=757q3ss871q44o7o805n8113n5p72q52\",\n    r\"I=3&THVQ=757q3ss871q44o7o805n8113n5p72q52\",\n    r\"uggc://tbbtyrnqf.t.qbhoyrpyvpx.arg/cntrnq/nqf?pyvrag=pn-svz_zlfcnpr_zlfcnpr-ubzrcntr_wf&qg=1231365765292&uy=ra&nqfnsr=uvtu&br=hgs8&ahz_nqf=4&bhgchg=wf&nqgrfg=bss&pbeeryngbe=1231365765292&punaary=svz_zlfcnpr_ubzrcntr_abgybttrqva%2Psvz_zlfcnpr_aba_HTP%2Psvz_zlfcnpr_havgrq-fgngrf&hey=uggc%3N%2S%2Sohyyrgvaf.zlfcnpr.pbz%2Svaqrk.psz&nq_glcr=grkg&rvq=6083027&rn=0&sez=0&tn_ivq=1579793869.1231365768&tn_fvq=1231365768&tn_uvq=2056210897&synfu=9.0.115&h_u=768&h_j=1024&h_nu=738&h_nj=1024&h_pq=24&h_gm=-480&h_uvf=2&h_wnin=gehr&h_acyht=7&h_azvzr=22\",\n    r\"frnepu.zvpebfbsg.pbz\",\n    r\"frnepu.zvpebfbsg.pbz/\",\n    r\"ZFPhygher=VC=74.125.75.17&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669340386893867&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q\",\n    r\"ZFPhygher=VC=74.125.75.17&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669340386893867&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=\",\n    r\"#fubhgobk .pybfr\",\n    r\"FrffvbaQQS2=102n9o0o9pq60132qn0337rr867p75953502q2s27s2s5r98; ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669341278771470&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=; AFP_zp_dfctwzssrwh-aowb_80=441326q33660\",\n    r\"FrffvbaQQS2=102n9o0o9pq60132qn0337rr867p75953502q2s27s2s5r98; AFP_zp_dfctwzssrwh-aowb_80=441326q33660; __hgzm=144631658.1231365869.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar); __hgzn=144631658.1670816052019209000.1231365869.1231365869.1231365869.1; __hgzo=144631658.0.10.1231365869; __hgzp=144631658; ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669341278771470&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q\",\n    r\"FrffvbaQQS2=9995p6rp12rrnr893334ro7nq70o7p64p69rqn844prs1473; ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669350559478880&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=; AFP_zp_dfctwzs-aowb_80=441327q73660\",\n    r\"FrffvbaQQS2=9995p6rp12rrnr893334ro7nq70o7p64p69rqn844prs1473; AFP_zp_dfctwzs-aowb_80=441327q73660; __hgzm=144631658.1231367054.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar); __hgzn=144631658.1796080716621419500.1231367054.1231367054.1231367054.1; __hgzo=144631658.0.10.1231367054; __hgzp=144631658; ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669350559478880&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q\",\n    r\"[glcr=fhozvg]\",\n    r\"n.svryqOga,n.svryqOgaPnapry\",\n    r\"n.svryqOgaPnapry\",\n    r\"oyvpxchaxg\",\n    r\"qvi.bow-nppbeqvba qg\",\n    r\"uggc://tbbtyrnqf.t.qbhoyrpyvpx.arg/cntrnq/nqf?pyvrag=pn-svz_zlfcnpr_nccf_wf&qg=1231367052227&uy=ra&nqfnsr=uvtu&br=hgs8&ahz_nqf=4&bhgchg=wf&nqgrfg=bss&pbeeryngbe=1231367052227&punaary=svz_zlfcnpr_nccf-pnainf%2Psvz_zlfcnpr_havgrq-fgngrf&hey=uggc%3N%2S%2Scebsvyr.zlfcnpr.pbz%2SZbqhyrf%2SNccyvpngvbaf%2SCntrf%2SPnainf.nfck&nq_glcr=grkg&rvq=6083027&rn=0&sez=1&tn_ivq=716357910.1231367056&tn_fvq=1231367056&tn_uvq=1387206491&synfu=9.0.115&h_u=768&h_j=1024&h_nu=738&h_nj=1024&h_pq=24&h_gm=-480&h_uvf=2&h_wnin=gehr&h_acyht=7&h_azvzr=22\",\n    r\"uggc://tbbtyrnqf.t.qbhoyrpyvpx.arg/cntrnq/nqf?pyvrag=pn-svz_zlfcnpr_zlfcnpr-ubzrcntr_wf&qg=1231365851658&uy=ra&nqfnsr=uvtu&br=hgs8&ahz_nqf=4&bhgchg=wf&nqgrfg=bss&pbeeryngbe=1231365851658&punaary=svz_zlfcnpr_ubzrcntr_abgybttrqva%2Psvz_zlfcnpr_aba_HTP%2Psvz_zlfcnpr_havgrq-fgngrf&hey=uggc%3N%2S%2Scebsvyrrqvg.zlfcnpr.pbz%2Svaqrk.psz&nq_glcr=grkg&rvq=6083027&rn=0&sez=0&tn_ivq=1979828129.1231365855&tn_fvq=1231365855&tn_uvq=2085229649&synfu=9.0.115&h_u=768&h_j=1024&h_nu=738&h_nj=1024&h_pq=24&h_gm=-480&h_uvf=2&h_wnin=gehr&h_acyht=7&h_azvzr=22\",\n    r\"uggc://zfacbegny.112.2b7.arg/o/ff/zfacbegnyubzr/1/U.7-cqi-2/f55023338617756?[NDO]&aqu=1&g=7%2S0%2S2009%2014%3N12%3N47%203%20480&af=zfacbegny&cntrAnzr=HF%20UCZFSGJ&t=uggc%3N%2S%2Sjjj.zfa.pbz%2S&f=0k0&p=43835816&x=A&oj=994&ou=634&uc=A&{2}&[NDR]\",\n    r\"zrgn[anzr=nwnkHey]\",\n    r\"anpuevpugra\",\n    r'b oS={\\'oT\\':1.1};x $8n(B){z(B!=o9)};x $S(B){O(!$8n(B))z A;O(B.4L)z\\'T\\';b S=7t B;O(S==\\'2P\\'&&B.p4){23(B.7f){12 1:z\\'T\\';12 3:z/\\S/.2g(B.8M)?\\'ox\\':\\'oh\\'}}O(S==\\'2P\\'||S==\\'x\\'){23(B.nE){12 2V:z\\'1O\\';12 7I:z\\'5a\\';12 18:z\\'4B\\'}O(7t B.I==\\'4F\\'){O(B.3u)z\\'pG\\';O(B.8e)z\\'1p\\'}}z S};x $2p(){b 4E={};Z(b v=0;v<1p.I;v++){Z(b X 1o 1p[v]){b nc=1p[v][X];b 6E=4E[X];O(6E&&$S(nc)==\\'2P\\'&&$S(6E)==\\'2P\\')4E[X]=$2p(6E,nc);17 4E[X]=nc}}z 4E};b $E=7p.E=x(){b 1d=1p;O(!1d[1])1d=[p,1d[0]];Z(b X 1o 1d[1])1d[0][X]=1d[1][X];z 1d[0]};b $4D=7p.pJ=x(){Z(b v=0,y=1p.I;v<y;v++){1p[v].E=x(1J){Z(b 1I 1o 1J){O(!p.1Y[1I])p.1Y[1I]=1J[1I];O(!p[1I])p[1I]=$4D.6C(1I)}}}};$4D.6C=x(1I){z x(L){z p.1Y[1I].3H(L,2V.1Y.nV.1F(1p,1))}};$4D(7F,2V,6J,nb);b 3l=x(B){B=B||{};B.E=$E;z B};b pK=Y 3l(H);b pZ=Y 3l(C);C.6f=C.35(\\'6f\\')[0];x $2O(B){z!!(B||B===0)};x $5S(B,n8){z $8n(B)?B:n8};x $7K(3c,1m){z 1q.na(1q.7K()*(1m-3c+1)+3c)};x $3N(){z Y 97().os()};x $4M(1U){pv(1U);pa(1U);z 1S};H.43=!!(C.5Z);O(H.nB)H.31=H[H.7q?\\'py\\':\\'nL\\']=1r;17 O(C.9N&&!C.om&&!oy.oZ)H.pF=H.4Z=H[H.43?\\'pt\\':\\'65\\']=1r;17 O(C.po!=1S)H.7J=1r;O(7t 5B==\\'o9\\'){b 5B=x(){};O(H.4Z)C.nd(\"pW\");5B.1Y=(H.4Z)?H[\"[[oN.1Y]]\"]:{}}5B.1Y.4L=1r;O(H.nL)5s{C.oX(\"pp\",A,1r)}4K(r){};b 18=x(1X){b 63=x(){z(1p[0]!==1S&&p.1w&&$S(p.1w)==\\'x\\')?p.1w.3H(p,1p):p};$E(63,p);63.1Y=1X;63.nE=18;z 63};18.1z=x(){};18.1Y={E:x(1X){b 7x=Y p(1S);Z(b X 1o 1X){b nC=7x[X];7x[X]=18.nY(nC,1X[X])}z Y 18(7x)},3d:x(){Z(b v=0,y=1p.I;v<y;v++)$E(p.1Y,1p[v])}};18.nY=x(2b,2n){O(2b&&2b!=2n){b S=$S(2n);O(S!=$S(2b))z 2n;23(S){12\\'x\\':b 7R=x(){p.1e=1p.8e.1e;z 2n.3H(p,1p)};7R.1e=2b;z 7R;12\\'2P\\':z $2p(2b,2n)}}z 2n};b 8o=Y 18({oQ:x(J){p.4w=p.4w||[];p.4w.1x(J);z p},7g:x(){O(p.4w&&p.4w.I)p.4w.9J().2x(10,p)},oP:x(){p.4w=[]}});b 2d=Y 18({1V:x(S,J){O(J!=18.1z){p.$19=p.$19||{};p.$19[S]=p.$19[S]||[];p.$19[S].5j(J)}z p},1v:x(S,1d,2x){O(p.$19&&p.$19[S]){p.$19[S].1b(x(J){J.3n({\\'L\\':p,\\'2x\\':2x,\\'1p\\':1d})()},p)}z p},3M:x(S,J){O(p.$19&&p.$19[S])p.$19[S].2U(J);z p}});b 4v=Y 18({2H:x(){p.P=$2p.3H(1S,[p.P].E(1p));O(!p.1V)z p;Z(b 3O 1o p.P){O($S(p.P[3O]==\\'x\\')&&3O.2g(/^5P[N-M]/))p.1V(3O,p.P[3O])}z p}});2V.E({7y:x(J,L){Z(b v=0,w=p.I;v<w;v++)J.1F(L,p[v],v,p)},3s:x(J,L){b 54=[];Z(b v=0,w=p.I;v<w;v++){O(J.1F(L,p[v],v,p))54.1x(p[v])}z 54},2X:x(J,L){b 54=[];Z(b v=0,w=p.I;v<w;v++)54[v]=J.1F(L,p[v],v,p);z 54},4i:x(J,L){Z(b v=0,w=p.I;v<w;v++){O(!J.1F(L,p[v],v,p))z A}z 1r},ob:x(J,L){Z(b v=0,w=p.I;v<w;v++){O(J.1F(L,p[v],v,p))z 1r}z A},3F:x(3u,15){b 3A=p.I;Z(b v=(15<0)?1q.1m(0,3A+15):15||0;v<3A;v++){O(p[v]===3u)z v}z-1},8z:x(1u,I){1u=1u||0;O(1u<0)1u=p.I+1u;I=I||(p.I-1u);b 89=[];Z(b v=0;v<I;v++)89[v]=p[1u++];z 89},2U:x(3u){b v=0;b 3A=p.I;6L(v<3A){O(p[v]===3u){p.6l(v,1);3A--}17{v++}}z p},1y:x(3u,15){z p.3F(3u,15)!=-1},oz:x(1C){b B={},I=1q.3c(p.I,1C.I);Z(b v=0;v<I;v++)B[1C[v]]=p[v];z B},E:x(1O){Z(b v=0,w=1O.I;v<w;v++)p.1x(1O[v]);z p},2p:x(1O){Z(b v=0,y=1O.I;v<y;v++)p.5j(1O[v]);z p},5j:x(3u){O(!p.1y(3u))p.1x(3u);z p},oc:x(){z p[$7K(0,p.I-1)]||A},7L:x(){z p[p.I-1]||A}});2V.1Y.1b=2V.1Y.7y;2V.1Y.2g=2V.1Y.1y;x $N(1O){z 2V.8z(1O)};x $1b(3J,J,L){O(3J&&7t 3J.I==\\'4F\\'&&$S(3J)!=\\'2P\\')2V.7y(3J,J,L);17 Z(b 1j 1o 3J)J.1F(L||3J,3J[1j],1j)};6J.E({2g:x(6b,2F){z(($S(6b)==\\'2R\\')?Y 7I(6b,2F):6b).2g(p)},3p:x(){z 5K(p,10)},o4:x(){z 69(p)},7A:x(){z p.3y(/-\\D/t,x(2G){z 2G.7G(1).nW()})},9b:x(){z p.3y(/\\w[N-M]/t,x(2G){z(2G.7G(0)+\\'-\\'+2G.7G(1).5O())})},8V:x(){z p.3y(/\\b[n-m]/t,x(2G){z 2G.nW()})},5L:x(){z p.3y(/^\\s+|\\s+$/t,\\'\\')},7j:x(){z p.3y(/\\s{2,}/t,\\' \\').5L()},5V:x(1O){b 1i=p.2G(/\\d{1,3}/t);z(1i)?1i.5V(1O):A},5U:x(1O){b 3P=p.2G(/^#?(\\w{1,2})(\\w{1,2})(\\w{1,2})$/);z(3P)?3P.nV(1).5U(1O):A},1y:x(2R,f){z(f)?(f+p+f).3F(f+2R+f)>-1:p.3F(2R)>-1},nX:x(){z p.3y(/([.*+?^${}()|[\\]\\/\\\\])/t,\\'\\\\$1\\')}});2V.E({5V:x(1O){O(p.I<3)z A;O(p.I==4&&p[3]==0&&!1O)z\\'p5\\';b 3P=[];Z(b v=0;v<3;v++){b 52=(p[v]-0).4h(16);3P.1x((52.I==1)?\\'0\\'+52:52)}z 1O?3P:\\'#\\'+3P.2u(\\'\\')},5U:x(1O){O(p.I!=3)z A;b 1i=[];Z(b v=0;v<3;v++){1i.1x(5K((p[v].I==1)?p[v]+p[v]:p[v],16))}z 1O?1i:\\'1i(\\'+1i.2u(\\',\\')+\\')\\'}});7F.E({3n:x(P){b J=p;P=$2p({\\'L\\':J,\\'V\\':A,\\'1p\\':1S,\\'2x\\':A,\\'4s\\':A,\\'6W\\':A},P);O($2O(P.1p)&&$S(P.1p)!=\\'1O\\')P.1p=[P.1p];z x(V){b 1d;O(P.V){V=V||H.V;1d=[(P.V===1r)?V:Y P.V(V)];O(P.1p)1d.E(P.1p)}17 1d=P.1p||1p;b 3C=x(){z J.3H($5S(P',\n    r\"hagreunyghat\",\n    r\"ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669341278771470&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q\",\n    r\"ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669350559478880&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q\",\n    r\"ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669341278771470&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=\",\n    r\"ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669350559478880&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=\",\n    r\"shapgvba (){Cuk.Nccyvpngvba.Frghc.Pber();Cuk.Nccyvpngvba.Frghc.Nwnk();Cuk.Nccyvpngvba.Frghc.Synfu();Cuk.Nccyvpngvba.Frghc.Zbqhyrf()}\",\n]\n\n# The 12 benchmarking blocks\n\n\ndef block0():\n    for i in range(6511):\n        regexs[0].search(r\"pyvpx\")\n\n    for i in range(1844):\n        regexs[1].search(r\"uggc://jjj.snprobbx.pbz/ybtva.cuc\")\n\n    for i in range(739):\n        regexs[2].sub(r\"\", \"QBZPbageby_cynprubyqre\", subcount[2])\n\n    for i in range(598):\n        regexs[1].search(r\"uggc://jjj.snprobbx.pbz/\")\n\n    for i in range(454):\n        regexs[1].search(r\"uggc://jjj.snprobbx.pbz/fepu.cuc\")\n\n    for i in range(352):\n        re.search(\n            r\"qqqq|qqq|qq|q|ZZZZ|ZZZ|ZZ|Z|llll|ll|l|uu|u|UU|U|zz|z|ff|f|gg|g|sss|ss|s|mmm|mm|m\",\n            \"qqqq, ZZZ q, llll\",\n        )\n\n    for i in range(312):\n        regexs[3].search(r\"vachggrkg QBZPbageby_cynprubyqre\")\n\n    for i in range(282):\n        regexs[4].search(r\"/ZlFcnprUbzrcntr/Vaqrk-FvgrUbzr,10000000\")\n\n    for i in range(177):\n        regexs[5].sub(r\"\", \"vachggrkg\", subcount[5])\n\n    for i in range(170):\n        regexs[6].sub(r\"\", \"528.9\", subcount[6])\n        regexs[7].search(r\"528\")\n\n    for i in range(156):\n        regexs[8].search(r\"VCPhygher=ra-HF\")\n        regexs[8].search(r\"CersreerqPhygher=ra-HF\")\n\n    for i in range(144):\n        regexs[0].search(r\"xrlcerff\")\n\n    for i in range(139):\n        regexs[6].sub(r\"\", \"521\", subcount[6])\n\n        # This has a different output to the V8 version.\n        # It could just be a difference in the engines.\n        regexs[7].search(r\"521\")\n        regexs[9].search(r\"\")\n        re.search(r\"JroXvg\\/(\\S+)\", strings[0])\n\n    for i in range(137):\n        regexs[10].sub(r\"\", \"qvi .so_zrah\", subcount[10])\n        re.sub(r\"\\[\", \"\", \"qvi .so_zrah\", 0)\n        regexs[11].sub(r\"\", \"qvi.so_zrah\", subcount[11])\n\n    for i in range(117):\n        regexs[2].sub(r\"\", \"uvqqra_ryrz\", subcount[2])\n\n    for i in range(95):\n        re.search(\n            r\"(?:^|;)\\s*sevraqfgre_ynat=([^;]*)\",\n            \"sevraqfgre_naba=nvq%3Qn6ss9p85n868ro9s059pn854735956o3%26ers%3Q%26df%3Q%26vpgl%3QHF\",\n        )\n\n    for i in range(93):\n        regexs[12].sub(r\"\", \"uggc://ubzr.zlfcnpr.pbz/vaqrk.psz\", subcount[12])\n        regexs[13].search(r\"uggc://ubzr.zlfcnpr.pbz/vaqrk.psz\")\n\n    for i in range(92):\n        re.sub(r\"([a-zA-Z]|\\s)+\", \"\", strings[1], 1)\n\n    for i in range(85):\n        regexs[14].sub(r\"\", \"svefg\", subcount[14])\n        regexs[15].sub(r\"\", \"svefg\", subcount[15])\n        regexs[12].sub(r\"\", \"uggc://cebsvyr.zlfcnpr.pbz/vaqrk.psz\", subcount[12])\n        regexs[14].sub(r\"\", \"ynfg\", subcount[14])\n        regexs[15].sub(r\"\", \"ynfg\", subcount[15])\n        regexs[16].search(r\"qvfcynl\")\n        regexs[13].search(r\"uggc://cebsvyr.zlfcnpr.pbz/vaqrk.psz\")\n\n\ndef block1():\n    for i in range(81):\n        regexs[8].search(r\"VC=74.125.75.1\")\n\n    for i in range(78):\n        re.sub(r\"(\\s)+e\", \"\", \"9.0  e115\", 1)\n        re.sub(r\".\", \"\", \"k\", 1)\n\n        # This prints a unicode escape where the V8 version prints the\n        # unicode character.\n        regexs[17].sub(r\"\", strings[2], subcount[17])\n\n        # This prints a unicode escape where the V8 version prints the\n        # unicode character.\n        regexs[17].sub(r\"\", strings[3], subcount[17])\n\n        regexs[8].search(r\"144631658\")\n        regexs[8].search(r\"Pbhagel=IIZ%3Q\")\n        regexs[8].search(r\"Pbhagel=IIZ=\")\n        regexs[8].search(r\"CersreerqPhygherCraqvat=\")\n        regexs[8].search(strings[4])\n        regexs[8].search(strings[5])\n        regexs[8].search(r\"__hgzp=144631658\")\n        regexs[8].search(r\"gvzrMbar=-8\")\n        regexs[8].search(r\"gvzrMbar=0\")\n        re.search(r\"Fnsnev\\/(\\d+\\.\\d+)\", strings[0])\n        regexs[3].search(r\"vachggrkg  QBZPbageby_cynprubyqre\")\n        regexs[0].search(r\"xrlqbja\")\n        regexs[0].search(r\"xrlhc\")\n\n    for i in range(77):\n        regexs[12].sub(r\"\", \"uggc://zrffntvat.zlfcnpr.pbz/vaqrk.psz\", subcount[12])\n        regexs[13].search(r\"uggc://zrffntvat.zlfcnpr.pbz/vaqrk.psz\")\n\n    for i in range(73):\n        regexs[18].sub(\n            r\"\",\n            \"FrffvbaFgbentr=%7O%22GnoThvq%22%3N%7O%22thvq%22%3N1231367125017%7Q%7Q\",\n            subcount[18],\n        )\n\n    for i in range(72):\n        regexs[1].search(strings[6])\n\n    for i in range(71):\n        regexs[19].search(r\"\")\n\n    for i in range(70):\n        regexs[11].sub(r\"\", \"3.5.0.0\", subcount[11])\n        re.sub(r\"d1\", \"\", strings[7], 0)\n        re.sub(r\"NQ_VQ\", \"\", strings[8], 0)\n        re.sub(r\"d2\", \"\", strings[9], 0)\n        re.sub(\n            r\"_\", \"\", \"NI%3Q1_CI%3Q1_PI%3Q1_EI%3Q1_HI%3Q1_HP%3Q1_IC%3Q0.0.0.0_IH%3Q0\", 0\n        )\n        regexs[20].split(\n            r\"svz_zlfcnpr_ubzrcntr_abgybttrqva,svz_zlfcnpr_aba_HTP,svz_zlfcnpr_havgrq-fgngrf\"\n        )\n        regexs[21].search(r\"ybnqvat\")\n\n    for i in range(68):\n        regexs[1].search(r\"#\")\n        re.search(\n            r\"(?:ZFVR.(\\d+\\.\\d+))|(?:(?:Sversbk|TenaCnenqvfb|Vprjrnfry).(\\d+\\.\\d+))|(?:Bcren.(\\d+\\.\\d+))|(?:NccyrJroXvg.(\\d+(?:\\.\\d+)?))\",\n            strings[0],\n        )\n        re.search(r\"(Znp BF K)|(Jvaqbjf;)\", strings[0])\n        re.search(r\"Trpxb\\/([0-9]+)\", strings[0])\n        regexs[21].search(r\"ybnqrq\")\n\n    for i in range(49):\n        regexs[16].search(r\"pbybe\")\n\n    for i in range(44):\n        regexs[12].sub(r\"\", \"uggc://sevraqf.zlfcnpr.pbz/vaqrk.psz\", subcount[12])\n        regexs[13].search(r\"uggc://sevraqf.zlfcnpr.pbz/vaqrk.psz\")\n\n\ndef block2():\n    for i in range(40):\n        regexs[14].sub(r\"\", \"fryrpgrq\", subcount[14])\n        regexs[15].sub(r\"\", \"fryrpgrq\", subcount[15])\n\n    for i in range(39):\n        re.sub(r\"\\buvqqra_ryrz\\b\", \"\", \"vachggrkg uvqqra_ryrz\", 0)\n        regexs[3].search(r\"vachggrkg \")\n        regexs[3].search(r\"vachggrkg\")\n        regexs[22].search(r\"HVYvaxOhggba\")\n        regexs[22].search(r\"HVYvaxOhggba_E\")\n        regexs[22].search(r\"HVYvaxOhggba_EJ\")\n        regexs[22].search(r\"zrah_ybtva_pbagnvare\")\n        re.search(r\"\\buvqqra_ryrz\\b\", \"vachgcnffjbeq\")\n\n    for i in range(37):\n        regexs[8].search(r\"111soqs57qo8o8480qo18sor2011r3n591q7s6s37r120904\")\n        regexs[8].search(r\"SbeprqRkcvengvba=633669315660164980\")\n        regexs[8].search(\n            r\"FrffvbaQQS2=111soqs57qo8o8480qo18sor2011r3n591q7s6s37r120904\"\n        )\n\n    for i in range(35):\n        regexs[14].sub(r\"\", \"puvyq p1 svefg\", subcount[14])\n        regexs[15].sub(r\"\", \"puvyq p1 svefg\", subcount[15])\n        regexs[14].sub(r\"\", \"sylbhg pybfrq\", subcount[14])\n        regexs[15].sub(r\"\", \"sylbhg pybfrq\", subcount[15])\n\n    for i in range(34):\n        regexs[19].search(r\"gno2\")\n        regexs[19].search(r\"gno3\")\n        regexs[8].search(r\"44132r503660\")\n        regexs[8].search(r\"SbeprqRkcvengvba=633669316860113296\")\n        regexs[8].search(r\"AFP_zp_dfctwzs-aowb_80=44132r503660\")\n        regexs[8].search(\n            r\"FrffvbaQQS2=s6r4579npn4rn2135s904r0s75pp1o5334p6s6pospo12696\"\n        )\n        regexs[8].search(r\"s6r4579npn4rn2135s904r0s75pp1o5334p6s6pospo12696\")\n\n    for i in range(32):\n        re.search(r\"puebzr\", strings[0], re.IGNORECASE)\n\n    for i in range(31):\n        regexs[23].sub(r\"\", \"uggc://jjj.snprobbx.pbz/\", subcount[23])\n        regexs[8].search(r\"SbeprqRkcvengvba=633669358527244818\")\n        regexs[8].search(r\"VC=66.249.85.130\")\n        regexs[8].search(\n            r\"FrffvbaQQS2=s15q53p9n372sn76npr13o271n4s3p5r29p235746p908p58\"\n        )\n        regexs[8].search(r\"s15q53p9n372sn76npr13o271n4s3p5r29p235746p908p58\")\n        regexs[24].search(r\"uggc://jjj.snprobbx.pbz/\")\n\n    for i in range(30):\n        regexs[6].sub(r\"\", \"419\", subcount[6])\n        re.search(r\"(?:^|\\s+)gvzrfgnzc(?:\\s+|$)\", \"gvzrfgnzc\")\n        regexs[7].search(r\"419\")\n\n    for i in range(29):\n        regexs[23].sub(r\"\", \"uggc://jjj.snprobbx.pbz/ybtva.cuc\", subcount[23])\n\n    for i in range(28):\n        regexs[25].sub(r\"\", \"Funer guvf tnqtrg\", subcount[25])\n        regexs[12].sub(r\"\", \"Funer guvf tnqtrg\", subcount[12])\n        regexs[26].search(r\"uggc://jjj.tbbtyr.pbz/vt/qverpgbel\")\n\n\ndef block3():\n    for i in range(27):\n        re.sub(r\"[A-Za-z]\", \"\", \"e115\", 0)\n\n    for i in range(23):\n        regexs[27].sub(r\"\", \"qvfcynl\", subcount[27])\n        regexs[27].sub(r\"\", \"cbfvgvba\", subcount[27])\n\n    for i in range(22):\n        regexs[14].sub(r\"\", \"unaqyr\", subcount[14])\n        regexs[15].sub(r\"\", \"unaqyr\", subcount[15])\n        regexs[14].sub(r\"\", \"yvar\", subcount[14])\n        regexs[15].sub(r\"\", \"yvar\", subcount[15])\n        regexs[14].sub(r\"\", \"cnerag puebzr6 fvatyr1 gno\", subcount[14])\n        regexs[15].sub(r\"\", \"cnerag puebzr6 fvatyr1 gno\", subcount[15])\n        regexs[14].sub(r\"\", \"fyvqre\", subcount[14])\n        regexs[15].sub(r\"\", \"fyvqre\", subcount[15])\n        regexs[28].search(r\"\")\n\n    for i in range(21):\n        regexs[12].sub(r\"\", \"uggc://jjj.zlfcnpr.pbz/\", subcount[12])\n        regexs[13].search(r\"uggc://jjj.zlfcnpr.pbz/\")\n\n    for i in range(20):\n        regexs[29].sub(r\"\", \"cntrivrj\", subcount[29])\n        regexs[30].sub(r\"\", \"cntrivrj\", subcount[30])\n        regexs[19].search(r\"ynfg\")\n        regexs[19].search(r\"ba svefg\")\n        regexs[8].search(r\"VC=74.125.75.3\")\n\n    for i in range(19):\n        regexs[31].search(r\"ra\")\n\n    for i in range(18):\n        regexs[32].split(strings[10])\n        regexs[32].split(strings[11])\n        regexs[33].sub(r\"\", strings[12], subcount[33])\n        regexs[8].search(r\"144631658.0.10.1231363570\")\n        regexs[8].search(\n            r\"144631658.1231363570.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)\"\n        )\n        regexs[8].search(\n            r\"144631658.3426875219718084000.1231363570.1231363570.1231363570.1\"\n        )\n        regexs[8].search(strings[13])\n        regexs[8].search(strings[14])\n        regexs[8].search(\n            r\"__hgzn=144631658.3426875219718084000.1231363570.1231363570.1231363570.1\"\n        )\n        regexs[8].search(r\"__hgzo=144631658.0.10.1231363570\")\n        regexs[8].search(\n            r\"__hgzm=144631658.1231363570.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)\"\n        )\n        regexs[34].search(strings[10])\n        regexs[34].search(strings[11])\n\n    for i in range(17):\n        re.match(r\"zfvr\", strings[0], re.IGNORECASE)\n        re.match(r\"bcren\", strings[0], re.IGNORECASE)\n        regexs[32].split(strings[15])\n        regexs[32].split(strings[16])\n        regexs[14].sub(r\"\", \"ohggba\", subcount[14])\n        regexs[15].sub(r\"\", \"ohggba\", subcount[15])\n        regexs[14].sub(r\"\", \"puvyq p1 svefg sylbhg pybfrq\", subcount[14])\n        regexs[15].sub(r\"\", \"puvyq p1 svefg sylbhg pybfrq\", subcount[15])\n        regexs[14].sub(r\"\", \"pvgvrf\", subcount[14])\n        regexs[15].sub(r\"\", \"pvgvrf\", subcount[15])\n        regexs[14].sub(r\"\", \"pybfrq\", subcount[14])\n        regexs[15].sub(r\"\", \"pybfrq\", subcount[15])\n        regexs[14].sub(r\"\", \"qry\", subcount[14])\n        regexs[15].sub(r\"\", \"qry\", subcount[15])\n        regexs[14].sub(r\"\", \"uqy_zba\", subcount[14])\n        regexs[15].sub(r\"\", \"uqy_zba\", subcount[15])\n        regexs[33].sub(r\"\", strings[17], subcount[33])\n        re.sub(r\"%3P\", \"\", strings[18], 0)\n        re.sub(r\"%3R\", \"\", strings[18], 0)\n        re.sub(r\"%3q\", \"\", strings[18], 0)\n        regexs[35].sub(r\"\", strings[18], subcount[35])\n        regexs[14].sub(r\"\", \"yvaxyvfg16\", subcount[14])\n        regexs[15].sub(r\"\", \"yvaxyvfg16\", subcount[15])\n        regexs[14].sub(r\"\", \"zvahf\", subcount[14])\n        regexs[15].sub(r\"\", \"zvahf\", subcount[15])\n        regexs[14].sub(r\"\", \"bcra\", subcount[14])\n        regexs[15].sub(r\"\", \"bcra\", subcount[15])\n        regexs[14].sub(r\"\", \"cnerag puebzr5 fvatyr1 ps NU\", subcount[14])\n        regexs[15].sub(r\"\", \"cnerag puebzr5 fvatyr1 ps NU\", subcount[15])\n        regexs[14].sub(r\"\", \"cynlre\", subcount[14])\n        regexs[15].sub(r\"\", \"cynlre\", subcount[15])\n        regexs[14].sub(r\"\", \"cyhf\", subcount[14])\n        regexs[15].sub(r\"\", \"cyhf\", subcount[15])\n        regexs[14].sub(r\"\", \"cb_uqy\", subcount[14])\n        regexs[15].sub(r\"\", \"cb_uqy\", subcount[15])\n        regexs[14].sub(r\"\", \"hyJVzt\", subcount[14])\n        regexs[15].sub(r\"\", \"hyJVzt\", subcount[15])\n        regexs[8].search(r\"144631658.0.10.1231363638\")\n        regexs[8].search(\n            r\"144631658.1231363638.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)\"\n        )\n        regexs[8].search(\n            r\"144631658.965867047679498800.1231363638.1231363638.1231363638.1\"\n        )\n        regexs[8].search(r\"4413268q3660\")\n        regexs[8].search(r\"4ss747o77904333q374or84qrr1s9r0nprp8r5q81534o94n\")\n        regexs[8].search(r\"SbeprqRkcvengvba=633669321699093060\")\n        regexs[8].search(r\"VC=74.125.75.20\")\n        regexs[8].search(strings[19])\n        regexs[8].search(strings[20])\n        regexs[8].search(r\"AFP_zp_tfwsbrg-aowb_80=4413268q3660\")\n        regexs[8].search(\n            r\"FrffvbaQQS2=4ss747o77904333q374or84qrr1s9r0nprp8r5q81534o94n\"\n        )\n        regexs[8].search(\n            r\"__hgzn=144631658.965867047679498800.1231363638.1231363638.1231363638.1\"\n        )\n        regexs[8].search(r\"__hgzo=144631658.0.10.1231363638\")\n        regexs[8].search(\n            r\"__hgzm=144631658.1231363638.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)\"\n        )\n        regexs[34].search(strings[15])\n        regexs[34].search(strings[16])\n\n\ndef block4():\n    for i in range(16):\n        re.sub(r\"\\*\", \"\", \"\", 0)\n        re.search(r\"\\bnpgvir\\b\", \"npgvir\")\n        re.search(r\"sversbk\", strings[0], re.IGNORECASE)\n        regexs[36].search(r\"glcr\")\n        re.search(r\"zfvr\", strings[0], re.IGNORECASE)\n        re.search(r\"bcren\", strings[0], re.IGNORECASE)\n\n    for i in range(15):\n        regexs[32].split(strings[21])\n        regexs[32].split(strings[22])\n        regexs[12].sub(r\"\", \"uggc://ohyyrgvaf.zlfcnpr.pbz/vaqrk.psz\", subcount[12])\n        regexs[33].sub(r\"\", strings[23], subcount[33])\n        regexs[37].sub(r\"\", \"yv\", subcount[37])\n        regexs[18].sub(r\"\", \"yv\", subcount[18])\n        regexs[8].search(r\"144631658.0.10.1231367822\")\n        regexs[8].search(\n            r\"144631658.1231367822.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)\"\n        )\n        regexs[8].search(\n            r\"144631658.4127520630321984500.1231367822.1231367822.1231367822.1\"\n        )\n        regexs[8].search(strings[24])\n        regexs[8].search(strings[25])\n        regexs[8].search(\n            r\"__hgzn=144631658.4127520630321984500.1231367822.1231367822.1231367822.1\"\n        )\n        regexs[8].search(r\"__hgzo=144631658.0.10.1231367822\")\n        regexs[8].search(\n            r\"__hgzm=144631658.1231367822.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)\"\n        )\n        regexs[34].search(strings[21])\n        regexs[34].search(strings[22])\n\n        # FIXME\n        # The \\{0,65534} should be a *\n        # There's a current python bug that will stop the regex compilation\n        # when a * appears there http://bugs.python.org/issue6156.\n        re.search(\n            r'\\.([\\w-]+)|\\[(\\w+)(?:([!*^$~|]?=)[\"\\']?(.*?)[\"\\']?)?\\]|:([\\w-]+)(?:\\([\"\\']?(.\\{0,65534}?)?[\"\\']?\\)|$)',\n            strings[26],\n        )\n\n        regexs[13].search(r\"uggc://ohyyrgvaf.zlfcnpr.pbz/vaqrk.psz\")\n        regexs[38].search(r\"yv\")\n\n    for i in range(14):\n        regexs[18].sub(r\"\", \"\", subcount[18])\n        re.sub(r\"(\\s+e|\\s+o[0-9]+)\", \"\", \"9.0  e115\", 1)\n        re.sub(r\"<\", \"\", \"Funer guvf tnqtrg\", 0)\n        re.sub(r\">\", \"\", \"Funer guvf tnqtrg\", 0)\n        regexs[39].sub(r\"\", \"Funer guvf tnqtrg\", subcount[39])\n        regexs[12].sub(r\"\", \"uggc://cebsvyrrqvg.zlfcnpr.pbz/vaqrk.psz\", subcount[12])\n        regexs[40].sub(r\"\", \"grnfre\", subcount[40])\n        regexs[41].sub(r\"\", \"grnfre\", subcount[41])\n        regexs[42].sub(r\"\", \"grnfre\", subcount[42])\n        regexs[43].sub(r\"\", \"grnfre\", subcount[43])\n        regexs[44].sub(r\"\", \"grnfre\", subcount[44])\n        regexs[45].sub(r\"\", \"grnfre\", subcount[45])\n        regexs[46].sub(r\"\", \"grnfre\", subcount[46])\n        regexs[47].sub(r\"\", \"grnfre\", subcount[47])\n        regexs[48].sub(r\"\", \"grnfre\", subcount[48])\n        regexs[16].search(r\"znetva-gbc\")\n        regexs[16].search(r\"cbfvgvba\")\n        regexs[19].search(r\"gno1\")\n        regexs[9].search(r\"qz\")\n        regexs[9].search(r\"qg\")\n        regexs[9].search(r\"zbqobk\")\n        regexs[9].search(r\"zbqobkva\")\n        regexs[9].search(r\"zbqgvgyr\")\n        regexs[13].search(r\"uggc://cebsvyrrqvg.zlfcnpr.pbz/vaqrk.psz\")\n        regexs[26].search(r\"/vt/znvytnqtrg\")\n        regexs[49].search(r\"glcr\")\n\n\ndef block5():\n    for i in range(13):\n        regexs[14].sub(r\"\", \"purpx\", subcount[14])\n        regexs[15].sub(r\"\", \"purpx\", subcount[15])\n        regexs[14].sub(r\"\", \"pvgl\", subcount[14])\n        regexs[15].sub(r\"\", \"pvgl\", subcount[15])\n        regexs[14].sub(r\"\", \"qrpe fyvqrgrkg\", subcount[14])\n        regexs[15].sub(r\"\", \"qrpe fyvqrgrkg\", subcount[15])\n        regexs[14].sub(r\"\", \"svefg fryrpgrq\", subcount[14])\n        regexs[15].sub(r\"\", \"svefg fryrpgrq\", subcount[15])\n        regexs[14].sub(r\"\", \"uqy_rag\", subcount[14])\n        regexs[15].sub(r\"\", \"uqy_rag\", subcount[15])\n        regexs[14].sub(r\"\", \"vape fyvqrgrkg\", subcount[14])\n        regexs[15].sub(r\"\", \"vape fyvqrgrkg\", subcount[15])\n        regexs[5].sub(r\"\", \"vachggrkg QBZPbageby_cynprubyqre\", subcount[5])\n        regexs[14].sub(r\"\", \"cnerag puebzr6 fvatyr1 gno fryrpgrq\", subcount[14])\n        regexs[15].sub(r\"\", \"cnerag puebzr6 fvatyr1 gno fryrpgrq\", subcount[15])\n        regexs[14].sub(r\"\", \"cb_guz\", subcount[14])\n        regexs[15].sub(r\"\", \"cb_guz\", subcount[15])\n        regexs[14].sub(r\"\", \"fhozvg\", subcount[14])\n        regexs[15].sub(r\"\", \"fhozvg\", subcount[15])\n        regexs[50].search(r\"\")\n        re.search(r\"NccyrJroXvg\\/([^\\s]*)\", strings[0])\n        re.search(r\"XUGZY\", strings[0])\n\n    for i in range(12):\n        re.sub(r\"(\\$\\{cebg\\})|(\\$cebg\\b)\", \"\", \"${cebg}://${ubfg}${cngu}/${dz}\", 0)\n        regexs[40].sub(r\"\", \"1\", subcount[40])\n        regexs[10].sub(r\"\", \"1\", subcount[10])\n        regexs[51].sub(r\"\", \"1\", subcount[51])\n        regexs[52].sub(r\"\", \"1\", subcount[52])\n        regexs[53].sub(r\"\", \"1\", subcount[53])\n        regexs[39].sub(r\"\", \"1\", subcount[39])\n        regexs[54].sub(r\"\", \"1\", subcount[54])\n        re.sub(r\"^(.*)\\..*$\", \"\", \"9.0  e115\", 1)\n        re.sub(r\"^.*e(.*)$\", \"\", \"9.0  e115\", 1)\n        regexs[55].sub(r\"\", \"<!-- ${nqiHey} -->\", subcount[55])\n        regexs[55].sub(\n            r\"\",\n            '<fpevcg glcr=\"grkg/wninfpevcg\" fep=\"${nqiHey}\"></fpevcg>',\n            subcount[55],\n        )\n        re.sub(r\"^.*\\s+(\\S+\\s+\\S+$)\", \"\", strings[1], 1)\n        regexs[30].sub(r\"\", \"tzk%2Subzrcntr%2Sfgneg%2Sqr%2S\", subcount[30])\n        regexs[30].sub(r\"\", \"tzk\", subcount[30])\n        re.sub(r\"(\\$\\{ubfg\\})|(\\$ubfg\\b)\", \"\", \"uggc://${ubfg}${cngu}/${dz}\", 0)\n        regexs[56].sub(r\"\", \"uggc://nqpyvrag.hvzfrei.arg${cngu}/${dz}\", subcount[56])\n        re.sub(r\"(\\$\\{dz\\})|(\\$dz\\b)\", \"\", \"uggc://nqpyvrag.hvzfrei.arg/wf.at/${dz}\", 0)\n        regexs[29].sub(r\"\", \"frpgvba\", subcount[29])\n        regexs[30].sub(r\"\", \"frpgvba\", subcount[30])\n        regexs[29].sub(r\"\", \"fvgr\", subcount[29])\n        regexs[30].sub(r\"\", \"fvgr\", subcount[30])\n        regexs[29].sub(r\"\", \"fcrpvny\", subcount[29])\n        regexs[30].sub(r\"\", \"fcrpvny\", subcount[30])\n        regexs[36].search(r\"anzr\")\n        re.search(r\"e\", \"9.0  e115\")\n\n\ndef block6():\n    for i in range(11):\n        re.sub(r\"(?i)##yv0##\", \"\", strings[27], 0)\n        regexs[57].sub(r\"\", strings[27], subcount[57])\n        regexs[58].sub(r\"\", strings[28], subcount[58])\n        regexs[59].sub(r\"\", strings[29], subcount[59])\n        re.sub(r\"(?i)##\\/o##\", \"\", strings[30], 0)\n        re.sub(r\"(?i)##\\/v##\", \"\", strings[30], 0)\n        re.sub(r\"(?i)##\\/h##\", \"\", strings[30], 0)\n        re.sub(r\"(?i)##o##\", \"\", strings[30], 0)\n        re.sub(r\"(?i)##oe##\", \"\", strings[30], 0)\n        re.sub(r\"(?i)##v##\", \"\", strings[30], 0)\n        re.sub(r\"(?i)##h##\", \"\", strings[30], 0)\n        re.sub(r\"(?i)##n##\", \"\", strings[31], 0)\n        re.sub(r\"(?i)##\\/n##\", \"\", strings[32], 0)\n\n        # This prints a unicode escape where the V8 version\n        # prints the unicode character.\n        re.sub(r\"#~#argjbexybtb#~#\", \"\", strings[33], 0)\n\n        re.search(r\" Zbovyr\\/\", strings[0])\n        re.search(r\"##yv1##\", strings[27], re.IGNORECASE)\n        re.search(r\"##yv10##\", strings[28], re.IGNORECASE)\n        re.search(r\"##yv11##\", strings[28], re.IGNORECASE)\n        re.search(r\"##yv12##\", strings[28], re.IGNORECASE)\n        re.search(r\"##yv13##\", strings[28], re.IGNORECASE)\n        re.search(r\"##yv14##\", strings[28], re.IGNORECASE)\n        re.search(r\"##yv15##\", strings[28], re.IGNORECASE)\n        regexs[58].search(strings[28])\n        re.search(r\"##yv17##\", strings[29], re.IGNORECASE)\n        re.search(r\"##yv18##\", strings[29], re.IGNORECASE)\n        regexs[59].search(strings[29])\n        re.search(r\"##yv2##\", strings[27], re.IGNORECASE)\n        re.search(r\"##yv20##\", strings[30], re.IGNORECASE)\n        re.search(r\"##yv21##\", strings[30], re.IGNORECASE)\n        re.search(r\"##yv22##\", strings[30], re.IGNORECASE)\n        re.search(r\"##yv23##\", strings[30], re.IGNORECASE)\n        re.search(r\"##yv3##\", strings[27], re.IGNORECASE)\n        regexs[57].search(strings[27])\n        re.search(r\"##yv5##\", strings[28], re.IGNORECASE)\n        re.search(r\"##yv6##\", strings[28], re.IGNORECASE)\n        re.search(r\"##yv7##\", strings[28], re.IGNORECASE)\n        re.search(r\"##yv8##\", strings[28], re.IGNORECASE)\n        re.search(r\"##yv9##\", strings[28], re.IGNORECASE)\n        regexs[8].search(r\"473qq1rs0n2r70q9qo1pq48n021s9468ron90nps048p4p29\")\n        regexs[8].search(r\"SbeprqRkcvengvba=633669325184628362\")\n        regexs[8].search(\n            r\"FrffvbaQQS2=473qq1rs0n2r70q9qo1pq48n021s9468ron90nps048p4p29\"\n        )\n        re.search(r\"AbxvnA[^\\/]*\", strings[0])\n\n    for i in range(10):\n        re.sub(r\"(?:^|\\s+)bss(?:\\s+|$)\", \"\", \" bss\", 0)\n        re.sub(r\"(\\$\\{0\\})|(\\$0\\b)\", \"\", strings[34], 0)\n        re.sub(r\"(\\$\\{1\\})|(\\$1\\b)\", \"\", strings[34], 0)\n        re.sub(r\"(\\$\\{pbzcyrgr\\})|(\\$pbzcyrgr\\b)\", \"\", strings[34], 0)\n        re.sub(r\"(\\$\\{sentzrag\\})|(\\$sentzrag\\b)\", \"\", strings[34], 0)\n        re.sub(r\"(\\$\\{ubfgcbeg\\})|(\\$ubfgcbeg\\b)\", \"\", strings[34], 0)\n        regexs[56].sub(r\"\", strings[34], subcount[56])\n        re.sub(r\"(\\$\\{cebgbpby\\})|(\\$cebgbpby\\b)\", \"\", strings[34], 0)\n        re.sub(r\"(\\$\\{dhrel\\})|(\\$dhrel\\b)\", \"\", strings[34], 0)\n        regexs[29].sub(r\"\", \"nqfvmr\", subcount[29])\n        regexs[30].sub(r\"\", \"nqfvmr\", subcount[30])\n        re.sub(r\"(\\$\\{2\\})|(\\$2\\b)\", \"\", \"uggc://${2}${3}${4}${5}\", 0)\n        re.sub(r\"(\\$\\{3\\})|(\\$3\\b)\", \"\", \"uggc://wf.hv-cbegny.qr${3}${4}${5}\", 0)\n        regexs[40].sub(r\"\", \"arjf\", subcount[40])\n        regexs[41].sub(r\"\", \"arjf\", subcount[41])\n        regexs[42].sub(r\"\", \"arjf\", subcount[42])\n        regexs[43].sub(r\"\", \"arjf\", subcount[43])\n        regexs[44].sub(r\"\", \"arjf\", subcount[44])\n        regexs[45].sub(r\"\", \"arjf\", subcount[45])\n        regexs[46].sub(r\"\", \"arjf\", subcount[46])\n        regexs[47].sub(r\"\", \"arjf\", subcount[47])\n        regexs[48].sub(r\"\", \"arjf\", subcount[48])\n        re.search(r\" PC=i=(\\d+)&oe=(.)\", strings[35])\n        regexs[60].search(r\" \")\n        regexs[60].search(r\" bss\")\n        regexs[60].search(r\"\")\n        regexs[19].search(r\" \")\n        regexs[19].search(r\"svefg ba\")\n        regexs[19].search(r\"ynfg vtaber\")\n        regexs[19].search(r\"ba\")\n        regexs[9].search(r\"scnq so \")\n        regexs[9].search(r\"zrqvgobk\")\n        regexs[9].search(r\"hsgy\")\n        regexs[9].search(r\"lhv-h\")\n        re.search(r\"Fnsnev|Xbadhrebe|XUGZY\", strings[0], re.IGNORECASE)\n        regexs[61].search(r\"uggc://wf.hv-cbegny.qr/tzk/ubzr/wf/20080602/onfr.wf\")\n        regexs[62].search(r\"#Ybtva_rznvy\")\n\n\ndef block7():\n    for i in range(9):\n        regexs[40].sub(r\"\", \"0\", subcount[40])\n        regexs[10].sub(r\"\", \"0\", subcount[10])\n        regexs[51].sub(r\"\", \"0\", subcount[51])\n        regexs[52].sub(r\"\", \"0\", subcount[52])\n        regexs[53].sub(r\"\", \"0\", subcount[53])\n        regexs[39].sub(r\"\", \"0\", subcount[39])\n        regexs[54].sub(r\"\", \"0\", subcount[54])\n        regexs[40].sub(r\"\", \"Lrf\", subcount[40])\n        regexs[10].sub(r\"\", \"Lrf\", subcount[10])\n        regexs[51].sub(r\"\", \"Lrf\", subcount[51])\n        regexs[52].sub(r\"\", \"Lrf\", subcount[52])\n        regexs[53].sub(r\"\", \"Lrf\", subcount[53])\n        regexs[39].sub(r\"\", \"Lrf\", subcount[39])\n        regexs[54].sub(r\"\", \"Lrf\", subcount[54])\n\n    for i in range(8):\n        regexs[63].sub(r\"\", \"Pybfr {0}\", subcount[63])\n        regexs[63].sub(r\"\", \"Bcra {0}\", subcount[63])\n        regexs[32].split(strings[36])\n        regexs[32].split(strings[37])\n        regexs[14].sub(r\"\", \"puvyq p1 svefg gnournqref\", subcount[14])\n        regexs[15].sub(r\"\", \"puvyq p1 svefg gnournqref\", subcount[15])\n        regexs[14].sub(r\"\", \"uqy_fcb\", subcount[14])\n        regexs[15].sub(r\"\", \"uqy_fcb\", subcount[15])\n        regexs[14].sub(r\"\", \"uvag\", subcount[14])\n        regexs[15].sub(r\"\", \"uvag\", subcount[15])\n        regexs[33].sub(r\"\", strings[38], subcount[33])\n        regexs[14].sub(r\"\", \"yvfg\", subcount[14])\n        regexs[15].sub(r\"\", \"yvfg\", subcount[15])\n        regexs[30].sub(r\"\", \"at_bhgre\", subcount[30])\n        regexs[14].sub(r\"\", \"cnerag puebzr5 qbhoyr2 NU\", subcount[14])\n        regexs[15].sub(r\"\", \"cnerag puebzr5 qbhoyr2 NU\", subcount[15])\n        regexs[14].sub(r\"\", \"cnerag puebzr5 dhnq5 ps NU osyvax zbarl\", subcount[14])\n        regexs[15].sub(r\"\", \"cnerag puebzr5 dhnq5 ps NU osyvax zbarl\", subcount[15])\n        regexs[14].sub(r\"\", \"cnerag puebzr6 fvatyr1\", subcount[14])\n        regexs[15].sub(r\"\", \"cnerag puebzr6 fvatyr1\", subcount[15])\n        regexs[14].sub(r\"\", \"cb_qrs\", subcount[14])\n        regexs[15].sub(r\"\", \"cb_qrs\", subcount[15])\n        regexs[14].sub(r\"\", \"gnopbagrag\", subcount[14])\n        regexs[15].sub(r\"\", \"gnopbagrag\", subcount[15])\n        regexs[30].sub(r\"\", \"iv_svefg_gvzr\", subcount[30])\n        re.search(\n            r\"(^|.)(ronl|qri-ehf3.wbg)(|fgberf|zbgbef|yvirnhpgvbaf|jvxv|rkcerff|punggre).(pbz(|.nh|.pa|.ux|.zl|.ft|.oe|.zk)|pb(.hx|.xe|.am)|pn|qr|se|vg|ay|or|ng|pu|vr|va|rf|cy|cu|fr)$\",\n            \"cntrf.ronl.pbz\",\n            re.IGNORECASE,\n        )\n        regexs[8].search(r\"144631658.0.10.1231364074\")\n        regexs[8].search(\n            r\"144631658.1231364074.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)\"\n        )\n        regexs[8].search(\n            r\"144631658.2294274870215848400.1231364074.1231364074.1231364074.1\"\n        )\n        regexs[8].search(r\"4413241q3660\")\n        regexs[8].search(r\"SbeprqRkcvengvba=633669357391353591\")\n        regexs[8].search(strings[39])\n        regexs[8].search(strings[40])\n        regexs[8].search(r\"AFP_zp_kkk-gdzogv_80=4413241q3660\")\n        regexs[8].search(\n            r\"FrffvbaQQS2=p98s8o9q42nr21or1r61pqorn1n002nsss569635984s6qp7\"\n        )\n        regexs[8].search(\n            r\"__hgzn=144631658.2294274870215848400.1231364074.1231364074.1231364074.1\"\n        )\n        regexs[8].search(r\"__hgzo=144631658.0.10.1231364074\")\n        regexs[8].search(\n            r\"__hgzm=144631658.1231364074.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)\"\n        )\n        regexs[8].search(r\"p98s8o9q42nr21or1r61pqorn1n002nsss569635984s6qp7\")\n        regexs[34].search(strings[36])\n        regexs[34].search(strings[37])\n\n\ndef block8():\n    for i in range(7):\n        re.match(r\"\\d+\", strings[1])\n        regexs[64].sub(r\"\", \"nsgre\", subcount[64])\n        regexs[64].sub(r\"\", \"orsber\", subcount[64])\n        regexs[64].sub(r\"\", \"obggbz\", subcount[64])\n        regexs[65].sub(r\"\", \"ohvygva_jrngure.kzy\", subcount[65])\n        regexs[37].sub(r\"\", \"ohggba\", subcount[37])\n        regexs[18].sub(r\"\", \"ohggba\", subcount[18])\n        regexs[65].sub(r\"\", \"qngrgvzr.kzy\", subcount[65])\n        regexs[65].sub(r\"\", \"uggc://eff.paa.pbz/eff/paa_gbcfgbevrf.eff\", subcount[65])\n        regexs[37].sub(r\"\", \"vachg\", subcount[37])\n        regexs[18].sub(r\"\", \"vachg\", subcount[18])\n        regexs[64].sub(r\"\", \"vafvqr\", subcount[64])\n        regexs[27].sub(r\"\", \"cbvagre\", subcount[27])\n        re.sub(r\"[A-Z]\", \"\", \"cbfvgvba\", 0)\n        regexs[27].sub(r\"\", \"gbc\", subcount[27])\n        regexs[64].sub(r\"\", \"gbc\", subcount[64])\n        regexs[37].sub(r\"\", \"hy\", subcount[37])\n        regexs[18].sub(r\"\", \"hy\", subcount[18])\n        regexs[37].sub(r\"\", strings[26], subcount[37])\n        regexs[18].sub(r\"\", strings[26], subcount[18])\n        regexs[65].sub(r\"\", \"lbhghor_vtbbtyr/i2/lbhghor.kzy\", subcount[65])\n        regexs[27].sub(r\"\", \"m-vaqrk\", subcount[27])\n        re.search(r\"#([\\w-]+)\", strings[26])\n        regexs[16].search(r\"urvtug\")\n        regexs[16].search(r\"znetvaGbc\")\n        regexs[16].search(r\"jvqgu\")\n        regexs[19].search(r\"gno0 svefg ba\")\n        regexs[19].search(r\"gno0 ba\")\n        regexs[19].search(r\"gno4 ynfg\")\n        regexs[19].search(r\"gno4\")\n        regexs[19].search(r\"gno5\")\n        regexs[19].search(r\"gno6\")\n        regexs[19].search(r\"gno7\")\n        regexs[19].search(r\"gno8\")\n        re.search(r\"NqborNVE\\/([^\\s]*)\", strings[0])\n        re.search(r\"NccyrJroXvg\\/([^ ]*)\", strings[0])\n        re.search(r\"XUGZY\", strings[0], re.IGNORECASE)\n        re.search(r\"^(?:obql|ugzy)$\", \"YV\", re.IGNORECASE)\n        regexs[38].search(r\"ohggba\")\n        regexs[38].search(r\"vachg\")\n        regexs[38].search(r\"hy\")\n        regexs[38].search(strings[26])\n        re.search(r\"^(\\w+|\\*)\", strings[26])\n        re.search(r\"znp|jva|yvahk\", \"Jva32\", re.IGNORECASE)\n        re.search(r\"eton?\\([\\d\\s,]+\\)\", \"fgngvp\")\n\n    for i in range(6):\n        re.sub(r\"\\r\", \"\", \"\", 0)\n        regexs[40].sub(r\"\", \"/\", subcount[40])\n        regexs[10].sub(r\"\", \"/\", subcount[10])\n        regexs[51].sub(r\"\", \"/\", subcount[51])\n        regexs[52].sub(r\"\", \"/\", subcount[52])\n        regexs[53].sub(r\"\", \"/\", subcount[53])\n        regexs[39].sub(r\"\", \"/\", subcount[39])\n        regexs[54].sub(r\"\", \"/\", subcount[54])\n        regexs[63].sub(\n            r\"\",\n            \"uggc://zfacbegny.112.2b7.arg/o/ff/zfacbegnyubzr/1/U.7-cqi-2/{0}?[NDO]&{1}&{2}&[NDR]\",\n            subcount[63],\n        )\n        regexs[12].sub(r\"\", strings[41], subcount[12])\n        regexs[23].sub(r\"\", \"uggc://jjj.snprobbx.pbz/fepu.cuc\", subcount[23])\n        regexs[40].sub(r\"\", \"freivpr\", subcount[40])\n        regexs[41].sub(r\"\", \"freivpr\", subcount[41])\n        regexs[42].sub(r\"\", \"freivpr\", subcount[42])\n        regexs[43].sub(r\"\", \"freivpr\", subcount[43])\n        regexs[44].sub(r\"\", \"freivpr\", subcount[44])\n        regexs[45].sub(r\"\", \"freivpr\", subcount[45])\n        regexs[46].sub(r\"\", \"freivpr\", subcount[46])\n        regexs[47].sub(r\"\", \"freivpr\", subcount[47])\n        regexs[48].sub(r\"\", \"freivpr\", subcount[48])\n        re.search(r\"((ZFVR\\s+([6-9]|\\d\\d)\\.))\", strings[0])\n        regexs[66].search(r\"\")\n        regexs[50].search(r\"fryrpgrq\")\n        regexs[8].search(r\"8sqq78r9n442851q565599o401385sp3s04r92rnn7o19ssn\")\n        regexs[8].search(r\"SbeprqRkcvengvba=633669340386893867\")\n        regexs[8].search(r\"VC=74.125.75.17\")\n        regexs[8].search(\n            r\"FrffvbaQQS2=8sqq78r9n442851q565599o401385sp3s04r92rnn7o19ssn\"\n        )\n        re.search(r\"Xbadhrebe|Fnsnev|XUGZY\", strings[0])\n        regexs[13].search(strings[41])\n        regexs[49].search(r\"unfsbphf\")\n\n\ndef block9():\n    for i in range(5):\n        regexs[32].split(strings[42])\n        regexs[32].split(strings[43])\n        regexs[20].split(r\"svz_zlfcnpr_hfre-ivrj-pbzzragf,svz_zlfcnpr_havgrq-fgngrf\")\n        regexs[33].sub(r\"\", strings[44], subcount[33])\n        regexs[67].sub(r\"\", \"zrah_arj zrah_arj_gbttyr zrah_gbttyr\", subcount[67])\n        regexs[67].sub(r\"\", \"zrah_byq zrah_byq_gbttyr zrah_gbttyr\", subcount[67])\n        regexs[8].search(r\"102n9o0o9pq60132qn0337rr867p75953502q2s27s2s5r98\")\n        regexs[8].search(r\"144631658.0.10.1231364380\")\n        regexs[8].search(\n            r\"144631658.1231364380.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)\"\n        )\n        regexs[8].search(\n            r\"144631658.3931862196947939300.1231364380.1231364380.1231364380.1\"\n        )\n        regexs[8].search(r\"441326q33660\")\n        regexs[8].search(r\"SbeprqRkcvengvba=633669341278771470\")\n        regexs[8].search(strings[45])\n        regexs[8].search(strings[46])\n        regexs[8].search(r\"AFP_zp_dfctwzssrwh-aowb_80=441326q33660\")\n        regexs[8].search(\n            r\"FrffvbaQQS2=102n9o0o9pq60132qn0337rr867p75953502q2s27s2s5r98\"\n        )\n        regexs[8].search(\n            r\"__hgzn=144631658.3931862196947939300.1231364380.1231364380.1231364380.1\"\n        )\n        regexs[8].search(r\"__hgzo=144631658.0.10.1231364380\")\n        regexs[8].search(\n            r\"__hgzm=144631658.1231364380.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)\"\n        )\n\n    for i in range(4):\n        regexs[14].sub(r\"\", \" yvfg1\", subcount[14])\n        regexs[15].sub(r\"\", \" yvfg1\", subcount[15])\n        regexs[14].sub(r\"\", \" yvfg2\", subcount[14])\n        regexs[15].sub(r\"\", \" yvfg2\", subcount[15])\n        regexs[14].sub(r\"\", \" frneputebhc1\", subcount[14])\n        regexs[15].sub(r\"\", \" frneputebhc1\", subcount[15])\n        regexs[68].sub(r\"\", strings[47], subcount[68])\n        regexs[18].sub(r\"\", strings[47], subcount[18])\n        re.sub(r\"&\", \"\", \"\", 0)\n        regexs[35].sub(r\"\", \"\", subcount[35])\n        regexs[63].sub(r\"\", \"(..-{0})(|(d+)|)\", subcount[63])\n        regexs[18].sub(r\"\", strings[48], subcount[18])\n        regexs[56].sub(\n            r\"\", \"//vzt.jro.qr/vij/FC/${cngu}/${anzr}/${inyhr}?gf=${abj}\", subcount[56]\n        )\n        re.sub(\n            r\"(\\$\\{anzr\\})|(\\$anzr\\b)\",\n            \"\",\n            \"//vzt.jro.qr/vij/FC/tzk_uc/${anzr}/${inyhr}?gf=${abj}\",\n            0,\n        )\n        regexs[69].sub(\n            r\"\",\n            '<fcna pynff=\"urnq\"><o>Jvaqbjf Yvir Ubgznvy</o></fcna><fcna pynff=\"zft\">{1}</fcna>',\n            subcount[69],\n        )\n        regexs[63].sub(\n            r\"\",\n            '<fcna pynff=\"urnq\"><o>{0}</o></fcna><fcna pynff=\"zft\">{1}</fcna>',\n            subcount[63],\n        )\n        regexs[69].sub(\n            r\"\",\n            '<fcna pynff=\"fvtahc\"><n uers=uggc://jjj.ubgznvy.pbz><o>{1}</o></n></fcna>',\n            subcount[69],\n        )\n        regexs[63].sub(\n            r\"\", '<fcna pynff=\"fvtahc\"><n uers={0}><o>{1}</o></n></fcna>', subcount[63]\n        )\n        regexs[15].sub(r\"\", \"Vzntrf\", subcount[15])\n        regexs[15].sub(r\"\", \"ZFA\", subcount[15])\n        regexs[15].sub(r\"\", \"Zncf\", subcount[15])\n        regexs[39].sub(r\"\", \"Zbq-Vasb-Vasb-WninFpevcgUvag\", subcount[39])\n        regexs[15].sub(r\"\", \"Arjf\", subcount[15])\n        regexs[32].split(strings[49])\n        regexs[32].split(strings[50])\n        regexs[15].sub(r\"\", \"Ivqrb\", subcount[15])\n        regexs[15].sub(r\"\", \"Jro\", subcount[15])\n        regexs[39].sub(r\"\", \"n\", subcount[39])\n        regexs[70].split(r\"nwnkFgneg\")\n        regexs[70].split(r\"nwnkFgbc\")\n        regexs[14].sub(r\"\", \"ovaq\", subcount[14])\n        regexs[15].sub(r\"\", \"ovaq\", subcount[15])\n        regexs[63].sub(\n            r\"\",\n            \"oevatf lbh zber. Zber fcnpr (5TO), zber frphevgl, fgvyy serr.\",\n            subcount[63],\n        )\n        regexs[14].sub(r\"\", \"puvyq p1 svefg qrpx\", subcount[14])\n        regexs[15].sub(r\"\", \"puvyq p1 svefg qrpx\", subcount[15])\n        regexs[14].sub(r\"\", \"puvyq p1 svefg qbhoyr2\", subcount[14])\n        regexs[15].sub(r\"\", \"puvyq p1 svefg qbhoyr2\", subcount[15])\n        regexs[14].sub(r\"\", \"puvyq p2 ynfg\", subcount[14])\n        regexs[15].sub(r\"\", \"puvyq p2 ynfg\", subcount[15])\n        regexs[14].sub(r\"\", \"puvyq p2\", subcount[14])\n        regexs[15].sub(r\"\", \"puvyq p2\", subcount[15])\n        regexs[14].sub(r\"\", \"puvyq p3\", subcount[14])\n        regexs[15].sub(r\"\", \"puvyq p3\", subcount[15])\n        regexs[14].sub(r\"\", \"puvyq p4 ynfg\", subcount[14])\n        regexs[15].sub(r\"\", \"puvyq p4 ynfg\", subcount[15])\n        regexs[14].sub(r\"\", \"pbclevtug\", subcount[14])\n        regexs[15].sub(r\"\", \"pbclevtug\", subcount[15])\n        regexs[14].sub(r\"\", \"qZFAZR_1\", subcount[14])\n        regexs[15].sub(r\"\", \"qZFAZR_1\", subcount[15])\n        regexs[14].sub(r\"\", \"qbhoyr2 ps\", subcount[14])\n        regexs[15].sub(r\"\", \"qbhoyr2 ps\", subcount[15])\n        regexs[14].sub(r\"\", \"qbhoyr2\", subcount[14])\n        regexs[15].sub(r\"\", \"qbhoyr2\", subcount[15])\n        regexs[14].sub(r\"\", \"uqy_arj\", subcount[14])\n        regexs[15].sub(r\"\", \"uqy_arj\", subcount[15])\n        regexs[30].sub(r\"\", \"uc_fubccvatobk\", subcount[30])\n        regexs[29].sub(r\"\", \"ugzy%2Rvq\", subcount[29])\n        regexs[30].sub(r\"\", \"ugzy%2Rvq\", subcount[30])\n        regexs[33].sub(r\"\", strings[51], subcount[33])\n        regexs[71].sub(\n            r\"\",\n            \"uggc://wf.hv-cbegny.qr/tzk/ubzr/wf/20080602/cebgbglcr.wf${4}${5}\",\n            subcount[71],\n        )\n        regexs[72].sub(\n            r\"\",\n            \"uggc://wf.hv-cbegny.qr/tzk/ubzr/wf/20080602/cebgbglcr.wf${5}\",\n            subcount[72],\n        )\n        regexs[73].sub(r\"\", strings[52], subcount[73])\n        regexs[69].sub(\n            r\"\",\n            \"uggc://zfacbegny.112.2b7.arg/o/ff/zfacbegnyubzr/1/U.7-cqi-2/f55332979829981?[NDO]&{1}&{2}&[NDR]\",\n            subcount[69],\n        )\n        regexs[14].sub(r\"\", \"vztZFSG\", subcount[14])\n        regexs[15].sub(r\"\", \"vztZFSG\", subcount[15])\n        regexs[14].sub(r\"\", \"zfasbbg1 ps\", subcount[14])\n        regexs[15].sub(r\"\", \"zfasbbg1 ps\", subcount[15])\n        regexs[14].sub(r\"\", strings[53], subcount[14])\n        regexs[15].sub(r\"\", strings[53], subcount[15])\n        regexs[14].sub(r\"\", \"cnerag puebzr6 fvatyr1 gno fryrpgrq ovaq\", subcount[14])\n        regexs[15].sub(r\"\", \"cnerag puebzr6 fvatyr1 gno fryrpgrq ovaq\", subcount[15])\n        regexs[14].sub(r\"\", \"cevznel\", subcount[14])\n        regexs[15].sub(r\"\", \"cevznel\", subcount[15])\n        regexs[30].sub(r\"\", \"erpgnatyr\", subcount[30])\n        regexs[14].sub(r\"\", \"frpbaqnel\", subcount[14])\n        regexs[15].sub(r\"\", \"frpbaqnel\", subcount[15])\n        regexs[70].split(r\"haybnq\")\n        regexs[63].sub(r\"\", \"{0}{1}1\", subcount[63])\n        regexs[69].sub(r\"\", \"|{1}1\", subcount[69])\n        re.search(r\"(..-HF)(\\|(\\d+)|)\", \"xb-xe,ra-va,gu-gu\", re.IGNORECASE)\n        regexs[4].search(r\"/ZlFcnprNccf/NccPnainf,45000012\")\n        regexs[8].search(r\"144631658.0.10.1231367708\")\n        regexs[8].search(\n            r\"144631658.1231367708.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)\"\n        )\n        regexs[8].search(\n            r\"144631658.2770915348920628700.1231367708.1231367708.1231367708.1\"\n        )\n        regexs[8].search(r\"4413235p3660\")\n        regexs[8].search(r\"441327q73660\")\n        regexs[8].search(r\"9995p6rp12rrnr893334ro7nq70o7p64p69rqn844prs1473\")\n        regexs[8].search(r\"SbeprqRkcvengvba=633669350559478880\")\n        regexs[8].search(strings[54])\n        regexs[8].search(strings[55])\n        regexs[8].search(r\"AFP_zp_dfctwzs-aowb_80=441327q73660\")\n        regexs[8].search(r\"AFP_zp_kkk-aowb_80=4413235p3660\")\n        regexs[8].search(\n            r\"FrffvbaQQS2=9995p6rp12rrnr893334ro7nq70o7p64p69rqn844prs1473\"\n        )\n        regexs[8].search(\n            r\"__hgzn=144631658.2770915348920628700.1231367708.1231367708.1231367708.1\"\n        )\n        regexs[8].search(r\"__hgzo=144631658.0.10.1231367708\")\n        regexs[8].search(\n            r\"__hgzm=144631658.1231367708.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)\"\n        )\n        regexs[34].search(strings[49])\n        regexs[34].search(strings[50])\n        re.search(r\"ZFVR\\s+5[.]01\", strings[0])\n        re.search(r\"HF(?=;)\", strings[56], re.IGNORECASE)\n        regexs[74].search(strings[47])\n        regexs[28].search(r\"svefg npgvir svefgNpgvir\")\n        regexs[28].search(r\"ynfg\")\n        re.search(r\"\\bp:(..)\", \"m:94043|yn:37.4154|yb:-122.0585|p:HF\", re.IGNORECASE)\n        regexs[75].search(strings[57])\n        regexs[75].search(strings[58])\n        regexs[76].search(strings[57])\n        regexs[76].search(strings[58])\n        regexs[77].search(strings[57])\n        regexs[77].search(strings[58])\n        re.search(r\"\\bhfucce\\s*=\\s*([^;]*)\", strings[59], re.IGNORECASE)\n        regexs[78].search(strings[57])\n        regexs[78].search(strings[58])\n        re.search(r\"\\bjci\\s*=\\s*([^;]*)\", strings[59], re.IGNORECASE)\n        regexs[79].search(strings[58])\n        regexs[79].search(strings[60])\n        regexs[79].search(strings[59])\n        re.search(\n            r\"\\|p:([a-z]{2})\",\n            \"m:94043|yn:37.4154|yb:-122.0585|p:HF|ue:1\",\n            re.IGNORECASE,\n        )\n        regexs[80].search(strings[47])\n        regexs[61].search(r\"cebgbglcr.wf\")\n        regexs[68].search(strings[47])\n        regexs[81].search(strings[47])\n        regexs[82].search(strings[47])\n        re.search(r\"^Fubpxjnir Synfu (\\d)\", strings[1])\n        re.search(r\"^Fubpxjnir Synfu (\\d+)\", strings[1])\n        regexs[83].search(r\"[bowrpg tybony]\")\n        regexs[62].search(strings[47])\n        regexs[84].search(strings[61])\n        regexs[84].search(strings[62])\n        re.search(r\"jroxvg\", strings[63])\n\n\ndef block10():\n    for i in range(3):\n        regexs[39].sub(r\"\", \"%3Szxg=ra-HF\", subcount[39])\n        regexs[40].sub(r\"\", \"-8\", subcount[40])\n        regexs[10].sub(r\"\", \"-8\", subcount[10])\n        regexs[51].sub(r\"\", \"-8\", subcount[51])\n        regexs[52].sub(r\"\", \"-8\", subcount[52])\n        regexs[53].sub(r\"\", \"-8\", subcount[53])\n        regexs[39].sub(r\"\", \"-8\", subcount[39])\n        regexs[54].sub(r\"\", \"-8\", subcount[54])\n        regexs[40].sub(r\"\", \"1.5\", subcount[40])\n        regexs[10].sub(r\"\", \"1.5\", subcount[10])\n        regexs[51].sub(r\"\", \"1.5\", subcount[51])\n        regexs[52].sub(r\"\", \"1.5\", subcount[52])\n        regexs[53].sub(r\"\", \"1.5\", subcount[53])\n        regexs[39].sub(r\"\", \"1.5\", subcount[39])\n        regexs[54].sub(r\"\", \"1.5\", subcount[54])\n        regexs[40].sub(r\"\", \"1024k768\", subcount[40])\n        regexs[10].sub(r\"\", \"1024k768\", subcount[10])\n        regexs[51].sub(r\"\", \"1024k768\", subcount[51])\n        regexs[52].sub(r\"\", \"1024k768\", subcount[52])\n        regexs[53].sub(r\"\", \"1024k768\", subcount[53])\n        regexs[39].sub(r\"\", \"1024k768\", subcount[39])\n        regexs[54].sub(r\"\", \"1024k768\", subcount[54])\n        regexs[40].sub(r\"\", strings[64], subcount[40])\n        regexs[10].sub(r\"\", strings[64], subcount[10])\n        regexs[51].sub(r\"\", strings[64], subcount[51])\n        regexs[52].sub(r\"\", strings[64], subcount[52])\n        regexs[53].sub(r\"\", strings[64], subcount[53])\n        regexs[39].sub(r\"\", strings[64], subcount[39])\n        regexs[54].sub(r\"\", strings[64], subcount[54])\n        regexs[40].sub(r\"\", \"14\", subcount[40])\n        regexs[10].sub(r\"\", \"14\", subcount[10])\n        regexs[51].sub(r\"\", \"14\", subcount[51])\n        regexs[52].sub(r\"\", \"14\", subcount[52])\n        regexs[53].sub(r\"\", \"14\", subcount[53])\n        regexs[39].sub(r\"\", \"14\", subcount[39])\n        regexs[54].sub(r\"\", \"14\", subcount[54])\n        regexs[40].sub(r\"\", \"24\", subcount[40])\n        regexs[10].sub(r\"\", \"24\", subcount[10])\n        regexs[51].sub(r\"\", \"24\", subcount[51])\n        regexs[52].sub(r\"\", \"24\", subcount[52])\n        regexs[53].sub(r\"\", \"24\", subcount[53])\n        regexs[39].sub(r\"\", \"24\", subcount[39])\n        regexs[54].sub(r\"\", \"24\", subcount[54])\n        regexs[40].sub(r\"\", strings[65], subcount[40])\n        regexs[10].sub(r\"\", strings[65], subcount[10])\n        regexs[51].sub(r\"\", strings[65], subcount[51])\n        regexs[52].sub(r\"\", strings[65], subcount[52])\n        regexs[53].sub(r\"\", strings[65], subcount[53])\n        regexs[39].sub(r\"\", strings[65], subcount[39])\n        regexs[54].sub(r\"\", strings[65], subcount[54])\n        regexs[40].sub(r\"\", strings[66], subcount[40])\n        regexs[10].sub(r\"\", strings[66], subcount[10])\n        regexs[51].sub(r\"\", strings[66], subcount[51])\n        regexs[52].sub(r\"\", strings[66], subcount[52])\n        regexs[53].sub(r\"\", strings[66], subcount[53])\n        regexs[39].sub(r\"\", strings[66], subcount[39])\n        regexs[54].sub(r\"\", strings[66], subcount[54])\n        regexs[40].sub(r\"\", \"9.0\", subcount[40])\n        regexs[10].sub(r\"\", \"9.0\", subcount[10])\n        regexs[51].sub(r\"\", \"9.0\", subcount[51])\n        regexs[52].sub(r\"\", \"9.0\", subcount[52])\n        regexs[53].sub(r\"\", \"9.0\", subcount[53])\n        regexs[39].sub(r\"\", \"9.0\", subcount[39])\n        regexs[54].sub(r\"\", \"9.0\", subcount[54])\n        regexs[40].sub(r\"\", \"994k634\", subcount[40])\n        regexs[10].sub(r\"\", \"994k634\", subcount[10])\n        regexs[51].sub(r\"\", \"994k634\", subcount[51])\n        regexs[52].sub(r\"\", \"994k634\", subcount[52])\n        regexs[53].sub(r\"\", \"994k634\", subcount[53])\n        regexs[39].sub(r\"\", \"994k634\", subcount[39])\n        regexs[54].sub(r\"\", \"994k634\", subcount[54])\n        regexs[40].sub(r\"\", \"?zxg=ra-HF\", subcount[40])\n        regexs[10].sub(r\"\", \"?zxg=ra-HF\", subcount[10])\n        regexs[51].sub(r\"\", \"?zxg=ra-HF\", subcount[51])\n        regexs[52].sub(r\"\", \"?zxg=ra-HF\", subcount[52])\n        regexs[53].sub(r\"\", \"?zxg=ra-HF\", subcount[53])\n        regexs[54].sub(r\"\", \"?zxg=ra-HF\", subcount[54])\n        regexs[25].sub(r\"\", \"PAA.pbz\", subcount[25])\n        regexs[12].sub(r\"\", \"PAA.pbz\", subcount[12])\n        regexs[39].sub(r\"\", \"PAA.pbz\", subcount[39])\n        regexs[25].sub(r\"\", \"Qngr & Gvzr\", subcount[25])\n        regexs[12].sub(r\"\", \"Qngr & Gvzr\", subcount[12])\n        regexs[39].sub(r\"\", \"Qngr & Gvzr\", subcount[39])\n        regexs[40].sub(r\"\", \"Frnepu Zvpebfbsg.pbz\", subcount[40])\n        regexs[54].sub(r\"\", \"Frnepu Zvpebfbsg.pbz\", subcount[54])\n        regexs[10].sub(r\"\", strings[67], subcount[10])\n        regexs[51].sub(r\"\", strings[67], subcount[51])\n        regexs[52].sub(r\"\", strings[67], subcount[52])\n        regexs[53].sub(r\"\", strings[67], subcount[53])\n        regexs[39].sub(r\"\", strings[67], subcount[39])\n        regexs[32].split(strings[68])\n        regexs[32].split(strings[69])\n        regexs[52].sub(r\"\", strings[70], subcount[52])\n        regexs[53].sub(r\"\", strings[70], subcount[53])\n        regexs[39].sub(r\"\", strings[70], subcount[39])\n        regexs[40].sub(r\"\", strings[71], subcount[40])\n        regexs[10].sub(r\"\", strings[71], subcount[10])\n        regexs[51].sub(r\"\", strings[71], subcount[51])\n        regexs[54].sub(r\"\", strings[71], subcount[54])\n        regexs[25].sub(r\"\", \"Jrngure\", subcount[25])\n        regexs[12].sub(r\"\", \"Jrngure\", subcount[12])\n        regexs[39].sub(r\"\", \"Jrngure\", subcount[39])\n        regexs[25].sub(r\"\", \"LbhGhor\", subcount[25])\n        regexs[12].sub(r\"\", \"LbhGhor\", subcount[12])\n        regexs[39].sub(r\"\", \"LbhGhor\", subcount[39])\n        regexs[33].sub(r\"\", strings[72], subcount[33])\n        re.sub(r\"^erzbgr_vsenzr_\", \"\", \"erzbgr_vsenzr_1\", 1)\n        regexs[40].sub(r\"\", strings[73], subcount[40])\n        regexs[10].sub(r\"\", strings[73], subcount[10])\n        regexs[51].sub(r\"\", strings[73], subcount[51])\n        regexs[52].sub(r\"\", strings[73], subcount[52])\n        regexs[53].sub(r\"\", strings[73], subcount[53])\n        regexs[39].sub(r\"\", strings[73], subcount[39])\n        regexs[54].sub(r\"\", strings[73], subcount[54])\n        regexs[40].sub(r\"\", strings[74], subcount[40])\n        regexs[10].sub(r\"\", strings[74], subcount[10])\n        regexs[51].sub(r\"\", strings[74], subcount[51])\n        regexs[52].sub(r\"\", strings[74], subcount[52])\n        regexs[53].sub(r\"\", strings[74], subcount[53])\n        regexs[39].sub(r\"\", strings[74], subcount[39])\n        regexs[54].sub(r\"\", strings[74], subcount[54])\n        re.sub(r\"\\-\", \"\", \"lhv-h\", 0)\n        regexs[9].search(r\"p\")\n        regexs[9].search(r\"qz p\")\n        regexs[9].search(r\"zbqynory\")\n        regexs[9].search(r\"lhv-h svefg\")\n        regexs[8].search(r\"144631658.0.10.1231365779\")\n        regexs[8].search(\n            r\"144631658.1231365779.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)\"\n        )\n        regexs[8].search(\n            r\"144631658.1877536177953918500.1231365779.1231365779.1231365779.1\"\n        )\n        regexs[8].search(strings[75])\n        regexs[8].search(strings[76])\n        regexs[8].search(\n            r\"__hgzn=144631658.1877536177953918500.1231365779.1231365779.1231365779.1\"\n        )\n        regexs[8].search(r\"__hgzo=144631658.0.10.1231365779\")\n        regexs[8].search(\n            r\"__hgzm=144631658.1231365779.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)\"\n        )\n        regexs[34].search(strings[68])\n        regexs[34].search(strings[69])\n        re.search(r\"^$\", \"\")\n        regexs[31].search(r\"qr\")\n        re.search(r\"^znk\\d+$\", \"\")\n        re.search(r\"^zva\\d+$\", \"\")\n        re.search(r\"^erfgber$\", \"\")\n        regexs[85].search(r\"zbqobkva zbqobk_abcnqqvat \")\n        regexs[85].search(r\"zbqgvgyr\")\n        regexs[85].search(r\"eaq_zbqobkva \")\n        regexs[85].search(r\"eaq_zbqgvgyr \")\n        re.search(r\"frpgvba\\d+_pbagragf\", \"obggbz_ani\")\n\n\ndef block11():\n    for i in range(2):\n        regexs[18].sub(r\"\", \" .pybfr\", subcount[18])\n        regexs[18].sub(r\"\", \" n.svryqOgaPnapry\", subcount[18])\n        regexs[18].sub(r\"\", \" qg\", subcount[18])\n        regexs[68].sub(r\"\", strings[77], subcount[68])\n        regexs[18].sub(r\"\", strings[77], subcount[18])\n        regexs[39].sub(r\"\", \"\", subcount[39])\n        re.sub(r\"^\", \"\", \"\", 1)\n        regexs[86].split(r\"\")\n        regexs[39].sub(r\"\", \"*\", subcount[39])\n        regexs[68].sub(r\"\", \"*\", subcount[68])\n        regexs[18].sub(r\"\", \"*\", subcount[18])\n        regexs[68].sub(r\"\", \".pybfr\", subcount[68])\n        regexs[18].sub(r\"\", \".pybfr\", subcount[18])\n        regexs[87].sub(\n            r\"\", \"//vzt.jro.qr/vij/FC/tzk_uc/fperra/${inyhr}?gf=${abj}\", subcount[87]\n        )\n        regexs[88].sub(\n            r\"\", \"//vzt.jro.qr/vij/FC/tzk_uc/fperra/1024?gf=${abj}\", subcount[88]\n        )\n        regexs[87].sub(\n            r\"\", \"//vzt.jro.qr/vij/FC/tzk_uc/jvafvmr/${inyhr}?gf=${abj}\", subcount[87]\n        )\n        regexs[88].sub(\n            r\"\", \"//vzt.jro.qr/vij/FC/tzk_uc/jvafvmr/992/608?gf=${abj}\", subcount[88]\n        )\n        regexs[30].sub(r\"\", \"300k120\", subcount[30])\n        regexs[30].sub(r\"\", \"300k250\", subcount[30])\n        regexs[30].sub(r\"\", \"310k120\", subcount[30])\n        regexs[30].sub(r\"\", \"310k170\", subcount[30])\n        regexs[30].sub(r\"\", \"310k250\", subcount[30])\n        re.sub(r\"^.*\\.(.*)\\s.*$\", \"\", \"9.0  e115\", 1)\n        regexs[2].sub(r\"\", \"Nppbeqvba\", subcount[2])\n        regexs[89].sub(r\"\", \"Nxghryy\\x0a\", subcount[89])\n        regexs[90].sub(r\"\", \"Nxghryy\\x0a\", subcount[90])\n        regexs[2].sub(r\"\", \"Nccyvpngvba\", subcount[2])\n        regexs[89].sub(r\"\", \"Oyvpxchaxg\\x0a\", subcount[89])\n        regexs[90].sub(r\"\", \"Oyvpxchaxg\\x0a\", subcount[90])\n        regexs[89].sub(r\"\", \"Svanamra\\x0a\", subcount[89])\n        regexs[90].sub(r\"\", \"Svanamra\\x0a\", subcount[90])\n        regexs[89].sub(r\"\", \"Tnzrf\\x0a\", subcount[89])\n        regexs[90].sub(r\"\", \"Tnzrf\\x0a\", subcount[90])\n        regexs[89].sub(r\"\", \"Ubebfxbc\\x0a\", subcount[89])\n        regexs[90].sub(r\"\", \"Ubebfxbc\\x0a\", subcount[90])\n        regexs[89].sub(r\"\", \"Xvab\\x0a\", subcount[89])\n        regexs[90].sub(r\"\", \"Xvab\\x0a\", subcount[90])\n        regexs[2].sub(r\"\", \"Zbqhyrf\", subcount[2])\n        regexs[89].sub(r\"\", \"Zhfvx\\x0a\", subcount[89])\n        regexs[90].sub(r\"\", \"Zhfvx\\x0a\", subcount[90])\n        regexs[89].sub(r\"\", \"Anpuevpugra\\x0a\", subcount[89])\n        regexs[90].sub(r\"\", \"Anpuevpugra\\x0a\", subcount[90])\n        regexs[2].sub(r\"\", \"Cuk\", subcount[2])\n        regexs[70].split(r\"ErdhrfgSvavfu\")\n        regexs[70].split(r\"ErdhrfgSvavfu.NWNK.Cuk\")\n        regexs[89].sub(r\"\", \"Ebhgr\\x0a\", subcount[89])\n        regexs[90].sub(r\"\", \"Ebhgr\\x0a\", subcount[90])\n        regexs[32].split(strings[78])\n        regexs[32].split(strings[79])\n        regexs[32].split(strings[80])\n        regexs[32].split(strings[81])\n        regexs[89].sub(r\"\", \"Fcbeg\\x0a\", subcount[89])\n        regexs[90].sub(r\"\", \"Fcbeg\\x0a\", subcount[90])\n        regexs[89].sub(r\"\", \"GI-Fcbg\\x0a\", subcount[89])\n        regexs[90].sub(r\"\", \"GI-Fcbg\\x0a\", subcount[90])\n        regexs[89].sub(r\"\", \"Gbhe\\x0a\", subcount[89])\n        regexs[90].sub(r\"\", \"Gbhe\\x0a\", subcount[90])\n        regexs[89].sub(r\"\", \"Hagreunyghat\\x0a\", subcount[89])\n        regexs[90].sub(r\"\", \"Hagreunyghat\\x0a\", subcount[90])\n        regexs[89].sub(r\"\", \"Ivqrb\\x0a\", subcount[89])\n        regexs[90].sub(r\"\", \"Ivqrb\\x0a\", subcount[90])\n        regexs[89].sub(r\"\", \"Jrggre\\x0a\", subcount[89])\n        regexs[90].sub(r\"\", \"Jrggre\\x0a\", subcount[90])\n        regexs[68].sub(r\"\", strings[82], subcount[68])\n        regexs[18].sub(r\"\", strings[82], subcount[18])\n        regexs[68].sub(r\"\", strings[83], subcount[68])\n        regexs[18].sub(r\"\", strings[83], subcount[18])\n        regexs[68].sub(r\"\", strings[84], subcount[68])\n        regexs[18].sub(r\"\", strings[84], subcount[18])\n        regexs[30].sub(r\"\", \"nqiFreivprObk\", subcount[30])\n        regexs[30].sub(r\"\", \"nqiFubccvatObk\", subcount[30])\n        regexs[39].sub(r\"\", \"nwnk\", subcount[39])\n        regexs[40].sub(r\"\", \"nxghryy\", subcount[40])\n        regexs[41].sub(r\"\", \"nxghryy\", subcount[41])\n        regexs[42].sub(r\"\", \"nxghryy\", subcount[42])\n        regexs[43].sub(r\"\", \"nxghryy\", subcount[43])\n        regexs[44].sub(r\"\", \"nxghryy\", subcount[44])\n        regexs[45].sub(r\"\", \"nxghryy\", subcount[45])\n        regexs[46].sub(r\"\", \"nxghryy\", subcount[46])\n        regexs[47].sub(r\"\", \"nxghryy\", subcount[47])\n        regexs[48].sub(r\"\", \"nxghryy\", subcount[48])\n        regexs[40].sub(r\"\", strings[85], subcount[40])\n        regexs[41].sub(r\"\", strings[85], subcount[41])\n        regexs[42].sub(r\"\", strings[85], subcount[42])\n        regexs[43].sub(r\"\", strings[85], subcount[43])\n        regexs[44].sub(r\"\", strings[85], subcount[44])\n        regexs[45].sub(r\"\", strings[85], subcount[45])\n        regexs[46].sub(r\"\", strings[85], subcount[46])\n        regexs[47].sub(r\"\", strings[85], subcount[47])\n        regexs[48].sub(r\"\", strings[85], subcount[48])\n        regexs[29].sub(r\"\", \"pngrtbel\", subcount[29])\n        regexs[30].sub(r\"\", \"pngrtbel\", subcount[30])\n        regexs[39].sub(r\"\", \"pybfr\", subcount[39])\n        regexs[39].sub(r\"\", \"qvi\", subcount[39])\n        regexs[68].sub(r\"\", strings[86], subcount[68])\n        regexs[18].sub(r\"\", strings[86], subcount[18])\n        regexs[39].sub(r\"\", \"qg\", subcount[39])\n        regexs[68].sub(r\"\", \"qg\", subcount[68])\n        regexs[18].sub(r\"\", \"qg\", subcount[18])\n        regexs[39].sub(r\"\", \"rzorq\", subcount[39])\n        regexs[68].sub(r\"\", \"rzorq\", subcount[68])\n        regexs[18].sub(r\"\", \"rzorq\", subcount[18])\n        regexs[39].sub(r\"\", \"svryqOga\", subcount[39])\n        regexs[39].sub(r\"\", \"svryqOgaPnapry\", subcount[39])\n        regexs[20].split(r\"svz_zlfcnpr_nccf-pnainf,svz_zlfcnpr_havgrq-fgngrf\")\n        regexs[40].sub(r\"\", \"svanamra\", subcount[40])\n        regexs[41].sub(r\"\", \"svanamra\", subcount[41])\n        regexs[42].sub(r\"\", \"svanamra\", subcount[42])\n        regexs[43].sub(r\"\", \"svanamra\", subcount[43])\n        regexs[44].sub(r\"\", \"svanamra\", subcount[44])\n        regexs[45].sub(r\"\", \"svanamra\", subcount[45])\n        regexs[46].sub(r\"\", \"svanamra\", subcount[46])\n        regexs[47].sub(r\"\", \"svanamra\", subcount[47])\n        regexs[48].sub(r\"\", \"svanamra\", subcount[48])\n        regexs[70].split(r\"sbphf\")\n        regexs[70].split(r\"sbphf.gno sbphfva.gno\")\n        regexs[70].split(r\"sbphfva\")\n        regexs[39].sub(r\"\", \"sbez\", subcount[39])\n        regexs[68].sub(r\"\", \"sbez.nwnk\", subcount[68])\n        regexs[18].sub(r\"\", \"sbez.nwnk\", subcount[18])\n        regexs[40].sub(r\"\", \"tnzrf\", subcount[40])\n        regexs[41].sub(r\"\", \"tnzrf\", subcount[41])\n        regexs[42].sub(r\"\", \"tnzrf\", subcount[42])\n        regexs[43].sub(r\"\", \"tnzrf\", subcount[43])\n        regexs[44].sub(r\"\", \"tnzrf\", subcount[44])\n        regexs[45].sub(r\"\", \"tnzrf\", subcount[45])\n        regexs[46].sub(r\"\", \"tnzrf\", subcount[46])\n        regexs[47].sub(r\"\", \"tnzrf\", subcount[47])\n        regexs[48].sub(r\"\", \"tnzrf\", subcount[48])\n        regexs[30].sub(r\"\", \"ubzrcntr\", subcount[30])\n        regexs[40].sub(r\"\", \"ubebfxbc\", subcount[40])\n        regexs[41].sub(r\"\", \"ubebfxbc\", subcount[41])\n        regexs[42].sub(r\"\", \"ubebfxbc\", subcount[42])\n        regexs[43].sub(r\"\", \"ubebfxbc\", subcount[43])\n        regexs[44].sub(r\"\", \"ubebfxbc\", subcount[44])\n        regexs[45].sub(r\"\", \"ubebfxbc\", subcount[45])\n        regexs[46].sub(r\"\", \"ubebfxbc\", subcount[46])\n        regexs[47].sub(r\"\", \"ubebfxbc\", subcount[47])\n        regexs[48].sub(r\"\", \"ubebfxbc\", subcount[48])\n        regexs[30].sub(r\"\", \"uc_cebzbobk_ugzy%2Puc_cebzbobk_vzt\", subcount[30])\n        regexs[30].sub(r\"\", \"uc_erpgnatyr\", subcount[30])\n        regexs[33].sub(r\"\", strings[87], subcount[33])\n        regexs[33].sub(r\"\", strings[88], subcount[33])\n        regexs[71].sub(\n            r\"\",\n            \"uggc://wf.hv-cbegny.qr/tzk/ubzr/wf/20080602/onfr.wf${4}${5}\",\n            subcount[71],\n        )\n        regexs[72].sub(\n            r\"\", \"uggc://wf.hv-cbegny.qr/tzk/ubzr/wf/20080602/onfr.wf${5}\", subcount[72]\n        )\n        regexs[71].sub(\n            r\"\",\n            \"uggc://wf.hv-cbegny.qr/tzk/ubzr/wf/20080602/qlaYvo.wf${4}${5}\",\n            subcount[71],\n        )\n        regexs[72].sub(\n            r\"\",\n            \"uggc://wf.hv-cbegny.qr/tzk/ubzr/wf/20080602/qlaYvo.wf${5}\",\n            subcount[72],\n        )\n        regexs[71].sub(\n            r\"\",\n            \"uggc://wf.hv-cbegny.qr/tzk/ubzr/wf/20080602/rssrpgYvo.wf${4}${5}\",\n            subcount[71],\n        )\n        regexs[72].sub(\n            r\"\",\n            \"uggc://wf.hv-cbegny.qr/tzk/ubzr/wf/20080602/rssrpgYvo.wf${5}\",\n            subcount[72],\n        )\n        regexs[73].sub(r\"\", strings[89], subcount[73])\n        regexs[69].sub(\n            r\"\",\n            \"uggc://zfacbegny.112.2b7.arg/o/ff/zfacbegnyubzr/1/U.7-cqi-2/f55023338617756?[NDO]&{1}&{2}&[NDR]\",\n            subcount[69],\n        )\n        regexs[23].sub(r\"\", strings[6], subcount[23])\n        regexs[40].sub(r\"\", \"xvab\", subcount[40])\n        regexs[41].sub(r\"\", \"xvab\", subcount[41])\n        regexs[42].sub(r\"\", \"xvab\", subcount[42])\n        regexs[43].sub(r\"\", \"xvab\", subcount[43])\n        regexs[44].sub(r\"\", \"xvab\", subcount[44])\n        regexs[45].sub(r\"\", \"xvab\", subcount[45])\n        regexs[46].sub(r\"\", \"xvab\", subcount[46])\n        regexs[47].sub(r\"\", \"xvab\", subcount[47])\n        regexs[48].sub(r\"\", \"xvab\", subcount[48])\n        regexs[70].split(r\"ybnq\")\n        regexs[18].sub(r\"\", \"zrqvnzbqgno lhv-anifrg lhv-anifrg-gbc\", subcount[18])\n        regexs[39].sub(r\"\", \"zrgn\", subcount[39])\n        regexs[68].sub(r\"\", strings[90], subcount[68])\n        regexs[18].sub(r\"\", strings[90], subcount[18])\n        regexs[70].split(r\"zbhfrzbir\")\n        regexs[70].split(r\"zbhfrzbir.gno\")\n        re.sub(r\"^.*jroxvg\\/(\\d+(\\.\\d+)?).*$\", \"\", strings[63], 1)\n        regexs[40].sub(r\"\", \"zhfvx\", subcount[40])\n        regexs[41].sub(r\"\", \"zhfvx\", subcount[41])\n        regexs[42].sub(r\"\", \"zhfvx\", subcount[42])\n        regexs[43].sub(r\"\", \"zhfvx\", subcount[43])\n        regexs[44].sub(r\"\", \"zhfvx\", subcount[44])\n        regexs[45].sub(r\"\", \"zhfvx\", subcount[45])\n        regexs[46].sub(r\"\", \"zhfvx\", subcount[46])\n        regexs[47].sub(r\"\", \"zhfvx\", subcount[47])\n        regexs[48].sub(r\"\", \"zhfvx\", subcount[48])\n        regexs[52].sub(r\"\", \"zlfcnpr_nccf_pnainf\", subcount[52])\n        regexs[40].sub(r\"\", strings[91], subcount[40])\n        regexs[41].sub(r\"\", strings[91], subcount[41])\n        regexs[42].sub(r\"\", strings[91], subcount[42])\n        regexs[43].sub(r\"\", strings[91], subcount[43])\n        regexs[44].sub(r\"\", strings[91], subcount[44])\n        regexs[45].sub(r\"\", strings[91], subcount[45])\n        regexs[46].sub(r\"\", strings[91], subcount[46])\n        regexs[47].sub(r\"\", strings[91], subcount[47])\n        regexs[48].sub(r\"\", strings[91], subcount[48])\n        regexs[39].sub(r\"\", \"anzr\", subcount[39])\n\n        # This prints something different to the V8 version\n        # The V8 version is escaping different things in the string that\n        # has the substitutions performed on it.\n        #\n        # V8 treats /\\S/ like / + escaped S + /\n        # Python treats it like / + \\ + S + /\n        re.sub(r\"\\b\\w+\\b\", \"\", strings[92], 0)\n\n        regexs[39].sub(r\"\", \"bow-nppbeqvba\", subcount[39])\n        regexs[39].sub(r\"\", \"bowrpg\", subcount[39])\n        regexs[68].sub(r\"\", \"bowrpg\", subcount[68])\n        regexs[18].sub(r\"\", \"bowrpg\", subcount[18])\n        regexs[29].sub(r\"\", \"cnenzf%2Rfglyrf\", subcount[29])\n        regexs[30].sub(r\"\", \"cnenzf%2Rfglyrf\", subcount[30])\n        regexs[30].sub(r\"\", \"cbchc\", subcount[30])\n        regexs[40].sub(r\"\", \"ebhgr\", subcount[40])\n        regexs[41].sub(r\"\", \"ebhgr\", subcount[41])\n        regexs[42].sub(r\"\", \"ebhgr\", subcount[42])\n        regexs[43].sub(r\"\", \"ebhgr\", subcount[43])\n        regexs[44].sub(r\"\", \"ebhgr\", subcount[44])\n        regexs[45].sub(r\"\", \"ebhgr\", subcount[45])\n        regexs[46].sub(r\"\", \"ebhgr\", subcount[46])\n        regexs[47].sub(r\"\", \"ebhgr\", subcount[47])\n        regexs[48].sub(r\"\", \"ebhgr\", subcount[48])\n        regexs[30].sub(r\"\", \"freivprobk_uc\", subcount[30])\n        regexs[30].sub(r\"\", \"fubccvatobk_uc\", subcount[30])\n        regexs[39].sub(r\"\", \"fubhgobk\", subcount[39])\n        regexs[40].sub(r\"\", \"fcbeg\", subcount[40])\n        regexs[41].sub(r\"\", \"fcbeg\", subcount[41])\n        regexs[42].sub(r\"\", \"fcbeg\", subcount[42])\n        regexs[43].sub(r\"\", \"fcbeg\", subcount[43])\n        regexs[44].sub(r\"\", \"fcbeg\", subcount[44])\n        regexs[45].sub(r\"\", \"fcbeg\", subcount[45])\n        regexs[46].sub(r\"\", \"fcbeg\", subcount[46])\n        regexs[47].sub(r\"\", \"fcbeg\", subcount[47])\n        regexs[48].sub(r\"\", \"fcbeg\", subcount[48])\n        regexs[40].sub(r\"\", \"gbhe\", subcount[40])\n        regexs[41].sub(r\"\", \"gbhe\", subcount[41])\n        regexs[42].sub(r\"\", \"gbhe\", subcount[42])\n        regexs[43].sub(r\"\", \"gbhe\", subcount[43])\n        regexs[44].sub(r\"\", \"gbhe\", subcount[44])\n        regexs[45].sub(r\"\", \"gbhe\", subcount[45])\n        regexs[46].sub(r\"\", \"gbhe\", subcount[46])\n        regexs[47].sub(r\"\", \"gbhe\", subcount[47])\n        regexs[48].sub(r\"\", \"gbhe\", subcount[48])\n        regexs[40].sub(r\"\", \"gi-fcbg\", subcount[40])\n        regexs[41].sub(r\"\", \"gi-fcbg\", subcount[41])\n        regexs[42].sub(r\"\", \"gi-fcbg\", subcount[42])\n        regexs[43].sub(r\"\", \"gi-fcbg\", subcount[43])\n        regexs[44].sub(r\"\", \"gi-fcbg\", subcount[44])\n        regexs[45].sub(r\"\", \"gi-fcbg\", subcount[45])\n        regexs[46].sub(r\"\", \"gi-fcbg\", subcount[46])\n        regexs[47].sub(r\"\", \"gi-fcbg\", subcount[47])\n        regexs[48].sub(r\"\", \"gi-fcbg\", subcount[48])\n        regexs[39].sub(r\"\", \"glcr\", subcount[39])\n        re.sub(r\"\\/\", \"\", \"haqrsvarq\", 0)\n        regexs[40].sub(r\"\", strings[93], subcount[40])\n        regexs[41].sub(r\"\", strings[93], subcount[41])\n        regexs[42].sub(r\"\", strings[93], subcount[42])\n        regexs[43].sub(r\"\", strings[93], subcount[43])\n        regexs[44].sub(r\"\", strings[93], subcount[44])\n        regexs[45].sub(r\"\", strings[93], subcount[45])\n        regexs[46].sub(r\"\", strings[93], subcount[46])\n        regexs[47].sub(r\"\", strings[93], subcount[47])\n        regexs[48].sub(r\"\", strings[93], subcount[48])\n        regexs[40].sub(r\"\", \"ivqrb\", subcount[40])\n        regexs[41].sub(r\"\", \"ivqrb\", subcount[41])\n        regexs[42].sub(r\"\", \"ivqrb\", subcount[42])\n        regexs[43].sub(r\"\", \"ivqrb\", subcount[43])\n        regexs[44].sub(r\"\", \"ivqrb\", subcount[44])\n        regexs[45].sub(r\"\", \"ivqrb\", subcount[45])\n        regexs[46].sub(r\"\", \"ivqrb\", subcount[46])\n        regexs[47].sub(r\"\", \"ivqrb\", subcount[47])\n        regexs[48].sub(r\"\", \"ivqrb\", subcount[48])\n        regexs[86].split(r\"ivfvgf=1\")\n        regexs[40].sub(r\"\", \"jrggre\", subcount[40])\n        regexs[41].sub(r\"\", \"jrggre\", subcount[41])\n        regexs[42].sub(r\"\", \"jrggre\", subcount[42])\n        regexs[43].sub(r\"\", \"jrggre\", subcount[43])\n        regexs[44].sub(r\"\", \"jrggre\", subcount[44])\n        regexs[45].sub(r\"\", \"jrggre\", subcount[45])\n        regexs[46].sub(r\"\", \"jrggre\", subcount[46])\n        regexs[47].sub(r\"\", \"jrggre\", subcount[47])\n        regexs[48].sub(r\"\", \"jrggre\", subcount[48])\n        re.search(r\"#[a-z0-9]+$\", \"uggc://jjj.fpuhryreim.arg/Qrsnhyg\", re.IGNORECASE)\n        regexs[66].search(r\"fryrpgrq\")\n        re.search(r\"(?:^|\\s+)lhv-ani(?:\\s+|$)\", \"sff lhv-ani\")\n        re.search(r\"(?:^|\\s+)lhv-anifrg(?:\\s+|$)\", \"zrqvnzbqgno lhv-anifrg\")\n        re.search(r\"(?:^|\\s+)lhv-anifrg-gbc(?:\\s+|$)\", \"zrqvnzbqgno lhv-anifrg\")\n        regexs[91].search(r\"GnoThvq\")\n        regexs[91].search(r\"thvq\")\n        re.search(r\"(pbzcngvoyr|jroxvg)\", strings[63])\n        re.search(r\".+(?:ei|vg|en|vr)[\\/: ]([\\d.]+)\", strings[63])\n        regexs[8].search(r\"144631658.0.10.1231365869\")\n        regexs[8].search(r\"144631658.0.10.1231367054\")\n        regexs[8].search(\n            r\"144631658.1231365869.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)\"\n        )\n        regexs[8].search(\n            r\"144631658.1231367054.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)\"\n        )\n        regexs[8].search(\n            r\"144631658.1670816052019209000.1231365869.1231365869.1231365869.1\"\n        )\n        regexs[8].search(\n            r\"144631658.1796080716621419500.1231367054.1231367054.1231367054.1\"\n        )\n        regexs[8].search(strings[94])\n        regexs[8].search(strings[95])\n        regexs[8].search(strings[96])\n        regexs[8].search(strings[97])\n        regexs[8].search(\n            r\"__hgzn=144631658.1670816052019209000.1231365869.1231365869.1231365869.1\"\n        )\n        regexs[8].search(\n            r\"__hgzn=144631658.1796080716621419500.1231367054.1231367054.1231367054.1\"\n        )\n        regexs[8].search(r\"__hgzo=144631658.0.10.1231365869\")\n        regexs[8].search(r\"__hgzo=144631658.0.10.1231367054\")\n        regexs[8].search(\n            r\"__hgzm=144631658.1231365869.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)\"\n        )\n        regexs[8].search(\n            r\"__hgzm=144631658.1231367054.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)\"\n        )\n        regexs[34].search(strings[78])\n        regexs[34].search(strings[79])\n        regexs[34].search(strings[81])\n        regexs[74].search(strings[77])\n        regexs[74].search(r\"*\")\n        regexs[74].search(strings[82])\n        regexs[74].search(strings[83])\n        regexs[74].search(strings[86])\n        regexs[74].search(r\"rzorq\")\n        regexs[74].search(r\"sbez.nwnk\")\n        regexs[74].search(strings[90])\n        regexs[74].search(r\"bowrpg\")\n        re.search(\n            r\"\\/onfr.wf(\\?.+)?$\", \"/uggc://wf.hv-cbegny.qr/tzk/ubzr/wf/20080602/onfr.wf\"\n        )\n        regexs[28].search(r\"uvag ynfgUvag ynfg\")\n        regexs[75].search(r\"\")\n        regexs[76].search(r\"\")\n        regexs[77].search(r\"\")\n        regexs[78].search(r\"\")\n        regexs[80].search(strings[77])\n        regexs[80].search(r\"*\")\n        regexs[80].search(r\".pybfr\")\n        regexs[80].search(strings[82])\n        regexs[80].search(strings[83])\n        regexs[80].search(strings[84])\n        regexs[80].search(strings[86])\n        regexs[80].search(r\"qg\")\n        regexs[80].search(r\"rzorq\")\n        regexs[80].search(r\"sbez.nwnk\")\n        regexs[80].search(strings[90])\n        regexs[80].search(r\"bowrpg\")\n        regexs[61].search(r\"qlaYvo.wf\")\n        regexs[61].search(r\"rssrpgYvo.wf\")\n        regexs[61].search(r\"uggc://jjj.tzk.arg/qr/?fgnghf=uvajrvf\")\n        regexs[92].search(r\" .pybfr\")\n        regexs[92].search(r\" n.svryqOgaPnapry\")\n        regexs[92].search(r\" qg\")\n        regexs[92].search(strings[48])\n        regexs[92].search(r\".nwnk\")\n        regexs[92].search(r\".svryqOga,n.svryqOgaPnapry\")\n        regexs[92].search(r\".svryqOgaPnapry\")\n        regexs[92].search(r\".bow-nppbeqvba qg\")\n        regexs[68].search(strings[77])\n        regexs[68].search(r\"*\")\n        regexs[68].search(r\".pybfr\")\n        regexs[68].search(strings[82])\n        regexs[68].search(strings[83])\n        regexs[68].search(strings[84])\n        regexs[68].search(strings[86])\n        regexs[68].search(r\"qg\")\n        regexs[68].search(r\"rzorq\")\n        regexs[68].search(r\"sbez.nwnk\")\n        regexs[68].search(strings[90])\n        regexs[68].search(r\"bowrpg\")\n        regexs[93].search(r\" .pybfr\")\n        regexs[93].search(r\" n.svryqOgaPnapry\")\n        regexs[93].search(r\" qg\")\n        regexs[93].search(strings[48])\n        regexs[93].search(r\".nwnk\")\n        regexs[93].search(r\".svryqOga,n.svryqOgaPnapry\")\n        regexs[93].search(r\".svryqOgaPnapry\")\n        regexs[93].search(r\".bow-nppbeqvba qg\")\n        regexs[81].search(strings[77])\n        regexs[81].search(r\"*\")\n        regexs[81].search(strings[48])\n        regexs[81].search(r\".pybfr\")\n        regexs[81].search(strings[82])\n        regexs[81].search(strings[83])\n        regexs[81].search(strings[84])\n        regexs[81].search(strings[86])\n        regexs[81].search(r\"qg\")\n        regexs[81].search(r\"rzorq\")\n        regexs[81].search(r\"sbez.nwnk\")\n        regexs[81].search(strings[90])\n        regexs[81].search(r\"bowrpg\")\n        regexs[94].search(r\" .pybfr\")\n        regexs[94].search(r\" n.svryqOgaPnapry\")\n        regexs[94].search(r\" qg\")\n        regexs[94].search(strings[48])\n        regexs[94].search(r\".nwnk\")\n        regexs[94].search(r\".svryqOga,n.svryqOgaPnapry\")\n        regexs[94].search(r\".svryqOgaPnapry\")\n        regexs[94].search(r\".bow-nppbeqvba qg\")\n        regexs[94].search(r\"[anzr=nwnkHey]\")\n        regexs[94].search(strings[82])\n        regexs[31].search(r\"rf\")\n        regexs[31].search(r\"wn\")\n        regexs[82].search(strings[77])\n        regexs[82].search(r\"*\")\n        regexs[82].search(strings[48])\n        regexs[82].search(r\".pybfr\")\n        regexs[82].search(strings[82])\n        regexs[82].search(strings[83])\n        regexs[82].search(strings[84])\n        regexs[82].search(strings[86])\n        regexs[82].search(r\"qg\")\n        regexs[82].search(r\"rzorq\")\n        regexs[82].search(r\"sbez.nwnk\")\n        regexs[82].search(strings[90])\n        regexs[82].search(r\"bowrpg\")\n        regexs[83].search(strings[98])\n        regexs[83].search(r\"shapgvba sbphf() { [angvir pbqr] }\")\n        regexs[62].search(r\"#Ybtva\")\n        regexs[62].search(r\"#Ybtva_cnffjbeq\")\n        regexs[62].search(strings[77])\n        regexs[62].search(r\"#fubhgobkWf\")\n        regexs[62].search(r\"#fubhgobkWfReebe\")\n        regexs[62].search(r\"#fubhgobkWfFhpprff\")\n        regexs[62].search(r\"*\")\n        regexs[62].search(strings[82])\n        regexs[62].search(strings[83])\n        regexs[62].search(strings[86])\n        regexs[62].search(r\"rzorq\")\n        regexs[62].search(r\"sbez.nwnk\")\n        regexs[62].search(strings[90])\n        regexs[62].search(r\"bowrpg\")\n        regexs[49].search(r\"pbagrag\")\n        regexs[24].search(strings[6])\n        re.search(r\"xbadhrebe\", strings[63])\n        re.search(r\"znp\", \"jva32\")\n        re.search(r\"zbmvyyn\", strings[63])\n        re.search(r\"zfvr\", strings[63])\n        re.search(r\"ag\\s5\\.1\", strings[63])\n        re.search(r\"bcren\", strings[63])\n        re.search(r\"fnsnev\", strings[63])\n        re.search(r\"jva\", \"jva32\")\n        re.search(r\"jvaqbjf\", strings[63])\n\n\ndef bench_regex_v8(loops):\n    with get_tracker():\n        t0 = pyperf.perf_counter()\n        for loops in range(loops):\n            block0()\n            block1()\n            block2()\n            block3()\n            block4()\n            block5()\n            block6()\n            block7()\n            block8()\n            block9()\n            block10()\n            block11()\n        return pyperf.perf_counter() - t0\n\n\nif __name__ == \"__main__\":\n    runner = pyperf.Runner()\n    runner.metadata[\"description\"] = (\n        \"Test the performance of regexps \" \"using V8's benchmarks\"\n    )\n    runner.bench_time_func(\"regex_v8\", bench_regex_v8)\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/spectral_norm_base.py",
    "content": "\"\"\"\nMathWorld: \"Hundred-Dollar, Hundred-Digit Challenge Problems\", Challenge #3.\nhttp://mathworld.wolfram.com/Hundred-DollarHundred-DigitChallengeProblems.html\n\nThe Computer Language Benchmarks Game\nhttp://benchmarksgame.alioth.debian.org/u64q/spectralnorm-description.html#spectralnorm\n\nContributed by Sebastien Loisel\nFixed by Isaac Gouy\nSped up by Josh Goldfoot\nDirtily sped up by Simon Descarpentries\nConcurrency by Jason Stitt\n\"\"\"\n\n\nDEFAULT_N = 130\n\n\ndef eval_A(i, j):\n    return 1.0 / ((i + j) * (i + j + 1) // 2 + i + 1)\n\n\ndef eval_times_u(func, u):\n    return [func((i, u)) for i in range(len(list(u)))]\n\n\ndef eval_AtA_times_u(u):\n    return eval_times_u(part_At_times_u, eval_times_u(part_A_times_u, u))\n\n\ndef part_A_times_u(i_u):\n    i, u = i_u\n    partial_sum = 0\n    for j, u_j in enumerate(u):\n        partial_sum += eval_A(i, j) * u_j\n    return partial_sum\n\n\ndef part_At_times_u(i_u):\n    i, u = i_u\n    partial_sum = 0\n    for j, u_j in enumerate(u):\n        partial_sum += eval_A(j, i) * u_j\n    return partial_sum\n\n\ndef bench_spectral_norm(loops):\n    range_it = range(loops)\n    for _ in range_it:\n        u = [1] * DEFAULT_N\n\n        for dummy in range(10):\n            v = eval_AtA_times_u(u)\n            u = eval_AtA_times_u(v)\n\n        vBv = vv = 0\n\n        for ue, ve in zip(u, v):\n            vBv += ue * ve\n            vv += ve * ve\n\n\ndef run_benchmark():\n    bench_spectral_norm(1)\n\n\nif __name__ == \"__main__\":\n    run_benchmark()\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/spectral_norm_memray.py",
    "content": "\"\"\"\nMathWorld: \"Hundred-Dollar, Hundred-Digit Challenge Problems\", Challenge #3.\nhttp://mathworld.wolfram.com/Hundred-DollarHundred-DigitChallengeProblems.html\n\nThe Computer Language Benchmarks Game\nhttp://benchmarksgame.alioth.debian.org/u64q/spectralnorm-description.html#spectralnorm\n\nContributed by Sebastien Loisel\nFixed by Isaac Gouy\nSped up by Josh Goldfoot\nDirtily sped up by Simon Descarpentries\nConcurrency by Jason Stitt\n\"\"\"\n\nimport pyperf\nfrom memray_helper import get_tracker\n\n\nDEFAULT_N = 130\n\n\ndef eval_A(i, j):\n    return 1.0 / ((i + j) * (i + j + 1) // 2 + i + 1)\n\n\ndef eval_times_u(func, u):\n    return [func((i, u)) for i in range(len(list(u)))]\n\n\ndef eval_AtA_times_u(u):\n    return eval_times_u(part_At_times_u, eval_times_u(part_A_times_u, u))\n\n\ndef part_A_times_u(i_u):\n    i, u = i_u\n    partial_sum = 0\n    for j, u_j in enumerate(u):\n        partial_sum += eval_A(i, j) * u_j\n    return partial_sum\n\n\ndef part_At_times_u(i_u):\n    i, u = i_u\n    partial_sum = 0\n    for j, u_j in enumerate(u):\n        partial_sum += eval_A(j, i) * u_j\n    return partial_sum\n\n\ndef bench_spectral_norm(loops):\n    range_it = range(loops)\n\n    with get_tracker():\n        t0 = pyperf.perf_counter()\n        for _ in range_it:\n            u = [1] * DEFAULT_N\n\n            for dummy in range(10):\n                v = eval_AtA_times_u(u)\n                u = eval_AtA_times_u(v)\n\n            vBv = vv = 0\n\n            for ue, ve in zip(u, v):\n                vBv += ue * ve\n                vv += ve * ve\n\n        return pyperf.perf_counter() - t0\n\n\nif __name__ == \"__main__\":\n    runner = pyperf.Runner()\n    runner.metadata[\"description\"] = (\n        'MathWorld: \"Hundred-Dollar, Hundred-Digit Challenge Problems\", '\n        \"Challenge #3.\"\n    )\n    runner.bench_time_func(\"spectral_norm\", bench_spectral_norm)\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/sqlite_synth_base.py",
    "content": "\"\"\"\nSQLite benchmark.\n\nThe goal of the benchmark is to test CFFI performance and going back and forth\nbetween SQLite and Python a lot. Therefore the queries themselves are really\nsimple.\n\"\"\"\n\nimport sqlite3\nimport math\n\n\nclass AvgLength(object):\n    def __init__(self):\n        self.sum = 0\n        self.count = 0\n\n    def step(self, x):\n        if x is not None:\n            self.count += 1\n            self.sum += len(x)\n\n    def finalize(self):\n        return self.sum / float(self.count)\n\n\ndef bench_sqlite(loops):\n    conn = sqlite3.connect(\":memory:\")\n    conn.execute(\"create table cos (x, y, z);\")\n    for i in range(loops):\n        cos_i = math.cos(i)\n        conn.execute(\"insert into cos values (?, ?, ?)\", [i, cos_i, str(i)])\n\n    conn.create_function(\"cos\", 1, math.cos)\n    for x, cosx1, cosx2 in conn.execute(\"select x, cos(x), y from cos\"):\n        assert math.cos(x) == cosx1 == cosx2\n\n    conn.create_aggregate(\"avglength\", 1, AvgLength)\n    cursor = conn.execute(\"select avglength(z) from cos;\")\n    cursor.fetchone()[0]\n\n    conn.execute(\"delete from cos;\")\n    conn.close()\n\n\ndef run_benchmark():\n    bench_sqlite(1)\n\n\nif __name__ == \"__main__\":\n    run_benchmark()\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/sqlite_synth_memray.py",
    "content": "\"\"\"\nSQLite benchmark.\n\nThe goal of the benchmark is to test CFFI performance and going back and forth\nbetween SQLite and Python a lot. Therefore the queries themselves are really\nsimple.\n\"\"\"\n\nimport sqlite3\nimport math\n\nimport pyperf\nfrom memray_helper import get_tracker\n\n\nclass AvgLength(object):\n    def __init__(self):\n        self.sum = 0\n        self.count = 0\n\n    def step(self, x):\n        if x is not None:\n            self.count += 1\n            self.sum += len(x)\n\n    def finalize(self):\n        return self.sum / float(self.count)\n\n\ndef bench_sqlite(loops):\n\n    with get_tracker():\n        t0 = pyperf.perf_counter()\n        conn = sqlite3.connect(\":memory:\")\n        conn.execute(\"create table cos (x, y, z);\")\n        for i in range(loops):\n            cos_i = math.cos(i)\n            conn.execute(\"insert into cos values (?, ?, ?)\", [i, cos_i, str(i)])\n\n        conn.create_function(\"cos\", 1, math.cos)\n        for x, cosx1, cosx2 in conn.execute(\"select x, cos(x), y from cos\"):\n            assert math.cos(x) == cosx1 == cosx2\n\n        conn.create_aggregate(\"avglength\", 1, AvgLength)\n        cursor = conn.execute(\"select avglength(z) from cos;\")\n        cursor.fetchone()[0]\n\n        conn.execute(\"delete from cos;\")\n        conn.close()\n\n        return pyperf.perf_counter() - t0\n\n\nif __name__ == \"__main__\":\n    runner = pyperf.Runner()\n    runner.metadata[\"description\"] = \"Benchmark Python aggregate for SQLite\"\n    runner.bench_time_func(\"sqlite_synth\", bench_sqlite)\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/telco_base.py",
    "content": "# coding: UTF-8\n\"\"\" Telco Benchmark for measuring the performance of decimal calculations\n\n- http://speleotrove.com/decimal/telco.html\n- http://speleotrove.com/decimal/telcoSpec.html\n\nA call type indicator, c, is set from the bottom (least significant) bit of the duration (hence c is 0 or 1).\nA rate, r, is determined from the call type. Those calls with c=0 have a low r: 0.0013; the remainder (‘distance calls’) have a ‘premium’ r: 0.00894. (The rates are, very roughly, in Euros or dollarates per second.)\nA price, p, for the call is then calculated (p=r*n). This is rounded to exactly 2 fractional digits using round-half-even (Banker’s round to nearest).\nA basic tax, b, is calculated: b=p*0.0675 (6.75%). This is truncated to exactly 2 fractional digits (round-down), and the total basic tax variable is then incremented (sumB=sumB+b).\nFor distance calls: a distance tax, d, is calculated: d=p*0.0341 (3.41%). This is truncated to exactly 2 fractional digits (round-down), and then the total distance tax variable is incremented (sumD=sumD+d).\nThe total price, t, is calculated (t=p+b, and, if a distance call, t=t+d).\nThe total prices variable is incremented (sumT=sumT+t).\nThe total price, t, is converted to a string, s.\n\n\"\"\"\n\nfrom decimal import ROUND_HALF_EVEN, ROUND_DOWN, Decimal, getcontext, Context\nimport io\nimport os\nfrom struct import unpack\n\nfrom pathlib import Path\n\n\ndef rel_path(*path):\n    return os.path.join(os.path.dirname(__file__), *path)\n\n\nDOC_ROOT = (Path(__file__).parent / \"telco_data\" / \"telco-bench.b\").resolve()\n\n\ndef bench_telco(loops, filename):\n    getcontext().rounding = ROUND_DOWN\n    rates = list(map(Decimal, (\"0.0013\", \"0.00894\")))\n    twodig = Decimal(\"0.01\")\n    Banker = Context(rounding=ROUND_HALF_EVEN)\n    basictax = Decimal(\"0.0675\")\n    disttax = Decimal(\"0.0341\")\n\n    with open(filename, \"rb\") as infil:\n        data = infil.read()\n\n    infil = io.BytesIO(data)\n    outfil = io.StringIO()\n\n    for _ in range(loops):\n        infil.seek(0)\n\n        sumT = Decimal(\"0\")  # sum of total prices\n        sumB = Decimal(\"0\")  # sum of basic tax\n        sumD = Decimal(\"0\")  # sum of 'distance' tax\n\n        for i in range(5000):\n            datum = infil.read(8)\n            if datum == \"\":\n                break\n            (n,) = unpack(\">Q\", datum)\n\n            calltype = n & 1\n            r = rates[calltype]\n\n            p = Banker.quantize(r * n, twodig)\n\n            b = p * basictax\n            b = b.quantize(twodig)\n            sumB += b\n\n            t = p + b\n\n            if calltype:\n                d = p * disttax\n                d = d.quantize(twodig)\n                sumD += d\n                t += d\n\n            sumT += t\n            print(t, file=outfil)\n\n        outfil.seek(0)\n        outfil.truncate()\n\n\ndef run_benchmark():\n    bench_telco(1, DOC_ROOT)\n\n\nif __name__ == \"__main__\":\n    run_benchmark()\n"
  },
  {
    "path": "benchmarks/benchmarking/cases/telco_memray.py",
    "content": "# coding: UTF-8\n\"\"\" Telco Benchmark for measuring the performance of decimal calculations\n\n- http://speleotrove.com/decimal/telco.html\n- http://speleotrove.com/decimal/telcoSpec.html\n\nA call type indicator, c, is set from the bottom (least significant) bit of the duration (hence c is 0 or 1).\nA rate, r, is determined from the call type. Those calls with c=0 have a low r: 0.0013; the remainder (‘distance calls’) have a ‘premium’ r: 0.00894. (The rates are, very roughly, in Euros or dollarates per second.)\nA price, p, for the call is then calculated (p=r*n). This is rounded to exactly 2 fractional digits using round-half-even (Banker’s round to nearest).\nA basic tax, b, is calculated: b=p*0.0675 (6.75%). This is truncated to exactly 2 fractional digits (round-down), and the total basic tax variable is then incremented (sumB=sumB+b).\nFor distance calls: a distance tax, d, is calculated: d=p*0.0341 (3.41%). This is truncated to exactly 2 fractional digits (round-down), and then the total distance tax variable is incremented (sumD=sumD+d).\nThe total price, t, is calculated (t=p+b, and, if a distance call, t=t+d).\nThe total prices variable is incremented (sumT=sumT+t).\nThe total price, t, is converted to a string, s.\n\n\"\"\"\n\nfrom decimal import ROUND_HALF_EVEN, ROUND_DOWN, Decimal, getcontext, Context\nimport io\nimport os\nfrom struct import unpack\n\nimport pyperf\nfrom memray_helper import get_tracker\nfrom pathlib import Path\n\n\ndef rel_path(*path):\n    return os.path.join(os.path.dirname(__file__), *path)\n\n\nDOC_ROOT = (Path(__file__).parent / \"telco_data\" / \"telco-bench.b\").resolve()\n\n\ndef bench_telco(loops, filename):\n    getcontext().rounding = ROUND_DOWN\n    rates = list(map(Decimal, (\"0.0013\", \"0.00894\")))\n    twodig = Decimal(\"0.01\")\n    Banker = Context(rounding=ROUND_HALF_EVEN)\n    basictax = Decimal(\"0.0675\")\n    disttax = Decimal(\"0.0341\")\n\n    with open(filename, \"rb\") as infil:\n        data = infil.read()\n\n    infil = io.BytesIO(data)\n    outfil = io.StringIO()\n\n    with get_tracker():\n        start = pyperf.perf_counter()\n        for _ in range(loops):\n            infil.seek(0)\n\n            sumT = Decimal(\"0\")  # sum of total prices\n            sumB = Decimal(\"0\")  # sum of basic tax\n            sumD = Decimal(\"0\")  # sum of 'distance' tax\n\n            for i in range(5000):\n                datum = infil.read(8)\n                if datum == \"\":\n                    break\n                (n,) = unpack(\">Q\", datum)\n\n                calltype = n & 1\n                r = rates[calltype]\n\n                p = Banker.quantize(r * n, twodig)\n\n                b = p * basictax\n                b = b.quantize(twodig)\n                sumB += b\n\n                t = p + b\n\n                if calltype:\n                    d = p * disttax\n                    d = d.quantize(twodig)\n                    sumD += d\n                    t += d\n\n                sumT += t\n                print(t, file=outfil)\n\n            outfil.seek(0)\n            outfil.truncate()\n\n        return pyperf.perf_counter() - start\n\n\ndef add_cmdline_args(cmd, args):\n    cmd.append(\"--doc_root=%s\" % args.doc_root)\n\n\nif __name__ == \"__main__\":\n    runner = pyperf.Runner(add_cmdline_args=add_cmdline_args)\n    runner.metadata[\"description\"] = \"Telco decimal benchmark\"\n    runner.argparser.add_argument(\"--doc_root\", default=DOC_ROOT)\n    args = runner.parse_args()\n    runner.bench_time_func(\"telco\", bench_telco, args.doc_root)\n"
  },
  {
    "path": "benchmarks/benchmarking/plot.py",
    "content": "from pathlib import Path\nfrom typing import Any\nfrom typing import Dict\n\nimport matplotlib\nimport matplotlib.patches as mpatches\nimport numpy as np\nfrom matplotlib import pyplot as plt\n\nmatplotlib.use(\"agg\")\n\n\ndef get_data(result) -> Dict[str, Any]:\n    results = {}\n\n    for case in result:\n        for benchmark in case[\"benchmarks\"]:\n            if \"metadata\" in benchmark:\n                name = benchmark[\"metadata\"][\"name\"]\n            else:\n                name = case[\"metadata\"][\"name\"]\n            data = []\n            for run in benchmark[\"runs\"]:\n                data.extend(run.get(\"values\", []))\n            results[name] = np.array(data, dtype=np.float64)\n\n    return results\n\n\ndef remove_outliers(values, m=2):\n    return values[abs(values - np.mean(values)) < m * np.std(values)]\n\n\ndef plot_diff_pair(ax, ref, head, names, outlier_rejection=True):\n    master_data = []\n    all_data = []\n    means = []\n    for name in names:\n        ref_values = ref[name]\n        head_values = head[name]\n        if outlier_rejection:\n            ref_values = remove_outliers(ref_values)\n            head_values = remove_outliers(head_values)\n        means.append(np.mean(head_values))\n        values = np.outer(ref_values, 1.0 / head_values).flatten()\n        values.sort()\n        idx = np.round(np.linspace(0, len(values) - 1, 100)).astype(int)\n        all_data.append(values[idx])\n        master_data.extend(values)\n\n    all_data.append(master_data)\n    violin = ax.violinplot(\n        all_data,\n        vert=False,\n        showmeans=True,\n        showmedians=False,\n        showextrema=False,\n        widths=1.0,\n        quantiles=[[0.1, 0.9]] * len(all_data),\n    )\n    violin[\"cquantiles\"].set_linestyle(\":\")\n    for pc, mean in zip(violin[\"bodies\"], means):\n        if mean < 0.1:\n            pc.set_facecolor(\"#ff0000\")\n        else:\n            pc.set_facecolor(\"#0000ff\")\n\n\ndef formatter(val, pos):\n    return f\"{val:.02f}x\"\n\n\ndef plot_diff(ref, head, output_filename: Path, title: str) -> None:\n    head_data = get_data(head.data)\n    ref_data = get_data(ref.data)\n\n    names = sorted(head_data.keys(), reverse=True)\n    fig, axs = plt.subplots(figsize=(8, 2 + len(names) * 0.3), layout=\"constrained\")\n    plt.axvline(1.0)\n    plot_diff_pair(axs, ref_data, head_data, names)\n    names.append(\"ALL\")\n    axs.set_yticks(np.arange(len(names)) + 1, names)\n    axs.set_ylim(0, len(names) + 1)\n    axs.tick_params(axis=\"x\", bottom=True, top=True, labelbottom=True, labeltop=True)\n    axs.xaxis.set_major_formatter(formatter)\n    axs.grid()\n    axs.set_title(title)\n\n    # Add legend for colors (red -> microbenchmark, blue -> macrobenchmark)\n\n    axs.legend(\n        handles=[\n            mpatches.Patch(color=\"#ff0000\", label=\"Microbenchmark\"),\n            mpatches.Patch(color=\"#0000ff\", label=\"Macrobenchmark\"),\n        ],\n        bbox_to_anchor=(0, 1.05),\n    )\n\n    plt.savefig(output_filename)\n    plt.close()\n"
  },
  {
    "path": "benchmarks/benchmarks.py",
    "content": "import mmap\nimport os\nimport tempfile\n\nfrom memray import AllocatorType\nfrom memray import FileReader\n\ntry:\n    from memray._test import MemoryAllocator\nexcept ImportError:\n    from memray import MemoryAllocator\n\nfrom memray import Tracker\n\nfrom .benchmarking.cases import async_tree_base\nfrom .benchmarking.cases import fannkuch_base\nfrom .benchmarking.cases import mdp_base\nfrom .benchmarking.cases import pprint_format_base\nfrom .benchmarking.cases import raytrace_base\n\nLOOPS = 1000\n\n\nclass TracebackBenchmarks:\n    def setup(self):\n        self.tempfile = tempfile.NamedTemporaryFile()\n        allocator = MemoryAllocator()\n\n        def fac(n):\n            if n == 1:\n                allocator.valloc(1234)\n                allocator.free()\n                return 1\n            return n * fac(n - 1)\n\n        os.unlink(self.tempfile.name)\n        with Tracker(self.tempfile.name):\n            fac(300)\n\n        (self.record,) = [\n            record\n            for record in FileReader(self.tempfile.name).get_allocation_records()\n            if record.allocator == AllocatorType.VALLOC\n        ]\n\n    def time_get_stack_trace(self):\n        self.record.stack_trace()\n\n\nclass AllocatorBenchmarks:\n    def setup(self):\n        self.tempfile = tempfile.NamedTemporaryFile()\n        self.allocator = MemoryAllocator()\n\n    def time_malloc(self):\n        os.unlink(self.tempfile.name)\n        with Tracker(self.tempfile.name):\n            for _ in range(LOOPS):\n                if self.allocator.malloc(1234):\n                    self.allocator.free()\n\n    def time_posix_memalign(self):\n        os.unlink(self.tempfile.name)\n        with Tracker(self.tempfile.name):\n            for _ in range(LOOPS):\n                if self.allocator.posix_memalign(1234):\n                    self.allocator.free()\n\n    def time_posix_realloc(self):\n        os.unlink(self.tempfile.name)\n        with Tracker(self.tempfile.name):\n            for _ in range(LOOPS):\n                if self.allocator.posix_memalign(1234):\n                    self.allocator.free()\n\n    def time_calloc(self):\n        os.unlink(self.tempfile.name)\n        with Tracker(self.tempfile.name):\n            for _ in range(LOOPS):\n                if self.allocator.calloc(1234):\n                    self.allocator.free()\n\n    def time_pvalloc(self):\n        os.unlink(self.tempfile.name)\n        with Tracker(self.tempfile.name):\n            for _ in range(LOOPS):\n                if self.allocator.pvalloc(1234):\n                    self.allocator.free()\n\n    def time_valloc(self):\n        os.unlink(self.tempfile.name)\n        with Tracker(self.tempfile.name):\n            for _ in range(LOOPS):\n                if self.allocator.valloc(1234):\n                    self.allocator.free()\n\n    def time_realloc(self):\n        os.unlink(self.tempfile.name)\n        with Tracker(self.tempfile.name):\n            for _ in range(LOOPS):\n                if self.allocator.realloc(1234):\n                    self.allocator.free()\n\n    def time_mmap(self):\n        os.unlink(self.tempfile.name)\n        with Tracker(self.tempfile.name):\n            for _ in range(LOOPS):\n                with mmap.mmap(-1, length=2048, access=mmap.ACCESS_WRITE) as mmap_obj:\n                    mmap_obj[0:100] = b\"a\" * 100\n\n\nclass ParserBenchmarks:\n    def setup(self):\n        self.tempfile = tempfile.NamedTemporaryFile()\n        self.allocator = MemoryAllocator()\n        os.unlink(self.tempfile.name)\n        self.tracker = Tracker(self.tempfile.name)\n        with self.tracker:\n            for _ in range(LOOPS):\n                self.allocator.valloc(1234)\n                self.allocator.free()\n\n    def time_end_to_end_parsing(self):\n        list(FileReader(self.tempfile.name).get_allocation_records())\n\n\ndef recursive(n, chunk_size):\n    \"\"\"Mimics generally-increasing but spiky usage\"\"\"\n    if not n:\n        return\n\n    allocator = MemoryAllocator()\n    allocator.valloc(n * chunk_size)\n\n    # Don't keep allocated memory when recursing, ~50% of the calls.\n    if n % 2:\n        allocator.free()\n        recursive(n - 1, chunk_size)\n    else:\n        recursive(n - 1, chunk_size)\n        allocator.free()\n\n\nclass HighWatermarkBenchmarks:\n    def setup(self):\n        self.tempfile = tempfile.NamedTemporaryFile()\n        os.unlink(self.tempfile.name)\n        self.tracker = Tracker(self.tempfile.name)\n\n        with self.tracker:\n            recursive(700, 99)\n\n    def time_high_watermark(self):\n        list(\n            FileReader(self.tempfile.name).get_high_watermark_allocation_records(\n                merge_threads=False\n            )\n        )\n\n\nclass MacroBenchmarksBase:\n    def __init_subclass__(cls) -> None:\n        for name in dir(cls):\n            if name.startswith(\"bench_\"):\n                bench_name = name[len(\"bench_\") :]\n                setattr(cls, f\"time_{bench_name}\", getattr(cls, name))\n\n    def bench_async_tree_cpu(self):\n        with self.tracker:\n            async_tree_base.run_benchmark(\"none\")\n\n    def bench_async_tree_io(self):\n        with self.tracker:\n            async_tree_base.run_benchmark(\"io\")\n\n    def bench_async_tree_memoization(self):\n        with self.tracker:\n            async_tree_base.run_benchmark(\"memoization\")\n\n    def bench_async_tree_cpu_io_mixed(self):\n        with self.tracker:\n            async_tree_base.run_benchmark(\"cpu_io_mixed\")\n\n    def bench_fannkuch(self):\n        with self.tracker:\n            fannkuch_base.run_benchmark()\n\n    def bench_mdp(self):\n        with self.tracker:\n            mdp_base.run_benchmark()\n\n    def bench_pprint_format(self):\n        with self.tracker:\n            pprint_format_base.run_benchmark()\n\n    def bench_raytrace(self):\n        with self.tracker:\n            raytrace_base.run_benchmark()\n\n\nclass MacroBenchmarksDefault(MacroBenchmarksBase):\n    def setup(self):\n        self.tracker_args = (\"/dev/null\",)\n        self.tracker_kwargs = {}\n        self.tracker = Tracker(*self.tracker_args, **self.tracker_kwargs)\n\n\nclass MacroBenchmarksPythonAllocators(MacroBenchmarksBase):\n    def setup(self):\n        self.tracker_args = (\"/dev/null\",)\n        self.tracker_kwargs = {\"trace_python_allocators\": True}\n        self.tracker = Tracker(*self.tracker_args, **self.tracker_kwargs)\n\n\nclass MacroBenchmarksPythonNative(MacroBenchmarksBase):\n    def setup(self):\n        self.tracker_args = (\"/dev/null\",)\n        self.tracker_kwargs = {\"native_traces\": True}\n        self.tracker = Tracker(*self.tracker_args, **self.tracker_kwargs)\n\n\nclass MacroBenchmarksPythonAll(MacroBenchmarksBase):\n    def setup(self):\n        self.tracker_args = (\"/dev/null\",)\n        self.tracker_kwargs = {\"native_traces\": True, \"trace_python_allocators\": True}\n        self.tracker = Tracker(*self.tracker_args, **self.tracker_kwargs)\n\n\nclass FileSizeBenchmarks:\n    def setup(self):\n        self.tempfile = tempfile.NamedTemporaryFile()\n        os.unlink(self.tempfile.name)\n        self.tracker = Tracker(self.tempfile.name)\n\n    def track_async_tree_cpu(self):\n        with self.tracker:\n            async_tree_base.run_benchmark(\"none\")\n        return os.stat(self.tempfile.name).st_size\n\n    def track_async_tree_io(self):\n        with self.tracker:\n            async_tree_base.run_benchmark(\"io\")\n        return os.stat(self.tempfile.name).st_size\n\n    def track_async_tree_memoization(self):\n        with self.tracker:\n            async_tree_base.run_benchmark(\"memoization\")\n        return os.stat(self.tempfile.name).st_size\n\n    def track_async_tree_cpu_io_mixed(self):\n        with self.tracker:\n            async_tree_base.run_benchmark(\"cpu_io_mixed\")\n        return os.stat(self.tempfile.name).st_size\n\n    def track_fannkuch(self):\n        with self.tracker:\n            fannkuch_base.run_benchmark()\n        return os.stat(self.tempfile.name).st_size\n\n    def track_mdp(self):\n        with self.tracker:\n            mdp_base.run_benchmark()\n        return os.stat(self.tempfile.name).st_size\n\n    def track_pprint_format(self):\n        with self.tracker:\n            pprint_format_base.run_benchmark()\n        return os.stat(self.tempfile.name).st_size\n\n    def track_raytrace(self):\n        with self.tracker:\n            raytrace_base.run_benchmark()\n        return os.stat(self.tempfile.name).st_size\n"
  },
  {
    "path": "benchmarks/requirements.txt",
    "content": "pyperf\nmatplotlib\nseaborn\nnumpy\n"
  },
  {
    "path": "docs/_static/css/custom.css",
    "content": "/* GLOBAL STYLES\n-------------------------------------------------- */\n/* Padding below the footer and lighter body text */\n\nbody {\n  padding-top: 3rem;\n  padding-bottom: 3rem;\n  color: #5a5a5a;\n}\n\na {\n  color: #fe2f4e;\n}\n\na:hover {\n  color: #fe6615;\n}\n\n/* NAVAR\n * ----------------------------------------*/\n\n.navbar {\n  background-color: rgb(245, 245, 245);\n}\n\n.navbar li {\n  transition: 0.3s background-color;\n  text-align: center;\n  background-color: transparent;\n  padding: 0rem 1rem;\n  text-decoration: none;\n  border-radius: 0.3rem;\n}\n\n.navbar li:hover {\n  background-color: #fe2f4e;\n}\n\n.navbar li .nav-link {\n  color: #fe2f4e;\n}\n\n.navbar li:hover .nav-link {\n  color: #31373e;\n}\n\n.dropdown-menu {\n  background-color: rgb(250, 250, 250);\n  /*#000000d0;*/\n}\n\n.dropdown-item {\n  color: #fe2f4e;\n}\n\n.dropdown-item:hover {\n  background-color: #fe2f4e;\n}\n\n/* Buttons\n-------------------------------------------------- */\n\n.outline-memray {\n  color: #31373e;\n  background-color: transparent;\n  border-color: #00a3e0;\n}\n\n.filled-memray {\n  color: #fff;\n  background-color: #fe2f4e;\n  border-color: #ff0000;\n}\n\n.filled-memray:hover {\n  color: #fff;\n  background-color: #fe6615;\n  border-color: #ff0000;\n}\n\n/* Hero element\n-------------------------------------------------- */\n\n.splash {\n  width: 99vw;\n  height: 99vh;\n  margin: 0;\n  padding: 0;\n  background-color: #fff;\n  background-repeat: no-repeat;\n  background-size: cover;\n  background-position: center;\n  font-family: \"Open Sans\", sans-serif;\n  font-weight: 300;\n}\n\n.splash-container {\n  z-index: 2;\n}\n\n.splash-image {\n  max-width: 70%;\n  min-width: 25em;\n}\n\n.m-intro {\n  text-align: center;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  height: 100%;\n  margin: 0 auto;\n  overflow: hidden;\n  position: relative;\n}\n\n.m-intro:before,\n.m-intro:after {\n  display: block;\n  position: absolute;\n  content: \"\";\n  width: 2560px;\n  height: 2560px;\n  position: absolute;\n  margin-top: -1280px;\n  margin-left: -1280px;\n  transform-origin: center;\n  background-position: center;\n  background-repeat: no-repeat;\n  top: 50%;\n  left: 50%;\n}\n\n.m-intro:before {\n  background-size: 100% auto;\n  -webkit-animation: rotate 30s infinite linear;\n  -moz-animation: rotate 30s infinite linear;\n  -o-animation: rotate 30s infinite linear;\n  animation: rotate 30s infinite linear;\n}\n\n.m-intro:after {\n  background-size: 100% auto;\n  -webkit-animation: rotate 80s infinite linear;\n  -moz-animation: rotate 80s infinite linear;\n  -o-animation: rotate 80s infinite linear;\n  animation: rotate 80s infinite linear;\n}\n\n/* Responsive layout for phones */\n@media (max-width: 767px) {\n  .m-intro {\n    min-width: auto;\n  }\n}\n\n/* Animation for the hero element\n-------------------------------------------------- */\n\n@-webkit-keyframes rotate {\n  0% {\n    transform: rotate(0);\n  }\n\n  100% {\n    transform: rotate(360deg);\n  }\n}\n\n@-moz-keyframes rotate {\n  0% {\n    transform: rotate(0);\n  }\n\n  100% {\n    transform: rotate(360deg);\n  }\n}\n\n@-o-keyframes rotate {\n  0% {\n    transform: rotate(0);\n  }\n\n  100% {\n    transform: rotate(360deg);\n  }\n}\n\n@keyframes rotate {\n  0% {\n    transform: rotate(0);\n  }\n\n  100% {\n    transform: rotate(360deg);\n  }\n}\n\n/* Text typing animation\n-------------------------------------------------- */\n\n.typewriter_container {\n  display: flex;\n  justify-content: center;\n  align-items: center;\n  font-size: clamp(2rem, 2.8vw, 5rem);\n}\n\n.typewriter {\n  overflow: hidden;\n  border-right: 0.15em solid #31373e;\n  white-space: nowrap;\n  margin: 0 auto;\n  animation:\n    typing 2.75s steps(40, end),\n    blink-caret 0.75s step-end infinite;\n}\n\n@keyframes typing {\n  from {\n    width: 0;\n  }\n\n  to {\n    width: 32ch;\n  }\n}\n\n@keyframes blink-caret {\n  from,\n  to {\n    border-color: transparent;\n  }\n\n  50% {\n    border-color: #31373e;\n  }\n}\n\n/* Scrolling Indicator (mouse wheel)\n-------------------------------------------------- */\n\n.mouse {\n  display: block;\n  margin: 0 auto;\n  width: 43px;\n  height: 80px;\n  border-radius: 53px;\n  border: 2px solid #ff0041;\n  position: absolute;\n  top: 85%;\n  position: absolute;\n  left: 50%;\n  margin-left: -14px;\n}\n\n.mouse span {\n  display: block;\n  margin: 6px auto;\n  width: 3px;\n  height: 7px;\n  border-radius: 100%;\n  background: #ff0041;\n  -webkit-animation-duration: 1s;\n  animation-duration: 1s;\n  -webkit-animation-fill-mode: both;\n  animation-fill-mode: both;\n  -webkit-animation-iteration-count: infinite;\n  animation-iteration-count: infinite;\n  -webkit-animation-name: scroll;\n  animation-name: scroll;\n}\n\n@-webkit-keyframes scroll {\n  0% {\n    opacity: 1;\n    -webkit-transform: translateY(0);\n    transform: translateY(0);\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: translateY(52px);\n    transform: translateY(52px);\n  }\n}\n\n@keyframes scroll {\n  0% {\n    opacity: 1;\n    -webkit-transform: translateY(0);\n    -ms-transform: translateY(0);\n    transform: translateY(0);\n  }\n\n  100% {\n    opacity: 0;\n    -webkit-transform: translateY(52px);\n    -ms-transform: translateY(52px);\n    transform: translateY(52px);\n  }\n}\n\n/* Image animations on scroll\n-------------------------------------------------- */\n\n.reveal_l {\n  position: relative;\n  transform: translateY(150px);\n  opacity: 0;\n  transition: 2s all ease;\n}\n\n.reveal_l.active {\n  transform: translateY(0);\n  opacity: 1;\n}\n\n.reveal_r {\n  position: relative;\n  transform: translateY(-150px);\n  opacity: 0;\n  transition: 2s all ease;\n}\n\n.reveal_r.active {\n  transform: translateY(0);\n  opacity: 1;\n}\n\n/* MARKETING CONTENT\n-------------------------------------------------- */\n\n/* Border for the rounded images */\n\n.rounded-header-image {\n  border-radius: 50%;\n  border: 5px solid rgb(245, 245, 245);\n  box-shadow: 0 2px 2px rgba(0, 0, 0, 0.3);\n}\n\n.rounded-header-image:hover {\n  -webkit-transform: scale(1.1);\n  transform: scale(1.1);\n  transition: all 0.3s ease-in-out;\n}\n\n/* Center align the text within the three columns below the carousel */\n.marketing .col-lg-4 {\n  margin-bottom: 1.5rem;\n  text-align: center;\n}\n\n.marketing h2 {\n  font-weight: 400;\n}\n\n.marketing .col-lg-4 p {\n  margin-right: 0.75rem;\n  margin-left: 0.75rem;\n}\n\n/* Featurettes\n------------------------- */\n\n.featurette-divider {\n  margin: 5rem 0;\n  /* Space out the Bootstrap <hr> more */\n}\n\n/* Thin out the marketing headings */\n.featurette-heading {\n  font-weight: 300;\n  line-height: 1;\n  letter-spacing: -0.05rem;\n}\n\n/* Cards and card columns\n----------------------------- */\n\n.card-container {\n  margin: 0 50px;\n}\n\n.card-columns {\n  flex-wrap: wrap;\n}\n\n.card:hover {\n  background: linear-gradient(90deg, #cc9add 8.06%, #ebad98 106.93%);\n  text-decoration: none;\n  transform: scale(1.05);\n  transition: all 0.3s ease-in-out;\n}\n\n.card:hover .card-title,\n.card:hover .card-subtitle,\n.card:hover .card-text {\n  color: white;\n}\n\n.card:hover .card-link {\n  color: rgb(231, 231, 231);\n}\n\n@media (min-width: 768px) {\n  .card {\n    flex-basis: calc(33.33% - 30px);\n  }\n}\n\n/* RESPONSIVE CSS\n-------------------------------------------------- */\n\n@media (min-width: 40em) {\n  /* Bump up size of carousel content */\n  .carousel-caption p {\n    margin-bottom: 1.25rem;\n    font-size: 1.25rem;\n    line-height: 1.4;\n  }\n\n  .featurette-heading {\n    font-size: 50px;\n  }\n}\n\n@media (min-width: 62em) {\n  .featurette-heading {\n    margin-top: 7rem;\n  }\n}\n"
  },
  {
    "path": "docs/_static/flamegraphs/.gitattributes",
    "content": "*.html -diff\n"
  },
  {
    "path": "docs/_static/js/custom.js",
    "content": "function reveal() {\n  var classes = [\".reveal_l\", \".reveal_r\"];\n  classes.map(function (c) {\n    var reveals = document.querySelectorAll(c);\n    for (var i = 0; i < reveals.length; i++) {\n      var windowHeight = window.innerHeight;\n      var elementTop = reveals[i].getBoundingClientRect().top;\n      var elementVisible = 150;\n      if (elementTop < windowHeight - elementVisible) {\n        reveals[i].classList.add(\"active\");\n      } else {\n        reveals[i].classList.remove(\"active\");\n      }\n    }\n  });\n}\nwindow.addEventListener(\"scroll\", reveal);\n// To check the scroll position on page load\nreveal();\n"
  },
  {
    "path": "docs/_templates/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n\n<head>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\n    <meta name=\"description\" content=\"\">\n    <meta name=\"author\" content=\"\">\n\n    <title>Memray: the endgame memory profiler</title>\n\n    <!-- Bootstrap core CSS -->\n    <link href=\"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css\" rel=\"stylesheet\">\n    <link href=\"https://fonts.googleapis.com/css?family=Open+Sans:300,400,700\" rel=\"stylesheet\">\n\n    <!-- Custom styles for this template -->\n    <link href=\" {{ pathto('_static/css/custom.css', 1) }}\" rel=\"stylesheet\">\n\n    <style>\n        .m-intro:before {\n            background-image: url(\"{{pathto('_static/images/circle_inner_opt.png', 1)}}\");\n        }\n\n        .m-intro:after {\n            background-image: url(\"{{pathto('_static/images/circle_outer_opt.png', 1)}}\");\n        }\n    </style>\n    <link rel=\"icon\" href=\"_static/favicon.ico\">\n\n</head>\n\n<body>\n\n    <header>\n        <nav class=\"navbar navbar-expand-md fixed-top\">\n            <div class=\"navbar-brand\">\n                <img src=\" {{ pathto('_static/images/logo.png', 1) }} \" style=\"height: 2rem;\" alt=\"Memray logo\">\n            </div>\n\n            <div class=\"navbar-light bg-light\">\n                <button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#navbarNavDropdown\"\n                    aria-controls=\"navbarNavDropdown\" aria-expanded=\"false\" aria-label=\"Toggle navigation\">\n                    <span class=\"navbar-toggler-icon\"></span>\n                </button>\n            </div>\n\n            <div class=\"collapse navbar-collapse\" id=\"navbarNavDropdown\">\n                <ul class=\"navbar-nav mr-auto\">\n                    <li class=\"nav-item\">\n                        <a class=\"nav-link\" href=\"{{ pathto('overview') }}\">Documentation</a>\n                    </li>\n                    <li class=\"nav-item\">\n                        <a class=\"nav-link\" href=\"{{ pathto('getting_started') }}\">Getting Started</a>\n                    </li>\n                    <li class=\"nav-item dropdown\">\n                        <a class=\"nav-link dropdown-toggle\" href=\"#\" id=\"navbarDropdownMenuLink3\" data-toggle=\"dropdown\"\n                            aria-haspopup=\"true\" aria-expanded=\"false\">\n                            Try for yourself\n                        </a>\n                        <div class=\"dropdown-menu\" aria-labelledby=\"navbarDropdownMenuLink3\">\n                            <a class=\"dropdown-item\" href=\"{{ pathto('tutorials/index') }}\">Tutorials</a>\n                            <a class=\"dropdown-item\" href=\"{{ pathto('examples/README') }}\">Examples</a>\n                        </div>\n                    </li>\n                    <li class=\"nav-item\">\n                        <a class=\"nav-link\" href=\"https://github.com/bloomberg/pytest-memray\">Pytest plugin</a>\n                    </li>\n                    <li class=\"nav-item dropdown\">\n                        <a class=\"nav-link dropdown-toggle\" href=\"#\" id=\"navbarDropdownMenuLink2\" data-toggle=\"dropdown\"\n                            aria-haspopup=\"true\" aria-expanded=\"false\">\n                            Community\n                        </a>\n                        <div class=\"dropdown-menu\" aria-labelledby=\"navbarDropdownMenuLink2\">\n                            <a class=\"dropdown-item\" href=\"https://github.com/bloomberg/memray\">Github</a>\n                            <a class=\"dropdown-item\" href=\"https://pypi.org/project/memray/\">PyPI</a>\n                            <a class=\"dropdown-item\"\n                                href=\"https://github.com/bloomberg/memray/discussions\">Discussions</a>\n                        </div>\n                    </li>\n                </ul>\n            </div>\n        </nav>\n    </header>\n\n    <main role=\"main\">\n\n        <section class=\"splash text-center\">\n            <div class=\"m-intro\">\n                <div class=\"splash-container\" style=\"z-index: 2;\">\n                    <img class=\"splash-image\" src=\" {{ pathto('_static/images/logo.png', 1) }} \" alt=\"<Memray logo\">\n                    <div class=\"typewriter_container\">\n                        <h1 class=\"lead typewriter\"><b>The endgame Python memory profiler</b></h1>\n                    </div>\n                    <p class=\"lead text-muted\">\n                        Memray tracks and reports memory allocations, both in Python code and in compiled\n                        extension modules.\n                    </p>\n                    <p>\n                        <a href=\" {{ pathto('getting_started') }} \"\n                            class=\"btn btn-primary filled-memray btn-lg\">Documentation</a>\n                        <a href=\"https://github.com/bloomberg/memray/discussions\"\n                            class=\"btn btn-secondary btn-lg\">Community</a>\n                    </p>\n                    <div class=\"mouse\"> <span></span> </div>\n                </div>\n            </div>\n        </section>\n\n        <!-- Marketing messaging and featurettes\n      ================================================== -->\n        <!-- Wrap the rest of the page in another container to center all the content. -->\n\n        <div class=\"container marketing\">\n\n            <hr class=\"featurette-divider\">\n\n            <!-- Three columns of text below the carousel -->\n            <div class=\"row\">\n                <div class=\"col-lg-4\">\n                    <img class=\"rounded-circle rounded-header-image\"\n                        src=\"{{ pathto('_static/images/mandelbrot_operation_native.png', 1) }}\"\n                        alt=\"Flame graph screenshot\" width=\"140\" height=\"140\">\n                    <h2>See where it happens</h2>\n                    <p>\n                        Memray knows the stack trace of every single allocation that happens in your code, no\n                        matter how small it is. This lets you see exactly where your memory is being\n                        allocated and gives you insights on how to optimize your code.\n                    </p>\n                    <p><a class=\"btn btn-secondary filled-memray\" href=\"{{ pathto('flamegraph') }}\" role=\"button\">View\n                            details &raquo;</a></p>\n                </div><!-- /.col-lg-4 -->\n                <div class=\"col-lg-4\">\n                    <img class=\"rounded-circle rounded-header-image\"\n                        src=\"{{ pathto('_static/images/summary_example.png', 1) }}\" alt=\"Summary reporter screenshot\"\n                        width=\"140\" height=\"140\">\n                    <h2>More than just a profiler</h2>\n                    <p>\n                        Memray does much more than just telling you where your application is spending\n                        memory and which memory is being leaked. For instance, it can help you find wasteful\n                        temporary allocations that you can avoid to speed up your program.\n                    </p>\n                    <p><a class=\"btn btn-secondary filled-memray\" href=\" {{ pathto('temporary_allocations') }} \"\n                            role=\"button\">See how &raquo;</a></p>\n                </div><!-- /.col-lg-4 -->\n                <div class=\"col-lg-4\">\n                    <img class=\"rounded-circle rounded-header-image\"\n                        src=\"https://docs.pytest.org/en/7.2.x/_static/pytest_logo_curves.svg\" alt=\"pytest logo\"\n                        width=\"140\" height=\"140\">\n                    <h2>Prevent regressions</h2>\n                    <p>\n                        You can easily integrate Memray into your pytest test suite. Learn where each test is\n                        spending its memory with per-test allocation summaries with useful statistics, or set\n                        limits on how much memory each test is allowed to use to prevent memory regressions!\n                    </p>\n                    <p><a class=\"btn btn-secondary filled-memray\" href=\"https://pytest-memray.readthedocs.io/en/latest/\"\n                            role=\"button\">Discover the plugin &raquo;</a></p>\n                </div><!-- /.col-lg-4 -->\n            </div><!-- /.row -->\n\n            <!-- START THE FEATURETTES -->\n            <hr class=\"featurette-divider\">\n\n            <div class=\"row featurette\">\n                <div class=\"col-md-7\">\n                    <h2 class=\"featurette-heading\">Native allocation tracking. <span class=\"text-muted\">No more leaks\n                            in C extensions.</span></h2>\n                    <p class=\"lead\">\n                        Memray sees allocations made by C/C++/Rust libraries.\n                        This means that when you use Memray to profile your\n                        Python code, you'll be able to see the entire call\n                        stack, including any calls to C/C++/Rust functions. This can\n                        be incredibly useful for tracking down memory issues, as\n                        it allows you to see exactly where and how memory is\n                        being allocated. Whether you're working\n                        on a complex project with many layers of code, or simply\n                        trying to optimize your Python scripts for better\n                        performance, Memray is an invaluable tool that can help\n                        you understand and improve your code's memory usage.\n                    </p>\n                </div>\n                <div class=\"col-md-5\">\n                    <img class=\"featurette-image img-fluid mx-auto reveal_l\"\n                        src=\"{{ pathto('_static/images/native_mode_debug.png', 1) }}\" alt=\"Native mode tracking\">\n                </div>\n            </div>\n\n            <hr class=\"featurette-divider\">\n\n            <div class=\"row featurette\">\n                <div class=\"col-md-7 order-md-2\">\n                    <h2 class=\"featurette-heading\">Catch it as it happens! <span class=\"text-muted\">Live memory\n                            profiling.</span></h2>\n                    <p class=\"lead\">\n                        One of the standout features of Memray is its ability to\n                        provide a live, real-time view of memory allocation.\n                        With the live mode, you can see exactly how memory is\n                        being used as your Python code is executing. This can be\n                        particularly useful for debugging and optimizing your\n                        code, as you can see in real-time how different parts of\n                        your code are impacting memory usage.\n                    </p>\n                </div>\n                <div class=\"col-md-5 order-md-1\">\n                    <img class=\"featurette-image img-fluid mx-auto reveal_r\"\n                        src=\"{{ pathto('_static/images/live_animated.webp', 1) }}\" alt=\"Live mode\">\n                </div>\n            </div>\n\n            <hr class=\"featurette-divider\">\n\n            <div class=\"row featurette\">\n                <div class=\"col-md-7\">\n                    <h2 class=\"featurette-heading\">One log, many analyses. <span class=\"text-muted\">\n                            There's a reporter for everyone!</span></h2>\n                    <p class=\"lead\">\n                        One of the great things about Memray is its flexibility\n                        and customizability. After running a memory profiling\n                        session, you can use a wide range of reporters to view\n                        the data in different ways. For example, you can use the\n                        flamegraph reporter to see a visual representation of\n                        the call stack and how memory is being used at each\n                        level. Or, you can use the statistical reporter to see\n                        summary statistics and trends in your memory usage.\n                        And these are just a few of the many reporters available\n                        in Memray - there are many more to choose from, allowing\n                        you to view your data in the way that makes the most\n                        sense for your specific needs.\n                    </p>\n                </div>\n                <div class=\"col-md-5\">\n                    <img class=\"featurette-image img-fluid mx-auto reveal_l\"\n                        src=\"{{ pathto('_static/images/stats_example.png', 1) }}\" alt=\"Many reporters\">\n                </div>\n            </div>\n\n            <div class=\"row featurette\">\n                <h2 class=\"featurette-heading\">Memray in the media</h2>\n                <div class=\"row\">\n                    <br>\n                    <div class=\"card-container\">\n                        <div class=\"card-columns\">\n                            <a href=\"https://news.ycombinator.com/item?id=31102089\" class=\"card\">\n                                <div class=\"card-body\">\n                                    <h5 class=\"card-title\">Memray: a memory profiler for Python</h5>\n                                    <h6 class=\"card-subtitle mb-2 text-muted\">Hacker News - 2022-04-20</h6>\n                                </div>\n                            </a>\n                            <a href=\"https://pythonbytes.fm/episodes/show/282/dont-embarrass-me-in-front-of-the-wizards\"\n                                class=\"card\">\n                                <div class=\"card-body\">\n                                    <h5 class=\"card-title\">#282: Don't Embarrass Me in Front of The Wizards</h5>\n                                    <h6 class=\"card-subtitle mb-2 text-muted\">PythonBytes (podcast) - 2022-05-03</h6>\n                                </div>\n                            </a>\n                            <a href=\"https://sdtimes.com/softwaredev/sd-times-open-source-project-of-the-week-memray/\"\n                                class=\"card\">\n                                <div class=\"card-body\">\n                                    <h5 class=\"card-title\">SD Times Open-Source Project of the Week: Memray</h5>\n                                    <h6 class=\"card-subtitle mb-2 text-muted\">SD Times - 2022-05-06</h6>\n                                </div>\n                            </a>\n                            <a href=\"https://devclass.com/2022/05/12/core-dev-memray-memory-profiler/\" class=\"card\">\n                                <div class=\"card-body\">\n                                    <h5 class=\"card-title\">New Memray memory profiler tracks both Python and native code\n                                    </h5>\n                                    <h6 class=\"card-subtitle mb-2 text-muted\">DevClass - 2022-05-12</h6>\n                                </div>\n                            </a>\n                            <a href=\"https://blog.opensource.org/memray-project-showcases-why-bloomberg-is-an-open-source-first-company/\"\n                                class=\"card\">\n                                <div class=\"card-body\">\n                                    <h5 class=\"card-title\">Memray project showcases why Bloomberg is an ‘open source\n                                        first’ company</h5>\n                                    <h6 class=\"card-subtitle mb-2 text-muted\">Voice of Open Source - 2022-05-17</h6>\n                                </div>\n                            </a>\n                            <a href=\"https://www.datanami.com/2022/05/18/memray-shines-a-light-on-python-c-c-memory-problems/\"\n                                class=\"card\">\n                                <div class=\"card-body\">\n                                    <h5 class=\"card-title\">Memray Shines a Light on Python-C/C++ Memory Problems</h5>\n                                    <h6 class=\"card-subtitle mb-2 text-muted\">Datanimi - 2022-05-18</h6>\n                                </div>\n                            </a>\n                            <a href=\"https://console.substack.com/p/console-107?s=r\" class=\"card\">\n                                <div class=\"card-body\">\n                                    <h5 class=\"card-title\">#107 -- Interview With Pablo of Bloomberg about Memray</h5>\n                                    <h6 class=\"card-subtitle mb-2 text-muted\">Console - 2022-05-29</h6>\n                                </div>\n                            </a>\n                            <a href=\"https://realpython.com/podcasts/rpp/128/\" class=\"card\">\n                                <div class=\"card-body\">\n                                    <h5 class=\"card-title\">Episode 128: Using a Memory Profiler in Python & What It Can\n                                        Teach You</h5>\n                                    <h6 class=\"card-subtitle mb-2 text-muted\">The Real Python Podcast - 2022-010-7</h6>\n                                </div>\n                            </a>\n                            <a href=\"https://tryolabs.com/blog/2022/12/26/top-python-libraries-2022\" class=\"card\">\n                                <div class=\"card-body\">\n                                    <h5 class=\"card-title\">Top Python libraries of 2022</h5>\n                                    <h6 class=\"card-subtitle mb-2 text-muted\">Tyro Labs - 2022-012-26</h6>\n                                </div>\n                            </a>\n                            <a href=\"https://www.dice.com/career-advice/developer-qa-pablo-galindo-talks-pythons-speedy-future\"\n                                class=\"card\">\n                                <div class=\"card-body\">\n                                    <h5 class=\"card-title\">Developer Q&A: Pablo Galindo Salgado Talks Python's Speedy\n                                        Future</h5>\n                                    <h6 class=\"card-subtitle mb-2 text-muted\">Dice - 2022-01-05</h6>\n                                </div>\n                            </a>\n                            <a href=\"https://www.reddit.com/r/Python/comments/u84tjr/bloomberg_just_open_sourced_memray_a_memory/\"\n                                class=\"card\">\n                                <div class=\"card-body\">\n                                    <h5 class=\"card-title\">Bloomberg just Open sourced Memray a memory profiler for\n                                        Python</h5>\n                                    <h6 class=\"card-subtitle mb-2 text-muted\">Reddit - 2022-04-20</h6>\n                                </div>\n                            </a>\n                            <a href=\"https://newsletter.researchcomputingteams.org/archive/research-computing-teams-119-23-apr-2022/\"\n                                class=\"card\">\n                                <div class=\"card-body\">\n                                    <h5 class=\"card-title\">Research Computing Teams #119, 23 Apr 2022</h5>\n                                    <h6 class=\"card-subtitle mb-2 text-muted\">Research Computing Teams - 2022-04-23</h6>\n                                </div>\n                            </a>\n                            <a href=\"https://console.substack.com/p/console-102?s=r\" class=\"card\">\n                                <div class=\"card-body\">\n                                    <h5 class=\"card-title\">Console #102 -- Snapdrop, Memray, and Headless Recorder </h5>\n                                    <h6 class=\"card-subtitle mb-2 text-muted\">Console - 2022-04-24</h6>\n                                </div>\n                            </a>\n                            <a href=\"https://www.infoq.com/news/2022/04/bloomberg-memray-python-profiler/\" class=\"card\">\n                                <div class=\"card-body\">\n                                    <h5 class=\"card-title\">Bloomberg Open-Sources Python Memory Profiler Memray</h5>\n                                    <h6 class=\"card-subtitle mb-2 text-muted\">InfoQ - 2022-04-26</h6>\n                                </div>\n                            </a>\n                            <a href=\"https://thestack.technology/memray-python-memory-profiler-bloomberg/\" class=\"card\">\n                                <div class=\"card-body\">\n                                    <h5 class=\"card-title\">Check your Memray: Bloomberg open sources tool for Python\n                                        apps</h5>\n                                    <h6 class=\"card-subtitle mb-2 text-muted\">The Stack - 2022-04-29</h6>\n                                </div>\n                            </a>\n                            <a href=\"https://www.marktechpost.com/2022/04/30/bloomberg-open-sources-memray-a-memory-profiler-that-can-track-memory-allocations-in-python-code-in-native-extension-modules-and-python-interpreter/\"\n                                class=\"card\">\n                                <div class=\"card-body\">\n                                    <h5 class=\"card-title\">Bloomberg Open-Sources Memray</h5>\n                                    <h6 class=\"card-subtitle mb-2 text-muted\">Market Tech - 4/30/22</h6>\n                                </div>\n                            </a>\n                        </div>\n                    </div>\n                </div><!-- /.row -->\n            </div>\n            <!-- /END THE FEATURETTES -->\n\n        </div><!-- /.container -->\n\n        <!-- FOOTER -->\n        <footer class=\"container\">\n            <p class=\"float-right\"><a href=\"#\">Back to top</a></p>\n            <p> <a href=\"https://github.com/bloomberg/memray\">GitHub Page</a> &middot; <a\n                    href=\"https://github.com/bloomberg/memray/blob/main/LICENSE\">License</a></p>\n        </footer>\n    </main>\n\n    <!-- Bootstrap core JavaScript\n      ================================================== -->\n    <!-- Placed at the end of the document so the pages load faster -->\n    <script src=\"https://code.jquery.com/jquery-3.2.1.slim.min.js\"\n        integrity=\"sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN\"\n        crossorigin=\"anonymous\"></script>\n    <script src=\"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js\"></script>\n\n    <!-- Custom JS -->\n    <script src=\"{{ pathto('_static/js/custom.js', 1) }}\"></script>\n\n</html>\n"
  },
  {
    "path": "docs/api.rst",
    "content": ".. module:: memray\n\nMemray API\n==========\n\nMemray exposes an API that can be used to programmatically activate or\ndeactivate tracking of a Python process's memory allocations. You do this by\ncreating a `Tracker` object and using it as a context manager in a ``with``\nstatement. While the body of the ``with`` statement runs, tracking will be\nenabled, with output being sent to a destination you specify when creating the\n`Tracker`. When the ``with`` block ends, tracking will be disabled and the\noutput will be flushed and closed.\n\nAPI Usage\n---------\n\n.. autoclass:: memray.Tracker\n   :members:\n\n.. autoclass:: memray.FileDestination\n   :members:\n\n.. autoclass:: memray.SocketDestination\n   :members:\n\n.. autoclass:: memray.FileFormat()\n\n   This enumeration lists the capture file formats that Memray can write. The\n   `Tracker` constructor accepts a *file_format* keyword argument for choosing\n   a different format than the default.\n\n    .. autoattribute:: memray.FileFormat.ALL_ALLOCATIONS\n       :annotation:\n\n    Record every allocation that the tracked process performs. This is the\n    default format. The produced capture files may be very large if the process\n    performs many allocations. This is the only format that allows detecting\n    :doc:`temporary allocations </temporary_allocations>` or using the\n    :doc:`stats reporter <stats>`.\n\n    .. autoattribute:: memray.FileFormat.AGGREGATED_ALLOCATIONS\n       :annotation:\n\n    For every location where the tracked process performed any allocations, the\n    capture file includes a count of:\n\n    - How many allocations at that location had not yet been deallocated when\n      the process reached its heap memory high water mark\n    - How many bytes had been allocated at that location and not yet\n      deallocated when the process reached its heap memory high water mark\n    - How many allocations at that location were leaked (i.e. not deallocated\n      before tracking stopped)\n    - How many bytes were leaked by allocations at that location\n\n    You cannot find :doc:`temporary allocations </temporary_allocations>` using\n    this capture file format, since finding temporary allocations requires\n    knowing when each allocation was deallocated, and that information is lost\n    by the aggregation. You also cannot use the :doc:`stats reporter <stats>`\n    with this capture file format, because it needs to see every allocation's\n    size to compute its statistics.\n\n    Additionally, if the process is killed before tracking ends (for instance,\n    by the Linux OOM killer), then no useful information is ever written to the\n    capture file, because aggregation was still happening inside the process\n    when it died.\n\n    If you can live with these limitations, then ``AGGREGATED_ALLOCATIONS``\n    results in much smaller capture files that can be used seamlessly with most\n    reporters.\n"
  },
  {
    "path": "docs/attach.rst",
    "content": "Attaching to a running process\n==============================\n\nMemray allows you to attach to a running process and to observe the allocations\nit performs once you've attached. This **doesn't allow you to see where memory\nwas allocated before you attached to the process**, but it does allow you to\nobserve or record future allocations. This can be useful if an application is\ncontinuing to request more memory than you think it should need, and you want\nto figure out why. It can also be useful for observing the allocation patterns\nof a long running process once the process has already completed any initial\nwarm up steps that it needs to do.\n\nBasic Usage\n-----------\n\nThe general form of the ``attach`` subcommand is:\n\n.. code:: shell\n\n    memray attach [options] <pid>\n\nThe only required argument for ``memray attach`` is a process ID to attempt to\nattach to. You must be :ref:`able to attach a debugger <ptrace privs>` to that\nprocess, and that process **must be a Python process**, and the Memray package\n**must be installed in the environment that the process is running in**. That\nis, ``memray attach`` will execute the Python statement ``import memray`` in\nthe process being attached to, and that import must succeed for attaching to\nwork.\n\nBy default this will open a :doc:`live mode TUI <live>` showing the allocations\nthat the process performs after you've attached, but you can instead provide\nthe name of a capture file to write to with the ``-o`` option, allowing you to\nanalyze the captured allocations with any Memray reporter you'd like. You can\nalso provide most of the options that ``memray run`` accepts. See :ref:`the\nCLI reference <memray attach CLI reference>` for details.\n\nIf you use the ``-o`` option, the process will continue recording allocations\nto the capture file even after ``memray attach`` has returned. Otherwise,\nallocations are tracked only for as long as the :doc:`live mode TUI <live>`\ncontinues running. Once you quit the TUI, the attached process will stop\ntracking allocations. If you later reattach to the same process, it will start\nfrom a clean slate, and will not be aware of any allocations seen during your\nfirst TUI session.\n\n.. _ptrace privs:\n\nDebugger Privileges\n-------------------\n\nMemray leverages a debugger for attaching to the process. It is compatible with\nboth gdb and lldb, but one or the other must be installed in order for ``memray\nattach`` to work. Only a super user (either root, or a user with the\n``CAP_SYS_PTRACE`` capability) can attach to processes run by another user.\nFurther, security settings on modern Linux systems typically prevent a regular\nuser from attaching even to their own processes. You can loosen that\nrestriction by writing ``0`` to ``/proc/sys/kernel/yama/ptrace_scope`` as root,\nallowing any user to attach to their own processes. When running a Docker\ncontainer, you can use ``--cap-add=SYS_PTRACE`` to allow attaching to processes\nwithin the container.\n\n.. warning::\n\n   Allowing arbitrary processes to be traced `is insecure\n   <https://www.kernel.org/doc/html/latest/admin-guide/LSM/Yama.html>`_, as it\n   provides an easy vector for privilege escalation within a remote code\n   execution attack. Be sure to consider the security implications before you\n   choose to grant regular users the ability to attach to processes.\n\nIn some cases (like MacOS), the debugger may require you to authenticate with\nyour username and password in order to attach to a process. In that case it is\npossible that a window will pop up asking for your password or for biometric\nauthentication.\n\nCaveats\n-------\n\n``memray attach`` works by injecting executable code into a running process.\nWe've tried to do this in the safest way possible, but we can't guarantee that\nthere aren't edge cases where this might crash or deadlock the process that\nyou're attempting to attach to, depending on what it's doing at the point when\nwe attach. We advise only using this as a debugging tool on development\nmachines.\n\nIf you attach to a Python 3.7 or Python 3.8 process that has never imported the\n``threading`` module, the attached process will show an error when the\ninterpreter finishes running the main script. This is due to `a known bug\n<https://github.com/python/cpython/issues/81597>`_ that was not fixed until\nPython 3.9. From Python 3.9 onwards there will be no error on exit, but the\ninterpreter will assign the wrong name to the main thread if ``threading`` is\nlater imported by the script. That should not have any major effect on the\nbehavior of the program.\n\nWhen attaching to a running process, Memray will ``import`` a helper module.\nThis means that Memray must be installed in the Python environment that the\nprocess is running in. If it's not, things can fail in various ways, including\ncrashing the process (see https://github.com/bloomberg/memray/issues/846 for\ninstance). It may be possible to attach to a process in a container from\noutside the container if the same version of Memray is installed in both\nenvironments, but it's safer and more reliable to run Memray in the container\ninstead.\n\nIf you do find some case where ``memray attach`` either doesn't work or causes\na crash or deadlock, we want to hear about it! Please `file a bug report`_\nexplaining what went wrong. If the issue is reproducible, please try running\n``memray attach`` with the ``--verbose`` flag, which outputs a lot of extra\ndebugging information, including the output of the debugger session that was\nused to inject our code into the remote process. If the process crashed and\nleft a core file, please include a stack trace of all of the threads in the\nprocess, so that we can understand what state it was in when we tried to\nattach. You can show all threads' stacks using ``thread apply all bt`` in gdb\nor ``thread backtrace all`` in lldb.\n\n.. _file a bug report: https://github.com/bloomberg/memray/issues/new?assignees=&labels=bug&template=---bug-report.yaml\n\nCLI Reference\n-------------\n\n.. _memray attach cli reference:\n\nmemray attach\n^^^^^^^^^^^^^\n\n.. argparse::\n    :ref: memray.commands.get_argument_parser\n    :path: attach\n    :prog: memray\n    :nodefaultconst:\n    :noepilog:\n\nmemray detach\n^^^^^^^^^^^^^\n\n.. argparse::\n    :ref: memray.commands.get_argument_parser\n    :path: detach\n    :prog: memray\n    :nodefaultconst:\n"
  },
  {
    "path": "docs/conf.py",
    "content": "\"\"\"Sphinx configuration file for memray's documentation.\"\"\"\n\nimport os\n\nimport memray.commands\n\n# -- General configuration ------------------------------------------------------------\n\n# The name of a reST role (builtin or Sphinx extension) to use as the default role,\n# that is, for text marked up `like this`. This can be set to 'py:obj' to make `filter`\n# a cross-reference to the Python function “filter”. The default is None,\n# which doesn’t reassign the default role.\ndefault_role = \"py:obj\"\n\nextensions = [\n    # first-party extensions\n    \"sphinx.ext.autodoc\",\n    \"sphinx.ext.doctest\",\n    \"sphinx.ext.extlinks\",\n    \"sphinx.ext.githubpages\",\n    \"sphinx.ext.intersphinx\",\n    \"sphinx.ext.napoleon\",\n    \"sphinx.ext.todo\",\n    \"sphinx.ext.viewcode\",\n    # third-party extensions\n    \"sphinxarg.ext\",\n]\n\n# Don't build our manpage document when we're using the HTML builder.\n# We override this setting when we build with the manpage builder.\nexclude_patterns = [\"manpage.rst\"]\n\n# General information about the project.\nproject = \"memray\"\nauthor = \"Pablo Galindo Salgado\"\n\n# -- Options for HTML -----------------------------------------------------------------\n\nhtml_title = project\nhtml_theme = \"furo\"\nhtml_static_path = [\"_static\", \"_static/flamegraphs\"]\nhtml_logo = \"_static/images/logo.png\"\nhtml_theme_options = {\n    \"sidebar_hide_name\": True,\n}\n\ntemplates_path = [\"_templates\"]\nhtml_additional_pages = {\n    \"index\": \"index.html\",\n}\nhtml_favicon = \"favicon.ico\"\n\n# -- Options for man pages ------------------------------------------------------------\nman_pages = [\n    (\"manpage\", \"memray\", \"Python memory profiler\", \"\", 1),\n]\n\n# -- Options for smartquotes ----------------------------------------------------------\n\n# Disable the conversion of dashes so that long options like \"--find-links\" won't\n# render as \"-find-links\" if included in the text.The default of \"qDe\" converts normal\n# quote characters ('\"' and \"'\"), en and em dashes (\"--\" and \"---\"), and ellipses \"...\"\nsmartquotes_action = \"qe\"\n\n# -- Options for intersphinx ----------------------------------------------------------\n\nintersphinx_mapping = {\n    \"python\": (\n        \"https://docs.python.org/3\",\n        (None,),\n    ),\n}\n\n# -- Options for sphinx-argparse ------------------------------------------------------\n\n# Limit the width of usage messages. argparse defaults to the terminal width,\n# but we don't want different output depending on the terminal width where the\n# docs were built.\nos.environ[\"COLUMNS\"] = \"88\"\n\n# -- Improving man page generation ----------------------------------------------------\n\n# The :manpage: mode of sphinx-argparse doesn't allow you to fully override the\n# parser's description with a custom reStructuredText one as it should. Work\n# around this by providing the first sentence of our desired description as the\n# parser's description, and then letting the argparse role append the rest of\n# the intended description. This description doesn't go into the HTML docs.\nmemray.commands._DESCRIPTION = \"Memray is a memory profiler for Python applications.\"\n"
  },
  {
    "path": "docs/examples/README.rst",
    "content": ".. _example-applications:\n\nExample Applications for Memray\n=================================\n\nThe projects in the directories located here contain very simple\nexamples to demonstrate usage with Memray.\n\nMake sure you install the required dependencies by running\n``python3.9 -m pip install -r requirements.txt`` in the respective\ndirectory. The examples below use the project in the ``mandelbrot`` folder, but\nyou can use the same instructions to launch the other examples as well.\n\nTo track memory allocations, invoke ``memray3.9 run``:\n\n.. code:: shell\n\n   memray3.9 run mandelbrot/mandelbrot.py\n\nMemray will print a message displaying the output file it creates.\n\n.. code:: text\n\n   Writing profile results into mandelbrot/memray-mandelbrot.py.187967.bin\n\nYou can use this file to create various reports. To generate a flame\ngraph, use the following command:\n\n.. code:: shell\n\n   memray3.9 flamegraph mandelbrot/memray-mandelbrot.py.187967.bin\n\nThe HTML file for the flame graph will be generated under\n``mandelbrot/memray-flamegraph-mandelbrot.py.187967.html``. The flame graph\ndisplays the stack frames in the application where allocations have occurred\nand shows the amount of memory used in each frame.\n\nYou can see sample outputs of the resulting flame graphs:\n\n- `Mandelbrot <../_static/flamegraphs/memray-flamegraph-mandelbrot.html>`_\n- `Nbody <../_static/flamegraphs/memray-flamegraph-nbody.html>`_\n- `SQLite <../_static/flamegraphs/memray-flamegraph-sqlite.html>`_\n- `Fibonacci <../_static/flamegraphs/memray-flamegraph-fib.html>`_\n"
  },
  {
    "path": "docs/examples/fibonacci/fib.py",
    "content": "import sys\n\n\ndef fib1(n):\n    my_list = [0, 1]\n    for i in range(2, n + 1):\n        my_list.append(my_list[i - 1] + my_list[i - 2])\n    return my_list[-1]\n\n\ndef fib2(n, cache={0: 0, 1: 1}):\n    if n in cache:\n        return cache[n]\n    cache[n] = fib2(n - 1) + fib2(n - 2)\n    return cache[n]\n\n\ndef run():\n    sys.setrecursionlimit(100000)\n    n = 99900\n    a = fib1(n)\n    b = fib2(n)\n\n    assert a == b\n\n\nrun()\n"
  },
  {
    "path": "docs/examples/mandelbrot/mandelbrot-threaded.py",
    "content": "from threading import Thread\n\nimport numpy as np\n\n\ndef mandelbrot(height, width, x=-0.5, y=0, zoom=1, max_iterations=100):\n    # To make navigation easier we calculate these values\n    x_width = 1.5\n    y_height = 1.5 * height / width\n    x_from = x - x_width / zoom\n    x_to = x + x_width / zoom\n    y_from = y - y_height / zoom\n    y_to = y + y_height / zoom\n    # Here the actual algorithm starts\n    x = np.linspace(x_from, x_to, width).reshape((1, width))\n    y = np.linspace(y_from, y_to, height).reshape((height, 1))\n    c = x + 1j * y\n    # Initialize z to all zero\n    z = np.zeros(c.shape, dtype=np.complex128)\n    # To keep track in which iteration the point diverged\n    div_time = np.zeros(z.shape, dtype=int)\n    # To keep track on which points did not converge so far\n    m = np.full(c.shape, True, dtype=bool)\n    for i in range(max_iterations):\n        z[m] = z[m] ** 2 + c[m]\n        diverged = np.greater(\n            np.abs(z), 2, out=np.full(c.shape, False), where=m\n        )  # Find diverging\n        div_time[diverged] = i  # set the value of the diverged iteration number\n        m[np.abs(z) > 2] = False  # to remember which have diverged\n    return div_time\n\n\nif __name__ == \"__main__\":\n    t1 = Thread(target=mandelbrot, args=(800, 1000))\n    t1.start()\n    t2 = Thread(target=mandelbrot, args=(800, 1000))\n    t2.start()\n    t3 = Thread(target=mandelbrot, args=(800, 1000))\n    t3.start()\n    t3.join()\n"
  },
  {
    "path": "docs/examples/mandelbrot/mandelbrot.py",
    "content": "import numpy as np\n\n\ndef mandelbrot(height, width, x=-0.5, y=0, zoom=1, max_iterations=100):\n    # To make navigation easier we calculate these values\n    x_width = 1.5\n    y_height = 1.5 * height / width\n    x_from = x - x_width / zoom\n    x_to = x + x_width / zoom\n    y_from = y - y_height / zoom\n    y_to = y + y_height / zoom\n    # Here the actual algorithm starts\n    x = np.linspace(x_from, x_to, width).reshape((1, width))\n    y = np.linspace(y_from, y_to, height).reshape((height, 1))\n    c = x + 1j * y\n    # Initialize z to all zero\n    z = np.zeros(c.shape, dtype=np.complex128)\n    # To keep track in which iteration the point diverged\n    div_time = np.zeros(z.shape, dtype=int)\n    # To keep track on which points did not converge so far\n    m = np.full(c.shape, True, dtype=bool)\n    for i in range(max_iterations):\n        z[m] = z[m] ** 2 + c[m]\n        diverged = np.greater(\n            np.abs(z), 2, out=np.full(c.shape, False), where=m\n        )  # Find diverging\n        div_time[diverged] = i  # set the value of the diverged iteration number\n        m[np.abs(z) > 2] = False  # to remember which have diverged\n    return div_time\n\n\nif __name__ == \"__main__\":\n    mandelbrot(800, 1000)\n"
  },
  {
    "path": "docs/examples/mandelbrot/requirements.txt",
    "content": "numpy\n"
  },
  {
    "path": "docs/examples/nbody/example.py",
    "content": "\"\"\"\nIn this example we investigate the primordial Earth embedded in a disk of\nplanetesimals, integrating it for a short period of time using the MERCURIUS\nintegrator. MERCURIUS is a hybrid integration scheme which combines the WHFAST\nand IAS15 algorithms in a similar way to the hybrid integrastor in the MERCURY\npackage.\n\"\"\"\n\nimport numpy as np\nimport rebound\n\n# First let's choose the basic properties required for the MERCURIUS\n# integrator. In particular, we are * setting planetesimals to semi-active\n# mode, which means they can influence active bodies but not other semi-active\n# bodies. * merge any planetesimals that collide with a planets, conserving\n# momentum and mass. * remove particles from the similation which leave our\n# pre-defined box. * track the energy lost due to ejections or collisions.\nsim = rebound.Simulation()\n\n# integrator options\nsim.integrator = \"mercurius\"\nsim.dt = 0.025 * 2.0 * np.pi  # we're working in units where 1 year = 2*pi\nsim.testparticle_type = 1\nsim.ri_ias15.min_dt = 1e-6  # ensure that close encounters do not stall the integration\n\n# collision and boundary options\nsim.collision = \"direct\"\nsim.collision_resolve = \"merge\"\nsim.collision_resolve_keep_sorted = 1\nsim.track_energy_offset = 1\n\n# Now that the setup is complete, it's time to add some particles! When using\n# the MERCURIUS integrator it is important to add active bodies first and\n# semi-active bodies later. The N_active variable separates massive bodies from\n# semi-active/test bodies. Here, we add two active particles, the Sun and the\n# Earth. Thus, N_active will be 2.\n\nsim.add(m=1.0)\nsim.add(m=3e-6, r=5e-5, a=1, e=0.05, f=np.pi)\nsim.N_active = sim.N  # sim.N= 2\n\n# Now, let's create our planetesimal disk. First we define three different\n# distribution functions - powerlaw, uniform and rayleigh.\n\n\ndef rand_powerlaw(slope, min_v, max_v):\n    y = np.random.uniform()\n    pow_max = pow(max_v, slope + 1.0)\n    pow_min = pow(min_v, slope + 1.0)\n    return pow((pow_max - pow_min) * y + pow_min, 1.0 / (slope + 1.0))\n\n\ndef rand_uniform(minimum, maximum):\n    return np.random.uniform() * (maximum - minimum) + minimum\n\n\ndef rand_rayleigh(sigma):\n    return sigma * np.sqrt(-2 * np.log(np.random.uniform()))\n\n\n# Next, let's set up the basic properties of our planetesimal disk. For this\n# simple example we are assuming that all planetesimals have the same mass and\n# radius.\n\nN_pl = 50000  # Number of planetesimals\nMtot_disk = 10 * sim.particles[1].m  # Total mass of planetesimal disk\nm_pl = Mtot_disk / float(N_pl)  # Mass of each planetesimal\nr_pl = 2e-5  # Radius of each planetesimal\n\n# Now let's add our planetesimals to the simulation!\n\nnp.random.seed(42)  # by setting a seed we will reproduce the same simulation every time\nwhile sim.N < (N_pl + sim.N_active):\n    a = rand_powerlaw(0, 0.99, 1.01)\n    e = rand_rayleigh(0.01)\n    inc = rand_rayleigh(0.005)\n    f = rand_uniform(-np.pi, np.pi)\n    p = rebound.Particle(\n        simulation=sim,\n        primary=sim.particles[0],\n        m=m_pl,\n        r=r_pl,\n        a=a,\n        e=e,\n        inc=inc,\n        Omega=0,\n        omega=0,\n        f=f,\n    )\n    # Only add planetesimal if it's far away from the planet\n    d = np.linalg.norm(np.array(p.xyz) - np.array(sim.particles[1].xyz))\n    if d > 0.01:\n        sim.add(p)\n\n# We move to the COM frame to avoid having the simulation drive away from the\n# origin. In addition, it is always good practice to monitor the change in\n# energy over the course of a simulation, which requires us to calculate it\n# before and after the simulation.\n\nsim.move_to_com()\nE0 = sim.calculate_energy()\n\n# Finally, let us simulate our system for 1 year, and check that our final\n# relative energy error is small.\n\ntimes = np.linspace(0.0, 10.0, 10)\nencounterN = np.zeros(len(times))\ntotalN = np.zeros(len(times))\nerrors = np.zeros(len(times))\nfor i, t in enumerate(times):\n    sim.integrate(t, exact_finish_time=0)\n    totalN[i] = sim.N\n    encounterN[i] = sim.ri_mercurius._encounterN\n    errors[i] = abs((sim.calculate_energy() - E0) / E0)\n"
  },
  {
    "path": "docs/examples/nbody/requirements.txt",
    "content": "numpy\nrebound\n"
  },
  {
    "path": "docs/examples/sqlite/example.py",
    "content": "import random\nimport sqlite3\nimport string\nimport time\n\ncreate_statement = \"\"\"\nCREATE TABLE IF NOT EXISTS database_threading_test\n(\n    symbol TEXT,\n    ts INTEGER,\n    o REAL,\n    h REAL,\n    l REAL,\n    c REAL,\n    vf REAL,\n    vt REAL,\n    PRIMARY KEY(symbol, ts)\n)\n\"\"\"\ninsert_statement = \"INSERT INTO database_threading_test VALUES(?,?,?,?,?,?,?,?)\"\nselect_statement = \"SELECT * from database_threading_test\"\n\n\ndef generate_values(count=100):\n    end = int(time.time()) - int(time.time()) % 900\n    symbol = \"\".join(\n        random.choice(string.ascii_uppercase + string.digits) for _ in range(10)\n    )\n    ts = list(range(end - count * 900, end, 900))\n    for i in range(count):\n        yield (\n            symbol,\n            ts[i],\n            random.random() * 1000,\n            random.random() * 1000,\n            random.random() * 1000,\n            random.random() * 1000,\n            random.random() * 1e9,\n            random.random() * 1e5,\n        )\n\n\ndef generate_values_list(symbols=1000, count=100):\n    values = []\n    for _ in range(symbols):\n        values.extend(generate_values(count))\n    return values\n\n\ndef main():\n    lst = generate_values_list()\n    conn = sqlite3.connect(\":memory:\")\n    with conn:\n        conn.execute(create_statement)\n        conn.executemany(insert_statement, lst)\n    results = conn.execute(select_statement).fetchall()\n    print(f\"There are {len(results)} items in teh db\")\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "docs/flamegraph.rst",
    "content": "Flame Graph Reporter\n====================\n\nThe flame graph reporter generates an HTML file containing a flame graph\nrepresentation of the allocations contributing to the tracked process's peak\nmemory usage.\n\nFlame graphs are a way to visualize where your program is spending its\nmemory. A few important things about flame graphs:\n\n- The flame graph displays the superposition of all stack traces that\n  led to all memory allocations active at a given time (normally the\n  time when the total amount of allocated memory was highest).\n\n- A stack trace is represented as a column of boxes, where each box\n  represents one function call in that call stack.\n\n- The y-axis shows the stack depth. One special row represents the root,\n  the next row represents the top level function calls that eventually\n  led to memory being allocated, the next row represents things directly\n  called by each of those top level calls, and so on. The furthest box\n  from the root in any given vertical slice of the flame graph is the\n  function that actually allocated the memory, and all of the boxes\n  between it and the root tell you the full call stack that led to that\n  allocation.\n\n- The x-axis **does not show the passage of time**, so the left-to-right\n  ordering has no special meaning. Two functions called by the same\n  caller will appear side by side in the flame graph, but can appear in\n  either order.\n\n- The width of each box represents how much memory was allocated by that\n  function call or its children. Wider boxes led to more memory being\n  allocated than narrower ones, in proportion to their width.\n\n- A flame graph can't tell you how many times a function was called,\n  only how much memory that function allocated.\n\nFlames versus Icicles\n---------------------\n\nIn what's traditionally called a flame graph, each function in a call\nstack is shown directly above its caller, with the root at the bottom.\nThis is called a \"flame graph\" because the wide base with narrowing\ncolumns above it looks sort of like a burning log with flames leaping\ninto the air above it.\n\nBy default, Memray instead generates what's sometimes called an \"icicle\ngraph\", which instead has the root at the top. In an icicle graph, each\nfunction is below its caller, and there is a wide ceiling that thinner\ncolumns descend from, like icicles hanging from a roof. We default to\nthe icicle representation because it plays more nicely with the\nbrowser's scroll bar: the most information-dense portion of an icicle\ngraph is at the top of the screen, and the further down the page you\nscroll, the sparser the graphed data becomes, as shallower call stacks\ndrop off.\n\nYou can switch between the flame graph orientation and the icicle graph\norientation with this toggle button:\n\n.. image:: _static/images/icicle_flame_toggle.png\n    :align: center\n\nWhichever of these modes you choose, the data shown in the table is the\nsame, just mirrored vertically.\n\n.. _interpreting flame graphs:\n\nInterpreting flame graphs\n-------------------------\n\nMemray's default (icicle mode) flame graphs can be interpreted as\nfollows:\n\n- The nodes at the bottom of the graph represent functions that\n  allocated memory.\n\n- For quickly identifying the functions that allocated more memory\n  directly, look for wide boxes along the bottom edge, as these show\n  a single stack trace was responsible for a large chunk of the total\n  memory of the snapshot that the graph represents.\n\n- Reading from the bottom up shows ancestry relationships.\n  Every function was called by its parent, which is shown directly above\n  it; the parent was called by its parent shown above it, and so on.\n  A quick scan upward from a function identifies how it was called.\n\n- Reading from the top down shows code flow and the bigger picture.\n  A function called every child function shown below it, which,\n  in turn, called functions shown below them. Reading top down shows\n  the big picture of code flow before various forks split execution into\n  smaller shafts.\n\n- You can directly compare the width of function boxes: wider boxes\n  mean more memory was allocated by the given node, so those are the\n  most important to understand first.\n\n- Major forks in the graph (when a node splits into several nodes in\n  the next level) can be useful to study: these nodes can indicate\n  a logical grouping of code, where a function processes work in stages,\n  each with its own function. It can also be caused by a conditional\n  statement, which chooses which function to call.\n\n- If the application is multi-threaded, the stacks of all the threads\n  that contribute to the memory peak will appear commingled in the\n  graph by default.\n\nAnd of course, if you switch from the \"icicle\" view to the \"flame\" view,\nthe root drops to the bottom of the page, and call stacks grow upwards\nfrom it instead of downwards.\n\nSimple example\n--------------\n\n.. code:: python\n\n   def a(n):\n       return b(n)\n\n   def b(n):\n       return [c(n), d(n)]\n\n   def c(n):\n       return \"a\" * n\n\n   def d(n):\n       return \"a\" * n\n\n   a(100000)\n\nThis code allocates memory from the system allocator in just 2 places:\n``c()``, and ``d()``. This is how a flame graph (with the root at the\nbottom) looks:\n\n.. image:: _static/images/simple_example.png\n\nHere you can see that ``a()`` called ``b()`` and that ``b()`` called\n``c()`` and ``d()``, which in turn did some allocations. As the boxes of\n``c()`` and ``d()`` are of the same width, you know that both allocated\nthe same amount of memory.\n\nA more complete example\n-----------------------\n\n.. code:: python\n\n   def a(n):\n       return [b(n), h(n)]\n\n   def b(n):\n       return c(n)\n\n   def c(n):\n       missing(n)\n       return d(n)\n\n   def missing(n):\n       return \"a\" * n\n\n   def d(n):\n       return [e(n), f(n), \"a\" * (n // 2)]\n\n   def e(n):\n       return \"a\" * n\n\n   def f(n):\n       return g(n)\n\n   def g(n):\n       return \"a\" * n * 2\n\n   def h(n):\n       return i(n)\n\n   def i(n):\n       return \"a\" * n\n\n   a(100000)\n\nThis code allocates memory from the system allocator in 5 places:\n``d()``, ``e()``, ``g()``, ``i()`` and ``missing()``. The associated\nflame graph looks like this:\n\n.. image:: _static/images/complex_example.png\n\nThe top edge shows that function ``g()`` allocates the most memory,\n``d()`` is wider, but its exposed top edge is smaller, which means that\n``d()`` itself allocated less memory than the one allocated by the\nfunctions called by it. Functions including ``b()`` and ``c()`` do\nnot allocate memory themselves directly; rather, the functions they\ncalled did the allocating.\n\nFunctions beneath ``g()`` show its ancestry: ``g()`` was called by\n``f()``, which was called by ``d()``, and so on.\n\nVisually comparing the widths of functions ``b()`` and ``h()`` shows\nthat the ``b()`` code path allocated about four times more than ``h()``.\nThe actual functions that did the allocations in each case were their\nchildren.\n\nA major fork in the code paths is visible where ``a()`` calls ``b()``\nand ``h()``. Understanding why the code does this may be a major clue to\nits logical organization. This may be the result of a conditional (if\nconditional, call ``b()``, else call ``h()``) or a logical grouping of\nstages (where ``a()`` is processed in two parts: ``b()`` and ``h()``).\nIn our case we know it's the second case, as ``a()`` is creating a list\nwith the result of ``b()`` and ``h()``.\n\nIf you look carefully you can notice that ``missing()`` allocates\nmemory, but it does not appear in the flame graph. This is because at\nthe time the largest memory peak was reached (when ``a()`` returned) the\nmemory allocated by ``missing()`` didn't contribute at all to the total\namount of memory. This is because the memory allocated by ``missing()``\nis deallocated as soon as the call ends.\n\nWith this information, we know that if you need to choose a place to start\nlooking for optimizations, you should start looking at ``g()``, then\n``e()`` and then ``i()`` (in that order) as these are the places that\nallocated the most memory when the program reached its maximum. Of\ncourse, the actual optimization may be done in the callers of these\nfunctions, but you have a way to start understanding where to optimize.\n\nNon-relevant frame hiding\n-------------------------\n\nThe flame graph exposes a button to show or hide frames which might be\ndistracting when interpreting the results, either because they were\ninjected by Memray or because they are low-level implementation\ndetails of CPython. By default, frames tagged as irrelevant are\nhidden. You can reveal them by unchecking the *Hide Irrelevant Frames*\ncheckbox:\n\n.. image:: _static/images/non_relevant_checkbox.png\n    :align: center\n\nNote that allocations in these frames will still be accounted for\nin parent frames, even if they're hidden.\n\n.. _memory-leaks-view:\n\nMemory Leaks View\n-----------------\n\nWhen generating flame graphs, the ``--leaks`` option can be specified\nto get information for memory that was leaked during the tracking\n(i.e. allocated after tracking started and not deallocated by the time\ntracking ended).\n\n.. important::\n\n    The Python allocator doesn't necessarily release memory to the system\n    when Python objects are deallocated and these can still appear as\n    \"leaks\". When you use the ``--leaks`` option, you should usually\n    also run your application with the ``PYTHONMALLOC=malloc``\n    environment variable set. See our documentation on :doc:`python\n    allocators <python_allocators>` for details.\n\n.. _split-threads-view:\n\nSplit-Threads View\n------------------\n\nWhen generating flame graphs, the ``--split-threads`` option can be\nspecified to get thread-specific filtering on the flame graph.\n\nIf ``--split-threads`` is not specified, thread information is not\ndisplayed on the flame graph. Instead, allocations occurring at the same\nsource location across different threads are grouped together. However,\nif ``--split-threads`` is used, the allocation patterns of individual\nthreads can be analyzed.\n\nWhen opening the report, the same merged thread view is presented, but\na new \"Filter Thread\" dropdown will be shown. This can be used to\nselect a specific thread to display a flame graph for that one thread:\n\n.. image:: _static/images/filter_thread_dropdown.png\n\nTo go back to the merged view, the \"Reset\" entry can be used in the\ndropdown menu.\n\nNote that the root node (displayed as **<root>**) is always present\nand is displayed as thread 0.\n\n.. _inverted flame graphs:\n\nInverted flame graphs\n---------------------\n\nIn a normal flame graph, the children of any given node are the functions\ncalled by that node, so the children of the root are thread entry points, and\nleaf nodes are functions that allocated memory but did not call any functions\nthat allocated memory. This means that, if multiple distinct call stacks led to\nthe same function allocating memory, there will be several leaf nodes for that\nsame function (one per distinct call stack by which it was reached).\n\nMemray also supports generating inverted flame graphs. In an inverted flame\ngraph, the children of any given node are the functions that called that node,\ninstead of the functions called by that node. This means that every function\nthat allocated memory is a child of the root node, and the leaf nodes are\nthread entry points. If one thread entry point led to multiple distinct\nallocations, there will be several leaf nodes for that same entry point (one\nper distinct call stack by which an allocation was reached from it).\n\nThe inverted flame graph is very helpful in analyzing where memory is being\nspent in aggregate. If a function that allocates memory is called from multiple\nplaces, in the normal flame graph it will show up multiple times in the leaves,\nbut in the inverted flame graph, all calls to one function will be aggregated\nand you'll see the total amount allocated by it in one place.\n\nYou can supply the ``--inverted`` option when generating a flame graph to ask\nMemray to produce an inverted flame graph.\n\nSimple inverted flame graph example\n-----------------------------------\n\n.. code:: python\n\n  def a():\n      return 1000000 * \"a\"\n\n  def a1():\n      return 1000000 * \"a\"\n\n  def b():\n      return a()\n\n  def c():\n      return b()\n\n  def d():\n      return b()\n\n  def f():\n      return g()\n\n  def e():\n      return g()\n\n  def g():\n      return c()\n\n  def main():\n      a = a1()\n      x = d()\n      y = e()\n      z = f()\n      return (x,y,z,a)\n\n  main()\n\n\nThis code allocates memory from the system allocator in just 2 places: ``a()``,\nand ``a1()``. This is how the normal frame graph looks:\n\n.. image:: _static/images/normal_flamegraph_for_inverted_example.png\n\nHere you can see that ``a()`` allocated memory three times when it was called\nfrom ``b()``, and ``a1()`` allocated memory when it was called from ``main()``.\n\nIf you generate the inverted flame graph with ``--inverted``, you'll instead\nsee something like:\n\n.. image:: _static/images/inverted_flame_graph_for_inverted_example.png\n\nHere you can see that we have ``return 1000000 * \"a\"`` two times at the root.\nThe block for one of those calls is three times wider than the other because\n``a()`` was called three times from ``b()``, while ``a1()`` was called only\nonce from ``main()``.\n\n.. _temporal flame graphs:\n\nTemporal Flame Graphs\n---------------------\n\nAs noted above, the snapshots generated by ``memray flamegraph`` normally show\nyou only a single point in time. By default, that's the point when the\nprocess's heap memory usage was highest. If you provide the ``--leaks`` option,\nit instead shows the point when tracking ended, so that you can inspect what\nwas still allocated at that point.\n\nIf the ``--temporal`` option is provided, ``memray flamegraph`` will create\na unique type of flame graph that we call a \"temporal flame graph\". In this\nmode, the flame graph can show you not just one point in time, but instead the\nusage over time (with approximately 10 millisecond granularity by default).\n\nA temporal flame graph includes a chart of the process's memory usage over time\nat the top of the page, and two sliders.\n\n.. image:: _static/images/temporal_high_water_mark_controls.png\n\nIf you don't use the ``--leaks`` option, the temporal flame graph will show you\ndata about the point in your chosen time range where heap memory usage was at\nits highest. Because the sliders are initially on the two extreme ends, it\nstarts off showing you exactly what the non-temporal report would: the moment\nduring tracking when the highest amount of heap memory was used. Moving the\nleft slider lets you ignore any high water mark that happened before it, and\nmoving the right slider lets you ignore any high water mark that happened after\nit. You can use these to focus in on what your process's heap memory usage was\nat any point during its run. The particular time slice within your chosen\nwindow where Memray found the high water mark is highlighted, though you might\nnot be able to see it unless you zoom in enough that a 10 millisecond time\nslice is wide enough.\n\nIf you use the ``--leaks`` option, the temporal flame graph will show you\nallocations performed within the time window you select and not freed by the\nend of it. Because the sliders are initially on the two extreme ends, it starts\noff showing you exactly what the non-temporal leaks report would: allocations\nperformed at any point after tracking started and not freed before tracking\nended. Moving the left slider lets you ignore allocations made before the point\nyou select. Moving the right slider lets you look for allocations that hadn't\nbeen freed as of an arbitrary point in time, rather than only seeing ones that\nweren't freed before tracking stopped.\n\nThese temporal reports can be used to gain fine grained insight into how your\nprocess was using memory at any point during its run, which can be invaluable\nfor understanding its memory usage patterns.\n\n.. note::\n\n    Temporal flame graphs contain much more data than the default non-temporal\n    flame graphs, so they're slower to generate, and the generated HTML files\n    are also larger. They can't be generated from :ref:`aggregated capture\n    files <aggregated capture files>`, which don't contain the necessary data\n    about allocations over time. They also can't be used for finding\n    :doc:`temporary allocations </temporary_allocations>`.\n\nYou can see an example of a temporal flame graph\n`here <_static/flamegraphs/memray-flamegraph-fib.html>`_.\n\nConclusion\n----------\n\nFlame graphs are effective visualization tools for a memory snapshot of\na program. They give an insightful visual map for the execution of\nPython code and allow navigating areas of interest, letting you\nidentify where to start looking for improvements. Unlike other code-path\nvisualizations such as acyclic graphs, flame graphs convey information\nintuitively using line lengths and can handle large-scale profiles,\nwhile usually remaining readable on one screen.\n\nBasic Usage\n-----------\n\nThe general form of the ``flamegraph`` subcommand is:\n\n.. code:: shell\n\n    memray flamegraph [options] <results>\n\nThe only argument the ``flamegraph`` subcommand requires is the capture file\npreviously generated using :doc:`the run subcommand <run>`.\n\nThe output file will be named ``memray-flamegraph-<input file name>.html``\nunless the ``-o`` argument was used to override the default name.\n\nReference\n---------\n\n.. argparse::\n    :ref: memray.commands.get_argument_parser\n    :path: flamegraph\n    :prog: memray\n\n    --leaks : @replace\n        Enables :ref:`memory-leaks-view`, where memory that was not deallocated is displayed, instead of peak memory\n        usage.\n\n    --split-threads : @replace\n        Enables :ref:`split-threads-view`, where each thread can be displayed separately. Allocations on the same source\n        line across different threads are not merged, if this flag is passed.\n"
  },
  {
    "path": "docs/getting_started.rst",
    "content": "Getting started\n===============\n\nInstallation\n------------\n\nMemray can easily be installed from PyPI.\n\nPyPI\n~~~~\n\nWhen installing Memray with ``pip`` you need to install it with the\nPython interpreter you intend to run your profiled application with. In\nthis case example we're installing it for use with Python 3.9:\n\n.. code:: shell\n\n    python3.9 -m pip install memray\n\nUsing the CLI\n-------------\n\nYou can invoke Memray the following way:\n\n.. code:: shell\n\n  python3.9 -m memray\n\nOr alternatively through the version-qualified ``memrayX.Y`` script:\n\n.. code:: shell\n\n  memray3.9\n\nYou can also invoke Memray without version-qualifying it:\n\n.. code:: shell\n\n  memray\n\nThe downside to the unqualified ``memray`` script is that it's not immediately\nclear what Python interpreter will be used to execute Memray. If you're using\na virtual environment that's not a problem because you know exactly what interpreter is\nin use, but otherwise you need to be careful to ensure that ``memray`` is\nrunning with the interpreter you meant to use.\n\nProfiling with Memray should be done in two steps:\n\n1. Run the application to track allocations and deallocations and save the results\n2. Generate the desired report from the captured results\n\nRunning the Analysis\n--------------------\n\nTo run memray on the ``example.py`` script, use :doc:`the run subcommand <run>`.\n\n.. code:: shell\n\n  memray3.9 run example.py\n\nThis will execute the script and track its memory allocations, displaying the name of the file where results are being recorded with a message like:\n\n.. code:: text\n\n  Writing profile results into memray-example.py.4131.bin\n\nGenerating a Flame Graph\n------------------------\n\nTo generate a flame graph displaying memory usage across the application, we can run ``memray flamegraph`` and specify\nthe results file:\n\n.. code:: shell\n\n  memray3.9 flamegraph memray-example.py.4131.bin\n\nThis will generate the ``memray-flamegraph-example.py.4131.html`` file in the current directory. See the :doc:`flamegraph`\ndocumentation which explains how to interpret flame graphs.\n\nNext Steps\n----------\n\nThe \"Hands-on Tutorial\" section of our sidebar includes :doc:`a set of lessons <tutorials/index>` you can use to\npractice working with Memray by debugging example Python applications with surprising memory allocation behavior. You\ncan also try Memray out on our :doc:`example applications <examples/README>`.\n\nIf you instead want to jump directly into debugging one of your own applications, the \"Concepts\" section of our sidebar\ngives background information to help you use Memray more effectively. Reading about :doc:`the run subcommand <run>` will\ntell you what options to use for debugging memory leaks, or for seeing the native stack traces corresponding to\nallocations. Interpreting the generated memory profiles will be much easier if you understand :doc:`the Python\nallocators <python_allocators>` as well as :doc:`some general memory concepts <memory>`.\n\nIf you find any bugs, you can `file a bug report`_. If you aren't sure whether something is a bug or expected behavior,\nor if you want to suggest an idea or discuss things with the maintainers, you should `start a discussion`_ instead.\n\nGood luck, and happy debugging!\n\n.. _file a bug report: https://github.com/bloomberg/memray/issues/new?&labels=bug&template=---bug-report.yaml\n.. _start a discussion: https://github.com/bloomberg/memray/discussions/new/choose\n"
  },
  {
    "path": "docs/index.rst",
    "content": ".. toctree::\n   :hidden:\n\n   overview\n   getting_started\n\n.. toctree::\n   :hidden:\n   :caption: Hands-on Tutorial\n\n   tutorials/index\n   tutorials/1\n   tutorials/2\n   tutorials/3\n   tutorials/additional_features\n\n.. toctree::\n   :hidden:\n   :caption: Concepts\n\n   run\n   python_allocators\n   memory\n   temporary_allocations\n   attach\n   native_mode\n   examples/README\n   api\n   jupyter_magic\n   performance\n\n.. toctree::\n   :hidden:\n   :caption: Reporters\n\n   live\n   summary\n   flamegraph\n   table\n   tree\n   stats\n   transform\n\n.. toctree::\n   :hidden:\n   :caption: Project Information\n\n   supported_environments\n   changelog\n   licenses\n"
  },
  {
    "path": "docs/jupyter_magic.rst",
    "content": ".. _Jupyter integration:\n\nJupyter Integration\n===================\n\nWe provide an IPython extension that adds a new Jupyter cell magic. This lets\nyou create Memray flame graphs directly in Jupyter notebooks.\n\nmemray_flamegraph\n-----------------\n\nTo load our IPython plugin, you simply need to run::\n\n    %load_ext memray\n\nOnce it's loaded, you'll have access to the ``%%memray_flamegraph`` cell magic.\nYou can fill a Jupyter cell with ``%%memray_flamegraph`` on its own line,\nfollowed by some code whose memory usage you want to profile. Memray will run\nthat cell's code, tracking its memory allocations, and then display a flame\ngraph directly in Jupyter for you to analyze.\n\nIt's also possible to provide arguments on the ``%%memray_flamegraph`` line.\nFor instance, ``%%memray_flamegraph --trace-python-allocators --leaks`` would\nlet you look for memory not freed by the code in the cell::\n\n    %%memray_flamegraph --trace-python-allocators --leaks\n    def a():\n        return \"a\" * 10_000\n\n    def bc():\n        return \"bc\" * 10_000\n\n    x = a() + bc()\n\nArguments\n---------\n\n.. argparse::\n   :ref: memray._ipython.flamegraph.argument_parser\n   :prog: %%memray_flamegraph\n"
  },
  {
    "path": "docs/licenses.rst",
    "content": "Licenses\n========\n\nMemray utilizes several other open source libraries under the hood. These are\nthe licenses of those libraries.\n\nlibbacktrace\n------------\n\n.. code-block:: text\n\n    Copyright (C) 2012-2016 Free Software Foundation, Inc.\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions are\n    met:\n\n        (1) Redistributions of source code must retain the above copyright\n        notice, this list of conditions and the following disclaimer.\n\n        (2) Redistributions in binary form must reproduce the above copyright\n        notice, this list of conditions and the following disclaimer in\n        the documentation and/or other materials provided with the\n        distribution.\n\n        (3) The name of the author may not be used to\n        endorse or promote products derived from this software without\n        specific prior written permission.\n\n    THIS SOFTWARE IS PROVIDED BY THE AUTHOR \"AS IS\" AND ANY EXPRESS OR\n    IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n    DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,\n    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n    SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n    STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\n    IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n    POSSIBILITY OF SUCH DAMAGE.\n\nlz4_stream\n----------\n\n.. code-block:: text\n\n    Copyright (c) 2015, Kasper Laudrup <laudrup@stacktrace.dk>\n    All rights reserved.\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions are\n    met:\n\n    1. Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n\n    2. Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n\n    3. Neither the name of the copyright holder nor the names of its\n    contributors may be used to endorse or promote products derived from\n    this software without specific prior written permission.\n\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n    \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n    HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nbootstrap\n---------\n\n.. code-block:: text\n\n    The MIT License (MIT)\n\n    Copyright (c) 2011-2025 The Bootstrap Authors\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\nd3\n--\n\n.. code-block:: text\n\n    Copyright 2010-2023 Mike Bostock\n\n    Permission to use, copy, modify, and/or distribute this software for any purpose\n    with or without fee is hereby granted, provided that the above copyright notice\n    and this permission notice appear in all copies.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\n    REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND\n    FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\n    INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS\n    OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER\n    TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF\n    THIS SOFTWARE.\n\nd3-flame-graph\n--------------\n\n.. code-block:: text\n\n                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"{}\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright {yyyy} {name of copyright owner}\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n\nd3-scale-chromatic\n------------------\n\n.. code-block:: text\n\n    Copyright 2010-2024 Mike Bostock\n\n    Permission to use, copy, modify, and/or distribute this software for any purpose\n    with or without fee is hereby granted, provided that the above copyright notice\n    and this permission notice appear in all copies.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\n    REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND\n    FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\n    INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS\n    OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER\n    TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF\n    THIS SOFTWARE.\n\n    Apache-Style Software License for ColorBrewer software and ColorBrewer Color Schemes\n\n    Copyright 2002 Cynthia Brewer, Mark Harrower, and The Pennsylvania State University\n\n    Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n    this file except in compliance with the License. You may obtain a copy of the\n    License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing, software distributed\n    under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR\n    CONDITIONS OF ANY KIND, either express or implied. See the License for the\n    specific language governing permissions and limitations under the License.\n\n@floating-ui/dom\n----------------\n\n.. code-block:: text\n\n    The MIT License (MIT)\n    Copyright (c) 2021 Floating UI contributors\n\n    Permission is hereby granted, free of charge, to any person obtaining\n    a copy of this software and associated documentation files (the\n    \"Software\"), to deal in the Software without restriction, including without\n    limitation the rights to use, copy, modify, merge, publish, distribute,\n    sublicense, and/or sell copies of the Software, and to permit persons to\n    whom the Software is furnished to do so, subject to the following\n    conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n    DEALINGS IN THE SOFTWARE.\n\ndatatables.net and datatables.net-bs4\n-------------------------------------\n\n.. code-block:: text\n\n    The MIT License (MIT)\n\n    Copyright SpryMedia Limited and other contributors\n    http://datatables.net\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\njquery\n------\n\n.. code-block:: text\n\n    Copyright OpenJS Foundation and other contributors, https://openjsf.org/\n\n    Permission is hereby granted, free of charge, to any person obtaining\n    a copy of this software and associated documentation files (the\n    \"Software\"), to deal in the Software without restriction, including\n    without limitation the rights to use, copy, modify, merge, publish,\n    distribute, sublicense, and/or sell copies of the Software, and to\n    permit persons to whom the Software is furnished to do so, subject to\n    the following conditions:\n\n    The above copyright notice and this permission notice shall be\n    included in all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\n    LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\n    OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\n    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nplotly.js-dist-min\n------------------\n\n.. code-block:: text\n\n    MIT License\n\n    Copyright (c) 2016-2024 Plotly Technologies Inc.\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\npopper.js\n---------\n\n.. code-block:: text\n\n    MIT License\n\n    Copyright (c) 2021 Floating UI contributors\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in all\n    copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n    SOFTWARE.\n"
  },
  {
    "path": "docs/live.rst",
    "content": "Live Reporting\n==============\n\nOverview\n--------\n\nMemray supports presenting a \"live\" view for observing the heap memory usage of a running Python program.\nThis provides insight into how memory is allocated as the program executes.\n\nIt is especially helpful for investigating the behavior of a program that has different allocation patterns during\ndifferent stages of the program's execution. It lets you see what the peak heap usage has been and how much memory is\nbeing allocated by various parts of the program. The information is presented in a tabular format, showing how much of\nthe in-use memory each function directly allocated (\"own memory\"), how much was cumulatively allocated by that function\nand everything it called (\"total memory\"), and the cumulative count of not yet freed allocations performed by that\nfunction and everything it called (\"allocation count\").\n\nUsage\n-----\n\nTo use live mode, you can specify the program to be profiled in live mode using ``run --live``:\n\n.. code:: shell-session\n\n  $ memray run --live application.py\n\nImmediately Memray will start your process in the background and will connect a TUI to it in the foreground. The TUI will\ndisplay the current high watermark of the heap every time it takes a snapshot, in a tabular format.\n\n.. image:: _static/images/live_running.png\n\nThis view presents the following information:\n\n- What the PID is of the running process.\n- What command was used to invoke the program.\n- The current heap size and the peak heap size seen so far.\n- How long the program has been running.\n- How many snapshots of the memory (referred to as samples) have been presented.\n- A plot of the heap size over time.\n\nOnce the program has exited, there will be a message presented in the live view, stating that \"Remote has disconnected\".\n\n.. image:: _static/images/live_disconnected.png\n\nSorting results\n---------------\n\nThe results are displayed in descending order of total memory allocated by a function and the subfunctions called by\nit. You can change the ordering with the following keyboard shortcuts:\n\n- t (default): Sort by total memory\n- o: Sort by own memory\n- a: Sort by allocation count\n\nIn most terminals you can also click the \"Sort by Total\", \"Sort by Own\", and \"Sort by Allocations\" buttons on the\nfooter.\n\nThe sorted column's heading is underlined.\n\nViewing different threads\n-------------------------\n\nBy default, the ``live`` command will present allocations from all of the program's threads. You can look at individual\nthreads of the program by first pressing ``m`` (to disable thread merging), and then pressing the greater than and less\nthan keys, ``<`` and ``>``, to switch between threads. In most terminals you can also click the \"Unmerge Threads\",\n\"Previous Thread\", and \"Next Thread\" buttons on the footer.\n\n.. image:: _static/images/live_different_thread.png\n\nUsing with native tracking\n--------------------------\n\nIt is possible to use :ref:`native tracking` along with the live mode. This can be achieved by passing ``--native``\nto the ``run`` command.\n\n.. code:: shell-session\n\n  $ memray run --live --native application.py\n\nRemote mode\n-----------\n\nRemote mode allows you to run the program to be traced in one process and the tui in another. To use remote mode, you can\nspecify the program to be profiled in live mode using ``run --live-remote``:\n\n.. code:: shell-session\n\n  $ memray run --live-remote application.py\n  Run 'memray live <port>' in another shell to see live results\n\nAs you can see, Memray is now waiting on a connection to the live tracking server. You can now attach to\nthe server using running the ``live`` command in a separate shell.\n\n.. code:: shell-session\n\n  $ # Run this in a different shell:\n  $ memray live <port>\n\nThis command will connect to the server that was started in the previous command, when given the requested port number.\nOnce the connection is established, the program will start executing. All memory allocations and deallocations\nthroughout the program will be tracked.\n\nThe program being tracked will present its output on the shell running the ``run --live-remote`` command. In the shell running\nthe ``live`` command, information about the program will be presented with the regular TUI of live mode.\n\n\nUsing a different port\n----------------------\n\nIt is possible to make ``run --live-remote`` start the server on a user-specified port, using the ``--live-port`` argument.\n\n.. code:: shell-session\n\n  $ memray run --live-remote --live-port 12345 application.py\n  Run 'memray live 12345' in another shell to see live results\n\n.. important::\n\n  Due to the syntax of the command line arguments of memray, make sure that you pass any options intended for the\n  ``run`` command *before* your script/module. Otherwise, they will be treated as arguments for the script and will not\n  be used by Memray.\n\n  For example, the following invocation will pass ``--live-port 12345`` to ``application.py``,\n  instead of having it be used by ``memray run``:\n\n  .. code:: shell-session\n\n    $ memray run --live-remote application.py --live-port 12345\n    Run 'memray live 60125' in another shell to see live results\n"
  },
  {
    "path": "docs/manpage.rst",
    "content": ":orphan:\n\nOverview\n========\n\n.. argparse::\n   :ref: memray.commands.get_argument_parser\n   :manpage:\n   :nosubcommands:\n\n   Memray can track memory allocations in Python code, in native extension modules, and in the Python\n   interpreter itself. It can generate several different types of reports to help you analyze the captured\n   memory usage data. While commonly used as a CLI tool, it can also be used as a library to perform more\n   fine-grained profiling tasks.\n\n   Most commonly you will use the ``memray run`` subcommand to create a capture file, and then use a reporter\n   like the ``memray flamegraph`` subcommand to analyze it.\n\n   .. note::\n\n       This manual page only documents usage of the Memray subcommands that can be invoked from the command line.\n       See `<https://bloomberg.github.io/memray/overview.html>`_ for the full Memray documentation, which\n       includes advice for interpreting Memray reports, example programs, API documentation, information about\n       integrating Memray into Jupyter notebooks and pytest test suites, explanations to help you understand how\n       Python uses memory and how Memray gathers information about memory usage, and more.\n\nRUN SUB-COMMAND\n---------------\n\n.. argparse::\n   :ref: memray.commands.get_argument_parser\n   :path: run\n   :nodefaultconst:\n   :noepilog:\n\nFLAMEGRAPH SUB-COMMAND\n----------------------\n\n.. argparse::\n   :ref: memray.commands.get_argument_parser\n   :path: flamegraph\n   :nodefaultconst:\n   :noepilog:\n\nTABLE SUB-COMMAND\n-----------------\n\n.. argparse::\n   :ref: memray.commands.get_argument_parser\n   :path: table\n   :nodefaultconst:\n   :noepilog:\n\nLIVE SUB-COMMAND\n----------------\n\n.. argparse::\n   :ref: memray.commands.get_argument_parser\n   :path: live\n   :nodefaultconst:\n   :noepilog:\n\nTREE SUB-COMMAND\n----------------\n\n.. argparse::\n   :ref: memray.commands.get_argument_parser\n   :path: tree\n   :nodefaultconst:\n   :noepilog:\n\nPARSE SUB-COMMAND\n-----------------\n\n.. argparse::\n   :ref: memray.commands.get_argument_parser\n   :path: parse\n   :nodefaultconst:\n   :noepilog:\n\nSUMMARY SUB-COMMAND\n-------------------\n\n.. argparse::\n   :ref: memray.commands.get_argument_parser\n   :path: summary\n   :nodefaultconst:\n   :noepilog:\n\nSTATS SUB-COMMAND\n-----------------\n\n.. argparse::\n   :ref: memray.commands.get_argument_parser\n   :path: stats\n   :nodefaultconst:\n   :noepilog:\n\nTRANSFORM SUB-COMMAND\n---------------------\n\n.. argparse::\n   :ref: memray.commands.get_argument_parser\n   :path: transform\n   :nodefaultconst:\n   :noepilog:\n\nATTACH SUB-COMMAND\n------------------\n\n.. argparse::\n   :ref: memray.commands.get_argument_parser\n   :path: attach\n   :nodefaultconst:\n   :noepilog:\n\nDETACH SUB-COMMAND\n------------------\n\n.. argparse::\n   :ref: memray.commands.get_argument_parser\n   :path: detach\n   :nodefaultconst:\n   :noepilog:\n"
  },
  {
    "path": "docs/memory.rst",
    "content": ".. _memory overview:\n\nMemory overview\n===============\n\nHeap memory vs resident memory\n------------------------------\n\nWhen you are profiling memory usage, you will often see two different metrics:\nheap memory and resident memory.\n\nResident memory corresponds to the memory that is allocated currently in your\nmain memory or RAM. Generally speaking, programs will store most of the memory\nthey are using in main memory but there are some caveats you need to be aware of\nif you want to make sense of how your programs are using memory. Resident memory\nis a metric that is **not independent** of the other programs that are running\nconcurrently and what's happening in your machine. This means that **two\nidentical runs of your program can have very different resident memory\nmeasurements**.  If the OS determines that other programs or\ntasks have higher priority than the one you are analyzing, it may move some of the\nmemory used by the program to swap space. This means that resident memory usage\nin your program may decrease (and increase later) even if you don't free or\nallocate any memory yourself.\n\nThis makes resident memory a tricky metric to make sense of. On the one hand it is a\ngood indicator of what may be causing your machine to run out of memory.\nUltimately this is the memory that is limited by the amount of RAM (and\nswap space) you have. But on the other hand the value of resident memory\nassociated with a given program is dependent on all the other programs that are\nrunning concurrently so it may be a bit difficult to properly diagnose why it\ndecreases or increases.\n\nMemory is lazily allocated\n--------------------------\n\nWhat makes it even more complicated to properly relate heap memory and resident\nmemory is that memory is lazily allocated by the OS. For example, if you call\none the system allocator APIs (``malloc`` for example), it may return instantly\nwithout actually allocating memory at all. It still will give you a pointer to a\nchunk of memory that you can use, but memory will only be allocated when you write to that pointer.\n``malloc`` promises you the memory chunk but you only get it for real when you\nreally need it. This means that heap memory will increase as soon as the\nallocator API is called but resident memory will only increase once you actually\nwrite to that memory.\n\nFor instance, consider this code: ::\n\n    import time\n    import numpy\n    time.sleep(1)\n    big_array = numpy.empty(1_000_000)\n    time.sleep(1)\n    big_array[:] = 42.0\n    time.sleep(1)\n\nIf you run ``memray`` against this code and generate a flamegraph, you will see\nthe following plot:\n\n.. image:: _static/images/rss_vs_heap.png\n\nAs you can see in the plot, the line for the heap size increases first\n(corresponding to the call to ``numpy.empty``) but the resident size does not\nincrease inmediately. Instead, the resident size only increases after we have\npopulated the whole array with floating point numbers. Is only at this moment\nwhen the OS will actually allocate the necessary memory pages to satisfy our\ninitial request. Notice that this happens when memory is **written** to the\narray, so a memory profiler **won't be able to tell you what makes the resident\nsize grow** as it doesn't have visibility into when pages are actually assigned.\n\nMemory is not freed immediately\n-------------------------------\n\nAnother thing that makes difficult to relate heap memory and resident memory is\nthat memory is not freed immediately after it is no longer needed. This is\nbecause the system allocator may not release the memory to the OS when it is no\nlonger needed. This means that once you call a deallocator API (``free`` for\nexample), the implementation may not free the memory for real until later. This means\nthat you may see the heap size decrease but the resident memory size may\nnot decrease yet.\n\nFor instance, consider this code: ::\n\n    import time\n    import numpy\n    time.sleep(1)\n    big_array = numpy.empty(1_000_000)\n    time.sleep(1)\n    big_array[:] = 42.0\n    time.sleep(1)\n    del big_array\n    time.sleep(1)\n\nIf you run ``memray`` against this code and generate a flamegraph, you will see the following the following plot:\n\n.. image:: _static/images/rss_vs_heap_no_free.png\n\nAs you can see in the plot, the line for the heap size decreases after we delete\nthe array (corresponding to the call to ``del``) but the resident size does not\ndecrease inmediately. Instead, the resident size will only decrease (not shown\nin this plot) after the system allocator determines that it is a good idea to free\nthe memory pages.  Notice that this happens when pages are released, so a\nmemory profiler **won't be able to tell you what makes the resident size\ndecrease** as it doesn't have visibility when pages are actually unmapped.\n\nMemory is shared\n----------------\n\nAnother thing that makes it difficult to relate heap memory and resident memory is\nthat memory is shared. This means that the same memory pages can be used by\ndifferent processes. This happens for instance when you fork a process. When you\nfork a process, the child process will initially share the same memory pages with the\nparent process. This means that the resident memory size that the child process\nrequires will not increase until copy on write (COW) is triggered. You can read\nmore about COW in the `Wikipedia page <https://en.wikipedia.org/wiki/Copy-on-write>`_.\n\nMemory can be fragmented\n------------------------\n\nAnother thing that makes it difficult to relate heap memory and resident memory is\nthat memory can be fragmented. This means that the memory that is allocated by\nthe system allocator may be spread around the address space in different\nfragments. This means that the resident memory size will increase/decrease in\nunpredictable ways. This happens because the system allocator may not be able to\nreuse memory that has been freed before.\n\nMemory fragmentation results in seemingly unnecessary requests to the OS\nfor more memory. Even when the sum of the space already available for the memory\nallocator is large enough to satisfy a memory allocation request, it's possible\nno individual fragment (or set of contiguous fragments) is large enough to satisfy that\nmemory allocation request.  Memory fragmentation is caused by a combination of\nthe allocation strategy used by the allocator you are using, the sizes and\nalignments of the internal structures, and the memory allocation\nbehavior of your application.\n\nDetecting fragmentation is a very difficult task because it depends on the system\nallocator that you are using. If you are using GLIBC's ``malloc`` for example,\nyou can use the ``malloc_stats`` API to get information about the memory\nallocator. This API will give you information about the number of free chunks\nand the total size of the free chunks. If you see that the number of free chunks\nis large but the total size of the free chunks is small, then you may be\nsuffering from memory fragmentation. You can read more about this in the `man\npage <https://man7.org/linux/man-pages/man3/malloc_stats.3.html>`_.\n\nAlthough this API must be called from native code, you can use the `ctypes module <https://docs.python.org/3/library/ctypes.html>`_\nto call it from Python. For example, you can use the following code to call it from Python: ::\n\n    import ctypes\n    libc = ctypes.CDLL(\"libc.so.6\")\n    libc.malloc_stats.restype = None\n    libc.malloc_stats()\n\nAnother option is to use GLIBC's ``malloc_info`` API. This API will give you\ninformation about the memory allocator in a format that is easier to parse from\nprograms. As with the other API, you can use the `ctypes module <https://docs.python.org/3/library/ctypes.html>`_\nto call it from Python. ::\n\n    import ctypes\n\n    class MallInfo(ctypes.Structure):\n        _fields_ = [\n            (name, ctypes.c_int)\n            for name in (\n                \"arena\",\n                \"ordblks\",\n                \"smblks\",\n                \"hblks\",\n                \"hblkhd\",\n                \"usmblks\",\n                \"fsmblks\",\n                \"uordblks\",\n                \"fordblks\",\n                \"keepcost\",\n            )\n        ]\n\n\n    libc = ctypes.CDLL(\"libc.so.6\")\n    mallinfo = libc.mallinfo\n    mallinfo.argtypes = []\n    mallinfo.restype = MallInfo\n\n    info = mallinfo()\n    fields = [(name, getattr(info, name)) for name, _ in info._fields_]\n    print(\"Malloc info:\")\n    for name, value in fields:\n        print(f\"- {name}: {value}\")\n"
  },
  {
    "path": "docs/native_mode.rst",
    "content": "Symbolic information in native mode\n===================================\n\n.. highlight:: shell-session\n\n.. important::\n\n   For the best native mode experience, we recommend running your program on\n   Linux using an interpreter and libraries built with as much debugging\n   information as possible.\n\nWhen passing the ``--native`` flag to the :doc:`the run subcommand <run>`,\nMemray will collect information about the native call stack leading to each\nallocation, and it will dump it to the result file. This information is in\na raw form where every call is identified by a number called the \"instruction\npointer\" or \"program counter\". The instruction pointer is a number that helps\nrunning programs identify what CPU instruction needs to be executed next. After\nfetching each instruction the instruction pointer is incremented, and holds the\nmemory address of (\"points to\") the next instruction to be executed. Processors\nusually fetch instructions sequentially from memory, but control transfer\ninstructions change the sequence by placing a new value in the instruction\npointer. These include branches (sometimes called jumps), subroutine calls, and\nreturns. A transfer that is performed only if some condition is true allows the\ncomputer to follow a different sequence under different conditions.\n\nWhen creating reports, Memray needs to convert these instruction pointers into\nhuman readable information, like the function name, the file name where that\nfunction is defined, and the line number within that file corresponding to the\ninstruction. This process is known as **symbolification**.\n\nHow Memray resolves symbols\n---------------------------\n\nThere are two different approaches Memray uses to symbolify an instruction\npointer:\n\n* Use the `DWARF <https://dwarfstd.org/>`_ debugging information embedded in\n  the executable or shared library containing the instruction. This process\n  will provide function names, file names, and line numbers, and will also be\n  able to resolve inlined functions. This method is used whenever debugging\n  information is available.\n\n* Use the symbol table information embedded in the executable or shared library\n  containing the instruction. This is a suboptimal method that will **only**\n  provide function names, not file names or line numbers. It can also be\n  unreliable as the symbol table may not contain entries for every function.\n\n.. attention::\n\n   To reduce tracking overhead, Memray delays symbolification **until reports\n   are being generated**. This means that when a report is being generated,\n   Memray needs to read information from the interpreter executable that was\n   used to run the tracked application, and from the shared libraries that were\n   loaded into it. Reports must be generated **on the same machine that the\n   application ran on**, because the same versions of the interpreter and\n   shared libraries need to be available for inspection. Failing to do this\n   will result in symbolification errors or incorrect reports.\n\nIf Memray is able to resolve file names, line numbers, and inline functions,\nit can hide some of the Python interpreter's internal functions which don't add\nmuch information to the report. If there is no debug information available then\nthe produced flame graphs will look more noisy and be harder to read, because\nwe won't be able to reliably detect these uninteresting functions. In these\nimages you can compare two flame-graphs, one with debug information and one\nwithout debug information, produced from the same capture file:\n\n.. list-table::\n\n    * - .. figure:: _static/images/native_mode_no_debug.png\n\n           Flamegraph in native mode produced without debug information.\n\n      - .. figure:: _static/images/native_mode_debug.png\n\n           Flamegraph in native mode produced with debug information.\n\nYou can see that file names are reported as ``<unknown>`` and line numbers as\n``0`` when debugging information is not available.\n\nOn Linux, you can check whether your binaries have DWARF debug information\navailable by running::\n\n    $ readelf -S ./a.out | grep debug\n\nFor example, for checking if the Python interpreter has DWARF debug information\navailable::\n\n    $ readelf -S $(which python) | grep debug\n\n    [26] .debug_aranges    PROGBITS         0000000000000000  00001057\n    [27] .debug_info       PROGBITS         0000000000000000  00001087\n    [28] .debug_abbrev     PROGBITS         0000000000000000  000010de\n    [29] .debug_line       PROGBITS         0000000000000000  0000111a\n    [30] .debug_str        PROGBITS         0000000000000000  00001177\n    [31] .debug_macro      PROGBITS         0000000000000000  00003eb1\n\n\n.. _mac symbolification:\n\nSymbolification in macOS\n------------------------\n\n.. caution::\n\n    Because most macOS binaries for Python don't include debug\n    information, **reports produced in macOS can be much less accurate**.\n\nOn Mac OS X there was a decision to not have the linker include all of the\ndebug information into the executables and libraries it builds. Instead, the\ncompiler generates the DWARF debug information in the ``.s`` files, the\nassembler outputs it in the ``.o`` files, and the linker includes a \"debug map\"\nin the executable or shared library which tells debug info users where all of\nthe symbols were relocated during the link. There is a tool called ``dsymutil``\nthat can read the debug map, load the DWARF information from the ``.o`` files,\nrelocate all the addresses and then output a single binary with all the DWARF\ninformation at their final, linked addresses. This final binary is called\na ``dSYM`` bundle and is normally placed alongside every executable.\n\nThis process has some advantages, but unfortunately in the Python world neither\nredistributors of Python interpreters nor library maintainers generally package\ndebugging information with the binaries. This means that **most macOS binaries\ndon't have debug information inside**, so in general **native mode\nsymbolification will not work well** in macOS.\n\nMemray will fall back to symbol table analysis if it can't find any debug\ninformation in the binary, but when producing reports we won't be able to\nidentify where the different symbols came from, making flame graphs very\nverbose and hard to read.\n\nAdding debugging information to your native extension\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nIf you are debugging your own native extension, you can generate debug\ninformation that Memray can use by executing ``dsymutil`` on your shared object\n**while the object files used to generate the shared object still exist**. For\ninstance, for the Memray extension itself (the paths will be different for your\nown extension)::\n\n    $ # Sanity check: ensure that the object files are still around\n    $ dsymutil -s  src/memray/_memray.cpython-310-darwin.so | grep OSO | head -n 1\n    [  9431] 000d39a1 66 (N_OSO        ) 00     0001   0000000062fb8052 'memray/build/temp.macosx-12.5-arm64-cpython-310/src/memray/_memray.o'\n\n    $ ls memray/build/temp.macosx-12.5-arm64-cpython-310/src/memray/_memray.o\n    .rw-r--r-- 3.5M pgalindo3 16 Aug 12:32 memray/build/temp.macosx-12.5-arm64-cpython-310/src/memray/_memray.o\n\n    $ # Then generate a dSYM bundle with the debug information:\n    $ dsymutil src/memray/_memray.cpython-310-darwin.so\n\nThis will place a new file called ``_memray.cpython-310-darwin.dSYM`` in the\nsame directory as the original shared object. Once this file is in place,\nmemray will be able to leverage the debug information it contains.\n\nDebuginfod integration\n----------------------\n\nMemray can use `debuginfod <https://sourceware.org/elfutils/Debuginfod.html>`_\nto fetch debug information from remote servers on demand. This is useful\nbecause many Linux distributions don't ship debug information with their\nbinaries, so you can use debuginfod to download the debug information from\na server that does have it. Many modern Linux distributions have debuginfod\nintegration so you can take advantage of this with little to no effort.\n\nTo take advantage of debuginfod, you need two things:\n\n1. The ``debuginfod`` client library must be installed. This library allows you\n   to query debuginfod servers. It is available in most Linux distributions\n   (including Debian, Ubuntu, Fedora, Arch Linux, etc.) and can be installed\n   with your package manager. For example, in Debian/Ubuntu::\n\n       $ sudo apt install debuginfod\n\n   In Arch Linux::\n\n       $ sudo pacman -S debuginfod\n\n   In Fedora::\n\n      $ sudo dnf install elfutils-debuginfod\n\n2. The ``DEBUGINFOD_URLS`` environment variable must point to the debuginfod\n   server you want to use. This is a space separated list of URLs.\n   For example::\n\n       $ export DEBUGINFOD_URLS=\"https://debuginfod.archlinux.org/\"\n\n   .. tip::\n       You can also use https://debuginfod.elfutils.org/ which works as a\n       federated server and queries all available debuginfod servers.\n\n   Some modern Linux distributions set this variable by default when the\n   ``debuginfod`` client is installed, so you may not need to set this up.\n\nOnce the client is installed and the environment variable is set, Memray will\nautomatically use debuginfod to download debug information for the binaries it\nencounters when generating native mode reports. The first time that Memray uses\ndebuginfod to fetch debug information it will take a bit longer to generate the\nreport, but subsequent runs will be much faster because the debug information\ngets cached locally.\n\nIf you'd like to see progress diagnostics during downloads, set::\n\n    $ export DEBUGINFOD_PROGRESS=1\n\nIf you want to see exactly which network requests are being made and which\ncached files are used you can set ``$DEBUGINFOD_VERBOSE`` (warning: it is\n*very* verbose)::\n\n    $ export DEBUGINFOD_VERBOSE=1\n\nIf you want to limit download times and/or sizes you can set these variables::\n\n    $ export DEBUGINFOD_TIMEOUT=10       # seconds\n    $ export DEBUGINFOD_MAXSIZE=1000000  # bytes\n\nIf you never want to query a debuginfod server, clear the ``$DEBUGINFOD_URLS``\nenvironment variable::\n\n    $ unset DEBUGINFOD_URLS\n\nIf you have a local debuginfod cache that you'd like to use, but don't want to\nattempt any upstream debuginfod queries, set ``$DEBUGINFOD_URLS`` to something\nnon-empty but ineffective, such as ``/dev/null``.\n\n.. tip::\n    Clients automatically clean the cache of files not accessed in a while. You\n    may also remove the debuginfod cache directory\n    ``$HOME/.cache/debuginfod_client`` at any time to clear space.\n"
  },
  {
    "path": "docs/overview.rst",
    "content": "Overview\n--------\n\n.. image:: _static/images/logo.png\n\n.. image:: _static/images/output.png\n\nMemray is a memory profiler for Python. It can track memory allocations in Python code, in native extension\nmodules, and in the Python interpreter itself. It can generate several different types of reports to help you\nanalyze the captured memory usage data. While commonly used as a CLI tool, it can also be used as a library to\nperform more fine-grained profiling tasks.\n\n\nNotable features:\n\n- 🕵️‍♀️ Traces every function call so it can accurately represent the call stack, unlike sampling profilers.\n- ℭ Also handles native calls in C/C++ libraries so the entire call stack is present in the results.\n- 🏎 Blazing fast! Profiling causes minimal slowdown in the application. Tracking native code is somewhat slower, but this can be enabled or disabled on demand.\n- 📈 It can generate various reports about the collected memory usage data, like flame graphs.\n- 🧵 Works with Python threads.\n- 👽🧵 Works with native-threads (e.g. C++ threads in native extensions)\n\nMemray can help with the following problems:\n\n- Analyze allocations in applications to help discover the cause of high memory usage.\n- Find memory leaks.\n- Find hotspots in code which cause a lot of allocations.\n\n\n.. image:: _static/images/quotes.png\n   :align: center\n\n.. note::\n    Memray only works on Linux and MacOS, and cannot be installed on other platforms.\n"
  },
  {
    "path": "docs/performance.rst",
    "content": "Performance\n===========\n\nThis section contains an analysis of the overhead of running Memray over different\ntest cases and configurations. All these test cases come from the official Python performance\nsuite: `pyperformance <http://github.com/python/pyperformance>`_.\n\nEvery test is executed many times using the `perf <http://github.com/python/pyperf>`_ tool\nin a machine specifically tuned to obtain reproducible performance results. The machine uses\nisolated CPUs with fixed frequencies to run the benchmarks. You can read more about how the\nmachine is tuned for benchmarks in the `perf documentation about tuning a system\n<https://pyperf.readthedocs.io/en/latest/system.html>`_.\n\nThese purpose of these results are to give you an idea of the overhead of running Memray\nwith different options. Of course, these results will vary from machine to machine but they\ncan give you an approximation of what to expect.\n\nTest system\n-----------\n\n* OS: Arch Linux x86_64\n* Kernel: 6.1.2-arch1-1\n* Memory: 64GB (8x8GB) DDR4/3200mhz Quad Channel Memory\n* Disk: 512GB (1x512GB) Intel 760p M.2 PCIe NVMe SSD - 3230MB/s Read & 1625MB/s Write\n* CPU: Intel(R) Core™ i9-9980XE Extreme Edition Processor\n* Python: 3.10.9 (LTO + PGO)\n* Memray version: 1.5.0\n* Libunwind version: libunwind 1.6.2-2\n* Libz4 version: libz4 1.9.4-1\n* Libc version: glibc 2.36-6\n* Compiler version: gcc 12.2.0-1\n\nSystem state\n~~~~~~~~~~~~\n\n* CPU: use 2 logical CPUs: 17,35\n* Perf event: Maximum sample rate: 1 per second\n* ASLR: Full randomization\n* Linux scheduler: Isolated CPUs (2/36): 17,35\n* Linux scheduler: RCU disabled on CPUs (2/36): 17,35\n* CPU Frequency: 0-16,18-34=min=1200 MHz, max=3000 MHz; 17,35=min=max=3000 MHz\n* CPU scaling governor (intel_pstate): performance\n* Turbo Boost (intel_pstate): Turbo Boost disabled\n* IRQ affinity: Default IRQ affinity: CPU 0-16,18-34\n\n\nSource of the overhead\n----------------------\n\nThe overhead of running Memray comes from two places:\n\n- A `Python profile function <https://docs.python.org/3/library/sys.html#sys.setprofile>`_ implemented in\n  C++. This function is called every time a Python function is called or returns\n  and is used to register the function calls so Memray can reconstruct the\n  stack trace of every allocation. Although the overhead is very, very small, it\n  adds up. This means that the more your application calls Python\n  functions the bigger the overhead will be.\n- The allocation registering code. This is the main source of the overhead.\n  Every time your application makes a memory allocation or deallocation,\n  Memray needs to register it. This means that the more frequently your application\n  allocates memory, the bigger the overhead will be. Tracking Python allocators\n  will greatly increase this overhead because the Python allocator is used for\n  small, short lived objects which means that it's generally called with very high\n  frequency.\n\nResults\n-------\n\nThe following plots show the overhead of running Memray over different test\ncases using violin plots. Each row corresponds to the result of a given test.\nFor a given row, the continuos vertical line in the middle corresponds to the\n**mean** while the two dashed vertical vars at the left and right of the mean\ncorrespond to the **10% and 90% quantiles**.  The shaded area represents the\ndistribution of the data, with thicker areas indicating a higher density of data\npoints. The **ALL** row corresponds to the distribution of all the results across all the\nbenchmarks combined.\n\nDefault options\n~~~~~~~~~~~~~~~\n\nThe following results correspond to running Memray with the default options.\n\n.. image:: _static/images/plot_default_options.png\n   :align: center\n\nPython allocators\n~~~~~~~~~~~~~~~~~\n\nThe following results correspond to running Memray with ``--trace-python-allocators``.\n\n.. image:: _static/images/plot_python_allocators.png\n   :align: center\n\nNative traces\n~~~~~~~~~~~~~\n\nThe following results correspond to running Memray with ``--native``.\n\n.. image:: _static/images/plot_native.png\n   :align: center\n\nPython allocators + Native traces\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nThe following results correspond to running Memray with ``--native --trace-python-allocators``.\n\n.. image:: _static/images/plot_python_allocators_native.png\n   :align: center\n"
  },
  {
    "path": "docs/python_allocators.rst",
    "content": ".. _Python allocators:\n\nPython allocators\n=================\n\nPython has a layer of abstraction between code that allocates memory and the\nsystem allocator (malloc, free, realloc, etc). Although the system allocator is\nquite fast and efficient, it is still generic and is not tuned to the specific\nallocation patterns of the Python interpreter, especially those regarding small\nPython objects. To improve performance and reduce fragmentation, Python has\na specialized allocator that handles allocation of small objects and defers to\nthe system allocator for large ones. This allocator is called ``pymalloc``.\n\n\nHow ``pymalloc`` works\n----------------------\n\nRequests greater than 512 bytes are routed to the system's allocator. This\nmeans that even if ``pymalloc`` is active, it will only affect requests for 512\nbytes or less. For those small requests, the ``pymalloc`` allocator will\nallocate big chunks of memory from the system allocator and then subdivide\nthose big chunks.\n\n.. image:: _static/images/pymalloc.png\n   :align: center\n\n\n``pymalloc`` works with 3 hierarchical data structures:\n\n- Arenas: These are chunks of memory that ``pymalloc`` directly requests from\n  the system allocator using ``mmap``. Arenas are always a multiple of\n  4 kilobytes. Arenas are subdivided into pools of different types.\n- Pools: Pools contain fixed size blocks of memory. Each pool only contains\n  blocks of a single consistent size, though different pools have blocks of\n  different sizes. Pools are used to easily find, allocate, and free memory\n  blocks of a given size.\n- Blocks: These are the fundamental units of storage. Small allocation requests\n  to ``pymalloc`` are always satisfied by returning a pointer to a specific\n  block. This block can be bigger than what the allocation requested.\n\nWhen the user code is done with a block, it is marked as unused. When all\nblocks in a pool have been marked as unused, the pool is marked as unused. Only\nwhen all pools in an arena have been marked as unused can the arena be returned\nto the system allocator. This rarely happens.\n\nThe following table shows the relationship between the allocation request and\nthe actual block size that will be returned:\n\n================     =======================      ================\nAllocation request to block size\n------------------------------------------------------------------\nRequest in bytes     Size of allocated block      Size class index\n================     =======================      ================\n1-8                  8                            0\n9-16                 16                           1\n17-24                24                           2\n25-32                32                           3\n33-40                40                           4\n41-48                48                           5\n49-56                56                           6\n57-64                64                           7\n65-72                72                           8\n ...                 ...                          ...\n497-504              504                          62\n505-512              512                          63\n================     =======================      ================\n\nAs indicated before, any request for more than 512 bytes will be made directly\nusing the system allocator.\n\nHow does this affect memory profiling?\n--------------------------------------\n\nMemory profiling with ``pymalloc`` active can yield some surprising results.\nThis is because when a request for memory comes, ``pymalloc`` will try to reuse\nexisting memory that has previously been used for other Python objects. This\nhas two main consequences:\n\n- Requests for **small** amounts of memory that can be satisfied from an\n  existing arena won't result in a call to the system allocator and therefore\n  won't appear in the profiler reports at all.\n\n- Requests for **small** amounts of memory that can't be satisfied from an\n  existing arena will result in a new arena being allocated from the system\n  allocator, which will be shown as an ``mmap`` request whose size is\n  a multiple of 4 kilobytes.\n\nThis may look confusing, and you may wish to deactivate ``pymalloc`` when\nprofiling memory, but that is not necessarily a good idea. When your\napplication runs, it normally runs with ``pymalloc`` activated, which means\nthat any allocation patterns that you see when profiling with ``pymalloc``\nactivated correspond exactly to what your application will be doing.\n\n.. note::\n    If you are interested in why your application is using a lot of memory, you\n    usually want to profile it exactly how it is normally executed, so you\n    usually want ``pymalloc`` to be active.\n\nThere are some cases when ``pymalloc`` gets in the way, though. For instance,\nif you are hunting memory leaks using the ``--leaks`` option of some of the\n``memray`` reporters, then having ``pymalloc`` active during profiling makes\nthis task more difficult.\n\n.. note::\n    When hunting for memory leaks using the ``--leaks`` option, you want to\n    see every allocation and deallocation independently, so you usually want\n    ``pymalloc`` deactivated.\n\nBecause ``pymalloc`` may not release all memory to the system even if you have\nfinished using it, the profiler will incorrectly report it as leaked. You'll\nalso be misled about the size of the leak, since the size of the leaked\nallocation will be reported as the size of the arena (some multiple of\n4 kilobytes), rather than the size of the leaked object (never more than 512\nbytes). Also, if just one block owned by an arena is leaked, that will prevent\nthe arena from being returned to the system allocator, but you won't be able to\ntell which object was leaked, since a single arena can be used to satisfy many\nallocation requests from many places, and only the place where the arena was\ncreated by requesting more memory from the system will have been recorded.\n\n.. caution::\n    Note that running without ``pymalloc`` will result in **slower** executions\n    and **much bigger** report files, as many extra allocations will be seen.\n\nHow can I deactivate ``pymalloc``\n---------------------------------\n\nTo deactivate ``pymalloc`` you can set the ``PYTHONMALLOC=malloc`` environment\nvariable or execute Python with ``-Xdev``. Or, you can pass the\n``--trace-python-allocators`` flag to ``memray run`` so that, even though\n``pymalloc`` is still used, Memray sees every call to the ``pymalloc``\nallocator instead of only the ones where it needs to make a request to the\nsystem allocator.\n"
  },
  {
    "path": "docs/run.rst",
    "content": "The ``run`` subcommand\n======================\n\nThe ``run`` subcommand is used to launch a new Python process and track the memory allocations it\nperforms while it runs.\n\nBasic tracking\n--------------\n\nThe general form of the ``run`` subcommand is one of:\n\n.. code:: shell\n\n    memray run [options] file.py [args]\n    memray run [options] -m module [args]\n\nLike the Python interpreter itself, the ``run`` subcommand can take a path to a Python file to run,\nor the name of a Python module to run if you use the ``-m`` flag. While it runs, memory allocations\nand deallocations throughout the program are tracked. By default they are saved into a file with the\nfollowing pattern:\n\n``memray-<script>.<pid>.bin``\n\nwhere ``<script>`` is the name of the executed script and ``<pid>`` is the process id it ran with.\n\nA different filename can be provided with the ``-o`` or ``--output`` argument.\n\n\n.. _Native tracking:\n\nNative tracking\n---------------\n\nOverview\n~~~~~~~~\n\nMemray supports tracking native C/C++ functions as well as Python functions. This can be especially useful\nwhen profiling libraries that have extension modules (such as ``numpy`` or ``pandas``) as this\ngives a holistic vision of how much memory is allocated by the extension and how much is allocated by Python itself.\n\nFor instance, consider the Mandelbrot example from the :ref:`example-applications` section with native tracking\ndisabled. Some of the most important allocations happen when operating on NumPy arrays:\n\n.. image:: _static/images/mandelbrot_operation_non_native.png\n\nHere, we can see that the allocation happens when doing some math on NumPy arrays but unfortunately this doesn't inform us\nof what exact operation is allocating memory or how temporaries are being used. We also don't know if the memory was\nallocated by NumPy or by the interpreter itself. By using the native tracking mode with Memray we can get a much richer report:\n\n.. image:: _static/images/mandelbrot_operation_native.png\n\nIn this native report, we can see all the internal C calls that are underneath. We can see that the memory allocation\nhappens when the NumPy arrays are being added, due to ``PyNumber_Add`` appearing in the stack trace. Based on\n``PyNumber_Multiply`` not appearing in the stack trace, we can conclude that the temporary array created by NumPy is\nimmediately freed (or that it didn't need to allocate memory in the first place, perhaps because it could reuse some\nalready allocated memory).\n\n.. tip::\n    Memray will also include *inlined* functions and *macros* when native tracking is enabled.\n\n.. caution::\n    Activating native tracking has a moderate impact on performance as every instruction pointer in the call stack needs\n    to be resolved whenever an allocation happens. This effect is more noticeable the more allocations the traced\n    application performs.\n\nCheck the :doc:`section on native symbolification <native_mode>` for more\ninformation on how to obtain the best reports with native information, and on\nhow to debug problems in reports with native information.\n\nUsage\n~~~~~\n\nTo activate native tracking, you need to provide the ``--native`` argument when using the ``run`` subcommand:\n\n.. code:: shell\n\n  memray run --native example.py\n\nThis will add native stack information to the result file, which any reporter will automatically use.\n\n.. important::\n   When generating reports for result files that contain native frames, the report needs to be generated **on the same\n   machine** where the result file was generated. This is because the shared libraries that were loaded by the process\n   need to be inspected by Memray to get the correct symbol names.\n\nWhen reporters display native information they will normally use a different color for the Python frames than the native\nframes. This can also be distinguished by looking at the file name in a frame, since Python frames will generally come\nfrom source files with a ``.py`` extension.\n\nPython allocator tracking\n-------------------------\n\nMemray normally tracks allocation and deallocation requests made to the system\nallocator, but by default it won't see individual Python objects being created.\nThat's because the Python interpreter normally uses its own memory pools for\ncreating most objects, only making calls to the system allocator as needed to\ngrow or shrink its memory pools. Our documentation on :doc:`python allocators\n<python_allocators>` describes this memory pooling in greater detail. This\nbehavior speeds the Python interpreter up, and by extension speeds up profiling\nwith Memray, while still allowing Memray to show you each place where your\nprogram needs to acquire more memory.\n\nYou can ask Memray to show you each individual object being created and\ndestroyed, instead, by providing the ``--trace-python-allocators`` argument to\nthe ``run`` subcommand. This records a lot more data and makes profiling much\nslower. It will show you all allocations, even ones that don't result in your\nprogram requesting more memory from the system because the interpreter already\nhad memory available for reuse. It can be useful in some cases, though,\nespecially when tracking down memory leaks.\n\n.. note::\n  This acts also as an alternative way to run with ``PYTHONMALLOC=malloc`` but\n  in a way that allows distiguishing allocations made by using the system\n  allocator directly and ones made by using the Python allocator.\n\n.. code:: shell\n\n  memray run --trace-python-allocators example.py\n\n.. caution::\n  Tracking the Python allocators will result in much larger report files and\n  slower profiling due to the larger amount of data that needs to be collected.\n\n.. _Live tracking:\n\nLive tracking\n-------------\n\nOverview\n~~~~~~~~\n\nMemray supports presenting a \"live\" view for observing the memory usage of a running Python program.\n\n.. image:: _static/images/live_running.png\n\nUsage\n~~~~~\n\nYou can run a program in live mode using ``run --live``:\n\n.. code:: shell\n\n  memray3.9 run --live application.py\n\nImmediately Memray will start your application in the background and will run a TUI in the foreground that you can use\nto analyze your application's memory usage. If you don't want to run your program in the background, you can instead\nuse ``run --live-remote``:\n\n.. code:: shell\n\n  memray3.9 run --live-remote application.py\n\nIn this mode, Memray will choose an unused port, bind to it, and display a message saying:\n\n.. code:: text\n\n  Run 'memray live <port>' in another shell to see live results\n\nIt will wait for you to run:\n\n.. code:: shell\n\n   memray3.9 live <port>\n\nin another terminal window to attach to it. Regardless of whether you choose to use one terminal or two, the resulting\nTUI is exactly the same. See :doc:`live` for details on how to interpret and control the TUI.\n\n\n.. _Tracking across forks:\n\nTracking across forks\n---------------------\n\nOverview\n~~~~~~~~\n\nMemray can optionally continue tracking in a child process after a parent process forks. This can be useful when using\n``multiprocessing``, or a framework utilizing a pre-fork pattern like Celery or Gunicorn.\n\nUsage\n~~~~~\n\nTo activate tracking through forks, you need to provide the ``--follow-fork`` argument to the ``run`` subcommand:\n\n.. code:: shell\n\n  memray run --follow-fork example.py\n\nIn this mode, each time the process forks, a new output file will be created for the new child process, with the new\nchild's process ID appended to the original capture file's name. The capture files for child processes are exactly like\nany other capture file, and can be fed into any reporter of your choosing.\n\n.. note::\n\n  ``--follow-fork`` mode can only be used with an output file. It is incompatible with ``--live``\n  mode and ``--live-remote`` mode, since the TUI can't be attached to multiple processes at once.\n\nLosing capture files after OOM Errors\n-------------------------------------\n\nWhen a process runs out of memory, this commonly causes an Out Of Memory error,\nor \"OOM Error\". That causes the process to be killed by its operating system.\nWithin orchestrations like Kubernetes the termination of the main process might\nimmediately lead to the destruction of the container and the loss of the files\nthat Memray uses to collect its results.\n\nWhen running ``memray run myprogram.py`` a capture file gets created on the file\nsystem, but the entire file system will be thrown away as soon as the\norchestration cleans up the container. If the program exits unexpectedly,\nperhaps because the kernel kills it due to an OOM error, the orchestration might\nthrow away the capture file before you ever get a chance to use it. Since Memray\nis often used to chase memory leaks, this condition might happen more often than\nyou'd like.\n\nSince Memray is running in the same process as your application, it has no way\nto prevent this data loss (by sending it over the network, for example) because\nany work it does will be terminated when the process crashes.\n\nInstead of directly calling ``memray run myprogram.py`` you can wrap it in\na script that will run Memray and run post-processing operations on the capture\nfile. That way, the container won't be destroyed by the orchestration until\nafter the wrapper script exits, rather than being destroyed as soon as the\nPython script being tracked by Memray exits.\n\n.. code-block:: shell\n\n  memray run --output /tmp/capture.bin myprogram.py\n  echo \"Program finished\"\n  # Do your post-processing here. This example just logs a summary of what's\n  # in the capture file, but you might want to generate reports from it and\n  # copy them over the network to some persistent storage, for instance.\n  memray summary /tmp/capture.bin\n\n.. _aggregated capture files:\n\nAggregated capture files\n------------------------\n\nIf you supply the ``--aggregate`` argument to ``memray run``, it will write\nmuch smaller capture files. Instead of containing information about every\nindividual allocation performed by the tracked program, a capture file produced\nusing ``--aggregate`` will contain some statistics about the process's\nallocations aggregated by the location where the allocation happened.\n\nSpecifically, for every location where the tracked process performed any\nallocations, an aggregated capture file includes a count of:\n\n- How many allocations at that location had not yet been deallocated when the\n  process reached its heap memory high water mark\n- How many bytes had been allocated at that location and not yet deallocated\n  when the process reached its heap memory high water mark\n- How many allocations at that location were leaked (i.e. not deallocated\n  before tracking stopped)\n- How many bytes were leaked by allocations at that location\n\nThese counts provide enough information to generate flame graphs. In fact, this\ninformation is enough to run most of our reporters, with just a few exceptions:\n\n- You cannot find :doc:`temporary allocations </temporary_allocations>` using\n  this capture file format, since finding temporary allocations requires\n  knowing when each individual allocation was deallocated.\n- You cannot use the :doc:`stats reporter <stats>` with this capture file\n  format, because it needs to see each individual allocation's size.\n- You cannot use ``--aggregate`` with :ref:`live tracking <live tracking>`,\n  since the live TUI needs to see each allocation as it happens.\n\nAlso, note that if the process is killed before tracking ends (for instance, by\nthe Linux OOM killer), then the process will die before it finishes calculating\nits statistics, and so no useful information is ever written to the capture\nfile. With the default file format, the capture file is usually still usable\neven if the process crashes or is killed, but with the aggregated file format\nit is not.\n\nIf you can live with these limitations, then using ``--aggregate`` results in\nmuch smaller capture files that can be used seamlessly with most reporters.\n\nCLI Reference\n-------------\n\n.. argparse::\n   :ref: memray.commands.get_argument_parser\n   :path: run\n   :prog: memray\n"
  },
  {
    "path": "docs/stats.rst",
    "content": "Stats Reporter\n==============\n\nThe stats reporter generates high level statistics about the tracked process's\nmemory allocations.\n\n.. image:: _static/images/stats_example.png\n\nThe output includes the following:\n\n* Total number of allocations performed\n\n* Total amount of memory allocated\n\n* Histogram displaying the distribution of allocation sizes. The y-axis data (size) is logarithmic.\n\n* Distribution of allocation types (e.g. *MALLOC*, *CALLOC*, *MMAP*, etc.)\n\n* Stack trace and **size** of the top 'n' largest allocating locations by size (*default: 5*, configurable with the ``-n`` command line param)\n\n* Stack trace and **count** of the top 'n' largest allocating locations by number of allocations (*default: 5*, configurable with the ``-n`` command line param)\n\n* (for JSON output only) Metadata about the tracked process\n\nBasic Usage\n-----------\n\nThe general form of the ``stats`` subcommand is:\n\n.. code:: shell\n\n    memray stats [options] <results>\n\nThe only argument the ``stats`` subcommand requires is the capture file\npreviously generated using :doc:`the run subcommand <run>`.\n\nThe output will be printed directly to the standard output of the terminal.\n\nJSON Output\n-----------\n\nIf you supply the ``--json`` flag, the ``stats`` subcommand will write its\noutput to a JSON file, rather than to the terminal. Like other commands that\noutput to files, the default output file name is based on the name of your\ncapture file, but it can be overridden with the ``-o`` / ``--output`` option.\nBy default Memray will refuse to overwrite an existing file, but you can force\nit to by supplying the ``-f`` / ``--force`` option.\n\nNote that new fields may be added to the JSON output over time, though we'll\ntry to avoid removing existing fields.\n\nCLI Reference\n-------------\n\n.. argparse::\n   :ref: memray.commands.get_argument_parser\n   :path: stats\n   :prog: memray\n"
  },
  {
    "path": "docs/summary.rst",
    "content": "Summary Reporter\n================\n\nThe summary reporter provides a quick overview of allocated memory at the time\nwhen the tracked process's memory usage was at its peak. It displays a table\nshowing how much of that peak memory each function directly allocated (\"own\nmemory\"), how much was cumulatively allocated by that function and everything\nit called (\"total memory\"), and the cumulative count of not yet freed\nallocations performed by that function and everything it called (\"allocation\ncount\"). Allocations for different threads are aggregated together and shown in\nthe same table.\n\n.. image:: _static/images/summary_example.png\n\nBasic Usage\n-----------\n\nThe general form of the ``summary`` subcommand is:\n\n.. code:: shell\n\n    memray summary [options] <results>\n\nThe only argument the ``summary`` subcommand requires is the capture file\npreviously generated using :doc:`the run subcommand <run>`.\n\nThe output will be printed directly to standard output. If standard output is\na terminal, the output will be colorized.\n\nCLI Reference\n-------------\n\n.. argparse::\n   :ref: memray.commands.get_argument_parser\n   :path: summary\n   :prog: memray\n"
  },
  {
    "path": "docs/supported_environments.rst",
    "content": "Supported environments\n======================\n\nSupported Python interpreters\n-----------------------------\n\nOnly CPython is supported.\n\nSupported Python versions\n-------------------------\n\nEvery Python version that hasn't reached end of life is supported.\n\nCurrently that's Python 3.8 through 3.14.\n\nSupported operating systems\n---------------------------\n\nYou will have the best Memray experience on Linux.\n\nWe also support macOS 11 or newer. We cannot support older\nmacOS versions, as they don't provide a C++17 compatible runtime. Although all\nfeatures work on macOS, the way that macOS applications and Python libraries\nare typically distributed often results in subpar native stacks on Mac. See\n:ref:`the native mode documentation <mac symbolification>` for details on these\nshortcomings.\n\nWe are unlikely to ever support Windows. While the basic technique that Memray\nuses to detect memory allocations is possible on Windows, much of the library\nwould need to be rewritten to support non-POSIX platforms, and none of the\ncurrent maintainers have the expertise to do so. We do test in WSL, however.\n\nSupported CPU architectures\n---------------------------\n\nFor Linux, we test on ``i686``, ``x86-64``, and ``aarch64``. Pre-built wheels\nare available on PyPI.\n\nFor macOS, we test on ``x86-64`` and ``arm64`` - so, both Intel and Apple\nSilicon Macs. Pre-built wheels are available for both architectures, though\nonly for Python 3.8 and newer.\n\nSupported runtime environments\n------------------------------\n\nWe require a C++17 runtime. As noted above, macOS 11 or higher is required for\na C++17 runtime on Mac.\n\nOn Linux we support glibc and musl libc. Other libc's have not been tested, and\nissues are likely. We support platforms compatible with the ``manylinux2014``\nspecification.\n\nKnown issues and limitations\n----------------------------\n\n* Native stack traces on macOS are often difficult to read, and may be missing\n  function calls. See :ref:`the native mode documentation <mac\n  symbolification>`.\n* We support :ref:`tracking across forks <tracking across forks>`, but can't\n  track across an ``exec``, so if the tracked child process calls `an os.exec\n  function`_, even to start a new Python interpreter, we will not be able to\n  report the allocations performed in the new process. Notably, the default\n  `multiprocessing start method`_ on macOS is \"spawn\", which leverages\n  ``exec``.\n* Cython_ functions will not be included in the Python stacks we report, even\n  if the Cython module is built with profiling_ support. You'll need to use\n  :ref:`native tracking` to see what's happening inside Cython modules.\n* We have experimental support for the ``greenlet`` library, which may lead to\n  incorrect stacks being reported if :doc:`the Memray API <api>` is used to\n  start tracking in one thread while another thread is already making use of\n  the Greenlet library.\n\n.. _an os.exec function: https://docs.python.org/3/library/os.html#os.execl\n.. _multiprocessing start method: https://docs.python.org/3/library/multiprocessing.html#contexts-and-start-methods\n.. _Cython: http://docs.cython.org/en/latest/\n.. _profiling: http://docs.cython.org/en/latest/src/tutorial/profiling_tutorial.html\n"
  },
  {
    "path": "docs/table.rst",
    "content": "Table Reporter\n==============\n\nThe table reporter generates an HTML document showing a simple tabular view of\nthe allocations contributing to the tracked process's peak memory usage. Each\nsource line that contributed to that peak memory usage is given a row in the\ngenerated table, showing the amount of memory it allocated, the type of\nallocator it used, and the number of allocations it was responsible for.\n\n.. image:: _static/images/table_example.png\n\n\nThe table can be sorted by each column and searched in the search field. The columns show the following data:\n\n- Thread ID: thread where the allocation happened\n- Size: total amount of memory used by all of these allocations\n- Allocator: allocator or deallocator function which acquired the memory\n- Allocations: total number of allocations performed by this entry\n- Location: function name, file and line of the allocation or \"???\" if unknown\n\nBasic Usage\n-----------\n\nThe general form of the ``table`` subcommand is:\n\n.. code:: shell\n\n    memray table [options] <results>\n\nThe only argument the ``table`` subcommand requires is the capture file\npreviously generated using :doc:`the run subcommand <run>`.\n\n\nThe output file will be named as ``memray-table-<input file name>.html`` unless the ``-o`` argument was\nspecified to override the default name.\n\n\nCLI Reference\n-------------\n\n.. argparse::\n   :ref: memray.commands.get_argument_parser\n   :path: table\n   :prog: memray\n"
  },
  {
    "path": "docs/temporary_allocations.rst",
    "content": "Temporary allocations\n=====================\n\nSome reporters accept the ``--temporary-allocation-threshold=THRESHOLD`` and\n``--temporary-allocations`` options. When one of these options is used, the\nreporter will show where temporary allocations happened.\n\nWhat are temporary allocations?\n-------------------------------\n\nWe consider a memory allocation \"temporary\" if there are at most ``THRESHOLD``\nother allocations performed between when it is allocated and when it is\ndeallocated. When the threshold is 0 an allocation is considered temporary\nonly if it is immediately deallocated. When the threshold is 1 an allocation\nwill be detected as temporary even if 1 other allocation occurs before it is\ndeallocated.\n\nSeeing where temporary allocations are being performed can help you identify\nareas of your code base that frequently perform small allocations and\ndeallocations. Sometimes these can be avoided by doing one big allocation\ninstead, or by using a memory pool.\n\nThe ``--temporary-allocations`` option behaves as though you passed\n``--temporary-allocation-threshold=1``.  We think this is the most interesting\ndefault threshold, because it lets you detect when elements are sequentially\nadded to a container. That's because growing a container is often performed by\nallocating a new, larger buffer for the container, then copying over every\nelement from the old buffer and deallocating it. When iteratively adding new\nelements to a container, each resize results in 1 allocation for a new buffer\nbefore the previously allocated buffer can be freed, and so these buffers\nwouldn't be seen as temporary with a threshold of 0.\n\nDetecting inefficient allocation patterns\n-----------------------------------------\n\nTemporary allocation detection can help detect inefficient allocation patterns.\nFor example, consider the following code:\n\n.. code-block:: python\n\n    def foo(n):\n        x = []\n        for _ in range(n):\n            x.append(None)\n        return x\n\n    foo(1_000_000)\n\nIf we run this code and check the output of the :doc:`the summary reporter </summary>`\n\n.. code-block:: shell-session\n\n    $ memray run -fo test.bin example.py\n    $ memray summary test.bin --temporary-allocations\n    ┏━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━┓\n    ┃                      ┃     <Total ┃      Total ┃            ┃ Own Memory ┃ Allocation ┃\n    ┃ Location             ┃    Memory> ┃   Memory % ┃ Own Memory ┃          % ┃      Count ┃\n    ┡━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━┩\n    │ foo at example.py    │   72.486MB │     99.93% │   72.486MB │     99.93% │         78 │\n    │ ...                  │            │            │            │            │            │\n    └──────────────────────┴────────────┴────────────┴────────────┴────────────┴────────────┘\n\nwe can see that our function ``foo()`` is responsible for making 78 allocations\nwhich cumulatively allocate 72.48MB. This happens because the list needs to grow\nas we append elements to it.\n\nIf we change how the list is built\n\n.. code-block:: python\n\n    def foo(n):\n        return [None] * n\n\n    foo(1_000_000)\n\nand run the same commands as before\n\n.. code-block:: shell-session\n\n    $ memray run -fo test.bin example2.py\n    $ memray summary test.bin --temporary-allocations\n    ┏━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━┓\n    ┃                      ┃     <Total ┃      Total ┃            ┃ Own Memory ┃ Allocation ┃\n    ┃ Location             ┃    Memory> ┃   Memory % ┃ Own Memory ┃          % ┃      Count ┃\n    ┡━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━┩\n    │ foo at example2.py   │    7.629MB │     99.29% │    7.629MB │     99.29% │          1 │\n    │ ...                  │            │            │            │            │            │\n    └──────────────────────┴────────────┴────────────┴────────────┴────────────┴────────────┘\n\nwe can see that ``foo()`` only made 1 allocation, and the total amount of memory\nit allocates has been reduced by around 90%. This is because ``[None] * n``\nknows how many elements will be present in the final result and allocates\na single chunk of memory large enough to hold all the elements right from the\nstart, instead of starting off with a small buffer and then repeatedly growing\nit as needed.\n"
  },
  {
    "path": "docs/transform.rst",
    "content": "Transform Reporter\n==================\n\nThe transform reporter is used to convert a Memray capture file into a format\nthat can be consumed by other tools.\n\nBasic Usage\n-----------\n\nThe general form of the ``transform`` subcommand is:\n\n.. code:: shell\n\n    memray transform <format> [options] <results>\n\nThe ``transform`` subcommand requires two arguments: the format you want the\noutput file to be in, and the location of the capture file previously generated\nusing :doc:`the run subcommand <run>`.\n\nThe output file will be named ``memray-<format>-<input file name>.<format_suffix>``\nunless the ``-o`` argument is used to override the default name.\n\nAvailable formats\n-----------------\n\nThese are the formats that you can use as the *format* parameter to the\n``transform`` subcommand.\n\ngprof2dot\n~~~~~~~~~\n\nThis format allows you to produce JSON files that are compatible with the\n`gprof2dot <https://github.com/jrfonseca/gprof2dot>`_ tool. This tool can\nthen be used in combination with `graphviz <https://graphviz.org/>`_\nto produce a graph-like representation of the memory usage like this one:\n\n.. image:: _static/images/gprof2dot_example.png\n\nA node in the output graph represents a function and has the following layout:\n\n.. code-block:: text\n\n    +-----------------------------+\n    |           filename          |\n    |        function_name        |\n    |           total %           |\n    |           (self %)          |\n    |        num_allocs ×         |\n    +-----------------------------+\n\nwhere:\n\n* ``total %`` is the percentage of memory allocated by this function and all its children;\n* ``self %`` is the percentage of memory allocated by this function alone;\n* ``num_allocs`` is the number of times an allocation was performed by this function alone.\n\nAn edge represents a call between two functions and has the following layout:\n\n.. code-block:: text\n\n               percentage %\n    caller -------------------> callee\n\nWhere ``percentage %`` is the percentage of memory allocated below calls from *caller* to *callee*.\n\nThe color of the nodes and edges varies according to the ``total %`` value. In\nthe default temperature-like color-map, the functions where the most memory is\nallocated (hot-spots) are saturated red, and functions where little memory is\nallocated are dark blue. Note that functions where negligible or no memory is\nallocated do not appear in the graph by default.\n\nCheck the `gprof2dot documentation <https://github.com/jrfonseca/gprof2dot>`_ for more\ninformation on how to use the tool.\n\ncsv\n~~~\n\nThis format allows you to produce a `comma separated values\n<https://en.wikipedia.org/wiki/Comma-separated_values>`_ file with all the\nallocations that contributed to the process's memory high water mark. This can\nbe very useful to analyze the information using other data analysis tools and\nlibraries such as `pandas <https://pandas.pydata.org>`_.\n\nEvery row in the CSV file represents a call stack where memory that contributed\nto the process's memory high water mark was allocated.\n\nThe available columns are:\n\n* ``allocator``: the name of the allocator that performed the allocations.\n* ``num_allocations``: the number of different allocations performed at this\n  location by this thread and not deallocated before the high water mark.\n* ``size``: the total size in bytes of the allocations performed at this\n  location by this thread and not deallocated before the high water mark.\n* ``tid``: the thread id of the thread that performed the allocations.\n* ``thread_name``: the name of the thread that performed the allocations.\n* ``stack_trace``: the stack trace of the allocations. The stack trace is\n  represented as a ``|`` separated list of stack frames (most recent call\n  first), where each stack frame in the list has the following format:\n  ``<function_name>;<file_name>;<line_number>``.\n\nCLI Reference\n-------------\n\n.. argparse::\n   :ref: memray.commands.get_argument_parser\n   :path: transform\n   :prog: memray\n"
  },
  {
    "path": "docs/tree.rst",
    "content": "Tree Reporter\n==============\n\nThe tree reporter provides a simplified representation of the call hierarchy of\nthe tracked process at the time when its memory usage was at its peak.\n\n.. image:: _static/images/tree_example.png\n\nThe tree reporter shows an interactive terminal applocation displaying a tree\nrepresentation of the allocated memory. Several aspects are important when\ninterpreting the tree representation:\n\n* Only the 10 source locations responsible for the most allocated bytes are\n  displayed. This is configurable with the ``--biggest-allocs`` command line\n  parameter.\n* The total memory and percentage shown in the root node of the tree are\n  calculated based only on the allocations that are shown. Since any allocation\n  not big enough to be shown will not be included there, the reported total\n  memory of the root node is normally less than the process's peak memory size.\n* The \"📂\" icon represents a frame that is a **caller** of a function where an\n  allocation happened while the \"📄\" icon represents a frame that allocated\n  memory.\n* Frames are colored based on their reported memory usage percentage, from red\n  (most bytes allocated) to green (fewest).\n* You can interact with the application using the following keys:\n\n  * You can navigate the tree using the arrow keys. Pressing the up arrow key\n    will move up one level in the tree, while pressing the down arrow key will\n    move down one row. When a new row is selected, the panel on the right\n    will be updated to show the source code of the selected frame and some metadata\n    about the allocations made by that frame and its children.\n  * Pressing the 'e' key will expand nodes and their children recursively until a node with\n    more than one child is found. This can be used to quickly expand the tree.\n  * Pressing the 'i' key will hide all nodes that belong to the import system and their\n    children.\n  * Presing the 'u' key will show all nodes that are marked as \"uninteresting\".\n\n.. note::\n   If the ``textual[syntax]`` package is installed, the Python source files\n   will be displayed with syntax highlighting!\n\n\nBasic Usage\n-----------\n\nThe general form of the ``tree`` subcommand is:\n\n.. code:: shell\n\n    memray tree [options] <results>\n\nThe only argument the ``tree`` subcommand requires is the capture file\npreviously generated using :doc:`the run subcommand <run>`.\n\nThe output will be printed directly to standard output. If standard output is\na terminal, the output will be colorized.\n\nCLI Reference\n-------------\n\n.. argparse::\n   :ref: memray.commands.get_argument_parser\n   :path: tree\n   :prog: memray\n"
  },
  {
    "path": "docs/tutorials/1.rst",
    "content": "Exercise 1 - Fibonacci Sequence\n===============================\n\nIntro\n---------\n\nThis first lesson is meant to familiarize you with the methods and tools we will be using for the\nrest of the exercises. By the end of it, you should understand:\n\n- Basic integration of Memray with pytest\n- How to run a python script with Memray\n- How to generate and interpret a flame graph\n\nIn this first example, we will be calculating and printing the results of a Fibonacci sequence of a\nspecified number of elements. Python has some great standardized practices for iterating over large\nsequences that you will have an opportunity to learn about.\n\nThis tutorial supports two modes of development: GitHub Codespaces or a local virtual environment.\nFeel free to choose the option more suitable to you below.\n\nDevelopment Environment Setup\n-----------------------------\n\nCodespaces Environment\n^^^^^^^^^^^^^^^^^^^^^^\n\nTo create a new Codespace, click this button, and follow the prompts. It should take approximately 1-2 minutes to setup.\n\n.. raw:: html\n\n  <a href='https://codespaces.new/bloomberg/memray?devcontainer_path=.devcontainer%2Ftutorials%2Fdevcontainer.json'><img src='https://github.com/codespaces/badge.svg' alt='Open in GitHub Codespaces' style='max-width: 100%;'></a>\n\nLocal Virtual Environment\n^^^^^^^^^^^^^^^^^^^^^^^^^\n\nNavigate to the `Memray GitHub repo <https://github.com/bloomberg/memray>`_ and get a copy of the\nsource code. You can either clone it, or just download the zip, whatever is your preference here.\n\nYou will also need a terminal with ``python3`` installed, preferably one of the latest versions.\nYou can see which versions of ``python3`` are currently supported at the Memray GitHub page as well.\n\nOnce you have the repo ready to navigate, ``cd`` into the docs/tutorials folder:\n\n.. code:: shell\n\n    cd docs/tutorials/\n\nIt is here where we will be running the tests and exercises for the remainder of the tutorial.\nFor reference here are the official `python3 venv docs <https://docs.python.org/3/library/venv.html>`_.\nYou can also just follow along with the commands below.\n\nLet's go ahead and setup our virtual environment.\n\n.. code:: shell\n\n    python3 -m venv .venv\n\nOnce your virtual environment has been created, you can activate it like so:\n\n.. code:: shell\n\n    source .venv/bin/activate\n\nYou can confirm activation was successful if your terminal prompt is prefixed with ``(.venv)``.\nWith our virtual environment ready, we can go ahead and install all the dependencies required\nfor the tutorial.\n\n.. code:: shell\n\n    python3 -m pip install -r requirements-tutorial.txt\n\nKeep your virtual environment activated for the rest of the tutorial, and you should be able to run\nany of the commands in the exercises.\n\nPytest plugin for Memray\n------------------------\n\nMemray supports the ability to augment your pytest tests to enforce an upper bound on your code's\nmemory usage. This will then cause the test to fail if it uses more than the allowed amount of\nmemory during the tests execution. Take a look at exercise 1's test: there is a line that specifies\n``@pytest.mark.limit_memory`` . This is how we set our upper bound memory limit. Markers like this\nare used for all of the tests covered in this workshop.\n\nCodespaces Test Execution\n^^^^^^^^^^^^^^^^^^^^^^^^^\n\nYour Codespace should be pre-configured to include the testing plugin. Click the flask on the\nnavigator (circled in green below). This will open the Testing tab, which will include all the\ntests we will be running during this tutorial. Drill down into exercise 1: here you will see\na handful of tests configured for your first exercise. You can execute this group of tests by\nclicking the play button (circled in red below).\n\n.. image:: ../_static/images/codespaces_testing_tab.png\n\nLocal Virtualenv Test Execution\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nPytest is already installed in your virtual environment, so you can simply invoke it to execute your tests.\nRun the following command in your terminal, it will search all subdirectories for tests.\nThis will test the entire workshop.\n\n.. code:: shell\n\n    pytest\n\nIt can be tedious to test all exercises when we are working on 1 exercise at a time. To save time,\nlet's run only the tests for exercise 1.\n\n.. code:: shell\n\n    pytest tests/test_exercise_1.py\n\n.. image:: ../_static/images/pytest_cli_output.png\n\nUnderstanding the results\n^^^^^^^^^^^^^^^^^^^^^^^^^\n\nDo you notice any issues with your test case? Initially we should see that the test is failing with\nsome additional information. Looks like our test case allocated more memory than we allotted for. We\nwill be taking advantage of this amazing feature included with Memray to help run our workshop. Your\ngoal for each exercise will be to modify the exercises (NOT the tests), in order to respect these memory limits.\n\nFlame graphs, what are they?\n----------------------------\n\nOK, so we know our test is broken. How can we use Memray to help us dive deeper into the underlying\nproblem? The answer is: a flame graph! A flame graph is a tool used to visualize the memory usage of\na program at a particular point in time. Memray can generate an HTML file that renders a *flamegraph\nreport*.\n\n.. image:: ../_static/images/exercise1_flamegraph.png\n\n\nThe *flamegraph report* is made up of three sections. At the top we have some controls to adjust the\nappearance of our report. The middle portion of the screen shows a line plot where we can see total\nmemory usage of our program plotted over time. The vertical (Y) axis is memory used, and the\nhorizontal (X) axis is time. The bottom portion is the flame graph, which displays a snapshot of the\nprogram's memory usage from only a single moment in time out of the entire execution runtime of the\nprogram. By default, Memray generates reports showing the point when the program's memory usage\nreached its peak. Each row in the flame graph is a frame in your stack trace. The width of each box\nrepresents the relative amount of memory used. In *icicles* mode, the lowest row is the top of the\nstack, and shows the functions that allocated memory, while in *flames* mode, the rows are flipped\nsuch that the top row shows the top of the stack and is the location where memory is allocated.\n\nYou can click on a particular box to filter out less recent frames from the stack, focusing on a\nparticular frame and the functions it called into.\n\nMore information on the :doc:`flame graph reporter <../flamegraph>` and how to\n:ref:`interpret flame graphs <interpreting flame graphs>` are available in the docs.\n\nGenerating a Flame Graph\n------------------------\n\nCodespaces Flame Graph Generation\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nFrom VS Code, open up 2 terminals. You can do this by typing Ctrl+Shift+P (Cmd+Shift+P on macOS) to\nopen the \"command palette\", and then typing \"terminal\" in the search box and selecting \"Python:\nCreate Terminal\".\n\nWe need to launch an HTTP server to view our generated flame graphs. Run this command in one of your\nterminals:\n\n.. code:: shell\n\n    python -m http.server 3000\n\nYou should now see a prompt to launch the application in your browser, and should click \"Open in\nBrowser\" in the bottom right. If that prompt doesn't appear, you can navigate to the *Ports* tab\n(circled in orange below) and click the *Open in Browser* button (circled in green below). This will\ngive you an HTTP server we will use in order to launch and view our generated flame graphs.\n\n.. image:: ../_static/images/ports_tab.png\n\nIn your second terminal, navigate to the ``exercise_1`` directory via\n\n.. code:: shell\n\n    cd docs/tutorials/exercise_1/\n\nRun the first exercise labeled ``fibonacci.py``, but make sure to have Memray wrap this call.\n\n.. code:: shell\n\n    memray run fibonacci.py\n\nAfter the run is complete, Memray will conveniently print the command to generate a flame graph from\nthe Memray output file. For example, we will run:\n\n.. code:: shell\n\n    memray flamegraph memray-fibonacci.py.<run-id>.bin\n\n.. note::\n\n    The run id will change each time you run the command.\n\nNow that we have generated our flame graph, let's load it up and have a look at it.\nTo do so, open the tab in your browser with your HTTP server, click on ``docs/tutorials/exercise_1``\ndirectory, and then click on the flame graph (it should have an html file extension)\n\nVoila! We have generated our very first flame graph. Try clicking around the graph and exploring some\nof the features of Memray.\n\n.. image:: ../_static/images/exercise1_flamegraph.png\n\nVenv Flame Graph Generation\n^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nRun the first exercise labeled ``fibonacci.py``, but make sure to have Memray wrap this call.\n\n.. code:: shell\n\n    memray run exercise_1/fibonacci.py\n\nAfter the run is complete, Memray will conveniently print the command to generate a flame graph from\nthe Memray output file. For example, we will run:\n\n.. code:: shell\n\n    memray flamegraph exercise_1/memray-fibonacci.py.<run-id>.bin\n\n.. note::\n\n    The run id will change each time you run the command.\n\nNow that we have generated our flame graph, you can launch the HTML output file in your web browser.\n\nChallenge\n---------\n\nTake a closer look at the stack on the flame graph — you will notice that the ``output.append`` call\nappears to be the source of almost all of our script's allocations. Maybe that could be used as\na clue as to what in particular we may want to change to pass our test?\n\n.. code-block:: python\n    :emphasize-lines: 13\n\n    def fibonacci(length):\n        # edge cases\n        if length < 1:\n            return []\n        if length == 1:\n            return [1]\n        if length == 2:\n            return [1, 1]\n\n        output = [1, 1]\n\n        for i in range(length - 2):\n            output.append(output[i] + output[i + 1])  # <- Here!\n\n        return output\n\nTry to edit ``fibonacci.py`` to make the program more memory efficient. Test your solution by running\nthe ``test_exercise_1.py`` unit test, and inspect the effect your changes have on the memory allocation by\ngenerating new flame graphs. Ensure you don't break any of the correctness tests along the way!\n\n.. raw:: html\n\n    <details>\n    <summary><i>Toggle to see the sample solution</i></summary>\n\nAfter examining the flame graph, we can see that the problem is caused by this intermediate array\n``output`` that we are using in order to capture and return the results of the calculation.\n\nPython has an amazing construct that works well in this situation called\n`generators <https://wiki.python.org/moin/Generators>`_.\n\nEssentially, a generator works by pausing execution of your function when a ``yield`` statement is\nreached, saving the state of the function for later. After each iteration, we can resume that paused\nfunction in order to retrieve the next value that is needed. This is more memory efficient than\nprocessing the entire loop and saving the results in memory — especially when you have 100,000\niterations! ::\n\n    def fibonacci(length):\n        # edge cases\n        if length < 1:\n            return\n        if length == 1:\n            yield 1\n            return\n\n        left = right = 1\n        yield left\n        yield right\n\n        for _ in range(length - 2):\n            left, right = right, left + right\n            yield right\n\nFull code solution `here <https://github.com/bloomberg/memray/blob/main/docs/tutorials/solutions/exercise_1/fibonacci.py>`_.\n\n.. raw:: html\n\n    </details>\n\nConclusion\n----------\n\nWe should try to avoid loading the entire result set into memory (like into a list) when we plan to\niterate on that result set anyways. This is especially true when your result set is very large. It is\ntypically best to work with generators in these types of situations.\n\n.. note::\n\n    Sometimes it is better to do all the calculations up front. Generators are far more memory\n    efficient than lists, but iterating over generators is slightly slower than iterating over\n    lists, and generators can only be iterated over once. The solution with the best trade-offs will\n    vary from case to case.\n\nUsing Memray's flame graph can be a quick and easy way to identify where your application has\na memory bottleneck.\n"
  },
  {
    "path": "docs/tutorials/2.rst",
    "content": "Exercise 2 - Clinging Onto Memory\n=================================\n\nIntro\n-----\n\nUnlike some low level languages like C, Python will manage our memory for us and will free up memory\nthat's no longer needed. Python's automatic memory management makes our lives easier, but sometimes,\nit may not work the way you would expect it to...\n\nWorking Through an Example\n^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nLet's go through an example where memory management in Python doesn't work how a person coming from\nother programming languages might expect.\n\nExercise\n\"\"\"\"\"\"\"\"\n\nTake a look at the example in ``holding_onto_memory.py``: how many MB of memory will it use at peak?\nTake a guess, and then confirm by running ``memray`` and generating a ``flamegraph``.\n\nExpectations vs Reality\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\n\nLet's presume that we can't mutate the original data, the best we can do is peak memory of 200MB:\nfor a brief moment in time both the original 100MB of data and the modified copy of the data will\nneed to be present. In practice, however, the actual peak usage will be 400MB as demonstrated by the\n``flamegraph``:\n\n.. image:: ../_static/images/exercise2_flamegraph.png\n\nExamining our flame graph further, we can see that we peak at 400MB of allocated memory in\n``add_scalar`` due to four 100MB allocations that are all alive simultaneously:\n\n1. The return value from ``subtract_scalar``, held by the ``data`` variable in ``process_data``\n2. The return value from ``raise_to_power``, held by the ``data_pow`` variable in ``process_data``\n3. The return value from ``duplicate_data``, held by the ``data`` argument in ``add_scalar``\n4. The return value from ``add_scalar``, which is created and populated before the function returns\n   and the ``data`` argument goes out of scope\n\nChallenge\n\"\"\"\"\"\"\"\"\"\n\nExperiment with the code in ``holding_onto_memory.py`` and try to get the peak memory usage down to\n200MB. Test your solutions by running the unit test in ``tests/test_exercise_2.py`` and examine them\nwith the help of ``memray`` reports.\n\n\nSolutions\n\"\"\"\"\"\"\"\"\"\n\n.. raw:: html\n\n   <details>\n   <summary><i>Toggle to see the sample solutions</i></summary>\n\nAfter examining the flame graph, we can see that the problem is caused by local variables which are\nno longer needed, but continue to use memory until ``process_data()`` has finished running.\nTherefore, we need to refactor the method in a way that does not use unnecessary variables to store\ndata that will not be read afterwards. There are two main approaches we can use to solve our issue\nhere:\n\n1. Avoiding local variables in ``process_data()`` all together and instead returning the result\n   of nested function calls::\n\n    def process_data():\n        # no extra reference to the original array\n        return add_scalar(\n            duplicate_data(\n                raise_to_power(\n                    subtract_scalar(\n                        load_xMb_of_data(SIZE_OF_DATA_IN_MB),\n                        SUBTRACT_AMOUNT\n                    ),\n                    POWER_AMOUNT\n                )\n            ),\n            ADD_AMOUNT\n        )\n\n2. Reassigning one variable: we can create a single variable, and re-use it multiple times to store\n   the new value of the manipulated array. This way, we will only hold one array in memory at a time,\n   instead of holding on to older versions of the mutated array unnecessarily::\n\n    def process_data():\n        # reusing the local variable instead of allocating more space\n        # this approach is called 'hidden mutability'\n        data = load_xMb_of_data(SIZE_OF_DATA_IN_MB)\n        data = subtract_scalar(data, SUBTRACT_AMOUNT)\n        data = raise_to_power(data, POWER_AMOUNT)\n        data = duplicate_data(data)\n        data = add_scalar(data, ADD_AMOUNT)\n        return data\n\nFull code solution `here\n<https://github.com/bloomberg/memray/blob/main/docs/tutorials/solutions/exercise_2/holding_onto_memory.py>`_.\n\n.. raw:: html\n\n   </details>\n\nConclusion\n^^^^^^^^^^\n\nTypically, holding onto data in memory a little longer than needed is not a big issue. However, when\nwe are working with large objects, we should be particularly careful. Over-allocating unnecessary\nmemory can lead to running out of memory on the machine (especially for Linux VMs which are\ntypically smaller than physical machines).\n\nMemray can be a helpful tool when trying to debug where we are over-allocating memory unnecessarily.\n\nMore resources:\n\n- A more detailed walkthrough with a `similar example\n  <https://pythonspeed.com/articles/function-calls-prevent-garbage-collection/>`_\n- Another `related article <https://pythonspeed.com/articles/minimizing-copying/>`_ about\n  unnecessary memory allocation\n- A great `article <https://pythonsimplified.com/mutability-immutability-in-python/>`_ on mutability\n  and immutability in Python\n"
  },
  {
    "path": "docs/tutorials/3.rst",
    "content": "Exercise 3 - LRU Cache\n======================\n\nIntro\n-----\n\nIn :doc:`exercise 2 <2>` we experimented with how and when Python automatically deallocates memory.\nThis exercise will delve deeper into the automatic deallocation logic used in Python.\n\nIn Python, Garbage Collection is when the program identifies and releases blocks of memory that are\nno longer in use. The Python Garbage Collector (GC) operates while the program is running and is\nactivated when the reference count of a particular object in memory reaches zero. The reference\ncount increases when an object is given a new name or is placed in a container such as a tuple or\na dictionary. Conversely, the reference count decreases when a name referring to the object is\nreassigned to a different object instead, or a variable referring to the object goes out of scope,\nor when a container referencing the object is destroyed.\n\nThe automatic garbage collection is really helpful, however, it may not clear all blocks of memory\nwe would expect it to.\n\nSymbolic information in native mode\n-----------------------------------\n\nWhen passing the ``--native`` flag to the ``run`` subcommand, Memray will collect information about\nthe native call stack leading to each allocation, and it will dump it to the result file. This\ninformation is in a raw form where every call is identified by a number called the \"instruction\npointer\" or \"program counter\". When creating reports, Memray needs to convert these instruction\npointers into human readable information, like the function name, the file name where that function\nis defined, and the line number within that file corresponding to the instruction.\n\nThis is particularly helpful when working with libraries written in a native language like C, C++,\nFortran, or Rust (for instance ``functools``, ``numpy``, ``cryptography``, etc).\n\nRead more about how Memray resolves symbols in \"native\" mode :doc:`here <../native_mode>`.\n\nWorking Through an Example\n^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nLet's work through another example where data is held in memory longer than we may expect.\n\nExercise\n\"\"\"\"\"\"\"\"\n\nLet's have a look at the example in ``lru_cache.py`` under exercise 3: can you spot any\nmemory-related bugs in the code? Try running ``memray`` and generating a ``flamegraph`` — was the\nmemory allocated the way you expected it to be?\n\nChallenge\n\"\"\"\"\"\"\"\"\"\n\nExperiment with the code in ``lru_cache.py`` and try to get the peak memory usage down to 70MB. Test\nyour solutions by running the unit test in ``tests/test_exercise_3.py`` and examine them with the\nhelp of ``memray`` reports.\n\nUtilizing the Native mode\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\n\nLet's have a look at our flamegraph — we can see that the majority of the allocations come from the\nreturn statement in the ``factorial_plus()`` method. That's quite odd, as the statement doesn't look\nto be doing any memory heavy operations.\n\n.. image:: ../_static/images/exercise3_flamegraph_basic.png\n\nLet's give the ``--native`` mode a go and see if we can uncover what might be causing the underlying\nmemory-heavy operations. Can you spot anything new that might help us understand what's causing such\nhigh memory usage?\n\n.. image:: ../_static/images/exercise3_flamegraph_native.png\n\nHints\n\"\"\"\"\"\n\n.. raw:: html\n\n    <details>\n    <summary><i>Hint 1</i></summary>\n\nThe ``cache`` decorator works with methods that have hashable arguments - it caches the result of the\ndecorated method per unique list of parameters. The results in the cache are kept alive until they\nage out (we have not set the size limit for our cache so this will never happen) of the cache or\nuntil the cache is cleared manually.\n\nLet's have another look at the method being cached::\n\n    @functools.cache\n    def factorial_plus(self, n: int) -> int:\n        return n * self.factorial_plus(n - 1) + self.inc if n else 1 + self.inc\n\nHow and which of the method calls be cached?\n\n.. raw:: html\n\n   </details>\n\n.. raw:: html\n\n   <details>\n   <summary><i>Hint 2</i></summary>\n\nRemove the comment ``# pylint: disable=W1518`` on line ``17``, and then run ``pylint`` to see\nanother hint.\n\n.. raw:: html\n\n   </details>\n\nSolutions\n\"\"\"\"\"\"\"\"\"\n\n.. raw:: html\n\n   <details>\n   <summary><i>Toggle to see the sample solutions</i></summary>\n\nThere are many different approaches to fix this memory issue - here are a few of them:\n\n1. The ``cache`` decorator calls ``functools.lru_cache(maxsize=None)``. The ``lru_cache`` object\n   itself stores (\"memoizes\") the results, and retains references to all argument values passed to\n   the decorated function in the cache. So, if we invoke such a decorated function with an object as\n   a parameter, that object will persist in memory indefinitely, until the program terminates. If no\n   other object ever compares equal to that object, we can never again get a cache hit for it,\n   thereby squandering cache space. This scenario frequently arises when decorating a method, with\n   the first parameter being ``self``.\n\n   One solution for this specific case involves utilizing a dedicated memoization method that stores\n   the cache on the ``self`` object itself. This arrangement ensures that the cache is released\n   alongside the object. ::\n\n    class Algorithms:\n        def __init__(self, inc: int):\n            self.inc = inc\n            self.factorial_plus = functools.cache(self._uncached_factorial_plus)\n\n        def _uncached_factorial_plus(self, n: int) -> int:\n            return n * self.factorial_plus(n - 1) + self.inc if n > 1 else 1 + self.inc\n\n    def generate_factorial_plus_last_digit(plus_range: int, factorial_range: int):\n        for i in range(plus_range):\n            A = Algorithms(i)\n            for j in range(factorial_range):\n                yield A.factorial_plus(j) % 10\n\n   Full code solution `here\n   <https://github.com/bloomberg/memray/blob/main/docs/tutorials/solutions/exercise_3/lru_cache.py>`_.\n\n2. Another approach would be setting a maximum size for the cache. We can do\n   that by passing an argument to ``@lru_cache`` decorator directly.\n\n   .. note::\n\n    ``@cache`` just wraps ``@lru_cache`` with some default arguments;\n    we can only set the cache size ourselves if we use the ``@lru_cache``\n    decorator directly.\n\n   .. code-block:: python\n\n    @functools.lru_cache(maxsize=10000)\n    def factorial_plus(self, n: int) -> int:\n        return n * self.factorial_plus(n - 1) + self.inc if n else 1 + self.inc\n\n   ``maxsize=`` here sets the maximum number of values stored in the cache.\n\n3. Finally, we can periodically manually invoke the cleanup of the cache. This can be done by calling\n   ``Algorithms.factorial_plus.cache_clear()``\n\n.. raw:: html\n\n   </details>\n\nConclusion\n^^^^^^^^^^\n\nThe ``@functools.cache`` decorator is a powerful tool that can help make our programs much more\nefficient. It is crucial to fully understand how this decorator works before attempting to use it.\nBy decorating an instance method, we have included the instance of this class (``self``) as part of\nthe key to our cached data. This can easily lead to unexpected memory leaks when working with\nmultiple instances of this class. That is because the LRU cache retains references to all of the\narguments of the decorated function in its cache. Consequently, if we invoke such a decorated\nfunction with an object as an argument, that object will persist in memory indefinitely, or until\nthe program terminates or the cache is cleared (reference counts in the GC for those cached objects\nare always > 0). If no other object instance ever compares equal to the one we've used as a cache\nkey, we'll never get a cache hit but are unnecessarily holding the object alive as a cache key,\nleading to unnecessary memory consumption.\n\nIn this tutorial we've learned to use Memray, either through manual inspection of Python scripts or\nvia the pytest API. These methods are helpful tools for catching these, and other similar unexpected\nmemory-related behaviors.\n\nRead more about:\n\n- Python GC memory reference counting mechanism, `reference count official documentation\n  <http://docs.python.org/extending/extending.html#reference-counts>`_\n- Best ways to cache method calls, `the official faq\n  <https://docs.python.org/3/faq/programming.html#faq-cache-method-calls>`_\n- The original issue on the python language repo going over the details of misuse of lru_cache when\n  decorating methods `on github <https://github.com/python/cpython/issues/64058>`_\n"
  },
  {
    "path": "docs/tutorials/Dockerfile",
    "content": "FROM debian:bookworm-slim\n\nARG DEBIAN_FRONTEND=noninteractive\n\nRUN apt-get update \\\n    && apt-get install -y --force-yes --no-install-recommends \\\n    python3-dev \\\n    python3-dbg \\\n    python3-pip \\\n    python3-venv \\\n    && apt-get clean \\\n    && rm -rf /var/lib/apt/lists/*\n\nENV VIRTUAL_ENV=/venv \\\n    PYTHONDONTWRITEBYTECODE=1 \\\n    PATH=/bin:$PATH\n\nRUN python3 -m venv \"$VIRTUAL_ENV\"\n\nENV PATH=\"${VIRTUAL_ENV}/bin:/usr/lib/ccache:${PATH}\" \\\n    PYTHON=\"${VIRTUAL_ENV}/bin/python\"\n\nCOPY requirements-tutorial.txt /tmp/\n\nRUN $PYTHON -m pip install -U \\\n    -r /tmp/requirements-tutorial.txt\n\nWORKDIR /src\n"
  },
  {
    "path": "docs/tutorials/additional_features.rst",
    "content": "What to learn about next\n========================\n\nWe've now acquainted ourselves with Memray, and had a look at how it can be used in development\nworkflows and for diagnosing unexpected memory issues. This section will briefly introduce you to\na few more features offered by Memray which you can explore further in your own time.\n\nEssential Concepts\n------------------\n\nCheck out the more detailed descriptions of the most essential concepts used in Memray by\nexploring the :doc:`concepts <../run>` section on the sidebar. It goes into detail about the\n``memray`` subcommands and features available, as well as memory management in Python.\n\npytest Plugin\n-------------\n\nMemray offers a helpful pytest plugin, ``pytest-memray``, which has a couple of notable\nfeatures:\n\n- ``@pytest.mark.limit_memory()`` marks tests as failed if the execution of said test allocates more\n  memory than allowed. We used these markers throughout the unit tests in the three tutorial\n  exercises. It will also print a helpful overview of which function calls used up the most memory\n  for the failed test cases.\n- Running your tests as ``pytest --memray`` will generate a report with a high level overview of the\n  memory allocated and will list a few top memory using functions.\n\nTry to utilize the plugin in your unit tests, and have them run as a part of your CI/CD pipeline.\n\nRead more about the memray pytest plugin in the `official documentation\n<https://pytest-memray.readthedocs.io/en/latest/>`_.\n\nReporters\n---------\n\nAs a part of this study guide, we've worked with flame graphs. However, Memray offers numerous other\ntypes of reports for you to explore:\n\n  - :doc:`Live Graphs <../live>`\n  - :doc:`Summary Reporter <../summary>`\n  - :doc:`Flame Graph Reporter <../flamegraph>`\n  - :doc:`Table Reporter <../table>`\n  - :doc:`Tree Reporter <../tree>`\n  - :doc:`Stats Reporter <../stats>`\n  - :doc:`Transform Reporter <../transform>`\n"
  },
  {
    "path": "docs/tutorials/exercise_1/__init__.py",
    "content": ""
  },
  {
    "path": "docs/tutorials/exercise_1/fibonacci.py",
    "content": "import operator\nfrom functools import reduce\nfrom itertools import chain\n\n\ndef fibonacci(length):\n    # edge cases\n    if length < 1:\n        return []\n    if length == 1:\n        return [1]\n    if length == 2:\n        return [1, 1]\n\n    output = [1, 1]\n\n    for i in range(length - 2):\n        output.append(output[i] + output[i + 1])\n\n    return output\n\n\ndef generate_fibonacci_hash(length_1, length_2, length_3):\n    # We could have used sum(...) here instead of reduce(operator.add, ...),\n    # but we choose to use reduce since it yields a more descriptive example\n    # of the generated flamegraph for this specific example\n    return (\n        reduce(\n            operator.add,\n            chain(fibonacci(length_1), fibonacci(length_2), fibonacci(length_3)),\n            0,\n        )\n        % 10000\n    )\n\n\nif __name__ == \"__main__\":\n    # DO NOT CHANGE\n    LENGTH_OF_SEQUENCE_1 = 33333\n    LENGTH_OF_SEQUENCE_2 = 30000\n    LENGTH_OF_SEQUENCE_3 = 34567\n    # DO NOT CHANGE\n    generate_fibonacci_hash(\n        LENGTH_OF_SEQUENCE_1, LENGTH_OF_SEQUENCE_2, LENGTH_OF_SEQUENCE_3\n    )\n"
  },
  {
    "path": "docs/tutorials/exercise_2/__init__.py",
    "content": ""
  },
  {
    "path": "docs/tutorials/exercise_2/holding_onto_memory.py",
    "content": "import numpy as np\n\n# DO NOT CHANGE\nMB_CONVERSION = 1000 * 1000\nDUPLICATE_CONST = 2\n\nSIZE_OF_DATA_IN_MB = 100\nSUBTRACT_AMOUNT = 3\nPOWER_AMOUNT = 2\nADD_AMOUNT = 10\n# DO NOT CHANGE\n\n\ndef load_xMb_of_data(mb: int) -> np.ndarray:\n    size = MB_CONVERSION * mb  # DO NOT CHANGE\n    return np.ones(size, dtype=np.uint8)\n\n\ndef duplicate_data(data: np.ndarray) -> np.ndarray:\n    return data * DUPLICATE_CONST\n\n\ndef add_scalar(data: np.ndarray, scalar: int) -> np.ndarray:\n    return data + scalar\n\n\ndef subtract_scalar(data: np.ndarray, scalar: int) -> np.ndarray:\n    return data - scalar\n\n\ndef raise_to_power(data: np.ndarray, power: int) -> np.ndarray:\n    return np.power(data, power)\n\n\ndef process_data() -> np.ndarray:\n    data = load_xMb_of_data(SIZE_OF_DATA_IN_MB)\n    data = subtract_scalar(data, SUBTRACT_AMOUNT)\n    data_pow = raise_to_power(data, POWER_AMOUNT)\n    return add_scalar(duplicate_data(data_pow), ADD_AMOUNT)\n\n\nif __name__ == \"__main__\":\n    process_data()\n"
  },
  {
    "path": "docs/tutorials/exercise_3/__init__.py",
    "content": ""
  },
  {
    "path": "docs/tutorials/exercise_3/lru_cache.py",
    "content": "# pylint: disable=C0114 C0115 C0116 R0903 C0103\n\nimport functools\nfrom collections import Counter\n\n# DO NOT CHANGE\nFIRST_COUNTER_RANGE = 500\nSECOND_COUNTER_RANGE = 1000\n# DO NOT CHANGE\n\n\nclass Algorithms:\n    def __init__(self, inc: int):\n        self.inc = inc\n\n    @functools.cache  # pylint: disable=W1518\n    def factorial_plus(self, n: int) -> int:\n        return n * self.factorial_plus(n - 1) + self.inc if n > 1 else 1 + self.inc\n\n\ndef generate_factorial_plus_last_digit(plus_range: int, factorial_range: int):\n    for i in range(plus_range):\n        A = Algorithms(i)\n        for j in range(factorial_range):\n            yield A.factorial_plus(j) % 10\n\n\ndef compare_counts_different_factorials():\n    counts_500 = Counter(\n        generate_factorial_plus_last_digit(FIRST_COUNTER_RANGE, FIRST_COUNTER_RANGE)\n    )\n    counts_1000 = Counter(\n        generate_factorial_plus_last_digit(SECOND_COUNTER_RANGE, SECOND_COUNTER_RANGE)\n    )\n\n    print(counts_500.most_common())\n    print(counts_1000.most_common())\n\n\nif __name__ == \"__main__\":\n    compare_counts_different_factorials()\n"
  },
  {
    "path": "docs/tutorials/index.rst",
    "content": "About This Tutorial\n===================\n\nThe tutorials in this section of the docs provide a gentle introduction to debugging memory issues using the Memray\nprofiler. You'll learn how to use basic features like generating flame graphs and integrating Memray with pytest test\nsuites, as well as some more advanced features like inspecting the C, C++, or Rust frames on the call stack in addition\nto the Python frames.\n\nThere are 3 different exercises within this tutorial:\n    - :doc:`Exercise 1 <1>` - Fibonacci Sequence\n    - :doc:`Exercise 2 <2>` - Clinging Onto memory\n    - :doc:`Exercise 3 <3>` - LRU Cache\n\nYou should follow them in the order they're presented here, as each builds on concepts introduced by the last.\n"
  },
  {
    "path": "docs/tutorials/requirements-tutorial.txt",
    "content": "memray\nnumpy\npylint\npytest\npytest-memray\n"
  },
  {
    "path": "docs/tutorials/solutions/exercise_1/fibonacci.py",
    "content": "import operator\nfrom functools import reduce\nfrom itertools import chain\n\n\ndef fibonacci(length):\n    # edge cases\n    if length < 1:\n        return\n    if length == 1:\n        yield 1\n        return\n\n    left = right = 1\n    yield left\n    yield right\n\n    for _ in range(length - 2):\n        left, right = right, left + right\n        yield right\n\n\ndef generate_fibonacci_hash(length_1, length_2, length_3):\n    # We could have used sum(...) here instead of reduce(operator.add, ...),\n    # but we choose to use reduce since it yields a more descriptive example\n    # of the generated flamegraph for this specific example\n    return (\n        reduce(\n            operator.add,\n            chain(fibonacci(length_1), fibonacci(length_2), fibonacci(length_3)),\n            0,\n        )\n        % 10000\n    )\n\n\nif __name__ == \"__main__\":\n    # DO NOT CHANGE\n    LENGTH_OF_SEQUENCE_1 = 33333\n    LENGTH_OF_SEQUENCE_2 = 30000\n    LENGTH_OF_SEQUENCE_3 = 34567\n    # DO NOT CHANGE\n    generate_fibonacci_hash(\n        LENGTH_OF_SEQUENCE_1, LENGTH_OF_SEQUENCE_2, LENGTH_OF_SEQUENCE_3\n    )\n"
  },
  {
    "path": "docs/tutorials/solutions/exercise_2/holding_onto_memory.py",
    "content": "import numpy as np\n\n# DO NOT CHANGE\nMB_CONVERSION = 1024 * 1024\nDUPLICATE_CONST = 2\n\nSIZE_OF_DATA_IN_MB = 100\nSUBTRACT_AMOUNT = 3\nPOWER_AMOUNT = 2\nADD_AMOUNT = 10\n# DO NOT CHANGE\n\n\ndef load_xMb_of_data(mb: int) -> np.ndarray:\n    size = MB_CONVERSION * mb\n    return np.ones(size, dtype=np.uint8)\n\n\ndef duplicate_data(data: np.ndarray) -> np.ndarray:\n    return data * DUPLICATE_CONST\n\n\ndef add_scalar(data: np.ndarray, scalar: int) -> np.ndarray:\n    return data + scalar\n\n\ndef subtract_scalar(data: np.ndarray, scalar: int) -> np.ndarray:\n    return data - scalar\n\n\ndef raise_to_power(data: np.ndarray, power: int) -> np.ndarray:\n    return np.power(data, power)\n\n\ndef process_data_fix_1():\n    # no extra reference to the original array\n    return add_scalar(\n        duplicate_data(\n            raise_to_power(\n                subtract_scalar(load_xMb_of_data(SIZE_OF_DATA_IN_MB), SUBTRACT_AMOUNT),\n                POWER_AMOUNT,\n            )\n        ),\n        ADD_AMOUNT,\n    )\n\n\ndef process_data_fix_2():\n    # reusing the local variable instead of allocating more space\n    # this approach is called 'hidden mutability'\n    data = load_xMb_of_data(SIZE_OF_DATA_IN_MB)\n    data = subtract_scalar(data, SUBTRACT_AMOUNT)\n    data = raise_to_power(data, POWER_AMOUNT)\n    data = duplicate_data(data)\n    data = add_scalar(data, ADD_AMOUNT)\n    return data\n\n\n# Use these to select which solution to test\nprocess_data = process_data_fix_1\n\nif __name__ == \"__main__\":\n    process_data()\n"
  },
  {
    "path": "docs/tutorials/solutions/exercise_3/lru_cache.py",
    "content": "import functools\nfrom collections import Counter\n\n# DO NOT CHANGE\nFIRST_COUNTER_RANGE = 500\nSECOND_COUNTER_RANGE = 1000\n# DO NOT CHANGE\n\n\nclass Algorithms:\n    def __init__(self, inc: int):\n        self.inc = inc\n        self.factorial_plus = functools.cache(self._uncached_factorial_plus)\n\n    def _uncached_factorial_plus(self, n: int) -> int:\n        return n * self.factorial_plus(n - 1) + self.inc if n > 1 else 1 + self.inc\n\n\ndef generate_factorial_plus_last_digit(plus_range: int, factorial_range: int):\n    for i in range(plus_range):\n        A = Algorithms(i)\n        for j in range(factorial_range):\n            yield A.factorial_plus(j) % 10\n\n\ndef compare_counts_different_factorials():\n    counts_500 = Counter(\n        generate_factorial_plus_last_digit(FIRST_COUNTER_RANGE, FIRST_COUNTER_RANGE)\n    )\n    counts_1000 = Counter(\n        generate_factorial_plus_last_digit(SECOND_COUNTER_RANGE, SECOND_COUNTER_RANGE)\n    )\n    print(counts_500.most_common())\n    print(counts_1000.most_common())\n\n\nif __name__ == \"__main__\":\n    compare_counts_different_factorials()\n"
  },
  {
    "path": "docs/tutorials/tests/__init__.py",
    "content": ""
  },
  {
    "path": "docs/tutorials/tests/test_exercise_1.py",
    "content": "import pytest\nfrom exercise_1.fibonacci import generate_fibonacci_hash\n\n# Memory tests\n\n\n@pytest.mark.limit_memory(\"100 KB\")\ndef test_fibonacci():\n    LENGTH_OF_SEQUENCE_1 = 33333  # pylint: disable=invalid-name\n    LENGTH_OF_SEQUENCE_2 = 30000  # pylint: disable=invalid-name\n    LENGTH_OF_SEQUENCE_3 = 34567  # pylint: disable=invalid-name\n\n    generate_fibonacci_hash(\n        LENGTH_OF_SEQUENCE_1, LENGTH_OF_SEQUENCE_2, LENGTH_OF_SEQUENCE_3\n    )\n\n\n# Correctness tests\n\n\ndef test_fibonacci_empty():\n    h = generate_fibonacci_hash(0, 0, 0)\n    assert h == 0\n\n\n@pytest.mark.parametrize(\n    (\"length\", \"expected\"),\n    [\n        (1, 1),\n        (2, 2),  # 1 + 1\n        (6, 20),  # 1 + 1 + 2 + 3 + 5 + 8\n    ],\n)\ndef test_fibonacci_short(length, expected):\n    h = generate_fibonacci_hash(0, 0, length)\n    assert h == expected\n\n\n@pytest.mark.parametrize(\n    (\"length\", \"expected\"),\n    [\n        (1, 1),\n        (2, 2),  # 1 + 1\n        (6, 20),  # 1 + 1 + 2 + 3 + 5 + 8\n    ],\n)\ndef test_fibonacci_multiple(length, expected):\n    h = generate_fibonacci_hash(length, length, length)\n    assert h == expected * 3\n\n\ndef test_hash_modulo_10000():\n    # 1 + 1 + 2 +3 + 5 + 8 + 13 + 21 + 34 + 55 + 89 + 144 + 233 + 377 + 610\n    # + 987 + 1597 + 2584 + 4181 == 10945\n    h = generate_fibonacci_hash(0, 0, 19)\n    assert h == 945  # 10945 % 10000\n"
  },
  {
    "path": "docs/tutorials/tests/test_exercise_2.py",
    "content": "import numpy as np\nimport pytest\nfrom exercise_2.holding_onto_memory import process_data\n\n\n@pytest.mark.limit_memory(\"230 MB\")\ndef test_holding_in_memory():\n    process_data()\n\n\ndef test_result():\n    result = process_data()\n    assert np.all(result == 18)\n"
  },
  {
    "path": "docs/tutorials/tests/test_exercise_3.py",
    "content": "import math\n\nimport pytest\nfrom exercise_3.lru_cache import Algorithms\nfrom exercise_3.lru_cache import compare_counts_different_factorials\nfrom exercise_3.lru_cache import generate_factorial_plus_last_digit\n\n# Memory tests\n\n\n@pytest.mark.limit_memory(\"200 MB\")\ndef test_lru_cache():\n    compare_counts_different_factorials()\n\n\n# Correctness tests\n\n\n@pytest.mark.parametrize(\"value\", [1, 4, 10])\ndef test_algorithms_0(value):\n    a = Algorithms(0)  # This is equivalent to the standard factorial function\n    assert a.factorial_plus(value) == math.factorial(value)\n\n\ndef test_algorithms_5():\n    a = Algorithms(5)\n\n    # 3 * (2 * (1 + 5) + 5) + 5\n    assert a.factorial_plus(3) == 56\n\n    # 4 * (3 * (2 * (1 + 5) + 5) + 5) + 5\n    assert a.factorial_plus(4) == 229\n\n\ndef test_generate_factorial_plus_last_digit_0():\n    values = list(generate_factorial_plus_last_digit(1, 6))\n    assert values == [1, 1, 2, 6, 4, 0]  # last digits of 1 1 2 6 24 120, i.e. 0! to 5!\n\n\ndef test_generate_factorial_plus_0_last_digit():\n    values = list(generate_factorial_plus_last_digit(5, 1))\n    assert values == [\n        1,\n        2,\n        3,\n        4,\n        5,\n    ]  # last digits of the first fac_plus_n factorial of 0, which is always n+1\n\n\ndef test_generate_factorial_plus():\n    values = list(generate_factorial_plus_last_digit(3, 5))\n    expected = (\n        [1, 1, 2, 6, 4]\n        + [2, 2, 5, 6, 5]  # last digits of the first fac_plus_0 factorial of n, i.e. n!\n        + [3, 3, 8, 6, 6]  # fac_plus_1 values are [2, 2, 5, 16, 65]\n    )  # fac_plus_1 values are [3, 3, 8, 26, 106]\n    assert (\n        values == expected\n    )  # last digits of the first fac_plus(n) factorial of 0, which is always n+1\n"
  },
  {
    "path": "news/.gitignore",
    "content": "!.gitignore\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"memray\",\n  \"private\": true,\n  \"devDependencies\": {\n    \"@babel/preset-env\": \"^7.14.7\",\n    \"copy-webpack-plugin\": \"^14.0.0\",\n    \"jest\": \"^27.0.1\",\n    \"lodash\": \"^4.17.23\",\n    \"webpack\": \"^5.105.2\",\n    \"webpack-cli\": \"^4.7.0\"\n  },\n  \"dependencies\": {\n    \"@floating-ui/dom\": \"^1.7.5\",\n    \"bootstrap\": \"4.6.0\",\n    \"d3\": \"7.9.0\",\n    \"d3-flame-graph\": \"4.1.3\",\n    \"d3-scale-chromatic\": \"3.1.0\",\n    \"datatables.net\": \"1.11.3\",\n    \"datatables.net-bs4\": \"1.10.23\",\n    \"jquery\": \"3.6.0\",\n    \"plotly.js-dist-min\": \"2.11.1\",\n    \"popper.js\": \"1.16.1\"\n  },\n  \"jest\": {\n    \"modulePathIgnorePatterns\": [\n      \"<rootDir>/build/\",\n      \"<rootDir>/node_modules/\"\n    ]\n  },\n  \"scripts\": {\n    \"build\": \"webpack\",\n    \"test\": \"jest\"\n  }\n}\n"
  },
  {
    "path": "pyproject.toml",
    "content": "[build-system]\n\nrequires = [\n     \"setuptools\",\n     \"wheel\",\n     \"pkgconfig\",\n     \"Cython>=0.29.31\"\n]\n\nbuild-backend = 'setuptools.build_meta'\n\n[tool.ruff]\nline-length = 95\nselect = [\"C4\", \"E\", \"F\", \"I001\", \"PERF\", \"W\"]\nfix = true\n\n[tool.ruff.isort]\nforce-single-line = true\nknown-first-party = [\"memray\"]\nknown-third-party=[\"rich\", \"elftools\", \"pytest\"]\n\n[tool.ruff.per-file-ignores]\n\"benchmarks/*\" = [\"C4\", \"PERF\"]\n\n[tool.isort]\nforce_single_line = true\nmulti_line_output = 3\ninclude_trailing_comma = true\nforce_grid_wrap = 0\nuse_parentheses = true\nline_length = 88\nknown_first_party=[\"memray\"]\nknown_third_party=[\"rich\", \"elftools\", \"pytest\"]\n\n[tool.towncrier]\npackage = \"memray\"\npackage_dir = \"src\"\nfilename = \"NEWS.rst\"\ndirectory = \"news\"\ntype = [\n  { name = \"Features\",                  directory = \"feature\", showcontent = true },\n  { name = \"Deprecations and Removals\", directory = \"removal\", showcontent = true },\n  { name = \"Bug Fixes\",                 directory = \"bugfix\",  showcontent = true },\n  { name = \"Improved Documentation\",    directory = \"doc\",     showcontent = true },\n  { name = \"Miscellaneous\",             directory = \"misc\",    showcontent = true },\n]\nunderlines = \"-~\"\n\n[tool.pytest.ini_options]\nmarkers = [\n    \"valgrind\",\n]\nxfail_strict = true\ntestpaths = [\"tests\"]\n\n[tool.check-manifest]\nignore = [\n  \"src/memray/reporters/templates/assets/*.js\",\n]\n\n[tool.mypy]\nexclude=\"tests/integration/(native_extension|multithreaded_extension)/\"\n\n[tool.cibuildwheel]\nbuild = [\"cp38-*\", \"cp39-*\", \"cp310-*\", \"cp311-*\"]\nskip = \"*musllinux*{i686,aarch64}*\"\nmanylinux-x86_64-image = \"manylinux2014\"\nmanylinux-i686-image = \"manylinux2014\"\nmusllinux-x86_64-image = \"musllinux_1_2\"\n\n[tool.cibuildwheel.linux]\nbefore-all = [\n  # Build the latest curl from source.\n  \"yum install -y openssl-devel\",\n  \"cd /\",\n  \"CURL_VERS=8.7.1\",\n  \"curl -LO https://curl.se/download/curl-$CURL_VERS.tar.bz2\",\n  \"tar xf ./curl-$CURL_VERS.tar.bz2\",\n  \"cd curl-$CURL_VERS\",\n  \"./configure --with-openssl\",\n  \"make install\",\n\n  # Build the latest zstd from source\n  \"yum install -y lz4-devel xz-devel\",\n  \"cd /\",\n  \"ZSTD_VERS=1.5.6\",\n  \"/usr/bin/curl -LO https://github.com/facebook/zstd/releases/download/v1.5.6/zstd-$ZSTD_VERS.tar.gz\",\n  \"tar xf ./zstd-$ZSTD_VERS.tar.gz\",\n  \"cd zstd-$ZSTD_VERS\",\n  \"V=1 LDLIBS=-lrt make install\",\n\n  # Build the latest elfutils from source.\n  \"yum install -y lz4-devel\",\n  \"cd /\",\n  \"VERS=0.191\",\n  \"/usr/bin/curl -L https://mirrors.kernel.org/sourceware/elfutils/$VERS/elfutils-$VERS.tar.bz2 >./elfutils.tar.bz2\",\n  \"tar -xf elfutils.tar.bz2\",\n  \"cd elfutils-$VERS\",\n  \"CFLAGS='-Wno-error -g -O3' CXXFLAGS='-Wno-error -g -O3' LDFLAGS=-lrt ./configure --enable-libdebuginfod --disable-debuginfod --disable-nls --with-zstd\",\n  \"make install\",\n\n  # Install Memray's other build and test dependencies\n  \"yum install -y libunwind-devel\",\n]\n\n[tool.cibuildwheel.macos]\nbefore-all = [\n  \"git clone --depth 1 --branch v1.9.4 https://github.com/lz4/lz4 lz4\",\n  \"cd lz4\",\n  \"make\",\n  \"make install PREFIX=$LZ4_INSTALL_DIR\",\n  \"find $LZ4_INSTALL_DIR\",\n]\nbefore-test = [\n  \"codesign --remove-signature /Library/Frameworks/Python.framework/Versions/*/bin/python3 || true\",\n  \"codesign --remove-signature /Library/Frameworks/Python.framework/Versions/*/Resources/Python.app/Contents/MacOS/Python || true\",\n]\n\n[tool.coverage.run]\nplugins = [\n  \"Cython.Coverage\",\n]\nsource = [\n  \"src/memray\",\n  \"tests/\",\n]\nbranch = true\nparallel = true\nomit = [\n  \"*__init__.py\",\n]\n\n[tool.coverage.report]\nskip_covered = true\nshow_missing = true\n\n\n# Override the default linux before-all for musl linux\n[[tool.cibuildwheel.overrides]]\nselect = \"*-musllinux*\"\nbefore-all = [\n  # Remove gettext-dev, which conficts with the musl-libintl, which is a build\n  # dependency of elfutils.\n  \"apk del gettext-dev glib-dev\",\n\n  # Build the latest elfutils from source. The build steps come from\n  # https://git.alpinelinux.org/aports/tree/main/elfutils, and the need to\n  # set the FNM_EXTMATCH macro to get the build to succeed is seen here:\n  # https://git.alpinelinux.org/aports/tree/main/elfutils/musl-macros.patch\n  \"cd /\",\n  \"apk add --update argp-standalone bison bsd-compat-headers bzip2-dev curl-dev flex-dev libtool linux-headers musl-fts-dev musl-libintl musl-obstack-dev xz-dev zlib-dev zstd-dev\",\n  \"VERS=0.191\",\n  \"curl -L https://mirrors.kernel.org/sourceware/elfutils/$VERS/elfutils-$VERS.tar.bz2 >./elfutils.tar.bz2\",\n  \"tar -xf elfutils.tar.bz2\",\n  \"cd elfutils-$VERS\",\n  \"CFLAGS='-Wno-error -DFNM_EXTMATCH=0 -g -O3' CXXFLAGS='-Wno-error -g -O3' ./configure --enable-libdebuginfod --disable-debuginfod --disable-nls --with-zstd\",\n  \"make install\",\n\n  # Reinstall libintl, as the Python interpreter requires it\n  \"apk del musl-libintl\",\n  \"apk add libintl\",\n\n  # Install Memray's other build and test dependencies\n  \"apk add --update libunwind-dev lz4-dev\"\n]\n"
  },
  {
    "path": "requirements-docs.txt",
    "content": "IPython\nsphinx\nsphinx-autobuild\nsphinx-argparse\nfuro\n"
  },
  {
    "path": "requirements-extra.txt",
    "content": "mypy\nbump2version\ntowncrier\npre-commit\n-r requirements-docs.txt\n"
  },
  {
    "path": "requirements-test.txt",
    "content": "Cython\ncoverage[toml]\ngreenlet; python_version < '3.14'\npytest\npytest-cov\nipython\nsetuptools\npkgconfig\npytest-textual-snapshot\ntextual >= 0.43, != 0.65.2, != 0.66\npackaging\n"
  },
  {
    "path": "setup.py",
    "content": "import distutils.command.build\nimport distutils.log\nimport os\nimport pathlib\nimport subprocess\nimport sys\nimport tempfile\nfrom sys import platform\nfrom sys import version_info\n\nimport pkgconfig\nfrom Cython.Build import cythonize\nfrom setuptools import Extension\nfrom setuptools import find_packages\nfrom setuptools import setup\nfrom setuptools.command.build_ext import build_ext as build_ext_orig\n\nIS_MAC = sys.platform == \"darwin\"\nIS_LINUX = \"linux\" in sys.platform\n\nLIBBACKTRACE_LOCATION = (\n    pathlib.Path(__file__).parent / \"src\" / \"vendor\" / \"libbacktrace\"\n).resolve()\n\nLIBBACKTRACE_INCLUDEDIRS = LIBBACKTRACE_LOCATION / \"install\" / \"include\"\nLIBBACKTRACE_LIBDIR = LIBBACKTRACE_LOCATION / \"install\" / \"lib\"\n\nASSETS_LOCATION = (\n    pathlib.Path(__file__).parent\n    / \"src\"\n    / \"memray\"\n    / \"reporters\"\n    / \"templates\"\n    / \"assets\"\n)\n\n\nclass BuildMemray(build_ext_orig):\n    def run(self):\n        self.build_js_files()\n        self.build_libbacktrace()\n        super().run()\n\n    def announce_and_run(self, command, **kwargs):\n        self.announce(\n            \"executing command: `{}`\".format(\" \".join(command)),\n            level=distutils.log.INFO,\n        )\n        subprocess.run(command, check=True, **kwargs)\n\n    def build_libbacktrace(self):\n        archive_location = LIBBACKTRACE_LIBDIR / \"libbacktrace.a\"\n\n        if archive_location.exists():\n            return\n\n        if not LIBBACKTRACE_LOCATION.exists():\n            self.announce_and_run(\n                [f\"{LIBBACKTRACE_LOCATION.parent / 'regenerate_libbacktrace.sh'}\"],\n                cwd=LIBBACKTRACE_LOCATION.parent,\n            )\n\n        configure_cmd = [\n            f\"{LIBBACKTRACE_LOCATION}/configure\",\n            \"--with-pic\",\n            \"--prefix\",\n            f\"{LIBBACKTRACE_LOCATION}/install\",\n            \"--includedir\",\n            f\"{LIBBACKTRACE_LOCATION}/install/include/libbacktrace\",\n        ]\n        libbacktrace_target = os.getenv(\"MEMRAY_LIBBACKTRACE_TARGET\")\n        if libbacktrace_target is not None:\n            configure_cmd.extend([\"--host\", libbacktrace_target])\n\n        with tempfile.TemporaryDirectory() as tmpdirname:\n            self.announce_and_run(\n                configure_cmd,\n                cwd=tmpdirname,\n            )\n            self.announce_and_run([\"make\", \"-j\"], cwd=tmpdirname)\n            self.announce_and_run([\"make\", \"install\"], cwd=tmpdirname)\n\n    def build_js_files(self):\n        if any(ASSETS_LOCATION.glob(\"*.js\")):\n            return\n\n        self.announce_and_run([\"npm\", \"install\"])\n        self.announce_and_run([\"npm\", \"run-script\", \"build\"])\n\n\ninstall_requires = [\n    \"jinja2 >= 2.9\",\n    \"typing_extensions; python_version < '3.8.0'\",\n    \"rich >= 11.2.0\",\n    \"textual >= 0.41.0\",\n]\ndocs_requires = [\n    \"IPython\",\n    \"bump2version\",\n    \"sphinx\",\n    \"furo\",\n    \"sphinx-argparse\",\n    \"towncrier\",\n]\n\nlint_requires = [\n    \"black\",\n    \"flake8\",\n    \"isort\",\n    \"mypy\",\n    \"check-manifest\",\n]\n\ntest_requires = [\n    \"Cython\",\n    \"greenlet; python_version < '3.14'\",\n    \"pytest\",\n    \"pytest-cov\",\n    \"ipython\",\n    \"setuptools\",\n    \"pytest-textual-snapshot\",\n    \"textual >= 0.43, != 0.65.2, != 0.66\",\n    \"packaging\",\n]\n\nbenchmark_requires = [\n    \"asv\",\n]\n\n\nTEST_BUILD = False\nif \"--test-build\" in sys.argv:\n    TEST_BUILD = True\n    sys.argv.remove(\"--test-build\")\n\n\nif os.getenv(\"CYTHON_TEST_MACROS\", None) is not None:\n    TEST_BUILD = True\n\nMINIMIZE_INLINING = os.getenv(\"MEMRAY_MINIMIZE_INLINING\", \"\") != \"\"\n\nCOMPILER_DIRECTIVES = {\n    \"language_level\": 3,\n    \"embedsignature\": True,\n    \"boundscheck\": False,\n    \"wraparound\": False,\n    \"cdivision\": True,\n    \"profile\": False,\n    \"linetrace\": False,\n    \"c_string_type\": \"unicode\",\n    \"c_string_encoding\": \"utf8\",\n    \"freethreading_compatible\": True,\n}\nEXTRA_COMPILE_ARGS = []\nEXTRA_LINK_ARGS = []\nUNDEF_MACROS = []\n\nif MINIMIZE_INLINING:\n    EXTRA_COMPILE_ARGS.append(\"-Og\")\nelse:\n    EXTRA_COMPILE_ARGS.append(\"-flto\")\n    EXTRA_LINK_ARGS.append(\"-flto\")\n\n# For Python 3.9+, hide all of our symbols except the module init function. For\n# Python 3.8 and earlier this isn't as easy, because PyMODINIT_FUNC doesn't\n# include __attribute__((visibility (\"default\"))), and Cython doesn't give us\n# a way to add the attribute. So, skip this optimization on 3.8 and earlier.\nif sys.version_info[:2] >= (3, 9):\n    EXTRA_COMPILE_ARGS.append(\"-fvisibility=hidden\")\n\nif TEST_BUILD:\n    COMPILER_DIRECTIVES = {\n        \"language_level\": 3,\n        \"boundscheck\": True,\n        \"embedsignature\": True,\n        \"wraparound\": True,\n        \"cdivision\": False,\n        \"profile\": False,\n        \"linetrace\": False,\n        \"overflowcheck\": True,\n        \"infer_types\": True,\n        \"c_string_type\": \"unicode\",\n        \"c_string_encoding\": \"utf8\",\n        \"freethreading_compatible\": True,\n    }\n    EXTRA_COMPILE_ARGS = []\n    UNDEF_MACROS = [\"NDEBUG\"]\n    if IS_LINUX:\n        EXTRA_COMPILE_ARGS.extend([\"-D_GLIBCXX_DEBUG\", \"-D_LIBCPP_DEBUG\"])\n\nDEFINE_MACROS = []\n\n# Ensure that we have a 64-bit off_t in all translation units.\nDEFINE_MACROS.append((\"_FILE_OFFSET_BITS\", \"64\"))\n\n# memray uses thread local storage (TLS) variables. As memray is compiled\n# into a Python extension, is a shared object. TLS variables in shared objects\n# use the most conservative and slow TLS model available by default:\n# global-dynamic. This TLS model generates function calls (__tls_get_addr) to\n# obtain the address of the TLS storage block, which is quite slow.  To\n# circuvent the slowdown, memray uses by default a less restrictive model:\n# initial-exec. This model is very fast but uses the limited TLS storage of the\n# executable. This means that is possible that dlopen will refuse to load the\n# shared object of the extension if there is not enough space. glibc reserves\n# 1152 bytes for oportunustic usage for shared libraries with initial-exec, so\n# this model will not present problems as long as the application uses glibc. In\n# case these assumptions are wrong, memray can revert to use the most\n# conservative model by setting the NO_MEMRAY_FAST_TLS environment variable.\n\nMEMRAY_FAST_TLS = True\nif os.getenv(\"NO_MEMRAY_FAST_TLS\", None) is not None:\n    MEMRAY_FAST_TLS = False\n\nif MEMRAY_FAST_TLS:\n    DEFINE_MACROS.append((\"USE_MEMRAY_TLS_MODEL\", \"1\"))\n\nBINARY_FORMATS = {\"darwin\": \"macho\", \"linux\": \"elf\"}\nBINARY_FORMAT = BINARY_FORMATS.get(sys.platform, \"elf\")\n\nlibrary_flags = {\"libraries\": [\"lz4\"]}\nif IS_LINUX:\n    library_flags[\"libraries\"].append(\"unwind\")\n    library_flags[\"libraries\"].append(\"debuginfod\")\n\ntry:\n    library_flags = pkgconfig.parse(\n        \" \".join(f\"lib{libname}\" for libname in library_flags[\"libraries\"])\n    )\nexcept EnvironmentError as e:\n    print(\"pkg-config not found.\", e)\n    print(\"Falling back to static flags.\")\nexcept pkgconfig.PackageNotFoundError as e:\n    print(\"Package Not Found\", e)\n    print(\"Falling back to static flags.\")\n\nMEMRAY_EXTENSION = Extension(\n    name=\"memray._memray\",\n    sources=[\n        \"src/memray/_memray.pyx\",\n        \"src/memray/_memray/compat.cpp\",\n        \"src/memray/_memray/hooks.cpp\",\n        \"src/memray/_memray/tracking_api.cpp\",\n        f\"src/memray/_memray/{BINARY_FORMAT}_shenanigans.cpp\",\n        \"src/memray/_memray/logging.cpp\",\n        \"src/memray/_memray/python_helpers.cpp\",\n        \"src/memray/_memray/source.cpp\",\n        \"src/memray/_memray/sink.cpp\",\n        \"src/memray/_memray/records.cpp\",\n        \"src/memray/_memray/record_reader.cpp\",\n        \"src/memray/_memray/record_writer.cpp\",\n        \"src/memray/_memray/snapshot.cpp\",\n        \"src/memray/_memray/socket_reader_thread.cpp\",\n        \"src/memray/_memray/native_resolver.cpp\",\n    ],\n    language=\"c++\",\n    extra_compile_args=[\"-std=c++17\", \"-Wall\", *EXTRA_COMPILE_ARGS],\n    extra_objects=[str(LIBBACKTRACE_LIBDIR / \"libbacktrace.a\")],\n    extra_link_args=[\"-std=c++17\", *EXTRA_LINK_ARGS],\n    define_macros=DEFINE_MACROS,\n    undef_macros=UNDEF_MACROS,\n    **library_flags,\n)\n\nMEMRAY_EXTENSION.include_dirs[:0] = [\"src\", str(LIBBACKTRACE_INCLUDEDIRS)]\nMEMRAY_EXTENSION.libraries.append(\"dl\")\n\n\nMEMRAY_TEST_EXTENSION = Extension(\n    name=\"memray._test_utils\",\n    sources=[\n        \"src/memray/_memray_test_utils.pyx\",\n    ],\n    language=\"c++\",\n    extra_compile_args=[\"-std=c++17\", \"-Wall\", *EXTRA_COMPILE_ARGS],\n    extra_link_args=[\"-std=c++17\", *EXTRA_LINK_ARGS],\n    define_macros=DEFINE_MACROS,\n    undef_macros=UNDEF_MACROS,\n)\n\nMEMRAY_INJECT_EXTENSION = Extension(\n    name=\"memray._inject\",\n    sources=[\n        \"src/memray/_memray/inject.cpp\",\n    ],\n    language=\"c++\",\n    extra_compile_args=[\"-std=c++17\", \"-Wall\", *EXTRA_COMPILE_ARGS],\n    extra_link_args=[\"-std=c++17\", *EXTRA_LINK_ARGS],\n    define_macros=DEFINE_MACROS,\n    undef_macros=UNDEF_MACROS,\n    py_limited_api=True,\n)\n\n\nif not (IS_LINUX or IS_MAC):\n    raise RuntimeError(f\"memray does not support this platform ({platform})\")\n\nabout = {}\nwith open(\"src/memray/_version.py\") as fp:\n    exec(fp.read(), about)\n\n\nHERE = pathlib.Path(__file__).parent.resolve()\nLONG_DESCRIPTION = (HERE / \"README.md\").read_text(encoding=\"utf-8\")\n\nsetup(\n    name=\"memray\",\n    version=about[\"__version__\"],\n    python_requires=\">=3.7.0\",\n    description=\"A memory profiler for Python applications\",\n    long_description=LONG_DESCRIPTION,\n    long_description_content_type=\"text/markdown\",\n    url=\"https://github.com/bloomberg/memray\",\n    author=\"Pablo Galindo Salgado\",\n    classifiers=[\n        \"Intended Audience :: Developers\",\n        \"License :: OSI Approved :: Apache Software License\",\n        \"Operating System :: POSIX :: Linux\",\n        \"Operating System :: MacOS\",\n        \"Programming Language :: Python :: 3.7\",\n        \"Programming Language :: Python :: 3.8\",\n        \"Programming Language :: Python :: 3.9\",\n        \"Programming Language :: Python :: 3.10\",\n        \"Programming Language :: Python :: 3.11\",\n        \"Programming Language :: Python :: 3.12\",\n        \"Programming Language :: Python :: 3.13\",\n        \"Programming Language :: Python :: 3.14\",\n        \"Programming Language :: Python :: Implementation :: CPython\",\n        \"Topic :: Software Development :: Debuggers\",\n    ],\n    license=\"Apache 2.0\",\n    package_dir={\"\": \"src\"},\n    packages=find_packages(where=\"src\", exclude=\"memray/_memray/\"),\n    ext_modules=cythonize(\n        [MEMRAY_EXTENSION, MEMRAY_TEST_EXTENSION, MEMRAY_INJECT_EXTENSION],\n        include_path=[\"src/memray\"],\n        compiler_directives=COMPILER_DIRECTIVES,\n    ),\n    include_package_data=True,\n    exclude_package_data={\"memray\": [\"_memray/*\"]},\n    install_requires=install_requires,\n    extras_require={\n        \"test\": test_requires,\n        \"docs\": docs_requires,\n        \"lint\": lint_requires,\n        \"benchmark\": benchmark_requires,\n        \"dev\": test_requires + lint_requires + docs_requires + benchmark_requires,\n    },\n    entry_points={\n        \"console_scripts\": [\n            f\"memray{version_info.major}.{version_info.minor}=memray.__main__:main\",\n            \"memray=memray.__main__:main\",\n        ],\n    },\n    cmdclass={\n        \"build_ext\": BuildMemray,\n    },\n)\n"
  },
  {
    "path": "src/memray/__init__.py",
    "content": "from ._ipython import load_ipython_extension\nfrom ._memray import AllocationRecord\nfrom ._memray import AllocatorType\nfrom ._memray import Destination\nfrom ._memray import FileDestination\nfrom ._memray import FileFormat\nfrom ._memray import FileReader\nfrom ._memray import MemorySnapshot\nfrom ._memray import SocketDestination\nfrom ._memray import SocketReader\nfrom ._memray import Tracker\nfrom ._memray import dump_all_records\nfrom ._memray import set_log_level\nfrom ._memray import start_thread_trace\nfrom ._metadata import Metadata\nfrom ._version import __version__\n\n__all__ = [\n    \"AllocationRecord\",\n    \"AllocatorType\",\n    \"FileFormat\",\n    \"MemorySnapshot\",\n    \"dump_all_records\",\n    \"start_thread_trace\",\n    \"Tracker\",\n    \"FileReader\",\n    \"SocketReader\",\n    \"Destination\",\n    \"FileDestination\",\n    \"SocketDestination\",\n    \"Metadata\",\n    \"__version__\",\n    \"set_log_level\",\n    \"load_ipython_extension\",\n]\n"
  },
  {
    "path": "src/memray/__init__.pyi",
    "content": "from memray._destination import Destination as Destination\nfrom memray._destination import FileDestination as FileDestination\nfrom memray._destination import SocketDestination as SocketDestination\nfrom memray._metadata import Metadata as Metadata\n\nfrom ._memray import AllocationRecord as AllocationRecord\nfrom ._memray import AllocatorType as AllocatorType\nfrom ._memray import FileFormat as FileFormat\nfrom ._memray import FileReader as FileReader\nfrom ._memray import MemorySnapshot as MemorySnapshot\nfrom ._memray import SocketReader as SocketReader\nfrom ._memray import Tracker as Tracker\nfrom ._memray import dump_all_records as dump_all_records\n"
  },
  {
    "path": "src/memray/__main__.py",
    "content": "import sys\n\nfrom memray.commands import main\n\nif __name__ == \"__main__\":\n    sys.exit(main())\n"
  },
  {
    "path": "src/memray/_destination.py",
    "content": "import pathlib\nimport typing\nfrom dataclasses import dataclass\n\n\n@dataclass(frozen=True)\nclass Destination:\n    pass\n\n\n@dataclass(frozen=True)\nclass FileDestination(Destination):\n    \"\"\"Specify an output file to write captured allocations into.\n\n    Args:\n        path: The path to the output file.\n        overwrite: By default, if a file already exists at that path an\n            exception will be raised. If you provide ``overwrite=True``, then\n            the existing file will be overwritten instead.\n    \"\"\"\n\n    path: typing.Union[pathlib.Path, str]\n    overwrite: bool = False\n    compress_on_exit: bool = True\n\n\n@dataclass(frozen=True)\nclass SocketDestination(Destination):\n    \"\"\"Specify a port to serve captured allocations on.\n\n    When a ``SocketDestination`` is passed to the `Tracker` constructor, the\n    process will immediately create a server socket on the given port and wait\n    for a reader to connect (see :ref:`Live Tracking`). The `Tracker`\n    constructor will not return until a client has connected. Any records the\n    tracker goes on to capture will be written over the socket to the attached\n    client.\n\n    Args:\n        server_port: The port to accept a client connection on.\n        address: The address to bind the server socket to. This should\n            generally be left alone, but you might want to use ``\"0.0.0.0\"`` to\n            accept connections from clients on other machines. Note that\n            sending records to clients on other machines is generally a bad\n            idea, though. In particular, this won't play nicely with\n            :ref:`Native Tracking`, because the client on the remote machine\n            won't have access to the shared libraries used by the tracked\n            process.\n    \"\"\"\n\n    server_port: int\n    address: str = \"127.0.0.1\"\n"
  },
  {
    "path": "src/memray/_errors.py",
    "content": "from typing import Any\n\n\nclass MemrayError(Exception):\n    \"\"\"Exceptions raised in this package.\"\"\"\n\n\nclass MemrayCommandError(MemrayError):\n    \"\"\"Exceptions raised from this package's CLI commands.\"\"\"\n\n    def __init__(self, *args: Any, exit_code: int) -> None:\n        super().__init__(*args)\n        self.exit_code = exit_code\n"
  },
  {
    "path": "src/memray/_ipython/__init__.py",
    "content": "from typing import Any\n\n\ndef load_ipython_extension(ipython: Any) -> None:\n    from .flamegraph import FlamegraphMagics\n\n    ipython.register_magics(FlamegraphMagics)\n\n\n__all__ = [\"load_ipython_extension\"]\n"
  },
  {
    "path": "src/memray/_ipython/flamegraph.py",
    "content": "import argparse\nimport shlex\nimport tempfile\nfrom pathlib import Path\nfrom textwrap import dedent\nfrom textwrap import indent\nfrom typing import Any\nfrom typing import Callable\nfrom typing import cast\n\nfrom IPython.core.error import UsageError\nfrom IPython.core.magic import Magics\nfrom IPython.core.magic import cell_magic\nfrom IPython.core.magic import magics_class\nfrom IPython.display import IFrame\nfrom IPython.display import display\nfrom rich import print as pprint\n\nfrom memray import FileReader\nfrom memray.commands.common import warn_if_not_enough_symbols\nfrom memray.reporters.flamegraph import FlameGraphReporter\n\nTEMPLATE = \"\"\"\\\nfrom memray import Tracker, FileFormat\nwith Tracker(\n    \"{dump_file!s}\",\n    native_traces={native_traces},\n    trace_python_allocators={trace_python_allocators},\n    follow_fork={follow_fork},\n    file_format=FileFormat.{file_format},\n) as tracker:\n{code}\n\"\"\"\n\n\ndef _run_cell(shell: Any, code: str) -> None:\n    run_cell = cast(Callable[[str], Any], shell.run_cell)\n    run_cell(code)\n\n\ndef _display_iframe(frame: IFrame) -> None:\n    show = cast(Callable[[IFrame], Any], display)\n    show(frame)\n\n\ndef argument_parser() -> argparse.ArgumentParser:\n    parser = argparse.ArgumentParser(prog=\"%%memray_flamegraph\")\n    parser.add_argument(\n        \"--native\",\n        help=\"Track native (C/C++) stack frames as well\",\n        action=\"store_true\",\n        dest=\"native\",\n        default=False,\n    )\n    parser.add_argument(\n        \"--follow-fork\",\n        action=\"store_true\",\n        help=\"Record allocations in child processes forked from the tracked script\",\n        default=False,\n    )\n    parser.add_argument(\n        \"--trace-python-allocators\",\n        action=\"store_true\",\n        help=\"Record allocations made by the pymalloc allocator\",\n        default=False,\n    )\n    alloc_type_group = parser.add_mutually_exclusive_group()\n    alloc_type_group.add_argument(\n        \"--leaks\",\n        help=\"Show memory leaks, instead of peak memory usage\",\n        action=\"store_true\",\n        dest=\"show_memory_leaks\",\n        default=False,\n    )\n    alloc_type_group.add_argument(\n        \"--temporary-allocation-threshold\",\n        metavar=\"N\",\n        help=dedent(\n            \"\"\"\n            Report temporary allocations, as opposed to leaked allocations\n            or high watermark allocations.  An allocation is considered\n            temporary if at most N other allocations occur before it is\n            deallocated.  With N=0, an allocation is temporary only if it\n            is immediately deallocated before any other allocation occurs.\n            \"\"\"\n        ),\n        action=\"store\",\n        dest=\"temporary_allocation_threshold\",\n        type=int,\n        default=-1,\n    )\n    alloc_type_group.add_argument(\n        \"--temporary-allocations\",\n        help=\"Equivalent to --temporary-allocation-threshold=1\",\n        action=\"store_const\",\n        dest=\"temporary_allocation_threshold\",\n        const=1,\n    )\n\n    parser.add_argument(\n        \"--temporal\",\n        help=(\n            \"Generate a dynamic flame graph that can analyze\"\n            \" allocations in a user-selected time range.\"\n        ),\n        action=\"store_true\",\n        default=False,\n    )\n    parser.add_argument(\n        \"--split-threads\",\n        help=\"Do not merge allocations across threads\",\n        action=\"store_true\",\n        default=False,\n    )\n    parser.add_argument(\n        \"--inverted\",\n        help=(\n            \"Invert the flame graph: \"\n            \"use allocators as roots instead of thread entry points\"\n        ),\n        action=\"store_true\",\n        default=False,\n    )\n    parser.add_argument(\n        \"--max-memory-records\",\n        help=\"Maximum number of memory records to display\",\n        type=int,\n        default=None,\n    )\n\n    return parser\n\n\n@magics_class\nclass FlamegraphMagics(Magics):\n    @cell_magic  # type: ignore\n    def memray_flamegraph(self, line: str, cell: str) -> None:\n        \"\"\"Memory profile the code in the cell and display a flame graph.\"\"\"\n        if self.shell is None:\n            raise UsageError(\"Cannot profile code when not in a shell\")\n\n        try:\n            options = argument_parser().parse_args(shlex.split(line))\n        except SystemExit:\n            # argparse wants to bail if the options aren't valid.\n            # It already printed a message, just return control to IPython.\n            return\n\n        if options.temporal and options.temporary_allocation_threshold >= 0:\n            raise UsageError(\n                \"Can't create a temporal flame graph of temporary allocations\"\n            )\n        elif options.temporal or options.temporary_allocation_threshold >= 0:\n            file_format = \"ALL_ALLOCATIONS\"\n        else:\n            file_format = \"AGGREGATED_ALLOCATIONS\"\n\n        results_dir = Path(\"memray-results\")\n        results_dir.mkdir(exist_ok=True)\n\n        tempdir = Path(tempfile.mkdtemp(dir=results_dir))\n        dump_file = Path(tempdir) / \"memray.dump\"\n        code = TEMPLATE.format(\n            dump_file=dump_file,\n            native_traces=options.native,\n            trace_python_allocators=options.trace_python_allocators,\n            follow_fork=options.follow_fork,\n            code=indent(cell, \" \" * 4),\n            file_format=file_format,\n        )\n        _run_cell(self.shell, code)\n\n        merge_threads = not options.split_threads\n\n        reporter = None\n\n        kwargs = {}\n        if options.max_memory_records is not None:\n            kwargs[\"max_memory_records\"] = options.max_memory_records\n\n        with FileReader(dump_file, report_progress=True, **kwargs) as reader:\n            if reader.metadata.has_native_traces:\n                warn_if_not_enough_symbols()\n\n            if options.temporal:\n                if options.show_memory_leaks:\n                    temporal_snapshot = reader.get_temporal_allocation_records(\n                        merge_threads=merge_threads\n                    )\n                    reporter = FlameGraphReporter.from_temporal_snapshot(\n                        temporal_snapshot,\n                        memory_records=tuple(reader.get_memory_snapshots()),\n                        native_traces=reader.metadata.has_native_traces,\n                        high_water_mark_by_snapshot=None,\n                        inverted=options.inverted,\n                    )\n                else:\n                    recs, hwms = reader.get_temporal_high_water_mark_allocation_records(\n                        merge_threads=merge_threads\n                    )\n                    reporter = FlameGraphReporter.from_temporal_snapshot(\n                        recs,\n                        memory_records=tuple(reader.get_memory_snapshots()),\n                        native_traces=reader.metadata.has_native_traces,\n                        high_water_mark_by_snapshot=hwms,\n                        inverted=options.inverted,\n                    )\n            else:\n                if options.show_memory_leaks:\n                    snapshot = reader.get_leaked_allocation_records(\n                        merge_threads=merge_threads\n                    )\n                elif options.temporary_allocation_threshold >= 0:\n                    snapshot = reader.get_temporary_allocation_records(\n                        threshold=options.temporary_allocation_threshold,\n                        merge_threads=merge_threads,\n                    )\n                else:\n                    snapshot = reader.get_high_watermark_allocation_records(\n                        merge_threads=merge_threads\n                    )\n\n                memory_records = tuple(reader.get_memory_snapshots())\n                reporter = FlameGraphReporter.from_snapshot(\n                    snapshot,\n                    memory_records=memory_records,\n                    native_traces=options.native,\n                    inverted=options.inverted,\n                )\n\n        assert reporter is not None\n        flamegraph_path = Path(tempdir) / \"flamegraph.html\"\n        with open(flamegraph_path, \"w\") as f:\n            reporter.render(\n                outfile=f,\n                metadata=reader.metadata,\n                show_memory_leaks=options.show_memory_leaks,\n                merge_threads=merge_threads,\n                inverted=options.inverted,\n            )\n        dump_file.unlink()\n        pprint(f\"Results saved to [bold cyan]{flamegraph_path}\")\n        _display_iframe(IFrame(flamegraph_path, width=\"100%\", height=\"600\"))\n\n\nassert FlamegraphMagics.memray_flamegraph.__doc__ is not None\nFlamegraphMagics.memray_flamegraph.__doc__ += \"\\n\\n\" + argument_parser().format_help()\n"
  },
  {
    "path": "src/memray/_memray/CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 3.10)\nset(CMAKE_CXX_STANDARD 17)\nset(CMAKE_CXX_STANDARD_REQUIRED ON)\nproject(_memray)\n\nfind_package(\n  Python\n  COMPONENTS Interpreter Development\n  REQUIRED)\n\nif(CMAKE_HOST_SYSTEM_NAME MATCHES \"Darwin\")\n  set(MEMRAY_LINKER_FILE macho_shenanigans.cpp)\nelse()\n  set(MEMRAY_LINKER_FILE elf_shenanigans.cpp)\nendif()\n\nadd_library(\n  _memray STATIC\n  ${MEMRAY_LINKER_FILE}\n  inject.cpp\n  compat.cpp\n  hooks.cpp\n  logging.cpp\n  native_resolver.cpp\n  python_helpers.cpp\n  record_reader.cpp\n  record_writer.cpp\n  records.cpp\n  sink.cpp\n  snapshot.cpp\n  socket_reader_thread.cpp\n  source.cpp\n  tracking_api.cpp)\n\nif(CMAKE_HOST_SYSTEM_NAME MATCHES \"Darwin\")\n  execute_process(\n    COMMAND brew --prefix lz4\n    RESULT_VARIABLE BREW_LZ4\n    OUTPUT_VARIABLE BREW_LZ4_PREFIX\n    OUTPUT_STRIP_TRAILING_WHITESPACE)\n  if(BREW_LZ4 EQUAL 0 AND EXISTS \"${BREW_LZ4_PREFIX}\")\n    message(STATUS \"Found Lz4 installed by Homebrew at ${BREW_LZ4_PREFIX}\")\n    include_directories(\"${BREW_LZ4_PREFIX}/include\")\n    link_directories(\"${BREW_LZ4_PREFIX}/lib\")\n  endif()\nelse()\n  find_package(PkgConfig REQUIRED)\n  pkg_check_modules(BINARY_DEPS REQUIRED liblz4 libunwind)\n  target_link_libraries(_memray ${BINARY_DEPS_STATIC_LIBRARIES})\n  target_include_directories(_memray PUBLIC ${BINARY_DEPS_INCLUDE_DIRS})\n  target_compile_options(_memray PUBLIC ${BINARY_DEPS_CFLAGS})\n  target_link_options(_memray PUBLIC ${BINARY_DEPS_LDFLAGS})\nendif()\n\ninclude_directories(. ../../vendor/libbacktrace/install/include\n                    ${Python_INCLUDE_DIRS})\nlink_directories(../../vendor/libbacktrace/install/lib)\n"
  },
  {
    "path": "src/memray/_memray/__init__.pxd",
    "content": ""
  },
  {
    "path": "src/memray/_memray/algorithm.pxd",
    "content": "cdef extern from \"<algorithm>\" namespace \"std\" nogil:\n    ssize_t count[Iter, T](Iter first, Iter last, const T& value)\n"
  },
  {
    "path": "src/memray/_memray/alloc.h",
    "content": "#pragma once\n\n#ifdef __linux__\n#    include <malloc.h>\n#endif\n\n#include <stdlib.h>\n\nextern \"C\" {\n#ifndef __GLIBC__\nstatic void*\npvalloc [[maybe_unused]] (size_t size)\n{\n    return NULL;\n}\n#endif\n\n#if !defined(_ISOC11_SOURCE) && defined(__GLIBC__)\nstatic void*\naligned_alloc(size_t alignment, size_t size)\n{\n    return NULL;\n}\n#endif\n\n#ifdef __APPLE__\n\nstatic void*\nmemalign [[maybe_unused]] (size_t alignment, size_t size)\n{\n    return NULL;\n}\n#endif\n}\n"
  },
  {
    "path": "src/memray/_memray/alloc.pxd",
    "content": "cdef extern from \"alloc.h\" nogil:\n    void *calloc (size_t count, size_t eltsize)\n    void free (void *ptr)\n    void *malloc (size_t size)\n    int posix_memalign(void** memptr, size_t alignment, size_t size)\n    void* aligned_alloc(size_t alignment, size_t size)\n    void *realloc (void *ptr, size_t newsize)\n    void* valloc(size_t size)\n    void* memalign(size_t alignment, size_t size)\n    void* pvalloc(size_t size)\n\ncdef extern from \"Python.h\":\n    void* PyMem_RawMalloc(size_t n) nogil\n    void* PyMem_RawCalloc(size_t nelem, size_t elsize) nogil\n    void* PyMem_RawRealloc(void *p, size_t n) nogil\n    void PyMem_RawFree(void *p) nogil\n\n    void* PyMem_Malloc(size_t n)\n    void* PyMem_Calloc(size_t nelem, size_t elsize)\n    void* PyMem_Realloc(void *p, size_t n)\n    void PyMem_Free(void *p)\n\n    void* PyObject_Malloc(size_t size)\n    void* PyObject_Calloc(size_t nelem, size_t elsize)\n    void* PyObject_Realloc(void *ptr, size_t new_size)\n    void PyObject_Free(void *ptr)\n"
  },
  {
    "path": "src/memray/_memray/compat.cpp",
    "content": "#include \"compat.h\"\n\nnamespace memray::compat {\n\nvoid\nsetprofileAllThreads(Py_tracefunc func, PyObject* arg)\n{\n    assert(PyGILState_Check());\n#if PY_VERSION_HEX >= 0x030D0000\n    PyEval_SetProfileAllThreads(func, arg);\n#else\n    PyThreadState* this_tstate = PyThreadState_Get();\n    PyInterpreterState* interp = threadStateGetInterpreter(this_tstate);\n    for (PyThreadState* tstate = PyInterpreterState_ThreadHead(interp); tstate != nullptr;\n         tstate = PyThreadState_Next(tstate))\n    {\n#    if PY_VERSION_HEX >= 0x03090000\n        if (_PyEval_SetProfile(tstate, func, arg) < 0) {\n            _PyErr_WriteUnraisableMsg(\"in PyEval_SetProfileAllThreads\", nullptr);\n        }\n#    else\n        // For 3.7 and 3.8, backport _PyEval_SetProfile from 3.9\n        // https://github.com/python/cpython/blob/v3.9.13/Python/ceval.c#L4738-L4767\n        PyObject* profileobj = tstate->c_profileobj;\n\n        tstate->c_profilefunc = NULL;\n        tstate->c_profileobj = NULL;\n        /* Must make sure that tracing is not ignored if 'profileobj' is freed */\n        tstate->use_tracing = tstate->c_tracefunc != NULL;\n        Py_XDECREF(profileobj);\n\n        Py_XINCREF(arg);\n        tstate->c_profileobj = arg;\n        tstate->c_profilefunc = func;\n\n        /* Flag that tracing or profiling is turned on */\n        tstate->use_tracing = (func != NULL) || (tstate->c_tracefunc != NULL);\n#    endif\n    }\n#endif\n}\n\n// Constants for older Python versions\nstatic const int NO_LINE_NUMBER = -0x80;\n\n// Code location info kinds for Python 3.11+\ntypedef enum _PyCodeLocationInfoKind {\n    PY_CODE_LOCATION_INFO_SHORT0 = 0,\n    PY_CODE_LOCATION_INFO_ONE_LINE0 = 10,\n    PY_CODE_LOCATION_INFO_ONE_LINE1 = 11,\n    PY_CODE_LOCATION_INFO_ONE_LINE2 = 12,\n\n    PY_CODE_LOCATION_INFO_NO_COLUMNS = 13,\n    PY_CODE_LOCATION_INFO_LONG = 14,\n    PY_CODE_LOCATION_INFO_NONE = 15\n} _PyCodeLocationInfoKind;\n\n// Parse line table for Python 3.11+\ninline bool\nparseLinetable311(uintptr_t addrq, const std::string& linetable, int firstlineno, LocationInfo* info)\n{\n    addrq /= 2;  // Convert from instruction offset to byte offset\n    const uint8_t* ptr = reinterpret_cast<const uint8_t*>(linetable.c_str());\n    uint64_t addr = 0;\n    info->lineno = firstlineno;\n\n    auto scan_varint = [&]() {\n        unsigned int read = *ptr++;\n        unsigned int val = read & 63;\n        unsigned int shift = 0;\n        while (read & 64) {\n            read = *ptr++;\n            shift += 6;\n            val |= (read & 63) << shift;\n        }\n        return val;\n    };\n\n    auto scan_signed_varint = [&]() {\n        unsigned int uval = scan_varint();\n        int sval = uval >> 1;\n        int sign = (uval & 1) ? -1 : 1;\n        return sign * sval;\n    };\n\n    while (*ptr != '\\0') {\n        uint8_t first_byte = *(ptr++);\n        uint8_t code = (first_byte >> 3) & 15;\n        size_t length = (first_byte & 7) + 1;\n        uintptr_t end_addr = addr + length;\n        switch (code) {\n            case PY_CODE_LOCATION_INFO_NONE: {\n                break;\n            }\n            case PY_CODE_LOCATION_INFO_LONG: {\n                int line_delta = scan_signed_varint();\n                info->lineno += line_delta;\n                info->end_lineno = info->lineno + scan_varint();\n                info->column = scan_varint() - 1;\n                info->end_column = scan_varint() - 1;\n                break;\n            }\n            case PY_CODE_LOCATION_INFO_NO_COLUMNS: {\n                int line_delta = scan_signed_varint();\n                info->lineno += line_delta;\n                info->column = info->end_column = -1;\n                break;\n            }\n            case PY_CODE_LOCATION_INFO_ONE_LINE0:\n            case PY_CODE_LOCATION_INFO_ONE_LINE1:\n            case PY_CODE_LOCATION_INFO_ONE_LINE2: {\n                int line_delta = code - 10;\n                info->lineno += line_delta;\n                info->end_lineno = info->lineno;\n                info->column = *(ptr++);\n                info->end_column = *(ptr++);\n                break;\n            }\n            default: {\n                uint8_t second_byte = *(ptr++);\n                assert((second_byte & 128) == 0);\n                info->column = code << 3 | (second_byte >> 4);\n                info->end_column = info->column + (second_byte & 15);\n                break;\n            }\n        }\n        if (addr <= addrq && end_addr > addrq) {\n            return true;\n        }\n        addr = end_addr;\n    }\n    return false;\n}\n\n// Parse line table for Python 3.10\ninline bool\nparseLinetable310(\n        const uintptr_t instruction_offset,\n        const std::string& linetable,\n        int firstlineno,\n        LocationInfo* info)\n{\n    int code_lineno = firstlineno;\n\n    // Word-code is two bytes, so the actual limit in the table is 2 * the instruction index\n    std::string::size_type last_executed_instruction = instruction_offset << 1;\n\n    for (std::string::size_type i = 0, current_instruction = 0; i < linetable.size();) {\n        unsigned char start_delta = linetable[i++];\n        signed char line_delta = linetable[i++];\n        current_instruction += start_delta;\n        code_lineno += (line_delta == NO_LINE_NUMBER) ? 0 : line_delta;\n        if (current_instruction > last_executed_instruction) {\n            break;\n        }\n    }\n\n    info->lineno = code_lineno;\n    info->end_lineno = code_lineno;\n    info->column = -1;\n    info->end_column = -1;\n    return true;\n}\n\n// Parse line table for Python 3.9 and earlier (co_lnotab format)\ninline bool\nparseLinetable39(\n        const uintptr_t instruction_offset,\n        const std::string& linetable,\n        int firstlineno,\n        LocationInfo* info)\n{\n    int code_lineno = firstlineno;\n\n    for (std::string::size_type i = 0, bc = 0; i < linetable.size();\n         code_lineno += static_cast<int8_t>(linetable[i++]))\n    {\n        bc += linetable[i++];\n        if (bc > instruction_offset) {\n            break;\n        }\n    }\n\n    info->lineno = code_lineno;\n    info->end_lineno = code_lineno;\n    info->column = -1;\n    info->end_column = -1;\n    return true;\n}\n\nbool\nparseLinetable(\n        int python_version,\n        const std::string& linetable,\n        uintptr_t addrq,\n        int firstlineno,\n        LocationInfo* info)\n{\n    if (linetable.empty()) {\n        info->lineno = firstlineno;\n        info->end_lineno = firstlineno;\n        info->column = -1;\n        info->end_column = -1;\n        return true;\n    }\n\n    if (python_version >= 0x030B0000) {\n        return parseLinetable311(addrq, linetable, firstlineno, info);\n    } else if (python_version >= 0x030A0000) {\n        return parseLinetable310(addrq, linetable, firstlineno, info);\n    } else {\n        return parseLinetable39(addrq, linetable, firstlineno, info);\n    }\n}\n\n}  // namespace memray::compat\n"
  },
  {
    "path": "src/memray/_memray/compat.h",
    "content": "#pragma once\n\n#define PY_SSIZE_T_CLEAN\n#include <Python.h>\n\n#include \"frameobject.h\"\n#include <cassert>\n#include <string>\n\nnamespace memray::compat {\n\ninline int\nisPythonFinalizing()\n{\n#if PY_VERSION_HEX >= 0x030D0000\n    return Py_IsFinalizing();\n#else\n    return _Py_IsFinalizing();\n#endif\n}\n\ninline bool\nisEntryFrame(PyFrameObject* frame)\n{\n#if PY_VERSION_HEX >= 0x030B0000\n    return _PyFrame_IsEntryFrame(frame);\n#else\n    (void)frame;\n    return true;\n#endif\n}\n\ninline PyFrameObject*\nthreadStateGetFrame(PyThreadState* tstate)\n{\n#if PY_VERSION_HEX < 0x030B0000\n    // Prior to Python 3.11 this was exposed.\n    return tstate->frame;\n#else\n    // Return a borrowed reference.\n    PyFrameObject* ret = PyThreadState_GetFrame(tstate);\n    if (ret) {\n        assert(Py_REFCNT(ret) >= 2);\n        Py_DECREF(ret);\n    }\n    return ret;\n#endif\n}\n\ninline PyCodeObject*\nframeGetCode(PyFrameObject* frame)\n{\n#if PY_VERSION_HEX < 0x030B0000\n    // Prior to Python 3.11 this was exposed.\n    return frame->f_code;\n#else\n    // Return a borrowed reference.\n    PyCodeObject* ret = PyFrame_GetCode(frame);\n    assert(Py_REFCNT(ret) >= 2);\n    Py_DECREF(ret);\n    return ret;\n#endif\n}\n\ninline PyFrameObject*\nframeGetBack(PyFrameObject* frame)\n{\n#if PY_VERSION_HEX < 0x030B0000\n    // Prior to Python 3.11 this was exposed.\n    return frame->f_back;\n#else\n    // Return a borrowed reference.\n    PyFrameObject* ret = PyFrame_GetBack(frame);\n    if (ret) {\n        assert(Py_REFCNT(ret) >= 2);\n        Py_DECREF(ret);\n    }\n    return ret;\n#endif\n}\n\ninline int\nframeGetLasti(PyFrameObject* frame)\n{\n#if PY_VERSION_HEX < 0x030B0000\n    // Prior to Python 3.11 this was exposed.\n    return frame->f_lasti;\n#else\n    // Use PyFrame_GetLasti for Python 3.11+\n    return PyFrame_GetLasti(frame);\n#endif\n}\n\ninline PyInterpreterState*\nthreadStateGetInterpreter(PyThreadState* tstate)\n{\n#if PY_VERSION_HEX < 0x03090000\n    return tstate->interp;\n#else\n    return PyThreadState_GetInterpreter(tstate);\n#endif\n}\n\n#if PY_VERSION_HEX >= 0x030E0000\n\nextern \"C\" void\n_PyEval_StopTheWorld(PyInterpreterState*);\nextern \"C\" void\n_PyEval_StartTheWorld(PyInterpreterState*);\n\ninline void\nstopTheWorld(PyInterpreterState* interp)\n{\n    _PyEval_StopTheWorld(interp);\n}\n\ninline void\nstartTheWorld(PyInterpreterState* interp)\n{\n    _PyEval_StartTheWorld(interp);\n}\n\n#else\n\ninline void\nstopTheWorld(PyInterpreterState*)\n{\n}\n\ninline void\nstartTheWorld(PyInterpreterState*)\n{\n}\n\n#endif\n\nvoid\nsetprofileAllThreads(Py_tracefunc func, PyObject* arg);\n\ninline const char*\ncodeGetLinetable(PyCodeObject* code, size_t* size)\n{\n#if PY_VERSION_HEX >= 0x030A0000\n    // Python 3.10+ uses co_linetable\n    PyObject* linetable = code->co_linetable;\n#else\n    // Python 3.9 and earlier use co_lnotab\n    PyObject* linetable = code->co_lnotab;\n#endif\n\n    if (linetable && PyBytes_Check(linetable)) {\n        *size = PyBytes_GET_SIZE(linetable);\n        return PyBytes_AS_STRING(linetable);\n    }\n    *size = 0;\n    return nullptr;\n}\n\n// Location information structure for line table parsing\nstruct LocationInfo\n{\n    int lineno;\n    int end_lineno;\n    int column;\n    int end_column;\n};\n\nbool\nparseLinetable(\n        int python_version,\n        const std::string& linetable,\n        uintptr_t addrq,\n        int firstlineno,\n        LocationInfo* info);\n\n#if PY_VERSION_HEX >= 0x030D0000\nusing RefTracer = PyRefTracer;\nusing RefTracerEvent = PyRefTracerEvent;\n#else\ntypedef enum { RefTracer_CREATE = 0, RefTracer_DESTROY = 1 } RefTracerEvent;\nusing RefTracer = int (*)(PyObject*, RefTracerEvent event, void* data);\n#endif\n\ninline int\nrefTracerSetTracer(RefTracer tracer, void* data)\n{\n#if PY_VERSION_HEX >= 0x030D0000\n    return PyRefTracer_SetTracer(tracer, data);\n#else\n    return 0;\n#endif\n}\n\n}  // namespace memray::compat\n"
  },
  {
    "path": "src/memray/_memray/elf_shenanigans.cpp",
    "content": "#include <cstring>\n#include <set>\n#include <string>\n#include <sys/mman.h>\n#include <unistd.h>\n\n#include \"elf_utils.h\"\n#include <link.h>\n\n#include \"hooks.h\"\n#include \"linker_shenanigans.h\"\n#include \"logging.h\"\n\nnamespace {\n\n/* Private struct to pass data to phdrs_callback. */\nstruct elf_patcher_context_t\n{\n    bool restore_original;\n    std::set<std::string>& patched;\n    const std::string& self_so_name;\n};\n\n}  // namespace\n\nnamespace memray::linker {\n\n/* Patching functions */\n\nstatic inline int\nunprotect_page(Addr addr)\n{\n    static size_t page_len = getpagesize();\n    auto memory_page = reinterpret_cast<void*>(addr & ~(page_len - 1));\n    return mprotect(memory_page, page_len, PROT_READ | PROT_WRITE);\n}\n\ntemplate<typename Hook>\nstatic void\npatch_symbol(\n        const Hook& hook,\n        typename Hook::signature_t intercept,\n        const char* symname,\n        Addr addr,\n        bool restore_original)\n{\n    // Make sure that we can read and write to the page where the address that we are trying to\n    // patch;\n    if (unprotect_page(addr) < 0) {\n        LOG(WARNING) << \"Could not prepare the memory page for symbol \" << symname << \" for patching\";\n    }\n\n    // Patch the address with the new function or the original one depending on the value of\n    // *restore_original*.\n    auto typedAddr = reinterpret_cast<typename Hook::signature_t*>(addr);\n    *typedAddr = restore_original ? hook.d_original : intercept;\n\n    LOG(DEBUG) << symname << \" intercepted!\";\n}\n\ntemplate<typename Table>\nstatic void\noverwrite_elf_table(\n        const Table& table,\n        const SymbolTable& symbols,\n        const Addr base_addr,\n        bool restore_original) noexcept\n{\n    for (const auto& relocation : table) {\n        /* Every element contains relocation entries that look like this:\n         *\n         *   typedef struct\n         *   {\n         *       Elf_Addr\tr_offset;\t\t// Address\n         *       Elf_Word\tr_info;\t\t\t// Relocation type and symbol index\n         *   } Elf_Rel;\n         *\n         * We are interested mainly on the r_info field, which is a word\n         * containing an index in the symbol table and also the type of the\n         * relocation. With the index and the symbol table (and the string\n         * table) we can resolve the symbol name.\n         */\n        const auto index = ELF_R_SYM(relocation.r_info);\n        const char* symname = symbols.getSymbolNameByIndex(index);\n        auto symbol_addr = relocation.r_offset + base_addr;\n#define FOR_EACH_HOOKED_FUNCTION(hookname)                                                              \\\n    if (strcmp(MEMRAY_ORIG(hookname).d_symbol, symname) == 0) {                                         \\\n        patch_symbol(                                                                                   \\\n                MEMRAY_ORIG(hookname),                                                                  \\\n                &intercept::hookname,                                                                   \\\n                symname,                                                                                \\\n                symbol_addr,                                                                            \\\n                restore_original);                                                                      \\\n        continue;                                                                                       \\\n    }\n        MEMRAY_HOOKED_FUNCTIONS\n    }\n#undef FOR_EACH_HOOKED_FUNCTION\n}\n\nstatic Sxword\nget_jump_table_type(const Dyn* dynamic_section)\n{\n    // The PLT/Jump table can have different entry types depending on the\n    // phase of the moon, the position of the planets, the current weather\n    // and other unpredictable stuff. Normally x86_64 uses RELA entries,\n    // and x86 uses REL entries. But sometimes it doesn't happen, so we need\n    // to check the DT_PLTREL tag to see which one we should use at runtime.\n    for (; dynamic_section->d_tag != DT_NULL; ++dynamic_section) {\n        if (dynamic_section->d_tag != DT_PLTREL) {\n            continue;\n        }\n        return dynamic_section->d_un.d_val;\n    }\n    return 0;\n}\n\nstatic void\npatch_symbols(const Dyn* dyn_info_struct, const Addr base, bool restore_original) noexcept\n{\n    SymbolTable symbols(base, dyn_info_struct);\n\n    /* There are three collections of symbols we want to override:\n     *\n     *    - Relocation table containing entries with implicit addends (RelTable)\n     *    - Relocation table containing entries with explicit addends (RelaTable)\n     *    - Relocations involving the procedure linkage table (JmprelTable)\n     *\n     * We do not need to treat differently these symbols because the linker has\n     * already done its job and the structures are abstracted for us. At the end\n     * of the day, these constructs provide the location of the resolved function\n     * and our job is just overwrite that value.\n     *\n     */\n\n    LOG(DEBUG) << \"Patching symbols with RELS relocation type\";\n    RelTable rels_relocations_table(base, dyn_info_struct);\n    overwrite_elf_table(rels_relocations_table, symbols, base, restore_original);\n\n    LOG(DEBUG) << \"Patching symbols with RELAS relocation type\";\n    RelaTable relas_relocations_table(base, dyn_info_struct);\n    overwrite_elf_table(relas_relocations_table, symbols, base, restore_original);\n\n    LOG(DEBUG) << \"Patching symbols with JMPRELS relocation type\";\n    switch (get_jump_table_type(dyn_info_struct)) {\n        case DT_REL: {\n            JmpRelTable jmp_relocations_table(base, dyn_info_struct);\n            overwrite_elf_table(jmp_relocations_table, symbols, base, restore_original);\n        } break;\n        case DT_RELA: {\n            JmpRelaTable jmp_relocations_table(base, dyn_info_struct);\n            overwrite_elf_table(jmp_relocations_table, symbols, base, restore_original);\n        } break;\n        default: {\n            LOG(DEBUG) << \"Unknown JMPRELS relocation table type\";\n        } break;\n    }\n}\n\nstatic int\nphdrs_callback(dl_phdr_info* info, [[maybe_unused]] size_t size, void* data) noexcept\n{\n    elf_patcher_context_t context = *reinterpret_cast<elf_patcher_context_t*>(data);\n    std::set<std::string> patched = context.patched;\n\n    if (context.restore_original) {\n        patched.clear();\n    } else {\n        if (patched.find(info->dlpi_name) != patched.end()) {\n            return 0;\n        }\n        patched.insert(info->dlpi_name);\n    }\n\n    if (strstr(info->dlpi_name, \"/ld-linux\") || strstr(info->dlpi_name, \"/ld-musl\")\n        || strstr(info->dlpi_name, \"linux-vdso.so.1\")\n        || strstr(info->dlpi_name, context.self_so_name.c_str()))\n    {\n        // Avoid chaos by not overwriting the symbols in the linker.\n        return 0;\n    }\n\n    LOG(INFO) << \"Patching symbols for \" << info->dlpi_name;\n\n    for (auto phdr = info->dlpi_phdr, end = phdr + info->dlpi_phnum; phdr != end; ++phdr) {\n        // The information of all the symbols that we want to overwrite are in the PT_DYNAMIC program\n        // header, that contains the dynamic linking information.\n        if (phdr->p_type != PT_DYNAMIC) {\n            continue;\n        }\n        const auto* dyn_info_struct = reinterpret_cast<const Dyn*>(phdr->p_vaddr + info->dlpi_addr);\n        patch_symbols(dyn_info_struct, info->dlpi_addr, context.restore_original);\n    }\n    return 0;\n}\n\n/* Public API functions */\n\nvoid\nSymbolPatcher::overwrite_symbols() noexcept\n{\n    elf_patcher_context_t context{false, symbols, self_so_name};\n    dl_iterate_phdr(&phdrs_callback, (void*)&context);\n}\n\nvoid\nSymbolPatcher::restore_symbols() noexcept\n{\n    elf_patcher_context_t context{true, symbols, self_so_name};\n    dl_iterate_phdr(&phdrs_callback, (void*)&context);\n}\n\n}  // namespace memray::linker\n"
  },
  {
    "path": "src/memray/_memray/elf_utils.h",
    "content": "#pragma once\n\n#include <cstdint>\n#include <cstring>\n#include <iostream>\n#include <string>\n#include <sys/mman.h>\n#include <unistd.h>\n\n#include <elf.h>\n#include <link.h>\n\n#if INTPTR_MAX == INT64_MAX\n#    define ELF_R_SYM ELF64_R_SYM\n#    if !defined(ELF_ST_BIND)\n#        define ELF_ST_BIND ELF64_ST_BIND\n#    endif\n#    define ELFCLASS_BITS 64\ntypedef uint64_t bloom_el_t;\n#else\n#    define ELF_R_SYM ELF32_R_SYM\n#    if !defined(ELF_ST_BIND)\n#        define ELF_ST_BIND ELF32_ST_BIND\n#    endif\n#    define ELFCLASS_BITS 32\ntypedef uint32_t bloom_el_t;\n#endif\n\n/* Utility classes and definitions */\n\n// We use these macros as instructed in the linker header to refer to ELF types independent\n// of the native wordsize. In this way, `ElfW(TYPE)' is used in place of `Elf32_TYPE' or `Elf64_TYPE'.\nusing Addr = ElfW(Addr);\nusing Dyn = ElfW(Dyn);\nusing Rel = ElfW(Rel);\nusing Rela = ElfW(Rela);\nusing Sym = ElfW(Sym);\nusing Sxword = ElfW(Sxword);\nusing Xword = ElfW(Xword);\n\ntemplate<class T, class U>\nT\nensureRelocatedAddress(const Addr base, const U addr)\n{\n    // Depending on the libc version, some values may be already relocated\n    // or not. So we need to check first if the relocation already happened\n    // and make it ourselves if that is not the case.\n    auto the_addr = reinterpret_cast<Addr>(addr);\n    if (the_addr < base) {\n        return reinterpret_cast<T>(base + the_addr);\n    }\n    return reinterpret_cast<T>(the_addr);\n}\n\ntemplate<typename T, Sxword AddrTag, Sxword SizeTag>\nstruct DynamicInfoTable\n{\n    T* table = nullptr;\n    Xword size = {};\n\n    explicit DynamicInfoTable(const Addr base, const Dyn* dynamic_section)\n    {\n        // Obtain the table address and the size from the tags in the dynamic section\n        for (; dynamic_section->d_tag != DT_NULL; ++dynamic_section) {\n            if (dynamic_section->d_tag == AddrTag) {\n                table = ensureRelocatedAddress<T*>(base, dynamic_section->d_un.d_ptr);\n            } else if (dynamic_section->d_tag == SizeTag) {\n                size = dynamic_section->d_un.d_val;\n            }\n        }\n    }\n\n    T* begin() const noexcept\n    {\n        return table;\n    }\n\n    T* end() const noexcept\n    {\n        return table + size / sizeof(T);\n    }\n};\n\nusing RelTable = DynamicInfoTable<Rel, DT_REL, DT_RELSZ>;\nusing RelaTable = DynamicInfoTable<Rela, DT_RELA, DT_RELASZ>;\nusing JmpRelTable = DynamicInfoTable<Rel, DT_JMPREL, DT_PLTRELSZ>;\nusing JmpRelaTable = DynamicInfoTable<Rela, DT_JMPREL, DT_PLTRELSZ>;\n\nstruct SymbolTable\n{\n    Addr base = 0;\n    const Dyn* dynamic_section;\n    DynamicInfoTable<const char, DT_STRTAB, DT_STRSZ> string_table;\n    DynamicInfoTable<Sym, DT_SYMTAB, DT_SYMENT> symbol_table;\n\n    explicit SymbolTable(Addr base, const Dyn* dynamic_section)\n    : base(base)\n    , dynamic_section(dynamic_section)\n    , string_table(base, dynamic_section)\n    , symbol_table(base, dynamic_section)\n    {\n    }\n\n    const char* getSymbolNameByIndex(size_t index) const\n    {\n        return string_table.table + symbol_table.table[index].st_name;\n    }\n\n    static inline bool isDefinedGlobalSymbol(ElfW(Sym) * sym)\n    {\n        unsigned char stb = ELF_ST_BIND(sym->st_info);\n        if (stb == STB_GLOBAL || stb == STB_WEAK) {\n            return sym->st_shndx != SHN_UNDEF;\n        }\n        return false;\n    }\n\n    static const ElfW(Dyn) * findDynByTag(const ElfW(Dyn) * const section_ptr, ElfW(Sxword) tag)\n    {\n        const ElfW(Dyn)* dyn = section_ptr;\n        while (dyn->d_tag != DT_NULL) {\n            if (dyn->d_tag == tag) {\n                return dyn;\n            }\n            ++dyn;\n        }\n        return nullptr;\n    }\n\n    uintptr_t getSymbolAddress(const char* name) const\n    {\n        uintptr_t result = 0;\n\n        const ElfW(Dyn)* dt_gnu_hash_base = findDynByTag(dynamic_section, DT_GNU_HASH);\n        if (dt_gnu_hash_base != nullptr) {\n            result = findSymbolByGNUHashTable(name, dt_gnu_hash_base);\n        } else {\n            // Fallback to DT_HASH if DT_GNU_HASH is not available\n            const ElfW(Dyn)* dt_hash_base = findDynByTag(dynamic_section, DT_HASH);\n            if (dt_hash_base != nullptr) {\n                result = findSymbolByElfHashTable(name, dt_hash_base);\n            }\n        }\n\n        return result;\n    }\n\n    uintptr_t findSymbolByElfHashTable(const char* name, const ElfW(Dyn) * dt_hash_base) const\n    {\n        // See https://www.gabriel.urdhr.fr/2015/09/28/elf-file-format/#hash-tables\n        auto* dt_hash = ensureRelocatedAddress<ElfW(Word)*>(base, dt_hash_base->d_un.d_ptr);\n        size_t nbucket_ = dt_hash[0];\n        uint32_t* bucket_ = dt_hash + 2;\n        uint32_t* chain_ = bucket_ + nbucket_;\n\n        // This function is adapted from the _dl_elf_hash() function in the linker source:\n        // https://github.com/bminor/glibc/blob/97e42bd482b62d7b74889be11c98b0bbb4059dcd/sysdeps/generic/dl-hash.h#L26-L73\n        auto elf_hash = [](const uint8_t* name) -> uint32_t {\n            uint32_t h = 0, g;\n            while (*name) {\n                h = (h << 4) + *name++;\n                g = h & 0xf0000000;\n                h ^= g;\n                h ^= g >> 24;\n            }\n            return h;\n        };\n\n        uint32_t hash = elf_hash(reinterpret_cast<const uint8_t*>(name));\n        for (uint32_t n = bucket_[hash % nbucket_]; n != 0; n = chain_[n]) {\n            auto* sym = ensureRelocatedAddress<ElfW(Sym)*>(base, symbol_table.table + n);\n            auto* sym_name = ensureRelocatedAddress<char*>(base, string_table.table + sym->st_name);\n            if (isDefinedGlobalSymbol(sym) && strcmp(sym_name, name) == 0) {\n                return base + sym->st_value;\n            }\n        }\n\n        return 0;\n    }\n\n    uintptr_t findSymbolByGNUHashTable(const char* name, const ElfW(Dyn) * dt_gnu_hash_base) const\n    {\n        // Adapted from the holy source of the linker:\n        // https://github.com/bminor/glibc/blob/97e42bd482b62d7b74889be11c98b0bbb4059dcd/elf/dl-lookup.c#L355-L569\n        // See https://www.gabriel.urdhr.fr/2015/09/28/elf-file-format/#hash-tables\n        // and https://sourceware.org/legacy-ml/binutils/2006-10/msg00377.html for more information.\n\n        // DT_GNU_HASH has nothing in common with standard DT_HASH, apart from serving the same purpose.\n        // It has its own hashing function, its own layout, it adds restrictions for the symbol table and\n        // contains an additional bloom filter to stop lookup for missing symbols early.\n\n        auto* hashtab = ensureRelocatedAddress<ElfW(Word)*>(base, dt_gnu_hash_base->d_un.d_ptr);\n\n        // The hash function is adapted from the dl_new_hash() in the linker source:\n        // https://github.com/bminor/glibc/blob/97e42bd482b62d7b74889be11c98b0bbb4059dcd/elf/dl-lookup.c#L572-L579\n        auto gnu_hash = [](const uint8_t* name) -> uint32_t {\n            uint32_t h = 5381;\n            while (*name) {\n                h += (h << 5) + *name++;\n            }\n            return h;\n        };\n\n        // A Bloom filter is used by GNU_HASH to make the lookup for missing symbols more efficient.\n        // Before doing symbol lookup, we take bloom[(hash / ELFCLASS_BITS) % bloom_size]. If bits hash %\n        // ELFCLASS_BITS and (hash >> bloom_shift) % ELFCLASS_BITS are set, then the symbol may or may\n        // not be in the hash table but if at least one bit is not set then the symbol is certainly\n        // absent from the hash table.\n        const bloom_el_t* bloom = reinterpret_cast<bloom_el_t*>(hashtab + 4);\n        const uint32_t bloom_size = hashtab[2];\n        const uint32_t bloom_shift = hashtab[3];\n\n        const uint32_t namehash = gnu_hash(reinterpret_cast<const uint8_t*>(name));\n        bloom_el_t word = bloom[(namehash / ELFCLASS_BITS) % bloom_size];\n        bloom_el_t mask = 0 | (bloom_el_t)1 << (namehash % ELFCLASS_BITS)\n                          | (bloom_el_t)1 << ((namehash >> bloom_shift) % ELFCLASS_BITS);\n\n        /* If at least one bit is not set, the symbol is surely missing. */\n        if ((word & mask) != mask) {\n            return 0;\n        }\n\n        // Chains in the GNU hash table are contiguous sequences of hashes for symbols with the same\n        // index. The last bit in chains' element is discarded and instead used for indicating the\n        // chain's end. If it is set then the element is the last one in the chain. Bucket are arrays\n        // that hold the indexes of the first symbol in the chains. Symbols in the same buckets are\n        // stored linearly. The order of the buckets is implementation dependent.\n\n        const uint32_t nbuckets = hashtab[0];\n        const auto* buckets = reinterpret_cast<const uint32_t*>(bloom + bloom_size);\n        uint32_t symbol_index = buckets[namehash % nbuckets];\n        const uint32_t symbol_offset = hashtab[1];\n        if (symbol_index < symbol_offset) {\n            return 0;\n        }\n        const uint32_t* chain = &buckets[nbuckets];\n\n        // Search for the symbol in the chain that we found.\n        while (true) {\n            auto* sym = symbol_table.table + symbol_index;\n            const auto* sym_name = string_table.table + sym->st_name;\n            const uint32_t hash = chain[symbol_index - symbol_offset];\n            if ((namehash | 1) == (hash | 1) && isDefinedGlobalSymbol(sym)\n                && strcmp(sym_name, name) == 0)\n            {\n                return base + sym->st_value;\n            }\n\n            // Chain ends with an element with the lowest bit set to 1: end of the chain\n            if (hash & 1) {\n                break;\n            }\n            symbol_index++;\n        }\n\n        return 0;\n    }\n};\n"
  },
  {
    "path": "src/memray/_memray/exceptions.h",
    "content": "#pragma once\n\n#include <stdexcept>\n\nnamespace memray::exception {\n\nclass MemrayException : public std::runtime_error\n{\n    using std::runtime_error::runtime_error;\n};\n\nclass IoError : public MemrayException\n{\n    using MemrayException::MemrayException;\n};\n\n}  // namespace memray::exception\n"
  },
  {
    "path": "src/memray/_memray/frame_tree.h",
    "content": "#pragma once\n#include <vector>\n\n#include \"records.h\"\n\nnamespace memray::tracking_api {\nclass FrameTree\n{\n  public:\n    using index_t = size_t;\n\n    inline index_t minIndex() const\n    {\n        return 1;\n    }\n\n    inline index_t maxIndex() const\n    {\n        return d_graph.size() - 1;\n    }\n\n    inline std::pair<frame_id_t, index_t> nextNode(index_t index) const\n    {\n        assert(1 <= index && index <= d_graph.size() - 1);\n        return std::make_pair(d_graph[index].frame_id, d_graph[index].parent_index);\n    }\n\n    using tracecallback_t = std::function<bool(frame_id_t, index_t)>;\n\n    template<typename T>\n    size_t getTraceIndex(const T& stack_trace, const tracecallback_t& callback)\n    {\n        index_t index = 0;\n        for (const auto& frame : stack_trace) {\n            index = getTraceIndexUnsafe(index, frame, callback);\n        }\n        return index;\n    }\n\n    size_t getTraceIndex(index_t parent_index, frame_id_t frame)\n    {\n        return getTraceIndexUnsafe(parent_index, frame, tracecallback_t());\n    }\n\n  private:\n    size_t getTraceIndexUnsafe(index_t parent_index, frame_id_t frame, const tracecallback_t& callback)\n    {\n        Node& parent = d_graph[parent_index];\n        auto it = std::lower_bound(parent.children.begin(), parent.children.end(), frame);\n        if (it == parent.children.end() || it->frame_id != frame) {\n            index_t new_index = d_graph.size();\n            it = parent.children.insert(it, {frame, new_index});\n            if (callback && !callback(frame, parent_index)) {\n                return 0;\n            }\n            d_graph.push_back({frame, parent_index});\n        }\n        return it->child_index;\n    }\n\n    struct DescendentEdge\n    {\n        frame_id_t frame_id;\n        index_t child_index;\n\n        bool operator<(frame_id_t the_frame_id) const\n        {\n            return this->frame_id < the_frame_id;\n        }\n    };\n\n    struct Node\n    {\n        frame_id_t frame_id;\n        index_t parent_index;\n        std::vector<DescendentEdge> children;\n    };\n    std::vector<Node> d_graph{{0, 0, {}}};\n};\n}  // namespace memray::tracking_api\n"
  },
  {
    "path": "src/memray/_memray/hooks.cpp",
    "content": "#include <cassert>\n#include <cstdio>\n#include <mutex>\n#include <unordered_set>\n\n#include \"hooks.h\"\n#include \"tracking_api.h\"\n\nnamespace memray::hooks {\n\n#if defined(__linux__)\nint\nphdr_symfind_callback(dl_phdr_info* info, [[maybe_unused]] size_t size, void* data) noexcept\n{\n    auto result = reinterpret_cast<symbol_query*>(data);\n\n    // From all maps without name, we only want to visit the executable (first map)\n    if (result->maps_visited++ != 0 && !info->dlpi_name[0]) {\n        return 0;\n    }\n\n    if (strstr(info->dlpi_name, \"linux-vdso.so.1\")) {\n        // This is an evil place that don't have symbols\n        return 0;\n    }\n\n    for (auto phdr = info->dlpi_phdr, end = phdr + info->dlpi_phnum; phdr != end; ++phdr) {\n        if (phdr->p_type != PT_DYNAMIC) {\n            continue;\n        }\n\n        const auto* dyn = reinterpret_cast<const Dyn*>(phdr->p_vaddr + info->dlpi_addr);\n        SymbolTable symbols(info->dlpi_addr, dyn);\n\n        const auto offset = symbols.getSymbolAddress(result->symbol_name);\n        if (offset == 0) {\n            continue;\n        }\n\n        result->address = reinterpret_cast<void*>(offset);\n        return 1;\n    }\n\n    return 0;\n}\n#endif\n\nAllocatorKind\nallocatorKind(const Allocator& allocator)\n{\n    switch (allocator) {\n        case Allocator::CALLOC:\n        case Allocator::MALLOC:\n        case Allocator::MEMALIGN:\n        case Allocator::POSIX_MEMALIGN:\n        case Allocator::ALIGNED_ALLOC:\n        case Allocator::PVALLOC:\n        case Allocator::REALLOC:\n        case Allocator::VALLOC:\n        case Allocator::PYMALLOC_MALLOC:\n        case Allocator::PYMALLOC_CALLOC:\n        case Allocator::PYMALLOC_REALLOC: {\n            return AllocatorKind::SIMPLE_ALLOCATOR;\n        }\n        case Allocator::FREE:\n        case Allocator::PYMALLOC_FREE: {\n            return AllocatorKind::SIMPLE_DEALLOCATOR;\n        }\n        case Allocator::MMAP: {\n            return AllocatorKind::RANGED_ALLOCATOR;\n        }\n        case Allocator::MUNMAP: {\n            return AllocatorKind::RANGED_DEALLOCATOR;\n        }\n    }\n    __builtin_unreachable();\n}\n\nbool\nisDeallocator(const Allocator& allocator)\n{\n    switch (allocatorKind(allocator)) {\n        case AllocatorKind::SIMPLE_ALLOCATOR:\n        case AllocatorKind::RANGED_ALLOCATOR:\n            return false;\n        case AllocatorKind::SIMPLE_DEALLOCATOR:\n        case AllocatorKind::RANGED_DEALLOCATOR:\n            return true;\n    }\n    __builtin_unreachable();\n}\n\n#define FOR_EACH_HOOKED_FUNCTION(f) SymbolHook<decltype(&::f)> MEMRAY_ORIG_NO_NS(f)(#f, &::f);\nMEMRAY_HOOKED_FUNCTIONS\n#undef FOR_EACH_HOOKED_FUNCTION\n\nvoid\nensureAllHooksAreValid()\n{\n#define FOR_EACH_HOOKED_FUNCTION(f) MEMRAY_ORIG(f).ensureValidOriginalSymbol();\n    MEMRAY_HOOKED_FUNCTIONS\n#undef FOR_EACH_HOOKED_FUNCTION\n}\n\n}  // namespace memray::hooks\n\nnamespace memray::intercept {\n\nvoid*\npymalloc_malloc(void* ctx, size_t size) noexcept\n{\n    auto* alloc = (PyMemAllocatorEx*)ctx;\n    void* ptr;\n    {\n        tracking_api::RecursionGuard guard;\n        ptr = alloc->malloc(alloc->ctx, size);\n    }\n    tracking_api::Tracker::trackAllocation(ptr, size, hooks::Allocator::PYMALLOC_MALLOC);\n    return ptr;\n}\n\nvoid*\npymalloc_realloc(void* ctx, void* ptr, size_t size) noexcept\n{\n    auto* alloc = (PyMemAllocatorEx*)ctx;\n    void* ret;\n    {\n        tracking_api::RecursionGuard guard;\n        ret = alloc->realloc(alloc->ctx, ptr, size);\n    }\n    if (ret) {\n        if (ptr) {\n            tracking_api::Tracker::trackDeallocation(ptr, 0, hooks::Allocator::PYMALLOC_FREE);\n        }\n        tracking_api::Tracker::trackAllocation(ret, size, hooks::Allocator::PYMALLOC_REALLOC);\n    }\n    return ret;\n}\n\nvoid*\npymalloc_calloc(void* ctx, size_t nelem, size_t size) noexcept\n{\n    auto* alloc = (PyMemAllocatorEx*)ctx;\n    void* ptr;\n    {\n        tracking_api::RecursionGuard guard;\n        ptr = alloc->calloc(alloc->ctx, nelem, size);\n    }\n    tracking_api::Tracker::trackAllocation(ptr, nelem * size, hooks::Allocator::PYMALLOC_CALLOC);\n    return ptr;\n}\n\nvoid\npymalloc_free(void* ctx, void* ptr) noexcept\n{\n    auto* alloc = (PyMemAllocatorEx*)ctx;\n    {\n        tracking_api::RecursionGuard guard;\n        alloc->free(alloc->ctx, ptr);\n    }\n    if (ptr) {\n        tracking_api::Tracker::trackDeallocation(ptr, 0, hooks::Allocator::PYMALLOC_FREE);\n    }\n}\n\nvoid*\nmalloc(size_t size) noexcept\n{\n    assert(MEMRAY_ORIG(malloc));\n\n    void* ptr;\n    {\n        tracking_api::RecursionGuard guard;\n        ptr = MEMRAY_ORIG(malloc)(size);\n    }\n    if (ptr) {\n        tracking_api::Tracker::trackAllocation(ptr, size, hooks::Allocator::MALLOC);\n    }\n    return ptr;\n}\n\nvoid\nfree(void* ptr) noexcept\n{\n    assert(MEMRAY_ORIG(free));\n\n    // We need to call our API before we call the real free implementation\n    // to make sure that the pointer is not reused in-between.\n    if (ptr != nullptr) {\n        tracking_api::Tracker::trackDeallocation(ptr, 0, hooks::Allocator::FREE);\n    }\n\n    {\n        tracking_api::RecursionGuard guard;\n        MEMRAY_ORIG(free)(ptr);\n    }\n}\n\nvoid*\nrealloc(void* ptr, size_t size) noexcept\n{\n    assert(MEMRAY_ORIG(realloc));\n\n    void* ret;\n    {\n        tracking_api::RecursionGuard guard;\n        ret = MEMRAY_ORIG(realloc)(ptr, size);\n    }\n    if (ret) {\n        if (ptr != nullptr) {\n            tracking_api::Tracker::trackDeallocation(ptr, 0, hooks::Allocator::FREE);\n        }\n        tracking_api::Tracker::trackAllocation(ret, size, hooks::Allocator::REALLOC);\n    }\n    return ret;\n}\n\nvoid*\ncalloc(size_t num, size_t size) noexcept\n{\n    assert(MEMRAY_ORIG(calloc));\n\n    void* ret;\n    {\n        tracking_api::RecursionGuard guard;\n        ret = MEMRAY_ORIG(calloc)(num, size);\n    }\n    if (ret) {\n        tracking_api::Tracker::trackAllocation(ret, num * size, hooks::Allocator::CALLOC);\n    }\n    return ret;\n}\n\nvoid*\nmmap(void* addr, size_t length, int prot, int flags, int fd, off_t offset) noexcept\n{\n    assert(MEMRAY_ORIG(mmap));\n    void* ptr;\n    {\n        tracking_api::RecursionGuard guard;\n        ptr = MEMRAY_ORIG(mmap)(addr, length, prot, flags, fd, offset);\n    }\n    if (ptr != MAP_FAILED) {\n        tracking_api::Tracker::trackAllocation(ptr, length, hooks::Allocator::MMAP);\n    }\n    return ptr;\n}\n\n#if defined(__GLIBC__)\nvoid*\nmmap64(void* addr, size_t length, int prot, int flags, int fd, off64_t offset) noexcept\n{\n    assert(MEMRAY_ORIG(mmap64));\n    void* ptr;\n    {\n        tracking_api::RecursionGuard guard;\n        ptr = MEMRAY_ORIG(mmap64)(addr, length, prot, flags, fd, offset);\n    }\n    if (ptr != MAP_FAILED) {\n        tracking_api::Tracker::trackAllocation(ptr, length, hooks::Allocator::MMAP);\n    }\n    return ptr;\n}\n#endif\n\nint\nmunmap(void* addr, size_t length) noexcept\n{\n    assert(MEMRAY_ORIG(munmap));\n    tracking_api::Tracker::trackDeallocation(addr, length, hooks::Allocator::MUNMAP);\n    {\n        tracking_api::RecursionGuard guard;\n        return MEMRAY_ORIG(munmap)(addr, length);\n    }\n}\n\nvoid*\nvalloc(size_t size) noexcept\n{\n    assert(MEMRAY_ORIG(valloc));\n\n    void* ret;\n    {\n        tracking_api::RecursionGuard guard;\n        ret = MEMRAY_ORIG(valloc)(size);\n    }\n    if (ret) {\n        tracking_api::Tracker::trackAllocation(ret, size, hooks::Allocator::VALLOC);\n    }\n    return ret;\n}\n\nint\nposix_memalign(void** memptr, size_t alignment, size_t size) noexcept\n{\n    assert(MEMRAY_ORIG(posix_memalign));\n\n    int ret;\n    {\n        tracking_api::RecursionGuard guard;\n        ret = MEMRAY_ORIG(posix_memalign)(memptr, alignment, size);\n    }\n    if (!ret) {\n        tracking_api::Tracker::trackAllocation(*memptr, size, hooks::Allocator::POSIX_MEMALIGN);\n    }\n    return ret;\n}\n\nvoid*\ndlopen(const char* filename, int flag) noexcept\n{\n    assert(MEMRAY_ORIG(dlopen));\n    void* ret = nullptr;\n    {\n        tracking_api::RecursionGuard guard;\n#if defined(__GLIBC__)\n        // In GLIBC, dlopen() will respect the RPATH/RUNPATH of the caller when searching for the\n        // library, which won't work if we intercept dlopen() as we will be the caller. This means that\n        // callers that rely on RUNPATH to find their dependencies will fail to load. To work around\n        // this, we need to manually find our caller and walk the linker search path to know what we need\n        // to dlopen().\n        if (filename != nullptr && filename[0] != '\\0' && std::strchr(filename, '/') == nullptr) {\n            void* const callerAddr = __builtin_extract_return_addr(__builtin_return_address(0));\n\n            Dl_info info;\n            if (dladdr(callerAddr, &info)) {\n                const char* dlname = info.dli_fname;\n                {\n                    // Check if we are being called from the main executable\n                    Dl_info main_info;\n                    void* main_sym = NULL;\n                    void* self_handle = MEMRAY_ORIG(dlopen)(nullptr, RTLD_LAZY | RTLD_NOLOAD);\n                    if (self_handle) {\n                        main_sym = dlsym(self_handle, \"main\");\n                        MEMRAY_ORIG(dlclose)(self_handle);\n                    }\n                    if (main_sym && dladdr(main_sym, &main_info)\n                        && strcmp(main_info.dli_fname, info.dli_fname) == 0)\n                    {\n                        dlname = nullptr;\n                    }\n                }\n\n                void* caller = MEMRAY_ORIG(dlopen)(dlname, RTLD_LAZY | RTLD_NOLOAD);\n                if (caller != nullptr) {\n                    Dl_serinfo size;\n                    if (dlinfo(caller, RTLD_DI_SERINFOSIZE, &size) == 0) {\n                        std::vector<char> paths_buf;\n                        paths_buf.resize(size.dls_size);\n                        auto paths = reinterpret_cast<Dl_serinfo*>(paths_buf.data());\n                        *paths = size;\n                        if (dlinfo(caller, RTLD_DI_SERINFO, paths) == 0) {\n                            for (unsigned int i = 0; i != paths->dls_cnt; ++i) {\n                                const char* name = paths->dls_serpath[i].dls_name;\n                                if (name == nullptr || name[0] == '\\0') {\n                                    continue;\n                                }\n                                std::string dir = name;\n                                if (dir.back() != '/') {\n                                    dir += '/';\n                                }\n\n                                dir += filename;\n                                ret = MEMRAY_ORIG(dlopen)(dir.c_str(), flag);\n                                if (ret) {\n                                    break;\n                                }\n                            }\n                        }\n                    }\n                    MEMRAY_ORIG(dlclose)(caller);\n                }\n            }\n        }\n#endif\n        // Fallback if we found nothing\n        if (ret == nullptr) {\n            ret = MEMRAY_ORIG(dlopen)(filename, flag);\n        }\n    }\n    if (ret) {\n        tracking_api::Tracker::invalidate_module_cache();\n        if (filename\n            && (nullptr != strstr(filename, \"/_greenlet.\") || nullptr != strstr(filename, \"/greenlet.\")))\n        {\n            tracking_api::Tracker::beginTrackingGreenlets();\n        }\n    }\n    return ret;\n}\n\nint\ndlclose(void* handle) noexcept\n{\n    assert(MEMRAY_ORIG(dlclose));\n\n    int ret;\n    {\n        tracking_api::RecursionGuard guard;\n        ret = MEMRAY_ORIG(dlclose)(handle);\n    }\n    tracking_api::NativeTrace::flushCache();\n    if (!ret) tracking_api::Tracker::invalidate_module_cache();\n    return ret;\n}\n\nvoid*\naligned_alloc(size_t alignment, size_t size) noexcept\n{\n    assert(MEMRAY_ORIG(aligned_alloc));\n\n    void* ret;\n    {\n        tracking_api::RecursionGuard guard;\n        ret = MEMRAY_ORIG(aligned_alloc)(alignment, size);\n    }\n    if (ret) {\n        tracking_api::Tracker::trackAllocation(ret, size, hooks::Allocator::ALIGNED_ALLOC);\n    }\n    return ret;\n}\n\n#if defined(__linux__)\n\nvoid*\nmemalign(size_t alignment, size_t size) noexcept\n{\n    assert(MEMRAY_ORIG(memalign));\n\n    void* ret;\n    {\n        tracking_api::RecursionGuard guard;\n        ret = MEMRAY_ORIG(memalign)(alignment, size);\n    }\n    if (ret) {\n        tracking_api::Tracker::trackAllocation(ret, size, hooks::Allocator::MEMALIGN);\n    }\n    return ret;\n}\n\n#    if defined(__GLIBC__)\nvoid*\npvalloc(size_t size) noexcept\n{\n    assert(MEMRAY_ORIG(pvalloc));\n\n    void* ret;\n    {\n        tracking_api::RecursionGuard guard;\n        ret = MEMRAY_ORIG(pvalloc)(size);\n    }\n    if (ret) {\n        tracking_api::Tracker::trackAllocation(ret, size, hooks::Allocator::PVALLOC);\n    }\n    return ret;\n}\n#    endif\n\nint\nprctl(int option, ...) noexcept\n{\n    unsigned long args[4];\n    va_list arguments;\n    va_start(arguments, option);\n    for (int i = 0; i < 4; i++) {\n        args[i] = va_arg(arguments, unsigned long);\n    }\n    va_end(arguments);\n\n    if (option == PR_SET_NAME) {\n        char* name = reinterpret_cast<char*>(args[0]);\n        tracking_api::Tracker::registerThreadName(name);\n    }\n\n    unsigned long ret = MEMRAY_ORIG(prctl)(option, args[0], args[1], args[2], args[3]);\n\n    return ret;\n}\n#endif\n\nPyGILState_STATE\nPyGILState_Ensure() noexcept\n{\n    PyGILState_STATE ret = MEMRAY_ORIG(PyGILState_Ensure)();\n    tracking_api::install_trace_function();\n    return ret;\n}\n\nint\npyreftracer(PyObject* obj, compat::RefTracerEvent event, void* data) noexcept\n{\n    tracking_api::Tracker::trackObject(obj, event);\n    return 0;\n}\n\n}  // namespace memray::intercept\n"
  },
  {
    "path": "src/memray/_memray/hooks.h",
    "content": "#pragma once\n\n#define PY_SSIZE_T_CLEAN\n#include <Python.h>\n\n#include <sys/mman.h>\n#include <sys/types.h>\n\n#include <cstdlib>\n#include <iostream>\n\n#ifdef __linux__\n#    ifndef _GNU_SOURCE\n#        define _GNU_SOURCE\n#    endif\n#    include \"elf_utils.h\"\n#    include <malloc.h>\n#    include <sys/prctl.h>\n#endif\n\n#include <dlfcn.h>\n\n#include \"alloc.h\"\n#include \"compat.h\"\n#include \"logging.h\"\n\n#if defined(__APPLE__)\n#    define MEMRAY_PLATFORM_HOOKED_FUNCTIONS\n#elif defined(__GLIBC__)\n#    define MEMRAY_PLATFORM_HOOKED_FUNCTIONS                                                            \\\n        FOR_EACH_HOOKED_FUNCTION(memalign)                                                              \\\n        FOR_EACH_HOOKED_FUNCTION(prctl)                                                                 \\\n        FOR_EACH_HOOKED_FUNCTION(pvalloc)                                                               \\\n        FOR_EACH_HOOKED_FUNCTION(mmap64)\n#else\n#    define MEMRAY_PLATFORM_HOOKED_FUNCTIONS                                                            \\\n        FOR_EACH_HOOKED_FUNCTION(memalign)                                                              \\\n        FOR_EACH_HOOKED_FUNCTION(prctl)\n#endif\n\n#define MEMRAY_HOOKED_FUNCTIONS                                                                         \\\n    FOR_EACH_HOOKED_FUNCTION(malloc)                                                                    \\\n    FOR_EACH_HOOKED_FUNCTION(free)                                                                      \\\n    FOR_EACH_HOOKED_FUNCTION(calloc)                                                                    \\\n    FOR_EACH_HOOKED_FUNCTION(realloc)                                                                   \\\n    FOR_EACH_HOOKED_FUNCTION(valloc)                                                                    \\\n    FOR_EACH_HOOKED_FUNCTION(posix_memalign)                                                            \\\n    FOR_EACH_HOOKED_FUNCTION(aligned_alloc)                                                             \\\n    FOR_EACH_HOOKED_FUNCTION(mmap)                                                                      \\\n    FOR_EACH_HOOKED_FUNCTION(munmap)                                                                    \\\n    FOR_EACH_HOOKED_FUNCTION(dlopen)                                                                    \\\n    FOR_EACH_HOOKED_FUNCTION(dlclose)                                                                   \\\n    FOR_EACH_HOOKED_FUNCTION(PyGILState_Ensure)                                                         \\\n    MEMRAY_PLATFORM_HOOKED_FUNCTIONS\n\nnamespace memray::hooks {\n\nstruct symbol_query\n{\n    size_t maps_visited;\n    const char* symbol_name;\n    void* address;\n};\n\n#ifdef __linux__\nint\nphdr_symfind_callback(dl_phdr_info* info, [[maybe_unused]] size_t size, void* data) noexcept;\n#endif\n\n_Pragma(\"GCC diagnostic ignored \\\"-Wignored-attributes\\\"\") template<typename Signature>\nstruct SymbolHook\n{\n    using signature_t = Signature;\n    const char* d_symbol;\n    signature_t d_original = nullptr;\n\n    explicit SymbolHook(const char* symbol, signature_t original)\n    : d_symbol(symbol)\n    , d_original(original)\n    {\n    }\n\n    void ensureValidOriginalSymbol()\n    {\n#if defined(__linux__)\n        symbol_query query{0, d_symbol, nullptr};\n        dl_iterate_phdr(&phdr_symfind_callback, (void*)&query);\n        auto symbol_addr = reinterpret_cast<signature_t>(query.address);\n        if (symbol_addr != nullptr) {\n            if (symbol_addr != d_original) {\n                LOG(WARNING) << \"Correcting symbol for \" << d_symbol << \" from \" << std::hex\n                             << reinterpret_cast<void*>(d_original) << \" to \"\n                             << reinterpret_cast<void*>(symbol_addr);\n            }\n            this->d_original = symbol_addr;\n        }\n#else\n        return;\n#endif\n    }\n\n    template<typename... Args>\n    auto operator()(Args... args) const noexcept -> decltype(d_original(args...))\n    {\n        return this->d_original(args...);\n    }\n\n    explicit operator bool() const noexcept\n    {\n        return this->d_original;\n    }\n};\n\nvoid\nensureAllHooksAreValid();\n\n// Allocators are roughly ordered by the likelihood of any given allocation\n// record using them. The allocators assigned 1 to 7 have a more compact\n// representation within capture files. 0 must remain unassigned (it's used as\n// a flag to indicate that the less compact representation was used).\nenum class Allocator : unsigned char {\n    PYMALLOC_FREE = 1,\n    PYMALLOC_MALLOC = 2,\n    PYMALLOC_CALLOC = 3,\n    PYMALLOC_REALLOC = 4,\n    FREE = 5,\n    MALLOC = 6,\n    REALLOC = 7,\n\n    CALLOC = 8,\n    POSIX_MEMALIGN = 9,\n    ALIGNED_ALLOC = 10,\n    MEMALIGN = 11,\n    VALLOC = 12,\n    PVALLOC = 13,\n    MMAP = 14,\n    MUNMAP = 15,\n};\n\nenum class AllocatorKind {\n    SIMPLE_ALLOCATOR = 1,\n    SIMPLE_DEALLOCATOR = 2,\n    RANGED_ALLOCATOR = 3,\n    RANGED_DEALLOCATOR = 4,\n};\n\nAllocatorKind\nallocatorKind(const Allocator& allocator);\n\nbool\nisDeallocator(const Allocator& allocator);\n\n#define MEMRAY_ORIG_concat_helper(x, y) x##y\n#define MEMRAY_ORIG_NO_NS(f) MEMRAY_ORIG_concat_helper(memray_, f)\n#define MEMRAY_ORIG(f) memray::hooks::MEMRAY_ORIG_NO_NS(f)\n\n#define FOR_EACH_HOOKED_FUNCTION(f) extern SymbolHook<decltype(&::f)> MEMRAY_ORIG_NO_NS(f);\nMEMRAY_HOOKED_FUNCTIONS\n#undef FOR_EACH_HOOKED_FUNCTION\n\n}  // namespace memray::hooks\n\nnamespace memray::intercept {\nvoid*\nmalloc(size_t size) noexcept;\n\nvoid\nfree(void* ptr) noexcept;\n\nvoid*\nrealloc(void* ptr, size_t size) noexcept;\n\nvoid*\ncalloc(size_t num, size_t size) noexcept;\n\nint\nposix_memalign(void** memptr, size_t alignment, size_t size) noexcept;\n\nvoid*\naligned_alloc(size_t alignment, size_t size) noexcept;\n\nvoid*\nmemalign(size_t alignment, size_t size) noexcept;\n\nvoid*\nvalloc(size_t size) noexcept;\n\nvoid*\npvalloc(size_t size) noexcept;\n\nvoid*\ndlopen(const char* filename, int flag) noexcept;\n\nint\ndlclose(void* handle) noexcept;\n\nvoid*\nmmap(void* addr, size_t length, int prot, int flags, int fd, off_t offset) noexcept;\n\n#if defined(__GLIBC__)\nvoid*\nmmap64(void* addr, size_t length, int prot, int flags, int fd, off64_t offset) noexcept;\n#endif\n\nint\nmunmap(void* addr, size_t length) noexcept;\n\nint\nprctl(int option, ...) noexcept;\n\nPyGILState_STATE\nPyGILState_Ensure() noexcept;\n\nvoid*\npymalloc_malloc(void* ctx, size_t size) noexcept;\nvoid*\npymalloc_realloc(void* ctx, void* ptr, size_t new_size) noexcept;\nvoid*\npymalloc_calloc(void* ctx, size_t nelem, size_t size) noexcept;\nvoid\npymalloc_free(void* ctx, void* ptr) noexcept;\n\nint\npyreftracer(PyObject*, compat::RefTracerEvent event, void* data) noexcept;\n\n}  // namespace memray::intercept\n"
  },
  {
    "path": "src/memray/_memray/hooks.pxd",
    "content": "from _memray.records cimport Allocation\nfrom libcpp cimport bool\n\n\ncdef extern from \"hooks.h\" namespace \"memray::hooks\":\n    cdef cppclass Allocator:\n        pass\n\n    bool isDeallocator(const Allocator& allocator)\n"
  },
  {
    "path": "src/memray/_memray/inject.cpp",
    "content": "#include <netdb.h>\n#include <stdint.h>\n#include <sys/socket.h>\n#include <sys/types.h>\n#include <unistd.h>\n\n#include <iostream>\n\n/* We depend on the Python 3.7 stable ABI, but we can't simply do the obvious\n     #define Py_LIMITED_API 0x03070000\n     #include \"Python.h\"\n   because we need to support building something that uses the stable ABI from\n   a free-threading interpreter, and Python.h doesn't support that.\n   So, we declare the ABI for the functions we need ourselves. */\n\nstruct PyObject;\ntypedef enum { PyGILState_LOCKED, PyGILState_UNLOCKED } PyGILState_STATE;\n#define Py_file_input 257\n\n#define PyAPI_FUNC(ret_type) extern \"C\" ret_type\n\nPyAPI_FUNC(char*) PyBytes_AsString(PyObject*);\nPyAPI_FUNC(PyObject*) PyDict_New(void);\nPyAPI_FUNC(int) PyDict_SetItemString(PyObject* dp, const char* key, PyObject* item);\nPyAPI_FUNC(void) PyErr_Clear(void);\nPyAPI_FUNC(void) PyErr_Fetch(PyObject**, PyObject**, PyObject**);\nPyAPI_FUNC(void) PyErr_NormalizeException(PyObject**, PyObject**, PyObject**);\nPyAPI_FUNC(PyObject*) PyErr_Occurred(void);\nPyAPI_FUNC(PyObject*) PyEval_EvalCode(PyObject*, PyObject*, PyObject*);\nPyAPI_FUNC(PyGILState_STATE) PyGILState_Ensure(void);\nPyAPI_FUNC(void) PyGILState_Release(PyGILState_STATE);\nPyAPI_FUNC(PyObject*) PyImport_ImportModule(const char* name);\nPyAPI_FUNC(PyObject*) PyObject_Repr(PyObject*);\nPyAPI_FUNC(PyObject*) PyUnicode_AsUTF8String(PyObject* unicode);\nPyAPI_FUNC(PyObject*) Py_CompileString(const char*, const char*, int);\nPyAPI_FUNC(void) Py_DecRef(PyObject*);\nPyAPI_FUNC(int) Py_IsInitialized(void);\n\nnamespace memray {\nnamespace {  // unnamed\n\nint\nconnect_client(const uint16_t port)\n{\n    struct addrinfo hints = {};\n    struct addrinfo* all_addresses = nullptr;\n\n    hints.ai_family = AF_UNSPEC;\n    hints.ai_socktype = SOCK_STREAM;\n\n    const std::string port_str = std::to_string(port);\n    const int rv = ::getaddrinfo(nullptr, port_str.c_str(), &hints, &all_addresses);\n    if (rv != 0) {\n        std::cerr << \"getaddrinfo() failed while trying to attach Memray: \" << ::gai_strerror(rv);\n        return -1;\n    }\n\n    int sockfd = -1;\n    for (const struct addrinfo* curr_address = all_addresses; curr_address != nullptr;\n         curr_address = curr_address->ai_next)\n    {\n        sockfd = ::socket(curr_address->ai_family, curr_address->ai_socktype, curr_address->ai_protocol);\n        if (sockfd == -1) {\n            continue;\n        }\n\n        if (::connect(sockfd, curr_address->ai_addr, curr_address->ai_addrlen) == -1) {\n            ::close(sockfd);\n            sockfd = -1;\n            continue;\n        }\n        break;\n    }\n    ::freeaddrinfo(all_addresses);\n    return sockfd;\n}\n\nbool\nsendall(const int fd, std::string_view data)\n{\n    size_t length = data.size();\n    while (length) {\n        const ssize_t ret = ::send(fd, data.data(), length, 0);\n        if (ret < 0 && errno != EINTR) {\n            return false;\n        } else if (ret >= 0) {\n            data.remove_prefix(ret);\n            length -= ret;\n        }\n    }\n    return true;\n}\n\nbool\nrecvall(const int fd, std::string* data)\n{\n    data->clear();\n\n    char buf[4096];\n    while (true) {\n        const ssize_t ret = ::recv(fd, buf, sizeof(buf), 0);\n        if (ret < 0 && errno != EINTR) {\n            return false;\n        } else if (ret > 0) {\n            *data += std::string_view(buf, ret);\n        } else if (ret == 0) {\n            return true;\n        }\n    }\n}\n\n// Clear the error indicator, return a string representing the error.\nstd::string\nMemray_PyErr_ToString()\n{\n    std::string ret;\n\n    if (!PyErr_Occurred()) {\n        return ret;\n    }\n\n    PyObject* type;\n    PyObject* val;\n    PyObject* tb;\n    PyErr_Fetch(&type, &val, &tb);\n    PyErr_NormalizeException(&type, &val, &tb);\n\n    PyObject* exc_repr = PyObject_Repr(val);\n    if (!exc_repr) {\n        PyErr_Clear();\n        ret = \"unknown exception (`repr(exc)` failed)!\";\n    } else {\n        PyObject* utf8 = PyUnicode_AsUTF8String(exc_repr);\n        if (!utf8) {\n            PyErr_Clear();\n            ret = \"unknown exception (`repr(exc).encode('utf-8')` failed)!\";\n        } else {\n            ret = PyBytes_AsString(utf8);\n        }\n        Py_DecRef(utf8);\n    }\n    Py_DecRef(exc_repr);\n\n    Py_DecRef(type);\n    Py_DecRef(val);\n    Py_DecRef(tb);\n\n    return ret;\n}\n\nbool\nrun_script_impl(const std::string& script, std::string* errmsg)\n{\n    int rc;\n\n    PyObject* builtins = nullptr;\n    PyObject* globals = nullptr;\n    PyObject* code = nullptr;\n    PyObject* mod = nullptr;\n    bool success = false;\n\n    builtins = PyImport_ImportModule(\"builtins\");\n    if (!builtins) {\n        goto done;\n    }\n\n    globals = PyDict_New();\n    if (!globals) {\n        goto done;\n    }\n\n    // Needed on 3.7 to avoid ImportError('__import__ not found')\n    rc = PyDict_SetItemString(globals, \"__builtins__\", builtins);\n    if (0 != rc) {\n        goto done;\n    }\n\n    code = Py_CompileString(script.data(), \"_memray_attach_hook.py\", Py_file_input);\n    if (!code) {\n        goto done;\n    }\n\n    mod = PyEval_EvalCode(code, globals, globals);\n    if (!mod) {\n        goto done;\n    }\n\n    success = true;\n\ndone:\n    Py_DecRef(mod);\n    Py_DecRef(code);\n    Py_DecRef(globals);\n    Py_DecRef(builtins);\n\n    *errmsg = Memray_PyErr_ToString();\n    return success;\n}\n\nbool\nrun_script(const std::string& script, std::string* errmsg)\n{\n    if (!Py_IsInitialized()) {\n        *errmsg = \"Python is not initialized\";\n        return false;\n    }\n\n    PyGILState_STATE gstate;\n    gstate = PyGILState_Ensure();\n    const bool ret = run_script_impl(script, errmsg);\n    PyGILState_Release(gstate);\n    return ret;\n}\n\nvoid\nrun_client(const uint16_t port)\n{\n    const int sock = connect_client(port);\n    if (sock == -1) {\n        std::cerr << \"memray attach failed!\" << std::endl;\n        return;\n    }\n\n    std::string script;\n    if (!recvall(sock, &script)) {\n        std::cerr << \"memray attach socket read error!\" << std::endl;\n        return;\n    }\n\n    std::string errmsg;\n    bool success = run_script(script.c_str(), &errmsg);\n\n    if (!success) {\n        sendall(sock, errmsg);\n    }\n    ::close(sock);\n}\n\nextern \"C\" void*\nthread_body(void* arg)\n{\n    int rc = pthread_detach(pthread_self());\n    if (0 != rc) {\n        std::cerr << \"Failed to detach thread!\" << std::endl;\n    }\n\n    uint16_t port = reinterpret_cast<uintptr_t>(arg);\n    run_client(port);\n    return nullptr;\n}\n\n}  // unnamed namespace\n}  // namespace memray\n\nextern \"C\" __attribute__((visibility(\"default\"))) int\nmemray_spawn_client(int port)\n{\n    // Running Python code directly in the point of attaching can lead to\n    // crashes as we don't know if the interpreter is ready to execute code.\n    // For instance, we can be in the middle of modifying the GC linked list\n    // or doing some other operation that is not reentrant. Instead, we spawn\n    // a new thread that will try to grab the GIL and run the code there.\n    pthread_t thread;\n    return pthread_create(&thread, nullptr, &memray::thread_body, (void*)(uintptr_t)port);\n}\n"
  },
  {
    "path": "src/memray/_memray/linker_shenanigans.h",
    "content": "#pragma once\n\n#include <set>\n#include <string>\n\n#include <dlfcn.h>\n\nnamespace memray::linker {\n\nstatic void\n_dummy(void){};\n\nclass SymbolPatcher\n{\n  private:\n    std::set<std::string> symbols;\n    std::string self_so_name = \"_memray.cpython-\";\n\n  public:\n    SymbolPatcher()\n    {\n        Dl_info info;\n        if (dladdr((void*)&_dummy, &info)) {\n            self_so_name = info.dli_fname;\n        }\n    }\n    void overwrite_symbols() noexcept;\n    void restore_symbols() noexcept;\n};\n}  // namespace memray::linker\n"
  },
  {
    "path": "src/memray/_memray/logging.cpp",
    "content": "#include <iostream>\n#include <stdexcept>\n\n#include \"logging.h\"\n\nnamespace memray {\n\nstatic int LOG_THRESHOLD = static_cast<int>(logLevel::WARNING);\n\nstatic const char*\nprefixFromLogLevel(int level)\n{\n    if (level >= CRITICAL) return \"Memray CRITICAL: \";\n    if (level >= ERROR) return \"Memray ERROR: \";\n    if (level >= WARNING) return \"Memray WARNING: \";\n    if (level >= INFO) return \"Memray INFO: \";\n    if (level >= DEBUG) return \"Memray DEBUG: \";\n    return \"Memray TRACE: \";\n}\n\nvoid\nsetLogThreshold(int threshold)\n{\n    LOG_THRESHOLD = threshold;\n}\n\nlogLevel\ngetLogThreshold()\n{\n    return static_cast<logLevel>(LOG_THRESHOLD);\n}\n\nvoid\nlogToStderr(const std::string& message, int level)\n{\n    if (level < LOG_THRESHOLD) {\n        return;\n    }\n\n    std::cerr << prefixFromLogLevel(level) << message << std::endl;\n}\n\n}  // namespace memray\n"
  },
  {
    "path": "src/memray/_memray/logging.h",
    "content": "#ifndef _MEMRAY_LOGGING_H\n#define _MEMRAY_LOGGING_H\n\n#include <sstream>\n#include <string>\n\nnamespace memray {\n\nenum logLevel {\n    NOTSET = 0,\n    DEBUG = 10,\n    INFO = 20,\n    WARNING = 30,\n    ERROR = 40,\n    CRITICAL = 50,\n};\n\nvoid\nlogToStderr(const std::string& message, int level);\n\nvoid\nsetLogThreshold(int threshold);\n\nlogLevel\ngetLogThreshold();\n\nclass LOG\n{\n  public:\n    // Constructors\n    LOG()\n    : msgLevel(INFO){};\n\n    explicit LOG(logLevel type)\n    {\n        msgLevel = type;\n    };\n\n    // Destructors\n    ~LOG()\n    {\n        logToStderr(buffer.str(), msgLevel);\n    };\n\n    // Operators\n    template<typename T>\n    LOG& operator<<(const T& msg)\n    {\n        if (msgLevel < getLogThreshold()) {\n            return *this;\n        }\n        buffer << msg;\n        return *this;\n    };\n\n  private:\n    // Data members\n    std::ostringstream buffer;\n    logLevel msgLevel = DEBUG;\n};\n\n}  // namespace memray\n\n#endif  //_MEMRAY_LOGGING_H\n"
  },
  {
    "path": "src/memray/_memray/logging.pxd",
    "content": "cdef extern from \"logging.h\" namespace \"memray\":\n    void setLogThreshold(int)\n"
  },
  {
    "path": "src/memray/_memray/lz4_stream.h",
    "content": "// Copyright (c) 2015, Kasper Laudrup <laudrup@stacktrace.dk>\n// All rights reserved.\n//\n// Redistribution and use in source and binary forms, with or without\n// modification, are permitted provided that the following conditions are\n// met:\n//\n// 1. Redistributions of source code must retain the above copyright\n// notice, this list of conditions and the following disclaimer.\n//\n// 2. Redistributions in binary form must reproduce the above copyright\n// notice, this list of conditions and the following disclaimer in the\n// documentation and/or other materials provided with the distribution.\n//\n// 3. Neither the name of the copyright holder nor the names of its\n// contributors may be used to endorse or promote products derived from\n// this software without specific prior written permission.\n//\n// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n// \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n//\n#ifndef LZ4_STREAM\n#define LZ4_STREAM\n\n// LZ4 Headers\n#include <lz4frame.h>\n\n// Standard headers\n#include <array>\n#include <cassert>\n#include <functional>\n#include <iostream>\n#include <memory>\n#include <streambuf>\n#include <vector>\n\nnamespace lz4_stream {\n/**\n * @brief An output stream that will LZ4 compress the input data.\n *\n * An output stream that will wrap another output stream and LZ4\n * compress its input data to that stream.\n *\n */\ntemplate<size_t SrcBufSize = 256>\nclass basic_ostream : public std::ostream\n{\n  public:\n    /**\n     * @brief Constructs an LZ4 compression output stream\n     *\n     * @param sink The stream to write compressed data to\n     */\n    basic_ostream(std::ostream& sink)\n    : std::ostream(new output_buffer(sink))\n    , buffer_(dynamic_cast<output_buffer*>(rdbuf()))\n    {\n        assert(buffer_);\n    }\n\n    /**\n     * @brief Destroys the LZ4 output stream. Calls close() if not already called.\n     */\n    ~basic_ostream()\n    {\n        close();\n        delete buffer_;\n    }\n\n    /**\n     * @brief Flushes and writes LZ4 footer data to the LZ4 output stream.\n     *\n     * After calling this function no more data should be written to the stream.\n     */\n    void close()\n    {\n        buffer_->close();\n    }\n\n  private:\n    class output_buffer : public std::streambuf\n    {\n      public:\n        output_buffer(const output_buffer&) = delete;\n        output_buffer& operator=(const output_buffer&) = delete;\n\n        output_buffer(std::ostream& sink)\n        : sink_(sink)\n        ,\n        // TODO: No need to recalculate the dest_buf_ size on each construction\n        dest_buf_(LZ4F_compressBound(src_buf_.size(), nullptr))\n        , ctx_(nullptr)\n        , closed_(false)\n        {\n            char* base = &src_buf_.front();\n            setp(base, base + src_buf_.size() - 1);\n\n            size_t ret = LZ4F_createCompressionContext(&ctx_, LZ4F_VERSION);\n            if (LZ4F_isError(ret) != 0) {\n                throw std::runtime_error(\n                        std::string(\"Failed to create LZ4 compression context: \")\n                        + LZ4F_getErrorName(ret));\n            }\n            write_header();\n        }\n\n        ~output_buffer()\n        {\n            close();\n        }\n\n        void close()\n        {\n            if (closed_) {\n                return;\n            }\n            sync();\n            write_footer();\n            LZ4F_freeCompressionContext(ctx_);\n            closed_ = true;\n        }\n\n      private:\n        int_type overflow(int_type ch) override\n        {\n            assert(std::less_equal<char*>()(pptr(), epptr()));\n\n            *pptr() = static_cast<basic_ostream::char_type>(ch);\n            pbump(1);\n            compress_and_write();\n\n            return ch;\n        }\n\n        int_type sync() override\n        {\n            compress_and_write();\n            return 0;\n        }\n\n        void compress_and_write()\n        {\n            // TODO: Throw exception instead or set badbit\n            assert(!closed_);\n            int orig_size = static_cast<int>(pptr() - pbase());\n            pbump(-orig_size);\n            size_t ret = LZ4F_compressUpdate(\n                    ctx_,\n                    &dest_buf_.front(),\n                    dest_buf_.capacity(),\n                    pbase(),\n                    orig_size,\n                    nullptr);\n            if (LZ4F_isError(ret) != 0) {\n                throw std::runtime_error(\n                        std::string(\"LZ4 compression failed: \") + LZ4F_getErrorName(ret));\n            }\n            sink_.write(&dest_buf_.front(), ret);\n        }\n\n        void write_header()\n        {\n            // TODO: Throw exception instead or set badbit\n            assert(!closed_);\n            size_t ret = LZ4F_compressBegin(ctx_, &dest_buf_.front(), dest_buf_.capacity(), nullptr);\n            if (LZ4F_isError(ret) != 0) {\n                throw std::runtime_error(\n                        std::string(\"Failed to start LZ4 compression: \") + LZ4F_getErrorName(ret));\n            }\n            sink_.write(&dest_buf_.front(), ret);\n        }\n\n        void write_footer()\n        {\n            assert(!closed_);\n            size_t ret = LZ4F_compressEnd(ctx_, &dest_buf_.front(), dest_buf_.capacity(), nullptr);\n            if (LZ4F_isError(ret) != 0) {\n                throw std::runtime_error(\n                        std::string(\"Failed to end LZ4 compression: \") + LZ4F_getErrorName(ret));\n            }\n            sink_.write(&dest_buf_.front(), ret);\n        }\n\n        std::ostream& sink_;\n        std::array<char, SrcBufSize> src_buf_;\n        std::vector<char> dest_buf_;\n        LZ4F_compressionContext_t ctx_;\n        bool closed_;\n    };\n\n    output_buffer* buffer_;\n};\n\n/**\n * @brief An input stream that will LZ4 decompress output data.\n *\n * An input stream that will wrap another input stream and LZ4\n * decompress its output data to that stream.\n *\n */\ntemplate<size_t SrcBufSize = 256, size_t DestBufSize = 256>\nclass basic_istream : public std::istream\n{\n  public:\n    /**\n     * @brief Constructs an LZ4 decompression input stream\n     *\n     * @param source The stream to read LZ4 compressed data from\n     */\n    basic_istream(std::istream& source)\n    : std::istream(new input_buffer(source))\n    , buffer_(dynamic_cast<input_buffer*>(rdbuf()))\n    {\n        assert(buffer_);\n    }\n\n    /**\n     * @brief Destroys the LZ4 output stream.\n     */\n    ~basic_istream()\n    {\n        delete buffer_;\n    }\n\n  private:\n    class input_buffer : public std::streambuf\n    {\n      public:\n        input_buffer(std::istream& source)\n        : source_(source)\n        , offset_(0)\n        , src_buf_size_(0)\n        , ctx_(nullptr)\n        {\n            size_t ret = LZ4F_createDecompressionContext(&ctx_, LZ4F_VERSION);\n            if (LZ4F_isError(ret) != 0) {\n                throw std::runtime_error(\n                        std::string(\"Failed to create LZ4 decompression context: \")\n                        + LZ4F_getErrorName(ret));\n            }\n            setg(&src_buf_.front(), &src_buf_.front(), &src_buf_.front());\n        }\n\n        ~input_buffer()\n        {\n            LZ4F_freeDecompressionContext(ctx_);\n        }\n\n        int_type underflow() override\n        {\n            size_t written_size = 0;\n            while (written_size == 0) {\n                if (offset_ == src_buf_size_) {\n                    source_.read(&src_buf_.front(), src_buf_.size());\n                    src_buf_size_ = static_cast<size_t>(source_.gcount());\n                    offset_ = 0;\n                }\n\n                if (src_buf_size_ == 0) {\n                    return traits_type::eof();\n                }\n\n                size_t src_size = src_buf_size_ - offset_;\n                size_t dest_size = dest_buf_.size();\n                size_t ret = LZ4F_decompress(\n                        ctx_,\n                        &dest_buf_.front(),\n                        &dest_size,\n                        &src_buf_.front() + offset_,\n                        &src_size,\n                        nullptr);\n                if (LZ4F_isError(ret) != 0) {\n                    throw std::runtime_error(\n                            std::string(\"LZ4 decompression failed: \") + LZ4F_getErrorName(ret));\n                }\n                written_size = dest_size;\n                offset_ += src_size;\n            }\n            setg(&dest_buf_.front(), &dest_buf_.front(), &dest_buf_.front() + written_size);\n            return traits_type::to_int_type(*gptr());\n        }\n\n        input_buffer(const input_buffer&) = delete;\n        input_buffer& operator=(const input_buffer&) = delete;\n\n      private:\n        std::istream& source_;\n        std::array<char, SrcBufSize> src_buf_;\n        std::array<char, DestBufSize> dest_buf_;\n        size_t offset_;\n        size_t src_buf_size_;\n        LZ4F_decompressionContext_t ctx_;\n    };\n\n    input_buffer* buffer_;\n};\n\nusing ostream = basic_ostream<>;\nusing istream = basic_istream<>;\n\n}  // namespace lz4_stream\n#endif  // LZ4_STREAM\n"
  },
  {
    "path": "src/memray/_memray/macho_shenanigans.cpp",
    "content": "#include <cstring>\n\n#include \"hooks.h\"\n#include \"linker_shenanigans.h\"\n#include \"logging.h\"\n#include \"macho_utils.h\"\n#include <iomanip>\n\n#ifndef __APPLE__\n#    error \"This file can only be compiled in MacOS systems\"\n#endif\n\nnamespace memray::linker {\n\ntemplate<typename Hook>\nstatic void\npatch_symbol(\n        const Hook& hook,\n        typename Hook::signature_t intercept,\n        const char* symname,\n        void* addr,\n        bool restore_original)\n{\n    kern_return_t err = vm_protect(\n            mach_task_self(),\n            reinterpret_cast<uintptr_t>(addr),\n            sizeof(void*),\n            0,\n            VM_PROT_READ | VM_PROT_WRITE | VM_PROT_COPY);\n    if (err == KERN_SUCCESS) {\n        auto typedAddr = reinterpret_cast<typename Hook::signature_t*>(addr);\n        *typedAddr = restore_original ? hook.d_original : intercept;\n        LOG(DEBUG) << symname << \" intercepted!\";\n    } else {\n        LOG(ERROR) << \"Failed to patch \" << symname;\n    }\n}\n\nstatic inline const char*\nget_canonical_name(const char* name)\n{\n    // In macOS 15 (Sequoia)+, the symbols in the shared cache have a prefix\n    // \"_malloc_type\" that we need to remove to match the symbols that we\n    // are looking for.\n    const char* prefix = \"_malloc_type\";\n    if (strncmp(name, prefix, strlen(prefix)) != 0) {\n        return name;\n    }\n    return name + strlen(prefix);\n}\n\nstatic void\npatch_symbols_in_section(\n        const section_t* section,\n        uintptr_t slide,\n        const DynamicInfoTable& dyninfo_table,\n        bool restore_original)\n{\n    auto symbol_addr_table = reinterpret_cast<void**>(slide + section->addr);\n    for (unsigned int i = 0; i < section->size / sizeof(void*); i++) {\n        const char* symbol_name = dyninfo_table.getSymbol(section->reserved1, i);\n        if (!symbol_name || !(symbol_name[0] == '_' || symbol_name[0] == '.') || !symbol_name[1]) {\n            continue;\n        }\n        const char* canonical_name = get_canonical_name(symbol_name);\n#define FOR_EACH_HOOKED_FUNCTION(hookname)                                                              \\\n    if (strcmp(MEMRAY_ORIG(hookname).d_symbol, canonical_name + 1) == 0) {                              \\\n        LOG(DEBUG) << \"Patching \" << symbol_name << \" symbol pointer at \" << std::hex << std::showbase  \\\n                   << *(symbol_addr_table + i) << \" for relocation entry \" << (symbol_addr_table + i);  \\\n        patch_symbol(                                                                                   \\\n                MEMRAY_ORIG(hookname),                                                                  \\\n                &intercept::hookname,                                                                   \\\n                symbol_name,                                                                            \\\n                symbol_addr_table + i,                                                                  \\\n                restore_original);                                                                      \\\n        continue;                                                                                       \\\n    }\n        MEMRAY_HOOKED_FUNCTIONS\n#undef FOR_EACH_HOOKED_FUNCTION\n    }\n}\n\nstatic uint64_t\nlazy_pointer_from_stub(uint64_t vaddr)\n{\n    // We messed with dark forces and we offended the macOS gods and now it is\n    // time to pay the price in blood. This function analyzes the machine code\n    // of a PLT entry in the __stubs or __auth_stubs section of a shared\n    // library that is part of the shared cache and returns the address of the\n    // GOT entry that contains the address of the symbol we are looking for.\n    // Unfortunately doing this is as crazy as it sounds.\n\n#if defined(__arm64__)\n    // For ARM64 architecture, each PLT entry has the following format:\n    //\n    //   adrp   x17, GOT_OFFSET_IN_PAGES\n    //   add    x17, x17, OFFSET_IN_GOT\n    //   ldr    x16, [x17]\n    //   braa   x16, x17\n    //\n    // This means that the address of the GOT entry can be calculated as:\n    //\n    //   addr_of_page(%rip) + page_size() * GOT_OFFSET_IN_PAGES + OFFSET_IN_GOT\n    //\n    // Where %rip is the instruction pointer of the 1st instruction in the PLT\n    // entry, page_size() is 4 KiB, and addr_of_page() is the start address of\n    // the 4 KiB page containing a given address.\n    //\n    // This code parses the machine code of the PLT entry and checks that it\n    // matches the expected instructions. If not, it returns 0. Otherwise, it\n    // extracts the (signed) GOT_OFFSET_IN_PAGES and (unsigned) OFFSET_IN_GOT\n    // values and computes the GOT entry address from them.\n    //\n    // Relevant documentation:\n    // https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/ADRP--Form-PC-relative-address-to-4KB-page-\n    // https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/ADD--immediate---Add--immediate--\n    // https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/ADDS--immediate---Add--immediate---setting-flags-\n\n    auto instructions = reinterpret_cast<const uint32_t*>(vaddr);\n\n    // Ensure the 1st instruction is an adrp.\n    const uint32_t adrp = instructions[0];\n    constexpr uint32_t ADRP_MASK = 0x9F000000;\n    constexpr uint32_t ADRP_INSTRUCTION = 0x90000000;\n    if ((adrp & ADRP_MASK) != ADRP_INSTRUCTION) {\n        LOG(DEBUG) << \"1st stub instruction is not adrp: \" << std::hex << std::setw(8)\n                   << std::setfill('0') << (adrp & ADRP_MASK) << \" != \" << ADRP_INSTRUCTION;\n        return 0;\n    }\n\n    // Ensure the 2nd instruction is an ADD or ADDS immediate without shift.\n    const uint32_t add = instructions[1];\n    constexpr uint32_t ADD_MASK = 0xDFC00000;\n    constexpr uint32_t ADD_INSTRUCTION = 0x91000000;\n    if ((add & ADD_MASK) != ADD_INSTRUCTION) {\n        LOG(DEBUG) << \"2nd stub instruction is not a 64-bit add immediate: \" << std::hex << std::setw(8)\n                   << std::setfill('0') << (add & ADD_MASK) << \" != \" << ADD_INSTRUCTION;\n        return 0;\n    }\n\n    // Extract the argument from the adrp instruction. It's in 2 pieces.\n    // The low 2 value bits are in instruction bits 30-29, inclusive.\n    // The high 19 value bits are in instruction bits 23-5, inclusive.\n    constexpr uint32_t ADRP_NUM_LO_BITS = 2;\n    constexpr uint32_t ADRP_NUM_HI_BITS = 19;\n    constexpr uint32_t ADRP_LOWEST_LO_BIT = 29;\n    constexpr uint32_t ADRP_LOWEST_HI_BIT = 5;\n    constexpr uint32_t ADRP_ARG_LO_MASK = ((1 << ADRP_NUM_LO_BITS) - 1) << ADRP_LOWEST_LO_BIT;\n    constexpr uint32_t ADRP_ARG_HI_MASK = ((1 << ADRP_NUM_HI_BITS) - 1) << ADRP_LOWEST_HI_BIT;\n\n    // The constants above show our work. These are the computed masks.\n    static_assert(ADRP_ARG_HI_MASK == 0x00FFFFE0);\n    static_assert(ADRP_ARG_LO_MASK == 0x60000000);\n\n    // Stitch the two pieces together to find the argument's value.\n    int32_t adrp_arg = ((adrp & ADRP_ARG_LO_MASK) >> ADRP_LOWEST_LO_BIT)\n                       | ((adrp & ADRP_ARG_HI_MASK) >> (ADRP_LOWEST_HI_BIT - ADRP_NUM_LO_BITS));\n\n    // If the highest bit of the argument is 1 then the value is negative,\n    // and we need to sign-extend it by prepending 11 (32 - 19 - 2) 1 bits.\n    constexpr uint32_t ADRP_ARG_HIGHEST_BIT_MASK = 1 << (ADRP_LOWEST_HI_BIT + ADRP_NUM_HI_BITS - 1);\n    static_assert(ADRP_ARG_HIGHEST_BIT_MASK == 0x00800000);\n\n    if (adrp & ADRP_ARG_HIGHEST_BIT_MASK) {\n        LOG(DEBUG) << \"sign-extending negative adrp immediate\";\n        adrp_arg |= 0xFFE00000;\n    }\n\n    // Extract the argument from the add instruction. This is easier.\n    // It's the 12 bits immediately above the 10 lowest bits.\n    constexpr uint32_t ADD_ARG_NUM_BITS = 12;\n    constexpr uint32_t ADD_ARG_LOWEST_BIT = 10;\n    constexpr uint32_t ADD_ARG_MASK = ((1 << ADD_ARG_NUM_BITS) - 1) << ADD_ARG_LOWEST_BIT;\n    static_assert(ADD_ARG_MASK == 0x003ffc00);\n\n    const uint32_t add_arg = (add & ADD_ARG_MASK) >> ADD_ARG_LOWEST_BIT;\n\n    // Compute the final address: find the index of the 4 KiB page containing\n    // vaddr, add adrp_arg pages, convert back to a virtual memory address,\n    // and add the add_arg offset.\n    static_assert(1 << 12 == 4 * 1024);\n    return (((vaddr >> 12) + adrp_arg) << 12) + add_arg;\n\n#elif defined(__x86_64__)\n    // For x86_64 architecture, each PLT entry has the following format:\n    //\n    //   jmpq   *OFFSET(%rip)\n    //\n    // This means that the address of the GOT entry can be calculated as:\n    //\n    //   %rip + OFFSET\n    //\n    // Where %rip is the address of the 1st instruction after the jmpq.\n    // In other words, it's the address of the jmpq plus 6 bytes, because\n    // the jmpq instruction is 6 bytes long.\n    //\n    // This code parses the machine code of the PLT entry and checks that it\n    // matches the expected instruction. If not, it returns 0. Otherwise, it\n    // extracts the (signed) OFFSET and computes the GOT entry address.\n    //\n    // Relevant documentation:\n    // https://www.felixcloutier.com/x86/jmp\n\n    // Check if the instruction is a jump.\n    const auto instruction = *reinterpret_cast<const uint16_t*>(vaddr);\n    constexpr uint16_t JMP_INSTRUCTION = 0x25ff;\n    if (instruction != JMP_INSTRUCTION) {\n        LOG(DEBUG) << \"1st stub instruction isn't jmp: \" << std::hex << std::setw(4) << std::setfill('0')\n                   << instruction << \" != \" << JMP_INSTRUCTION;\n        return 0;\n    }\n\n    // Computing the final address by combining the PLT entry address and the offset\n    const auto offset = *reinterpret_cast<const int32_t*>(vaddr + 2);\n    const uint64_t rip = vaddr + sizeof(instruction) + sizeof(offset);\n    return rip + offset;\n\n#else\n    LOG(ERROR) << \"Unknown arch to compute address from stub at \" << std::hex << std::showbase << vaddr;\n    return 0;\n#endif\n}\n\nstatic void\npatch_stubs(\n        const section_t* section,\n        uintptr_t slide,\n        const DynamicInfoTable& dyninfo_table,\n        bool restore_original)\n{\n    auto symbol_addr_table = reinterpret_cast<char*>(slide + section->addr);\n    size_t element_size = section->reserved2;\n    if (element_size == 0) {\n        LOG(DEBUG) << \"Cannot patch stubs because element size is 0\";\n        return;\n    }\n    for (unsigned int i = 0; i < section->size / element_size; i++) {\n        const char* symbol_name = dyninfo_table.getSymbol(section->reserved1, i);\n        if (!symbol_name || !(symbol_name[0] == '_' || symbol_name[0] == '.') || !symbol_name[1]) {\n            continue;\n        }\n        const char* canonical_name = get_canonical_name(symbol_name);\n        auto stub_addr = reinterpret_cast<uint64_t>(symbol_addr_table + i * element_size);\n#define FOR_EACH_HOOKED_FUNCTION(hookname)                                                              \\\n    if (strcmp(MEMRAY_ORIG(hookname).d_symbol, canonical_name + 1) == 0) {                              \\\n        LOG(DEBUG) << \"Extracting symbol address for \" << symbol_name << \" from stub function at \"      \\\n                   << std::hex << std::showbase << stub_addr;                                           \\\n        void* symbol_addr = reinterpret_cast<void*>(lazy_pointer_from_stub(stub_addr));                 \\\n        if (!symbol_addr) {                                                                             \\\n            LOG(DEBUG) << \"Symbol address could not be identified\";                                     \\\n            continue;                                                                                   \\\n        }                                                                                               \\\n        LOG(DEBUG) << \"Patching \" << symbol_name << \" pointer at address \" << std::hex << std::showbase \\\n                   << symbol_addr;                                                                      \\\n        patch_symbol(                                                                                   \\\n                MEMRAY_ORIG(hookname),                                                                  \\\n                &intercept::hookname,                                                                   \\\n                symbol_name,                                                                            \\\n                symbol_addr,                                                                            \\\n                restore_original);                                                                      \\\n        continue;                                                                                       \\\n    }\n        MEMRAY_HOOKED_FUNCTIONS\n#undef FOR_EACH_HOOKED_FUNCTION\n    }\n}\n\nstatic void\npatch_symbols_in_shared_object(\n        const struct mach_header* header,\n        intptr_t slide,\n        const char* image_name,\n        bool restore_original,\n        std::set<std::string>& patched)\n{\n    if (!restore_original) {\n        if (patched.find(image_name) != patched.end()) {\n            // We already patched this library\n            return;\n        }\n        patched.insert(image_name);\n    }\n\n    if (strstr(image_name, \"memray.cpython\") || strstr(image_name, \"/dyld\")\n        || strstr(image_name, \"dyld.dylib\"))\n    {\n        LOG(DEBUG) << \"Skipping patching symbols for \" << image_name;\n        return;\n    }\n    LOG(DEBUG) << \"Patching symbols for \" << image_name;\n\n    auto segment_filter = [](const char* seg_name) {\n        return strcmp(seg_name, SEG_DATA) == 0 || strcmp(seg_name, SEG_DATA_CONST) == 0\n               || strcmp(seg_name, SEG_AUTH_CONST) == 0 || strcmp(seg_name, SEG_TEXT) == 0;\n    };\n\n    DynamicInfoTable dyninfo_table(header, slide, segment_filter);\n    if (!dyninfo_table) {\n        LOG(DEBUG) << \"Could not construct dynamic information table\" << image_name;\n        return;\n    }\n\n    LOG(DEBUG) << \"Found \" << dyninfo_table.segments.size() << \" data segments\";\n\n    for (const auto& segment_cmd : dyninfo_table.segments) {\n        const auto current_seg = reinterpret_cast<uintptr_t>(segment_cmd);\n        auto section_head = reinterpret_cast<const section_t*>(current_seg + sizeof(segment_command_t));\n        LOG(DEBUG) << \"Considering segment \" << segment_cmd->segname;\n        for (size_t i = 0; i < segment_cmd->nsects; i++) {\n            const section_t* section = section_head + i;\n            unsigned int section_type = section->flags & SECTION_TYPE;\n            LOG(DEBUG) << \"Considering section \" << i << \" (\" << section->segname << \":\"\n                       << section->sectname << \")\";\n\n            // dlopen with null and check for _dyld_shared_cache_contains_path but do it only\n            // once with std::once_flag\n            static std::function<bool(const char*)> dyld_shared_cache_contains_path;\n            static std::once_flag _dyld_shared_cache_check_flag;\n            std::call_once(_dyld_shared_cache_check_flag, [&]() {\n                void* handle = dlopen(nullptr, RTLD_LAZY);\n                dyld_shared_cache_contains_path =\n                        (bool (*)(const char*))(dlsym(handle, \"_dyld_shared_cache_contains_path\"));\n                dlclose(handle);\n            });\n\n            if (dyld_shared_cache_contains_path && _dyld_shared_cache_contains_path(image_name)\n                && strcmp(section->segname, SEG_TEXT) == 0)\n            {\n                // Shared libraries that are part of the shared cache will have the symbols we are\n                // looking for in the __stubs/__auth_stubs PLT section pointing to a GOT that we cannot\n                // access checking data sections. This means that the only way to get the GOT location\n                // is by analyzing the PLT stubs directly using dark rituals and black magic.\n                if (strcmp(section->sectname, \"__auth_stubs\") != 0\n                    && strcmp(section->sectname, \"__stubs\") != 0)\n                {\n                    LOG(DEBUG) << \"Skipping section \" << i << \" (\" << section->segname << \":\"\n                               << section->sectname << \")\";\n                    continue;\n                }\n                // MacOS has some memory interposition libraries that can make us crash (via\n                // stackoverflow when initializing TLS variables) if we patch them. This is because these\n                // libraries interact in a way we cannot avoid with libdyld, which in turn sets the TLS\n                // on first init.\n                if (strstr(image_name, \"MallocStackLogging\")) {\n                    LOG(DEBUG) << \"Skipping section \" << i << \" (\" << section->segname << \":\"\n                               << section->sectname << \")\";\n                    continue;\n                }\n                LOG(DEBUG) << \"Patching section \" << i << \" (\" << section->segname << \":\"\n                           << section->sectname << \")\";\n                patch_stubs(section, slide, dyninfo_table, restore_original);\n            } else {\n                if (section_type != S_LAZY_SYMBOL_POINTERS && section_type != S_NON_LAZY_SYMBOL_POINTERS)\n                {\n                    LOG(DEBUG) << \"Skipping section \" << i << \" (\" << section->segname << \":\"\n                               << section->sectname << \")\";\n                    continue;\n                }\n                LOG(DEBUG) << \"Patching section \" << i << \" (\" << section->segname << \":\"\n                           << section->sectname << \")\";\n                patch_symbols_in_section(section, slide, dyninfo_table, restore_original);\n            }\n        }\n    }\n}\n\nstatic void\npatch_symbols_in_all_shared_objects(bool restore_original, std::set<std::string>& patched)\n{\n    if (restore_original) {\n        patched.clear();\n    }\n    uint32_t c = _dyld_image_count();\n    for (uint32_t i = 0; i < c; i++) {\n        const struct mach_header* header = _dyld_get_image_header(i);\n        intptr_t slide = _dyld_get_image_vmaddr_slide(i);\n        const char* image_name = _dyld_get_image_name(i);\n        if (strstr(image_name, \"libdyld.dylib\") || strstr(image_name, \"/usr/lib/system/\")) {\n            LOG(DEBUG) << \"Skipping patching image: \" << image_name;\n            continue;\n        }\n        LOG(DEBUG) << \"Patching image: \" << image_name;\n        patch_symbols_in_shared_object(header, slide, image_name, restore_original, patched);\n    }\n}\n\n/* Public API functions */\n\nvoid\nSymbolPatcher::overwrite_symbols() noexcept\n{\n    patch_symbols_in_all_shared_objects(false, symbols);\n}\n\nvoid\nSymbolPatcher::restore_symbols() noexcept\n{\n    patch_symbols_in_all_shared_objects(true, symbols);\n}\n\n}  // namespace memray::linker\n"
  },
  {
    "path": "src/memray/_memray/macho_utils.h",
    "content": "#pragma once\n\n#include <cstring>\n#include <dlfcn.h>\n#include <mach-o/dyld.h>\n#include <mach-o/loader.h>\n#include <mach-o/nlist.h>\n#include <mach/mach.h>\n#include <mach/vm_map.h>\n#include <mach/vm_region.h>\n#include <sys/types.h>\n#include <vector>\n\n#include \"hooks.h\"\n#include \"linker_shenanigans.h\"\n#include \"logging.h\"\n\n#ifndef __APPLE__\n#    error \"This file can only be compiled in MacOS systems\"\n#endif\n\n#ifdef __LP64__\ntypedef struct mach_header_64 mach_header_t;\ntypedef struct segment_command_64 segment_command_t;\ntypedef struct section_64 section_t;\ntypedef struct nlist_64 nlist_t;\n#    define ARCH_LC_SEGMENT LC_SEGMENT_64\n#else\ntypedef struct mach_header mach_header_t;\ntypedef struct segment_command segment_command_t;\ntypedef struct section section_t;\ntypedef struct nlist nlist_t;\n#    define ARCH_LC_SEGMENT LC_SEGMENT\n#endif\n\n#ifndef SEG_DATA_CONST\n#    define SEG_DATA_CONST \"__DATA_CONST\"\n#endif\n\n#ifndef SEG_AUTH_CONST\n#    define SEG_AUTH_CONST \"__AUTH_CONST\"\n#endif\n\nstruct DynamicInfoTable\n{\n    using segment_filter_t = std::function<bool(const char* segname)>;\n\n    const nlist_t* symbol_table = nullptr;\n    const char* string_table = nullptr;\n    const uint32_t* dynsym_table = nullptr;\n    std::vector<const segment_command_t*> segments;\n\n    explicit DynamicInfoTable(\n            const struct mach_header* header,\n            uintptr_t slide,\n            const segment_filter_t& segment_filter)\n    {\n        const segment_command_t* linkedit_cmd = nullptr;\n        const struct symtab_command* symtab_cmd = nullptr;\n        const struct dysymtab_command* dysym_cmd = nullptr;\n\n        const segment_command_t* current_segment_cmd = nullptr;\n        uintptr_t current_cmd = reinterpret_cast<uintptr_t>(header) + sizeof(mach_header_t);\n        for (uint i = 0; i < header->ncmds; i++, current_cmd += current_segment_cmd->cmdsize) {\n            current_segment_cmd = reinterpret_cast<const segment_command_t*>(current_cmd);\n            switch (current_segment_cmd->cmd) {\n                case ARCH_LC_SEGMENT: {\n                    const char* segname = current_segment_cmd->segname;\n                    if (strcmp(segname, SEG_LINKEDIT) == 0) {\n                        linkedit_cmd = current_segment_cmd;\n                    }\n                    if (segment_filter(segname)) {\n                        segments.emplace_back(current_segment_cmd);\n                    }\n                } break;\n                case LC_SYMTAB:\n                    symtab_cmd = reinterpret_cast<const symtab_command*>(current_segment_cmd);\n                    break;\n                case LC_DYSYMTAB:\n                    dysym_cmd = reinterpret_cast<const dysymtab_command*>(current_segment_cmd);\n                    break;\n            }\n        }\n\n        if (!linkedit_cmd || !symtab_cmd || !dysym_cmd) {\n            return;\n        }\n        const auto linkedit_base = slide + linkedit_cmd->vmaddr - linkedit_cmd->fileoff;\n        symbol_table = reinterpret_cast<nlist_t*>(linkedit_base + symtab_cmd->symoff);\n        string_table = reinterpret_cast<char*>(linkedit_base + symtab_cmd->stroff);\n        dynsym_table = reinterpret_cast<uint32_t*>(linkedit_base + dysym_cmd->indirectsymoff);\n    }\n\n    explicit operator bool() const\n    {\n        return symbol_table && string_table && dynsym_table;\n    }\n\n    [[nodiscard]] const char* getSymbol(uintptr_t section_offset, unsigned long index) const\n    {\n        auto index_into_symtable = (dynsym_table + section_offset)[index];\n        if (index_into_symtable & (INDIRECT_SYMBOL_ABS | INDIRECT_SYMBOL_LOCAL)) {\n            return nullptr;\n        }\n\n        uint32_t string_table_offset = symbol_table[index_into_symtable].n_un.n_strx;\n        return string_table + string_table_offset;\n    }\n};\n"
  },
  {
    "path": "src/memray/_memray/native_resolver.cpp",
    "content": "#include <cstring>\n#include <iostream>\n#include <utility>\n\n#include \"native_resolver.h\"\n\n#include \"logging.h\"\n\nnamespace memray::native_resolver {\n\n#ifdef __APPLE__\nstatic const logLevel RESOLVE_LIB_LOG_LEVEL = DEBUG;\n#else\nstatic const logLevel RESOLVE_LIB_LOG_LEVEL = WARNING;\n#endif\n\nstd::unordered_set<std::string> InternedString::s_interned_data = []() {\n    std::unordered_set<std::string> ret;\n    ret.reserve(4096);\n    return ret;\n}();\n\nstd::mutex InternedString::s_mutex;\n\nSymbolResolver::BacktraceStateCache SymbolResolver::s_backtrace_states = []() {\n    SymbolResolver::BacktraceStateCache ret;\n    ret.reserve(PREALLOCATED_BACKTRACE_STATES);\n    return ret;\n}();\n\nstd::mutex SymbolResolver::s_backtrace_states_mutex;\n\nInternedString::InternedString(const std::string& orig)\n: d_ref(internString(orig))\n{\n}\n\nconst std::string&\nInternedString::get() const\n{\n    return d_ref.get();\n}\n\nInternedString::operator const std::string&() const\n{\n    return d_ref.get();\n}\n\nstd::reference_wrapper<const std::string>\nInternedString::internString(const std::string& orig)\n{\n    std::lock_guard<std::mutex> lock(s_mutex);\n    auto inserted = s_interned_data.insert(orig);\n    return *inserted.first;\n}\n\nMemorySegment::MemorySegment(\n        InternedString filename,\n        uintptr_t start,\n        uintptr_t end,\n        backtrace_state* state)\n: d_filename(filename)\n, d_start(start)\n, d_end(end)\n, d_state(state)\n{\n}\n\nstatic std::string\ndemangle(const char* function)\n{\n    if (!function) {\n        return {};\n    } else if (function[0] != '_' || function[1] != 'Z') {\n        return {function};\n    }\n\n    std::string ret;\n    int status = 0;\n    char* demangled = abi::__cxa_demangle(function, nullptr, nullptr, &status);\n    if (demangled != nullptr) {\n        ret = demangled;\n        free(demangled);\n    } else {\n        ret = function;\n    }\n    return ret;\n}\n\nvoid\nMemorySegment::resolveFromSymbolTable(uintptr_t address, MemorySegment::ExpandedFrame& expanded_frame)\n        const\n{\n    struct CallbackData\n    {\n        ExpandedFrame* expanded_frame;\n        const MemorySegment* segment;\n        uintptr_t address;\n    };\n    CallbackData data = {&expanded_frame, this, address};\n\n    auto callback = [](void* data, uintptr_t, const char* symbol, uintptr_t, uintptr_t) {\n        const std::string the_symbol = demangle(symbol);\n        auto the_data = reinterpret_cast<CallbackData*>(data);\n        the_data->expanded_frame->push_back(\n                Frame{the_symbol.empty() ? \"<unknown>\" : the_symbol, \"<unknown>\", 0});\n    };\n    auto error_callback = [](void* _data, const char* msg, int errnum) {\n        auto* data = reinterpret_cast<const CallbackData*>(_data);\n        LOG(ERROR) << \"Error getting backtrace for address \" << std::hex << data->address << std::dec\n                   << \" in segment \" << data->segment->d_filename.get() << \" (errno \" << errnum\n                   << \"): \" << msg;\n    };\n    backtrace_syminfo(d_state, address, callback, error_callback, &data);\n}\n\nvoid\nMemorySegment::resolveFromDebugInfo(uintptr_t address, MemorySegment::ExpandedFrame& expanded_frame)\n        const\n{\n    auto callback =\n            [](void* data, uintptr_t /*addr*/, const char* file, int line, const char* symbol) -> int {\n        const std::string the_symbol = demangle(symbol);\n        if (the_symbol.empty()) {\n            return 0;\n        }\n        Frame frame{the_symbol, file ? file : \"<unknown>\", line};\n        auto expanded_frame = reinterpret_cast<ExpandedFrame*>(data);\n        expanded_frame->push_back(frame);\n        return 0;\n    };\n    auto error_callback = [](void* data, const char*, int) {\n        auto expanded_frame = reinterpret_cast<ExpandedFrame*>(data);\n        // Ensure that on failure we fall back to the symbol table approach if the regular\n        // callback has been called previously.\n        expanded_frame->clear();\n    };\n    backtrace_pcinfo(d_state, address, callback, error_callback, &expanded_frame);\n}\n\nMemorySegment::ExpandedFrame\nMemorySegment::resolveIp(uintptr_t address) const\n{\n    ExpandedFrame expanded_frame{};\n    assert(d_state != nullptr);\n    // libbacktrace expects a program counter that is 1 byte less than the one produced by\n    // libunwind (and any other unwinder that I tested). This is because libbacktrace's native\n    // unwinder does indeed produce program counters with one byte less for some reason and\n    // libbacktrace's symbolizer is prepared to work with libbacktrace's machinery convention.\n    uintptr_t corrected_address = address - 1;\n    resolveFromDebugInfo(corrected_address, expanded_frame);\n    if (expanded_frame.empty()) {\n        resolveFromSymbolTable(corrected_address, expanded_frame);\n    }\n    return expanded_frame;\n}\n\nbool\nMemorySegment::operator<(const MemorySegment& segment) const\n{\n    return std::tie(d_start, d_end, d_filename.get())\n           < std::tie(segment.d_start, segment.d_end, segment.d_filename.get());\n}\n\nbool\nMemorySegment::operator!=(const MemorySegment& segment) const\n{\n    return std::tie(d_start, d_end, d_filename.get())\n           != std::tie(segment.d_start, segment.d_end, segment.d_filename.get());\n}\n\nbool\nMemorySegment::isAddressInRange(uintptr_t addr) const\n{\n    return d_start <= addr && d_end > addr;\n}\n\nuintptr_t\nMemorySegment::start() const\n{\n    return d_start;\n}\n\nuintptr_t\nMemorySegment::end() const\n{\n    return d_end;\n}\n\nInternedString\nMemorySegment::filename() const\n{\n    return d_filename;\n}\n\nResolvedFrame::ResolvedFrame(InternedString symbol, InternedString filename, int lineno)\n: d_symbol(symbol)\n, d_filename(filename)\n, d_line(lineno)\n{\n}\n\nconst std::string&\nResolvedFrame::Symbol() const\n{\n    return d_symbol;\n}\n\nconst std::string&\nResolvedFrame::File() const\n{\n    return d_filename;\n}\n\nint\nResolvedFrame::Line() const\n{\n    return d_line;\n}\n\nPyObject*\nResolvedFrame::toPythonObject(python_helpers::PyUnicode_Cache& pystring_cache) const\n{\n    PyObject* pyfunction_name = pystring_cache.getUnicodeObject(Symbol());  // Borrowed\n    if (pyfunction_name == nullptr) {\n        return nullptr;\n    }\n    PyObject* pyfilename = pystring_cache.getUnicodeObject(File());  // Borrowed\n    if (pyfilename == nullptr) {\n        return nullptr;\n    }\n    PyObject* pylineno = PyLong_FromLong(Line());\n    if (pylineno == nullptr) {\n        return nullptr;\n    }\n    PyObject* tuple = PyTuple_New(3);\n    if (tuple == nullptr) {\n        Py_DECREF(pylineno);\n        return nullptr;\n    }\n    Py_INCREF(pyfunction_name);\n    Py_INCREF(pyfilename);\n    PyTuple_SET_ITEM(tuple, 0, pyfunction_name);\n    PyTuple_SET_ITEM(tuple, 1, pyfilename);\n    PyTuple_SET_ITEM(tuple, 2, pylineno);\n    return tuple;\n}\n\nconst std::string&\nResolvedFrames::memoryMap() const\n{\n    return d_interned_memory_map_name;\n}\n\nconst std::vector<ResolvedFrame>&\nResolvedFrames::frames() const\n{\n    return d_frames;\n}\n\nSymbolResolver::SymbolResolver()\n{\n    d_resolved_ips_cache.reserve(PREALLOCATED_IPS_CACHE_ITEMS);\n}\n\ntemplate<typename T>\nstatic auto\nfindModule(const uintptr_t ip, const T& segments)\n{\n    return lower_bound(\n            segments.begin(),\n            segments.end(),\n            ip,\n            [](const MemorySegment& segment, const uintptr_t ip) { return segment.end() < ip; });\n}\n\nSymbolResolver::resolved_frames_t\nSymbolResolver::resolve(uintptr_t ip, size_t generation)\n{\n    // Check if we have resolved this frame previously\n    auto it = d_resolved_ips_cache.find({ip, generation});\n    if (it == d_resolved_ips_cache.end()) {\n        // This is the first time we resolved this frame, do the actual resolution\n        // work and insert it into the cache.\n        auto resolved_frames = resolveFromSegments(ip, generation);\n        it = d_resolved_ips_cache.emplace(ips_cache_pair_t(ip, generation), resolved_frames).first;\n    }\n    return it->second;\n}\n\nSymbolResolver::resolved_frames_t\nSymbolResolver::resolveFromSegments(uintptr_t ip, size_t generation)\n{\n    if (d_are_segments_dirty) {\n        // Sort the segments so the binary search below works\n        sort(currentSegments().begin(), currentSegments().end());\n        d_are_segments_dirty = false;\n    }\n\n    const auto& segments = d_segments.at(generation);\n    auto segment = findModule(ip, segments);\n    if (segment == segments.end() || !segment->isAddressInRange(ip)) {\n        return nullptr;\n    }\n\n    std::vector<ResolvedFrame> frames;\n    const auto expanded_frame = segment->resolveIp(ip);\n    if (expanded_frame.empty()) {\n        return nullptr;\n    }\n    std::transform(\n            expanded_frame.begin(),\n            expanded_frame.end(),\n            std::back_inserter(frames),\n            [](const auto& frame) {\n                return ResolvedFrame{\n                        InternedString(frame.symbol),\n                        InternedString(frame.filename),\n                        frame.lineno,\n                };\n            });\n    return std::make_shared<ResolvedFrames>(segment->filename(), std::move(frames));\n}\n\nvoid\nSymbolResolver::addSegment(\n        InternedString filename,\n        backtrace_state* backtrace_state,\n        const uintptr_t address_start,\n        const uintptr_t address_end)\n{\n    currentSegments().emplace_back(filename, address_start, address_end, backtrace_state);\n    d_are_segments_dirty = true;\n}\n\nvoid\nSymbolResolver::addSegments(\n        const std::string& filename,\n        uintptr_t addr,\n        const std::vector<tracking_api::Segment>& segments)\n{\n    InternedString interned_filename(filename);\n    auto state = getBacktraceState(interned_filename, addr);\n    if (state == nullptr) {\n        LOG(RESOLVE_LIB_LOG_LEVEL) << \"Failed to prepare a backtrace state for \" << filename;\n        return;\n    }\n\n    for (const auto& segment : segments) {\n        const uintptr_t segment_start = addr + segment.vaddr;\n        const uintptr_t segment_end = addr + segment.vaddr + segment.memsz;\n        addSegment(interned_filename, state, segment_start, segment_end);\n    }\n}\n\nvoid\nSymbolResolver::clearSegments()\n{\n    if (d_are_segments_dirty) {\n        // Sort the segments so the binary search in resolve() works\n        sort(currentSegments().begin(), currentSegments().end());\n    }\n    size_t reserve_size = 256;\n    if (currentSegmentGeneration() > 0) {\n        reserve_size = currentSegments().size();\n    }\n    d_segments[currentSegmentGeneration() + 1].reserve(reserve_size);\n}\n\nbacktrace_state*\nSymbolResolver::getBacktraceState(InternedString interned_filename, uintptr_t address_start)\n{\n    // We hash into \"s_backtrace_states\" using a `const char*`. This is safe\n    // because every `const char*` we save is owned by an interned string.\n    const char* filename = interned_filename.get().c_str();\n    auto key = std::make_pair(filename, address_start);\n\n    std::lock_guard<std::mutex> lock(s_backtrace_states_mutex);\n\n    auto it = s_backtrace_states.find(key);\n    if (it != s_backtrace_states.end()) {\n        return it->second;\n    }\n\n    struct CallbackData\n    {\n        const char* fileName;\n    };\n    CallbackData data = {filename};\n\n    auto errorHandler = [](void* rawData, const char* msg, int errnum) {\n        auto data = reinterpret_cast<const CallbackData*>(rawData);\n        LOG(RESOLVE_LIB_LOG_LEVEL) << \"Error creating backtrace state for segment \" << data->fileName\n                                   << \"(errno \" << errnum << \"): \" << msg;\n    };\n\n    auto state = backtrace_create_state(data.fileName, true, errorHandler, &data);\n\n    if (!state) {\n        return nullptr;\n    }\n\n    const int descriptor = backtrace_open(data.fileName, errorHandler, &data, nullptr);\n    if (descriptor >= 1) {\n        int foundSym = 0;\n        struct libbacktrace_base_address base_address = {address_start};\n#ifdef __linux__\n        int foundDwarf = 0;\n        auto ret =\n                elf_add(state,\n                        data.fileName,\n                        descriptor,\n                        nullptr,\n                        0,\n                        base_address,\n                        nullptr,\n                        errorHandler,\n                        &data,\n                        &state->fileline_fn,\n                        &foundSym,\n                        &foundDwarf,\n                        nullptr,\n                        false,\n                        false,\n                        nullptr,\n                        0);\n        state->syminfo_fn = (ret && foundSym) ? &elf_syminfo : &elf_nosyms;\n#elif defined(__APPLE__)\n        auto ret = macho_add(\n                state,\n                data.fileName,\n                descriptor,\n                0,\n                nullptr,\n                base_address,\n                0,\n                errorHandler,\n                &data,\n                &state->fileline_fn,\n                &foundSym);\n        state->syminfo_fn = (ret && foundSym) ? &macho_syminfo : &macho_nosyms;\n#else\n        return nullptr;\n#endif\n    }\n\n    s_backtrace_states.insert(it, {key, state});\n    return state;\n}\n\nstd::vector<MemorySegment>&\nSymbolResolver::currentSegments()\n{\n    return d_segments.at(d_segments.size());\n}\n\nsize_t\nSymbolResolver::currentSegmentGeneration() const\n{\n    return d_segments.size();\n}\n\nstd::vector<std::string>\nunwindHere()\n{\n    struct CallbackData\n    {\n        std::vector<std::string> frames;\n        struct backtrace_state* state;\n    };\n\n    auto err_callback = [](void* data, const char* msg, int errnum) { return; };\n\n    auto callback = [](void* vdata, uintptr_t pc, const char* filename, int lineno, const char* function)\n            -> int {\n        auto result = reinterpret_cast<CallbackData*>(vdata);\n        std::string the_function = function ? function : \"\";\n        std::string the_filename = filename ? filename : \"\";\n        if (!function && !filename) {\n            // Fallback callbacks for when we can't get a filename or function name via debug\n            // information. These fallback callbacks query the symbol table instead.\n            auto fallback_callback =\n                    [](void* data, uintptr_t, const char* symbol, uintptr_t, uintptr_t) {\n                        auto result = reinterpret_cast<std::vector<std::string>*>(data);\n                        std::string the_function = symbol ? symbol : \"\";\n                        result->push_back(the_function + \"::\");\n                    };\n            auto fallback_err_callback = [](void* data, const char* msg, int errnum) { return; };\n            backtrace_syminfo(result->state, pc, fallback_callback, fallback_err_callback, vdata);\n        } else {\n            result->frames.push_back(the_function + \":\" + the_filename + \":\" + std::to_string(lineno));\n        }\n        return 0;\n    };\n\n    struct backtrace_state* state = backtrace_create_state(\"\", 1, err_callback, nullptr);\n    if (!state) {\n        return {};\n    }\n    CallbackData data = {std::vector<std::string>(), state};\n    ::backtrace_full(state, 0, callback, err_callback, &data);\n    return data.frames;\n}\n\n}  // namespace memray::native_resolver\n"
  },
  {
    "path": "src/memray/_memray/native_resolver.h",
    "content": "#pragma once\n\n#define PY_SSIZE_T_CLEAN\n#include <Python.h>\n\n#include <algorithm>\n#include <memory>\n#include <string>\n#include <tuple>\n#include <unistd.h>\n#include <unordered_map>\n#include <unordered_set>\n#include <utility>\n#include <vector>\n\n#include <cxxabi.h>\n\n#include <libbacktrace/backtrace.h>\n#include <libbacktrace/internal.h>\n\n#include \"python_helpers.h\"\n#include \"records.h\"\n\nnamespace memray::native_resolver {\n\nstatic constexpr int PREALLOCATED_BACKTRACE_STATES = 64;\nstatic constexpr int PREALLOCATED_IPS_CACHE_ITEMS = 32768;\n\nclass InternedString\n{\n  public:\n    explicit InternedString(const std::string& orig);\n    const std::string& get() const;\n    operator const std::string&() const;\n\n  private:\n    static std::reference_wrapper<const std::string> internString(const std::string& orig);\n\n    std::reference_wrapper<const std::string> d_ref;\n\n    static std::mutex s_mutex;\n    static std::unordered_set<std::string> s_interned_data;\n};\n\nclass MemorySegment\n{\n  public:\n    // Aliases and helpers\n    struct Frame\n    {\n        std::string symbol;\n        std::string filename;\n        int lineno;\n    };\n\n    using ExpandedFrame = std::vector<Frame>;\n\n    // Constructors\n    MemorySegment(InternedString filename, uintptr_t start, uintptr_t end, backtrace_state* state);\n\n    ExpandedFrame resolveIp(uintptr_t address) const;\n    bool operator<(const MemorySegment& segment) const;\n    bool operator!=(const MemorySegment& segment) const;\n    bool isAddressInRange(uintptr_t addr) const;\n\n    // Getters\n    uintptr_t start() const;\n    uintptr_t end() const;\n    InternedString filename() const;\n\n  private:\n    // Methods\n    void resolveFromDebugInfo(uintptr_t address, ExpandedFrame& expanded_frame) const;\n    void resolveFromSymbolTable(uintptr_t address, ExpandedFrame& expanded_frame) const;\n\n    // Data members\n    InternedString d_filename;\n    uintptr_t d_start;\n    uintptr_t d_end;\n    backtrace_state* d_state;\n};\n\nclass ResolvedFrame\n{\n  public:\n    // Constructors\n    ResolvedFrame(InternedString symbol, InternedString filename, int lineno);\n\n    // Methods\n    PyObject* toPythonObject(python_helpers::PyUnicode_Cache& pystring_cache) const;\n\n    // Getters\n    const std::string& Symbol() const;\n    const std::string& File() const;\n    int Line() const;\n\n  private:\n    // Data members\n    InternedString d_symbol;\n    InternedString d_filename;\n    int d_line;\n};\n\nclass ResolvedFrames\n{\n  public:\n    // Constructors\n    template<typename T>\n    ResolvedFrames(InternedString interned_memory_map_name, T&& frames)\n    : d_interned_memory_map_name(interned_memory_map_name)\n    , d_frames(std::forward<T>(frames))\n    {\n    }\n\n    // Getters\n    const std::string& memoryMap() const;\n    const std::vector<ResolvedFrame>& frames() const;\n\n  private:\n    // Data members\n    InternedString d_interned_memory_map_name;\n    std::vector<ResolvedFrame> d_frames{};\n};\n\nclass SymbolResolver\n{\n  public:\n    using resolved_frames_t = std::shared_ptr<const ResolvedFrames>;\n\n    // Constructors\n    SymbolResolver();\n\n    // Methods\n    resolved_frames_t resolve(uintptr_t ip, size_t generation);\n    void addSegments(\n            const std::string& filename,\n            uintptr_t addr,\n            const std::vector<tracking_api::Segment>& segments);\n    void clearSegments();\n\n    static backtrace_state* getBacktraceState(InternedString filename, uintptr_t address_start);\n\n    // Getters\n    size_t currentSegmentGeneration() const;\n\n  private:\n    // Aliases and helpers\n    using ips_cache_pair_t = std::pair<uintptr_t, ssize_t>;\n\n    struct pair_hash\n    {\n        template<class T1, class T2>\n        std::size_t operator()(const std::pair<T1, T2>& pair) const\n        {\n            return std::hash<T1>()(pair.first) ^ std::hash<T2>()(pair.second);\n        }\n    };\n\n    using BacktraceStateCache =\n            std::unordered_map<std::pair<const char*, uintptr_t>, backtrace_state*, pair_hash>;\n\n    // Methods\n    void addSegment(\n            InternedString filename,\n            backtrace_state* backtrace_state,\n            uintptr_t address_start,\n            uintptr_t address_end);\n    std::vector<MemorySegment>& currentSegments();\n    resolved_frames_t resolveFromSegments(uintptr_t ip, size_t generation);\n\n    // Data members\n    std::unordered_map<size_t, std::vector<MemorySegment>> d_segments;\n    bool d_are_segments_dirty = false;\n    mutable std::unordered_map<ips_cache_pair_t, resolved_frames_t, pair_hash> d_resolved_ips_cache;\n\n    static std::mutex s_backtrace_states_mutex;\n    static BacktraceStateCache s_backtrace_states;\n};\n\nstd::vector<std::string>\nunwindHere();\n}  // namespace memray::native_resolver\n"
  },
  {
    "path": "src/memray/_memray/native_resolver.pxd",
    "content": "from libcpp.string cimport string\nfrom libcpp.vector cimport vector\n\n\ncdef extern from \"native_resolver.h\" namespace \"memray::native_resolver\":\n    vector[string] unwindHere() except+\n"
  },
  {
    "path": "src/memray/_memray/pthread.pxd",
    "content": "cdef extern from \"<pthread.h>\" nogil:\n    ctypedef int pthread_t\n\n    ctypedef struct pthread_attr_t:\n        pass\n    ctypedef struct pthread_mutexattr_t:\n        pass\n    ctypedef struct pthread_mutex_t:\n       pass\n\n    enum:\n        PTHREAD_CANCEL_ENABLE\n        PTHREAD_CANCEL_DISABLE\n\n    int pthread_cancel(pthread_t thread)\n    int pthread_setcancelstate(int state, int *oldstate)\n    pthread_t pthread_self()\n    int pthread_equal(pthread_t t1, pthread_t t2)\n    int pthread_create(pthread_t *thread, pthread_attr_t *attr,\n                       void *(*start_routine) (void *), void *arg)\n    int pthread_join(pthread_t thread, void **retval)\n    int pthread_kill(pthread_t thread, int sig)\n"
  },
  {
    "path": "src/memray/_memray/python_helpers.cpp",
    "content": "#include \"python_helpers.h\"\n\nnamespace memray::python_helpers {\nPyObject*\nPyUnicode_Cache::getUnicodeObject(const std::string& str)\n{\n    auto it = d_cache.find(str);\n    if (it == d_cache.end()) {\n        PyObject* pystring = PyUnicode_FromString(str.c_str());\n        if (pystring == nullptr) {\n            return nullptr;\n        }\n        auto pystring_capsule = py_capsule_t(pystring, [](auto obj) { Py_DECREF(obj); });\n        it = d_cache.emplace(str, std::move(pystring_capsule)).first;\n    }\n    return it->second.get();\n}\n}  // namespace memray::python_helpers\n"
  },
  {
    "path": "src/memray/_memray/python_helpers.h",
    "content": "#pragma once\n\n#define PY_SSIZE_T_CLEAN\n#include <Python.h>\n\n#include <functional>\n#include <memory>\n#include <string>\n#include <unordered_map>\n\nnamespace memray::python_helpers {\nclass PyUnicode_Cache\n{\n  public:\n    PyObject* getUnicodeObject(const std::string& str);\n\n  private:\n    using py_capsule_t = std::unique_ptr<PyObject, std::function<void(PyObject*)>>;\n    std::unordered_map<std::string, py_capsule_t> d_cache{};\n};\n}  // namespace memray::python_helpers\n"
  },
  {
    "path": "src/memray/_memray/record_reader.cpp",
    "content": "#define __STDC_FORMAT_MACROS\n#define PY_SSIZE_T_CLEAN\n#include <Python.h>\n\n#include <algorithm>\n#include <array>\n#include <cinttypes>\n#include <cstdio>\n#include <stdexcept>\n#include <unordered_map>\n\n#include \"compat.h\"\n#include \"hooks.h\"\n#include \"logging.h\"\n#include \"record_reader.h\"\n#include \"records.h\"\n#include \"source.h\"\n\nnamespace memray::api {\n\nusing namespace tracking_api;\nusing namespace io;\n\nnamespace {  // unnamed\n\nconst char*\nallocatorName(hooks::Allocator allocator)\n{\n    switch (allocator) {\n        case hooks::Allocator::MALLOC:\n            return \"malloc\";\n        case hooks::Allocator::FREE:\n            return \"free\";\n        case hooks::Allocator::CALLOC:\n            return \"calloc\";\n        case hooks::Allocator::REALLOC:\n            return \"realloc\";\n        case hooks::Allocator::POSIX_MEMALIGN:\n            return \"posix_memalign\";\n        case hooks::Allocator::ALIGNED_ALLOC:\n            return \"aligned_alloc\";\n        case hooks::Allocator::MEMALIGN:\n            return \"memalign\";\n        case hooks::Allocator::VALLOC:\n            return \"valloc\";\n        case hooks::Allocator::PVALLOC:\n            return \"pvalloc\";\n        case hooks::Allocator::MMAP:\n            return \"mmap\";\n        case hooks::Allocator::MUNMAP:\n            return \"munmap\";\n        case hooks::Allocator::PYMALLOC_MALLOC:\n            return \"pymalloc_malloc\";\n        case hooks::Allocator::PYMALLOC_CALLOC:\n            return \"pymalloc_calloc\";\n        case hooks::Allocator::PYMALLOC_REALLOC:\n            return \"pymalloc_realloc\";\n        case hooks::Allocator::PYMALLOC_FREE:\n            return \"pymalloc_free\";\n    }\n\n    return nullptr;\n}\n\n}  // unnamed namespace\n\nvoid\nRecordReader::readHeader(HeaderRecord& header)\n{\n    if (!d_input->read(header.magic, sizeof(MAGIC)) || (memcmp(header.magic, MAGIC, sizeof(MAGIC)) != 0))\n    {\n        throw std::ios_base::failure(\n                \"The provided input file does not look like a binary generated by memray.\");\n    }\n    if (!d_input->read(reinterpret_cast<char*>(&header.version), sizeof(header.version))) {\n        throw std::ios_base::failure(\"Failed to read input file header.\");\n    }\n    if (header.version != CURRENT_HEADER_VERSION) {\n        throw std::ios_base::failure(\n                \"The provided input file is incompatible with this version of memray.\");\n    }\n    header.command_line.reserve(4096);\n    if (!d_input->read(reinterpret_cast<char*>(&header.python_version), sizeof(header.python_version))\n        || !d_input->read(reinterpret_cast<char*>(&header.native_traces), sizeof(header.native_traces))\n        || !d_input->read(reinterpret_cast<char*>(&header.file_format), sizeof(header.file_format))\n        || !d_input->read(reinterpret_cast<char*>(&header.stats), sizeof(header.stats))\n        || !d_input->getline(header.command_line, '\\0')\n        || !d_input->read(reinterpret_cast<char*>(&header.pid), sizeof(header.pid))\n        || !d_input->read(reinterpret_cast<char*>(&header.main_tid), sizeof(header.main_tid))\n        || !d_input->read(\n                reinterpret_cast<char*>(&header.skipped_frames_on_main_tid),\n                sizeof(header.skipped_frames_on_main_tid))\n        || !d_input->read(\n                reinterpret_cast<char*>(&header.python_allocator),\n                sizeof(header.python_allocator))\n        || !d_input->read(\n                reinterpret_cast<char*>(&header.trace_python_allocators),\n                sizeof(header.trace_python_allocators))\n        || !d_input->read(\n                reinterpret_cast<char*>(&header.track_object_lifetimes),\n                sizeof(header.track_object_lifetimes)))\n    {\n        throw std::ios_base::failure(\"Failed to read input file header.\");\n    }\n}\n\nbool\nRecordReader::readVarint(uint64_t* val)\n{\n    *val = 0;\n    int shift = 0;\n\n    while (true) {\n        unsigned char next;\n        if (!d_input->read(reinterpret_cast<char*>(&next), sizeof(next))) {\n            return false;\n        }\n\n        *val |= (static_cast<uint64_t>(next & 0x7f) << shift);\n        if (0 == (next & 0x80)) {\n            return true;\n        }\n\n        shift += 7;\n        if (shift >= 64) {\n            return false;\n        }\n    }\n}\n\nbool\nRecordReader::readSignedVarint(int64_t* val)\n{\n    uint64_t zigzag_val;\n    if (!readVarint(&zigzag_val)) {\n        return false;\n    }\n\n    *val = static_cast<int64_t>((zigzag_val >> 1) ^ (~(zigzag_val & 1) + 1));\n    return true;\n}\n\nRecordReader::RecordReader(\n        std::unique_ptr<Source> source,\n        bool track_stacks,\n        bool track_object_lifetimes)\n: d_input(std::move(source))\n, d_track_stacks(track_stacks)\n, d_track_object_lifetimes(track_object_lifetimes)\n{\n    readHeader(d_header);\n\n    // Reserve some space for the different containers\n    d_thread_names.reserve(16);\n\n    if (d_track_stacks) {\n        d_native_frames.reserve(d_header.native_traces ? 2048 : 0);\n    }\n}\n\nvoid\nRecordReader::close() noexcept\n{\n    d_input->close();\n}\n\nbool\nRecordReader::isOpen() const noexcept\n{\n    return d_input->is_open();\n}\n\nbool\nRecordReader::parseFramePush(FramePush* record, unsigned int flags)\n{\n    record->frame.is_entry_frame = flags & 1;\n    return readVarint(&record->frame.code_object_id)\n           && readSignedVarint(&record->frame.instruction_offset);\n}\n\nbool\nRecordReader::processFramePush(const FramePush& record)\n{\n    if (!d_track_stacks) {\n        return true;\n    }\n    if (!d_curr_thread_stack) {\n        throw std::runtime_error(\"invalid capture file: FRAME_PUSH with no previous CONTEXT_SWITCH\");\n    }\n    auto& stack = *d_curr_thread_stack;\n    FrameTree::index_t current_stack_id = stack.empty() ? 0 : stack.back();\n    FrameTree::index_t new_stack_id;\n    {\n        std::unique_lock<std::mutex> lock(d_mutex);\n        auto frame_id = d_python_frame_registry.registerRecord(record.frame).first;\n        new_stack_id = d_tree.getTraceIndex(current_stack_id, frame_id);\n    }\n    stack.push_back(new_stack_id);\n    return true;\n}\n\nbool\nRecordReader::parseFramePop(FramePop* record, unsigned int flags)\n{\n    record->count = flags + 1;\n    return true;\n}\n\nbool\nRecordReader::processFramePop(const FramePop& record)\n{\n    if (!d_track_stacks) {\n        return true;\n    }\n    if (!d_curr_thread_stack) {\n        throw std::runtime_error(\"invalid capture file: FRAME_POP with no previous CONTEXT_SWITCH\");\n    }\n\n    auto& stack = *d_curr_thread_stack;\n    assert(!stack.empty());\n    auto count = record.count;\n    while (count) {\n        --count;\n        stack.pop_back();\n    }\n    return true;\n}\n\nbool\nRecordReader::parseCodeObjectRecord(tracking_api::pycode_map_val_t* pycode_val)\n{\n    size_t linetable_size = 0;\n    if (!readVarint(&pycode_val->first) || !d_input->getline(pycode_val->second.function_name, '\\0')\n        || !d_input->getline(pycode_val->second.filename, '\\0')\n        || !readIntegralDelta(&d_last.code_firstlineno, &pycode_val->second.firstlineno)\n        || !readVarint(&linetable_size))\n    {\n        return false;\n    }\n\n    pycode_val->second.linetable.resize(linetable_size);\n    return d_input->read(const_cast<char*>(pycode_val->second.linetable.data()), linetable_size);\n}\n\nbool\nRecordReader::processCodeObjectRecord(const tracking_api::pycode_map_val_t& pycode_val)\n{\n    if (!d_track_stacks) {\n        return true;\n    }\n    std::lock_guard<std::mutex> lock(d_mutex);\n    d_code_object_map[pycode_val.first] = pycode_val.second;\n    return true;\n}\n\nbool\nRecordReader::parseNativeFrameIndex(UnresolvedNativeFrame* frame)\n{\n    return readIntegralDelta(&d_last.instruction_pointer, &frame->ip)\n           && readIntegralDelta(&d_last.native_frame_id, &frame->index);\n}\n\nbool\nRecordReader::processNativeFrameIndex(const UnresolvedNativeFrame& frame)\n{\n    if (!d_track_stacks) {\n        return true;\n    }\n    std::lock_guard<std::mutex> lock(d_mutex);\n    d_native_frames.emplace_back(frame);\n    return true;\n}\n\nbool\nRecordReader::parseAllocationRecord(AllocationRecord* record, unsigned int flags)\n{\n    unsigned int pointer_cache_index = (flags >> 3) & 0x0f;\n    if (pointer_cache_index == 0x0f) {\n        // Cache miss, read the pointer, then update the cache\n        if (!readIntegralDelta(&d_last.data_pointer, &record->address)) {\n            return false;\n        }\n\n        record->address <<= 3;\n\n        std::move(\n                d_recent_addresses.begin(),\n                d_recent_addresses.end() - 1,\n                d_recent_addresses.begin() + 1);\n        d_recent_addresses[0] = record->address;\n    } else {\n        // Cache hit, reuse previous pointer\n        record->address = d_recent_addresses[pointer_cache_index];\n    }\n\n    auto allocator_id = flags & 7;\n    if (allocator_id) {\n        record->allocator = static_cast<hooks::Allocator>(allocator_id);\n    } else {\n        if (!d_input->read(reinterpret_cast<char*>(&record->allocator), sizeof(record->allocator))) {\n            return false;\n        }\n    }\n\n    if (d_header.native_traces\n        && hooks::allocatorKind(record->allocator) != hooks::AllocatorKind::SIMPLE_DEALLOCATOR)\n    {\n        if (!readIntegralDelta(&d_last.native_frame_id, &record->native_frame_id)) {\n            return false;\n        }\n    } else {\n        record->native_frame_id = 0;\n    }\n\n    if (hooks::allocatorKind(record->allocator) == hooks::AllocatorKind::SIMPLE_DEALLOCATOR) {\n        record->size = 0;\n    } else if (!readVarint(&record->size)) {\n        return false;\n    }\n\n    return true;\n}\n\nbool\nRecordReader::processAllocationRecord(const AllocationRecord& record)\n{\n    if (!d_curr_thread_stack) {\n        throw std::runtime_error(\"invalid capture file: ALLOCATION with no previous CONTEXT_SWITCH\");\n    }\n    d_latest_allocation.tid = d_last.thread_id;\n    d_latest_allocation.address = record.address;\n    d_latest_allocation.size = record.size;\n    d_latest_allocation.allocator = record.allocator;\n    if (d_track_stacks && !hooks::isDeallocator(record.allocator)) {\n        d_latest_allocation.native_frame_id = record.native_frame_id;\n        auto& stack = *d_curr_thread_stack;\n        d_latest_allocation.frame_index = stack.empty() ? 0 : stack.back();\n        d_latest_allocation.native_segment_generation = d_symbol_resolver.currentSegmentGeneration();\n    } else {\n        d_latest_allocation.native_frame_id = 0;\n        d_latest_allocation.frame_index = 0;\n        d_latest_allocation.native_segment_generation = 0;\n    }\n    d_latest_allocation.n_allocations = 1;\n    return true;\n}\n\nbool\nRecordReader::parseMemoryMapStart()\n{\n    // Currently nothing to do (this record type has no body)\n    return true;\n}\n\nbool\nRecordReader::processMemoryMapStart()\n{\n    std::lock_guard<std::mutex> lock(d_mutex);\n    d_symbol_resolver.clearSegments();\n    return true;\n}\n\nbool\nRecordReader::parseSegmentHeader(std::string* filename, size_t* num_segments, uintptr_t* addr)\n{\n    return d_input->getline(*filename, '\\0') && readVarint(num_segments)\n           && d_input->read(reinterpret_cast<char*>(addr), sizeof(*addr));\n}\n\nbool\nRecordReader::processSegmentHeader(const std::string& filename, size_t num_segments, uintptr_t addr)\n{\n    std::vector<Segment> segments;\n    segments.reserve(num_segments);\n    for (size_t i = 0; i < num_segments; i++) {\n        RecordType record_type;\n        if (!d_input->read(reinterpret_cast<char*>(&record_type), sizeof(record_type))\n            || (record_type != RecordType::SEGMENT))\n        {\n            return false;\n        }\n\n        Segment segment{};\n        if (!parseSegment(&segment)) {\n            return false;\n        }\n        if (d_track_stacks) {\n            segments.emplace_back(segment);\n        }\n    }\n\n    if (d_track_stacks) {\n        std::lock_guard<std::mutex> lock(d_mutex);\n        d_symbol_resolver.addSegments(filename, addr, segments);\n    }\n    return true;\n}\n\nbool\nRecordReader::parseSegment(Segment* segment)\n{\n    if (!d_input->read(reinterpret_cast<char*>(&segment->vaddr), sizeof(segment->vaddr))\n        || !readVarint(&segment->memsz))\n    {\n        return false;\n    }\n    return true;\n}\n\nbool\nRecordReader::parseThreadRecord(std::string* name)\n{\n    return d_input->getline(*name, '\\0');\n}\n\nbool\nRecordReader::processThreadRecord(const std::string& name)\n{\n    d_thread_names[d_last.thread_id] = name;\n    return true;\n}\n\nbool\nRecordReader::parseMemoryRecord(MemoryRecord* record)\n{\n    if (!readVarint(&record->rss) || !readVarint(&record->ms_since_epoch)) {\n        return false;\n    }\n    record->ms_since_epoch += d_header.stats.start_time;\n    return true;\n}\n\nbool\nRecordReader::processMemoryRecord(const MemoryRecord& record)\n{\n    d_latest_memory_record = record;\n    return true;\n}\n\nbool\nRecordReader::parseContextSwitch(thread_id_t* tid)\n{\n    return d_input->read(reinterpret_cast<char*>(tid), sizeof(*tid));\n}\n\nbool\nRecordReader::processContextSwitch(thread_id_t tid)\n{\n    d_last.thread_id = tid;\n    auto [it, inserted] = d_stack_traces.emplace(tid, stack_t{});\n    auto& stack = it->second;\n    d_curr_thread_stack = &stack;\n    if (inserted) {\n        stack.reserve(1024);\n    }\n    return true;\n}\n\nbool\nRecordReader::parseMemorySnapshotRecord(MemorySnapshot* record)\n{\n    return d_input->read(reinterpret_cast<char*>(record), sizeof(*record));\n}\n\nbool\nRecordReader::processMemorySnapshotRecord(const MemorySnapshot& record)\n{\n    d_latest_memory_snapshot = record;\n    return true;\n}\n\nbool\nRecordReader::parseAggregatedAllocationRecord(AggregatedAllocation* record)\n{\n    return d_input->read(reinterpret_cast<char*>(record), sizeof(*record));\n}\n\nbool\nRecordReader::processAggregatedAllocationRecord(const AggregatedAllocation& record)\n{\n    d_latest_aggregated_allocation = record;\n    return true;\n}\n\nbool\nRecordReader::parsePythonTraceIndexRecord(std::pair<frame_id_t, FrameTree::index_t>* record)\n{\n    return readVarint(&record->first) && readVarint(&record->second);\n}\n\nbool\nRecordReader::processPythonTraceIndexRecord(const std::pair<frame_id_t, FrameTree::index_t>& record)\n{\n    if (!d_track_stacks) {\n        return true;\n    }\n    std::lock_guard<std::mutex> lock(d_mutex);\n    d_tree.getTraceIndex(record.second, record.first);  // Called for its side effect.\n    return true;\n}\n\nbool\nRecordReader::parsePythonFrameIndexRecord(std::pair<frame_id_t, Frame>* pyframe_val)\n{\n    auto& [frame_id, frame] = *pyframe_val;\n    if (!readVarint(&frame_id) || !readVarint(&frame.code_object_id)\n        || !readSignedVarint(&frame.instruction_offset)\n        || !d_input->read(reinterpret_cast<char*>(&frame.is_entry_frame), sizeof(frame.is_entry_frame)))\n    {\n        return false;\n    }\n\n    return true;\n}\n\nbool\nRecordReader::processPythonFrameIndexRecord(const std::pair<frame_id_t, Frame>& record)\n{\n    if (!d_track_stacks) {\n        return true;\n    }\n    std::lock_guard<std::mutex> lock(d_mutex);\n    frame_id_t frame_id = d_python_frame_registry.registerRecord(record.second).first;\n    if (frame_id != record.first) {\n        throw std::runtime_error(\"Frame ID mismatch\");\n    }\n    return true;\n}\n\nbool\nRecordReader::parseObjectRecord(ObjectRecord* record, unsigned int flags)\n{\n    record->is_created = (flags & 0x01) > 0;\n\n    unsigned int pointer_cache_index = (flags >> 1) & 0x0f;\n    if (pointer_cache_index == 0x0f) {\n        // Cache miss, read the pointer, then update the cache\n        if (!readIntegralDelta(&d_last.data_pointer, &record->address)) {\n            return false;\n        }\n\n        record->address <<= 3;\n\n        std::move(\n                d_recent_addresses.begin(),\n                d_recent_addresses.end() - 1,\n                d_recent_addresses.begin() + 1);\n        d_recent_addresses[0] = record->address;\n    } else {\n        // Cache hit, reuse previous pointer\n        record->address = d_recent_addresses[pointer_cache_index];\n    }\n\n    if (d_header.native_traces && record->is_created) {\n        if (!readIntegralDelta(&d_last.native_frame_id, &record->native_frame_id)) {\n            return false;\n        }\n    } else {\n        record->native_frame_id = 0;\n    }\n    return true;\n}\n\nbool\nRecordReader::processObjectRecord(const ObjectRecord& record)\n{\n    d_latest_object.tid = d_last.thread_id;\n    d_latest_object.address = record.address;\n    d_latest_object.native_frame_id = record.native_frame_id;\n\n    if (d_track_stacks && record.is_created) {\n        d_latest_object.native_frame_id = record.native_frame_id;\n        auto& stack = d_stack_traces[d_latest_object.tid];\n        d_latest_object.frame_index = stack.empty() ? 0 : stack.back();\n        d_latest_object.native_segment_generation = d_symbol_resolver.currentSegmentGeneration();\n    } else {\n        d_latest_object.native_frame_id = 0;\n        d_latest_object.frame_index = 0;\n        d_latest_object.native_segment_generation = 0;\n    }\n\n    d_latest_object.is_created = record.is_created;\n    return true;\n}\n\nbool\nRecordReader::parseSurvivingObjectRecord(ObjectRecord* record)\n{\n    record->is_created = true;  // Surviving objects are always created\n    if (!readVarint(reinterpret_cast<uintptr_t*>(&record->address))) {\n        return false;\n    }\n    record->address <<= 3;\n\n    if (d_header.native_traces) {\n        if (!readVarint(&record->native_frame_id)) {\n            return false;\n        }\n    } else {\n        record->native_frame_id = 0;\n    }\n    return true;\n}\n\nbool\nRecordReader::processSurvivingObjectRecord(const ObjectRecord& record)\n{\n    return processObjectRecord(record);\n}\n\nRecordReader::RecordResult\nRecordReader::nextRecord()\n{\n    RecordReader::RecordResult ret;\n\n    if (d_header.file_format == FileFormat::ALL_ALLOCATIONS) {\n        ret = nextRecordFromAllAllocationsFile();\n        assert(ret != RecordResult::MEMORY_SNAPSHOT);\n        assert(ret != RecordResult::AGGREGATED_ALLOCATION_RECORD);\n    } else if (d_header.file_format == FileFormat::AGGREGATED_ALLOCATIONS) {\n        ret = nextRecordFromAggregatedAllocationsFile();\n        assert(ret != RecordResult::MEMORY_RECORD);\n        assert(ret != RecordResult::ALLOCATION_RECORD);\n    } else {\n        LOG(ERROR) << \"Invalid file format enumerator\";\n        return RecordResult::ERROR;\n    }\n    return ret;\n}\n\nLocation\nRecordReader::frameToLocation(frame_id_t frame_id)\n{\n    auto it = d_python_location_by_frame_id.find(frame_id);\n    if (it == d_python_location_by_frame_id.end()) {\n        auto& frame = d_python_frame_registry.getRecord(frame_id);\n        auto& code = d_code_object_map[frame.code_object_id];\n\n        int lineno = 0;\n\n        if (!code.linetable.empty() && frame.instruction_offset >= 0) {\n            compat::LocationInfo info;\n            if (compat::parseLinetable(\n                        d_header.python_version,\n                        code.linetable,\n                        frame.instruction_offset,\n                        code.firstlineno,\n                        &info))\n            {\n                lineno = info.lineno;\n            }\n        }\n\n        it = d_python_location_by_frame_id\n                     .emplace(frame_id, Location{code.function_name, code.filename, lineno})\n                     .first;\n    }\n    return it->second;\n}\n\nvoid\nRecordReader::extractRecordTypeAndFlags(\n        unsigned char record_type_and_flags,\n        RecordType* record_type,\n        unsigned char* flags) const\n{\n    unsigned char flags_mask;\n    if (record_type_and_flags & static_cast<unsigned char>(RecordType::ALLOCATION)) {\n        *record_type = RecordType::ALLOCATION;\n        flags_mask = static_cast<unsigned char>(RecordType::ALLOCATION) - 1;\n    } else if (record_type_and_flags & static_cast<unsigned char>(RecordType::FRAME_PUSH)) {\n        *record_type = RecordType::FRAME_PUSH;\n        flags_mask = static_cast<unsigned char>(RecordType::FRAME_PUSH) - 1;\n    } else if (record_type_and_flags & static_cast<unsigned char>(RecordType::OBJECT_RECORD)) {\n        *record_type = RecordType::OBJECT_RECORD;\n        flags_mask = static_cast<unsigned char>(RecordType::OBJECT_RECORD) - 1;\n    } else if (record_type_and_flags & static_cast<unsigned char>(RecordType::FRAME_POP)) {\n        *record_type = RecordType::FRAME_POP;\n        flags_mask = static_cast<unsigned char>(RecordType::FRAME_POP) - 1;\n    } else {\n        *record_type = static_cast<RecordType>(record_type_and_flags);\n        flags_mask = 0;\n    }\n    *flags = record_type_and_flags & flags_mask;\n}\n\nRecordReader::RecordResult\nRecordReader::nextRecordFromAllAllocationsFile()\n{\n    while (true) {\n        unsigned char record_type_and_flags;\n        if (!d_input->read(\n                    reinterpret_cast<char*>(&record_type_and_flags),\n                    sizeof(record_type_and_flags)))\n        {\n            return RecordResult::END_OF_FILE;\n        }\n\n        RecordType record_type;\n        unsigned char flags;\n        extractRecordTypeAndFlags(record_type_and_flags, &record_type, &flags);\n\n        switch (record_type) {\n            case RecordType::TRAILER: {\n                return RecordResult::END_OF_FILE;\n            } break;\n            case RecordType::ALLOCATION: {\n                AllocationRecord record;\n                if (!parseAllocationRecord(&record, flags) || !processAllocationRecord(record)) {\n                    if (d_input->is_open()) LOG(ERROR) << \"Failed to process allocation record\";\n                    return RecordResult::ERROR;\n                }\n                return RecordResult::ALLOCATION_RECORD;\n            } break;\n            case RecordType::MEMORY_RECORD: {\n                MemoryRecord record;\n                if (!parseMemoryRecord(&record) || !processMemoryRecord(record)) {\n                    if (d_input->is_open()) LOG(ERROR) << \"Failed to process memory record\";\n                    return RecordResult::ERROR;\n                }\n                return RecordResult::MEMORY_RECORD;\n            } break;\n            case RecordType::CONTEXT_SWITCH: {\n                thread_id_t tid;\n                if (!parseContextSwitch(&tid) || !processContextSwitch(tid)) {\n                    if (d_input->is_open()) LOG(ERROR) << \"Failed to process context switch record\";\n                    return RecordResult::ERROR;\n                }\n            } break;\n            case RecordType::FRAME_PUSH: {\n                FramePush record;\n                if (!parseFramePush(&record, flags) || !processFramePush(record)) {\n                    if (d_input->is_open()) LOG(ERROR) << \"Failed to process frame push\";\n                    return RecordResult::ERROR;\n                }\n            } break;\n            case RecordType::FRAME_POP: {\n                FramePop record;\n                if (!parseFramePop(&record, flags) || !processFramePop(record)) {\n                    if (d_input->is_open()) LOG(ERROR) << \"Failed to process frame pop\";\n                    return RecordResult::ERROR;\n                }\n            } break;\n            case RecordType::CODE_OBJECT: {\n                tracking_api::pycode_map_val_t record;\n                if (!parseCodeObjectRecord(&record) || !processCodeObjectRecord(record)) {\n                    if (d_input->is_open()) LOG(ERROR) << \"Failed to process code object\";\n                    return RecordResult::ERROR;\n                }\n            } break;\n            case RecordType::NATIVE_TRACE_INDEX: {\n                UnresolvedNativeFrame record;\n                if (!parseNativeFrameIndex(&record) || !processNativeFrameIndex(record)) {\n                    if (d_input->is_open()) LOG(ERROR) << \"Failed to process native frame index\";\n                    return RecordResult::ERROR;\n                }\n            } break;\n            case RecordType::MEMORY_MAP_START: {\n                if (!parseMemoryMapStart() || !processMemoryMapStart()) {\n                    if (d_input->is_open()) LOG(ERROR) << \"Failed to process memory map start\";\n                    return RecordResult::ERROR;\n                }\n            } break;\n            case RecordType::SEGMENT_HEADER: {\n                std::string filename;\n                size_t num_segments;\n                uintptr_t addr;\n                if (!parseSegmentHeader(&filename, &num_segments, &addr)\n                    || !processSegmentHeader(filename, num_segments, addr))\n                {\n                    if (d_input->is_open()) LOG(ERROR) << \"Failed to process segment header\";\n                    return RecordResult::ERROR;\n                }\n            } break;\n            case RecordType::THREAD_RECORD: {\n                std::string name;\n                if (!parseThreadRecord(&name) || !processThreadRecord(name)) {\n                    if (d_input->is_open()) LOG(ERROR) << \"Failed to process thread record\";\n                    return RecordResult::ERROR;\n                }\n            } break;\n            case RecordType::OBJECT_RECORD: {\n                ObjectRecord record;\n                if (!parseObjectRecord(&record, flags) || !processObjectRecord(record)) {\n                    if (d_input->is_open()) LOG(ERROR) << \"Failed to process native object record\";\n                    return RecordResult::ERROR;\n                }\n                if (!d_track_object_lifetimes) {\n                    break;\n                }\n                return RecordResult::OBJECT_RECORD;\n            } break;\n            default:\n                if (d_input->is_open()) LOG(ERROR) << \"Invalid record type\";\n                return RecordResult::ERROR;\n        }\n    }\n}\n\nRecordReader::RecordResult\nRecordReader::nextRecordFromAggregatedAllocationsFile()\n{\n    while (true) {\n        AggregatedRecordType record_type;\n        if (!d_input->read(reinterpret_cast<char*>(&record_type), sizeof(record_type))) {\n            return RecordResult::END_OF_FILE;\n        }\n\n        switch (record_type) {\n            case AggregatedRecordType::MEMORY_SNAPSHOT: {\n                MemorySnapshot record;\n                if (!parseMemorySnapshotRecord(&record) || !processMemorySnapshotRecord(record)) {\n                    if (d_input->is_open()) LOG(ERROR) << \"Failed to process memory record\";\n                    return RecordResult::ERROR;\n                }\n\n                return RecordResult::MEMORY_SNAPSHOT;\n            } break;\n\n            case AggregatedRecordType::AGGREGATED_ALLOCATION: {\n                AggregatedAllocation record;\n                if (!parseAggregatedAllocationRecord(&record)\n                    || !processAggregatedAllocationRecord(record))\n                {\n                    if (d_input->is_open()) {\n                        LOG(ERROR) << \"Failed to process aggregated allocation record\";\n                    }\n                    return RecordResult::ERROR;\n                }\n\n                return RecordResult::AGGREGATED_ALLOCATION_RECORD;\n            } break;\n\n            case AggregatedRecordType::PYTHON_TRACE_INDEX: {\n                std::pair<frame_id_t, FrameTree::index_t> record;\n                if (!parsePythonTraceIndexRecord(&record) || !processPythonTraceIndexRecord(record)) {\n                    return RecordResult::ERROR;\n                }\n            } break;\n\n            case AggregatedRecordType::PYTHON_FRAME_INDEX: {\n                std::pair<frame_id_t, Frame> record;\n                if (!parsePythonFrameIndexRecord(&record) || !processPythonFrameIndexRecord(record)) {\n                    return RecordResult::ERROR;\n                }\n            } break;\n\n            case AggregatedRecordType::NATIVE_TRACE_INDEX: {\n                UnresolvedNativeFrame record;\n                if (!parseNativeFrameIndex(&record) || !processNativeFrameIndex(record)) {\n                    if (d_input->is_open()) LOG(ERROR) << \"Failed to process native frame index\";\n                    return RecordResult::ERROR;\n                }\n            } break;\n\n            case AggregatedRecordType::MEMORY_MAP_START: {\n                if (!parseMemoryMapStart() || !processMemoryMapStart()) {\n                    if (d_input->is_open()) LOG(ERROR) << \"Failed to process memory map start\";\n                    return RecordResult::ERROR;\n                }\n            } break;\n\n            case AggregatedRecordType::SEGMENT_HEADER: {\n                std::string filename;\n                size_t num_segments;\n                uintptr_t addr;\n                if (!parseSegmentHeader(&filename, &num_segments, &addr)\n                    || !processSegmentHeader(filename, num_segments, addr))\n                {\n                    if (d_input->is_open()) LOG(ERROR) << \"Failed to process segment header\";\n                    return RecordResult::ERROR;\n                }\n            } break;\n\n            case AggregatedRecordType::SEGMENT: {\n                // These should always be consumed by processSegmentHeader\n                if (d_input->is_open()) LOG(ERROR) << \"Unexpected SEGMENT record\";\n                return RecordResult::ERROR;\n            } break;\n\n            case AggregatedRecordType::THREAD_RECORD: {\n                std::string name;\n                if (!parseThreadRecord(&name) || !processThreadRecord(name)) {\n                    if (d_input->is_open()) LOG(ERROR) << \"Failed to process thread record\";\n                    return RecordResult::ERROR;\n                }\n            } break;\n\n            case AggregatedRecordType::CONTEXT_SWITCH: {\n                thread_id_t tid;\n                if (!parseContextSwitch(&tid) || !processContextSwitch(tid)) {\n                    if (d_input->is_open()) LOG(ERROR) << \"Failed to process context switch record\";\n                    return RecordResult::ERROR;\n                }\n            } break;\n\n            case AggregatedRecordType::SURVIVING_OBJECT: {\n                ObjectRecord record;\n                if (!parseSurvivingObjectRecord(&record) || !processSurvivingObjectRecord(record)) {\n                    if (d_input->is_open()) LOG(ERROR) << \"Failed to process surviving object record\";\n                    return RecordResult::ERROR;\n                }\n                if (!d_track_object_lifetimes) {\n                    break;\n                }\n                return RecordResult::OBJECT_RECORD;\n            } break;\n\n            case AggregatedRecordType::CODE_OBJECT: {\n                tracking_api::pycode_map_val_t record;\n                if (!parseCodeObjectRecord(&record) || !processCodeObjectRecord(record)) {\n                    if (d_input->is_open()) LOG(ERROR) << \"Failed to process code object\";\n                    return RecordResult::ERROR;\n                }\n            } break;\n\n            case AggregatedRecordType::AGGREGATED_TRAILER: {\n                return RecordResult::END_OF_FILE;\n            } break;\n\n            default: {\n                if (d_input->is_open()) LOG(ERROR) << \"Invalid record type\";\n                return RecordResult::ERROR;\n            } break;\n        }\n    }\n}\n\n// Python public APIs\n\nPyObject*\nRecordReader::Py_GetStackFrame(FrameTree::index_t index, size_t max_stacks)\n{\n    return Py_GetStackFrameAndEntryInfo(index, nullptr, max_stacks);\n}\n\nPyObject*\nRecordReader::Py_GetStackFrameAndEntryInfo(\n        FrameTree::index_t index,\n        std::vector<unsigned char>* is_entry_frame,\n        size_t max_stacks)\n{\n    if (!d_track_stacks) {\n        PyErr_SetString(PyExc_RuntimeError, \"Stack tracking is disabled\");\n        return NULL;\n    }\n    if (is_entry_frame) {\n        is_entry_frame->clear();\n        is_entry_frame->reserve(64);\n    }\n    std::lock_guard<std::mutex> lock(d_mutex);\n\n    size_t stacks_obtained = 0;\n    FrameTree::index_t current_index = index;\n    PyObject* list = PyList_New(0);\n    if (list == nullptr) {\n        return nullptr;\n    }\n\n    while (current_index != 0 && stacks_obtained++ != max_stacks) {\n        auto [frame_id, next_index] = d_tree.nextNode(current_index);\n        const auto& frame = d_python_frame_registry.getRecord(frame_id);\n        Location location = frameToLocation(frame_id);\n        PyObject* pyframe = location.toPythonObject(d_pystring_cache);\n        if (pyframe == nullptr) {\n            goto error;\n        }\n        int ret = PyList_Append(list, pyframe);\n        Py_DECREF(pyframe);\n        if (ret != 0) {\n            goto error;\n        }\n        if (is_entry_frame) {\n            is_entry_frame->push_back(frame.is_entry_frame);\n        }\n        current_index = next_index;\n    }\n    return list;\nerror:\n    Py_XDECREF(list);\n    return nullptr;\n}\n\nPyObject*\nRecordReader::Py_GetNativeStackFrame(FrameTree::index_t index, size_t generation, size_t max_stacks)\n{\n    if (!d_track_stacks) {\n        PyErr_SetString(PyExc_RuntimeError, \"Stack tracking is disabled\");\n        return NULL;\n    }\n    std::lock_guard<std::mutex> lock(d_mutex);\n\n    size_t stacks_obtained = 0;\n    FrameTree::index_t current_index = index;\n    PyObject* list = PyList_New(0);\n    if (list == nullptr) {\n        return nullptr;\n    }\n\n    while (current_index != 0 && stacks_obtained++ != max_stacks) {\n        auto frame = d_native_frames[current_index - 1];\n        current_index = frame.index;\n        auto resolved_frames = d_symbol_resolver.resolve(frame.ip, generation);\n        if (!resolved_frames) {\n            continue;\n        }\n        for (auto& native_frame : resolved_frames->frames()) {\n            PyObject* pyframe = native_frame.toPythonObject(d_pystring_cache);\n            if (pyframe == nullptr) {\n                return nullptr;\n            }\n            int ret = PyList_Append(list, pyframe);\n            Py_DECREF(pyframe);\n            if (ret != 0) {\n                goto error;\n            }\n        }\n    }\n    return list;\nerror:\n    Py_XDECREF(list);\n    return nullptr;\n}\n\nstd::optional<location_id_t>\nRecordReader::getLatestPythonLocationId(const Allocation& allocation)\n{\n    if (!d_track_stacks) {\n        throw std::runtime_error(\"Stack tracking is disabled\");\n    }\n\n    if (0 == allocation.frame_index) {\n        return {};\n    }\n    std::unique_lock<std::mutex> lock(d_mutex);\n    auto frame_id = d_tree.nextNode(allocation.frame_index).first;\n    Location location = frameToLocation(frame_id);\n    return d_location_registry.registerRecord(location).first;\n}\n\nPyObject*\nRecordReader::Py_GetLocation(std::optional<location_id_t> location_id)\n{\n    if (!d_track_stacks) {\n        PyErr_SetString(PyExc_RuntimeError, \"Stack tracking is disabled\");\n        return NULL;\n    }\n\n    if (!location_id) {\n        Py_RETURN_NONE;\n    }\n    std::unique_lock<std::mutex> lock(d_mutex);\n    return d_location_registry.getRecord(location_id.value()).toPythonObject(d_pystring_cache);\n}\n\nHeaderRecord\nRecordReader::getHeader() const noexcept\n{\n    return d_header;\n}\n\nthread_id_t\nRecordReader::getMainThreadTid() const noexcept\n{\n    return d_header.main_tid;\n}\n\nsize_t\nRecordReader::getSkippedFramesOnMainThread() const noexcept\n{\n    return d_header.skipped_frames_on_main_tid;\n}\n\nstd::string\nRecordReader::getThreadName(thread_id_t tid)\n{\n    auto it = d_thread_names.find(tid);\n    if (it != d_thread_names.end()) {\n        return it->second;\n    }\n    return \"\";\n}\n\nAllocation\nRecordReader::getLatestAllocation() const noexcept\n{\n    return d_latest_allocation;\n}\n\nMemoryRecord\nRecordReader::getLatestMemoryRecord() const noexcept\n{\n    return d_latest_memory_record;\n}\n\nAggregatedAllocation\nRecordReader::getLatestAggregatedAllocation() const noexcept\n{\n    return d_latest_aggregated_allocation;\n}\n\nMemorySnapshot\nRecordReader::getLatestMemorySnapshot() const noexcept\n{\n    return d_latest_memory_snapshot;\n}\n\nTrackedObject\nRecordReader::getLatestObject() const noexcept\n{\n    return d_latest_object;\n}\n\nPyObject*\nRecordReader::dumpAllRecords()\n{\n    std::string python_allocator;\n    switch (d_header.python_allocator) {\n        case PythonAllocatorType::PYTHONALLOCATOR_PYMALLOC:\n            python_allocator = \"pymalloc\";\n            break;\n        case PythonAllocatorType::PYTHONALLOCATOR_PYMALLOC_DEBUG:\n            python_allocator = \"pymalloc debug\";\n            break;\n        case PythonAllocatorType::PYTHONALLOCATOR_MIMALLOC:\n            python_allocator = \"mimalloc\";\n            break;\n        case PythonAllocatorType::PYTHONALLOCATOR_MIMALLOC_DEBUG:\n            python_allocator = \"mimalloc debug\";\n            break;\n        case PythonAllocatorType::PYTHONALLOCATOR_MALLOC:\n            python_allocator = \"pymalloc\";\n            break;\n        case PythonAllocatorType::PYTHONALLOCATOR_OTHER:\n            python_allocator = \"other\";\n            break;\n    }\n    std::string file_format;\n    switch (d_header.file_format) {\n        case FileFormat::ALL_ALLOCATIONS: {\n            file_format = \"ALL_ALLOCATIONS\";\n        } break;\n        case FileFormat::AGGREGATED_ALLOCATIONS: {\n            file_format = \"AGGREGATED_ALLOCATIONS\";\n        } break;\n        default: {\n            file_format = \"<unknown enum value \" + std::to_string((int)d_header.file_format) + \">\";\n        } break;\n    }\n    printf(\"HEADER magic=%.*s version=%d python_version=%08x native_traces=%s file_format=%s\"\n           \" n_allocations=%zd n_frames=%zd start_time=%lld end_time=%lld\"\n           \" pid=%d main_tid=%lu skipped_frames_on_main_tid=%zd\"\n           \" command_line=%s python_allocator=%s trace_python_allocators=%s\"\n           \" track_object_lifetimes=%s\\n\",\n           (int)sizeof(d_header.magic),\n           d_header.magic,\n           d_header.version,\n           d_header.python_version,\n           d_header.native_traces ? \"true\" : \"false\",\n           file_format.c_str(),\n           d_header.stats.n_allocations,\n           d_header.stats.n_frames,\n           d_header.stats.start_time,\n           d_header.stats.end_time,\n           d_header.pid,\n           d_header.main_tid,\n           d_header.skipped_frames_on_main_tid,\n           d_header.command_line.c_str(),\n           python_allocator.c_str(),\n           d_header.trace_python_allocators ? \"true\" : \"false\",\n           d_header.track_object_lifetimes ? \"true\" : \"false\");\n\n    switch (d_header.file_format) {\n        case FileFormat::ALL_ALLOCATIONS:\n            return dumpAllRecordsFromAllAllocationsFile();\n        case FileFormat::AGGREGATED_ALLOCATIONS:\n            return dumpAllRecordsFromAggregatedAllocationsFile();\n        default:\n            printf(\"UNRECOGNIZED FILE CONTENTS\\n\");\n            Py_RETURN_NONE;\n    }\n}\n\nPyObject*\nRecordReader::dumpAllRecordsFromAllAllocationsFile()\n{\n    while (true) {\n        if (0 != PyErr_CheckSignals()) {\n            return nullptr;\n        }\n\n        unsigned char record_type_and_flags;\n        if (!d_input->read(\n                    reinterpret_cast<char*>(&record_type_and_flags),\n                    sizeof(record_type_and_flags)))\n        {\n            Py_RETURN_NONE;\n        }\n\n        RecordType record_type;\n        unsigned char flags;\n        extractRecordTypeAndFlags(record_type_and_flags, &record_type, &flags);\n\n        switch (record_type) {\n            case RecordType::TRAILER: {\n                printf(\"TRAILER\\n\");\n                Py_RETURN_NONE;  // Treat as EOF\n            } break;\n            case RecordType::ALLOCATION: {\n                printf(\"ALLOCATION \");\n\n                AllocationRecord record;\n                if (!parseAllocationRecord(&record, flags)) {\n                    Py_RETURN_NONE;\n                }\n\n                const char* allocator = allocatorName(record.allocator);\n\n                std::string unknownAllocator;\n                if (!allocator) {\n                    unknownAllocator =\n                            \"<unknown allocator \" + std::to_string((int)record.allocator) + \">\";\n                    allocator = unknownAllocator.c_str();\n                }\n                printf(\"address=%p size=%zd allocator=%s native_frame_id=%zd\\n\",\n                       (void*)record.address,\n                       record.size,\n                       allocator,\n                       record.native_frame_id);\n            } break;\n            case RecordType::FRAME_PUSH: {\n                printf(\"FRAME_PUSH \");\n\n                FramePush record;\n                if (!parseFramePush(&record, flags)) {\n                    Py_RETURN_NONE;\n                }\n\n                printf(\"code_object_id=%zd instruction_offset=%d is_entry_frame=%d\\n\",\n                       record.frame.code_object_id,\n                       record.frame.instruction_offset,\n                       record.frame.is_entry_frame);\n            } break;\n            case RecordType::FRAME_POP: {\n                printf(\"FRAME_POP \");\n\n                FramePop record;\n                if (!parseFramePop(&record, flags)) {\n                    Py_RETURN_NONE;\n                }\n\n                printf(\"count=%zd\\n\", record.count);\n            } break;\n            case RecordType::CODE_OBJECT: {\n                printf(\"CODE_OBJECT \");\n                tracking_api::pycode_map_val_t record;\n                if (!parseCodeObjectRecord(&record)) {\n                    Py_RETURN_NONE;\n                }\n                printf(\"code_id=%zd function_name=%s filename=%s firstlineno=%d linetable_size=%zd\\n\",\n                       record.first,\n                       record.second.function_name.c_str(),\n                       record.second.filename.c_str(),\n                       record.second.firstlineno,\n                       record.second.linetable.size());\n            } break;\n            case RecordType::NATIVE_TRACE_INDEX: {\n                printf(\"NATIVE_FRAME_ID \");\n\n                UnresolvedNativeFrame record;\n                if (!parseNativeFrameIndex(&record)) {\n                    Py_RETURN_NONE;\n                }\n\n                printf(\"ip=%p index=%zu\\n\", (void*)record.ip, record.index);\n            } break;\n            case RecordType::MEMORY_MAP_START: {\n                printf(\"MEMORY_MAP_START\\n\");\n                if (!parseMemoryMapStart()) {\n                    Py_RETURN_NONE;\n                }\n            } break;\n            case RecordType::SEGMENT_HEADER: {\n                printf(\"SEGMENT_HEADER \");\n\n                std::string filename;\n                size_t num_segments;\n                uintptr_t addr;\n                if (!parseSegmentHeader(&filename, &num_segments, &addr)) {\n                    Py_RETURN_NONE;\n                }\n\n                printf(\"filename=%s num_segments=%zd addr=%p\\n\",\n                       filename.c_str(),\n                       num_segments,\n                       (void*)addr);\n            } break;\n            case RecordType::SEGMENT: {\n                printf(\"SEGMENT \");\n\n                Segment record;\n                if (!parseSegment(&record)) {\n                    Py_RETURN_NONE;\n                }\n\n                printf(\"%p %\" PRIxPTR \"\\n\", (void*)record.vaddr, record.memsz);\n            } break;\n            case RecordType::THREAD_RECORD: {\n                printf(\"THREAD \");\n\n                std::string name;\n                if (!parseThreadRecord(&name)) {\n                    Py_RETURN_NONE;\n                }\n\n                printf(\"%s\\n\", name.c_str());\n            } break;\n            case RecordType::MEMORY_RECORD: {\n                printf(\"MEMORY_RECORD \");\n\n                MemoryRecord record;\n                if (!parseMemoryRecord(&record)) {\n                    Py_RETURN_NONE;\n                }\n\n                printf(\"time=%\" PRIu64 \" memory=%zd\\n\", record.ms_since_epoch, record.rss);\n            } break;\n            case RecordType::CONTEXT_SWITCH: {\n                printf(\"CONTEXT_SWITCH \");\n\n                thread_id_t tid;\n                if (!parseContextSwitch(&tid)) {\n                    Py_RETURN_NONE;\n                }\n\n                printf(\"tid=%lu\\n\", tid);\n            } break;\n            case RecordType::OBJECT_RECORD: {\n                printf(\"OBJECT_RECORD \");\n\n                ObjectRecord record;\n                if (!parseObjectRecord(&record, flags)) {\n                    Py_RETURN_NONE;\n                }\n\n                printf(\"address=%p native_frame_id=%zd\\n\",\n                       (void*)record.address,\n                       record.native_frame_id);\n            } break;\n            default: {\n                printf(\"UNKNOWN RECORD TYPE %d\\n\", (int)record_type);\n                Py_RETURN_NONE;\n            } break;\n        }\n    }\n}\n\nPyObject*\nRecordReader::dumpAllRecordsFromAggregatedAllocationsFile()\n{\n    while (true) {\n        if (0 != PyErr_CheckSignals()) {\n            return nullptr;\n        }\n\n        AggregatedRecordType record_type;\n        if (!d_input->read(reinterpret_cast<char*>(&record_type), sizeof(record_type))) {\n            Py_RETURN_NONE;\n        }\n\n        switch (record_type) {\n            case AggregatedRecordType::MEMORY_SNAPSHOT: {\n                printf(\"MEMORY_SNAPSHOT \");\n\n                MemorySnapshot record;\n                if (!parseMemorySnapshotRecord(&record)) {\n                    Py_RETURN_NONE;\n                }\n\n                printf(\"time=%\" PRIu64 \" rss=%zd heap=%zd\\n\",\n                       record.ms_since_epoch,\n                       record.rss,\n                       record.heap);\n            } break;\n\n            case AggregatedRecordType::AGGREGATED_ALLOCATION: {\n                printf(\"AGGREGATED_ALLOCATION \");\n\n                AggregatedAllocation record;\n                if (!parseAggregatedAllocationRecord(&record)) {\n                    Py_RETURN_NONE;\n                }\n\n                const char* allocator = allocatorName(record.allocator);\n\n                std::string unknownAllocator;\n                if (!allocator) {\n                    unknownAllocator =\n                            \"<unknown allocator \" + std::to_string((int)record.allocator) + \">\";\n                    allocator = unknownAllocator.c_str();\n                }\n\n                printf(\"tid=%lu allocator=%s native_frame_id=%zd python_frame_id=%zd\"\n                       \" native_segment_generation=%zd n_allocations_in_high_water_mark=%zd\"\n                       \" n_allocations_leaked=%zd bytes_in_high_water_mark=%zd bytes_leaked=%zd\\n\",\n                       record.tid,\n                       allocator,\n                       record.native_frame_id,\n                       record.frame_index,\n                       record.native_segment_generation,\n                       record.n_allocations_in_high_water_mark,\n                       record.n_allocations_leaked,\n                       record.bytes_in_high_water_mark,\n                       record.bytes_leaked);\n            } break;\n\n            case AggregatedRecordType::PYTHON_TRACE_INDEX: {\n                printf(\"PYTHON_TRACE_INDEX \");\n\n                std::pair<frame_id_t, FrameTree::index_t> record;\n                if (!parsePythonTraceIndexRecord(&record)) {\n                    Py_RETURN_NONE;\n                }\n\n                printf(\"frame_id=%zd parent_index=%zd\\n\", record.first, record.second);\n            } break;\n\n            case AggregatedRecordType::PYTHON_FRAME_INDEX: {\n                printf(\"PYTHON_FRAME_INDEX \");\n\n                std::pair<frame_id_t, Frame> record;\n                if (!parsePythonFrameIndexRecord(&record)) {\n                    Py_RETURN_NONE;\n                }\n\n                printf(\"frame_id=%zd code_object_id=%zd instruction_offset=%d is_entry_frame=%d\\n\",\n                       record.first,\n                       record.second.code_object_id,\n                       record.second.instruction_offset,\n                       record.second.is_entry_frame);\n            } break;\n\n            case AggregatedRecordType::NATIVE_TRACE_INDEX: {\n                printf(\"NATIVE_TRACE_INDEX \");\n\n                UnresolvedNativeFrame record;\n                if (!parseNativeFrameIndex(&record)) {\n                    Py_RETURN_NONE;\n                }\n\n                printf(\"ip=%p index=%zu\\n\", (void*)record.ip, record.index);\n            } break;\n\n            case AggregatedRecordType::MEMORY_MAP_START: {\n                printf(\"MEMORY_MAP_START\\n\");\n                if (!parseMemoryMapStart()) {\n                    Py_RETURN_NONE;\n                }\n            } break;\n\n            case AggregatedRecordType::SEGMENT_HEADER: {\n                printf(\"SEGMENT_HEADER \");\n\n                std::string filename;\n                size_t num_segments;\n                uintptr_t addr;\n                if (!parseSegmentHeader(&filename, &num_segments, &addr)) {\n                    Py_RETURN_NONE;\n                }\n\n                printf(\"filename=%s num_segments=%zd addr=%p\\n\",\n                       filename.c_str(),\n                       num_segments,\n                       (void*)addr);\n            } break;\n\n            case AggregatedRecordType::SEGMENT: {\n                printf(\"SEGMENT \");\n\n                Segment record;\n                if (!parseSegment(&record)) {\n                    Py_RETURN_NONE;\n                }\n\n                printf(\"%p %\" PRIxPTR \"\\n\", (void*)record.vaddr, record.memsz);\n            } break;\n\n            case AggregatedRecordType::THREAD_RECORD: {\n                printf(\"THREAD_RECORD \");\n\n                std::string name;\n                if (!parseThreadRecord(&name)) {\n                    Py_RETURN_NONE;\n                }\n\n                printf(\"%s\\n\", name.c_str());\n            } break;\n\n            case AggregatedRecordType::CONTEXT_SWITCH: {\n                printf(\"CONTEXT_SWITCH \");\n\n                thread_id_t tid;\n                if (!parseContextSwitch(&tid)) {\n                    Py_RETURN_NONE;\n                }\n\n                printf(\"tid=%lu\\n\", tid);\n            } break;\n\n            case AggregatedRecordType::SURVIVING_OBJECT: {\n                printf(\"SURVIVING_OBJECT \");\n                ObjectRecord record;\n                if (!parseSurvivingObjectRecord(&record)) {\n                    Py_RETURN_NONE;\n                }\n                printf(\"address=0x%p native_frame_id=%zu\\n\",\n                       (void*)record.address,\n                       record.native_frame_id);\n            } break;\n\n            case AggregatedRecordType::CODE_OBJECT: {\n                printf(\"CODE_OBJECT \");\n                tracking_api::pycode_map_val_t record;\n                if (!parseCodeObjectRecord(&record)) {\n                    Py_RETURN_NONE;\n                }\n                printf(\"code_id=%zd function_name=%s filename=%s firstlineno=%d linetable_size=%zd\\n\",\n                       record.first,\n                       record.second.function_name.c_str(),\n                       record.second.filename.c_str(),\n                       record.second.firstlineno,\n                       record.second.linetable.size());\n            } break;\n\n            case AggregatedRecordType::AGGREGATED_TRAILER: {\n                printf(\"AGGREGATED_TRAILER\\n\");\n                Py_RETURN_NONE;  // Treat as EOF\n            } break;\n\n            default: {\n                printf(\"UNKNOWN RECORD TYPE %d\\n\", (int)record_type);\n                Py_RETURN_NONE;\n            } break;\n        }\n    }\n}\n\n}  // namespace memray::api\n"
  },
  {
    "path": "src/memray/_memray/record_reader.h",
    "content": "#pragma once\n\n#define PY_SSIZE_T_CLEAN\n#include <Python.h>\n\n#include <assert.h>\n#include <limits>\n#include <memory>\n#include <optional>\n#include <stddef.h>\n#include <stdint.h>\n#include <string>\n#include <unordered_map>\n#include <vector>\n\n#include \"frame_tree.h\"\n#include \"native_resolver.h\"\n#include \"python_helpers.h\"\n#include \"records.h\"\n#include \"source.h\"\n\nnamespace memray::api {\n\nusing namespace tracking_api;\n\nusing allocations_t = std::vector<Allocation>;\nusing location_id_t = size_t;\n\nclass RecordReader\n{\n  public:\n    enum class RecordResult {\n        ALLOCATION_RECORD,\n        AGGREGATED_ALLOCATION_RECORD,\n        MEMORY_RECORD,\n        MEMORY_SNAPSHOT,\n        OBJECT_RECORD,\n        ERROR,\n        END_OF_FILE,\n    };\n    explicit RecordReader(\n            std::unique_ptr<memray::io::Source> source,\n            bool track_stacks = true,\n            bool track_object_lifetimes = false);\n    void close() noexcept;\n    bool isOpen() const noexcept;\n    PyObject*\n    Py_GetStackFrame(FrameTree::index_t index, size_t max_stacks = std::numeric_limits<size_t>::max());\n    PyObject* Py_GetStackFrameAndEntryInfo(\n            FrameTree::index_t index,\n            std::vector<unsigned char>* is_entry_frame,\n            size_t max_stacks = std::numeric_limits<size_t>::max());\n    PyObject* Py_GetNativeStackFrame(\n            FrameTree::index_t index,\n            size_t generation,\n            size_t max_stacks = std::numeric_limits<size_t>::max());\n    std::optional<location_id_t> getLatestPythonLocationId(const Allocation& allocation);\n    PyObject* Py_GetLocation(std::optional<location_id_t> frame);\n\n    RecordResult nextRecord();\n    HeaderRecord getHeader() const noexcept;\n    thread_id_t getMainThreadTid() const noexcept;\n    size_t getSkippedFramesOnMainThread() const noexcept;\n    PyObject* dumpAllRecords();\n    std::string getThreadName(thread_id_t tid);\n    Allocation getLatestAllocation() const noexcept;\n    MemoryRecord getLatestMemoryRecord() const noexcept;\n    AggregatedAllocation getLatestAggregatedAllocation() const noexcept;\n    MemorySnapshot getLatestMemorySnapshot() const noexcept;\n    TrackedObject getLatestObject() const noexcept;\n\n  private:\n    // Aliases\n    using stack_t = std::vector<FrameTree::index_t>;\n    using stack_traces_t = std::unordered_map<thread_id_t, stack_t>;\n\n    // Private methods\n    void readHeader(HeaderRecord& header);\n    template<typename T>\n    bool readVarint(T* val);\n    bool readVarint(uint64_t* val);\n    template<typename T>\n    bool readSignedVarint(T* val);\n    bool readSignedVarint(int64_t* val);\n    template<typename T>\n    bool readIntegralDelta(T* cache, T* new_val);\n    Location frameToLocation(frame_id_t frame);\n    void extractRecordTypeAndFlags(\n            unsigned char record_type_and_flags,\n            RecordType* record_type,\n            unsigned char* flags) const;\n    RecordResult nextRecordFromAllAllocationsFile();\n    RecordResult nextRecordFromAggregatedAllocationsFile();\n    PyObject* dumpAllRecordsFromAllAllocationsFile();\n    PyObject* dumpAllRecordsFromAggregatedAllocationsFile();\n\n    // Data members\n    mutable std::mutex d_mutex;\n    std::unique_ptr<memray::io::Source> d_input;\n    const bool d_track_stacks;\n    const bool d_track_object_lifetimes;\n    HeaderRecord d_header;\n    std::unordered_map<code_object_id_t, CodeObjectInfo> d_code_object_map{};\n    stack_traces_t d_stack_traces{};\n    FrameTree d_tree{};\n    Registry<Frame> d_python_frame_registry{};\n    std::unordered_map<frame_id_t, Location> d_python_location_by_frame_id{};\n    Registry<Location> d_location_registry{};\n\n    mutable python_helpers::PyUnicode_Cache d_pystring_cache{};\n    native_resolver::SymbolResolver d_symbol_resolver;\n    std::vector<UnresolvedNativeFrame> d_native_frames{};\n    // Pointer cache for recently seen addresses (LRU, indices 0-14)\n    // The cache must stay synchronized with the writer's cache.\n    // Index 0 = most recent, 14 = least recent\n    // Cache encoding in allocation records:\n    //   - 0x0 to 0xE (0-14): Cache hit at this index\n    //   - 0xF (15): Cache miss, full address follows\n    std::array<uintptr_t, 15> d_recent_addresses{};\n    DeltaEncodedFields d_last;\n    stack_t* d_curr_thread_stack{};\n\n    std::unordered_map<thread_id_t, std::string> d_thread_names;\n    Allocation d_latest_allocation;\n    AggregatedAllocation d_latest_aggregated_allocation;\n    MemoryRecord d_latest_memory_record{};\n    MemorySnapshot d_latest_memory_snapshot{};\n    TrackedObject d_latest_object;\n\n    // Methods\n    [[nodiscard]] bool parseFramePush(FramePush* record, unsigned int flags);\n    [[nodiscard]] bool processFramePush(const FramePush& record);\n\n    [[nodiscard]] static bool parseFramePop(FramePop* record, unsigned int flags);\n    [[nodiscard]] bool processFramePop(const FramePop& record);\n\n    [[nodiscard]] bool parseNativeFrameIndex(UnresolvedNativeFrame* frame);\n    [[nodiscard]] bool processNativeFrameIndex(const UnresolvedNativeFrame& frame);\n\n    [[nodiscard]] bool parseAllocationRecord(AllocationRecord* record, unsigned int flags);\n    [[nodiscard]] bool processAllocationRecord(const AllocationRecord& record);\n\n    [[nodiscard]] static bool parseMemoryMapStart();\n    [[nodiscard]] bool processMemoryMapStart();\n\n    [[nodiscard]] bool parseSegmentHeader(std::string* filename, size_t* num_segments, uintptr_t* addr);\n    [[nodiscard]] bool\n    processSegmentHeader(const std::string& filename, size_t num_segments, uintptr_t addr);\n\n    [[nodiscard]] bool parseSegment(Segment* segment);\n\n    [[nodiscard]] bool parseThreadRecord(std::string* name);\n    [[nodiscard]] bool processThreadRecord(const std::string& name);\n\n    [[nodiscard]] bool parseMemoryRecord(MemoryRecord* record);\n    [[nodiscard]] bool processMemoryRecord(const MemoryRecord& record);\n\n    [[nodiscard]] bool parseContextSwitch(thread_id_t* tid);\n    [[nodiscard]] bool processContextSwitch(thread_id_t tid);\n\n    [[nodiscard]] bool parseMemorySnapshotRecord(MemorySnapshot* record);\n    [[nodiscard]] bool processMemorySnapshotRecord(const MemorySnapshot& record);\n\n    [[nodiscard]] bool parseAggregatedAllocationRecord(AggregatedAllocation* record);\n    [[nodiscard]] bool processAggregatedAllocationRecord(const AggregatedAllocation& record);\n\n    [[nodiscard]] bool parsePythonTraceIndexRecord(std::pair<frame_id_t, FrameTree::index_t>* record);\n    [[nodiscard]] bool processPythonTraceIndexRecord(const std::pair<frame_id_t, FrameTree::index_t>&);\n\n    [[nodiscard]] bool parsePythonFrameIndexRecord(std::pair<frame_id_t, Frame>* pyframe_val);\n    [[nodiscard]] bool processPythonFrameIndexRecord(const std::pair<frame_id_t, Frame>& record);\n\n    [[nodiscard]] bool parseCodeObjectRecord(tracking_api::pycode_map_val_t* pycode_val);\n    [[nodiscard]] bool processCodeObjectRecord(const tracking_api::pycode_map_val_t& record);\n\n    [[nodiscard]] bool parseObjectRecord(ObjectRecord* record, unsigned int flags);\n    [[nodiscard]] bool processObjectRecord(const ObjectRecord& record);\n\n    [[nodiscard]] bool parseSurvivingObjectRecord(ObjectRecord* record);\n    [[nodiscard]] bool processSurvivingObjectRecord(const ObjectRecord& record);\n};\n\ntemplate<typename T>\nbool\nRecordReader::readVarint(T* val)\n{\n    static_assert(std::is_unsigned<T>::value, \"Only unsigned varints are supported\");\n    uint64_t temp;\n    if (!readVarint(&temp)) {\n        return false;\n    }\n    *val = temp;\n    return true;\n}\n\ntemplate<typename T>\nbool\nRecordReader::readSignedVarint(T* val)\n{\n    static_assert(!std::is_unsigned<T>::value, \"Only signed varints are supported\");\n    int64_t temp;\n    if (!readSignedVarint(&temp)) {\n        return false;\n    }\n    *val = temp;\n    return true;\n}\n\ntemplate<typename T>\nbool\nRecordReader::readIntegralDelta(T* prev, T* new_val)\n{\n    int64_t delta;\n    if (!readSignedVarint(&delta)) {\n        return false;\n    }\n    *prev += delta;\n    *new_val = *prev;\n    return true;\n}\n\n}  // namespace memray::api\n"
  },
  {
    "path": "src/memray/_memray/record_reader.pxd",
    "content": "from _memray.records cimport AggregatedAllocation\nfrom _memray.records cimport Allocation\nfrom _memray.records cimport HeaderRecord\nfrom _memray.records cimport MemoryRecord\nfrom _memray.records cimport MemorySnapshot\nfrom _memray.records cimport TrackedObject\nfrom _memray.records cimport optional_location_id_t\nfrom _memray.source cimport Source\nfrom libcpp cimport bool\nfrom libcpp.memory cimport unique_ptr\nfrom libcpp.string cimport string\nfrom libcpp.vector cimport vector\n\n\ncdef extern from \"record_reader.h\" namespace \"memray::api\":\n    cdef enum RecordResult 'memray::api::RecordReader::RecordResult':\n        RecordResultAllocationRecord 'memray::api::RecordReader::RecordResult::ALLOCATION_RECORD'\n        RecordResultAggregatedAllocationRecord 'memray::api::RecordReader::RecordResult::AGGREGATED_ALLOCATION_RECORD'\n        RecordResultMemoryRecord 'memray::api::RecordReader::RecordResult::MEMORY_RECORD'\n        RecordResultMemorySnapshot 'memray::api::RecordReader::RecordResult::MEMORY_SNAPSHOT'\n        RecordResultError 'memray::api::RecordReader::RecordResult::ERROR'\n        RecordResultEndOfFile 'memray::api::RecordReader::RecordResult::END_OF_FILE'\n        RecordResultObjectRecord 'memray::api::RecordReader::RecordResult::OBJECT_RECORD'\n\n    cdef cppclass RecordReader:\n        RecordReader(unique_ptr[Source]) except+\n        RecordReader(unique_ptr[Source], bool track_stacks) except+\n        RecordReader(unique_ptr[Source], bool track_stacks, bool track_object_lifetimes) except+\n        void close()\n        bool isOpen() const\n        RecordResult nextRecord() except+\n        object Py_GetStackFrame(size_t frame_id) except+\n        object Py_GetStackFrame(size_t frame_id, size_t max_stacks) except+\n        object Py_GetStackFrameAndEntryInfo(\n            size_t frame_id, vector[unsigned char]* is_entry_frame\n        ) except+\n        object Py_GetStackFrameAndEntryInfo(\n            size_t frame_id, vector[unsigned char]* is_entry_frame, size_t max_stacks\n        ) except+\n        object Py_GetNativeStackFrame(int frame_id, size_t generation) except+\n        object Py_GetNativeStackFrame(int frame_id, size_t generation, size_t max_stacks) except+\n        optional_location_id_t getLatestPythonLocationId(const Allocation&) except+\n        object Py_GetLocation(optional_location_id_t frame) except+\n        HeaderRecord getHeader()\n        size_t getMainThreadTid()\n        size_t getSkippedFramesOnMainThread()\n        object dumpAllRecords() except+\n        string getThreadName(long int tid) except+\n        Allocation getLatestAllocation()\n        MemoryRecord getLatestMemoryRecord()\n        AggregatedAllocation getLatestAggregatedAllocation()\n        MemorySnapshot getLatestMemorySnapshot()\n        TrackedObject getLatestObject()\n"
  },
  {
    "path": "src/memray/_memray/record_writer.cpp",
    "content": "#include \"record_writer.h\"\n\n#include <algorithm>\n#include <array>\n#include <cerrno>\n#include <chrono>\n#include <cstring>\n#include <fcntl.h>\n#include <memory>\n#include <stdexcept>\n\n#include \"frame_tree.h\"\n#include \"records.h\"\n#include \"snapshot.h\"\n\n#if PY_VERSION_HEX >= 0x030D0000\n// This function still exists in 3.13 but Python.h no longer has its prototype.\nextern \"C\" const char*\n_PyMem_GetCurrentAllocatorName();\n#endif\n\nnamespace memray::tracking_api {\n\nusing namespace std::chrono;\n\nstatic PythonAllocatorType\ngetPythonAllocator()\n{\n#if PY_VERSION_HEX >= 0x03080000\n    const char* name = _PyMem_GetCurrentAllocatorName();\n#elif PY_VERSION_HEX >= 0x03070000\n    const char* name = _PyMem_GetAllocatorsName();\n#else\n    const char* name = \"\";\n#endif\n    std::string allocator_name = name != nullptr ? name : \"\";\n    if (allocator_name == \"pymalloc\") {\n        return PythonAllocatorType::PYTHONALLOCATOR_PYMALLOC;\n    }\n    if (allocator_name == \"pymalloc_debug\") {\n        return PythonAllocatorType::PYTHONALLOCATOR_PYMALLOC_DEBUG;\n    }\n    if (allocator_name == \"mimalloc\") {\n        return PythonAllocatorType::PYTHONALLOCATOR_MIMALLOC;\n    }\n    if (allocator_name == \"mimalloc_debug\") {\n        return PythonAllocatorType::PYTHONALLOCATOR_MIMALLOC_DEBUG;\n    }\n    if (allocator_name == \"malloc\") {\n        return PythonAllocatorType::PYTHONALLOCATOR_MALLOC;\n    }\n    return PythonAllocatorType::PYTHONALLOCATOR_OTHER;\n}\n\nRecordWriter::RecordWriter(std::unique_ptr<memray::io::Sink> sink)\n: d_sink(std::move(sink))\n{\n}\n\nclass StreamingRecordWriter : public RecordWriter\n{\n  public:\n    explicit StreamingRecordWriter(\n            std::unique_ptr<memray::io::Sink> sink,\n            const std::string& command_line,\n            bool native_traces,\n            bool trace_python_allocators,\n            bool track_object_lifetimes);\n\n    StreamingRecordWriter(StreamingRecordWriter& other) = delete;\n    StreamingRecordWriter(StreamingRecordWriter&& other) = delete;\n    void operator=(const StreamingRecordWriter&) = delete;\n    void operator=(StreamingRecordWriter&&) = delete;\n\n    bool writeRecord(const MemoryRecord& record) override;\n    bool writeRecord(const pycode_map_val_t& item) override;\n    bool writeRecord(const UnresolvedNativeFrame& record) override;\n\n    bool writeMappings(const std::vector<ImageSegments>& mappings) override;\n\n    bool writeThreadSpecificRecord(thread_id_t tid, const FramePop& record) override;\n    bool writeThreadSpecificRecord(thread_id_t tid, const FramePush& record) override;\n    bool writeThreadSpecificRecord(thread_id_t tid, const AllocationRecord& record) override;\n    bool writeThreadSpecificRecord(thread_id_t tid, const ThreadRecord& record) override;\n    bool writeThreadSpecificRecord(thread_id_t tid, const ObjectRecord& record) override;\n\n    bool writeHeader(bool seek_to_start) override;\n    bool writeTrailer() override;\n\n    void setMainTidAndSkippedFrames(thread_id_t main_tid, size_t skipped_frames_on_main_tid) override;\n    std::unique_ptr<RecordWriter> cloneInChildProcess() override;\n\n  private:\n    bool maybeWriteContextSwitchRecordUnsafe(thread_id_t tid);\n    int pointerCacheIndex(uintptr_t ptr);\n\n    // Data members\n    int d_version{CURRENT_HEADER_VERSION};\n    HeaderRecord d_header{};\n    TrackerStats d_stats{};\n    // LRU Pointer Cache System\n    // ========================\n    // Recent allocation addresses are cached to avoid repeating pointers.\n    // - Cache holds 15 most recent unique addresses (indices 0-14)\n    // - Index 0 = most recently added, 14 = least recently added\n    // - On miss: new address inserted at index 0, others shift right, index 14 drops\n    //\n    // Wire format uses 4 bits (pppp):\n    //   0x0-0xE (0-14): Cache hit - reuse address at this index\n    //   0xF (15):       Cache miss - read/write full address, update cache\n    //\n    // Compression example:\n    //   malloc() returns 0x7fff8000 five times, free() called five times\n    //   Traditional: 5 * 8 bytes (addresses) = 40 bytes\n    //   With cache:  8 bytes (first addr) + 5 * 0 bytes (cache hits) = 8 bytes\n    //\n    // CRITICAL: Reader and writer caches must stay synchronized by processing\n    //           records in identical order with identical LRU updates.\n    std::array<uintptr_t, 15> d_recent_addresses{};\n    DeltaEncodedFields d_last;\n};\n\nclass AggregatingRecordWriter : public RecordWriter\n{\n  public:\n    explicit AggregatingRecordWriter(\n            std::unique_ptr<memray::io::Sink> sink,\n            const std::string& command_line,\n            bool native_traces,\n            bool trace_python_allocators,\n            bool track_object_lifetimes);\n\n    AggregatingRecordWriter(StreamingRecordWriter& other) = delete;\n    AggregatingRecordWriter(StreamingRecordWriter&& other) = delete;\n    void operator=(const AggregatingRecordWriter&) = delete;\n    void operator=(AggregatingRecordWriter&&) = delete;\n\n    bool writeRecord(const MemoryRecord& record) override;\n    bool writeRecord(const pycode_map_val_t& item) override;\n    bool writeRecord(const UnresolvedNativeFrame& record) override;\n\n    bool writeMappings(const std::vector<ImageSegments>& mappings) override;\n\n    bool writeThreadSpecificRecord(thread_id_t tid, const FramePop& record) override;\n    bool writeThreadSpecificRecord(thread_id_t tid, const FramePush& record) override;\n    bool writeThreadSpecificRecord(thread_id_t tid, const AllocationRecord& record) override;\n    bool writeThreadSpecificRecord(thread_id_t tid, const ThreadRecord& record) override;\n    bool writeThreadSpecificRecord(thread_id_t tid, const ObjectRecord& record) override;\n\n    bool writeHeader(bool seek_to_start) override;\n    bool writeTrailer() override;\n\n    void setMainTidAndSkippedFrames(thread_id_t main_tid, size_t skipped_frames_on_main_tid) override;\n    std::unique_ptr<RecordWriter> cloneInChildProcess() override;\n\n  private:\n    // Aliases\n    using python_stack_ids_t = std::vector<FrameTree::index_t>;\n    using python_stack_ids_by_tid = std::unordered_map<thread_id_t, python_stack_ids_t>;\n\n    // Data members\n    HeaderRecord d_header;\n    TrackerStats d_stats;\n    Registry<Frame> d_python_frame_registry;\n    std::unordered_map<code_object_id_t, CodeObjectInfo> d_code_objects_by_id;\n    std::vector<UnresolvedNativeFrame> d_native_frames{};\n    std::vector<std::vector<ImageSegments>> d_mappings_by_generation{};\n    std::vector<MemorySnapshot> d_memory_snapshots;\n    std::unordered_map<thread_id_t, std::string> d_thread_name_by_tid;\n    FrameTree d_python_frame_tree;\n    python_stack_ids_by_tid d_python_stack_ids_by_thread;\n    std::unordered_map<uintptr_t, frame_id_t> d_surviving_objects;\n    DeltaEncodedFields d_last;\n    api::HighWaterMarkAggregator d_high_water_mark_aggregator;\n};\n\nstd::unique_ptr<RecordWriter>\ncreateRecordWriter(\n        std::unique_ptr<memray::io::Sink> sink,\n        const std::string& command_line,\n        bool native_traces,\n        FileFormat file_format,\n        bool trace_python_allocators,\n        bool track_object_lifetimes)\n{\n    switch (file_format) {\n        case FileFormat::ALL_ALLOCATIONS:\n            return std::make_unique<StreamingRecordWriter>(\n                    std::move(sink),\n                    command_line,\n                    native_traces,\n                    trace_python_allocators,\n                    track_object_lifetimes);\n        case FileFormat::AGGREGATED_ALLOCATIONS:\n            return std::make_unique<AggregatingRecordWriter>(\n                    std::move(sink),\n                    command_line,\n                    native_traces,\n                    trace_python_allocators,\n                    track_object_lifetimes);\n        default:\n            throw std::runtime_error(\"Invalid file format enumerator\");\n    }\n}\n\nStreamingRecordWriter::StreamingRecordWriter(\n        std::unique_ptr<memray::io::Sink> sink,\n        const std::string& command_line,\n        bool native_traces,\n        bool trace_python_allocators,\n        bool track_object_lifetimes)\n: RecordWriter(std::move(sink))\n, d_stats({0, 0, duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count()})\n{\n    d_header = HeaderRecord{\n            \"\",\n            d_version,\n            PY_VERSION_HEX,\n            native_traces,\n            FileFormat::ALL_ALLOCATIONS,\n            d_stats,\n            command_line,\n            ::getpid(),\n            0,\n            0,\n            getPythonAllocator(),\n            trace_python_allocators,\n            track_object_lifetimes};\n    strncpy(d_header.magic, MAGIC, sizeof(d_header.magic));\n}\n\nvoid\nStreamingRecordWriter::setMainTidAndSkippedFrames(\n        thread_id_t main_tid,\n        size_t skipped_frames_on_main_tid)\n{\n    d_header.main_tid = main_tid;\n    d_header.skipped_frames_on_main_tid = skipped_frames_on_main_tid;\n}\n\nbool\nStreamingRecordWriter::writeRecord(const MemoryRecord& record)\n{\n    auto token = static_cast<unsigned char>(RecordType::MEMORY_RECORD);\n    return writeSimpleType(token) && writeVarint(record.rss)\n           && writeVarint(record.ms_since_epoch - d_stats.start_time) && d_sink->flush();\n}\n\nbool\nStreamingRecordWriter::writeRecord(const pycode_map_val_t& item)\n{\n    auto token = static_cast<unsigned char>(RecordType::CODE_OBJECT);\n    return writeSimpleType(token) && writeVarint(item.first)\n           && writeString(item.second.function_name.c_str()) && writeString(item.second.filename.c_str())\n           && writeIntegralDelta(&d_last.code_firstlineno, item.second.firstlineno)\n           && writeVarint(item.second.linetable.size())\n           && d_sink->writeAll(item.second.linetable.data(), item.second.linetable.size());\n}\n\nbool\nStreamingRecordWriter::writeRecord(const UnresolvedNativeFrame& record)\n{\n    return writeSimpleType(static_cast<unsigned char>(RecordType::NATIVE_TRACE_INDEX))\n           && writeIntegralDelta(&d_last.instruction_pointer, record.ip)\n           && writeIntegralDelta(&d_last.native_frame_id, record.index);\n}\n\nbool\nStreamingRecordWriter::writeMappings(const std::vector<ImageSegments>& mappings)\n{\n    return writeMappingsCommon(mappings);\n}\n\nbool\nRecordWriter::writeMappingsCommon(const std::vector<ImageSegments>& mappings)\n{\n    auto start_token = static_cast<unsigned char>(RecordType::MEMORY_MAP_START);\n    if (!writeSimpleType(start_token)) {\n        return false;\n    }\n\n    for (const auto& image : mappings) {\n        auto segment_header_token = static_cast<unsigned char>(RecordType::SEGMENT_HEADER);\n        if (!writeSimpleType(segment_header_token) || !writeString(image.filename.c_str())\n            || !writeVarint(image.segments.size()) || !writeSimpleType(image.addr))\n        {\n            return false;\n        }\n\n        auto segment_token = static_cast<unsigned char>(RecordType::SEGMENT);\n\n        for (const auto& segment : image.segments) {\n            if (!writeSimpleType(segment_token) || !writeSimpleType(segment.vaddr)\n                || !writeVarint(segment.memsz))\n            {\n                return false;\n            }\n        }\n    }\n\n    return true;\n}\n\nbool\nStreamingRecordWriter::maybeWriteContextSwitchRecordUnsafe(thread_id_t tid)\n{\n    if (d_last.thread_id == tid) {\n        return true;  // nothing to do.\n    }\n    d_last.thread_id = tid;\n\n    auto token = static_cast<unsigned char>(RecordType::CONTEXT_SWITCH);\n    ContextSwitch record{tid};\n    return writeSimpleType(token) && writeSimpleType(record);\n}\n\nint\nStreamingRecordWriter::pointerCacheIndex(uintptr_t ptr)\n{\n    auto it = std::find(d_recent_addresses.begin(), d_recent_addresses.end(), ptr);\n    if (it != d_recent_addresses.end()) {\n        return static_cast<int>(std::distance(d_recent_addresses.begin(), it));\n    }\n\n    std::move(d_recent_addresses.begin(), d_recent_addresses.end() - 1, d_recent_addresses.begin() + 1);\n    d_recent_addresses[0] = ptr;\n\n    return -1;\n}\n\nbool\nStreamingRecordWriter::writeThreadSpecificRecord(thread_id_t tid, const FramePop& record)\n{\n    if (!maybeWriteContextSwitchRecordUnsafe(tid)) {\n        return false;\n    }\n\n    // FRAME_POP ENCODING: 0b0001nnnn, n+1 is number of frames to pop.\n    // If there are more than 16 frames to pop, we emit multiple FRAME_POP records.\n    size_t count = record.count;\n    while (count) {\n        uint8_t to_pop = (count > 16 ? 16 : count);\n        count -= to_pop;\n\n        to_pop -= 1;  // i.e. 0 means pop 1 frame, 15 means pop 16 frames\n        auto token = static_cast<unsigned char>(RecordType::FRAME_POP);\n        token |= to_pop;\n        if (!writeSimpleType(token)) {\n            return false;\n        }\n    }\n\n    return true;\n}\n\nbool\nStreamingRecordWriter::writeThreadSpecificRecord(thread_id_t tid, const FramePush& record)\n{\n    if (!maybeWriteContextSwitchRecordUnsafe(tid)) {\n        return false;\n    }\n\n    // FRAME_PUSH ENCODING: 0b01uuuuue, `u` are unused bits, `e` is is-entry-frame.\n    // In the future we can use `u` to pack more information into the token,\n    // like whether the code object id has been recently seen.\n    // This is followed by the varint encoded code object id and instruction offset.\n    auto token = static_cast<unsigned char>(RecordType::FRAME_PUSH);\n    token |= record.frame.is_entry_frame;\n    return writeSimpleType(token) && writeVarint(record.frame.code_object_id)\n           && writeSignedVarint(record.frame.instruction_offset);\n}\n\nbool\nStreamingRecordWriter::writeThreadSpecificRecord(thread_id_t tid, const AllocationRecord& record)\n{\n    if (!maybeWriteContextSwitchRecordUnsafe(tid)) {\n        return false;\n    }\n\n    // ALLOCATION ENCODING: 0b1ppppaaa\n    //\n    // Bit layout of the first byte:\n    // ┌─┬─────┬─────┐\n    // │1│pppp │ aaa │\n    // └─┴─────┴─────┘\n    //  ↑   ↑     ↑\n    //  │   │     └── Allocator ID (0-7):\n    //  │   │           1-7: Common allocators (PYMALLOC_FREE, MALLOC, etc.)\n    //  │   │             0: Uncommon allocator, full ID follows as separate byte\n    //  │   └──────── Pointer cache index (0-15):\n    //  │               0-14: Cache hit, reuse address at cache[index]\n    //  │                 15: Cache miss, delta-encoded pointer follows\n    //  └──────────── Record type marker (always 1 for ALLOCATION)\n    //\n    // Byte sequence after the type byte:\n    // [pointer]     - Delta-encoded pointer >> 3 (only if pppp=15)\n    // [allocator]   - Full allocator ID byte (only if aaa=0)\n    // [native_id]   - Delta-encoded native_frame_id (only if native traces enabled\n    //                 AND not a simple deallocator)\n    // [size]        - Varint-encoded size (only if not a simple deallocator)\n    //\n    // Example sequences:\n    // - Cached malloc(256):        [0b10011110] [size:256]\n    //     (cache_idx=1, allocator=6)\n    // - New pymalloc_free(ptr):    [0b11111001] [ptr_delta]\n    //     (cache_miss, allocator=1, no size for deallocator)\n    d_stats.n_allocations += 1;\n    auto token = static_cast<unsigned char>(RecordType::ALLOCATION);\n\n    auto allocator_id = static_cast<unsigned char>(record.allocator);\n    if (allocator_id < 8) {\n        token |= allocator_id;\n    }\n\n    int pointer_cache_index = pointerCacheIndex(record.address);\n    token |= (pointer_cache_index & 0x0f) << 3;\n\n    return writeSimpleType(token)\n           && (pointer_cache_index != -1\n               || writeIntegralDelta(&d_last.data_pointer, record.address >> 3))\n           && (allocator_id < 8 || writeSimpleType(record.allocator))\n           && (!d_header.native_traces\n               || hooks::allocatorKind(record.allocator) == hooks::AllocatorKind::SIMPLE_DEALLOCATOR\n               || writeIntegralDelta(&d_last.native_frame_id, record.native_frame_id))\n           && (hooks::allocatorKind(record.allocator) == hooks::AllocatorKind::SIMPLE_DEALLOCATOR\n               || writeVarint(record.size));\n}\n\nbool\nStreamingRecordWriter::writeThreadSpecificRecord(thread_id_t tid, const ThreadRecord& record)\n{\n    if (!maybeWriteContextSwitchRecordUnsafe(tid)) {\n        return false;\n    }\n\n    auto token = static_cast<unsigned char>(RecordType::THREAD_RECORD);\n    return writeSimpleType(token) && writeString(record.name);\n}\n\nbool\nStreamingRecordWriter::writeThreadSpecificRecord(thread_id_t tid, const ObjectRecord& record)\n{\n    if (!maybeWriteContextSwitchRecordUnsafe(tid)) {\n        return false;\n    }\n\n    // OBJECT_RECORD ENCODING: 0b001ppppc\n    // c: creation (1) or destruction (0)\n    // p: 4 bit pointer cache exactly as in ALLOCATION\n    // This byte is followed by the pointer on cache misses, exactly as in ALLOCATION.\n    // For creations that is followed by the native frame id if native tracking is enabled.\n    auto token = static_cast<unsigned char>(RecordType::OBJECT_RECORD);\n    if (record.is_created) {\n        token |= 1;\n    }\n\n    int pointer_cache_index = pointerCacheIndex(record.address);\n    token |= (pointer_cache_index & 0x0f) << 1;\n\n    return writeSimpleType(token)\n           && (pointer_cache_index != -1\n               || writeIntegralDelta(&d_last.data_pointer, record.address >> 3))\n           && (!d_header.native_traces || !record.is_created\n               || writeIntegralDelta(&d_last.native_frame_id, record.native_frame_id));\n}\n\nbool\nStreamingRecordWriter::writeHeader(bool seek_to_start)\n{\n    if (seek_to_start) {\n        // If we can't seek to the beginning to the stream (e.g. dealing with a socket), just give\n        // up.\n        if (!d_sink->seek(0, SEEK_SET)) {\n            return false;\n        }\n    }\n\n    d_stats.end_time = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();\n    d_header.stats = d_stats;\n    return writeHeaderCommon(d_header);\n}\n\nbool\nRecordWriter::writeHeaderCommon(const HeaderRecord& header)\n{\n    if (!writeSimpleType(header.magic) or !writeSimpleType(header.version)\n        or !writeSimpleType(header.python_version) or !writeSimpleType(header.native_traces)\n        or !writeSimpleType(header.file_format) or !writeSimpleType(header.stats)\n        or !writeString(header.command_line.c_str()) or !writeSimpleType(header.pid)\n        or !writeSimpleType(header.main_tid) or !writeSimpleType(header.skipped_frames_on_main_tid)\n        or !writeSimpleType(header.python_allocator) or !writeSimpleType(header.trace_python_allocators)\n        or !writeSimpleType(header.track_object_lifetimes))\n    {\n        return false;\n    }\n    return true;\n}\n\nbool\nStreamingRecordWriter::writeTrailer()\n{\n    // The FileSource will ignore trailing 0x00 bytes. This non-zero trailer\n    // marks the boundary between bytes we wrote and padding bytes.\n    auto token = static_cast<unsigned char>(RecordType::TRAILER);\n    return writeSimpleType(token);\n}\n\nstd::unique_ptr<RecordWriter>\nStreamingRecordWriter::cloneInChildProcess()\n{\n    std::unique_ptr<io::Sink> new_sink = d_sink->cloneInChildProcess();\n    if (!new_sink) {\n        return {};\n    }\n    return std::make_unique<StreamingRecordWriter>(\n            std::move(new_sink),\n            d_header.command_line,\n            d_header.native_traces,\n            d_header.trace_python_allocators,\n            d_header.track_object_lifetimes);\n}\n\nAggregatingRecordWriter::AggregatingRecordWriter(\n        std::unique_ptr<memray::io::Sink> sink,\n        const std::string& command_line,\n        bool native_traces,\n        bool trace_python_allocators,\n        bool track_object_lifetimes)\n: RecordWriter(std::move(sink))\n{\n    memcpy(d_header.magic, MAGIC, sizeof(d_header.magic));\n    d_header.version = CURRENT_HEADER_VERSION;\n    d_header.python_version = PY_VERSION_HEX;\n    d_header.native_traces = native_traces;\n    d_header.file_format = FileFormat::AGGREGATED_ALLOCATIONS;\n    d_header.command_line = command_line;\n    d_header.pid = ::getpid();\n    d_header.python_allocator = getPythonAllocator();\n    d_header.trace_python_allocators = trace_python_allocators;\n    d_header.track_object_lifetimes = track_object_lifetimes;\n\n    d_stats.start_time = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();\n}\n\nvoid\nAggregatingRecordWriter::setMainTidAndSkippedFrames(\n        thread_id_t main_tid,\n        size_t skipped_frames_on_main_tid)\n{\n    d_header.main_tid = main_tid;\n    d_header.skipped_frames_on_main_tid = skipped_frames_on_main_tid;\n}\n\nbool\nAggregatingRecordWriter::writeHeader(bool seek_to_start)\n{\n    // Nothing to do; everything is written by writeTrailer.\n    (void)seek_to_start;\n    return true;\n}\n\nbool\nAggregatingRecordWriter::writeTrailer()\n{\n    d_stats.end_time = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();\n    d_header.stats = d_stats;\n    if (!writeHeaderCommon(d_header)) {\n        return false;\n    }\n\n    for (const auto& memory_snapshot : d_memory_snapshots) {\n        if (!writeSimpleType(AggregatedRecordType::MEMORY_SNAPSHOT) || !writeSimpleType(memory_snapshot))\n        {\n            return false;\n        }\n    }\n\n    for (const auto& [tid, thread_name] : d_thread_name_by_tid) {\n        if (!writeSimpleType(AggregatedRecordType::CONTEXT_SWITCH)\n            || !writeSimpleType(ContextSwitch{tid})\n            || !writeSimpleType(AggregatedRecordType::THREAD_RECORD)\n            || !writeString(thread_name.c_str()))\n        {\n            return false;\n        }\n    }\n\n    for (const auto& mappings : d_mappings_by_generation) {\n        if (!writeMappingsCommon(mappings)) {\n            return false;\n        }\n    }\n\n    // Write code objects first\n    for (const auto& [code_id, code_info] : d_code_objects_by_id) {\n        if (!writeSimpleType(AggregatedRecordType::CODE_OBJECT) || !writeVarint(code_id)\n            || !writeString(code_info.function_name.c_str()) || !writeString(code_info.filename.c_str())\n            || !writeIntegralDelta(&d_last.code_firstlineno, code_info.firstlineno)\n            || !writeVarint(code_info.linetable.size())\n            || !d_sink->writeAll(code_info.linetable.data(), code_info.linetable.size()))\n        {\n            return false;\n        }\n    }\n\n    UnresolvedNativeFrame last{};\n    for (const auto& record : d_native_frames) {\n        if (!writeSimpleType(AggregatedRecordType::NATIVE_TRACE_INDEX)\n            || !writeIntegralDelta(&last.ip, record.ip)\n            || !writeIntegralDelta(&last.index, record.index))\n        {\n            return false;\n        }\n    }\n\n    for (size_t frame_id = 0; frame_id < d_python_frame_registry.size(); ++frame_id) {\n        const auto& frame = d_python_frame_registry.getRecord(frame_id);\n        if (!writeSimpleType(AggregatedRecordType::PYTHON_FRAME_INDEX) || !writeVarint(frame_id)\n            || !writeVarint(frame.code_object_id) || !writeSignedVarint(frame.instruction_offset)\n            || !writeSimpleType(frame.is_entry_frame))\n        {\n            return false;\n        }\n    }\n\n    for (FrameTree::index_t index = d_python_frame_tree.minIndex();\n         index <= d_python_frame_tree.maxIndex();\n         ++index)\n    {\n        auto [frame_id, parent_index] = d_python_frame_tree.nextNode(index);\n\n        if (!writeSimpleType(AggregatedRecordType::PYTHON_TRACE_INDEX) || !writeVarint(frame_id)\n            || !writeVarint(parent_index))\n        {\n            return false;\n        }\n    }\n\n    // Write surviving objects\n    for (const auto& [address, native_frame_id] : d_surviving_objects) {\n        if (!writeSimpleType(AggregatedRecordType::SURVIVING_OBJECT) || !writeVarint(address >> 3)\n            || (d_header.native_traces && !writeVarint(native_frame_id)))\n        {\n            return false;\n        }\n    }\n\n    d_high_water_mark_aggregator.visitAllocations([&](const AggregatedAllocation& allocation) {\n        if (allocation.n_allocations_in_high_water_mark == 0 && allocation.n_allocations_leaked == 0) {\n            return true;\n        }\n\n        return writeSimpleType(AggregatedRecordType::AGGREGATED_ALLOCATION)\n               && writeSimpleType(allocation);\n    });\n\n    // The FileSource will ignore trailing 0x00 bytes. This non-zero trailer\n    // marks the boundary between bytes we wrote and padding bytes.\n    if (!writeSimpleType(AggregatedRecordType::AGGREGATED_TRAILER)) {\n        return false;\n    }\n\n    return true;\n}\n\nstd::unique_ptr<RecordWriter>\nAggregatingRecordWriter::cloneInChildProcess()\n{\n    std::unique_ptr<io::Sink> new_sink = d_sink->cloneInChildProcess();\n    if (!new_sink) {\n        return {};\n    }\n    return std::make_unique<AggregatingRecordWriter>(\n            std::move(new_sink),\n            d_header.command_line,\n            d_header.native_traces,\n            d_header.trace_python_allocators,\n            d_header.track_object_lifetimes);\n}\n\nbool\nAggregatingRecordWriter::writeRecord(const MemoryRecord& record)\n{\n    MemorySnapshot snapshot{\n            record.ms_since_epoch,\n            record.rss,\n            d_high_water_mark_aggregator.getCurrentHeapSize()};\n    d_memory_snapshots.push_back(snapshot);\n    return true;\n}\n\nbool\nAggregatingRecordWriter::writeRecord(const pycode_map_val_t& item)\n{\n    // For aggregating writer, we'll store code objects in a map\n    const auto& [code_id, code_info] = item;\n    d_code_objects_by_id.emplace(code_id, code_info);\n    return true;\n}\n\nbool\nAggregatingRecordWriter::writeRecord(const UnresolvedNativeFrame& record)\n{\n    d_native_frames.emplace_back(record);\n    return true;\n}\n\nbool\nAggregatingRecordWriter::writeMappings(const std::vector<ImageSegments>& mappings)\n{\n    d_mappings_by_generation.push_back(mappings);\n    return true;\n}\n\nbool\nAggregatingRecordWriter::writeThreadSpecificRecord(thread_id_t tid, const FramePop& record)\n{\n    auto count = record.count;\n    auto& stack = d_python_stack_ids_by_thread[tid];\n    assert(stack.size() >= record.count);\n    while (count) {\n        count -= 1;\n        stack.pop_back();\n    }\n    return true;\n}\n\nbool\nAggregatingRecordWriter::writeThreadSpecificRecord(thread_id_t tid, const FramePush& record)\n{\n    auto [it, inserted] = d_python_stack_ids_by_thread.emplace(tid, python_stack_ids_t{});\n    auto& stack = it->second;\n    if (inserted) {\n        stack.reserve(1024);\n    }\n    auto frame_index = d_python_frame_registry.registerRecord(record.frame).first;\n    FrameTree::index_t current_stack_id = stack.empty() ? 0 : stack.back();\n    FrameTree::index_t new_stack_id = d_python_frame_tree.getTraceIndex(current_stack_id, frame_index);\n    stack.push_back(new_stack_id);\n    return true;\n}\n\nbool\nAggregatingRecordWriter::writeThreadSpecificRecord(thread_id_t tid, const AllocationRecord& record)\n{\n    Allocation allocation;\n    allocation.tid = tid;\n    allocation.address = record.address;\n    allocation.size = record.size;\n    allocation.allocator = record.allocator;\n    allocation.native_frame_id = record.native_frame_id;\n    if (!hooks::isDeallocator(record.allocator)) {\n        auto& stack = d_python_stack_ids_by_thread[tid];\n        allocation.frame_index = stack.empty() ? 0 : stack.back();\n    } else {\n        allocation.frame_index = 0;\n    }\n    allocation.native_segment_generation = d_mappings_by_generation.size();\n    allocation.n_allocations = 1;\n    d_high_water_mark_aggregator.addAllocation(allocation);\n    return true;\n}\n\nbool\nAggregatingRecordWriter::writeThreadSpecificRecord(thread_id_t tid, const ThreadRecord& record)\n{\n    d_thread_name_by_tid[tid] = record.name;\n    return true;\n}\n\nbool\nAggregatingRecordWriter::writeThreadSpecificRecord(thread_id_t tid, const ObjectRecord& record)\n{\n    if (record.is_created) {\n        d_surviving_objects[record.address] = record.native_frame_id;\n    } else {\n        d_surviving_objects.erase(record.address);\n    }\n    return true;\n}\n\n}  // namespace memray::tracking_api\n"
  },
  {
    "path": "src/memray/_memray/record_writer.h",
    "content": "#pragma once\n\n#include <limits>\n#include <string>\n#include <type_traits>\n#include <unistd.h>\n\n#include \"sink.h\"\n\nnamespace memray::tracking_api {\n\nclass RecordWriter\n{\n  public:\n    virtual ~RecordWriter() = default;\n\n    RecordWriter(RecordWriter& other) = delete;\n    RecordWriter(RecordWriter&& other) = delete;\n    void operator=(const RecordWriter&) = delete;\n    void operator=(RecordWriter&&) = delete;\n\n    virtual bool writeRecord(const MemoryRecord& record) = 0;\n    virtual bool writeRecord(const pycode_map_val_t& item) = 0;\n    virtual bool writeRecord(const UnresolvedNativeFrame& record) = 0;\n\n    virtual bool writeMappings(const std::vector<ImageSegments>& mappings) = 0;\n\n    virtual bool writeThreadSpecificRecord(thread_id_t tid, const FramePop& record) = 0;\n    virtual bool writeThreadSpecificRecord(thread_id_t tid, const FramePush& record) = 0;\n    virtual bool writeThreadSpecificRecord(thread_id_t tid, const AllocationRecord& record) = 0;\n    virtual bool writeThreadSpecificRecord(thread_id_t tid, const ThreadRecord& record) = 0;\n    virtual bool writeThreadSpecificRecord(thread_id_t tid, const ObjectRecord& record) = 0;\n\n    virtual bool writeHeader(bool seek_to_start) = 0;\n    virtual bool writeTrailer() = 0;\n\n    virtual void setMainTidAndSkippedFrames(thread_id_t main_tid, size_t skipped_frames_on_main_tid) = 0;\n    virtual std::unique_ptr<RecordWriter> cloneInChildProcess() = 0;\n\n  protected:\n    // Expose the sink for use by the following helper functions.\n    explicit RecordWriter(std::unique_ptr<memray::io::Sink> sink);\n    std::unique_ptr<memray::io::Sink> d_sink;\n\n    // Helper functions for common code needed by both subclasses.\n    bool writeHeaderCommon(const HeaderRecord&);\n    bool writeMappingsCommon(const std::vector<ImageSegments>&);\n\n    template<typename T>\n    bool inline writeSimpleType(const T& item);\n\n    bool inline writeString(const char* the_string);\n    bool inline writeVarint(uint64_t val);\n    bool inline writeSignedVarint(int64_t val);\n\n    template<typename T>\n    bool inline writeIntegralDelta(T* prev, T new_val);\n};\n\nstd::unique_ptr<RecordWriter>\ncreateRecordWriter(\n        std::unique_ptr<memray::io::Sink> sink,\n        const std::string& command_line,\n        bool native_traces,\n        FileFormat file_format,\n        bool trace_python_allocators,\n        bool track_object_lifetimes);\n\ntemplate<typename T>\nbool inline RecordWriter::writeSimpleType(const T& item)\n{\n    static_assert(\n            std::is_trivially_copyable<T>::value,\n            \"writeSimpleType called on non trivially copyable type\");\n\n    return d_sink->writeAll(reinterpret_cast<const char*>(&item), sizeof(item));\n};\n\nbool inline RecordWriter::writeString(const char* the_string)\n{\n    return d_sink->writeAll(the_string, strlen(the_string) + 1);\n}\n\nbool inline RecordWriter::writeVarint(uint64_t rest)\n{\n    unsigned char next_7_bits = rest & 0x7f;\n    rest >>= 7;\n    while (rest) {\n        next_7_bits |= 0x80;\n        if (!writeSimpleType(next_7_bits)) {\n            return false;\n        }\n        next_7_bits = rest & 0x7f;\n        rest >>= 7;\n    }\n\n    return writeSimpleType(next_7_bits);\n}\n\nbool inline RecordWriter::writeSignedVarint(int64_t val)\n{\n    // protobuf style \"zig-zag\" encoding\n    // https://developers.google.com/protocol-buffers/docs/encoding#signed-ints\n    // This encodes -64 through 63 in 1 byte, -8192 through 8191 in 2 bytes, etc\n    uint64_t zigzag_val = (static_cast<uint64_t>(val) << 1)\n                          ^ static_cast<uint64_t>(val >> std::numeric_limits<int64_t>::digits);\n    return writeVarint(zigzag_val);\n}\n\ntemplate<typename T>\nbool inline RecordWriter::writeIntegralDelta(T* prev, T new_val)\n{\n    int64_t delta = new_val - *prev;\n    *prev = new_val;\n    return writeSignedVarint(delta);\n}\n\n}  // namespace memray::tracking_api\n"
  },
  {
    "path": "src/memray/_memray/record_writer.pxd",
    "content": "from _memray.records cimport AllocationRecord\nfrom _memray.records cimport CodeObjectInfo\nfrom _memray.records cimport FileFormat\nfrom _memray.records cimport FramePop\nfrom _memray.records cimport FramePush\nfrom _memray.records cimport HeaderRecord\nfrom _memray.records cimport ImageSegments\nfrom _memray.records cimport MemoryRecord\nfrom _memray.records cimport ObjectRecord\nfrom _memray.records cimport ThreadRecord\nfrom _memray.records cimport UnresolvedNativeFrame\nfrom _memray.records cimport code_object_id_t\nfrom _memray.records cimport thread_id_t\nfrom _memray.sink cimport Sink\nfrom libcpp cimport bool\nfrom libcpp.memory cimport unique_ptr\nfrom libcpp.string cimport string\nfrom libcpp.utility cimport pair\nfrom libcpp.vector cimport vector\n\n\ncdef extern from *:\n    ctypedef struct PyCodeObject:\n        pass\n\n    ctypedef struct PyFrameObject:\n        pass\n\n\ncdef extern from \"compat.h\" namespace \"memray::compat\":\n    char* codeGetLinetable(PyCodeObject*, size_t*)\n    int frameGetLasti(PyFrameObject*)\n\n\ncdef extern from \"record_writer.h\" namespace \"memray::tracking_api\":\n    cdef cppclass RecordWriter:\n        bool writeRecord(const MemoryRecord& record) except+\n        bool writeRecord(const pair[code_object_id_t, CodeObjectInfo]& record) except+\n        bool writeRecord(const UnresolvedNativeFrame& record) except+\n        bool writeMappings(const vector[ImageSegments]& mappings) except+\n        bool writeThreadSpecificRecord(thread_id_t tid, const FramePop& record) except+\n        bool writeThreadSpecificRecord(thread_id_t tid, const FramePush& record) except+\n        bool writeThreadSpecificRecord(thread_id_t tid, const AllocationRecord& record) except+\n        bool writeThreadSpecificRecord(thread_id_t tid, const ThreadRecord& record) except+\n        bool writeThreadSpecificRecord(thread_id_t tid, const ObjectRecord& record) except+\n        bool writeHeader(bool seek_to_start) except+\n        bool writeTrailer() except+\n        void setMainTidAndSkippedFrames(thread_id_t main_tid, size_t skipped_frames_on_main_tid) except+\n        unique_ptr[RecordWriter] cloneInChildProcess() except+\n\n    cdef unique_ptr[RecordWriter] createRecordWriter(\n        unique_ptr[Sink],\n        string command_line,\n        bool native_trace,\n        FileFormat file_format,\n        bool trace_python_allocators,\n        bool track_object_lifetimes,\n    ) except+\n"
  },
  {
    "path": "src/memray/_memray/records.cpp",
    "content": "#define PY_SSIZE_T_CLEAN\n#include <Python.h>\n\n#include \"python_helpers.h\"\n#include \"records.h\"\n\nnamespace memray::tracking_api {\n\nconst char MAGIC[7] = \"memray\";\n\nPyObject*\nAllocation::toPythonObject() const\n{\n    // We are not using PyBuildValue here because unrolling the\n    // operations speeds up the parsing moderately. Additionally, some of\n    // the types we need to convert from are not supported by PyBuildValue\n    // natively.\n    PyObject* tuple = PyTuple_New(8);\n    if (tuple == nullptr) {\n        return nullptr;\n    }\n\n#define __CHECK_ERROR(elem)                                                                             \\\n    do {                                                                                                \\\n        if (elem == nullptr) {                                                                          \\\n            Py_DECREF(tuple);                                                                           \\\n            return nullptr;                                                                             \\\n        }                                                                                               \\\n    } while (0)\n    PyObject* elem = PyLong_FromLong(tid);\n    __CHECK_ERROR(elem);\n    PyTuple_SET_ITEM(tuple, 0, elem);\n    elem = PyLong_FromUnsignedLong(address);\n    __CHECK_ERROR(elem);\n    PyTuple_SET_ITEM(tuple, 1, elem);\n    elem = PyLong_FromSize_t(size);\n    __CHECK_ERROR(elem);\n    PyTuple_SET_ITEM(tuple, 2, elem);\n    elem = PyLong_FromLong(static_cast<int>(allocator));\n    __CHECK_ERROR(elem);\n    PyTuple_SET_ITEM(tuple, 3, elem);\n    elem = PyLong_FromSize_t(frame_index);\n    __CHECK_ERROR(elem);\n    PyTuple_SET_ITEM(tuple, 4, elem);\n    elem = PyLong_FromSize_t(n_allocations);\n    __CHECK_ERROR(elem);\n    PyTuple_SET_ITEM(tuple, 5, elem);\n    elem = PyLong_FromSize_t(native_frame_id);\n    __CHECK_ERROR(elem);\n    PyTuple_SET_ITEM(tuple, 6, elem);\n    elem = PyLong_FromSize_t(native_segment_generation);\n    __CHECK_ERROR(elem);\n    PyTuple_SET_ITEM(tuple, 7, elem);\n#undef __CHECK_ERROR\n    return tuple;\n}\n\nAllocation\nAggregatedAllocation::contributionToHighWaterMark() const\n{\n    return {\n            tid,\n            0,\n            bytes_in_high_water_mark,\n            allocator,\n            native_frame_id,\n            frame_index,\n            native_segment_generation,\n            n_allocations_in_high_water_mark,\n    };\n}\n\nAllocation\nAggregatedAllocation::contributionToLeaks() const\n{\n    return {\n            tid,\n            0,\n            bytes_leaked,\n            allocator,\n            native_frame_id,\n            frame_index,\n            native_segment_generation,\n            n_allocations_leaked,\n    };\n}\n\nPyObject*\nLocation::toPythonObject(python_helpers::PyUnicode_Cache& pystring_cache) const\n{\n    PyObject* pyfunction_name = pystring_cache.getUnicodeObject(function_name);\n    if (pyfunction_name == nullptr) {\n        return nullptr;\n    }\n    PyObject* pyfilename = pystring_cache.getUnicodeObject(filename);\n    if (pyfilename == nullptr) {\n        return nullptr;\n    }\n    PyObject* pylineno = PyLong_FromLong(this->lineno);\n    if (pylineno == nullptr) {\n        return nullptr;\n    }\n    PyObject* tuple = PyTuple_New(3);\n    if (tuple == nullptr) {\n        Py_DECREF(pylineno);\n        return nullptr;\n    }\n    Py_INCREF(pyfunction_name);\n    Py_INCREF(pyfilename);\n    PyTuple_SET_ITEM(tuple, 0, pyfunction_name);\n    PyTuple_SET_ITEM(tuple, 1, pyfilename);\n    PyTuple_SET_ITEM(tuple, 2, pylineno);\n    return tuple;\n}\n\nPyObject*\nTrackedObject::toPythonObject() const\n{\n    PyObject* tuple = PyTuple_New(6);\n    if (tuple == nullptr) {\n        return nullptr;\n    }\n#define __CHECK_ERROR(elem)                                                                             \\\n    do {                                                                                                \\\n        if (elem == nullptr) {                                                                          \\\n            Py_DECREF(tuple);                                                                           \\\n            return nullptr;                                                                             \\\n        }                                                                                               \\\n    } while (0)\n    PyObject* elem = PyLong_FromLong(tid);\n    __CHECK_ERROR(elem);\n    PyTuple_SET_ITEM(tuple, 0, elem);\n\n    elem = PyLong_FromUnsignedLong(address);\n    __CHECK_ERROR(elem);\n    PyTuple_SET_ITEM(tuple, 1, elem);\n\n    PyObject* is_created_obj = is_created ? Py_True : Py_False;\n    Py_INCREF(is_created_obj);\n    PyTuple_SET_ITEM(tuple, 2, is_created_obj);\n\n    elem = PyLong_FromSize_t(frame_index);\n    __CHECK_ERROR(elem);\n    PyTuple_SET_ITEM(tuple, 3, elem);\n\n    elem = PyLong_FromSize_t(native_frame_id);\n    __CHECK_ERROR(elem);\n    PyTuple_SET_ITEM(tuple, 4, elem);\n\n    elem = PyLong_FromSize_t(native_segment_generation);\n    __CHECK_ERROR(elem);\n    PyTuple_SET_ITEM(tuple, 5, elem);\n#undef __CHECK_ERROR\n\n    return tuple;\n}\n}  // namespace memray::tracking_api\n"
  },
  {
    "path": "src/memray/_memray/records.h",
    "content": "#pragma once\n\n#define PY_SSIZE_T_CLEAN\n#include <Python.h>\n\n#include <fstream>\n#include <mutex>\n#include <stddef.h>\n#include <string>\n#include <tuple>\n#include <unordered_map>\n#include <utility>\n#include <vector>\n\n#include \"hooks.h\"\n#include \"python_helpers.h\"\n\nnamespace memray::tracking_api {\n\nextern const char MAGIC[7];  // Value assigned in records.cpp\nconst int CURRENT_HEADER_VERSION = 12;\n\nusing frame_id_t = size_t;\nusing thread_id_t = unsigned long;\nusing millis_t = long long;\nusing code_object_id_t = size_t;\n\n// If the high (128) bit is set on a given record type discriminator,\n// it's an ALLOCATION record with 7 bits available for flags (see\n// \"ALLOCATION ENCODING\" in record_writer.cpp for details).\n//\n// Otherwise, if the 64 bit is set, it's a FRAME_PUSH record with 6 bits\n// available for flags (see \"FRAME_PUSH ENCODING\" in record_writer.cpp).\n//\n// Otherwise, if the 16 bit is set, it's a FRAME_POP record with 4 bits\n// available for flags (see \"FRAME_POP ENCODING\" in record_writer.cpp).\n//\n// Otherwise, it's a record type that has no flags, and all remaining\n// bits identify the record type\nenum class RecordType : unsigned char {\n    FILLER = 0,\n    TRAILER = 1,\n    MEMORY_RECORD = 2,\n    NATIVE_TRACE_INDEX = 5,\n    MEMORY_MAP_START = 6,\n    SEGMENT_HEADER = 7,\n    SEGMENT = 8,\n    THREAD_RECORD = 10,\n    CONTEXT_SWITCH = 12,\n    CODE_OBJECT = 14,\n\n    FRAME_POP = 16,  // 16 through 31\n    OBJECT_RECORD = 32,  // 32 through 63\n    FRAME_PUSH = 64,  // 64 through 127\n    ALLOCATION = 128,  // 128 through 255\n};\n\n// Enumerators that have the same name as in RecordType are encoded the same\n// way and have the same enumeration value. Enumerators with different names\n// have different encoded representations.\nenum class AggregatedRecordType : unsigned char {\n    MEMORY_SNAPSHOT = 1,\n    AGGREGATED_ALLOCATION = 2,\n    PYTHON_TRACE_INDEX = 3,\n    PYTHON_FRAME_INDEX = 4,\n\n    NATIVE_TRACE_INDEX = 5,\n    MEMORY_MAP_START = 6,\n    SEGMENT_HEADER = 7,\n    SEGMENT = 8,\n    THREAD_RECORD = 10,\n    CONTEXT_SWITCH = 12,\n    SURVIVING_OBJECT = 13,\n    CODE_OBJECT = 14,\n\n    AGGREGATED_TRAILER = 15,\n};\n\nstruct TrackerStats\n{\n    size_t n_allocations{0};\n    size_t n_frames{0};\n    millis_t start_time{};\n    millis_t end_time{};\n};\n\nenum PythonAllocatorType : unsigned char {\n    PYTHONALLOCATOR_PYMALLOC = 1,\n    PYTHONALLOCATOR_PYMALLOC_DEBUG = 2,\n    PYTHONALLOCATOR_MALLOC = 3,\n    PYTHONALLOCATOR_OTHER = 4,\n    PYTHONALLOCATOR_MIMALLOC = 5,\n    PYTHONALLOCATOR_MIMALLOC_DEBUG = 6,\n};\n\nenum FileFormat : unsigned char {\n    ALL_ALLOCATIONS,\n    AGGREGATED_ALLOCATIONS,\n};\n\nstruct HeaderRecord\n{\n    char magic[sizeof(MAGIC)];\n    int version{};\n    int python_version{PY_VERSION_HEX};\n    bool native_traces{false};\n    FileFormat file_format{FileFormat::ALL_ALLOCATIONS};\n    TrackerStats stats{};\n    std::string command_line;\n    int pid{-1};\n    thread_id_t main_tid{};\n    size_t skipped_frames_on_main_tid{};\n    PythonAllocatorType python_allocator{};\n    bool trace_python_allocators{};\n    bool track_object_lifetimes{false};\n};\n\nstruct MemoryRecord\n{\n    uint64_t ms_since_epoch;\n    size_t rss;\n};\n\nstruct MemorySnapshot\n{\n    uint64_t ms_since_epoch;\n    size_t rss;\n    size_t heap;\n};\n\nstruct AllocationRecord\n{\n    uintptr_t address;\n    size_t size;\n    hooks::Allocator allocator;\n    frame_id_t native_frame_id{0};\n};\n\nstruct Allocation\n{\n    thread_id_t tid;\n    uintptr_t address;\n    size_t size;\n    hooks::Allocator allocator;\n    frame_id_t native_frame_id{0};\n    size_t frame_index{0};\n    size_t native_segment_generation{0};\n    size_t n_allocations{1};\n\n    PyObject* toPythonObject() const;\n};\n\nstruct TrackedObject\n{\n    thread_id_t tid;\n    uintptr_t address;\n    bool is_created;\n    frame_id_t native_frame_id{0};\n    size_t frame_index{0};\n    size_t native_segment_generation{0};\n\n    PyObject* toPythonObject() const;\n};\n\nstruct AggregatedAllocation\n{\n    thread_id_t tid;\n    hooks::Allocator allocator;\n    frame_id_t native_frame_id;\n    size_t frame_index;\n    size_t native_segment_generation;\n\n    size_t n_allocations_in_high_water_mark;\n    size_t n_allocations_leaked;\n    size_t bytes_in_high_water_mark;\n    size_t bytes_leaked;\n\n    Allocation contributionToHighWaterMark() const;\n    Allocation contributionToLeaks() const;\n};\n\nstruct MemoryMapStart\n{\n};\n\nstruct SegmentHeader\n{\n    const char* filename;\n    size_t num_segments;\n    uintptr_t addr;\n};\n\nstruct Segment\n{\n    uintptr_t vaddr;\n    uintptr_t memsz;\n};\n\nstruct ImageSegments\n{\n    std::string filename;\n    uintptr_t addr;\n    std::vector<Segment> segments;\n};\n\nstruct Frame\n{\n    code_object_id_t code_object_id;\n    int instruction_offset;\n    bool is_entry_frame;\n\n    auto operator==(const Frame& other) const -> bool\n    {\n        return (code_object_id == other.code_object_id && instruction_offset == other.instruction_offset\n                && is_entry_frame == other.is_entry_frame);\n    }\n\n    struct Hash\n    {\n        auto operator()(memray::tracking_api::Frame const& frame) const noexcept -> std::size_t\n        {\n            return std::hash<uint64_t>()(frame.code_object_id)\n                   ^ std::hash<int>()(frame.instruction_offset) ^ frame.is_entry_frame;\n        }\n    };\n};\n\nstruct Location\n{\n    std::string function_name;\n    std::string filename;\n    int lineno{0};\n\n    PyObject* toPythonObject(python_helpers::PyUnicode_Cache& pystring_cache) const;\n\n    auto operator==(const Location& other) const -> bool\n    {\n        return (function_name == other.function_name && filename == other.filename\n                && lineno == other.lineno);\n    }\n\n    struct Hash\n    {\n        auto operator()(const Location& location) const noexcept -> std::size_t\n        {\n            auto the_func = std::hash<std::string>{}(location.function_name);\n            auto the_filename = std::hash<std::string>{}(location.filename);\n            auto lineno = std::hash<int>{}(location.lineno);\n            return the_func ^ the_filename ^ lineno;\n        }\n    };\n};\n\n// For storing code object info with strings (used in reader)\nstruct CodeObjectInfo\n{\n    std::string function_name;\n    std::string filename;\n    std::string linetable;\n    int firstlineno;\n};\n\nusing pycode_map_val_t = std::pair<code_object_id_t, CodeObjectInfo>;\n\n// Structure to represent code object information\nstruct CodeObject\n{\n    const char* function_name;\n    const char* filename;\n    const char* linetable;\n    size_t linetable_size;\n    int firstlineno;\n};\n\nstruct RawFrame\n{\n    PyCodeObject* code;\n    CodeObject code_info;\n    bool is_entry_frame;\n    int instruction_offset;\n};\n\nstruct FramePush\n{\n    Frame frame;\n};\n\nstruct FramePop\n{\n    size_t count;\n};\n\nstruct UnresolvedNativeFrame\n{\n    uintptr_t ip;\n    size_t index;\n};\n\nstruct ContextSwitch\n{\n    thread_id_t tid;\n};\n\nstruct DeltaEncodedFields\n{\n    thread_id_t thread_id{};\n    uintptr_t instruction_pointer{};\n    uintptr_t data_pointer{};\n    frame_id_t native_frame_id{};\n    int code_firstlineno{};\n};\n\ntemplate<typename RecordType>\nclass Registry\n{\n  public:\n    using index_t = size_t;\n\n    size_t size() const\n    {\n        return d_record_by_id.size();\n    }\n\n    std::pair<index_t, bool> registerRecord(const RecordType& record)\n    {\n        auto [it, inserted] = d_id_by_record.emplace(record, d_record_by_id.size());\n        if (inserted) {\n            d_record_by_id.push_back(record);\n        }\n        return std::make_pair(it->second, inserted);\n    }\n\n    RecordType& getRecord(index_t index)\n    {\n        return d_record_by_id[index];\n    }\n\n    const RecordType& getRecord(index_t index) const\n    {\n        return d_record_by_id[index];\n    }\n\n  private:\n    std::unordered_map<RecordType, index_t, typename RecordType::Hash> d_id_by_record{};\n    std::vector<RecordType> d_record_by_id{};\n};\n\nstruct ThreadRecord\n{\n    const char* name;\n};\n\nstruct ObjectRecord\n{\n    uintptr_t address;  // Address of the PyObject*\n    bool is_created;  // true for creation, false for destruction\n    frame_id_t native_frame_id{0};  // Optional native frame id for backtraces\n};\n\n}  // namespace memray::tracking_api\n"
  },
  {
    "path": "src/memray/_memray/records.pxd",
    "content": "from _memray.hooks cimport Allocator\nfrom libc.stdint cimport uint64_t\nfrom libc.stdint cimport uintptr_t\nfrom libcpp cimport bool\nfrom libcpp.string cimport string\nfrom libcpp.vector cimport vector\n\n\ncdef extern from \"hooks.h\" namespace \"memray::hooks\":\n    cdef enum Allocator:\n        MALLOC \"memray::hooks::Allocator::MALLOC\"\n        CALLOC \"memray::hooks::Allocator::CALLOC\"\n        REALLOC \"memray::hooks::Allocator::REALLOC\"\n        VALLOC \"memray::hooks::Allocator::VALLOC\"\n        ALIGNED_ALLOC \"memray::hooks::Allocator::ALIGNED_ALLOC\"\n        POSIX_MEMALIGN \"memray::hooks::Allocator::POSIX_MEMALIGN\"\n        MEMALIGN \"memray::hooks::Allocator::MEMALIGN\"\n        PVALLOC \"memray::hooks::Allocator::PVALLOC\"\n        FREE \"memray::hooks::Allocator::FREE\"\n        PYMALLOC_MALLOC \"memray::hooks::Allocator::PYMALLOC_MALLOC\"\n        PYMALLOC_CALLOC \"memray::hooks::Allocator::PYMALLOC_CALLOC\"\n        PYMALLOC_REALLOC \"memray::hooks::Allocator::PYMALLOC_REALLOC\"\n        PYMALLOC_FREE \"memray::hooks::Allocator::PYMALLOC_FREE\"\n\ncdef extern from \"records.h\" namespace \"memray::tracking_api\":\n   ctypedef unsigned long thread_id_t\n   ctypedef size_t frame_id_t\n   ctypedef size_t code_object_id_t\n   ctypedef long long millis_t\n\n   struct CodeObjectInfo:\n       string function_name\n       string filename\n       string linetable\n       int firstlineno\n\n   struct AllocationRecord:\n       uintptr_t address\n       size_t size\n       Allocator allocator\n       frame_id_t native_frame_id\n\n   struct Frame:\n       code_object_id_t code_object_id\n       int instruction_offset\n       bool is_entry_frame\n\n   struct FramePush:\n       Frame frame\n\n   struct FramePop:\n       size_t count\n\n   struct ThreadRecord:\n       const char* name\n\n   struct Segment:\n       uintptr_t vaddr\n       size_t memsz\n\n   struct ImageSegments:\n       string filename\n       uintptr_t addr\n       vector[Segment] segments\n\n   struct UnresolvedNativeFrame:\n       uintptr_t ip\n       frame_id_t index\n\n   struct TrackerStats:\n       size_t n_allocations\n       size_t n_frames\n       long long start_time\n       long long end_time\n\n   cdef enum FileFormat:\n       ALL_ALLOCATIONS 'memray::tracking_api::FileFormat::ALL_ALLOCATIONS'\n       AGGREGATED_ALLOCATIONS 'memray::tracking_api::FileFormat::AGGREGATED_ALLOCATIONS'\n\n   struct HeaderRecord:\n       int version\n       bool native_traces\n       FileFormat file_format\n       TrackerStats stats\n       string command_line\n       int pid\n       size_t main_tid\n       size_t skipped_frames_on_main_tid\n       int python_allocator\n       bool trace_python_allocators\n       bool track_object_lifetimes\n\n   cdef cppclass Allocation:\n       thread_id_t tid\n       uintptr_t address\n       size_t size\n       Allocator allocator\n       frame_id_t native_frame_id\n       size_t frame_index\n       size_t native_segment_generation\n       size_t n_allocations\n\n       object toPythonObject()\n\n   cdef cppclass AggregatedAllocation:\n       thread_id_t tid\n       Allocator allocator\n       frame_id_t native_frame_id\n       size_t frame_index\n       size_t native_segment_generation\n\n       size_t n_allocations_in_high_water_mark\n       size_t n_allocations_leaked\n       size_t bytes_in_high_water_mark\n       size_t bytes_leaked\n\n       Allocation contributionToHighWaterMark()\n       Allocation contributionToLeaks()\n\n   struct MemoryRecord:\n       uint64_t ms_since_epoch\n       size_t rss\n\n   struct MemorySnapshot:\n       uint64_t ms_since_epoch\n       size_t rss\n       size_t heap\n\n   cdef cppclass TrackedObject:\n       thread_id_t tid\n       uintptr_t address\n       bool is_created\n       frame_id_t native_frame_id\n       size_t frame_index\n       size_t native_segment_generation\n\n       object toPythonObject()\n\n   cdef cppclass ObjectRecord:\n       uintptr_t address\n       bool is_created\n       frame_id_t native_frame_id\n\ncdef extern from \"<optional>\":\n   # Cython doesn't have libcpp.optional yet, so just declare this opaquely.\n   cdef cppclass optional_location_id_t \"std::optional<memray::api::location_id_t>\":\n       pass\n"
  },
  {
    "path": "src/memray/_memray/sink.cpp",
    "content": "#define PY_SSIZE_T_CLEAN\n#include <Python.h>\n\n#include <cerrno>\n#include <cstdio>\n\n#include <arpa/inet.h>\n#include <fcntl.h>\n#include <sys/mman.h>\n#include <sys/socket.h>\n#include <sys/types.h>\n#include <unistd.h>\n#include <utility>\n\n#include \"exceptions.h\"\n#include \"lz4_stream.h\"\n#include \"sink.h\"\n\nnamespace memray::io {\n\nusing namespace memray::exception;\n\nnamespace {  // unnamed\n\n#ifdef __APPLE__\nstatic int\nposix_fallocate(int fd, off_t offset, off_t len)\n{\n    fstore_t store = {F_ALLOCATEALL, F_PEOFPOSMODE, 0, len, 0};\n    int res = ::fcntl(fd, F_PREALLOCATE, &store);\n    if (res != 0) {\n        return errno;\n    }\n    do {\n        res = ::ftruncate(fd, offset + len);\n    } while (res != 0 && errno == EINTR);\n    if (res != 0) {\n        return errno;\n    }\n    return 0;\n}\n#endif\n\nstd::string\nremoveSuffix(const std::string& s, const std::string& suffix)\n{\n    if (s.size() < suffix.size()) {\n        return s;  // Too short to end with suffix.\n    }\n\n    if (0 != s.compare(s.size() - suffix.size(), std::string::npos, suffix)) {\n        return s;  // Long enough, but doesn't end with suffix.\n    }\n\n    return s.substr(0, s.size() - suffix.size());\n}\n\n}  // unnamed namespace\n\nbool\nFileSink::writeAll(const char* data, size_t length)\n{\n    // If the file isn't big enough for all this data, grow it.\n    size_t maxWritableWithoutGrowing = bytesBeyondBufferNeedle();\n    if (maxWritableWithoutGrowing < length) {\n        if (!grow(length - maxWritableWithoutGrowing)) {\n            return false;\n        }\n        assert(bytesBeyondBufferNeedle() >= length);\n    }\n\n    while (length) {\n        if (d_bufferNeedle == d_bufferEnd) {\n            // We've reached the end of our window. Slide it forward.\n            if (!seek(d_bufferOffset + (d_bufferEnd - d_buffer), SEEK_SET)) {\n                return false;\n            }\n        }\n\n        size_t available = d_bufferEnd - d_bufferNeedle;\n        size_t toCopy = std::min(available, length);\n        memcpy(d_bufferNeedle, data, toCopy);\n        d_bufferNeedle += toCopy;\n        data += toCopy;\n        length -= toCopy;\n    }\n    return true;\n}\n\nFileSink::FileSink(const std::string& file_name, bool overwrite, bool compress)\n: d_filename(file_name)\n, d_fileNameStem(removeSuffix(file_name, \".\" + std::to_string(::getpid())))\n, d_compress(compress)\n{\n    int flags = O_CREAT | O_RDWR | O_TRUNC | O_CLOEXEC;\n    if (!overwrite) {\n        flags |= O_EXCL;\n    }\n    do {\n        d_fd = ::open(file_name.c_str(), flags, 0644);\n    } while (d_fd < 0 && errno == EINTR);\n    if (d_fd < 0) {\n        throw IoError{\"Could not create output file \" + file_name + \": \" + std::string(strerror(errno))};\n    }\n}\n\nbool\nFileSink::seek(off_t offset, int whence)\n{\n    // Don't allow seeking relative to the current offset. We move the offset\n    // when we grow the file, and don't move it when we write, so users can't\n    // possibly know what the offset is.\n    if (whence != SEEK_SET && whence != SEEK_END) {\n        errno = EINVAL;\n        return false;\n    }\n\n    // Convert offset to an absolute position, if it isn't already\n    if (whence != SEEK_SET) {\n        offset = lseek(d_fd, offset, whence);\n    }\n\n    if (offset < 0) {\n        errno = EINVAL;\n        return false;\n    }\n\n    // Free our existing buffer, if any\n    if (d_buffer && 0 != munmap(d_buffer, BUFFER_SIZE)) {\n        return false;\n    }\n\n    // Note: It is OK to map beyond the end of the file,\n    //       though not to write beyond the end.\n    d_buffer = static_cast<char*>(mmap(d_buffer, BUFFER_SIZE, PROT_WRITE, MAP_SHARED, d_fd, offset));\n    if (d_buffer == MAP_FAILED) {\n        d_buffer = nullptr;\n        return false;\n    }\n    d_bufferNeedle = d_buffer;\n    d_bufferOffset = offset;\n\n    size_t bytesRemaining = d_fileSize - offset;\n    d_bufferEnd = d_buffer + std::min(bytesRemaining, BUFFER_SIZE);\n\n    return true;\n}\n\nbool\nFileSink::grow(size_t needed)\n{\n    static size_t pagesize = sysconf(_SC_PAGESIZE);\n    // Grow to next multiple of the page size that is strictly > 110% of current size + needed\n    size_t new_size = (d_fileSize + needed) * 1.1;\n    new_size = (new_size / pagesize + 1) * pagesize;\n    assert(new_size > d_fileSize);  // check for overflow\n\n    off_t delta = new_size - d_fileSize;\n    int rc;\n    do {\n        // posix_fallocate returns an error number instead of setting errno\n        rc = posix_fallocate(d_fd, d_fileSize, delta);\n    } while (rc == EINTR);\n\n    if (rc != 0) {\n        errno = rc;\n        return false;\n    }\n\n    d_fileSize = new_size;\n    assert(static_cast<off_t>(d_fileSize) == lseek(d_fd, 0, SEEK_END));\n\n    return true;\n}\n\nsize_t\nFileSink::bytesBeyondBufferNeedle()\n{\n    size_t bytesBeyondBuffer = d_fileSize - d_bufferOffset;\n    size_t positionWithinBuffer = d_bufferNeedle - d_buffer;\n    return bytesBeyondBuffer - positionWithinBuffer;\n}\n\nstd::unique_ptr<Sink>\nFileSink::cloneInChildProcess()\n{\n    std::string file_name = d_fileNameStem + \".\" + std::to_string(::getpid());\n    return std::make_unique<FileSink>(file_name, true, d_compress);\n}\n\nvoid\nFileSink::compress() noexcept\n{\n    std::ifstream in_file(d_filename);\n    std::string tmp_filename = d_filename + \".lz4.tmp\";\n    std::ofstream out_file(tmp_filename);\n    bool success = true;\n    constexpr size_t bufsize = 4 * 1024;\n\n    // lz4_stream is using exceptions rather than failbit/badbit\n    try {\n        lz4_stream::ostream lz4_stream(out_file);\n        std::vector<char> buf(bufsize);\n        while (in_file) {\n            in_file.read(&buf[0], buf.size());\n            lz4_stream.write(&buf[0], in_file.gcount());\n        }\n    } catch (...) {\n        success = false;\n    }\n\n    out_file.close();\n    if (!in_file.eof() || !out_file) {\n        success = false;\n    }\n\n    if (!success) {\n        std::cerr << \"Failed to compress input file\" << std::endl;\n        ::unlink(tmp_filename.c_str());\n    } else if (0 != std::rename(tmp_filename.c_str(), d_filename.c_str())) {\n        std::perror(\"Error moving compressed file back to original name\");\n        ::unlink(tmp_filename.c_str());\n    }\n}\n\nFileSink::~FileSink()\n{\n    if (d_buffer) {\n        if (0 != munmap(d_buffer, BUFFER_SIZE)) {\n            LOG(ERROR) << \"Failed to unmap output file: \" << strerror(errno);\n        }\n        d_buffer = d_bufferNeedle = d_bufferEnd = nullptr;\n    }\n    if (d_fd != -1) {\n        ::close(d_fd);\n    }\n\n    if (d_compress) {\n        compress();\n    }\n}\n\nSocketSink::SocketSink(std::string host, uint16_t port)\n: d_host(std::move(host))\n, d_port(port)\n, d_buffer(new char[BUFFER_SIZE])\n, d_bufferNeedle(d_buffer.get())\n{\n    open();\n}\n\nsize_t\nSocketSink::freeSpaceInBuffer()\n{\n    return BUFFER_SIZE - (d_bufferNeedle - d_buffer.get());\n}\n\nbool\nSocketSink::writeAll(const char* data, size_t length)\n{\n    while (freeSpaceInBuffer() < length) {\n        size_t toWrite = freeSpaceInBuffer();\n        memcpy(d_bufferNeedle, data, toWrite);\n        d_bufferNeedle += toWrite;\n        data += toWrite;\n        length -= toWrite;\n        if (!flush()) {\n            return false;\n        }\n    }\n\n    memcpy(d_bufferNeedle, data, length);\n    d_bufferNeedle += length;\n    return true;\n}\n\nbool\nSocketSink::flush()\n{\n    return _flush();\n}\n\nbool\nSocketSink::_flush()\n{\n    const char* data = d_buffer.get();\n    size_t length = d_bufferNeedle - data;\n\n    d_bufferNeedle = d_buffer.get();\n\n    while (length) {\n        ssize_t ret = ::send(d_socket_fd, data, length, 0);\n        if (ret < 0 && errno != EINTR) {\n            return false;\n        } else if (ret >= 0) {\n            data += ret;\n            length -= ret;\n        }\n    }\n    return true;\n}\n\nbool\nSocketSink::seek(__attribute__((unused)) off_t offset, __attribute__((unused)) int whence)\n{\n    return false;\n}\n\nstd::unique_ptr<Sink>\nSocketSink::cloneInChildProcess()\n{\n    // We can't clone ourselves. We can't start a new TCP stream and block\n    // waiting for a client, and we can't create a new sink that shares the\n    // same socket because the client would see writes from all processes\n    // interleaved.\n    return {};\n}\n\nSocketSink::~SocketSink()\n{\n    if (d_socket_open) {\n        _flush();\n        ::close(d_socket_fd);\n        d_socket_open = false;\n    }\n}\n\nvoid\nSocketSink::open()\n{\n    int sockfd;\n    struct sockaddr_storage their_addr;\n    socklen_t sin_size;\n    int yes = 1;\n\n    sockaddr_in si;\n    si.sin_family = AF_INET;\n    si.sin_addr.s_addr = ::inet_addr(d_host.c_str());\n    si.sin_port = htons(d_port);\n\n    if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) {\n        LOG(ERROR) << \"Encountered error in 'socket' call: \" << strerror(errno);\n        throw IoError{\"Failed to open socket\"};\n    }\n\n    if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {\n        ::close(sockfd);\n        LOG(ERROR) << \"Encountered error in 'setsockopt' call: \" << strerror(errno);\n        throw IoError{\"Failed to set socket options\"};\n    }\n\n    if (bind(sockfd, (sockaddr*)&si, sizeof si) == -1) {\n        ::close(sockfd);\n        LOG(WARNING) << \"Encountered error in 'bind' call: \" << strerror(errno);\n        throw IoError{\"Failed to bind to host and port\"};\n    }\n\n    if (listen(sockfd, 1) == -1) {\n        ::close(sockfd);\n        throw IoError{\"Encountered error in listen call\"};\n    }\n\n    LOG(DEBUG) << \"Waiting for connections\";\n    sin_size = sizeof their_addr;\n\n    bool async_err = false;\n    do {\n        Py_BEGIN_ALLOW_THREADS;\n        d_socket_fd = accept(sockfd, (struct sockaddr*)&their_addr, &sin_size);\n        Py_END_ALLOW_THREADS;\n    } while (d_socket_fd != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));\n    ::close(sockfd);\n\n    if (async_err) {\n        return;\n    }\n\n    if (d_socket_fd == -1) {\n        LOG(ERROR) << \"Encountered error in 'accept' call: \" << strerror(errno);\n        throw IoError{strerror(errno)};\n    }\n\n    d_socket_open = true;\n}\n\nNullSink::~NullSink()\n{\n}\n\nbool\nNullSink::writeAll(const char*, size_t)\n{\n    return true;\n}\n\nbool\nNullSink::seek(off_t, int)\n{\n    return true;\n}\n\nstd::unique_ptr<Sink>\nNullSink::cloneInChildProcess()\n{\n    return std::make_unique<NullSink>();\n}\n\n}  // namespace memray::io\n"
  },
  {
    "path": "src/memray/_memray/sink.h",
    "content": "#pragma once\n\n#include <cerrno>\n#include <memory>\n#include <string>\n#include <unistd.h>\n\n#include \"records.h\"\n\nnamespace memray::io {\n\nclass Sink\n{\n  public:\n    virtual ~Sink(){};\n    virtual bool writeAll(const char* data, size_t length) = 0;\n    virtual bool seek(off_t offset, int whence) = 0;\n    virtual std::unique_ptr<Sink> cloneInChildProcess() = 0;\n    virtual bool flush()\n    {\n        return true;\n    }\n};\n\nclass FileSink : public memray::io::Sink\n{\n  public:\n    FileSink(const std::string& file_name, bool overwrite, bool compress);\n    ~FileSink() override;\n    FileSink(FileSink&) = delete;\n    FileSink(FileSink&&) = delete;\n    void operator=(const FileSink&) = delete;\n    void operator=(const FileSink&&) = delete;\n\n    bool writeAll(const char* data, size_t length) override;\n    bool seek(off_t offset, int whence) override;\n    std::unique_ptr<Sink> cloneInChildProcess() override;\n\n  private:\n    void compress() noexcept;\n    bool grow(size_t needed);\n    bool slideWindow();\n    size_t bytesBeyondBufferNeedle();\n\n    std::string d_filename;\n    std::string d_fileNameStem;\n    bool d_compress{1};\n    int d_fd{-1};\n    size_t d_fileSize{0};\n    const size_t BUFFER_SIZE{16 * 1024 * 1024};  // 16 MiB\n    size_t d_bufferOffset{0};\n    char* d_buffer{nullptr};\n    char* d_bufferEnd{nullptr};  // exclusive\n    char* d_bufferNeedle{nullptr};\n};\n\nclass SocketSink : public Sink\n{\n  public:\n    explicit SocketSink(std::string host, uint16_t port);\n    ~SocketSink() override;\n\n    SocketSink(SocketSink&) = delete;\n    SocketSink(SocketSink&&) = delete;\n    void operator=(const SocketSink&) = delete;\n    void operator=(const SocketSink&&) = delete;\n\n    bool writeAll(const char* data, size_t length) override;\n    bool seek(off_t offset, int whence) override;\n    std::unique_ptr<Sink> cloneInChildProcess() override;\n    bool flush() override;\n\n  private:\n    size_t freeSpaceInBuffer();\n    void open();\n    bool _flush();\n\n    const std::string d_host;\n    uint16_t d_port;\n    int d_socket_fd{-1};\n    bool d_socket_open{false};\n\n    const size_t BUFFER_SIZE{PIPE_BUF};\n    std::unique_ptr<char[]> d_buffer{nullptr};\n    char* d_bufferNeedle{nullptr};\n};\n\nclass NullSink : public Sink\n{\n  public:\n    ~NullSink() override;\n    bool writeAll(const char* data, size_t length) override;\n    bool seek(off_t offset, int whence) override;\n    std::unique_ptr<Sink> cloneInChildProcess() override;\n};\n\n}  // namespace memray::io\n"
  },
  {
    "path": "src/memray/_memray/sink.pxd",
    "content": "from libc.stdint cimport int16_t\nfrom libcpp cimport bool\nfrom libcpp.string cimport string\n\n\ncdef extern from \"sink.h\" namespace \"memray::io\":\n    cdef cppclass Sink:\n        pass\n\n    cdef cppclass FileSink(Sink):\n        FileSink(const string& file_name, bool overwrite, bool compress) except +IOError\n\n    cdef cppclass SocketSink(Sink):\n        SocketSink(string host, unsigned int port) except +IOError\n\n    cdef cppclass NullSink(Sink):\n        NullSink() except +IOError\n"
  },
  {
    "path": "src/memray/_memray/snapshot.cpp",
    "content": "#include \"snapshot.h\"\n\n#include <numeric>\n#include <unordered_set>\n\nnamespace memray::api {\n\nbool\nLocationKey::operator==(const LocationKey& rhs) const\n{\n    return python_frame_id == rhs.python_frame_id && native_frame_id == rhs.native_frame_id\n           && thread_id == rhs.thread_id;\n}\n\nbool\nHighWaterMarkLocationKey::operator==(const HighWaterMarkLocationKey& rhs) const\n{\n    return thread_id == rhs.thread_id && python_frame_id == rhs.python_frame_id\n           && native_frame_id == rhs.native_frame_id\n           && native_segment_generation == rhs.native_segment_generation && allocator == rhs.allocator;\n}\n\nbool\nHighWaterMarkLocationKey::operator!=(const HighWaterMarkLocationKey& rhs) const\n{\n    return !(*this == rhs);\n}\n\nbool\nHighWaterMarkLocationKey::operator<(const HighWaterMarkLocationKey& rhs) const\n{\n    if (thread_id != rhs.thread_id) {\n        return thread_id < rhs.thread_id;\n    } else if (python_frame_id != rhs.python_frame_id) {\n        return python_frame_id < rhs.python_frame_id;\n    } else if (native_frame_id != rhs.native_frame_id) {\n        return native_frame_id < rhs.native_frame_id;\n    } else if (native_segment_generation != rhs.native_segment_generation) {\n        return native_segment_generation < rhs.native_segment_generation;\n    } else if (allocator != rhs.allocator) {\n        return allocator < rhs.allocator;\n    }\n    return false;\n}\n\nbool\noperator<(const AllocationLifetime& lhs, const AllocationLifetime& rhs)\n{\n    // Sort first by location, then allocatedBefore, then deallocatedBefore.\n    // Sort by n_bytes if allocatedBefore/deallocatedBefore are equal,\n    // so that our test suite gets records in a predictable order.\n    if (lhs.key != rhs.key) {\n        return lhs.key < rhs.key;\n    } else if (lhs.allocatedBeforeSnapshot != rhs.allocatedBeforeSnapshot) {\n        return lhs.allocatedBeforeSnapshot < rhs.allocatedBeforeSnapshot;\n    } else if (lhs.deallocatedBeforeSnapshot != rhs.deallocatedBeforeSnapshot) {\n        return lhs.deallocatedBeforeSnapshot < rhs.deallocatedBeforeSnapshot;\n    } else {\n        return lhs.n_bytes < rhs.n_bytes;\n    }\n}\n\nInterval::Interval(uintptr_t begin, uintptr_t end)\n: begin(begin)\n, end(end)\n{\n}\n\nstd::optional<Interval>\nInterval::intersection(const Interval& other) const\n{\n    auto max_start = std::max(begin, other.begin);\n    auto min_end = std::min(end, other.end);\n    if (min_end <= max_start) {\n        return std::nullopt;\n    } else {\n        return Interval(max_start, min_end);\n    }\n}\n\nsize_t\nInterval::size() const\n{\n    return end - begin;\n}\n\nbool\nInterval::operator==(const Interval& rhs) const\n{\n    return begin == rhs.begin && end == rhs.end;\n}\n\nbool\nInterval::operator!=(const Interval& rhs) const\n{\n    return !(rhs == *this);\n}\n\nbool\nInterval::leftIntersects(const Interval& other) const\n{\n    return (begin == other.begin) && (end < other.end);\n}\n\nbool\nInterval::rightIntersects(const Interval& other) const\n{\n    return (begin > other.begin) && (end == other.end);\n}\n\nvoid\nSnapshotAllocationAggregator::addAllocation(const Allocation& allocation)\n{\n    switch (hooks::allocatorKind(allocation.allocator)) {\n        case hooks::AllocatorKind::SIMPLE_ALLOCATOR: {\n            d_ptr_to_allocation[allocation.address] = allocation;\n            break;\n        }\n        case hooks::AllocatorKind::SIMPLE_DEALLOCATOR: {\n            auto it = d_ptr_to_allocation.find(allocation.address);\n            if (it != d_ptr_to_allocation.end()) {\n                d_ptr_to_allocation.erase(it);\n            }\n            break;\n        }\n        case hooks::AllocatorKind::RANGED_ALLOCATOR: {\n            d_interval_tree.addInterval(allocation.address, allocation.size, allocation);\n            break;\n        }\n        case hooks::AllocatorKind::RANGED_DEALLOCATOR: {\n            d_interval_tree.removeInterval(allocation.address, allocation.size);\n            break;\n        }\n    }\n    d_index++;\n}\n\nreduced_snapshot_map_t\nSnapshotAllocationAggregator::getSnapshotAllocations(bool merge_threads)\n{\n    reduced_snapshot_map_t stack_to_allocation{};\n\n    for (const auto& it : d_ptr_to_allocation) {\n        const Allocation& record = it.second;\n        const thread_id_t thread_id = merge_threads ? NO_THREAD_INFO : record.tid;\n        auto loc_key = LocationKey{record.frame_index, record.native_frame_id, thread_id};\n        auto alloc_it = stack_to_allocation.find(loc_key);\n        if (alloc_it == stack_to_allocation.end()) {\n            stack_to_allocation.insert(alloc_it, std::pair(loc_key, record));\n        } else {\n            alloc_it->second.size += record.size;\n            alloc_it->second.n_allocations += 1;\n        }\n    }\n\n    // Process ranged allocations. As there can be partial deallocations in mmap'd regions,\n    // we update the allocation to reflect the actual size at the peak, based on the lengths\n    // of the ranges in the interval tree.\n    for (const auto& [range, allocation] : d_interval_tree) {\n        const thread_id_t thread_id = merge_threads ? NO_THREAD_INFO : allocation.tid;\n        auto loc_key = LocationKey{allocation.frame_index, allocation.native_frame_id, thread_id};\n        auto alloc_it = stack_to_allocation.find(loc_key);\n        if (alloc_it == stack_to_allocation.end()) {\n            Allocation new_alloc = allocation;\n            new_alloc.size = range.size();\n            stack_to_allocation.insert(alloc_it, std::pair(loc_key, new_alloc));\n        } else {\n            alloc_it->second.size += range.size();\n            alloc_it->second.n_allocations += 1;\n        }\n    }\n\n    return stack_to_allocation;\n}\n\nTemporaryAllocationsAggregator::TemporaryAllocationsAggregator(size_t max_items)\n: d_max_items(max_items)\n{\n}\n\nvoid\nTemporaryAllocationsAggregator::addAllocation(const Allocation& allocation)\n{\n    hooks::AllocatorKind kind = hooks::allocatorKind(allocation.allocator);\n    auto it = d_current_allocations.find(allocation.tid);\n    switch (kind) {\n        case hooks::AllocatorKind::SIMPLE_ALLOCATOR:\n        case hooks::AllocatorKind::RANGED_ALLOCATOR: {\n            if (it == d_current_allocations.end()) {\n                it = d_current_allocations.insert(\n                        it,\n                        std::pair(allocation.tid, std::deque<Allocation>()));\n            }\n\n            it->second.emplace_front(allocation);\n            if (it->second.size() > d_max_items) {\n                it->second.pop_back();\n            }\n            break;\n        }\n        case hooks::AllocatorKind::SIMPLE_DEALLOCATOR:\n        case hooks::AllocatorKind::RANGED_DEALLOCATOR: {\n            if (it == d_current_allocations.end()) {\n                break;\n            }\n\n            auto alloc_it =\n                    std::find_if(it->second.begin(), it->second.end(), [&](auto& current_allocation) {\n                        bool match = (current_allocation.address == allocation.address);\n                        if (kind == hooks::AllocatorKind::RANGED_DEALLOCATOR) {\n                            match = match && (current_allocation.size == allocation.size);\n                        }\n                        return match;\n                    });\n\n            if (alloc_it != it->second.end()) {\n                d_temporary_allocations.push_back(*alloc_it);\n            }\n            break;\n        }\n    }\n}\n\nreduced_snapshot_map_t\nTemporaryAllocationsAggregator::getSnapshotAllocations(bool merge_threads)\n{\n    reduced_snapshot_map_t stack_to_allocation{};\n\n    for (const auto& record : d_temporary_allocations) {\n        const thread_id_t thread_id = merge_threads ? NO_THREAD_INFO : record.tid;\n        auto loc_key = LocationKey{record.frame_index, record.native_frame_id, thread_id};\n        auto alloc_it = stack_to_allocation.find(loc_key);\n        if (alloc_it == stack_to_allocation.end()) {\n            stack_to_allocation.insert(alloc_it, std::pair(loc_key, record));\n        } else {\n            alloc_it->second.size += record.size;\n            alloc_it->second.n_allocations += 1;\n        }\n    }\n\n    return stack_to_allocation;\n}\n\nvoid\nAggregatedCaptureReaggregator::addAllocation(const Allocation& allocation)\n{\n    // Store a list of pre-aggregated leaked or high water mark allocations.\n    assert(!hooks::isDeallocator(allocation.allocator));\n    assert(0 == allocation.address);\n\n    if (allocation.n_allocations != 0) {\n        d_allocations.push_back(allocation);\n    }\n}\n\nreduced_snapshot_map_t\nAggregatedCaptureReaggregator::getSnapshotAllocations(bool merge_threads)\n{\n    // Spit them back out, possibly with threads merged.\n    reduced_snapshot_map_t stack_to_allocation{};\n\n    for (const auto& record : d_allocations) {\n        const thread_id_t thread_id = merge_threads ? NO_THREAD_INFO : record.tid;\n        auto loc_key = LocationKey{record.frame_index, record.native_frame_id, thread_id};\n        auto alloc_it = stack_to_allocation.find(loc_key);\n        if (alloc_it == stack_to_allocation.end()) {\n            stack_to_allocation.insert(alloc_it, std::pair(loc_key, record));\n        } else {\n            alloc_it->second.size += record.size;\n            alloc_it->second.n_allocations += 1;\n        }\n    }\n\n    return stack_to_allocation;\n}\n\nbool\noperator==(const Contribution& lhs, const Contribution& rhs)\n{\n    return lhs.allocations == rhs.allocations && lhs.bytes == rhs.bytes;\n}\n\nbool\noperator!=(const Contribution& lhs, const Contribution& rhs)\n{\n    return !(lhs == rhs);\n}\n\nUsageHistory&\nHighWaterMarkAggregator::getUsageHistory(const Allocation& allocation)\n{\n    HighWaterMarkLocationKey loc_key{\n            allocation.tid,\n            allocation.frame_index,\n            allocation.native_frame_id,\n            allocation.native_segment_generation,\n            allocation.allocator};\n\n    auto it = d_usage_history_by_location.find(loc_key);\n    if (it == d_usage_history_by_location.end()) {\n        assert(!hooks::isDeallocator(allocation.allocator));\n        it = d_usage_history_by_location.emplace(loc_key, UsageHistory{}).first;\n    }\n    return it->second;\n}\n\nvoid\nUsageHistory::UsageHistoryImpl::rebase(size_t new_peak)\n{\n    if (last_known_peak != new_peak) {\n        assert(last_known_peak < new_peak);  // we can only move forward.\n        // Any deltas since the last peak are part of the new one.\n        allocations_contributed_to_last_known_peak += count_since_last_peak;\n        bytes_contributed_to_last_known_peak += bytes_since_last_peak;\n\n        count_since_last_peak = 0;\n        bytes_since_last_peak = 0;\n\n        last_known_peak = new_peak;\n    }\n}\n\nUsageHistory::UsageHistoryImpl\nUsageHistory::recordContributionsToCompletedSnapshots(\n        const std::vector<size_t>& highest_peak_by_snapshot,\n        std::vector<HistoricalContribution>& heap_contribution_by_snapshot) const\n{\n    size_t current_snapshot = highest_peak_by_snapshot.size();\n    auto history = d_history;\n\n    // If any snapshots have completed since this location's last allocation\n    // or deallocation, we need to record the final amount we contributed to\n    // their HWMs in `heap_contribution_by_snapshot`. This loop will fire:\n    // - 0 times if no snapshots are newly completed.\n    // - 1 time if only 1 snapshot is newly completed.\n    // - 1 time if more than 1 snapshot is newly completed but we contributed\n    //   the same amount to the HWM of each of them.\n    // - 2 times if at least 2 snapshots are newly completed and we contributed\n    //   different amounts to the HWM of the first than the rest. This means we\n    //   had (de)allocations during the first snapshot but after its HWM, which\n    //   we need to record as contributions to the HWM of the rest.\n    while (history.last_known_snapshot != current_snapshot) {\n        assert(history.last_known_snapshot < current_snapshot);\n        size_t last_snapshot_peak = highest_peak_by_snapshot.at(history.last_known_snapshot);\n        history.rebase(last_snapshot_peak);\n\n        HistoricalContribution hc{\n                history.last_known_snapshot,\n                last_snapshot_peak,\n                {history.bytes_contributed_to_last_known_peak,\n                 history.allocations_contributed_to_last_known_peak}};\n\n        bool changed;\n        if (!heap_contribution_by_snapshot.empty()) {\n            // See if the amount contributed has changed since the last record.\n            changed = heap_contribution_by_snapshot.back().contrib != hc.contrib;\n        } else {\n            // An empty vector implicitly no contributed bytes/allocations.\n            changed = Contribution{0, 0} != hc.contrib;\n        }\n\n        if (changed) {\n            // Only record amounts that differ from the last recorded amount.\n            // We represent \"runs\" of the same value implicitly.\n            heap_contribution_by_snapshot.push_back(hc);\n        }\n\n        if (history.count_since_last_peak) {\n            history.last_known_snapshot++;\n        } else {\n            history.last_known_snapshot = current_snapshot;\n        }\n    }\n    return history;\n}\n\nvoid\nUsageHistory::recordUsageDelta(\n        const std::vector<size_t>& highest_peak_by_snapshot,\n        size_t current_peak,\n        size_t count_delta,\n        size_t bytes_delta)\n{\n    size_t current_snapshot = highest_peak_by_snapshot.size();\n    if (d_history.last_known_snapshot < current_snapshot) {\n        d_history = recordContributionsToCompletedSnapshots(\n                highest_peak_by_snapshot,\n                d_heap_contribution_by_snapshot);\n    }\n\n    if (d_history.last_known_peak != current_peak) {\n        d_history.rebase(current_peak);\n    }\n\n    d_history.count_since_last_peak += count_delta;\n    d_history.bytes_since_last_peak += bytes_delta;\n}\n\nContribution\nUsageHistory::highWaterMarkContribution(size_t highest_peak) const\n{\n    // If the highest peak was in a snapshot we've already moved past, return\n    // our last contribution to a peak <= highest_peak, or an empty\n    // contribution if no allocations occurred here before that highest peak.\n    if (highest_peak < d_history.last_known_peak) {\n        auto it = std::lower_bound(\n                d_heap_contribution_by_snapshot.rbegin(),\n                d_heap_contribution_by_snapshot.rend(),\n                highest_peak,\n                [](const HistoricalContribution& hc, size_t highest_peak) {\n                    return hc.peak_index > highest_peak;\n                });\n        if (it == d_heap_contribution_by_snapshot.rend()) {\n            return {0, 0};\n        }\n        return it->contrib;\n    }\n\n    auto total = d_history;\n    total.rebase(highest_peak);\n    Contribution ret;\n    ret.bytes = total.bytes_contributed_to_last_known_peak;\n    ret.allocations = total.allocations_contributed_to_last_known_peak;\n    return ret;\n}\n\nContribution\nUsageHistory::leaksContribution() const\n{\n    Contribution ret;\n    ret.bytes = d_history.bytes_contributed_to_last_known_peak + d_history.bytes_since_last_peak;\n    ret.allocations =\n            d_history.allocations_contributed_to_last_known_peak + d_history.count_since_last_peak;\n    return ret;\n}\n\nstd::vector<HistoricalContribution>\nUsageHistory::contributionsBySnapshot(\n        const std::vector<size_t>& highest_peak_by_snapshot,\n        size_t current_peak) const\n{\n    size_t current_snapshot = highest_peak_by_snapshot.size();\n    auto ret = d_heap_contribution_by_snapshot;\n\n    auto final = d_history;\n    if (final.last_known_snapshot < current_snapshot) {\n        final = recordContributionsToCompletedSnapshots(highest_peak_by_snapshot, ret);\n    }\n\n    if (final.last_known_peak != current_peak) {\n        final.rebase(current_peak);\n    }\n    final.last_known_snapshot = current_snapshot;\n\n    Contribution hwm{\n            final.bytes_contributed_to_last_known_peak,\n            final.allocations_contributed_to_last_known_peak};\n\n    Contribution leaks = hwm;\n    leaks.allocations += final.count_since_last_peak;\n    leaks.bytes += final.bytes_since_last_peak;\n\n    if (ret.empty() || ret.back().contrib != hwm) {\n        ret.emplace_back(HistoricalContribution{final.last_known_snapshot, current_peak, hwm});\n    }\n\n    if (ret.empty() || ret.back().contrib != leaks) {\n        ret.emplace_back(\n                HistoricalContribution{final.last_known_snapshot + 1, static_cast<size_t>(-1), leaks});\n    }\n\n    return ret;\n}\n\nvoid\nHighWaterMarkAggregator::recordUsageDelta(\n        const Allocation& allocation,\n        size_t count_delta,\n        size_t bytes_delta)\n{\n    size_t new_heap_size = d_current_heap_size + bytes_delta;\n    if (d_current_heap_size >= d_heap_size_at_last_peak && new_heap_size < d_current_heap_size) {\n        // This is the falling edge of a peak we haven't yet recorded.\n        d_peak_count += 1;\n        d_heap_size_at_last_peak = d_current_heap_size;\n    }\n    d_current_heap_size = new_heap_size;\n\n    auto& history = getUsageHistory(allocation);\n    history.recordUsageDelta(\n            d_high_water_mark_index_by_snapshot,\n            d_peak_count,\n            count_delta,\n            bytes_delta);\n}\n\nvoid\nHighWaterMarkAggregator::addAllocation(const Allocation& allocation_or_deallocation)\n{\n    // Note: Deallocation records don't tell us where the memory was allocated,\n    //       so we need to save the records for allocations and cross-reference\n    //       deallocations against them.\n    switch (hooks::allocatorKind(allocation_or_deallocation.allocator)) {\n        case hooks::AllocatorKind::SIMPLE_ALLOCATOR: {\n            const Allocation& allocation = allocation_or_deallocation;\n            recordUsageDelta(allocation, 1, allocation.size);\n            d_ptr_to_allocation[allocation.address] = allocation;\n            break;\n        }\n        case hooks::AllocatorKind::SIMPLE_DEALLOCATOR: {\n            const Allocation& deallocation = allocation_or_deallocation;\n            auto it = d_ptr_to_allocation.find(deallocation.address);\n            if (it != d_ptr_to_allocation.end()) {\n                const Allocation& allocation = it->second;\n                recordUsageDelta(allocation, -1, -allocation.size);\n                d_ptr_to_allocation.erase(it);\n            }\n            break;\n        }\n        case hooks::AllocatorKind::RANGED_ALLOCATOR: {\n            const Allocation& allocation = allocation_or_deallocation;\n            recordUsageDelta(allocation, 1, allocation.size);\n            d_mmap_intervals.addInterval(allocation.address, allocation.size, allocation);\n            break;\n        }\n        case hooks::AllocatorKind::RANGED_DEALLOCATOR: {\n            const Allocation& deallocation = allocation_or_deallocation;\n            auto removal_stats =\n                    d_mmap_intervals.removeInterval(deallocation.address, deallocation.size);\n            for (const auto& [interval, allocation] : removal_stats.freed_allocations) {\n                recordUsageDelta(allocation, -1, -interval.size());\n            }\n            for (const auto& [interval, allocation] : removal_stats.shrunk_allocations) {\n                recordUsageDelta(allocation, 0, -interval.size());\n            }\n            for (const auto& [interval, allocation] : removal_stats.split_allocations) {\n                recordUsageDelta(allocation, 1, -interval.size());\n            }\n            break;\n        }\n    }\n}\n\nvoid\nHighWaterMarkAggregator::captureSnapshot()\n{\n    if (d_current_heap_size >= d_heap_size_at_last_peak) {\n        // We're currently on the rising edge of a new peak.\n        d_high_water_mark_index_by_snapshot.push_back(d_peak_count + 1);\n        d_high_water_mark_bytes_by_snapshot.push_back(d_current_heap_size);\n    } else {\n        d_high_water_mark_index_by_snapshot.push_back(d_peak_count);\n        d_high_water_mark_bytes_by_snapshot.push_back(d_heap_size_at_last_peak);\n    }\n\n    // Count the start of a snapshot as a \"peak\", even though heap utilization\n    // may in fact be lower than at a previous peak.\n    d_peak_count++;\n    d_heap_size_at_last_peak = d_current_heap_size;\n}\n\nsize_t\nHighWaterMarkAggregator::getCurrentHeapSize() const noexcept\n{\n    return d_current_heap_size;\n}\n\nstd::vector<size_t>\nHighWaterMarkAggregator::highWaterMarkBytesBySnapshot() const\n{\n    auto ret = d_high_water_mark_bytes_by_snapshot;\n    ret.push_back(d_heap_size_at_last_peak);\n    return ret;\n}\n\nHighWaterMarkAggregator::Index\nHighWaterMarkAggregator::generateIndex() const\n{\n    std::vector<AllocationLifetime> index;\n\n    uint64_t final_peak_count = d_peak_count;\n    if (d_current_heap_size >= d_heap_size_at_last_peak) {\n        // We're currently at a new peak that we haven't yet fallen from.\n        final_peak_count++;\n    }\n\n    for (const auto& [location, history] : d_usage_history_by_location) {\n        auto contribs =\n                history.contributionsBySnapshot(d_high_water_mark_index_by_snapshot, final_peak_count);\n\n        // Loop over all but the last historical contribution.\n        for (size_t i = 0; i + 1 < contribs.size(); ++i) {\n            auto& curr = contribs[i];\n            auto& next = contribs[i + 1];\n\n            index.emplace_back(AllocationLifetime{\n                    curr.as_of_snapshot,\n                    next.as_of_snapshot,\n                    location,\n                    curr.contrib.allocations,\n                    curr.contrib.bytes});\n        }\n\n        if (!contribs.empty()) {\n            // The last one is special because there's no end snapshot.\n            auto& curr = contribs.back();\n\n            index.emplace_back(AllocationLifetime{\n                    curr.as_of_snapshot,\n                    static_cast<size_t>(-1),\n                    location,\n                    curr.contrib.allocations,\n                    curr.contrib.bytes});\n        }\n    }\n\n    // Finally, sort the vector we're returning, so that our callers can count\n    // on all intervals for a given location being contiguous.\n    std::sort(index.begin(), index.end());\n    return index;\n}\n\nbool\nHighWaterMarkAggregator::visitAllocations(const allocation_callback_t& callback) const\n{\n    // Find true peak: max(highest snapshot peak, latest peak, current usage)\n    uint64_t final_peak_count = 0;\n    uint64_t final_peak_bytes = 0;\n    for (size_t i = 0; i < d_high_water_mark_index_by_snapshot.size(); ++i) {\n        if (d_high_water_mark_bytes_by_snapshot[i] > final_peak_bytes) {\n            final_peak_bytes = d_high_water_mark_bytes_by_snapshot[i];\n            final_peak_count = d_high_water_mark_index_by_snapshot[i];\n        }\n    }\n\n    if (d_heap_size_at_last_peak > final_peak_bytes) {\n        final_peak_count = d_peak_count;\n        final_peak_bytes = d_heap_size_at_last_peak;\n    }\n\n    if (d_current_heap_size >= final_peak_bytes) {\n        // We're currently at a new peak that we haven't yet fallen from.\n        final_peak_count = d_peak_count + 1;\n        final_peak_bytes = d_current_heap_size;\n    }\n\n    return std::all_of(\n            d_usage_history_by_location.begin(),\n            d_usage_history_by_location.end(),\n            [&](const auto& entry) {\n                const auto& [loc, usage] = entry;\n                Contribution hwm = usage.highWaterMarkContribution(final_peak_count);\n                Contribution leaks = usage.leaksContribution();\n                AggregatedAllocation alloc{\n                        loc.thread_id,\n                        loc.allocator,\n                        loc.native_frame_id,\n                        loc.python_frame_id,\n                        loc.native_segment_generation,\n                        hwm.allocations,\n                        leaks.allocations,\n                        hwm.bytes,\n                        leaks.bytes};\n\n                return callback(alloc);\n            });\n}\n\nvoid\nAllocationLifetimeAggregator::addAllocation(const Allocation& allocation_or_deallocation)\n{\n    // Note: Deallocation records don't tell us where the memory was allocated,\n    //       so we need to save the records for allocations and cross-reference\n    //       deallocations against them.\n    switch (hooks::allocatorKind(allocation_or_deallocation.allocator)) {\n        case hooks::AllocatorKind::SIMPLE_ALLOCATOR: {\n            const Allocation& allocation = allocation_or_deallocation;\n            size_t generation = d_num_snapshots;\n            d_ptr_to_allocation[allocation.address] = {allocation, generation};\n            break;\n        }\n        case hooks::AllocatorKind::SIMPLE_DEALLOCATOR: {\n            const Allocation& deallocation = allocation_or_deallocation;\n            const auto it = d_ptr_to_allocation.find(deallocation.address);\n            if (it != d_ptr_to_allocation.end()) {\n                const auto& [allocation, generation] = it->second;\n                recordDeallocation(extractKey(allocation), 1, allocation.size, generation);\n                d_ptr_to_allocation.erase(it);\n            }\n            break;\n        }\n        case hooks::AllocatorKind::RANGED_ALLOCATOR: {\n            const Allocation& allocation = allocation_or_deallocation;\n            size_t generation = d_num_snapshots;\n            d_mmap_intervals.addInterval(\n                    allocation.address,\n                    allocation.size,\n                    {std::make_shared<Allocation>(allocation), generation});\n            break;\n        }\n        case hooks::AllocatorKind::RANGED_DEALLOCATOR: {\n            const Allocation& deallocation = allocation_or_deallocation;\n            auto removal_stats =\n                    d_mmap_intervals.removeInterval(deallocation.address, deallocation.size);\n            for (const auto& [interval, pair] : removal_stats.freed_allocations) {\n                recordRangedDeallocation(pair.first, interval.size(), pair.second);\n            }\n            for (const auto& [interval, pair] : removal_stats.shrunk_allocations) {\n                recordRangedDeallocation(pair.first, interval.size(), pair.second);\n            }\n            for (const auto& [interval, pair] : removal_stats.split_allocations) {\n                recordRangedDeallocation(pair.first, interval.size(), pair.second);\n            }\n            break;\n        }\n    }\n}\n\nHighWaterMarkLocationKey\nAllocationLifetimeAggregator::extractKey(const Allocation& allocation) const\n{\n    return {allocation.tid,\n            allocation.frame_index,\n            allocation.native_frame_id,\n            allocation.native_segment_generation,\n            allocation.allocator};\n}\n\nvoid\nAllocationLifetimeAggregator::recordRangedDeallocation(\n        const std::shared_ptr<Allocation>& allocation_ptr,\n        size_t bytes_deallocated,\n        size_t generation_allocated)\n{\n    // We hold one reference, and the IntervalTree may or may not hold others.\n    // We use a count of 0 for all but the last deallocation of a range so that\n    // partial deallocations won't affect the count of allocations by location.\n    bool fully_deallocated = allocation_ptr.use_count() == 1;\n    recordDeallocation(\n            extractKey(*allocation_ptr),\n            (fully_deallocated ? 1 : 0),\n            bytes_deallocated,\n            generation_allocated);\n}\n\nvoid\nAllocationLifetimeAggregator::recordDeallocation(\n        const HighWaterMarkLocationKey& key,\n        size_t count_delta,\n        size_t bytes_delta,\n        size_t generation)\n{\n    if (d_num_snapshots == generation) {\n        // Allocated and deallocated within the same snapshot. We can ignore this.\n        return;\n    }\n\n    auto& counts = d_allocation_history[std::make_tuple(generation, d_num_snapshots, key)];\n    counts.first += count_delta;\n    counts.second += bytes_delta;\n}\n\nvoid\nAllocationLifetimeAggregator::captureSnapshot()\n{\n    ++d_num_snapshots;\n}\n\nstd::vector<AllocationLifetime>\nAllocationLifetimeAggregator::generateIndex() const\n{\n    struct KeyHash\n    {\n        size_t operator()(const std::pair<size_t, HighWaterMarkLocationKey>& key) const\n        {\n            size_t ret = HighWaterMarkLocationKeyHash{}(std::get<1>(key));\n            ret = (ret << 1) ^ std::get<0>(key);\n            return ret;\n        }\n    };\n\n    // First, gather information about allocations that were never deallocated.\n    // These are still sitting in `d_ptr_to_allocation` and `d_mmap_intervals`,\n    // since `d_allocation_history` only gets updated when things are freed.\n    // We can't update `d_allocation_history` here since this method is const.\n    std::unordered_map<std::pair<size_t, HighWaterMarkLocationKey>, std::pair<size_t, size_t>, KeyHash>\n            leaks;\n\n    for (const auto& [ptr, allocation_and_generation] : d_ptr_to_allocation) {\n        (void)ptr;\n        const auto& [allocation, generation] = allocation_and_generation;\n        auto& counts = leaks[std::make_pair(generation, extractKey(allocation))];\n        counts.first += 1;\n        counts.second += allocation.size;\n    }\n\n    std::unordered_set<void*> leaked_mappings;\n    for (const auto& [interval, allocation_ptr_and_generation] : d_mmap_intervals) {\n        const auto& [allocation_ptr, generation] = allocation_ptr_and_generation;\n        auto& counts = leaks[std::make_pair(generation, extractKey(*allocation_ptr))];\n\n        // Ensure we only count each allocation once, even if it's been split.\n        auto inserted = leaked_mappings.insert(allocation_ptr.get()).second;\n        counts.first += (inserted ? 1 : 0);\n        counts.second += interval.size();\n    }\n\n    // Then, combine information about both leaked allocations and freed\n    // allocations into the vector we'll be returning.\n    std::vector<AllocationLifetime> ret;\n\n    for (const auto& [when_where, how_much] : leaks) {\n        const auto& [allocated_before, key] = when_where;\n        const auto& [n_allocations, n_bytes] = how_much;\n        ret.push_back({allocated_before, static_cast<size_t>(-1), key, n_allocations, n_bytes});\n    }\n\n    for (const auto& [when_where, how_much] : d_allocation_history) {\n        const auto& [allocated_before, deallocated_before, key] = when_where;\n        const auto& [n_allocations, n_bytes] = how_much;\n        ret.push_back({allocated_before, deallocated_before, key, n_allocations, n_bytes});\n    }\n\n    // Finally, sort the vector we're returning, so that our callers can count\n    // on all intervals for a given location being contiguous.\n    std::sort(ret.begin(), ret.end());\n    return ret;\n}\n\n/**\n * Produce an aggregated snapshot from a vector of allocations and a index in that vector\n *\n * This function takes a vector containing a sequence of allocation events and an index in that\n * vector indicating the position where the snapshot should be produced and returns a collection\n * of allocations representing the heap structure at that particular point. This collection of\n * allocations is aggregated so allocations with the same stack trace will be reported together\n * as a single allocation with the size being the sum af the sizes of the individual allocations.\n *\n **/\nstatic reduced_snapshot_map_t\nreduceSnapshotAllocations(const allocations_t& records, size_t snapshot_index, bool merge_threads)\n{\n    assert(snapshot_index < records.size());\n\n    SnapshotAllocationAggregator aggregator;\n\n    std::for_each(records.cbegin(), records.cbegin() + snapshot_index + 1, [&](auto& record) {\n        aggregator.addAllocation(record);\n    });\n\n    return aggregator.getSnapshotAllocations(merge_threads);\n}\n\nvoid\nHighWatermarkFinder::updatePeak(size_t index) noexcept\n{\n    if (d_current_memory >= d_last_high_water_mark.peak_memory) {\n        d_last_high_water_mark.index = index;\n        d_last_high_water_mark.peak_memory = d_current_memory;\n    }\n}\n\nvoid\nHighWatermarkFinder::processAllocation(const Allocation& allocation)\n{\n    size_t index = d_allocations_seen++;\n    switch (hooks::allocatorKind(allocation.allocator)) {\n        case hooks::AllocatorKind::SIMPLE_ALLOCATOR: {\n            d_current_memory += allocation.size;\n            updatePeak(index);\n            d_ptr_to_allocation_size[allocation.address] = allocation.size;\n            break;\n        }\n        case hooks::AllocatorKind::SIMPLE_DEALLOCATOR: {\n            auto it = d_ptr_to_allocation_size.find(allocation.address);\n            if (it != d_ptr_to_allocation_size.end()) {\n                d_current_memory -= it->second;\n                d_ptr_to_allocation_size.erase(it);\n            }\n            updatePeak(index);\n            break;\n        }\n        case hooks::AllocatorKind::RANGED_ALLOCATOR: {\n            d_mmap_intervals.addInterval(allocation.address, allocation.size, allocation);\n            d_current_memory += allocation.size;\n            updatePeak(index);\n            break;\n        }\n        case hooks::AllocatorKind::RANGED_DEALLOCATOR: {\n            const auto address = allocation.address;\n            const auto size = allocation.size;\n            const auto removal_stats = d_mmap_intervals.removeInterval(address, size);\n            d_current_memory -= removal_stats.total_freed_bytes;\n            updatePeak(index);\n            break;\n        }\n    }\n}\n\nHighWatermark\nHighWatermarkFinder::getHighWatermark() const noexcept\n{\n    return d_last_high_water_mark;\n}\n\nsize_t\nHighWatermarkFinder::getCurrentWatermark() const noexcept\n{\n    return d_current_memory;\n}\n\nvoid\nAllocationStatsAggregator::addAllocation(\n        const Allocation& allocation,\n        std::optional<frame_id_t> python_frame_id)\n{\n    d_high_water_mark_finder.processAllocation(allocation);\n    if (hooks::isDeallocator(allocation.allocator)) {\n        return;\n    }\n    d_total_allocations += 1;\n    d_total_bytes_allocated += allocation.size;\n    d_allocation_count_by_size[allocation.size] += 1;\n    d_allocation_count_by_allocator[static_cast<int>(allocation.allocator)] += 1;\n    auto& size_and_count = d_size_and_count_by_location[python_frame_id];\n    size_and_count.first += allocation.size;\n    size_and_count.second += 1;\n}\n\nPyObject*\nPy_ListFromSnapshotAllocationRecords(const reduced_snapshot_map_t& stack_to_allocation)\n{\n    PyObject* list = PyList_New(stack_to_allocation.size());\n    if (list == nullptr) {\n        return nullptr;\n    }\n    size_t list_index = 0;\n    for (const auto& it : stack_to_allocation) {\n        const auto& record = it.second;\n        PyObject* pyrecord = record.toPythonObject();\n        if (pyrecord == nullptr) {\n            Py_DECREF(list);\n            return nullptr;\n        }\n        PyList_SET_ITEM(list, list_index++, pyrecord);\n    }\n    return list;\n}\n\nPyObject*\nPy_GetSnapshotAllocationRecords(\n        const allocations_t& all_records,\n        size_t record_index,\n        bool merge_threads)\n{\n    if (all_records.empty()) {\n        return PyList_New(0);\n    }\n    const auto stack_to_allocation = reduceSnapshotAllocations(all_records, record_index, merge_threads);\n    return Py_ListFromSnapshotAllocationRecords(stack_to_allocation);\n}\n\n}  // namespace memray::api\n"
  },
  {
    "path": "src/memray/_memray/snapshot.h",
    "content": "#pragma once\n\n#define PY_SSIZE_T_CLEAN\n#include <Python.h>\n\n#include <algorithm>\n#include <deque>\n#include <functional>\n#include <optional>\n#include <unordered_map>\n#include <vector>\n\n#include \"frame_tree.h\"\n#include \"records.h\"\n\nnamespace memray::api {\n\nusing namespace tracking_api;\n\nconst thread_id_t NO_THREAD_INFO = 0;\n\nstruct LocationKey\n{\n    size_t python_frame_id;\n    size_t native_frame_id;\n    thread_id_t thread_id;\n\n    bool operator==(const LocationKey& rhs) const;\n};\n\nstruct index_thread_pair_hash\n{\n    std::size_t operator()(const LocationKey& p) const\n    {\n        // Reduce the risk of the Python frame ID and native frame ID hashing\n        // to the same value and cancelling each other out by adding a fixed\n        // offset to one of them. Don't worry about collisions with the TID:\n        // it's of a fundamentally different type and collisions are unlikely.\n        return std::hash<size_t>{}(p.python_frame_id)\n               xor std::hash<size_t>{}(p.native_frame_id + 2147483647)\n               xor std::hash<thread_id_t>{}(p.thread_id);\n    }\n};\n\nusing allocations_t = std::vector<Allocation>;\nusing reduced_snapshot_map_t = std::unordered_map<LocationKey, Allocation, index_thread_pair_hash>;\n\nstruct Interval\n{\n    Interval(uintptr_t begin, uintptr_t end);\n    [[nodiscard]] std::optional<Interval> intersection(const Interval& other) const;\n    [[nodiscard]] bool leftIntersects(const Interval& other) const;\n    [[nodiscard]] bool rightIntersects(const Interval& other) const;\n    [[nodiscard]] size_t size() const;\n\n    bool operator==(const Interval& rhs) const;\n    bool operator!=(const Interval& rhs) const;\n\n    uintptr_t begin;\n    uintptr_t end;\n};\n\ntemplate<typename T>\nclass IntervalTree\n{\n  private:\n    using intervals_t = std::vector<std::pair<Interval, T>>;\n    intervals_t d_intervals;\n\n  public:\n    using const_iterator = typename intervals_t::const_iterator;\n    using iterator = typename intervals_t::iterator;\n\n    void addInterval(uintptr_t start, size_t size, const T& element)\n    {\n        if (size <= 0) {\n            return;\n        }\n        d_intervals.emplace_back(Interval(start, start + size), element);\n    }\n\n    struct RemovalStats\n    {\n        size_t total_freed_bytes;\n        std::vector<std::pair<Interval, T>> freed_allocations;\n        std::vector<std::pair<Interval, T>> shrunk_allocations;\n        std::vector<std::pair<Interval, T>> split_allocations;\n    };\n\n    RemovalStats removeInterval(uintptr_t start, size_t size)\n    {\n        RemovalStats stats{};\n\n        if (size <= 0) {\n            return stats;\n        }\n\n        std::vector<std::pair<Interval, T>> new_intervals;\n        new_intervals.reserve(d_intervals.size() + 1);  // We create at most 1 new interval.\n        const auto removed_interval = Interval(start, start + size);\n\n        for (auto& [interval, value] : d_intervals) {\n            std::optional<Interval> maybe_intersection = interval.intersection(removed_interval);\n            if (!maybe_intersection) {\n                // Keep this interval entirely (the removed interval doesn't overlap it).\n                new_intervals.emplace_back(interval, value);\n                continue;\n            }\n\n            const auto& intersection = maybe_intersection.value();\n            stats.total_freed_bytes += intersection.size();\n            if (intersection == interval) {\n                // Keep none of this interval (the removed interval contains it).\n                stats.freed_allocations.emplace_back(intersection, value);\n            } else if (intersection.leftIntersects(interval)) {\n                // Keep the end of this interval (the removed interval overlaps the start).\n                stats.shrunk_allocations.emplace_back(intersection, value);\n                new_intervals.emplace_back(Interval{intersection.end, interval.end}, value);\n            } else if (intersection.rightIntersects(interval)) {\n                // Keep the start of this interval (the removed interval overlaps the end).\n                stats.shrunk_allocations.emplace_back(intersection, value);\n                new_intervals.emplace_back(Interval{interval.begin, intersection.begin}, value);\n            } else {\n                // Split this interval in two (the removed interval overlaps the middle).\n                stats.split_allocations.emplace_back(intersection, value);\n                new_intervals.emplace_back(Interval{interval.begin, intersection.begin}, value);\n                new_intervals.emplace_back(Interval{intersection.end, interval.end}, value);\n            }\n        }\n\n        d_intervals = new_intervals;\n        return stats;\n    }\n\n    size_t size()\n    {\n        size_t result = 0;\n        std::for_each(d_intervals.begin(), d_intervals.end(), [&](const auto& pair) {\n            result += pair.first.size();\n        });\n        return result;\n    }\n\n    iterator begin()\n    {\n        return d_intervals.begin();\n    }\n\n    iterator end()\n    {\n        return d_intervals.end();\n    }\n\n    const_iterator begin() const\n    {\n        return d_intervals.begin();\n    }\n\n    const_iterator end() const\n    {\n        return d_intervals.end();\n    }\n\n    const_iterator cbegin()\n    {\n        return d_intervals.cbegin();\n    }\n\n    const_iterator cend()\n    {\n        return d_intervals.cend();\n    }\n};\n\nclass AbstractAggregator\n{\n  public:\n    virtual void addAllocation(const Allocation& allocation) = 0;\n    virtual reduced_snapshot_map_t getSnapshotAllocations(bool merge_threads) = 0;\n    virtual ~AbstractAggregator() = default;\n};\n\nclass SnapshotAllocationAggregator : public AbstractAggregator\n{\n  private:\n    size_t d_index{0};\n    IntervalTree<Allocation> d_interval_tree;\n    std::unordered_map<uintptr_t, Allocation> d_ptr_to_allocation{};\n\n  public:\n    void addAllocation(const Allocation& allocation) override;\n    reduced_snapshot_map_t getSnapshotAllocations(bool merge_threads) override;\n};\n\nclass TemporaryAllocationsAggregator : public AbstractAggregator\n{\n  private:\n    size_t d_max_items;\n    std::unordered_map<thread_id_t, std::deque<Allocation>> d_current_allocations{};\n    std::vector<Allocation> d_temporary_allocations{};\n\n  public:\n    TemporaryAllocationsAggregator(size_t max_items);\n    void addAllocation(const Allocation& allocation) override;\n    reduced_snapshot_map_t getSnapshotAllocations(bool merge_threads) override;\n};\n\nclass AggregatedCaptureReaggregator : public AbstractAggregator\n{\n  public:\n    void addAllocation(const Allocation& allocation) override;\n    reduced_snapshot_map_t getSnapshotAllocations(bool merge_threads) override;\n\n  private:\n    std::vector<Allocation> d_allocations;\n};\n\nPyObject*\nPy_ListFromSnapshotAllocationRecords(const reduced_snapshot_map_t& stack_to_allocation);\n\nstruct HighWatermark\n{\n    size_t index{0};\n    size_t peak_memory{0};\n};\n\nclass HighWatermarkFinder\n{\n  public:\n    HighWatermarkFinder() = default;\n    void processAllocation(const Allocation& allocation);\n    HighWatermark getHighWatermark() const noexcept;\n    size_t getCurrentWatermark() const noexcept;\n\n  private:\n    HighWatermarkFinder(const HighWatermarkFinder&) = delete;\n    HighWatermarkFinder& operator=(const HighWatermarkFinder&) = delete;\n\n    void updatePeak(size_t index) noexcept;\n\n    HighWatermark d_last_high_water_mark;\n    size_t d_current_memory{0};\n    size_t d_allocations_seen{0};\n    std::unordered_map<uintptr_t, size_t> d_ptr_to_allocation_size{};\n    IntervalTree<Allocation> d_mmap_intervals;\n};\n\n// Like LocationKey, but considers the native_segment_generation and the\n// allocator to be part of the key. Arguably it's a bug that LocationKey\n// doesn't, for each of these. For now, I'm defining a separate type to avoid\n// scope creep, but we should merge these.\nstruct HighWaterMarkLocationKey\n{\n    // Ordered widest field to narrowest, to avoid padding.\n    thread_id_t thread_id;\n    size_t python_frame_id;\n    size_t native_frame_id;\n    size_t native_segment_generation;\n    hooks::Allocator allocator;\n\n    bool operator==(const HighWaterMarkLocationKey& rhs) const;\n    bool operator!=(const HighWaterMarkLocationKey& rhs) const;\n    bool operator<(const HighWaterMarkLocationKey& rhs) const;\n};\n\nstruct HighWaterMarkLocationKeyHash\n{\n    size_t operator()(const HighWaterMarkLocationKey& p) const\n    {\n        // Keep the fewest bits from the hashes of the fields that vary least.\n        size_t ret = std::hash<hooks::Allocator>{}(p.allocator);\n        ret = (ret << 1) ^ std::hash<size_t>{}(p.native_segment_generation);\n        ret = (ret << 1) ^ std::hash<thread_id_t>{}(p.thread_id);\n        ret = (ret << 1) ^ std::hash<size_t>{}(p.native_frame_id);\n        ret = (ret << 1) ^ std::hash<size_t>{}(p.python_frame_id);\n        return ret;\n    }\n};\n\nstruct Contribution\n{\n    size_t bytes;\n    size_t allocations;\n};\n\nbool\noperator==(const Contribution& lhs, const Contribution& rhs);\n\nbool\noperator!=(const Contribution& lhs, const Contribution& rhs);\n\nstruct HistoricalContribution\n{\n    size_t as_of_snapshot;\n    size_t peak_index;\n    Contribution contrib;\n};\n\nclass UsageHistory\n{\n  public:\n    void recordUsageDelta(\n            const std::vector<size_t>& highest_peak_by_snapshot,\n            size_t current_peak,\n            size_t count_delta,\n            size_t bytes_delta);\n\n    Contribution highWaterMarkContribution(size_t highest_peak) const;\n    Contribution leaksContribution() const;\n    std::vector<HistoricalContribution> contributionsBySnapshot(\n            const std::vector<size_t>& highest_peak_by_snapshot,\n            size_t current_peak) const;\n\n  private:\n    // This class represents allocations observed at some location over time.\n    // When an allocation or deallocation is observed, we first check if a new\n    // peak was discovered after the last time an allocation or deallocation\n    // was performed here. If so, the counters tracking what happened since the\n    // last peak must be merged into allocations_contributed_to_last_known_peak\n    // and bytes_contributed_to_last_known_peak and reset: they didn't\n    // contribute to the previous peak, but they are accounted for in the newly\n    // discovered peak. Finally, we update those counters to account for\n    // allocations or deallocations since the current peak.\n    struct UsageHistoryImpl\n    {\n        uint64_t last_known_snapshot;\n        uint64_t last_known_peak;\n        size_t allocations_contributed_to_last_known_peak;\n        size_t bytes_contributed_to_last_known_peak;\n        // NOTE: We may have more deallocations than allocations since the last\n        // peak, or more bytes deallocated than allocated. These 2 size_t's\n        // may represent negative counts as large positive numbers. That's OK:\n        // they represent deltas since the last known peak, and are always\n        // added to the values from the last known peak. Unsigned integers use\n        // modular arithmetic, and addition will overflow to the correct value.\n        size_t count_since_last_peak;\n        size_t bytes_since_last_peak;\n\n        // Update so that `last_known_peak == new_peak`.\n        void rebase(size_t new_peak);\n    };\n\n    UsageHistoryImpl d_history{};\n    std::vector<HistoricalContribution> d_heap_contribution_by_snapshot;\n\n    // Append records for already-completed snapshots to the given vector.\n    UsageHistoryImpl recordContributionsToCompletedSnapshots(\n            const std::vector<size_t>& highest_peak_by_snapshot,\n            std::vector<HistoricalContribution>& heap_contribution_by_snapshot) const;\n};\n\nstruct AllocationLifetime\n{\n    size_t allocatedBeforeSnapshot;\n    size_t deallocatedBeforeSnapshot;  // SIZE_MAX if never deallocated\n    HighWaterMarkLocationKey key;\n    size_t n_allocations;\n    size_t n_bytes;\n};\n\nclass HighWaterMarkAggregator\n{\n  public:\n    using Index = std::vector<AllocationLifetime>;\n\n    void addAllocation(const Allocation& allocation);\n    void captureSnapshot();\n\n    size_t getCurrentHeapSize() const noexcept;\n    std::vector<size_t> highWaterMarkBytesBySnapshot() const;\n    Index generateIndex() const;\n\n    using allocation_callback_t = std::function<bool(const AggregatedAllocation&)>;\n    bool visitAllocations(const allocation_callback_t& callback) const;\n\n  private:\n    // For each call to captureSnapshot(), record the index of the highest\n    // high water mark found since the last snapshot was taken.\n    std::vector<size_t> d_high_water_mark_index_by_snapshot;\n\n    // For each call to captureSnapshot(), record the heap size at the highest\n    // high water mark found since the last snapshot was taken.\n    std::vector<size_t> d_high_water_mark_bytes_by_snapshot;\n\n    // Number of high water marks found (incremented on the falling edge,\n    // as well as on a new snapshot being taken).\n    uint64_t d_peak_count{};\n    size_t d_heap_size_at_last_peak{};\n    size_t d_current_heap_size{};\n\n    // Information about allocations and deallocations, aggregated by location.\n    using UsageHistoryByLocation =\n            std::unordered_map<HighWaterMarkLocationKey, UsageHistory, HighWaterMarkLocationKeyHash>;\n    UsageHistoryByLocation d_usage_history_by_location;\n\n    // Simple allocations contributing to the current heap size.\n    std::unordered_map<uintptr_t, Allocation> d_ptr_to_allocation;\n\n    // Ranged allocations contributing to the current heap size.\n    IntervalTree<Allocation> d_mmap_intervals;\n\n    UsageHistory& getUsageHistory(const Allocation& allocation);\n    void recordUsageDelta(const Allocation& allocation, size_t count_delta, size_t bytes_delta);\n    reduced_snapshot_map_t getAllocations(bool merge_threads, bool stop_at_high_water_mark) const;\n};\n\nclass AllocationLifetimeAggregator\n{\n  public:\n    void addAllocation(const Allocation& allocation);\n    void captureSnapshot();\n\n    std::vector<AllocationLifetime> generateIndex() const;\n\n  private:\n    size_t d_num_snapshots{};\n\n    struct allocation_history_key_hash\n    {\n        size_t operator()(const std::tuple<size_t, size_t, HighWaterMarkLocationKey>& key) const\n        {\n            size_t ret = HighWaterMarkLocationKeyHash{}(std::get<2>(key));\n            ret = (ret << 1) ^ std::get<1>(key);\n            ret = (ret << 1) ^ std::get<0>(key);\n            return ret;\n        }\n    };\n\n    // Record of freed allocations that spanned multiple snapshots.\n    std::unordered_map<\n            std::tuple<size_t, size_t, HighWaterMarkLocationKey>,\n            std::pair<size_t, size_t>,\n            allocation_history_key_hash>\n            d_allocation_history;\n\n    // Simple allocations contributing to the current heap size.\n    std::unordered_map<uintptr_t, std::pair<Allocation, size_t>> d_ptr_to_allocation;\n\n    // Ranged allocations contributing to the current heap size.\n    IntervalTree<std::pair<std::shared_ptr<Allocation>, size_t>> d_mmap_intervals;\n\n    HighWaterMarkLocationKey extractKey(const Allocation& allocation) const;\n\n    void recordRangedDeallocation(\n            const std::shared_ptr<Allocation>& allocation,\n            size_t bytes_deallocated,\n            size_t generation_allocated);\n\n    void recordDeallocation(\n            const HighWaterMarkLocationKey& key,\n            size_t count_delta,\n            size_t bytes_delta,\n            size_t generation);\n};\n\nclass AllocationStatsAggregator\n{\n  public:\n    void addAllocation(const Allocation& allocation, std::optional<frame_id_t> python_frame_id);\n\n    uint64_t totalAllocations()\n    {\n        return d_total_allocations;\n    }\n\n    uint64_t totalBytesAllocated()\n    {\n        return d_total_bytes_allocated;\n    }\n\n    uint64_t peakBytesAllocated()\n    {\n        return d_high_water_mark_finder.getHighWatermark().peak_memory;\n    }\n\n    const std::unordered_map<size_t, uint64_t>& allocationCountBySize()\n    {\n        return d_allocation_count_by_size;\n    }\n\n    const std::unordered_map<int, uint64_t>& allocationCountByAllocator()\n    {\n        return d_allocation_count_by_allocator;\n    }\n\n    std::vector<std::pair<uint64_t, std::optional<frame_id_t>>> topLocationsBySize(size_t num_largest)\n    {\n        return topLocationsBySizeAndCountField<0>(num_largest);\n    }\n\n    std::vector<std::pair<uint64_t, std::optional<frame_id_t>>> topLocationsByCount(int num_largest)\n    {\n        return topLocationsBySizeAndCountField<1>(num_largest);\n    }\n\n  private:\n    typedef std::pair<uint64_t, uint64_t> SizeAndCount;\n    typedef std::unordered_map<std::optional<frame_id_t>, SizeAndCount> SizeAndCountByLocation;\n\n    SizeAndCountByLocation d_size_and_count_by_location;\n    std::unordered_map<size_t, uint64_t> d_allocation_count_by_size;\n    std::unordered_map<int, uint64_t> d_allocation_count_by_allocator;\n    HighWatermarkFinder d_high_water_mark_finder;\n    uint64_t d_total_allocations{};\n    uint64_t d_total_bytes_allocated{};\n\n    template<int field>\n    std::vector<\n            std::pair<typename std::tuple_element<field, SizeAndCount>::type, std::optional<frame_id_t>>>\n    topLocationsBySizeAndCountField(size_t num_largest)\n    {\n        if (num_largest == 0) {\n            return {};\n        }\n        if (num_largest > d_size_and_count_by_location.size()) {\n            num_largest = d_size_and_count_by_location.size();\n        }\n\n        std::vector<std::pair<uint64_t, std::optional<frame_id_t>>> heap;\n        heap.reserve(d_size_and_count_by_location.size());\n        for (auto it : d_size_and_count_by_location) {\n            auto location = it.first;\n            auto val = std::get<field>(it.second);\n            heap.push_back({val, location});\n        }\n        std::make_heap(heap.begin(), heap.end());\n        for (size_t i = 0; i < num_largest; ++i) {\n            std::pop_heap(heap.begin(), heap.end() - i);\n        }\n        return {heap.rbegin(), heap.rbegin() + num_largest};\n    }\n};\n\nPyObject*\nPy_GetSnapshotAllocationRecords(\n        const allocations_t& all_records,\n        size_t record_index,\n        bool merge_threads);\n\n}  // namespace memray::api\n"
  },
  {
    "path": "src/memray/_memray/snapshot.pxd",
    "content": "from _memray.hooks cimport Allocator\nfrom _memray.records cimport AggregatedAllocation\nfrom _memray.records cimport Allocation\nfrom _memray.records cimport optional_location_id_t\nfrom libc.stdint cimport uint64_t\nfrom libcpp cimport bool\nfrom libcpp.functional cimport function\nfrom libcpp.unordered_map cimport unordered_map\nfrom libcpp.utility cimport pair\nfrom libcpp.vector cimport vector\n\n\ncdef extern from \"snapshot.h\" namespace \"memray::api\":\n    unsigned long NO_THREAD_INFO\n\n    cdef struct HighWatermark:\n        size_t index\n        size_t peak_memory\n\n    cdef cppclass HighWatermarkFinder:\n        void processAllocation(const Allocation&) except+\n        HighWatermark getHighWatermark()\n        size_t getCurrentWatermark()\n\n    cdef cppclass reduced_snapshot_map_t:\n        pass\n\n    cdef cppclass AbstractAggregator:\n        void addAllocation(const Allocation&) except+\n        reduced_snapshot_map_t getSnapshotAllocations(bool merge_threads) except+\n\n    cdef cppclass TemporaryAllocationsAggregator(AbstractAggregator):\n        TemporaryAllocationsAggregator(size_t max_items)\n\n    cdef cppclass SnapshotAllocationAggregator(AbstractAggregator):\n        pass\n\n    cdef cppclass AggregatedCaptureReaggregator(AbstractAggregator):\n        pass\n\n    cdef cppclass LocationKey:\n        size_t python_frame_id\n        size_t native_frame_id\n        unsigned long thread_id\n\n    cdef cppclass index_thread_pair_hash:\n        pass\n\n    cdef cppclass HighWaterMarkLocationKey:\n        unsigned long thread_id\n        size_t python_frame_id\n        size_t native_frame_id\n        size_t native_segment_generation\n        Allocator allocator\n\n        bool operator==(const HighWaterMarkLocationKey& other)\n        bool operator!=(const HighWaterMarkLocationKey& other)\n\n    cdef cppclass AllocationLifetime:\n        size_t allocatedBeforeSnapshot\n        size_t deallocatedBeforeSnapshot\n        HighWaterMarkLocationKey key\n        size_t n_allocations\n        size_t n_bytes\n\n    cdef cppclass AllocationLifetimeAggregator:\n        void addAllocation(const Allocation& allocation) except+\n        void captureSnapshot()\n        vector[AllocationLifetime] generateIndex() except+\n\n    cdef cppclass HighWaterMarkAggregator:\n        void addAllocation(const Allocation& allocation) except+\n        void captureSnapshot() except+\n\n        size_t getCurrentHeapSize()\n        bool visitAllocations[T](const T& callback) except+\n        vector[size_t] highWaterMarkBytesBySnapshot() except+\n        vector[AllocationLifetime] generateIndex() except+\n\n    cdef cppclass AllocationStatsAggregator:\n        void addAllocation(const Allocation&, optional_location_id_t python_frame_id) except+\n        uint64_t totalAllocations()\n        uint64_t totalBytesAllocated()\n        uint64_t peakBytesAllocated()\n        const unordered_map[size_t, uint64_t]& allocationCountBySize()\n        const unordered_map[int, uint64_t]& allocationCountByAllocator()\n        vector[pair[uint64_t, optional_location_id_t]] topLocationsBySize(size_t num_largest) except+\n        vector[pair[uint64_t, optional_location_id_t]] topLocationsByCount(size_t num_largest) except+\n\n    object Py_ListFromSnapshotAllocationRecords(const reduced_snapshot_map_t&) except+\n    object Py_GetSnapshotAllocationRecords(const vector[Allocation]& all_records, size_t record_index, bool merge_threads) except+\n"
  },
  {
    "path": "src/memray/_memray/socket_reader_thread.cpp",
    "content": "#include \"socket_reader_thread.h\"\n\n#include <iostream>\n\nnamespace memray::socket_thread {\n\nvoid\nBackgroundSocketReader::backgroundThreadWorker()\n{\n    while (true) {\n        if (d_stop_thread) {\n            break;\n        }\n\n        const auto record_type = d_record_reader->nextRecord();\n\n        if (d_stop_thread) {\n            break;\n        }\n\n        switch (record_type) {\n            case RecordResult::ALLOCATION_RECORD: {\n                std::lock_guard<std::mutex> lock(d_mutex);\n                d_aggregator.addAllocation(d_record_reader->getLatestAllocation());\n            } break;\n\n            case RecordResult::MEMORY_RECORD: {\n            } break;\n\n            case RecordResult::AGGREGATED_ALLOCATION_RECORD: {\n                // This should never happen. We checked the source format in\n                // the constructor, and RecordReader should never return\n                // records that don't match the source format.\n                std::cerr << \"BUG: AGGREGATED_ALLOCATION_RECORD from ALL_ALLOCATIONS input\" << std::endl;\n                abort();\n            } break;\n\n            case RecordResult::MEMORY_SNAPSHOT: {\n                // As above.\n                std::cerr << \"BUG: MEMORY_SNAPSHOT from ALL_ALLOCATIONS input\" << std::endl;\n                abort();\n            } break;\n\n            case RecordResult::OBJECT_RECORD: {\n                std::cerr << \"BUG: OBJECT_RECORD from ALL_ALLOCATIONS input\" << std::endl;\n                abort();\n            } break;\n\n            case RecordResult::END_OF_FILE:\n            case RecordResult::ERROR: {\n                d_stop_thread = true;\n            } break;\n        }\n    }\n}\n\nBackgroundSocketReader::BackgroundSocketReader(std::shared_ptr<api::RecordReader> reader)\n: d_record_reader(reader)\n{\n    if (d_record_reader->getHeader().file_format != api::FileFormat::ALL_ALLOCATIONS) {\n        throw std::runtime_error(\"BackgroundSocketReader only supports ALL_ALLOCATIONS\");\n    }\n}\n\nvoid\nBackgroundSocketReader::start()\n{\n    d_thread = std::thread(&BackgroundSocketReader::backgroundThreadWorker, this);\n}\n\nBackgroundSocketReader::~BackgroundSocketReader()\n{\n    d_record_reader->close();\n    d_stop_thread = true;\n    d_thread.join();\n}\n\nPyObject*\nBackgroundSocketReader::Py_GetSnapshotAllocationRecords(bool merge_threads)\n{\n    api::reduced_snapshot_map_t stack_to_allocation;\n    {\n        std::lock_guard<std::mutex> lock(d_mutex);\n        stack_to_allocation = d_aggregator.getSnapshotAllocations(merge_threads);\n    }\n\n    return api::Py_ListFromSnapshotAllocationRecords(stack_to_allocation);\n}\n\nbool\nBackgroundSocketReader::is_active() const\n{\n    return !d_stop_thread;\n}\n\n}  // namespace memray::socket_thread\n"
  },
  {
    "path": "src/memray/_memray/socket_reader_thread.h",
    "content": "#pragma once\n\n#define PY_SSIZE_T_CLEAN\n#include <Python.h>\n\n#include <atomic>\n#include <memory>\n#include <mutex>\n#include <thread>\n\n#include \"record_reader.h\"\n#include \"snapshot.h\"\n\nnamespace memray::socket_thread {\n\nclass BackgroundSocketReader\n{\n  private:\n    using RecordResult = api::RecordReader::RecordResult;\n\n    std::atomic<bool> d_stop_thread{false};\n    std::mutex d_mutex;\n    std::shared_ptr<api::RecordReader> d_record_reader;\n\n    api::SnapshotAllocationAggregator d_aggregator;\n    std::thread d_thread;\n\n    void backgroundThreadWorker();\n\n  public:\n    BackgroundSocketReader(BackgroundSocketReader& other) = delete;\n    BackgroundSocketReader(BackgroundSocketReader&& other) = delete;\n    void operator=(const BackgroundSocketReader&) = delete;\n    void operator=(BackgroundSocketReader&&) = delete;\n\n    explicit BackgroundSocketReader(std::shared_ptr<api::RecordReader> reader);\n    ~BackgroundSocketReader();\n\n    void start();\n    bool is_active() const;\n    PyObject* Py_GetSnapshotAllocationRecords(bool merge_threads);\n};\n\n}  // namespace memray::socket_thread\n"
  },
  {
    "path": "src/memray/_memray/socket_reader_thread.pxd",
    "content": "from _memray.record_reader cimport RecordReader\nfrom libcpp cimport bool\nfrom libcpp cimport int\nfrom libcpp.memory cimport shared_ptr\n\n\ncdef extern from \"socket_reader_thread.h\" namespace \"memray::socket_thread\":\n    cdef cppclass BackgroundSocketReader:\n        BackgroundSocketReader(shared_ptr[RecordReader]) except+\n\n        void start() except+\n        bool is_active()\n        object Py_GetSnapshotAllocationRecords(bool merge_threads)\n"
  },
  {
    "path": "src/memray/_memray/source.cpp",
    "content": "#define PY_SSIZE_T_CLEAN\n#include <Python.h>\n\n#include <cerrno>\n#include <cstring>\n#include <iostream>\n#include <netdb.h>\n#include <stdexcept>\n#include <sys/socket.h>\n#include <unistd.h>\n\n#include <chrono>\n#include <thread>\n\n#include \"exceptions.h\"\n#include \"logging.h\"\n#include \"source.h\"\n\nusing namespace memray::exception;\n\nnamespace memray::io {\n\nFileSource::FileSource(const std::string& file_name)\n: d_file_name(file_name)\n{\n    d_raw_stream = std::make_shared<std::ifstream>(d_file_name, std::ios::binary | std::ios::in);\n    if (!(*d_raw_stream)) {\n        throw IoError{\"Could not open file \" + file_name + \": \" + std::string(strerror(errno))};\n    }\n    char lz4_magic[] = {0x04, 0x22, 0x4D, 0x18};\n    char file_magic[sizeof(lz4_magic)] = {};\n    d_raw_stream->read(file_magic, sizeof(file_magic));\n    d_raw_stream->seekg(0, std::ios::beg);\n\n    if (0 == memcmp(lz4_magic, file_magic, sizeof(lz4_magic))) {\n        d_stream = std::make_shared<lz4_stream::istream>(*d_raw_stream);\n    } else {\n        d_stream = d_raw_stream;\n        findReadableSize();\n    }\n}\n\nbool\nFileSource::read(char* stream, ssize_t length)\n{\n    if (d_stream->read(stream, length).fail()) {\n        return false;\n    }\n    d_bytes_read += length;\n    if (d_readable_size && d_bytes_read > d_readable_size) {\n        return false;\n    }\n    return true;\n}\n\nbool\nFileSource::getline(std::string& result, char delimiter)\n{\n    std::getline(*d_stream, result, delimiter);\n    if (!d_stream) {\n        return false;\n    }\n    d_bytes_read += result.size() + 1;\n    if (d_readable_size && d_bytes_read > d_readable_size) {\n        return false;\n    }\n    return true;\n}\n\nvoid\nFileSource::close()\n{\n    _close();\n}\n\nvoid\nFileSource::findReadableSize()\n{\n    // We grow the file in chunks and then overwrite the zero-filled data with\n    // valid data, which means that if the process is killed in the middle of\n    // tracking there will be some zero-filled bytes at the end of the file.\n    // Ignore any zeroed bytes at the end of the file, assuming they resulted\n    // from such premature termination (because when tracking ends successfully\n    // a TRAILER record is written at the end of the valid data). We may ignore\n    // some valid zero bytes that were part of a complete record, but since the\n    // record type cannot be all zeroes, we will at worst lose one valid record\n    // in order to recover from the file truncation. To ignore these, we count\n    // the zeroed bytes at the end of the file, and make calls to read() and\n    // getline() fail if they read into those bytes.\n    d_raw_stream->seekg(-1, d_raw_stream->end);\n    while (*d_raw_stream) {\n        char c = d_raw_stream->peek();\n        if (c != 0x00) {\n            d_readable_size = d_raw_stream->tellg() + std::streamoff(1);\n            break;\n        }\n        // If we're at BOF, this sets failbit and makes the loop break.\n        d_raw_stream->seekg(-1, d_raw_stream->cur);\n    }\n    d_raw_stream->seekg(0, d_raw_stream->beg);\n}\n\nvoid\nFileSource::_close()\n{\n    d_raw_stream->close();\n}\n\nbool\nFileSource::is_open()\n{\n    return d_raw_stream->is_open();\n}\n\nFileSource::~FileSource()\n{\n    _close();\n}\n\nSocketBuf::SocketBuf(int socket_fd)\n: d_sockfd(socket_fd)\n{\n    setg(d_buf, d_buf, d_buf);\n}\n\nvoid\nSocketBuf::close()\n{\n    d_open = false;\n}\n\nint\nSocketBuf::underflow()\n{\n    if (gptr() < egptr()) {\n        return traits_type::to_int_type(*gptr());\n    }\n\n    ssize_t bytes_read;\n    do {\n        bytes_read = ::recv(d_sockfd, d_buf, MAX_BUF_SIZE, 0);\n    } while (bytes_read < 0 && errno == EINTR);\n\n    if (bytes_read < 0) {\n        if (d_open) {\n            LOG(ERROR) << \"Encountered error in 'recv' call: \" << strerror(errno);\n        }\n        return traits_type::eof();\n    }\n\n    if (bytes_read == 0) {\n        return traits_type::eof();\n    }\n\n    setg(d_buf, d_buf, d_buf + bytes_read);\n    return traits_type::to_int_type(*gptr());\n}\n\nstd::streamsize\nSocketBuf::xsgetn(char* destination, std::streamsize length)\n{\n    std::streamsize needed = length;\n    while (needed > 0) {\n        if (gptr() == egptr()) {\n            // Buffer empty. Get some new data, and throw if we can't.\n            if (underflow() == traits_type::eof()) {\n                return traits_type::eof();\n            }\n        }\n\n        std::streamsize available = egptr() - gptr();\n        std::streamsize to_copy = std::min(available, needed);\n\n        ::memcpy(destination, gptr(), to_copy);\n        gbump(static_cast<int>(to_copy));\n        destination += to_copy;\n        needed -= to_copy;\n    }\n    return length;\n}\n\nSocketSource::SocketSource(int port)\n{\n    struct addrinfo hints = {};\n    struct addrinfo* all_addresses = nullptr;\n    struct addrinfo* curr_address = nullptr;\n    int rv;\n\n    hints.ai_family = AF_UNSPEC;\n    hints.ai_socktype = SOCK_STREAM;\n\n    std::string port_str = std::to_string(port);\n    while (curr_address == nullptr) {\n        Py_BEGIN_ALLOW_THREADS;\n        if ((rv = ::getaddrinfo(nullptr, port_str.c_str(), &hints, &all_addresses)) != 0) {\n            Py_UNBLOCK_THREADS;\n            LOG(ERROR) << \"Encountered error in 'getaddrinfo' call: \" << ::gai_strerror(rv);\n            throw IoError{\"Failed to resolve host IP and port\"};\n        }\n\n        // loop through all the results and connect to the first we can\n        for (curr_address = all_addresses; curr_address != nullptr; curr_address = curr_address->ai_next)\n        {\n            if ((d_sockfd = ::socket(\n                         curr_address->ai_family,\n                         curr_address->ai_socktype,\n                         curr_address->ai_protocol))\n                == -1)\n            {\n                continue;\n            }\n\n            if (::connect(d_sockfd, curr_address->ai_addr, curr_address->ai_addrlen) == -1) {\n                ::close(d_sockfd);\n                continue;\n            }\n            break;\n        }\n        if (curr_address == nullptr) {\n            freeaddrinfo(all_addresses);\n            LOG(DEBUG) << \"No connection, sleeping before retrying...\";\n            std::this_thread::sleep_for(std::chrono::milliseconds(500));\n        }\n        Py_END_ALLOW_THREADS;\n        // Give a chance to check for signals arriving so we don't block the main thread.\n        if (PyErr_CheckSignals() < 0) {\n            break;\n        }\n    }\n    if (curr_address == nullptr) {\n        d_is_open = false;\n        return;\n    }\n\n    freeaddrinfo(all_addresses);\n    d_is_open = true;\n    d_socket_buf = std::make_unique<SocketBuf>(d_sockfd);\n}\n\nbool\nSocketSource::read(char* result, ssize_t length)\n{\n    if (!d_is_open) {\n        return false;\n    }\n    return d_socket_buf->sgetn(result, length) != SocketBuf::traits_type::eof();\n}\n\nvoid\nSocketSource::_close()\n{\n    if (!d_is_open) {\n        return;\n    }\n    d_is_open = false;\n    d_socket_buf->close();\n    ::shutdown(d_sockfd, SHUT_RDWR);\n    ::close(d_sockfd);\n}\n\nvoid\nSocketSource::close()\n{\n    _close();\n}\n\nbool\nSocketSource::is_open()\n{\n    return d_is_open;\n}\n\nbool\nSocketSource::getline(std::string& result, char delimiter)\n{\n    int buf;\n    while (true) {\n        buf = d_socket_buf->sbumpc();\n        if (buf == static_cast<int>(delimiter) || buf == SocketBuf::traits_type::eof()) {\n            if (!d_is_open) {\n                return false;\n            }\n            break;\n        }\n        result.push_back(static_cast<char>(buf));\n    }\n    return true;\n}\n\nSocketSource::~SocketSource()\n{\n    _close();\n}\n\n}  // namespace memray::io\n"
  },
  {
    "path": "src/memray/_memray/source.h",
    "content": "#pragma once\n\n#include <atomic>\n#include <cstdint>\n#include <fstream>\n#include <memory>\n#include <string>\n\n#include \"lz4_stream.h\"\n\nnamespace memray::io {\n\nconst int MAX_BUF_SIZE = 4096;\n\nclass Source\n{\n  public:\n    virtual ~Source(){};\n    virtual void close() = 0;\n    virtual bool is_open() = 0;\n    virtual bool read(char* result, ssize_t length) = 0;\n    virtual bool getline(std::string& result, char delimiter) = 0;\n};\n\nclass FileSource : public Source\n{\n  public:\n    FileSource(FileSource& other) = delete;\n    FileSource(FileSource&& other) = delete;\n    void operator=(const FileSource&) = delete;\n    void operator=(FileSource&&) = delete;\n\n    FileSource(const std::string& file_name);\n    ~FileSource() override;\n    void close() override;\n    bool is_open() override;\n    bool read(char* result, ssize_t length) override;\n    bool getline(std::string& result, char delimiter) override;\n\n  private:\n    void _close();\n    void findReadableSize();\n    const std::string& d_file_name;\n    std::shared_ptr<std::ifstream> d_raw_stream;\n    std::shared_ptr<std::istream> d_stream;\n    std::streamoff d_readable_size{};\n    std::streamoff d_bytes_read{};\n};\n\nclass SocketBuf : public std::streambuf\n{\n  public:\n    explicit SocketBuf(int socket_fd);\n    void close();\n\n  private:\n    int underflow() override;\n    std::streamsize xsgetn(char_type* s, std::streamsize n) override;\n    int d_sockfd{-1};\n    char d_buf[MAX_BUF_SIZE];\n    std::atomic<bool> d_open{true};\n};\n\nclass SocketSource : public Source\n{\n  public:\n    SocketSource(SocketSource& other) = delete;\n    SocketSource(SocketSource&& other) = delete;\n    void operator=(const SocketSource&) = delete;\n    void operator=(SocketSource&&) = delete;\n\n    SocketSource(int port);\n    ~SocketSource() override;\n    void close() override;\n    bool is_open() override;\n    bool read(char* result, ssize_t length) override;\n    bool getline(std::string& result, char delimiter) override;\n\n  private:\n    void _close();\n    int d_sockfd{-1};\n    std::atomic<bool> d_is_open{false};\n    std::unique_ptr<SocketBuf> d_socket_buf;\n};\n\n}  // namespace memray::io\n"
  },
  {
    "path": "src/memray/_memray/source.pxd",
    "content": "from libcpp cimport bool\nfrom libcpp.string cimport string\n\n\ncdef extern from \"source.h\" namespace \"memray::io\":\n    cdef cppclass Source:\n        pass\n\n    cdef cppclass FileSource(Source):\n        FileSource(const string& file_name) except+ IOError\n\n    cdef cppclass SocketSource(Source):\n        SocketSource(int port) except+ IOError\n"
  },
  {
    "path": "src/memray/_memray/tracking_api.cpp",
    "content": "#define PY_SSIZE_T_CLEAN\n#include <Python.h>\n\n#include <cassert>\n\n#ifdef __linux__\n#    include <link.h>\n#elif defined(__APPLE__)\n#    include \"macho_utils.h\"\n#    include <mach/mach.h>\n#    include <mach/task.h>\n#endif\n\n#include <algorithm>\n#include <mutex>\n#include <type_traits>\n#include <unistd.h>\n\n#include \"compat.h\"\n#include \"exceptions.h\"\n#include \"hooks.h\"\n#include \"record_writer.h\"\n#include \"records.h\"\n#include \"tracking_api.h\"\n\nusing namespace memray::exception;\nusing namespace std::chrono_literals;\n\nextern \"C\" Py_ssize_t\n_PyEval_RequestCodeExtraIndex(freefunc free);\nextern \"C\" int\n_PyCode_GetExtra(PyObject* code, Py_ssize_t index, void** extra);\nextern \"C\" int\n_PyCode_SetExtra(PyObject* code, Py_ssize_t index, void* extra);\n\nnamespace {\n\n#ifdef __linux__\nstd::string\nget_executable()\n{\n    char buff[PATH_MAX + 1];\n    ssize_t len = ::readlink(\"/proc/self/exe\", buff, sizeof(buff));\n    if (len > PATH_MAX) {\n        throw std::runtime_error(\"Path to executable is more than PATH_MAX bytes\");\n    } else if (len == -1) {\n        throw std::runtime_error(\"Could not determine executable path\");\n    }\n    return std::string(buff, len);\n}\n\nstatic bool\nstarts_with(const std::string& haystack, const std::string_view& needle)\n{\n    return haystack.compare(0, needle.size(), needle) == 0;\n}\n#endif\n\nclass StopTheWorldGuard\n{\n  public:\n    StopTheWorldGuard()\n    : d_interp(PyGILState_GetThisThreadState()->interp)\n    {\n        memray::compat::stopTheWorld(d_interp);\n    }\n\n    ~StopTheWorldGuard()\n    {\n        memray::compat::startTheWorld(d_interp);\n    }\n\n  private:\n    StopTheWorldGuard(const StopTheWorldGuard&) = delete;\n    StopTheWorldGuard& operator=(const StopTheWorldGuard&) = delete;\n    StopTheWorldGuard(StopTheWorldGuard&&) = delete;\n\n    PyInterpreterState* d_interp;\n};\n\n#if PY_VERSION_HEX < 0x030C0000\nPy_ssize_t s_extra_index = -1;\n#endif\n\n}  // namespace\n\nnamespace memray::tracking_api {\n\n#ifdef __linux__\nMEMRAY_FAST_TLS thread_local bool RecursionGuard::_isActive = false;\n#else\npthread_key_t RecursionGuard::isActiveKey;\n#endif\n\nstatic inline thread_id_t\ngenerate_next_tid()\n{\n    static std::atomic<thread_id_t> s_tid_counter = 0;\n    return ++s_tid_counter;\n}\n\nMEMRAY_FAST_TLS thread_local thread_id_t t_tid = generate_next_tid();\n\nstatic inline thread_id_t\nthread_id()\n{\n    return t_tid;\n}\n\n// Tracker interface\n\n// If a TLS variable has not been constructed, accessing it will cause it to be\n// constructed. That's normally great, but we need to prevent that from\n// happening unexpectedly for the TLS vector owned by this class.\n//\n// Methods of this class can be called during thread teardown. It's possible\n// that, after the TLS vector for a dying thread has already been destroyed,\n// libpthread makes a call to free() that calls into our Tracker, and if it\n// does, we must prevent it touching the vector again and re-constructing it.\n// Otherwise, it would be re-constructed immediately but its destructor would\n// be added to this thread's list of finalizers after all the finalizers for\n// the thread already ran.  If that happens, the vector will be free()d before\n// its destructor runs. Worse, its destructor will remain on the list of\n// finalizers for the current thread's pthread struct, and its destructor will\n// later be run on that already free()d memory if this thread's pthread struct\n// is ever reused. When that happens it tends to cause heap corruption, because\n// another vector is placed at the same location as the original one, and the\n// vector destructor runs twice on it (once for the newly created vector, and\n// once for the vector that had been created before the thread died and the\n// pthread struct was reused).\n//\n// To prevent that, we create the vector in one method, pushLazilyEmittedFrame.\n// All other methods access a pointer called `d_stack` that is set to the TLS\n// stack when it is created by pushLazilyEmittedFrame, and set to a null\n// pointer when the TLS stack is destroyed.\n//\n// This can result in this class being constructed during thread teardown, but\n// that doesn't cause the same problem because it has a trivial destructor.\nclass PythonStackTracker\n{\n  private:\n    PythonStackTracker() = default;\n\n    class LazilyEmittedFrame\n    {\n      public:\n        LazilyEmittedFrame(PyFrameObject* frame);\n\n        // Has this frame been emitted already?\n        bool isEmitted() const;\n\n        // Update the instruction offset from the frame, if possible.\n        // If the offset changes, mark the frame as not emitted.\n        void updateInstructionOffset();\n\n        // Drop our reference to the frame, freezing the instruction offset.\n        void freezeInstructionOffset();\n\n        // Has the instruction offset been frozen?\n        bool isFrozen() const;\n\n        // If we haven't already, register the held code object, saving its ID\n        // and dropping our borrowed reference to the code object.\n        void resolveCodeObjectId(Tracker& tracker);\n\n        // Emit this frame if it hasn't already been emitted.\n        // Returns true on success or if the frame was already emitted.\n        bool emit(Tracker& tracker);\n\n      private:\n        bool d_emitted{false};\n\n        // Threads' initial stacks can have calls to sys.settrace tracing\n        // functions which our profile function won't see get popped. We can't\n        // hold borrowed references to those frames; we won't know when they\n        // die. For frames on those initial stacks, we resolve the instruction\n        // offset once up front then set `d_frame` to a null pointer.\n        PyFrameObject* d_frame{};\n\n        // Likewise, we can't hold borrowed references to the code objects\n        // owned by initial frames. We drop our reference once a code object id\n        // has been assigned. For initial frames, we assign that ID while the\n        // world is stopped, before the reference could become invalid.\n        PyCodeObject* d_code{};\n\n        // Information extracted from PyCodeObject while the GIL is held,\n        // and later used while the GIL may not be held.\n        CodeObject d_code_info{};\n\n        // The unique ID assigned by the Tracker for the associated code object\n        code_object_id_t d_code_object_id{};\n\n        // Whether this frame is an entry frame for native unwinding purposes.\n        bool d_is_entry_frame{};\n\n        // The frame's current bytecode offset within the code object.\n        int d_instruction_offset{};\n    };\n\n  public:\n    static bool s_greenlet_tracking_enabled;\n    static bool s_native_tracking_enabled;\n\n    static void installProfileHooks();\n    static void recordAllStacks(Tracker& tracker);\n    static void removeProfileHooks();\n\n    static PythonStackTracker& get();\n    void emitPendingPushesAndPops();\n    void populateShadowStack();\n    void handleTraceEvent(int what, PyFrameObject* frame);\n\n    void installGreenletTraceFunctionIfNeeded();\n    void handleGreenletSwitch(PyObject* from, PyObject* to);\n\n  private:\n    // Fetch the thread-local stack tracker without checking if its stack needs to be reloaded.\n    static PythonStackTracker& getUnsafe();\n\n    static std::vector<LazilyEmittedFrame>\n    pythonFrameToStack(PyFrameObject* current_frame, Tracker& tracker);\n\n    void reloadStackIfTrackerChanged();\n    void clear();\n\n    void pushLazilyEmittedFrame(const LazilyEmittedFrame& frame);\n\n    int pushPythonFrame(PyFrameObject* frame);\n    void popPythonFrame();\n\n    static std::mutex s_mutex;\n    static std::unordered_map<PyThreadState*, std::vector<LazilyEmittedFrame>> s_initial_stack_by_thread;\n    static std::atomic<unsigned int> s_tracker_generation;\n\n    uint32_t d_num_pending_pops{};\n    uint32_t d_tracker_generation{};\n    std::vector<LazilyEmittedFrame>* d_stack{};\n    bool d_greenlet_hooks_installed{};\n};\n\nbool PythonStackTracker::s_greenlet_tracking_enabled{false};\nbool PythonStackTracker::s_native_tracking_enabled{false};\n\nstd::mutex PythonStackTracker::s_mutex;\nstd::unordered_map<PyThreadState*, std::vector<PythonStackTracker::LazilyEmittedFrame>>\n        PythonStackTracker::s_initial_stack_by_thread;\nstd::atomic<unsigned int> PythonStackTracker::s_tracker_generation;\n\nPythonStackTracker&\nPythonStackTracker::get()\n{\n    PythonStackTracker& ret = getUnsafe();\n    ret.reloadStackIfTrackerChanged();\n    return ret;\n}\n\nPythonStackTracker&\nPythonStackTracker::getUnsafe()\n{\n    // See giant comment above.\n    static_assert(std::is_trivially_destructible<PythonStackTracker>::value);\n    MEMRAY_FAST_TLS thread_local PythonStackTracker t_python_stack_tracker;\n    return t_python_stack_tracker;\n}\n\nvoid\nPythonStackTracker::emitPendingPushesAndPops()\n{\n    if (!d_stack) {\n        return;\n    }\n\n    if (!d_stack->empty()) {\n        PyThreadState* ts = PyGILState_GetThisThreadState();\n        if (!ts || ts->c_profilefunc != PyTraceFunction) {\n            // Note: clear() will call back into emitPendingPushesAndPops() to\n            //       emit the pops, but we won't call back into clear() because\n            //       the stack has already been emptied.\n            clear();\n            return;\n        }\n    }\n\n#ifdef Py_GIL_DISABLED\n    PyGILState_STATE gstate = PyGILState_Ensure();\n#endif\n\n    // At any time, the stack contains (from beginning to end) any number of\n    // emitted frames followed by any number of not yet emitted frames.\n    // The line number of the last emitted frame may be out of date.\n    // We iterate in reverse order, to see the not emitted frames first.\n    // After the loop, `it` points to the first frame not to need emitting,\n    // or to `rend()` if all frames need emitting.\n    auto it = d_stack->rbegin();\n    for (; it != d_stack->rend(); ++it) {\n        // Note: updateInstructionOffset() may change isEmitted()!\n        if (!it->isEmitted()) {\n            // Has not been emitted before; now will be the first time.\n            it->updateInstructionOffset();\n        } else {\n            // Has been emitted...\n            it->updateInstructionOffset();\n            if (it->isEmitted()) {\n                // ... and the line number didn't change. This and all later\n                // frames have been emitted and don't need to be re-emitted.\n                break;\n            } else {\n                // ... but the instruction offset was wrong; emit an artificial\n                // pop so we can push back in with the right offset.\n                d_num_pending_pops++;\n\n                // The next frame is the first to not need (re)emitting.\n                ++it;\n                break;\n            }\n        }\n    }\n    auto first_to_emit = it.base();\n\n    Tracker* tracker = Tracker::getTracker();\n    if (tracker) {\n        // Emit pending pops\n        if (d_num_pending_pops) {\n            tracker->popFrames(d_num_pending_pops);\n            d_num_pending_pops = 0;\n        }\n\n        // Emit pending pushes\n        for (auto to_emit = first_to_emit; to_emit != d_stack->end(); ++to_emit) {\n            if (!to_emit->emit(*tracker)) {\n                break;\n            }\n        }\n    }\n\n#ifdef Py_GIL_DISABLED\n    PyGILState_Release(gstate);\n#endif\n}\n\nvoid\nPythonStackTracker::reloadStackIfTrackerChanged()\n{\n    // Note: this function does not require the GIL.\n    if (d_tracker_generation == s_tracker_generation) {\n        return;\n    }\n\n    // If we reach this point, a new Tracker was installed by another thread,\n    // which also captured our Python stack. Trust it, ignoring any stack we\n    // already hold (since the stack we hold could be incorrect if tracking\n    // stopped and later restarted underneath our still-running thread).\n\n    if (d_stack) {\n        d_stack->clear();\n    }\n    d_num_pending_pops = 0;\n\n    std::vector<LazilyEmittedFrame> correct_stack;\n\n    {\n        std::unique_lock<std::mutex> lock(s_mutex);\n        d_tracker_generation = s_tracker_generation;\n\n        auto it = s_initial_stack_by_thread.find(PyGILState_GetThisThreadState());\n        if (it != s_initial_stack_by_thread.end()) {\n            it->second.swap(correct_stack);\n            s_initial_stack_by_thread.erase(it);\n        }\n    }\n\n    // Iterate in reverse so that we push the most recent call last\n    for (auto frame_it = correct_stack.rbegin(); frame_it != correct_stack.rend(); ++frame_it) {\n        pushLazilyEmittedFrame(*frame_it);\n    }\n}\n\nvoid\nPythonStackTracker::populateShadowStack()\n{\n    installGreenletTraceFunctionIfNeeded();\n\n    clear();\n\n    PyFrameObject* frame = PyEval_GetFrame();\n\n    std::vector<PyFrameObject*> stack;\n    while (frame) {\n        stack.push_back(frame);\n        frame = compat::frameGetBack(frame);\n    }\n\n    std::for_each(stack.rbegin(), stack.rend(), [this](auto& frame) { pushPythonFrame(frame); });\n}\n\nvoid\nPythonStackTracker::handleTraceEvent(int what, PyFrameObject* frame)\n{\n    installGreenletTraceFunctionIfNeeded();\n\n    if (d_stack && !d_stack->empty() && d_stack->back().isFrozen()) {\n        // This stack was set by reloadStackIfTrackerChanged and may have calls\n        // to sys.settrace tracing functions on it. Drop it now, replacing it\n        // with a stack fetched from PyEval_GetFrame which we know can't have\n        // trace function frames on it, and which we can track properly.\n        populateShadowStack();\n\n        if (what == PyTrace_CALL) {\n            // The stack we just populated includes the frame for this call.\n            // Return early to avoid duplicating it.\n            return;\n        }\n    }\n\n    if (what == PyTrace_CALL) {\n        pushPythonFrame(frame);\n    } else if (what == PyTrace_RETURN) {\n        popPythonFrame();\n    }\n}\n\nint\nPythonStackTracker::pushPythonFrame(PyFrameObject* frame)\n{\n    try {\n        pushLazilyEmittedFrame(LazilyEmittedFrame(frame));\n        return 0;\n    } catch (const std::runtime_error&) {\n        return -1;\n    }\n}\n\nvoid\nPythonStackTracker::pushLazilyEmittedFrame(const LazilyEmittedFrame& frame)\n{\n    // Note: this function does not require the GIL.\n    struct StackCreator\n    {\n        std::vector<LazilyEmittedFrame> stack;\n\n        StackCreator()\n        {\n            const size_t INITIAL_PYTHON_STACK_FRAMES = 1024;\n            stack.reserve(INITIAL_PYTHON_STACK_FRAMES);\n            PythonStackTracker::getUnsafe().d_stack = &stack;\n        }\n        ~StackCreator()\n        {\n            PythonStackTracker::getUnsafe().d_stack = nullptr;\n        }\n    };\n\n    MEMRAY_FAST_TLS static thread_local StackCreator t_stack_creator;\n    t_stack_creator.stack.push_back(frame);\n    assert(d_stack);  // The above call sets d_stack if it wasn't already set.\n}\n\nvoid\nPythonStackTracker::popPythonFrame()\n{\n    if (!d_stack || d_stack->empty()) {\n        return;\n    }\n\n    if (d_stack->back().isEmitted()) {\n        d_num_pending_pops += 1;\n        assert(d_num_pending_pops != 0);  // Ensure we didn't overflow.\n    }\n    d_stack->pop_back();\n}\n\nvoid\nPythonStackTracker::installGreenletTraceFunctionIfNeeded()\n{\n    if (!s_greenlet_tracking_enabled || d_greenlet_hooks_installed) {\n        return;  // Nothing to do.\n    }\n\n    assert(PyGILState_Check());\n\n    RecursionGuard guard;\n\n    // Borrowed reference\n    PyObject* modules = PySys_GetObject(\"modules\");\n    if (!modules) {\n        return;\n    }\n\n    // Borrowed reference\n    // Look directly at `sys.modules` since we only want to do something if\n    // `greenlet._greenlet` has already been imported.\n    PyObject* _greenlet = PyDict_GetItemString(modules, \"greenlet._greenlet\");\n    if (!_greenlet) {\n        // Before greenlet 1.0, the extension module was just named \"greenlet\"\n        _greenlet = PyDict_GetItemString(modules, \"greenlet\");\n        if (!_greenlet) {\n            return;\n        }\n    }\n\n    // Borrowed reference\n    PyObject* _memray = PyDict_GetItemString(modules, \"memray._memray\");\n    if (!_memray) {\n        return;\n    }\n\n    PyObject* ret = PyObject_CallMethod(\n            _greenlet,\n            \"settrace\",\n            \"N\",\n            PyObject_GetAttrString(_memray, \"greenlet_trace_function\"));\n    Py_XDECREF(ret);\n\n    if (!ret) {\n        // This might be hit from PyGILState_Ensure when a new thread state is\n        // created on a C thread, so we can't reasonably raise the exception.\n        PyErr_Print();\n        _exit(1);\n    }\n\n    // Note: guarded by the GIL\n    d_greenlet_hooks_installed = true;\n\n    static bool warned = false;\n    if (!warned) {\n        warned = true;\n\n        PyObject* res = PyObject_CallMethod(_memray, \"print_greenlet_warning\", nullptr);\n        Py_XDECREF(res);\n        if (!res) {\n            PyErr_Print();\n            _exit(1);\n        }\n    }\n}\n\nvoid\nPythonStackTracker::handleGreenletSwitch(PyObject* from, PyObject* to)\n{\n    RecursionGuard guard;\n\n    // Clear any old TLS stack, emitting pops for frames that had been pushed.\n    this->clear();\n\n    // Save current TID on old greenlet. Print errors but otherwise ignore them.\n    PyObject* tid = PyLong_FromUnsignedLong(t_tid);\n    if (!tid || 0 != PyObject_SetAttrString(from, \"_memray_tid\", tid)) {\n        PyErr_Print();\n    }\n    Py_XDECREF(tid);\n\n    // Restore TID from new greenlet, or generate a new one. Ignore errors:\n    // maybe we haven't seen this TID before, or maybe someone overwrote our\n    // attribute, but either way we can recover by generating a new one.\n    tid = PyObject_GetAttrString(to, \"_memray_tid\");\n    if (!tid || !PyLong_CheckExact(tid)) {\n        PyErr_Clear();\n        t_tid = generate_next_tid();\n    } else {\n        t_tid = PyLong_AsUnsignedLong(tid);\n    }\n    Py_XDECREF(tid);\n\n    populateShadowStack();\n}\n\nstd::unique_ptr<std::mutex> Tracker::s_mutex(new std::mutex);\npthread_key_t Tracker::s_native_unwind_vector_key;\nstd::unique_ptr<Tracker> Tracker::s_instance_owner;\nstd::atomic<Tracker*> Tracker::s_instance = nullptr;\n\nPythonStackTracker::LazilyEmittedFrame::LazilyEmittedFrame(PyFrameObject* frame)\n{\n    assert(PyGILState_Check());\n\n    d_frame = frame;\n    d_code = compat::frameGetCode(frame);\n#if PY_VERSION_HEX < 0x030C0000\n    if (s_extra_index != -1) {\n        void* extra;\n        if (-1 == _PyCode_GetExtra((PyObject*)d_code, s_extra_index, &extra)) {\n            throw std::runtime_error(\"Failed to get extra data from code object\");\n        }\n        if (!extra && -1 == _PyCode_SetExtra((PyObject*)d_code, s_extra_index, d_code)) {\n            throw std::runtime_error(\"Failed to set extra data on code object\");\n        }\n    }\n#endif\n\n    d_code_info.function_name = PyUnicode_AsUTF8(d_code->co_name);\n    if (d_code_info.function_name == nullptr) {\n        throw std::runtime_error(\"Failed to get function name from frame\");\n    }\n\n    d_code_info.filename = PyUnicode_AsUTF8(d_code->co_filename);\n    if (d_code_info.filename == nullptr) {\n        throw std::runtime_error(\"Failed to get filename from frame\");\n    }\n\n    // Get linetable information\n    d_code_info.linetable = compat::codeGetLinetable(d_code, &d_code_info.linetable_size);\n    d_code_info.firstlineno = d_code->co_firstlineno;\n\n    // If native tracking is not enabled, treat every frame as an entry frame.\n    // It doesn't matter to the reader, and is more efficient.\n    d_is_entry_frame = !s_native_tracking_enabled || compat::isEntryFrame(frame);\n}\n\nbool\nPythonStackTracker::LazilyEmittedFrame::isEmitted() const\n{\n    return d_emitted;\n}\n\nvoid\nPythonStackTracker::LazilyEmittedFrame::updateInstructionOffset()\n{\n    if (d_frame) {\n        auto old_instruction_offset = d_instruction_offset;\n        d_instruction_offset = compat::frameGetLasti(d_frame);\n\n        if (d_instruction_offset != old_instruction_offset) {\n            d_emitted = false;\n        }\n    }\n}\n\nvoid\nPythonStackTracker::LazilyEmittedFrame::freezeInstructionOffset()\n{\n    d_frame = nullptr;\n}\n\nbool\nPythonStackTracker::LazilyEmittedFrame::isFrozen() const\n{\n    return d_frame == nullptr;\n}\n\nvoid\nPythonStackTracker::LazilyEmittedFrame::resolveCodeObjectId(Tracker& tracker)\n{\n    if (d_code) {\n        d_code_object_id = tracker.registerCodeObject(d_code, d_code_info);\n        d_code = nullptr;\n    }\n}\n\nbool\nPythonStackTracker::LazilyEmittedFrame::emit(Tracker& tracker)\n{\n    if (d_emitted) {\n        return true;  // Already emitted.\n    }\n\n    resolveCodeObjectId(tracker);\n    bool ret = tracker.pushFrame(Frame{d_code_object_id, d_instruction_offset, d_is_entry_frame});\n    if (ret) {\n        d_emitted = true;\n    }\n    return ret;\n}\n\nstd::vector<PythonStackTracker::LazilyEmittedFrame>\nPythonStackTracker::pythonFrameToStack(PyFrameObject* current_frame, Tracker& tracker)\n{\n    std::vector<LazilyEmittedFrame> stack;\n    while (current_frame) {\n        try {\n            stack.push_back(LazilyEmittedFrame(current_frame));\n        } catch (const std::runtime_error&) {\n            return {};\n        }\n\n        stack.back().resolveCodeObjectId(tracker);\n        stack.back().updateInstructionOffset();\n        stack.back().freezeInstructionOffset();\n        current_frame = compat::frameGetBack(current_frame);\n    }\n\n    return stack;\n}\n\nvoid\nPythonStackTracker::recordAllStacks(Tracker& tracker)\n{\n    // We need to ensure that stacks are captured atomically with respect to\n    // incrementing s_tracker_generation and to setting Tracker::isActive().\n    // The caller must use the GIL for this in with-GIL builds, and call\n    // _PyEval_StopTheWorld in free-threaded builds. Otherwise, the shadow\n    // stack may become inconsistent with the true stack for a thread, which\n    // leads to frames being used after they've been freed.\n\n    // Additionally, the Tracker mutex must be held, as pythonFrameToStack\n    // calls registerCodeObject. The Tracker is an argument as this function\n    // is called before tracking is activated and the singleton is installed.\n\n    assert(PyGILState_Check());\n    PyThreadState* current_thread = PyThreadState_Get();\n\n    // Record the current Python stack of every thread\n    std::unordered_map<PyThreadState*, std::vector<LazilyEmittedFrame>> stack_by_thread;\n    for (PyThreadState* tstate =\n                 PyInterpreterState_ThreadHead(compat::threadStateGetInterpreter(current_thread));\n         tstate != nullptr;\n         tstate = PyThreadState_Next(tstate))\n    {\n        if (tstate == current_thread) {\n            // Handled by the call to populateShadowStack in below\n            continue;\n        }\n\n        PyFrameObject* frame = compat::threadStateGetFrame(tstate);\n        if (!frame) {\n            continue;\n        }\n\n        stack_by_thread[tstate] = pythonFrameToStack(frame, tracker);\n        if (PyErr_Occurred()) {\n            throw std::runtime_error(\"Failed to capture a thread's Python stack\");\n        }\n    }\n\n    {\n        std::unique_lock<std::mutex> lock(s_mutex);\n        s_initial_stack_by_thread.swap(stack_by_thread);\n\n        // Register that tracking has begun (again?), telling threads to sync their\n        // TLS from these captured stacks. Update this atomically with the map, or\n        // a thread that's 2 generations behind could grab the new stacks with the\n        // previous generation number and immediately think they're out of date.\n        s_tracker_generation++;\n    }\n\n    PythonStackTracker::get().populateShadowStack();\n}\n\nvoid\nPythonStackTracker::installProfileHooks()\n{\n    // Install our profile function in all existing threads. Note that the\n    // profile function may begin executing before recordAllStacks is called.\n    compat::setprofileAllThreads(PyTraceFunction, nullptr);\n}\n\nvoid\nPythonStackTracker::removeProfileHooks()\n{\n    assert(PyGILState_Check());\n    compat::setprofileAllThreads(nullptr, nullptr);\n    std::unique_lock<std::mutex> lock(s_mutex);\n    s_initial_stack_by_thread.clear();\n}\n\nvoid\nPythonStackTracker::clear()\n{\n    if (!d_stack) {\n        return;\n    }\n\n    d_num_pending_pops +=\n            std::count_if(d_stack->begin(), d_stack->end(), [](const auto& f) { return f.isEmitted(); });\n    d_stack->clear();\n    emitPendingPushesAndPops();\n}\n\nTracker::Tracker(\n        std::unique_ptr<RecordWriter> record_writer,\n        bool native_traces,\n        unsigned int memory_interval,\n        bool follow_fork,\n        bool trace_python_allocators,\n        bool reference_tracking)\n: d_writer(std::move(record_writer))\n, d_unwind_native_frames(native_traces)\n, d_memory_interval(memory_interval)\n, d_follow_fork(follow_fork)\n, d_trace_python_allocators(trace_python_allocators)\n, d_reference_tracking(reference_tracking)\n{\n    static std::once_flag once;\n    call_once(once, [] {\n        // We use the pthread TLS API for this vector because we must be able\n        // to re-create it while TLS destructors are running (a destructor can\n        // call malloc, hitting our malloc hook). POSIX guarantees multiple\n        // rounds of TLS destruction if destructors call pthread_setspecific.\n        // Note: If this raises an exception, the call_once can be retried.\n        if (0 != pthread_key_create(&s_native_unwind_vector_key, [](void* data) {\n                delete static_cast<std::vector<NativeTrace::ip_t>*>(data);\n            }))\n        {\n            throw std::runtime_error{\"Failed to create pthread key\"};\n        }\n\n        hooks::ensureAllHooksAreValid();\n        NativeTrace::setup();\n\n#if PY_VERSION_HEX >= 0x030C0000\n        PyCode_AddWatcher([](PyCodeEvent event, PyCodeObject* code) {\n            if (event == PY_CODE_EVENT_DESTROY) {\n                if (RecursionGuard::isActive() || !Tracker::isActive()) {\n                    return 0;\n                }\n                RecursionGuard guard;\n\n                std::unique_lock<std::mutex> lock(*s_mutex);\n                Tracker* tracker = Tracker::getTracker();\n                if (tracker) {\n                    tracker->forgetCodeObject(code);\n                }\n            }\n            return 0;\n        });\n#else\n        s_extra_index = _PyEval_RequestCodeExtraIndex([](void* code) {\n            if (RecursionGuard::isActive() || !Tracker::isActive()) {\n                return;\n            }\n            RecursionGuard guard;\n\n            std::unique_lock<std::mutex> lock(*s_mutex);\n            Tracker* tracker = Tracker::getTracker();\n            if (tracker) {\n                tracker->forgetCodeObject((PyCodeObject*)code);\n            }\n        });\n#endif\n    });\n\n    d_writer->setMainTidAndSkippedFrames(thread_id(), computeMainTidSkip());\n    if (!d_writer->writeHeader(false)) {\n        throw IoError{\"Failed to write output header\"};\n    }\n\n    RecursionGuard guard;\n    updateModuleCacheImpl();\n\n    PythonStackTracker::s_native_tracking_enabled = native_traces;\n    PythonStackTracker::installProfileHooks();\n    if (d_reference_tracking) {\n        registerReferenceTrackingHooks();\n    }\n    if (d_trace_python_allocators) {\n        registerPymallocHooks();\n    }\n    d_background_thread = std::make_unique<BackgroundThread>(d_writer, memory_interval);\n    d_background_thread->start();\n\n    d_patcher.overwrite_symbols();\n}\n\nTracker::~Tracker()\n{\n    RecursionGuard guard;\n    tracking_api::Tracker::deactivate();\n\n    PythonStackTracker::s_native_tracking_enabled = false;\n    d_background_thread->stop();\n\n    {\n        std::scoped_lock<std::mutex> lock(*s_mutex);\n        d_patcher.restore_symbols();\n    }\n\n    if (Py_IsInitialized() && !compat::isPythonFinalizing()) {\n        PyGILState_STATE gstate;\n        gstate = PyGILState_Ensure();\n\n        if (d_reference_tracking) {\n            std::scoped_lock<std::mutex> lock(*s_mutex);\n            unregisterReferenceTrackingHooks();\n        }\n\n        if (d_trace_python_allocators) {\n            std::scoped_lock<std::mutex> lock(*s_mutex);\n            unregisterPymallocHooks();\n        }\n\n        PythonStackTracker::removeProfileHooks();\n\n        PyGILState_Release(gstate);\n    }\n\n    std::scoped_lock<std::mutex> lock(*s_mutex);\n    d_tracked_objects.clear();\n    d_writer->writeTrailer();\n    d_writer->writeHeader(true);\n    d_writer.reset();\n}\n\nTracker::BackgroundThread::BackgroundThread(\n        std::shared_ptr<RecordWriter> record_writer,\n        unsigned int memory_interval)\n: d_writer(std::move(record_writer))\n, d_memory_interval(memory_interval)\n{\n#ifdef __linux__\n    d_procs_statm.open(\"/proc/self/statm\");\n    if (!d_procs_statm) {\n        throw IoError{\"Failed to open /proc/self/statm\"};\n    }\n#endif\n}\n\nuint64_t\nTracker::BackgroundThread::timeElapsed()\n{\n    std::chrono::milliseconds ms = std::chrono::duration_cast<std::chrono::milliseconds>(\n            std::chrono::system_clock::now().time_since_epoch());\n    return ms.count();\n}\n\nsize_t\nTracker::BackgroundThread::getRSS() const\n{\n#ifdef __linux__\n    static long pagesize = sysconf(_SC_PAGE_SIZE);\n    constexpr int max_unsigned_long_chars = std::numeric_limits<unsigned long>::digits10 + 1;\n    constexpr int bufsize = (max_unsigned_long_chars + sizeof(' ')) * 2;\n    char buffer[bufsize];\n    d_procs_statm.read(buffer, sizeof(buffer) - 1);\n    buffer[d_procs_statm.gcount()] = '\\0';\n    d_procs_statm.clear();\n    d_procs_statm.seekg(0);\n\n    size_t rss;\n    if (sscanf(buffer, \"%*u %zu\", &rss) != 1) {\n        std::cerr << \"WARNING: Failed to read RSS value from /proc/self/statm\" << std::endl;\n        d_procs_statm.close();\n        return 0;\n    }\n\n    return rss * pagesize;\n#elif defined(__APPLE__)\n    struct mach_task_basic_info info;\n    mach_msg_type_number_t infoCount = MACH_TASK_BASIC_INFO_COUNT;\n    if (task_info(mach_task_self(), MACH_TASK_BASIC_INFO, (task_info_t)&info, &infoCount)\n        != KERN_SUCCESS)\n        return (size_t)0L; /* Can't access? */\n    return (size_t)info.resident_size;\n#else\n    return 0;\n#endif\n}\n\nbool\nTracker::BackgroundThread::captureMemorySnapshot()\n{\n    auto now = timeElapsed();\n    size_t rss = getRSS();\n    if (rss == 0) {\n        std::cerr << \"Failed to detect RSS, deactivating tracking\" << std::endl;\n        Tracker::deactivate();\n        return false;\n    }\n\n    std::lock_guard<std::mutex> lock(*s_mutex);\n    if (!d_writer->writeRecord(MemoryRecord{now, rss})) {\n        std::cerr << \"Failed to write output, deactivating tracking\" << std::endl;\n        Tracker::deactivate();\n        return false;\n    }\n\n    return true;\n}\n\nvoid\nTracker::BackgroundThread::start()\n{\n    assert(d_thread.get_id() == std::thread::id());\n\n    if (!captureMemorySnapshot()) {\n        return;\n    }\n\n    d_thread = std::thread([&]() {\n        RecursionGuard::setValue(true);\n        while (true) {\n            {\n                std::unique_lock<std::mutex> lock(d_mutex);\n                d_cv.wait_for(lock, d_memory_interval * 1ms, [this]() { return d_stop; });\n                if (d_stop) {\n                    return;\n                }\n            }\n\n            if (!captureMemorySnapshot()) {\n                return;\n            }\n        }\n    });\n}\n\nvoid\nTracker::BackgroundThread::stop()\n{\n    {\n        std::scoped_lock<std::mutex> lock(d_mutex);\n        d_stop = true;\n    }\n    d_cv.notify_one();\n    if (d_thread.joinable()) {\n        try {\n            d_thread.join();\n        } catch (const std::system_error&) {\n        }\n    }\n}\n\nvoid\nTracker::prepareFork()\n{\n    // Don't do any custom track_allocation handling while inside fork\n    RecursionGuard::setValue(true);\n}\n\nvoid\nTracker::parentFork()\n{\n    // We can continue tracking\n    RecursionGuard::setValue(false);\n}\n\nvoid\nTracker::childFork()\n{\n    // Intentionally leak any old tracker. Its destructor cannot be called,\n    // because it would try to destroy mutexes that might be locked by threads\n    // that no longer exist, and to join a background thread that no longer\n    // exists, and potentially to flush buffered output to a socket it no\n    // longer owns. Note that d_instance_owner is always set after d_instance\n    // and unset before d_instance.\n    (void)s_instance_owner.release();\n\n    // Likewise, leak our old mutex, and re-create it.\n    (void)s_mutex.release();\n    s_mutex.reset(new std::mutex);\n\n    // Save a reference to the old tracker (if any), then unset our singleton.\n    Tracker* old_tracker = s_instance;\n    Tracker::deactivate();\n\n    // If we inherited an active tracker, try to clone its record writer.\n    std::unique_ptr<RecordWriter> new_writer;\n    if (old_tracker && old_tracker->d_follow_fork) {\n        new_writer = old_tracker->d_writer->cloneInChildProcess();\n    }\n\n    if (!new_writer) {\n        // Either tracking wasn't active, or the tracker was using a sink that\n        // can't be cloned. Leave our singleton unset and bail out. Note that\n        // the old tracker's hooks may still be installed.  If this process\n        // exits, trackDeallocation will be called to track the deallocation of\n        // s_mutex when the process's globals are destroyed! To handle this,\n        // the hooks must check the (static) isActive() flag before acquiring\n        // s_mutex or calling any methods on the now null tracker singleton.\n        RecursionGuard::setValue(false);\n        return;\n    }\n\n    // Re-enable tracking with a brand new tracker.\n    // Disable tracking until the new tracker is fully installed.\n    s_instance_owner.reset(new Tracker(\n            std::move(new_writer),\n            old_tracker->d_unwind_native_frames,\n            old_tracker->d_memory_interval,\n            old_tracker->d_follow_fork,\n            old_tracker->d_trace_python_allocators,\n            old_tracker->d_reference_tracking));\n\n    StopTheWorldGuard stop_the_world;\n    std::unique_lock<std::mutex> lock(*s_mutex);\n    PythonStackTracker::recordAllStacks(*s_instance_owner);\n    tracking_api::Tracker::activate();\n    RecursionGuard::setValue(false);\n}\n\nsize_t\nTracker::computeMainTidSkip()\n{\n    // Determine how many frames from the current stack to elide from our\n    // reported stack traces. This avoids showing the user frames above the one\n    // that called `Tracker.__enter__`.\n    assert(PyGILState_Check());\n\n    PyFrameObject* frame = PyEval_GetFrame();\n\n    size_t num_frames = 0;\n    while (frame) {\n        ++num_frames;\n        frame = compat::frameGetBack(frame);\n    }\n\n    assert(num_frames > 0);\n    return num_frames - 1;\n}\n\nbool\nTracker::areNativeTracesEnabled()\n{\n    return PythonStackTracker::s_native_tracking_enabled;\n}\n\nvoid\nTracker::trackAllocationImpl(\n        void* ptr,\n        size_t size,\n        hooks::Allocator func,\n        const std::optional<NativeTrace>& trace)\n{\n    registerCachedThreadName();\n    PythonStackTracker::get().emitPendingPushesAndPops();\n\n    if (d_unwind_native_frames) {\n        frame_id_t native_index = 0;\n\n        // Skip the internal frames so we don't need to filter them later.\n        if (trace && trace.value().size()) {\n            native_index =\n                    d_native_trace_tree.getTraceIndex(trace.value(), [&](frame_id_t ip, uint32_t index) {\n                        return d_writer->writeRecord(UnresolvedNativeFrame{ip, index});\n                    });\n        }\n        AllocationRecord record{reinterpret_cast<uintptr_t>(ptr), size, func, native_index};\n        if (!d_writer->writeThreadSpecificRecord(thread_id(), record)) {\n            std::cerr << \"Failed to write output, deactivating tracking\" << std::endl;\n            deactivate();\n        }\n    } else {\n        AllocationRecord record{reinterpret_cast<uintptr_t>(ptr), size, func};\n        if (!d_writer->writeThreadSpecificRecord(thread_id(), record)) {\n            std::cerr << \"Failed to write output, deactivating tracking\" << std::endl;\n            deactivate();\n        }\n    }\n}\n\nvoid\nTracker::trackDeallocationImpl(void* ptr, size_t size, hooks::Allocator func)\n{\n    registerCachedThreadName();\n    AllocationRecord record{reinterpret_cast<uintptr_t>(ptr), size, func};\n    if (!d_writer->writeThreadSpecificRecord(thread_id(), record)) {\n        std::cerr << \"Failed to write output, deactivating tracking\" << std::endl;\n        deactivate();\n    }\n}\n\nvoid\nTracker::trackObjectImpl(PyObject* obj, int event, const std::optional<NativeTrace>& trace)\n{\n    registerCachedThreadName();\n    PythonStackTracker::get().emitPendingPushesAndPops();\n\n    if (event == 0) {  // Creation event\n        d_tracked_objects.emplace(obj);\n\n        if (d_unwind_native_frames) {\n            frame_id_t native_index = 0;\n            // Skip the internal frames so we don't need to filter them later.\n            if (trace && trace.value().size()) {\n                native_index = d_native_trace_tree.getTraceIndex(\n                        trace.value(),\n                        [&](frame_id_t ip, uint32_t index) {\n                            return d_writer->writeRecord(UnresolvedNativeFrame{ip, index});\n                        });\n            }\n\n            ObjectRecord record{reinterpret_cast<uintptr_t>(obj), true, native_index};\n            if (!d_writer->writeThreadSpecificRecord(thread_id(), record)) {\n                std::cerr << \"Failed to write output, deactivating tracking\" << std::endl;\n                deactivate();\n            }\n        } else {\n            ObjectRecord record{reinterpret_cast<uintptr_t>(obj), true};\n            if (!d_writer->writeThreadSpecificRecord(thread_id(), record)) {\n                std::cerr << \"Failed to write output, deactivating tracking\" << std::endl;\n                deactivate();\n            }\n        }\n    } else {  // Destruction event\n        d_tracked_objects.erase(obj);\n        ObjectRecord record{reinterpret_cast<uintptr_t>(obj), false};\n        if (!d_writer->writeThreadSpecificRecord(thread_id(), record)) {\n            std::cerr << \"Failed to write output, deactivating tracking\" << std::endl;\n            deactivate();\n        }\n    }\n}\n\nvoid\nTracker::invalidate_module_cache_impl()\n{\n    d_patcher.overwrite_symbols();\n    updateModuleCacheImpl();\n}\n\n#ifdef __linux__\nstatic int\ndl_iterate_phdr_callback(struct dl_phdr_info* info, [[maybe_unused]] size_t size, void* data)\n{\n    auto& mappings = *reinterpret_cast<std::vector<ImageSegments>*>(data);\n    const char* filename = info->dlpi_name;\n    std::string executable;\n    assert(filename != nullptr);\n    if (!filename[0]) {\n        executable = get_executable();\n        filename = executable.c_str();\n    }\n    if (::starts_with(filename, \"linux-vdso.so\")) {\n        // This cannot be resolved to anything, so don't write it to the file\n        return 0;\n    }\n\n    std::vector<Segment> segments;\n    for (int i = 0; i < info->dlpi_phnum; i++) {\n        const auto& phdr = info->dlpi_phdr[i];\n        if (phdr.p_type == PT_LOAD) {\n            segments.emplace_back(Segment{phdr.p_vaddr, phdr.p_memsz});\n        }\n    }\n\n    mappings.push_back({filename, info->dlpi_addr, std::move(segments)});\n    return 0;\n}\n#endif\n\nvoid\nTracker::updateModuleCacheImpl()\n{\n    if (!d_unwind_native_frames) {\n        return;\n    }\n\n    static size_t s_last_mappings_size = 20;\n\n    std::vector<ImageSegments> mappings;\n    mappings.reserve(s_last_mappings_size + 1);\n\n#ifdef __linux__\n    dl_iterate_phdr(&dl_iterate_phdr_callback, &mappings);\n#elif defined(__APPLE__)\n    uint32_t c = _dyld_image_count();\n    for (uint32_t i = 0; i < c; i++) {\n        const struct mach_header* header = _dyld_get_image_header(i);\n        auto slide = static_cast<uintptr_t>(_dyld_get_image_vmaddr_slide(i));\n        const char* image_name = _dyld_get_image_name(i);\n        std::vector<Segment> segments;\n\n        const segment_command_t* current_segment_cmd;\n        uintptr_t current_cmd = reinterpret_cast<uintptr_t>(header) + sizeof(mach_header_t);\n        for (uint j = 0; j < header->ncmds; j++, current_cmd += current_segment_cmd->cmdsize) {\n            current_segment_cmd = reinterpret_cast<const segment_command_t*>(current_cmd);\n            if (current_segment_cmd->cmd == ARCH_LC_SEGMENT) {\n                segments.emplace_back(Segment{current_segment_cmd->vmaddr, current_segment_cmd->vmsize});\n            }\n        }\n\n        mappings.push_back({image_name, slide, std::move(segments)});\n    }\n#endif\n\n    s_last_mappings_size = mappings.size();\n\n    if (!d_writer->writeMappings(mappings)) {\n        std::cerr << \"memray: Failed to write output, deactivating tracking\" << std::endl;\n        Tracker::deactivate();\n        return;\n    }\n}\n\nvoid\nTracker::registerThreadNameImpl(const char* name)\n{\n    RecursionGuard guard;\n    dropCachedThreadName();\n    if (!d_writer->writeThreadSpecificRecord(thread_id(), ThreadRecord{name})) {\n        std::cerr << \"memray: Failed to write output, deactivating tracking\" << std::endl;\n        deactivate();\n    }\n}\n\nvoid\nTracker::registerCachedThreadName()\n{\n    if (d_cached_thread_names.empty()) {\n        return;\n    }\n\n    auto it = d_cached_thread_names.find((uint64_t)(pthread_self()));\n    if (it != d_cached_thread_names.end()) {\n        auto& name = it->second;\n        if (!d_writer->writeThreadSpecificRecord(thread_id(), ThreadRecord{name.c_str()})) {\n            std::cerr << \"memray: Failed to write output, deactivating tracking\" << std::endl;\n            deactivate();\n        }\n        d_cached_thread_names.erase(it);\n    }\n}\n\nvoid\nTracker::dropCachedThreadName()\n{\n    d_cached_thread_names.erase((uint64_t)(pthread_self()));\n}\n\nvoid\nTracker::registerReferenceTrackingHooks() const noexcept\n{\n    compat::refTracerSetTracer(intercept::pyreftracer, nullptr);\n}\n\nvoid\nTracker::unregisterReferenceTrackingHooks() const noexcept\n{\n    compat::refTracerSetTracer(nullptr, nullptr);\n}\n\nstd::unordered_set<PyObject*>\nTracker::getSurvivingObjects()\n{\n    std::scoped_lock<std::mutex> lock(*s_mutex);\n    RecursionGuard guard;\n\n    std::unordered_set<PyObject*> surviving_objects;\n    // remove everything with 0 refcount\n    for (auto obj : d_tracked_objects) {\n#ifndef Py_GIL_DISABLED\n        // CPython used to have some bugs where deallocation of objects\n        // wasn't triggering the tracking hooks and that was causing us\n        // to see deleted objects at this stage. This check is left here\n        // as a precaution to know if CPython is still missing some cases\n        // still. The check is not done in free-threaded builds because\n        // the semantics of Py_REFCNT are more complicated and this may not\n        // do what we want.\n        if (Py_REFCNT(obj) == 0) {\n            Py_UNREACHABLE();\n        }\n#endif\n        Py_INCREF(obj);\n        surviving_objects.insert(obj);\n    }\n    d_tracked_objects.clear();\n\n    // While we hold s_mutex and our reference tracking hooks are installed,\n    // other threads can't destroy any objects. As soon as we uninstall the\n    // tracking hooks, objects can be destroyed by background threads without\n    // us finding out. This means we can't uninstall the hooks until after\n    // we've incremented the reference count of all the surviving objects.\n    if (d_reference_tracking) {\n        unregisterReferenceTrackingHooks();\n    }\n    return surviving_objects;\n}\n\ncode_object_id_t\nTracker::registerCodeObject(PyCodeObject* code_ptr, const CodeObject& code_obj)\n{\n    auto it = d_code_object_cache.find(code_ptr);\n    if (it != d_code_object_cache.end()) {\n        return it->second;\n    }\n\n    // New code object - register it\n    code_object_id_t code_id = d_next_code_object_id++;\n    d_code_object_cache[code_ptr] = code_id;\n\n    // Write the code object record\n    pycode_map_val_t code_record{\n            code_id,\n            CodeObjectInfo{\n                    code_obj.function_name,\n                    code_obj.filename,\n                    std::string(code_obj.linetable, code_obj.linetable_size),\n                    code_obj.firstlineno}};\n\n    if (!d_writer->writeRecord(code_record)) {\n        std::cerr << \"memray: Failed to write code object record, deactivating tracking\" << std::endl;\n        deactivate();\n    }\n\n    return code_id;\n}\n\nvoid\nTracker::forgetCodeObject(PyCodeObject* code)\n{\n    d_code_object_cache.erase(code);\n}\n\nbool\nTracker::popFrames(uint32_t count)\n{\n    const FramePop entry{count};\n    if (!d_writer->writeThreadSpecificRecord(thread_id(), entry)) {\n        std::cerr << \"memray: Failed to write output, deactivating tracking\" << std::endl;\n        deactivate();\n        return false;\n    }\n    return true;\n}\n\nbool\nTracker::pushFrame(const Frame& cooked)\n{\n    const FramePush entry{cooked};\n    if (!d_writer->writeThreadSpecificRecord(thread_id(), entry)) {\n        std::cerr << \"memray: Failed to write output, deactivating tracking\" << std::endl;\n        deactivate();\n        return false;\n    }\n    return true;\n}\n\nvoid\nTracker::activate()\n{\n    // NOTE: Tracker::s_mutex must be held\n    s_instance = s_instance_owner.get();\n}\n\nvoid\nTracker::deactivate()\n{\n    s_instance = nullptr;\n}\n\nbool\nTracker::isActive()\n{\n    return s_instance != nullptr;\n}\n\n// Static methods managing the singleton\n\nPyObject*\nTracker::createTracker(\n        std::unique_ptr<RecordWriter> record_writer,\n        bool native_traces,\n        unsigned int memory_interval,\n        bool follow_fork,\n        bool trace_python_allocators,\n        bool reference_tracking)\n{\n    s_instance_owner.reset(new Tracker(\n            std::move(record_writer),\n            native_traces,\n            memory_interval,\n            follow_fork,\n            trace_python_allocators,\n            reference_tracking));\n\n    StopTheWorldGuard stop_the_world;\n    std::unique_lock<std::mutex> lock(*s_mutex);\n    PythonStackTracker::recordAllStacks(*s_instance_owner);\n    tracking_api::Tracker::activate();\n    Py_RETURN_NONE;\n}\n\nPyObject*\nTracker::destroyTracker()\n{\n    // Note: the GIL is used for synchronization of the singleton\n    s_instance_owner.reset();\n    Py_RETURN_NONE;\n}\n\nTracker*\nTracker::getTracker()\n{\n    return s_instance;\n}\n\nstatic struct\n{\n    PyMemAllocatorEx raw;\n    PyMemAllocatorEx mem;\n    PyMemAllocatorEx obj;\n} s_orig_pymalloc_allocators;\n\nvoid\nTracker::registerPymallocHooks() const noexcept\n{\n    assert(d_trace_python_allocators);\n    PyMemAllocatorEx alloc;\n\n    PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &alloc);\n    if (alloc.free == &intercept::pymalloc_free) {\n        // Nothing to do; our hooks are already installed.\n        return;\n    }\n\n    alloc.malloc = intercept::pymalloc_malloc;\n    alloc.calloc = intercept::pymalloc_calloc;\n    alloc.realloc = intercept::pymalloc_realloc;\n    alloc.free = intercept::pymalloc_free;\n    PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &s_orig_pymalloc_allocators.raw);\n    PyMem_GetAllocator(PYMEM_DOMAIN_MEM, &s_orig_pymalloc_allocators.mem);\n    PyMem_GetAllocator(PYMEM_DOMAIN_OBJ, &s_orig_pymalloc_allocators.obj);\n    alloc.ctx = &s_orig_pymalloc_allocators.raw;\n    PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &alloc);\n    alloc.ctx = &s_orig_pymalloc_allocators.mem;\n    PyMem_SetAllocator(PYMEM_DOMAIN_MEM, &alloc);\n    alloc.ctx = &s_orig_pymalloc_allocators.obj;\n    PyMem_SetAllocator(PYMEM_DOMAIN_OBJ, &alloc);\n}\n\nvoid\nTracker::unregisterPymallocHooks() const noexcept\n{\n    assert(d_trace_python_allocators);\n    PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &s_orig_pymalloc_allocators.raw);\n    PyMem_SetAllocator(PYMEM_DOMAIN_MEM, &s_orig_pymalloc_allocators.mem);\n    PyMem_SetAllocator(PYMEM_DOMAIN_OBJ, &s_orig_pymalloc_allocators.obj);\n}\n\n// Trace Function interface\n\nint\nPyTraceFunction(\n        [[maybe_unused]] PyObject* obj,\n        PyFrameObject* frame,\n        int what,\n        [[maybe_unused]] PyObject* arg)\n{\n    RecursionGuard guard;\n    if (!Tracker::isActive()) {\n        return 0;\n    }\n\n    if (frame != PyEval_GetFrame()) {\n        // This should only happen for the phony frames produced by Cython\n        // extension modules that were compiled with `profile=True`.\n        return 0;\n    }\n\n    PythonStackTracker::get().handleTraceEvent(what, frame);\n    return 0;\n}\n\nvoid\nTracker::beginTrackingGreenlets()\n{\n    assert(PyGILState_Check());\n    PythonStackTracker::s_greenlet_tracking_enabled = true;\n}\n\nvoid\nTracker::handleGreenletSwitch(PyObject* from, PyObject* to)\n{\n    // We must stop tracking the stack once our trace function is uninstalled.\n    // Otherwise, we'd keep referencing frames after they're destroyed.\n    PyThreadState* ts = PyThreadState_Get();\n    if (ts->c_profilefunc != PyTraceFunction) {\n        return;\n    }\n\n    // Grab the Tracker lock, as this may need to write pushes/pops.\n    std::unique_lock<std::mutex> lock(*s_mutex);\n    RecursionGuard guard;\n\n    PythonStackTracker::get().handleGreenletSwitch(from, to);\n}\n\nvoid\nset_up_pthread_fork_handlers()\n{\n    static std::once_flag once;\n    call_once(once, [] {\n        // On macOS the recursion guard uses pthread TLS keys, so we\n        // need to create those keys before we install our handlers.\n        RecursionGuard::initialize();\n        pthread_atfork(&Tracker::prepareFork, &Tracker::parentFork, NULL);\n    });\n}\n\nvoid\ninstall_trace_function()\n{\n    assert(PyGILState_Check());\n    RecursionGuard guard;\n    // Don't clear the python stack if we have already registered the tracking\n    // function with the current thread. This happens when PyGILState_Ensure is\n    // called and a thread state with our hooks installed already exists.\n    PyThreadState* ts = PyThreadState_Get();\n    if (ts->c_profilefunc == PyTraceFunction) {\n        return;\n    }\n\n    PyEval_SetProfile(PyTraceFunction, nullptr);\n    PythonStackTracker::get().populateShadowStack();\n}\n\n}  // namespace memray::tracking_api\n"
  },
  {
    "path": "src/memray/_memray/tracking_api.h",
    "content": "#pragma once\n\n#define PY_SSIZE_T_CLEAN\n#include <Python.h>\n\n#include <atomic>\n#include <condition_variable>\n#include <cstddef>\n#include <fstream>\n#include <iterator>\n#include <memory>\n#include <optional>\n#include <string>\n#include <thread>\n#include <unordered_set>\n\n#include <unwind.h>\n\n#include \"frameobject.h\"\n\n#if defined(__linux__)\n#    define UNW_LOCAL_ONLY\n#    include <libunwind.h>\n#elif defined(__APPLE__)\n#    include <execinfo.h>\n#endif\n\n#include \"frame_tree.h\"\n#include \"hooks.h\"\n#include \"linker_shenanigans.h\"\n#include \"record_writer.h\"\n#include \"records.h\"\n\n#if defined(USE_MEMRAY_TLS_MODEL)\n#    if defined(__GLIBC__)\n#        define MEMRAY_FAST_TLS __attribute__((tls_model(\"initial-exec\")))\n#    else\n#        define MEMRAY_FAST_TLS __attribute__((tls_model(\"local-dynamic\")))\n#    endif\n#else\n#    define MEMRAY_FAST_TLS\n#endif\n\nnamespace memray::tracking_api {\n\nstruct RecursionGuard\n{\n    RecursionGuard()\n    : wasLocked(isActive())\n    {\n        setValue(true);\n    }\n\n    ~RecursionGuard()\n    {\n        setValue(wasLocked);\n    }\n\n    const bool wasLocked;\n\n#ifdef __linux__\n    MEMRAY_FAST_TLS static thread_local bool _isActive;\n\n    static void initialize()\n    {\n    }\n\n    static __attribute__((always_inline)) inline bool isActive()\n    {\n        return _isActive;\n    }\n\n    static __attribute__((always_inline)) inline void setValue(bool value)\n    {\n        _isActive = value;\n    }\n#else\n    static pthread_key_t isActiveKey;\n\n    static void initialize()\n    {\n        if (0 != pthread_key_create(&isActiveKey, NULL)) {\n            throw std::runtime_error{\"Failed to create pthread key\"};\n        }\n    }\n\n    static __attribute__((always_inline)) inline bool isActive()\n    {\n        return pthread_getspecific(isActiveKey) != 0;\n    }\n\n    static __attribute__((always_inline)) inline void setValue(bool value)\n    {\n        static bool true_constant = true;\n        if (pthread_setspecific(isActiveKey, value ? &true_constant : (void*)0) != 0) {\n            abort();\n        }\n        return;\n    }\n#endif\n};\n\n// Trace function interface\n\n/**\n * Trace function to be installed in all Python treads to track function calls\n *\n * This trace function's sole purpose is to give a thread-safe, GIL-synchronized view of the Python\n * stack. To retrieve the Python stack using the C-API forces the caller to have the GIL held. Requiring\n * the GIL in the allocator function has too much impact on performance and can deadlock extension\n * modules that have native locks that are not synchronized themselves with the GIL. For this reason we\n * need a way to record and store the Python call frame information in a way that we can read without the\n * need to use the C-API. This trace function writes to disk the PUSH and POP operations so the Python\n *stack at any point can be reconstructed later.\n *\n **/\nint\nPyTraceFunction(PyObject* obj, PyFrameObject* frame, int what, PyObject* arg);\n\n/**\n * Installs the trace function in the current thread.\n *\n * This function installs the trace function in the current thread using the C-API.\n *\n * */\nvoid\ninstall_trace_function();\n\n/**\n * Install our pthread fork handlers.\n */\nvoid\nset_up_pthread_fork_handlers();\n\nclass NativeTrace\n{\n  public:\n    using ip_t = frame_id_t;\n\n    NativeTrace(std::vector<ip_t>& data)\n    : d_data(data)\n    {\n    }\n\n    auto begin() const\n    {\n        return std::reverse_iterator(d_data.begin() + d_skip + d_size);\n    }\n    auto end() const\n    {\n        return std::reverse_iterator(d_data.begin() + d_skip);\n    }\n    ip_t operator[](size_t i) const\n    {\n        return d_data[d_skip + d_size - 1 - i];\n    }\n    int size() const\n    {\n        return d_size;\n    }\n    __attribute__((always_inline)) inline bool fill(size_t skip)\n    {\n        size_t size;\n        while (true) {\n#ifdef __linux__\n            size = unw_backtrace((void**)d_data.data(), d_data.size());\n#elif defined(__APPLE__)\n            size = ::backtrace((void**)d_data.data(), d_data.size());\n#else\n            return 0;\n#endif\n            if (size < d_data.size()) {\n                break;\n            }\n\n            d_data.resize(d_data.size() * 2);\n        }\n        d_size = size > skip ? size - skip : 0;\n        d_skip = skip;\n        return d_size > 0;\n    }\n\n    static void setup()\n    {\n#ifdef __linux__\n        // configure libunwind for better speed\n        if (unw_set_caching_policy(unw_local_addr_space, UNW_CACHE_PER_THREAD)) {\n            fprintf(stderr, \"WARNING: Failed to enable per-thread libunwind caching.\\n\");\n        }\n#    if (UNW_VERSION_MAJOR > 1 && UNW_VERSION_MINOR >= 3)\n        if (unw_set_cache_size(unw_local_addr_space, 1024, 0)) {\n            fprintf(stderr, \"WARNING: Failed to set libunwind cache size.\\n\");\n        }\n#    endif\n#else\n        return;\n#endif\n    }\n\n    static inline void flushCache()\n    {\n#ifdef __linux__\n        unw_flush_cache(unw_local_addr_space, 0, 0);\n#else\n        return;\n#endif\n    }\n\n  private:\n    size_t d_size = 0;\n    size_t d_skip = 0;\n    std::vector<ip_t>& d_data;\n};\n\n/**\n * Singleton managing all the global state and functionality of the tracing mechanism\n *\n * This class acts as the only interface to the tracing functionality and encapsulates all the\n * required global state. *All access* must be done through the singleton interface as the singleton\n * has the same lifetime of the entire program. The singleton can be activated and deactivated to\n * temporarily stop the tracking as desired. The singleton manages a mirror copy of the Python stack\n * so it can be accessed synchronized by its the allocation tracking interfaces.\n * */\nclass Tracker\n{\n  public:\n    // Constructors\n    ~Tracker();\n\n    Tracker(Tracker& other) = delete;\n    Tracker(Tracker&& other) = delete;\n    void operator=(const Tracker&) = delete;\n    void operator=(Tracker&&) = delete;\n\n    // Interface to get the tracker instance\n    static PyObject* createTracker(\n            std::unique_ptr<RecordWriter> record_writer,\n            bool native_traces,\n            unsigned int memory_interval,\n            bool follow_fork,\n            bool trace_python_allocators,\n            bool reference_tracking);\n    static PyObject* destroyTracker();\n    static Tracker* getTracker();\n\n    // Allocation tracking interface\n    __attribute__((always_inline)) inline static void\n    trackAllocation(void* ptr, size_t size, hooks::Allocator func)\n    {\n        if (RecursionGuard::isActive() || !Tracker::isActive()) {\n            return;\n        }\n        RecursionGuard guard;\n\n        std::optional<NativeTrace> trace{std::nullopt};\n        if (Tracker::areNativeTracesEnabled()) {\n            if (!prepareNativeTrace(trace)) {\n                return;\n            }\n            // Skip the internal frames so we don't need to filter them later.\n            trace.value().fill(1);\n        }\n\n        std::unique_lock<std::mutex> lock(*s_mutex);\n        Tracker* tracker = getTracker();\n        if (tracker) {\n            tracker->trackAllocationImpl(ptr, size, func, trace);\n        }\n    }\n\n    // Object tracking interface\n    __attribute__((always_inline)) inline static void trackObject(PyObject* obj, int event)\n    {\n        if (RecursionGuard::isActive() || !Tracker::isActive()) {\n            return;\n        }\n        RecursionGuard guard;\n\n        std::optional<NativeTrace> trace{std::nullopt};\n        if (Tracker::areNativeTracesEnabled()) {\n            if (!prepareNativeTrace(trace)) {\n                return;\n            }\n            // Skip the internal frames so we don't need to filter them later.\n            trace.value().fill(1);\n        }\n\n        std::unique_lock<std::mutex> lock(*s_mutex);\n        Tracker* tracker = getTracker();\n        if (tracker) {\n            tracker->trackObjectImpl(obj, event, trace);\n        }\n    }\n\n    static inline bool prepareNativeTrace(std::optional<NativeTrace>& trace)\n    {\n        auto t_trace_data_ptr = static_cast<std::vector<NativeTrace::ip_t>*>(\n                pthread_getspecific(s_native_unwind_vector_key));\n        if (!t_trace_data_ptr) {\n            t_trace_data_ptr = new std::vector<NativeTrace::ip_t>();\n            if (pthread_setspecific(s_native_unwind_vector_key, t_trace_data_ptr) != 0) {\n                Tracker::deactivate();\n                std::cerr << \"memray: pthread_setspecific failed\" << std::endl;\n                delete t_trace_data_ptr;\n                return false;\n            }\n            t_trace_data_ptr->resize(128);\n        }\n        trace.emplace(*t_trace_data_ptr);\n        return true;\n    }\n\n    __attribute__((always_inline)) inline static void\n    trackDeallocation(void* ptr, size_t size, hooks::Allocator func)\n    {\n        if (RecursionGuard::isActive() || !Tracker::isActive()) {\n            return;\n        }\n        RecursionGuard guard;\n\n        std::unique_lock<std::mutex> lock(*s_mutex);\n        Tracker* tracker = getTracker();\n        if (tracker) {\n            tracker->trackDeallocationImpl(ptr, size, func);\n        }\n    }\n\n    __attribute__((always_inline)) inline static void invalidate_module_cache()\n    {\n        if (RecursionGuard::isActive() || !Tracker::isActive()) {\n            return;\n        }\n        RecursionGuard guard;\n\n        std::unique_lock<std::mutex> lock(*s_mutex);\n        Tracker* tracker = getTracker();\n        if (tracker) {\n            tracker->invalidate_module_cache_impl();\n        }\n    }\n\n    __attribute__((always_inline)) inline static void registerThreadName(const char* name)\n    {\n        if (RecursionGuard::isActive() || !Tracker::isActive()) {\n            return;\n        }\n        RecursionGuard guard;\n\n        std::unique_lock<std::mutex> lock(*s_mutex);\n        Tracker* tracker = getTracker();\n        if (tracker) {\n            tracker->registerThreadNameImpl(name);\n        }\n    }\n\n    inline static void registerThreadNameById(uint64_t thread, const char* name)\n    {\n        if (RecursionGuard::isActive() || !Tracker::isActive()) {\n            return;\n        }\n        RecursionGuard guard;\n\n        std::unique_lock<std::mutex> lock(*s_mutex);\n        Tracker* tracker = getTracker();\n        if (tracker) {\n            if (thread == (uint64_t)(pthread_self())) {\n                tracker->registerThreadNameImpl(name);\n            } else {\n                // We've got a different thread's name, but don't know what id\n                // has been assigned to that thread (if any!). Set this update\n                // aside to be handled later, from that thread.\n                tracker->d_cached_thread_names.emplace(thread, name);\n            }\n        }\n    }\n\n    // stack interface\n    bool pushFrame(const Frame& frame);\n    bool popFrames(uint32_t count);\n\n    // code object registration\n    code_object_id_t registerCodeObject(PyCodeObject* code_ptr, const CodeObject& code_obj);\n    void forgetCodeObject(PyCodeObject* code);\n\n    // Interface to activate/deactivate the tracking\n    static bool isActive();\n    static void activate();\n    static void deactivate();\n\n    /**\n     * Sets a flag to enable integration with the `greenlet` module.\n     */\n    static void beginTrackingGreenlets();\n\n    /**\n     * Handle a notification of control switching from one greenlet to another.\n     */\n    static void handleGreenletSwitch(PyObject* from, PyObject* to);\n\n    static void prepareFork();\n    static void parentFork();\n    static void childFork();\n    std::unordered_set<PyObject*> getSurvivingObjects();\n\n  private:\n    class BackgroundThread\n    {\n      public:\n        // Constructors\n        BackgroundThread(std::shared_ptr<RecordWriter> record_writer, unsigned int memory_interval);\n\n        // Methods\n        void start();\n        void stop();\n\n      private:\n        // Data members\n        std::shared_ptr<RecordWriter> d_writer;\n        bool d_stop{false};\n        unsigned int d_memory_interval;\n        std::mutex d_mutex;\n        std::condition_variable d_cv;\n        std::thread d_thread;\n        mutable std::ifstream d_procs_statm;\n\n        // Methods\n        size_t getRSS() const;\n        static uint64_t timeElapsed();\n        bool captureMemorySnapshot();\n    };\n\n    // Data members\n    static std::unique_ptr<std::mutex> s_mutex;\n    static pthread_key_t s_native_unwind_vector_key;\n    static std::unique_ptr<Tracker> s_instance_owner;\n    static std::atomic<Tracker*> s_instance;\n\n    std::shared_ptr<RecordWriter> d_writer;\n    FrameTree d_native_trace_tree;\n    const bool d_unwind_native_frames;\n    const unsigned int d_memory_interval;\n    const bool d_follow_fork;\n    const bool d_trace_python_allocators;\n    const bool d_reference_tracking;\n    linker::SymbolPatcher d_patcher;\n    std::unique_ptr<BackgroundThread> d_background_thread;\n\n    std::unordered_map<PyCodeObject*, code_object_id_t> d_code_object_cache;\n    code_object_id_t d_next_code_object_id{1};\n    std::unordered_map<uint64_t, std::string> d_cached_thread_names;\n    std::unordered_set<PyObject*> d_tracked_objects;\n\n    // Methods\n    static size_t computeMainTidSkip();\n\n    void trackAllocationImpl(\n            void* ptr,\n            size_t size,\n            hooks::Allocator func,\n            const std::optional<NativeTrace>& trace);\n    void trackDeallocationImpl(void* ptr, size_t size, hooks::Allocator func);\n    void trackObjectImpl(PyObject* obj, int event, const std::optional<NativeTrace>& trace);\n    void invalidate_module_cache_impl();\n    void updateModuleCacheImpl();\n    void registerThreadNameImpl(const char* name);\n    void registerCachedThreadName();\n    void dropCachedThreadName();\n    void registerPymallocHooks() const noexcept;\n    void unregisterPymallocHooks() const noexcept;\n    void registerReferenceTrackingHooks() const noexcept;\n    void unregisterReferenceTrackingHooks() const noexcept;\n\n    explicit Tracker(\n            std::unique_ptr<RecordWriter> record_writer,\n            bool native_traces,\n            unsigned int memory_interval,\n            bool follow_fork,\n            bool trace_python_allocators,\n            bool reference_tracking);\n\n    static bool areNativeTracesEnabled();\n};\n\n}  // namespace memray::tracking_api\n"
  },
  {
    "path": "src/memray/_memray/tracking_api.pxd",
    "content": "from _memray.record_writer cimport RecordWriter\nfrom cpython cimport PyObject\nfrom libc.stdint cimport uint64_t\nfrom libcpp cimport bool\nfrom libcpp.memory cimport unique_ptr\nfrom libcpp.string cimport string\nfrom libcpp.unordered_set cimport unordered_set\n\n\ncdef extern from \"tracking_api.h\" namespace \"memray::tracking_api\":\n    void set_up_pthread_fork_handlers() except+\n    void install_trace_function() except*\n\n    cdef cppclass RecursionGuard:\n        RecursionGuard()\n\n    cdef cppclass Tracker:\n        @staticmethod\n        object createTracker(\n            unique_ptr[RecordWriter] record_writer,\n            bool native_traces,\n            unsigned int memory_interval,\n            bool follow_fork,\n            bool trace_pymalloc,\n            bool reference_tracking,\n        ) except+\n\n        @staticmethod\n        object destroyTracker() except +\n\n        @staticmethod\n        Tracker* getTracker()\n\n        @staticmethod\n        void beginTrackingGreenlets() except+\n\n        @staticmethod\n        void handleGreenletSwitch(object, object) except+\n\n        @staticmethod\n        void registerThreadNameById(uint64_t, const char*) except+\n\n        @staticmethod\n        void childFork() noexcept nogil\n\n        @staticmethod\n        unordered_set[PyObject*] getSurvivingObjects() except+\n"
  },
  {
    "path": "src/memray/_memray.pyi",
    "content": "import enum\nfrom pathlib import Path\nfrom types import CodeType\nfrom types import FrameType\nfrom types import TracebackType\nfrom typing import Any\nfrom typing import Iterable\nfrom typing import Iterator\nfrom typing import List\nfrom typing import NamedTuple\nfrom typing import Optional\nfrom typing import Tuple\nfrom typing import Type\nfrom typing import TypedDict\nfrom typing import Union\nfrom typing import overload\n\nfrom memray._destination import FileDestination as FileDestination\nfrom memray._destination import SocketDestination as SocketDestination\nfrom memray._metadata import Metadata\nfrom memray._stats import Stats\n\nfrom . import Destination\n\nPythonStackElement = Tuple[str, str, int]\nNativeStackElement = Tuple[str, str, int]\nMemorySnapshot = NamedTuple(\n    \"MemorySnapshot\", [(\"time\", int), (\"rss\", int), (\"heap\", int)]\n)\n\ndef set_log_level(level: int) -> None: ...\n\nclass AllocationRecord:\n    @property\n    def address(self) -> int: ...\n    @property\n    def allocator(self) -> int: ...\n    @property\n    def n_allocations(self) -> int: ...\n    @property\n    def size(self) -> int: ...\n    @property\n    def stack_id(self) -> int: ...\n    @property\n    def tid(self) -> int: ...\n    @property\n    def native_stack_id(self) -> int: ...\n    @property\n    def native_segment_generation(self) -> int: ...\n    @property\n    def thread_name(self) -> str: ...\n    def hybrid_stack_trace(\n        self,\n        max_stacks: Optional[int] = None,\n    ) -> List[Union[PythonStackElement, NativeStackElement]]: ...\n    def native_stack_trace(\n        self, max_stacks: Optional[int] = None\n    ) -> List[NativeStackElement]: ...\n    def stack_trace(\n        self, max_stacks: Optional[int] = None\n    ) -> List[PythonStackElement]: ...\n    def __eq__(self, other: Any) -> Any: ...\n    def __ge__(self, other: Any) -> Any: ...\n    def __gt__(self, other: Any) -> Any: ...\n    def __hash__(self) -> Any: ...\n    def __le__(self, other: Any) -> Any: ...\n    def __lt__(self, other: Any) -> Any: ...\n    def __ne__(self, other: Any) -> Any: ...\n\nclass TrackedObjectRecord:\n    @property\n    def tid(self) -> int: ...\n    @property\n    def address(self) -> int: ...\n    @property\n    def is_created(self) -> bool: ...\n    @property\n    def frame_index(self) -> int: ...\n    @property\n    def native_frame_id(self) -> int: ...\n    @property\n    def native_segment_generation(self) -> int: ...\n    def toPythonObject(self) -> Any: ...\n    def hybrid_stack_trace(\n        self,\n        max_stacks: Optional[int] = None,\n    ) -> List[Union[PythonStackElement, NativeStackElement]]: ...\n    def native_stack_trace(\n        self, max_stacks: Optional[int] = None\n    ) -> List[NativeStackElement]: ...\n    def stack_trace(\n        self, max_stacks: Optional[int] = None\n    ) -> List[PythonStackElement]: ...\n    def __eq__(self, other: Any) -> Any: ...\n    def __hash__(self) -> Any: ...\n    def __repr__(self) -> str: ...\n    def __str__(self) -> str: ...\n\nclass Interval:\n    def __init__(\n        self,\n        allocated_before_snapshot: int,\n        deallocated_before_snapshot: int | None,\n        n_allocations: int,\n        n_bytes: int,\n    ) -> None: ...\n    def __eq__(self, other: Any) -> Any: ...\n    allocated_before_snapshot: int\n    deallocated_before_snapshot: int | None\n    n_allocations: int\n    n_bytes: int\n\nclass TemporalAllocationRecord:\n    @property\n    def allocator(self) -> int: ...\n    @property\n    def stack_id(self) -> int: ...\n    @property\n    def tid(self) -> int: ...\n    @property\n    def native_stack_id(self) -> int: ...\n    @property\n    def native_segment_generation(self) -> int: ...\n    @property\n    def thread_name(self) -> str: ...\n    def hybrid_stack_trace(\n        self,\n        max_stacks: Optional[int] = None,\n    ) -> List[Union[PythonStackElement, NativeStackElement]]: ...\n    def native_stack_trace(\n        self, max_stacks: Optional[int] = None\n    ) -> List[NativeStackElement]: ...\n    def stack_trace(\n        self, max_stacks: Optional[int] = None\n    ) -> List[PythonStackElement]: ...\n    def __eq__(self, other: Any) -> Any: ...\n    def __hash__(self) -> Any: ...\n    intervals: List[Interval]\n\nclass AllocatorType(enum.IntEnum):\n    PYMALLOC_FREE = 1\n    PYMALLOC_MALLOC = 2\n    PYMALLOC_CALLOC = 3\n    PYMALLOC_REALLOC = 4\n    FREE = 5\n    MALLOC = 6\n    REALLOC = 7\n    CALLOC = 8\n    POSIX_MEMALIGN = 9\n    ALIGNED_ALLOC = 10\n    MEMALIGN = 11\n    VALLOC = 12\n    PVALLOC = 13\n    MMAP = 14\n    MUNMAP = 15\n\nclass FileFormat(enum.IntEnum):\n    ALL_ALLOCATIONS = 1\n    AGGREGATED_ALLOCATIONS = 2\n\ndef start_thread_trace(frame: FrameType, event: str, arg: Any) -> None: ...\n\nclass FileReader:\n    @property\n    def metadata(self) -> Metadata: ...\n    def __init__(\n        self,\n        file_name: Union[str, Path],\n        *,\n        report_progress: bool = False,\n        max_memory_records: int = 10000,\n    ) -> None: ...\n    def get_allocation_records(self) -> Iterable[AllocationRecord]: ...\n    def get_temporal_allocation_records(\n        self,\n        merge_threads: bool,\n    ) -> Iterable[TemporalAllocationRecord]: ...\n    def get_temporal_high_water_mark_allocation_records(\n        self,\n        merge_threads: bool,\n    ) -> Tuple[List[TemporalAllocationRecord], List[int]]: ...\n    def get_high_watermark_allocation_records(\n        self,\n        merge_threads: bool = ...,\n    ) -> Iterable[AllocationRecord]: ...\n    def get_leaked_allocation_records(\n        self, merge_threads: bool = ...\n    ) -> Iterable[AllocationRecord]: ...\n    def get_temporary_allocation_records(\n        self, merge_threads: bool = ..., threshold: int = ...\n    ) -> Iterable[AllocationRecord]: ...\n    def get_memory_snapshots(self) -> Iterable[MemorySnapshot]: ...\n    def __enter__(self) -> Any: ...\n    def __exit__(\n        self,\n        exctype: Optional[Type[BaseException]],\n        excinst: Optional[BaseException],\n        exctb: Optional[TracebackType],\n    ) -> bool: ...\n    @property\n    def closed(self) -> bool: ...\n    def close(self) -> None: ...\n    def get_tracked_objects(\n        self, filter_objs: Optional[Iterable[Any]] = None\n    ) -> Iterable[TrackedObjectRecord]: ...\n\ndef compute_statistics(\n    file_name: Union[str, Path],\n    *,\n    report_progress: bool = False,\n    num_largest: int = 5,\n) -> Stats: ...\ndef dump_all_records(file_name: Union[str, Path]) -> None: ...\n\nclass SocketReader:\n    def __init__(self, port: int) -> None: ...\n    def __enter__(self) -> \"SocketReader\": ...\n    def __exit__(\n        self,\n        exc_type: Optional[Type[BaseException]],\n        exc_value: Optional[BaseException],\n        exc_traceback: Optional[TracebackType],\n    ) -> Any: ...\n    def get_current_snapshot(\n        self, *, merge_threads: bool\n    ) -> Iterator[AllocationRecord]: ...\n    @property\n    def command_line(self) -> Optional[str]: ...\n    @property\n    def is_active(self) -> bool: ...\n    @property\n    def pid(self) -> Optional[int]: ...\n    @property\n    def has_native_traces(self) -> bool: ...\n\nclass Tracker:\n    @property\n    def reader(self) -> FileReader: ...\n    @overload\n    def __init__(\n        self,\n        file_name: Union[Path, str],\n        *,\n        native_traces: bool = ...,\n        memory_interval_ms: int = ...,\n        follow_fork: bool = ...,\n        trace_python_allocators: bool = ...,\n        file_format: FileFormat = ...,\n        reference_tracking: bool = ...,\n        track_object_lifetimes: bool = ...,\n    ) -> None: ...\n    @overload\n    def __init__(\n        self,\n        *,\n        destination: Destination,\n        native_traces: bool = ...,\n        memory_interval_ms: int = ...,\n        follow_fork: bool = ...,\n        trace_python_allocators: bool = ...,\n        file_format: FileFormat = ...,\n        reference_tracking: bool = ...,\n    ) -> None: ...\n    def __enter__(self) -> Any: ...\n    def __exit__(\n        self,\n        exctype: Optional[Type[BaseException]],\n        excinst: Optional[BaseException],\n        exctb: Optional[TracebackType],\n    ) -> bool: ...\n    def get_surviving_objects(self) -> list[object]: ...\n\ndef greenlet_trace(event: str, args: Any) -> None: ...\n\nclass PymallocDomain(enum.IntEnum):\n    PYMALLOC_RAW = 1\n    PYMALLOC_MEM = 2\n    PYMALLOC_OBJECT = 3\n\ndef size_fmt(num: int, suffix: str = \"B\") -> str: ...\n\nclass SymbolicSupport(enum.IntEnum):\n    NONE = 1\n    FUNCTION_NAME_ONLY = 2\n    TOTAL = 3\n\ndef get_symbolic_support() -> SymbolicSupport: ...\n\nRTLD_NOW: int\nRTLD_DEFAULT: int\n\nclass HighWaterMarkAggregatorTestHarness:\n    def add_allocation(\n        self,\n        tid: int,\n        address: int,\n        size: int,\n        allocator: int,\n        native_frame_id: int,\n        frame_index: int,\n        native_segment_generation: int,\n    ) -> None: ...\n    def capture_snapshot(self) -> None: ...\n    def high_water_mark_bytes_by_snapshot(self) -> list[int]: ...\n    def get_current_heap_size(self) -> int: ...\n    def get_temporal_allocations(self) -> list[TemporalAllocationRecord]: ...\n    def get_allocations(self) -> list[dict[str, int]]: ...\n\nclass AllocationLifetimeAggregatorTestHarness:\n    def add_allocation(\n        self,\n        tid: int,\n        address: int,\n        size: int,\n        allocator: int,\n        native_frame_id: int,\n        frame_index: int,\n        native_segment_generation: int,\n    ) -> None: ...\n    def capture_snapshot(self) -> None: ...\n    def get_allocations(self) -> list[TemporalAllocationRecord]: ...\n\nclass Segment(TypedDict):\n    vaddr: int\n    memsz: int\n\nclass Mapping(TypedDict):\n    filename: str\n    addr: int\n    segments: list[Segment]\n\nclass RecordWriterTestHarness:\n    def __init__(\n        self,\n        file_path: str,\n        native_traces: bool = False,\n        trace_python_allocators: bool = False,\n        file_format: FileFormat = FileFormat.ALL_ALLOCATIONS,\n        main_tid: int = 1,\n        skipped_frames: int = 0,\n        command_line: str = ...,\n    ) -> None: ...\n    def write_header(self, seek_to_start: bool) -> None: ...\n    def write_memory_record(self, ms_since_epoch: int, rss: int) -> bool: ...\n    def write_code_object(\n        self,\n        id: int,\n        function_name: str,\n        filename: str,\n        linetable: bytes,\n        firstlineno: int,\n    ) -> bool: ...\n    def write_unresolved_native_frame(self, ip: int, index: int) -> bool: ...\n    def write_allocation_record(\n        self,\n        tid: int,\n        address: int,\n        size: int,\n        allocator: int,\n        native_frame_id: int = 0,\n    ) -> bool: ...\n    def write_frame_push(\n        self,\n        tid: int,\n        code_object_id: int,\n        instruction_offset: int,\n        is_entry_frame: bool,\n    ) -> bool: ...\n    def write_frame_pop(self, tid: int, count: int) -> bool: ...\n    def write_thread_record(self, tid: int, name: str) -> bool: ...\n    def write_mappings(self, mappings: list[Mapping]) -> bool: ...\n    def write_trailer(self) -> bool: ...\n    @staticmethod\n    def get_linetable(code_object: CodeType) -> bytes: ...\n    @staticmethod\n    def get_lasti(frame_object: FrameType) -> int: ...\n"
  },
  {
    "path": "src/memray/_memray.pyx",
    "content": "import collections\nimport contextlib\nimport os\nimport pathlib\nimport platform\nimport sys\n\ncimport cython\n\nimport threading\nfrom datetime import datetime\n\nfrom rich import print as pprint\nfrom rich.progress import Progress\nfrom rich.progress import SpinnerColumn\n\nfrom posix.time cimport CLOCK_MONOTONIC\nfrom posix.time cimport clock_gettime\nfrom posix.time cimport timespec\n\nfrom _memray cimport records\nfrom _memray.algorithm cimport count\nfrom _memray.hooks cimport Allocator\nfrom _memray.hooks cimport isDeallocator\nfrom _memray.logging cimport setLogThreshold\nfrom _memray.native_resolver cimport unwindHere\nfrom _memray.record_reader cimport RecordReader\nfrom _memray.record_reader cimport RecordResult\nfrom _memray.record_writer cimport PyCodeObject\nfrom _memray.record_writer cimport PyFrameObject\nfrom _memray.record_writer cimport RecordWriter\nfrom _memray.record_writer cimport codeGetLinetable\nfrom _memray.record_writer cimport createRecordWriter\nfrom _memray.record_writer cimport frameGetLasti\nfrom _memray.records cimport AggregatedAllocation\nfrom _memray.records cimport Allocation as _Allocation\nfrom _memray.records cimport FileFormat as _FileFormat\nfrom _memray.records cimport MemoryRecord\nfrom _memray.records cimport MemorySnapshot as _MemorySnapshot\nfrom _memray.records cimport TrackedObject\nfrom _memray.sink cimport FileSink\nfrom _memray.sink cimport NullSink\nfrom _memray.sink cimport Sink\nfrom _memray.sink cimport SocketSink\nfrom _memray.snapshot cimport NO_THREAD_INFO\nfrom _memray.snapshot cimport AbstractAggregator\nfrom _memray.snapshot cimport AggregatedCaptureReaggregator\nfrom _memray.snapshot cimport AllocationLifetime\nfrom _memray.snapshot cimport AllocationLifetimeAggregator\nfrom _memray.snapshot cimport AllocationStatsAggregator\nfrom _memray.snapshot cimport HighWatermark\nfrom _memray.snapshot cimport HighWaterMarkAggregator\nfrom _memray.snapshot cimport HighWatermarkFinder\nfrom _memray.snapshot cimport HighWaterMarkLocationKey\nfrom _memray.snapshot cimport Py_GetSnapshotAllocationRecords\nfrom _memray.snapshot cimport Py_ListFromSnapshotAllocationRecords\nfrom _memray.snapshot cimport SnapshotAllocationAggregator\nfrom _memray.snapshot cimport TemporaryAllocationsAggregator\nfrom _memray.socket_reader_thread cimport BackgroundSocketReader\nfrom _memray.source cimport FileSource\nfrom _memray.source cimport SocketSource\nfrom _memray.tracking_api cimport RecursionGuard\nfrom _memray.tracking_api cimport Tracker as NativeTracker\nfrom _memray.tracking_api cimport install_trace_function\nfrom _memray.tracking_api cimport set_up_pthread_fork_handlers\nfrom cpython cimport Py_DECREF\nfrom cpython cimport PyErr_CheckSignals\nfrom cpython cimport PyObject\nfrom libc.math cimport ceil\nfrom libc.stdint cimport uint64_t\nfrom libc.stdint cimport uintptr_t\nfrom libcpp cimport bool\nfrom libcpp.limits cimport numeric_limits\nfrom libcpp.memory cimport make_shared\nfrom libcpp.memory cimport make_unique\nfrom libcpp.memory cimport shared_ptr\nfrom libcpp.memory cimport unique_ptr\nfrom libcpp.string cimport string as cppstring\nfrom libcpp.unordered_map cimport unordered_map\nfrom libcpp.unordered_set cimport unordered_set\nfrom libcpp.utility cimport move\nfrom libcpp.utility cimport pair\nfrom libcpp.vector cimport vector\n\nfrom ._destination import Destination\nfrom ._destination import FileDestination\nfrom ._destination import SocketDestination\nfrom ._metadata import Metadata\nfrom ._stats import Stats\nfrom ._thread_name_interceptor import ThreadNameInterceptor\n\n# NOTE: We can't reinitialize tracking in a child process until the interpreter\n#       has reinitialized its locks, so we do it in a Python fork handler.\n#       But, Python fork handlers aren't guaranteed to run for every fork, and\n#       the child process must never inherit an active tracker, so we must use\n#       a pthread fork handler to disable tracking before forking.\nset_up_pthread_fork_handlers()\nos.register_at_fork(after_in_child=NativeTracker.childFork)\n\n\ndef set_log_level(int level):\n    \"\"\"Configure which log messages will be printed to stderr by memray.\n\n    By default, only log records of severity `logging.WARNING` or higher will\n    be printed, but you can adjust this threshold.\n\n    Args:\n        level (int): The lowest severity level that a log record can have and\n            still be printed.\n    \"\"\"\n    setLogThreshold(level)\n\n\ncpdef enum AllocatorType:\n    PYMALLOC_FREE = 1\n    PYMALLOC_MALLOC = 2\n    PYMALLOC_CALLOC = 3\n    PYMALLOC_REALLOC = 4\n    FREE = 5\n    MALLOC = 6\n    REALLOC = 7\n    CALLOC = 8\n    POSIX_MEMALIGN = 9\n    ALIGNED_ALLOC = 10\n    MEMALIGN = 11\n    VALLOC = 12\n    PVALLOC = 13\n    MMAP = 14\n    MUNMAP = 15\n\n# Note: enumerator values are negative because they must be unique\n#       from the enumerator values of the AllocatorType enum above\ncpdef enum ObjectTrackingEvent:\n    OBJECT_CREATED = -1\n    OBJECT_DESTROYED = -2\n\ncpdef enum PythonAllocatorType:\n    PYTHON_ALLOCATOR_PYMALLOC = 1\n    PYTHON_ALLOCATOR_PYMALLOC_DEBUG = 2\n    PYTHON_ALLOCATOR_MALLOC = 3\n    PYTHON_ALLOCATOR_OTHER = 4\n    PYTHON_ALLOCATOR_MIMALLOC = 5\n    PYTHON_ALLOCATOR_MIMALLOC_DEBUG = 6\n\ncpdef enum FileFormat:\n    ALL_ALLOCATIONS = _FileFormat.ALL_ALLOCATIONS\n    AGGREGATED_ALLOCATIONS = _FileFormat.AGGREGATED_ALLOCATIONS\n\n\ndef size_fmt(num, suffix='B'):\n    for unit in ['','k','M','G','T','P','E','Z']:\n        if abs(num) < 1000.0:\n            return f\"{num:5.3f}{unit}{suffix}\"\n        num /= 1000.0\n    return f\"{num:.1f}Y{suffix}\"\n\n# Memray core\n\ncdef stack_trace(\n    RecordReader* reader,\n    tid,\n    allocator,\n    python_stack_id,\n    max_stacks=None,\n):\n    if allocator in (AllocatorType.FREE, AllocatorType.MUNMAP, ObjectTrackingEvent.OBJECT_DESTROYED):\n        raise NotImplementedError(\"Stack traces for deallocations aren't captured.\")\n\n    assert reader != NULL, \"Cannot get stack trace without reader.\"\n    cdef ssize_t to_skip\n    cdef ssize_t to_keep\n\n    if max_stacks is not None:\n        return reader.Py_GetStackFrame(python_stack_id, max_stacks)\n\n    stack_trace = reader.Py_GetStackFrame(python_stack_id)\n    if tid == reader.getMainThreadTid():\n        to_skip = reader.getSkippedFramesOnMainThread()\n        to_keep = max(len(stack_trace) - to_skip, 0)\n        del stack_trace[to_keep:]\n    return stack_trace\n\n\ncdef native_stack_trace(\n    RecordReader* reader,\n    allocator,\n    native_stack_id,\n    generation,\n    max_stacks=None,\n):\n    if allocator in (AllocatorType.FREE, AllocatorType.MUNMAP):\n        raise NotImplementedError(\"Stack traces for deallocations aren't captured.\")\n\n    assert reader != NULL, \"Cannot get stack trace without reader.\"\n    if max_stacks is None:\n        return reader.Py_GetNativeStackFrame(native_stack_id, generation)\n    return reader.Py_GetNativeStackFrame(native_stack_id, generation, max_stacks)\n\n\ncdef hybrid_stack_trace(\n    RecordReader* reader,\n    tid,\n    allocator,\n    python_stack_id,\n    native_stack_id,\n    generation,\n    max_stacks=None,\n):\n    # This function merges a Python stack and a native stack into\n    # a \"hybrid\" stack. It substitutes _PyFrame_EvalFrameDefault calls in\n    # the native stack with the corresponding frame in the Python stack.\n    # This sounds easy, but there are several tricky aspects:\n    # 1. For the thread that called Tracker.__enter__, we want to hide\n    #    frames (both Python and C) above the one that made that call.\n    #    For other threads we want to keep all frames.\n    # 2. If _PyFrame_EvalFrameDefault allocates memory before calling our\n    #    profile function, we'll have too few Python frames to pair up\n    #    every _PyFrame_EvalFrameDefault call. This happens in 3.11.\n    # 3. Since Python 3.11, one _PyFrame_EvalFrameDefault call can evaluate\n    #    many Python frames. If a frame's is_entry_frame flag is unset, it\n    #    uses the same _PyFrame_EvalFrameDefault call as its caller.\n    # 4. If the interpreter was stripped, we may not be able to recognize\n    #    every (or even any) _PyFrame_EvalFrameDefault call, so we may\n    #    have extra Python frames left after pairing.\n    cdef vector[unsigned char] is_entry_frame\n    native_stack = native_stack_trace(reader, allocator, native_stack_id, generation)\n    python_stack = reader.Py_GetStackFrameAndEntryInfo(python_stack_id, &is_entry_frame)\n\n    cdef ssize_t num_non_entry_frames = count(\n        is_entry_frame.begin(), is_entry_frame.end(), 0\n    )\n\n    # Entry frames replace native frames; non-entry frames are inserted.\n    hybrid_stack = [None] * (len(native_stack) + num_non_entry_frames)\n\n    # Both stacks are from most recent to least, but we must pair things up\n    # least recent to most to handle cases where _PyFrame_EvalFrameDefault\n    # allocated memory before calling the profile function.\n    native_stack.reverse()\n    cdef ssize_t pidx = len(python_stack) - 1\n    cdef ssize_t hidx = len(hybrid_stack) - 1\n\n    cdef ssize_t to_skip = 0\n    if tid == reader.getMainThreadTid():\n        to_skip = reader.getSkippedFramesOnMainThread()\n    cdef ssize_t first_kept_frame = pidx - to_skip\n\n    for native_frame in native_stack:\n        symbol = native_frame[0]\n        # Check for Python frame boundaries: traditional _PyEval_EvalFrameDefault\n        # or Python 3.14 tail call interpreter LLVM-generated functions\n        is_python_frame_boundary = \"_PyEval_EvalFrameDefault\" in symbol or (\n            symbol.startswith(\"_TAIL_CALL_\") and \".llvm.\" in symbol\n        )\n        if pidx >= 0 and is_python_frame_boundary:\n            while True:\n                # If we're not keeping all frames and we've reached the\n                # first one we want to keep, remove frames above it.\n                if to_skip != 0 and pidx == first_kept_frame:\n                    del hybrid_stack[hidx + 1:]\n\n                assert hidx >= 0\n                hybrid_stack[hidx] = python_stack[pidx]\n                hidx -= 1\n                pidx -= 1\n\n                # Stop when we either run out of Python frames or reach the\n                # entry frame being evaluated by the next eval loop.\n                if pidx < 0 or is_entry_frame[pidx]:\n                    break\n        else:\n            assert hidx >= 0\n            hybrid_stack[hidx] = native_frame\n            hidx -= 1\n\n    if pidx >= 0:\n        # We ran out of native frames without using up all of our Python\n        # frames. We've seen this happen on stripped interpreters on Alpine\n        # Linux in CI. Presumably this indicates that unwinding failed to\n        # symbolify some of the Python frame boundaries (_PyEval_EvalFrameDefault\n        # or Python 3.14 tail call interpreter functions).\n        return python_stack\n    assert hidx == -1\n\n    return hybrid_stack[:max_stacks]\n\n\n@cython.freelist(1024)\ncdef class AllocationRecord:\n    cdef object _tuple\n    cdef dict _stack_trace_cache\n    cdef shared_ptr[RecordReader] _reader\n\n    def __init__(self, record):\n        self._tuple = record\n        self._stack_trace_cache = {}\n\n    def __eq__(self, other):\n        cdef AllocationRecord _other\n        if isinstance(other, AllocationRecord):\n            _other = other\n            return self._tuple == _other._tuple\n        return NotImplemented\n\n    def __hash__(self):\n        return hash(self._tuple)\n\n    @property\n    def tid(self):\n        return self._tuple[0]\n\n    @property\n    def address(self):\n        return self._tuple[1]\n\n    @property\n    def size(self):\n        return self._tuple[2]\n\n    @property\n    def allocator(self):\n        return self._tuple[3]\n\n    @property\n    def stack_id(self):\n        return self._tuple[4]\n\n    @property\n    def n_allocations(self):\n        return self._tuple[5]\n\n    @property\n    def native_stack_id(self):\n        return self._tuple[6]\n\n    @property\n    def native_segment_generation(self):\n        return self._tuple[7]\n\n    @property\n    def thread_name(self):\n        if self.tid == -1:\n            return \"merged thread\"\n        assert self._reader.get() != NULL, \"Cannot get thread name without reader.\"\n        return self._reader.get().getThreadName(self.tid)\n\n    def stack_trace(self, max_stacks=None):\n        cache_key = (\"python\", max_stacks)\n        if cache_key not in self._stack_trace_cache:\n            self._stack_trace_cache[cache_key] = stack_trace(\n                self._reader.get(),\n                self.tid,\n                self.allocator,\n                self.stack_id,\n                max_stacks,\n            )\n        return self._stack_trace_cache[cache_key]\n\n    def native_stack_trace(self, max_stacks=None):\n        cache_key = (\"native\", max_stacks)\n        if cache_key not in self._stack_trace_cache:\n            self._stack_trace_cache[cache_key] = native_stack_trace(\n                self._reader.get(),\n                self.allocator,\n                self.native_stack_id,\n                self.native_segment_generation,\n                max_stacks,\n            )\n        return self._stack_trace_cache[cache_key]\n\n    def hybrid_stack_trace(self, max_stacks=None):\n        cache_key = (\"hybrid\", max_stacks)\n        if cache_key not in self._stack_trace_cache:\n            self._stack_trace_cache[cache_key] = hybrid_stack_trace(\n                self._reader.get(),\n                self.tid,\n                self.allocator,\n                self.stack_id,\n                self.native_stack_id,\n                self.native_segment_generation,\n                max_stacks,\n            )\n        return self._stack_trace_cache[cache_key]\n\n    def __repr__(self):\n        return (f\"AllocationRecord<tid={hex(self.tid)}, address={hex(self.address)}, \"\n                f\"size={'N/A' if not self.size else size_fmt(self.size)}, allocator={self.allocator!r}, \"\n                f\"allocations={self.n_allocations}>\")\n\n\n@cython.freelist(1024)\ncdef class TrackedObjectRecord:\n    cdef object _tuple\n    cdef dict _stack_trace_cache\n    cdef shared_ptr[RecordReader] _reader\n\n    def __init__(self, record):\n        self._tuple = record\n        self._stack_trace_cache = {}\n\n    def __eq__(self, other):\n        cdef TrackedObjectRecord _other\n        if isinstance(other, TrackedObjectRecord):\n            _other = other\n            return self._tuple == _other._tuple\n        return NotImplemented\n\n    def __hash__(self):\n        return hash(self._tuple)\n\n    @property\n    def tid(self):\n        return self._tuple[0]\n\n    @property\n    def address(self):\n        return self._tuple[1]\n\n    @property\n    def is_created(self):\n        return self._tuple[2]\n\n    @property\n    def stack_id(self):\n        return self._tuple[3]\n\n    @property\n    def native_stack_id(self):\n        return self._tuple[4]\n\n    @property\n    def native_segment_generation(self):\n        return self._tuple[5]\n\n    @property\n    def thread_name(self):\n        if self.tid == -1:\n            return \"merged thread\"\n        assert self._reader.get() != NULL, \"Cannot get thread name without reader.\"\n        return self._reader.get().getThreadName(self.tid)\n\n    def stack_trace(self, max_stacks=None):\n        cache_key = (\"python\", max_stacks)\n        event = (\n                ObjectTrackingEvent.OBJECT_CREATED if self.is_created\n                else ObjectTrackingEvent.OBJECT_DESTROYED\n        )\n        if cache_key not in self._stack_trace_cache:\n            self._stack_trace_cache[cache_key] = stack_trace(\n                self._reader.get(),\n                self.tid,\n                event,\n                self.stack_id,\n                max_stacks,\n            )\n        return self._stack_trace_cache[cache_key]\n\n    def native_stack_trace(self, max_stacks=None):\n        cache_key = (\"native\", max_stacks)\n        event = (\n                ObjectTrackingEvent.OBJECT_CREATED if self.is_created\n                else ObjectTrackingEvent.OBJECT_DESTROYED\n        )\n        if cache_key not in self._stack_trace_cache:\n            self._stack_trace_cache[cache_key] = native_stack_trace(\n                self._reader.get(),\n                event,\n                self.native_stack_id,\n                self.native_segment_generation,\n                max_stacks,\n            )\n        return self._stack_trace_cache[cache_key]\n\n    def hybrid_stack_trace(self, max_stacks=None):\n        cache_key = (\"hybrid\", max_stacks)\n        if cache_key not in self._stack_trace_cache:\n            self._stack_trace_cache[cache_key] = hybrid_stack_trace(\n                self._reader.get(),\n                self.tid,\n                None,  # No allocator for objects\n                self.stack_id,\n                self.native_stack_id,\n                self.native_segment_generation,\n                max_stacks,\n            )\n        return self._stack_trace_cache[cache_key]\n\n    def __repr__(self):\n        return (f\"TrackedObjectRecord<tid={hex(self.tid)}, address={hex(self.address)}, \"\n                f\"is_created={self.is_created}, stack_id={self.stack_id}>\")\n\n\n@cython.freelist(1024)\ncdef class Interval:\n    cdef public size_t allocated_before_snapshot\n    cdef public object deallocated_before_snapshot\n    cdef public size_t n_allocations\n    cdef public size_t n_bytes\n\n    def __cinit__(\n        self,\n        size_t allocated_before_snapshot,\n        object deallocated_before_snapshot,\n        size_t n_allocations,\n        size_t n_bytes,\n    ):\n        self.allocated_before_snapshot = allocated_before_snapshot\n        self.deallocated_before_snapshot = deallocated_before_snapshot\n        self.n_allocations = n_allocations\n        self.n_bytes = n_bytes\n\n    def __eq__(self, other):\n        if type(other) is not Interval:\n            return NotImplemented\n        return (\n            self.allocated_before_snapshot,\n            self.deallocated_before_snapshot,\n            self.n_allocations,\n            self.n_bytes,\n        ) == (\n            other.allocated_before_snapshot,\n            other.deallocated_before_snapshot,\n            other.n_allocations,\n            other.n_bytes,\n        )\n\n    def __repr__(self):\n        return (\n            f\"Interval(allocated_before_snapshot={self.allocated_before_snapshot},\"\n            f\" deallocated_before_snapshot={self.deallocated_before_snapshot},\"\n            f\" n_allocations={self.n_allocations},\"\n            f\" n_bytes={self.n_bytes})\"\n        )\n\n\n@cython.freelist(1024)\ncdef class TemporalAllocationRecord:\n    cdef object _tuple\n    cdef dict _stack_trace_cache\n    cdef shared_ptr[RecordReader] _reader\n    cdef public object intervals\n\n    def __cinit__(self, record):\n        self._tuple = record\n        self._stack_trace_cache = {}\n        self.intervals = []\n\n    def __eq__(self, other):\n        if type(other) != TemporalAllocationRecord:\n            return NotImplemented\n        cdef TemporalAllocationRecord o = other\n        return self._tuple == o._tuple and self._intervals == o._intervals\n\n    def __hash__(self):\n        return hash(self._tuple)\n\n    @property\n    def tid(self):\n        return self._tuple[0]\n\n    @property\n    def allocator(self):\n        return self._tuple[1]\n\n    @property\n    def stack_id(self):\n        return self._tuple[2]\n\n    @property\n    def native_stack_id(self):\n        return self._tuple[3]\n\n    @property\n    def native_segment_generation(self):\n        return self._tuple[4]\n\n    @property\n    def thread_name(self):\n        assert self._reader.get() != NULL, \"Cannot get thread name without reader.\"\n        return self._reader.get().getThreadName(self.tid)\n\n    def stack_trace(self, max_stacks=None):\n        cache_key = (\"python\", max_stacks)\n        if cache_key not in self._stack_trace_cache:\n            self._stack_trace_cache[cache_key] = stack_trace(\n                self._reader.get(),\n                self.tid,\n                self.allocator,\n                self.stack_id,\n                max_stacks,\n            )\n        return self._stack_trace_cache[cache_key]\n\n    def native_stack_trace(self, max_stacks=None):\n        cache_key = (\"native\", max_stacks)\n        if cache_key not in self._stack_trace_cache:\n            self._stack_trace_cache[cache_key] = native_stack_trace(\n                self._reader.get(),\n                self.allocator,\n                self.native_stack_id,\n                self.native_segment_generation,\n                max_stacks,\n            )\n        return self._stack_trace_cache[cache_key]\n\n    def hybrid_stack_trace(self, max_stacks=None):\n        cache_key = (\"hybrid\", max_stacks)\n        if cache_key not in self._stack_trace_cache:\n            self._stack_trace_cache[cache_key] = hybrid_stack_trace(\n                self._reader.get(),\n                self.tid,\n                self.allocator,\n                self.stack_id,\n                self.native_stack_id,\n                self.native_segment_generation,\n                max_stacks,\n            )\n        return self._stack_trace_cache[cache_key]\n\n\ncdef create_temporal_allocation_record(\n    const HighWaterMarkLocationKey& key,\n    shared_ptr[RecordReader] reader,\n):\n    cdef object elem = (\n        key.thread_id,\n        <int>key.allocator,\n        key.python_frame_id,\n        key.native_frame_id,\n        key.native_segment_generation,\n    )\n    cdef TemporalAllocationRecord alloc = TemporalAllocationRecord(elem)\n    alloc._reader = reader\n    return alloc\n\n\ncdef class TemporalAllocationGenerator:\n    cdef vector[AllocationLifetime] lifetimes\n    cdef shared_ptr[RecordReader] reader\n\n    cdef TemporalAllocationRecord curr_record\n    cdef HighWaterMarkLocationKey last_key\n    cdef size_t idx\n\n    cdef setup(\n        self,\n        vector[AllocationLifetime]&& lifetimes,\n        shared_ptr[RecordReader] reader,\n    ):\n        self.lifetimes = move(lifetimes)\n        self.reader = move(reader)\n\n    def __iter__(self):\n        return self\n\n    def __next__(self):\n        to_return = None\n        cdef AllocationLifetime lifetime\n        while self.idx < self.lifetimes.size():\n            lifetime = self.lifetimes[self.idx]\n            self.idx += 1\n\n            if lifetime.key != self.last_key:\n                if self.curr_record is not None:\n                    to_return = self.curr_record\n                self.last_key = lifetime.key\n                self.curr_record = create_temporal_allocation_record(\n                    lifetime.key, self.reader\n                )\n\n            if lifetime.deallocatedBeforeSnapshot == <size_t>(-1):\n                deallocated_before_snapshot = None\n            else:\n                deallocated_before_snapshot = lifetime.deallocatedBeforeSnapshot\n\n            self.curr_record.intervals.append(\n                Interval(\n                    lifetime.allocatedBeforeSnapshot,\n                    deallocated_before_snapshot,\n                    lifetime.n_allocations,\n                    lifetime.n_bytes,\n                )\n            )\n\n            if to_return is not None:\n                return to_return\n\n        if self.curr_record is not None:\n            to_return = self.curr_record\n            self.curr_record = None\n            return to_return\n        raise StopIteration\n\n\nMemorySnapshot = collections.namedtuple(\"MemorySnapshot\", \"time rss heap\")\n\ntracker_creation_lock = threading.Lock()\n\n\ncdef class Tracker:\n    \"\"\"Context manager for tracking memory allocations in a Python script.\n\n    You can track memory allocations in a Python process by using a Tracker as\n    a context manager::\n\n        with memray.Tracker(\"some_output_file.bin\"):\n\n    Any code inside of the ``with`` block will have its allocations tracked.\n    Any allocations made by other threads will also be tracked for the duration\n    of the ``with`` block. Because of the way tracking works, there can only be\n    one tracker active in the entire program at a time. Attempting to activate\n    a tracker while one is already active will raise an exception, as will\n    attempting to activate the same tracker more than once. If you want to\n    re-enable tracking after the ``with`` block ends, you will need to create\n    a fresh `Tracker` instance.\n\n    Args:\n        file_name (str or pathlib.Path): The name of the file to write the\n            captured allocations into. This is the only argument that can be\n            passed positionally. If not provided, the *destination* keyword\n            argument must be provided.\n        destination (FileDestination or SocketDestination): The destination to\n            write captured allocations to. If provided, the *file_name*\n            argument must not be provided.\n        native_traces (bool): Whether or not to capture native stack frames, in\n            addition to Python stack frames (see :ref:`Native Tracking`).\n            Defaults to False.\n        trace_python_allocators (bool): Whether or not to trace Python allocators\n            as independent allocations. (see :ref:`Python allocators`).\n            Defaults to False.\n        track_object_lifetimes (bool): Whether or not to track which objects are\n            created during the tracking session and still alive at the end (or\n            in other words, what objects are leaked by the code being tracked).\n            Defaults to False.\n        follow_fork (bool): Whether or not to continue tracking in a subprocess\n            that is forked from the tracked process (see :ref:`Tracking across\n            Forks`). Defaults to False.\n        memory_interval_ms (int): How many milliseconds to wait between sending\n            periodic resident set size updates. By default, every 10\n            milliseconds a record is written that contains the current\n            timestamp and the total number of bytes of virtual memory allocated\n            by the process. These records are used to create the graph of\n            memory usage over time that appears at the top of the flame graph,\n            for instance. This parameter lets you adjust the frequency between\n            updates, though you shouldn't need to change it.\n        file_format (FileFormat): The format that should be used when writing\n            to the capture file. See the `FileFormat` documentation for a list\n            of supported file formats and their limitations.\n    \"\"\"\n    cdef bool _native_traces\n    cdef bool _track_object_lifetimes\n    cdef unsigned int _memory_interval_ms\n    cdef bool _follow_fork\n    cdef bool _trace_python_allocators\n    cdef object _previous_profile_func\n    cdef object _previous_thread_profile_func\n    cdef unique_ptr[RecordWriter] _writer\n    cdef object _surviving_objects\n\n    cdef unique_ptr[Sink] _make_writer(self, destination) except*:\n        # Creating a Sink can raise Python exceptions (if is interrupted by signal\n        # handlers). If this happens, this method will propagate the appropriate exception.\n        if isinstance(destination, FileDestination):\n            is_dev_null = False\n            with contextlib.suppress(OSError):\n                if pathlib.Path(\"/dev/null\").samefile(destination.path):\n                    is_dev_null = True\n\n            if is_dev_null:\n                return unique_ptr[Sink](new NullSink())\n            return unique_ptr[Sink](new FileSink(os.fsencode(destination.path),\n                                                 destination.overwrite,\n                                                 destination.compress_on_exit))\n\n        elif isinstance(destination, SocketDestination):\n            return unique_ptr[Sink](new SocketSink(destination.address, destination.server_port))\n        else:\n            raise TypeError(\"destination must be a SocketDestination or FileDestination\")\n\n    def __cinit__(self, object file_name=None, *, object destination=None,\n                  bool native_traces=False, unsigned int memory_interval_ms = 10,\n                  bool follow_fork=False, bool trace_python_allocators=False,\n                  bool track_object_lifetimes=False,\n                  FileFormat file_format=FileFormat.ALL_ALLOCATIONS):\n        if (file_name, destination).count(None) != 1:\n            raise TypeError(\"Exactly one of 'file_name' or 'destination' argument must be specified\")\n\n        # Check Python version if reference tracking is enabled\n        if track_object_lifetimes and sys.version_info < (3, 13, 3):\n            raise RuntimeError(\n                \"Python object reference tracking requires Python 3.13.3 or later. \"\n                f\"Current version: {'.'.join(map(str, sys.version_info[:3]))}\"\n            )\n\n        cdef cppstring command_line = \" \".join(sys.argv)\n        self._native_traces = native_traces\n        self._track_object_lifetimes = track_object_lifetimes\n        self._memory_interval_ms = memory_interval_ms\n        self._follow_fork = follow_fork\n        self._trace_python_allocators = trace_python_allocators\n\n        if file_name is not None:\n            destination = FileDestination(path=file_name)\n\n        if not isinstance(destination, FileDestination):\n            if follow_fork:\n                raise RuntimeError(\"follow_fork requires an output file\")\n\n            if file_format != FileFormat.ALL_ALLOCATIONS:\n                raise RuntimeError(\"AGGREGATED_ALLOCATIONS requires an output file\")\n\n        self._writer = move(\n            createRecordWriter(\n                move(self._make_writer(destination)),\n                command_line,\n                native_traces,\n                file_format,\n                trace_python_allocators,\n                track_object_lifetimes,\n            )\n        )\n\n    @cython.profile(False)\n    def __enter__(self):\n        cdef unique_ptr[RecordWriter] writer\n        with tracker_creation_lock:\n            if NativeTracker.getTracker() != NULL:\n                raise RuntimeError(\"No more than one Tracker instance can be active at the same time\")\n\n            if self._writer == NULL:\n                raise RuntimeError(\"Attempting to use stale output handle\")\n            writer = move(self._writer)\n\n            for attr in (\"_name\", \"_ident\"):\n                assert not hasattr(threading.Thread, attr)\n                setattr(\n                    threading.Thread,\n                    attr,\n                    ThreadNameInterceptor(attr, NativeTracker.registerThreadNameById),\n                )\n\n            orig_set_os_name = getattr(threading.Thread, \"_set_os_name\", None)\n            if orig_set_os_name is not None:\n                def set_os_name_wrapper(self):\n                    cdef unique_ptr[RecursionGuard] guard = make_unique[RecursionGuard]()\n                    orig_set_os_name(self)\n\n                setattr(threading.Thread, \"_set_os_name\", set_os_name_wrapper)\n\n            self._previous_profile_func = sys.getprofile()\n            self._previous_thread_profile_func = threading._profile_hook\n            threading.setprofile(start_thread_trace)\n\n            if \"greenlet\" in sys.modules:\n                NativeTracker.beginTrackingGreenlets()\n\n            NativeTracker.createTracker(\n                move(writer),\n                self._native_traces,\n                self._memory_interval_ms,\n                self._follow_fork,\n                self._trace_python_allocators,\n                self._track_object_lifetimes,\n            )\n            return self\n\n    @cython.profile(False)\n    def __exit__(self, exc_type, exc_value, exc_traceback):\n        if self._track_object_lifetimes:\n            self._populate_surviving_objects()\n        with tracker_creation_lock:\n            NativeTracker.destroyTracker()\n            sys.setprofile(self._previous_profile_func)\n            threading.setprofile(self._previous_thread_profile_func)\n\n            for attr in (\"_name\", \"_ident\"):\n                delattr(threading.Thread, attr)\n\n    cdef void _populate_surviving_objects(self):\n        cdef NativeTracker *tracker = NativeTracker.getTracker()\n        if tracker == NULL:\n            return\n\n        cdef unordered_set[PyObject*] objects = tracker.getSurvivingObjects()\n        self._surviving_objects = []\n        for obj in objects:\n            self._surviving_objects.append(<object>obj)\n            Py_DECREF(<object>obj)\n\n    def get_surviving_objects(self):\n        \"\"\"Get a list of objects that were alive at the end of the tracking period.\n\n        Returns:\n            list: A list of objects that were alive at the end of the tracking period.\n\n        Raises:\n            RuntimeError: If *track_object_lifetimes* was not enabled at\n                Tracker construction, or if tracking has not completed yet.\n        \"\"\"\n        if not self._track_object_lifetimes:\n            raise RuntimeError(\n                \"track_object_lifetimes=True was not provided at Tracker construction\"\n            )\n        if self._surviving_objects is None:\n            raise RuntimeError(\n                \"Tracking was never started or has not finished yet or failed.\"\n            )\n        return tuple(self._surviving_objects)\n\n\ndef start_thread_trace(frame, event, arg):\n    if event in {\"call\", \"c_call\"}:\n        install_trace_function()\n    return start_thread_trace\n\n\ndef greenlet_trace_function(event, args):\n    if event in {\"switch\", \"throw\"}:\n        NativeTracker.handleGreenletSwitch(args[0], args[1])\n\n\ndef print_greenlet_warning():\n    pprint(\n        \":warning: [bold red]Memray support for Greenlet is experimental[/] :warning:\\n\"\n        \"[yellow]Please report any issues at https://github.com/bloomberg/memray/issues[/]\\n\"\n        \"\\n\",\n        file=sys.stderr,\n    )\n\n\ncdef millis_to_dt(millis):\n    return datetime.fromtimestamp(millis // 1000).replace(\n        microsecond=millis % 1000 * 1000).astimezone()\n\n\ncdef _create_metadata(header, peak_memory):\n    stats = header[\"stats\"]\n    allocator_id_to_name = {\n        PythonAllocatorType.PYTHON_ALLOCATOR_PYMALLOC: \"pymalloc\",\n        PythonAllocatorType.PYTHON_ALLOCATOR_PYMALLOC_DEBUG: \"pymalloc debug\",\n        PythonAllocatorType.PYTHON_ALLOCATOR_MIMALLOC: \"mimalloc\",\n        PythonAllocatorType.PYTHON_ALLOCATOR_MIMALLOC_DEBUG: \"mimalloc debug\",\n        PythonAllocatorType.PYTHON_ALLOCATOR_MALLOC: \"malloc\",\n        PythonAllocatorType.PYTHON_ALLOCATOR_OTHER: \"unknown\",\n    }\n    return Metadata(\n        start_time=millis_to_dt(stats[\"start_time\"]),\n        end_time=millis_to_dt(stats[\"end_time\"]),\n        total_allocations=stats[\"n_allocations\"],\n        total_frames=stats[\"n_frames\"],\n        peak_memory=peak_memory,\n        command_line=header[\"command_line\"],\n        pid=header[\"pid\"],\n        main_thread_id=header[\"main_tid\"],\n        python_allocator=allocator_id_to_name[header[\"python_allocator\"]],\n        has_native_traces=header[\"native_traces\"],\n        trace_python_allocators=header[\"trace_python_allocators\"],\n        file_format=FileFormat(header[\"file_format\"]),\n    )\n\n\ncdef class ProgressIndicator:\n    cdef bool _report_progress\n    cdef object _indicator\n    cdef object _context_manager\n    cdef object _task\n    cdef object _task_description\n    cdef object _total\n    cdef size_t _cumulative_num_processed\n    cdef size_t _update_interval\n    cdef size_t _ns_between_refreshes\n    cdef timespec _next_refresh\n\n    def __init__(self,\n        str task_description,\n        object total,\n        bool report_progress=True,\n        size_t refresh_per_second=10,\n    ):\n        self._report_progress = report_progress\n        self._total = total\n        self._cumulative_num_processed = 0\n        # Only check the elapsed time every N records\n        self._update_interval = 100_000\n        self._ns_between_refreshes = 1_000_000_000 // refresh_per_second\n        self._next_refresh.tv_sec = 0\n        self._next_refresh.tv_nsec = 0\n        self._task_description = task_description\n        self._task = None\n        self._context_manager = None\n        if report_progress:\n            self._indicator = Progress(\n                SpinnerColumn(),\n                *Progress.get_default_columns(),\n                auto_refresh=False,\n                transient=True,\n            )\n\n    def __enter__(self):\n        if not self._report_progress:\n            return self\n        self._context_manager = self._indicator.__enter__()\n        self._task = self._context_manager.add_task(\n            f\"[cyan]{self._task_description}...\",\n            total=self._total\n        )\n        return self\n\n    def __exit__(self, type, value, traceback):\n        if not self._report_progress:\n            return\n        self._context_manager.update(self._task, completed=self._cumulative_num_processed)\n        return self._context_manager.__exit__(type, value, traceback)\n\n    cdef bool _time_for_refresh(self):\n        cdef timespec now\n        cdef int rc = clock_gettime(CLOCK_MONOTONIC, &now)\n\n        if 0 != rc:\n            return True\n\n        if now.tv_sec > self._next_refresh.tv_sec or (\n            now.tv_sec == self._next_refresh.tv_sec\n            and now.tv_nsec > self._next_refresh.tv_nsec\n        ):\n            self._next_refresh = now\n            self._next_refresh.tv_nsec += self._ns_between_refreshes\n            while self._next_refresh.tv_nsec > 1_000_000_000:\n                self._next_refresh.tv_nsec -= 1_000_000_000\n                self._next_refresh.tv_sec += 1\n            return True\n\n        return False\n\n    cdef update(self, size_t n_processed):\n        self._cumulative_num_processed += n_processed\n        if not self._report_progress:\n            return\n        if self._cumulative_num_processed % self._update_interval == 0:\n            if self._time_for_refresh():\n                assert(self._context_manager is not None)\n                self._context_manager.update(\n                    self._task, completed=self._cumulative_num_processed\n                )\n                self._context_manager.refresh()\n\n    @property\n    def num_processed(self):\n        return self._cumulative_num_processed\n\n\ncdef class FileReader:\n    cdef cppstring _path\n\n    cdef object _file\n    cdef vector[_MemorySnapshot] _memory_snapshots\n    cdef HighWatermark _high_watermark\n    cdef object _header\n    cdef bool _report_progress\n    cdef size_t _memory_snapshot_stride\n\n    def __cinit__(self, object file_name, *, bool report_progress=False, int max_memory_records=10000):\n        try:\n            self._file = open(file_name)\n        except OSError as exc:\n            raise OSError(f\"Could not open file {file_name}: {exc.strerror}\") from None\n\n        if platform.system() == \"Linux\":\n            self._path = \"/proc/self/fd/\" + str(self._file.fileno())\n        else:\n            self._path = str(file_name)\n        self._report_progress = report_progress\n\n        # Initial pass to populate _header, _high_watermark, and _memory_snapshots.\n        cdef shared_ptr[RecordReader] reader_sp = make_shared[RecordReader](\n            unique_ptr[FileSource](new FileSource(self._path)),\n            False\n        )\n        cdef RecordReader* reader = reader_sp.get()\n\n        self._header = reader.getHeader()\n        stats = self._header[\"stats\"]\n\n        n_memory_snapshots_approx = 2048\n        if 0 < stats[\"start_time\"] < stats[\"end_time\"]:\n            n_memory_snapshots_approx = (stats[\"end_time\"] - stats[\"start_time\"]) / 10\n\n        if n_memory_snapshots_approx > max_memory_records:\n            n_memory_snapshots_approx = max_memory_records\n        self._memory_snapshots.reserve(n_memory_snapshots_approx)\n\n        cdef object total = stats['n_allocations'] or None\n        cdef HighWatermarkFinder finder\n\n        cdef ProgressIndicator progress_indicator = ProgressIndicator(\n            \"Calculating high watermark\",\n            total=total,\n            report_progress=self._report_progress\n        )\n        self._memory_snapshot_stride = 0\n        cdef MemoryRecord memory_record\n        with progress_indicator:\n            while True:\n                PyErr_CheckSignals()\n                ret = reader.nextRecord()\n                if ret == RecordResult.RecordResultAllocationRecord:\n                    finder.processAllocation(reader.getLatestAllocation())\n                    progress_indicator.update(1)\n                elif ret == RecordResult.RecordResultAggregatedAllocationRecord:\n                    finder.processAllocation(\n                        reader.getLatestAggregatedAllocation().contributionToHighWaterMark()\n                    )\n                    progress_indicator.update(1)\n                elif ret == RecordResult.RecordResultMemoryRecord:\n                    memory_record = reader.getLatestMemoryRecord()\n                    self._memory_snapshots.push_back(\n                        _MemorySnapshot(\n                            memory_record.ms_since_epoch,\n                            memory_record.rss,\n                            finder.getCurrentWatermark(),\n                        )\n                    )\n                elif ret == RecordResult.RecordResultMemorySnapshot:\n                    self._memory_snapshots.push_back(reader.getLatestMemorySnapshot())\n                else:\n                    break\n\n        if len(self._memory_snapshots) > max_memory_records:\n            self._memory_snapshot_stride = int(ceil(<double>len(self._memory_snapshots) / max_memory_records))\n            self._memory_snapshots = self._memory_snapshots[::self._memory_snapshot_stride]\n        self._high_watermark = finder.getHighWatermark()\n        stats[\"n_allocations\"] = progress_indicator.num_processed\n\n    def __dealloc__(self):\n        self.close()\n\n    cpdef close(self):\n        if self._file is not None:\n            file = self._file\n            self._file = None\n            file.close()\n\n    cdef void _ensure_not_closed(self) except *:\n        if self._file is None:\n            raise ValueError(\"Operation on a closed FileReader\")\n\n    @property\n    def closed(self):\n        return self._file is None\n\n    def __enter__(self):\n        return self\n\n    def __exit__(self, exc_type, exc_value, exc_traceback):\n        self.close()\n\n    def _reaggregate_allocations(\n        self, size_t records_to_process, bool merge_threads, bool leaks\n    ):\n        \"\"\"Aggregate records from an AGGREGATED_ALLOCATIONS capture file.\n\n        An extra aggregation pass is still needed to account for merge_threads,\n        as well as (for now at least) different location key formats.\n        \"\"\"\n        cdef AggregatedCaptureReaggregator aggregator\n        cdef shared_ptr[RecordReader] reader_sp = make_shared[RecordReader](\n            unique_ptr[FileSource](new FileSource(self._path))\n        )\n        cdef RecordReader* reader = reader_sp.get()\n\n        cdef ProgressIndicator progress_indicator = ProgressIndicator(\n            \"Processing allocation records\",\n            total=records_to_process,\n            report_progress=self._report_progress\n        )\n\n        cdef AggregatedAllocation record\n        with progress_indicator:\n            while True:\n                PyErr_CheckSignals()\n                ret = reader.nextRecord()\n                if ret == RecordResult.RecordResultAggregatedAllocationRecord:\n                    record = reader.getLatestAggregatedAllocation()\n                    if leaks:\n                        aggregator.addAllocation(record.contributionToLeaks())\n                    else:\n                        aggregator.addAllocation(record.contributionToHighWaterMark())\n                    records_to_process -= 1\n                    progress_indicator.update(1)\n                elif ret == RecordResult.RecordResultMemorySnapshot:\n                    pass\n                else:\n                    assert ret != RecordResult.RecordResultMemoryRecord\n                    assert ret != RecordResult.RecordResultAllocationRecord\n                    break\n\n        for elem in Py_ListFromSnapshotAllocationRecords(\n            aggregator.getSnapshotAllocations(merge_threads)\n        ):\n            alloc = AllocationRecord(elem)\n            (<AllocationRecord> alloc)._reader = reader_sp\n            yield alloc\n\n        reader.close()\n\n    def _aggregate_allocations(self, size_t records_to_process, bool merge_threads,\n                               size_t temporary_buffer_size=0):\n        cdef unique_ptr[AbstractAggregator] the_aggregator\n        if temporary_buffer_size:\n            the_aggregator.reset(\n                new TemporaryAllocationsAggregator(temporary_buffer_size)\n            )\n        else:\n            the_aggregator.reset(new SnapshotAllocationAggregator())\n        cdef AbstractAggregator* aggregator = the_aggregator.get()\n\n        cdef shared_ptr[RecordReader] reader_sp = make_shared[RecordReader](\n            unique_ptr[FileSource](new FileSource(self._path))\n        )\n        cdef RecordReader* reader = reader_sp.get()\n\n        cdef ProgressIndicator progress_indicator = ProgressIndicator(\n            \"Processing allocation records\",\n            total=records_to_process,\n            report_progress=self._report_progress\n        )\n\n        with progress_indicator:\n            while records_to_process > 0:\n                PyErr_CheckSignals()\n                ret = reader.nextRecord()\n                if ret == RecordResult.RecordResultAllocationRecord:\n                    aggregator.addAllocation(reader.getLatestAllocation())\n                    records_to_process -= 1\n                    progress_indicator.update(1)\n                elif ret == RecordResult.RecordResultMemoryRecord:\n                    pass\n                else:\n                    assert ret != RecordResult.RecordResultMemorySnapshot\n                    assert ret != RecordResult.RecordResultAggregatedAllocationRecord\n                    break\n\n        for elem in Py_ListFromSnapshotAllocationRecords(\n            aggregator.getSnapshotAllocations(merge_threads)\n        ):\n            alloc = AllocationRecord(elem)\n            (<AllocationRecord> alloc)._reader = reader_sp\n            yield alloc\n\n        reader.close()\n\n    def get_high_watermark_allocation_records(self, merge_threads=True):\n        self._ensure_not_closed()\n        if self._header[\"file_format\"] == FileFormat.AGGREGATED_ALLOCATIONS:\n            yield from self._reaggregate_allocations(\n                self._header[\"stats\"][\"n_allocations\"],\n                merge_threads,\n                leaks=False,\n            )\n            return\n\n        # If allocation 0 caused the peak, we need to process 1 record, etc\n        cdef size_t max_records = self._high_watermark.index + 1\n        yield from self._aggregate_allocations(max_records, merge_threads)\n\n    def get_leaked_allocation_records(self, merge_threads=True):\n        self._ensure_not_closed()\n        if self._header[\"file_format\"] == FileFormat.AGGREGATED_ALLOCATIONS:\n            yield from self._reaggregate_allocations(\n                self._header[\"stats\"][\"n_allocations\"],\n                merge_threads,\n                leaks=True,\n            )\n            return\n\n        cdef size_t max_records = self._header[\"stats\"][\"n_allocations\"]\n        yield from self._aggregate_allocations(max_records, merge_threads)\n\n    def get_temporary_allocation_records(self, merge_threads=True, threshold=1):\n        self._ensure_not_closed()\n        if self._header[\"file_format\"] == FileFormat.AGGREGATED_ALLOCATIONS:\n            raise NotImplementedError(\n                \"Can't find temporary allocations using a pre-aggregated capture file.\"\n            )\n\n        cdef size_t max_records = self._header[\"stats\"][\"n_allocations\"]\n        yield from self._aggregate_allocations(\n            max_records,\n            merge_threads,\n            temporary_buffer_size=threshold + 1,\n        )\n\n    def get_temporal_allocation_records(self, merge_threads=True):\n        self._ensure_not_closed()\n        if self._header[\"file_format\"] == FileFormat.AGGREGATED_ALLOCATIONS:\n            raise NotImplementedError(\n                \"Can't get allocation history using a pre-aggregated capture file.\"\n            )\n\n        cdef shared_ptr[RecordReader] reader_sp = make_shared[RecordReader](\n            unique_ptr[FileSource](new FileSource(self._path))\n        )\n        cdef RecordReader* reader = reader_sp.get()\n\n        cdef size_t records_to_process = self._header[\"stats\"][\"n_allocations\"]\n        cdef ProgressIndicator progress_indicator = ProgressIndicator(\n            \"Processing allocation records\",\n            total=records_to_process,\n            report_progress=self._report_progress\n        )\n\n        cdef AllocationLifetimeAggregator aggregator\n        cdef _Allocation allocation\n        cdef size_t memory_records_seen = 0\n\n        with progress_indicator:\n            while records_to_process > 0:\n                PyErr_CheckSignals()\n                ret = reader.nextRecord()\n                if ret == RecordResult.RecordResultAllocationRecord:\n                    allocation = reader.getLatestAllocation()\n                    if merge_threads:\n                        allocation.tid = NO_THREAD_INFO\n                    aggregator.addAllocation(allocation)\n                    records_to_process -= 1\n                    progress_indicator.update(1)\n                elif ret == RecordResult.RecordResultMemoryRecord:\n                    memory_records_seen += 1\n                    if self._memory_snapshot_stride and (memory_records_seen - 1) % self._memory_snapshot_stride != 0:\n                        continue\n                    aggregator.captureSnapshot()\n                else:\n                    assert ret != RecordResult.RecordResultMemorySnapshot\n                    assert ret != RecordResult.RecordResultAggregatedAllocationRecord\n                    break\n\n        cdef TemporalAllocationGenerator gen = TemporalAllocationGenerator()\n        gen.setup(move(aggregator.generateIndex()), reader_sp)\n        yield from gen\n\n    def get_temporal_high_water_mark_allocation_records(self, merge_threads=True):\n        self._ensure_not_closed()\n        if self._header[\"file_format\"] == FileFormat.AGGREGATED_ALLOCATIONS:\n            raise NotImplementedError(\n                \"Can't get allocation history using a pre-aggregated capture file.\"\n            )\n\n        cdef shared_ptr[RecordReader] reader_sp = make_shared[RecordReader](\n            unique_ptr[FileSource](new FileSource(self._path))\n        )\n        cdef RecordReader* reader = reader_sp.get()\n\n        cdef size_t records_to_process = self._header[\"stats\"][\"n_allocations\"]\n        cdef ProgressIndicator progress_indicator = ProgressIndicator(\n            \"Processing allocation records\",\n            total=records_to_process,\n            report_progress=self._report_progress\n        )\n\n        cdef HighWaterMarkAggregator aggregator\n        cdef _Allocation allocation\n        cdef size_t memory_records_seen = 0\n\n        with progress_indicator:\n            while records_to_process > 0:\n                PyErr_CheckSignals()\n                ret = reader.nextRecord()\n                if ret == RecordResult.RecordResultAllocationRecord:\n                    allocation = reader.getLatestAllocation()\n                    if merge_threads:\n                        allocation.tid = 0\n                    aggregator.addAllocation(allocation)\n                    records_to_process -= 1\n                    progress_indicator.update(1)\n                elif ret == RecordResult.RecordResultMemoryRecord:\n                    memory_records_seen += 1\n                    if self._memory_snapshot_stride and (memory_records_seen - 1) % self._memory_snapshot_stride != 0:\n                        continue\n                    aggregator.captureSnapshot()\n                else:\n                    assert ret != RecordResult.RecordResultMemorySnapshot\n                    assert ret != RecordResult.RecordResultAggregatedAllocationRecord\n                    break\n\n        cdef TemporalAllocationGenerator gen = TemporalAllocationGenerator()\n        gen.setup(move(aggregator.generateIndex()), reader_sp)\n        hwm_by_snapshot = aggregator.highWaterMarkBytesBySnapshot()\n        return gen, hwm_by_snapshot\n\n    def get_allocation_records(self):\n        self._ensure_not_closed()\n        if self._header[\"file_format\"] == FileFormat.AGGREGATED_ALLOCATIONS:\n            raise NotImplementedError(\n                \"Can't get all allocations from a pre-aggregated capture file.\"\n            )\n\n        cdef shared_ptr[RecordReader] reader_sp = make_shared[RecordReader](\n            unique_ptr[FileSource](new FileSource(self._path))\n        )\n        cdef RecordReader* reader = reader_sp.get()\n\n        while True:\n            PyErr_CheckSignals()\n            ret = reader.nextRecord()\n            if ret == RecordResult.RecordResultAllocationRecord:\n                alloc = AllocationRecord(reader.getLatestAllocation().toPythonObject())\n                (<AllocationRecord> alloc)._reader = reader_sp\n                yield alloc\n            elif ret == RecordResult.RecordResultMemoryRecord:\n                pass\n            elif ret == RecordResult.RecordResultMemorySnapshot:\n                pass\n            else:\n                break\n\n        reader.close()\n\n    def get_memory_snapshots(self):\n        for record in self._memory_snapshots:\n            yield MemorySnapshot(record.ms_since_epoch, record.rss, record.heap)\n\n    def get_object_lifetime_events(self, included_objects=None):\n        \"\"\"Return all object lifetime events recorded in the file.\n\n        This method yields TrackedObjectRecord instances representing Python objects\n        that were tracked during the recording session.\n\n        Args:\n            included_objects (list, optional): If provided, only yield\n                lifetime events for objects in the list.\n\n        Returns:\n            An iterator of TrackedObjectRecord instances.\n        \"\"\"\n        self._ensure_not_closed()\n\n        object_ids = set()\n        if included_objects is not None:\n            object_ids = {id(obj) for obj in included_objects}\n\n        cdef shared_ptr[RecordReader] reader_sp = make_shared[RecordReader](\n            unique_ptr[FileSource](new FileSource(self._path)),\n            True,  # track_stacks\n            True   # track_object_lifetimes\n        )\n        cdef RecordReader* reader = reader_sp.get()\n\n        # Check if the file was generated with object lifetime tracking enabled\n        cdef object header = reader.getHeader()\n        if not header[\"track_object_lifetimes\"]:\n            raise RuntimeError(\n                \"Object lifetime events are not available in this capture file. \"\n                \"The file was not generated with track_object_lifetimes=True.\"\n            )\n\n        cdef TrackedObject tracked_object\n        while True:\n            PyErr_CheckSignals()\n            ret = reader.nextRecord()\n            if ret == RecordResult.RecordResultObjectRecord:\n                tracked_object = reader.getLatestObject()\n                if included_objects is not None and tracked_object.address not in object_ids:\n                    continue\n                object_record = TrackedObjectRecord(tracked_object.toPythonObject())\n                object_record._reader = reader_sp\n                yield object_record\n            elif ret == RecordResult.RecordResultAllocationRecord:\n                pass\n            elif ret == RecordResult.RecordResultMemoryRecord:\n                pass\n            elif ret == RecordResult.RecordResultMemorySnapshot:\n                pass\n            else:\n                break\n\n        reader.close()\n\n    @property\n    def metadata(self):\n        return _create_metadata(self._header, self._high_watermark.peak_memory)\n\n\ndef compute_statistics(\n    file_name,\n    *,\n    report_progress=False,\n    num_largest=5,\n):\n    cdef shared_ptr[RecordReader] reader_sp = make_shared[RecordReader](\n        unique_ptr[FileSource](new FileSource(file_name))\n    )\n    cdef RecordReader* reader = reader_sp.get()\n\n    cdef header = reader.getHeader()\n    total = header[\"stats\"][\"n_allocations\"] or None\n\n    if header[\"file_format\"] == FileFormat.AGGREGATED_ALLOCATIONS:\n        raise NotImplementedError(\n            \"Can't compute statistics using a pre-aggregated capture file.\"\n        )\n\n    cdef AllocationStatsAggregator aggregator\n    cdef ProgressIndicator progress_indicator = ProgressIndicator(\n        \"Computing statistics\",\n        total=total,\n        report_progress=report_progress,\n    )\n    with progress_indicator:\n        while True:\n            PyErr_CheckSignals()\n            ret = reader.nextRecord()\n            if ret == RecordResult.RecordResultAllocationRecord:\n                aggregator.addAllocation(\n                    reader.getLatestAllocation(),\n                    reader.getLatestPythonLocationId(reader.getLatestAllocation()),\n                )\n                progress_indicator.update(1)\n            elif ret == RecordResult.RecordResultMemoryRecord:\n                pass\n            elif ret == RecordResult.RecordResultMemorySnapshot:\n                pass\n            elif ret == RecordResult.RecordResultObjectRecord:\n                pass\n            else:\n                assert ret != RecordResult.RecordResultMemorySnapshot\n                assert ret != RecordResult.RecordResultAggregatedAllocationRecord\n                break\n\n    # Ignore the n_allocations in the header, use our observed value.\n    header[\"stats\"][\"n_allocations\"] = progress_indicator.num_processed\n\n    # Convert allocation counts by allocator/by size to Python dicts.\n    cdef dict tmp = aggregator.allocationCountByAllocator()\n    allocation_count_by_allocator = {AllocatorType(k).name: v for k, v in tmp.items()}\n    cdef dict allocation_count_by_size = aggregator.allocationCountBySize();\n\n    # Convert top locations by bytes allocated/by allocation count to dicts\n    unknown = (\"<unknown>\", \"<unknown>\", 0)\n\n    top_locations_by_size = [\n        ((reader.Py_GetLocation(size_and_loc.second) or unknown), size_and_loc.first)\n        for size_and_loc in aggregator.topLocationsBySize(num_largest)\n    ]\n\n    top_locations_by_count = [\n        ((reader.Py_GetLocation(count_and_loc.second) or unknown), count_and_loc.first)\n        for count_and_loc in aggregator.topLocationsByCount(num_largest)\n    ]\n\n    # And we're done!\n    cdef uint64_t peak_memory = aggregator.peakBytesAllocated()\n    return Stats(\n        metadata=_create_metadata(header, peak_memory),\n        total_num_allocations=aggregator.totalAllocations(),\n        total_memory_allocated=aggregator.totalBytesAllocated(),\n        peak_memory_allocated=peak_memory,\n        allocation_count_by_size=allocation_count_by_size,\n        allocation_count_by_allocator=allocation_count_by_allocator,\n        top_locations_by_size=top_locations_by_size,\n        top_locations_by_count=top_locations_by_count,\n    )\n\n\ndef dump_all_records(object file_name):\n    cdef str path = str(file_name)\n    if not pathlib.Path(path).exists():\n        raise IOError(f\"No such file: {path}\")\n\n    cdef shared_ptr[RecordReader] _reader = make_shared[RecordReader](\n            unique_ptr[FileSource](new FileSource(path)))\n    _reader.get().dumpAllRecords()\n\n\ncdef class SocketReader:\n    cdef BackgroundSocketReader* _impl\n    cdef shared_ptr[RecordReader] _reader\n    cdef object _header\n    cdef object _port\n\n    def __cinit__(self, int port):\n        self._impl = NULL\n\n    def __init__(self, port: int):\n        self._header = {}\n        self._port = port\n\n    cdef _teardown(self):\n        with nogil:\n            del self._impl\n        self._impl = NULL\n\n    cdef unique_ptr[SocketSource] _make_source(self) except*:\n        # Creating a SocketSource can raise Python exceptions (if is interrupted by signal\n        # handlers). If this happens, this method will propagate the appropriate exception.\n        # We cannot use make_unique or C++ exceptions from SocketSource() won't be caught.\n        cdef SocketSource* source = new SocketSource(self._port)\n        return unique_ptr[SocketSource](source)\n\n    def __enter__(self):\n        if self._impl is not NULL:\n            raise ValueError(\n                \"Can not enter the context of a SocketReader object more than \"\n                \"once, at the same time.\"\n            )\n\n        self._reader = make_shared[RecordReader](move(self._make_source()))\n        self._header = self._reader.get().getHeader()\n\n        self._impl = new BackgroundSocketReader(self._reader)\n        self._impl.start()\n\n        return self\n\n    def __exit__(self, exc_type, exc_value, exc_traceback):\n        assert self._impl is not NULL\n\n        self._teardown()\n        self._reader.get().close()\n\n    def __dealloc__(self):\n        if self._impl is not NULL:\n            self._teardown()\n\n    @property\n    def command_line(self):\n        if not self._header:\n            return None\n        return self._header[\"command_line\"]\n\n    @property\n    def is_active(self):\n        if self._impl == NULL:\n            return False\n        return self._impl.is_active()\n\n    @property\n    def pid(self):\n        if not self._header:\n            return None\n        return self._header[\"pid\"]\n\n    @property\n    def has_native_traces(self):\n        if not self._header:\n            return False\n        return self._header[\"native_traces\"]\n\n    def get_current_snapshot(self, *, bool merge_threads):\n        if self._impl is NULL:\n            return\n\n        snapshot_allocations = self._impl.Py_GetSnapshotAllocationRecords(merge_threads=merge_threads)\n        for elem in snapshot_allocations:\n            alloc = AllocationRecord(elem)\n            (<AllocationRecord> alloc)._reader = self._reader\n            yield alloc\n\ncpdef enum SymbolicSupport:\n    NONE = 1\n    FUNCTION_NAME_ONLY = 2\n    TOTAL = 3\n\ndef get_symbolic_support():\n    locations = unwindHere()\n    for location in locations:\n        function, file, line = location.split(\":\")\n        # Check for Python frame boundaries: traditional _PyEval_EvalFrameDefault\n        # or Python 3.14 tail call interpreter LLVM-generated functions\n        is_python_frame_boundary = function == \"_PyEval_EvalFrameDefault\" or (\n            function.startswith(\"_TAIL_CALL_\") and \".llvm.\" in function\n        )\n        if not is_python_frame_boundary:\n            continue\n        if not file:\n            return SymbolicSupport.FUNCTION_NAME_ONLY\n        return SymbolicSupport.TOTAL\n    return SymbolicSupport.NONE\n\n\ncdef extern from \"<dlfcn.h>\":\n    int _RTLD_NOW \"RTLD_NOW\"\n    void* _RTLD_DEFAULT \"RTLD_DEFAULT\"\n\n\nRTLD_NOW = _RTLD_NOW\nRTLD_DEFAULT = <long long>_RTLD_DEFAULT\n\n\ncdef extern from \"snapshot.h\":\n    \"\"\"\n    std::vector<memray::tracking_api::AggregatedAllocation>\n    collectAllocations(const memray::api::HighWaterMarkAggregator& aggregator)\n    {\n        std::vector<memray::tracking_api::AggregatedAllocation> ret;\n        aggregator.visitAllocations([&](const memray::tracking_api::AggregatedAllocation& agg) {\n            if (agg.n_allocations_in_high_water_mark || agg.n_allocations_leaked) {\n                ret.push_back(agg);\n            }\n            return true;\n        });\n        return ret;\n    }\n    \"\"\"\n    vector[AggregatedAllocation] collectAllocations(HighWaterMarkAggregator) except+\n\n\ncdef class HighWaterMarkAggregatorTestHarness:\n    cdef HighWaterMarkAggregator aggregator\n\n    def add_allocation(\n        self,\n        tid,\n        address,\n        size,\n        allocator,\n        native_frame_id,\n        frame_index,\n        native_segment_generation,\n    ):\n        cdef _Allocation allocation\n        allocation.tid = tid\n        allocation.address = address\n        allocation.size = size\n        allocation.allocator = <Allocator><int>allocator\n        allocation.native_frame_id = native_frame_id\n        allocation.frame_index = frame_index\n        allocation.native_segment_generation = native_segment_generation\n        allocation.n_allocations = 1\n        self.aggregator.addAllocation(allocation)\n\n    def capture_snapshot(self):\n        return self.aggregator.captureSnapshot()\n\n    def high_water_mark_bytes_by_snapshot(self):\n        return self.aggregator.highWaterMarkBytesBySnapshot()\n\n    def get_current_heap_size(self):\n        return self.aggregator.getCurrentHeapSize()\n\n    def get_temporal_allocations(self):\n        cdef shared_ptr[RecordReader] reader\n        cdef TemporalAllocationGenerator gen = TemporalAllocationGenerator()\n        gen.setup(move(self.aggregator.generateIndex()), reader)\n        yield from gen\n\n    def get_allocations(self):\n        ret = []\n        for allocation in collectAllocations(self.aggregator):\n            ret.append(\n                dict(\n                    tid=allocation.tid,\n                    allocator=AllocatorType(<int>allocation.allocator),\n                    native_frame_id=allocation.native_frame_id,\n                    frame_index=allocation.frame_index,\n                    native_segment_generation=allocation.native_segment_generation,\n                    n_allocations_in_high_water_mark=allocation.n_allocations_in_high_water_mark,\n                    n_allocations_leaked=allocation.n_allocations_leaked,\n                    bytes_in_high_water_mark=allocation.bytes_in_high_water_mark,\n                    bytes_leaked=allocation.bytes_leaked,\n                )\n            )\n        return ret\n\n\ncdef class AllocationLifetimeAggregatorTestHarness:\n    cdef AllocationLifetimeAggregator aggregator\n\n    def add_allocation(\n        self,\n        tid,\n        address,\n        size,\n        allocator,\n        native_frame_id,\n        frame_index,\n        native_segment_generation,\n    ):\n        cdef _Allocation allocation\n        allocation.tid = tid\n        allocation.address = address\n        allocation.size = size\n        allocation.allocator = <Allocator><int>allocator\n        allocation.native_frame_id = native_frame_id\n        allocation.frame_index = frame_index\n        allocation.native_segment_generation = native_segment_generation\n        allocation.n_allocations = 1\n        self.aggregator.addAllocation(allocation)\n\n    def capture_snapshot(self):\n        return self.aggregator.captureSnapshot()\n\n    def get_allocations(self):\n        cdef shared_ptr[RecordReader] reader\n        cdef TemporalAllocationGenerator gen = TemporalAllocationGenerator()\n        gen.setup(move(self.aggregator.generateIndex()), reader)\n        yield from gen\n\n\ncdef class RecordWriterTestHarness:\n    \"\"\"A Python wrapper around the C++ RecordWriter class for testing purposes.\"\"\"\n\n    cdef unique_ptr[RecordWriter] _writer\n\n    def __cinit__(\n        self,\n        str file_path,\n        bool native_traces=False,\n        bool trace_python_allocators=False,\n        track_object_lifetimes=False,\n        records.FileFormat file_format=records.FileFormat.ALL_ALLOCATIONS,\n        records.thread_id_t main_tid=1,\n        size_t skipped_frames=0,\n        str command_line=\"memray test harness\",\n    ):\n        \"\"\"Initialize a new RecordWriterTestHarness.\n\n        Args:\n            file_path: Path to the output file\n            native_traces: Whether to include native traces\n            trace_python_allocators: Whether to trace Python allocators\n            track_object_lifetimes: Whether to track Python object lifetimes\n            file_format: The format of the output file\n        \"\"\"\n        self._writer = createRecordWriter(\n            unique_ptr[Sink](new FileSink(file_path.encode('utf-8'), True, False)),\n            command_line.encode(),\n            native_traces,\n            file_format,\n            trace_python_allocators,\n            track_object_lifetimes,\n        )\n        self._writer.get().setMainTidAndSkippedFrames(main_tid, skipped_frames)\n        self.write_header(False)\n\n    def write_header(self, bool seek_to_start) -> None:\n        if not self._writer.get().writeHeader(seek_to_start):\n            raise RuntimeError(\"Failed to write header\")\n\n    def write_memory_record(self, uint64_t ms_since_epoch, size_t rss) -> bool:\n        \"\"\"Write a memory record to the file.\"\"\"\n        cdef records.MemoryRecord record\n        record.ms_since_epoch = ms_since_epoch\n        record.rss = rss\n        return self._writer.get().writeRecord(record)\n\n    def write_code_object(\n        self,\n        records.code_object_id_t id,\n        str function_name,\n        str filename,\n        bytes linetable,\n        int firstlineno,\n    ) -> bool:\n        \"\"\"Write a code object record to the file.\"\"\"\n        return self._writer.get().writeRecord(\n            pair[records.code_object_id_t, records.CodeObjectInfo](\n                id,\n                records.CodeObjectInfo(\n                    function_name.encode(),\n                    filename.encode(),\n                    linetable,\n                    firstlineno,\n                )\n            )\n        )\n\n    @staticmethod\n    def get_linetable(code_object):\n        \"\"\"Get the linetable from a code object.\"\"\"\n        cdef const char* addr\n        cdef size_t size\n        import types\n        if not isinstance(code_object, types.CodeType):\n            raise TypeError(\"Expected a code object\")\n        addr = codeGetLinetable(<PyCodeObject*>code_object, &size)\n        return <bytes>addr[:size]\n\n    @staticmethod\n    def get_lasti(frame_object):\n        \"\"\"Get the linetable from a code object.\"\"\"\n        import types\n        if not isinstance(frame_object, types.FrameType):\n            raise TypeError(\"Expected a frame object\")\n        return frameGetLasti(<PyFrameObject*>frame_object)\n\n    def write_unresolved_native_frame(self, uintptr_t ip, size_t index) -> bool:\n        \"\"\"Write an unresolved native frame record to the file.\"\"\"\n        cdef records.UnresolvedNativeFrame record\n        record.ip = ip\n        record.index = index\n        return self._writer.get().writeRecord(record)\n\n    def write_allocation_record(self, records.thread_id_t tid, uintptr_t address,\n                                     size_t size, unsigned char allocator,\n                                     size_t native_frame_id=0) -> bool:\n        \"\"\"Write a native allocation record to the file.\"\"\"\n        cdef records.AllocationRecord record\n        record.address = address\n        record.size = size\n        record.allocator = <records.Allocator>allocator\n        record.native_frame_id = native_frame_id\n        return self._writer.get().writeThreadSpecificRecord(tid, record)\n\n    def write_frame_push(\n        self,\n        records.thread_id_t tid,\n        records.code_object_id_t code_object_id,\n        int instruction_offset,\n        bool is_entry_frame,\n    ) -> bool:\n        \"\"\"Write a frame push record to the file.\"\"\"\n        cdef records.FramePush record\n        record.frame.code_object_id = code_object_id\n        record.frame.instruction_offset = instruction_offset\n        record.frame.is_entry_frame = is_entry_frame\n        return self._writer.get().writeThreadSpecificRecord(tid, record)\n\n    def write_frame_pop(self, records.thread_id_t tid, size_t count) -> bool:\n        \"\"\"Write a frame pop record to the file.\"\"\"\n        cdef records.FramePop record\n        record.count = count\n        return self._writer.get().writeThreadSpecificRecord(tid, record)\n\n    def write_thread_record(self, records.thread_id_t tid, str name) -> bool:\n        \"\"\"Write a thread record to the file.\"\"\"\n        cdef records.ThreadRecord record\n        cdef bytes name_bytes = name.encode('utf-8')\n        record.name = name_bytes\n        return self._writer.get().writeThreadSpecificRecord(tid, record)\n\n    def write_mappings(self, list mappings) -> bool:\n        \"\"\"Write memory mappings to the file.\"\"\"\n        return self._writer.get().writeMappings(\n            [\n                records.ImageSegments(\n                    mapping['filename'].encode('utf-8'),\n                    mapping['addr'],\n                    [\n                        records.Segment(seg[\"vaddr\"], seg[\"memsz\"])\n                        for seg in mapping[\"segments\"]\n                    ],\n                )\n                for mapping in mappings\n            ]\n        )\n\n    def write_object_record(\n        self,\n        records.thread_id_t tid,\n        uintptr_t address,\n        bool is_created,\n        records.frame_id_t native_frame_id = 0,\n    ) -> bool:\n        \"\"\"Write an object tracking record to the file.\"\"\"\n        cdef records.ObjectRecord record\n        record.address = address\n        record.is_created = is_created\n        record.native_frame_id = native_frame_id\n        return self._writer.get().writeThreadSpecificRecord(tid, record)\n\n    def write_trailer(self) -> bool:\n        \"\"\"Write the trailer to the file.\"\"\"\n        return self._writer.get().writeTrailer()\n"
  },
  {
    "path": "src/memray/_memray_test_utils.pyx",
    "content": "\"\"\"Utilities used only by memray's test suite.\n\nIf you make changes to this file that move functions around, you will need to\nchange line numbers in test files as well.\n\"\"\"\nimport sys\n\nfrom posix.mman cimport MAP_ANONYMOUS\nfrom posix.mman cimport MAP_FAILED\nfrom posix.mman cimport MAP_SHARED\nfrom posix.mman cimport PROT_WRITE\nfrom posix.mman cimport mmap\nfrom posix.mman cimport munmap\nfrom posix.unistd cimport read\nfrom posix.unistd cimport write\n\nfrom _memray.alloc cimport PyMem_Calloc\nfrom _memray.alloc cimport PyMem_Free\nfrom _memray.alloc cimport PyMem_Malloc\nfrom _memray.alloc cimport PyMem_RawCalloc\nfrom _memray.alloc cimport PyMem_RawFree\nfrom _memray.alloc cimport PyMem_RawMalloc\nfrom _memray.alloc cimport PyMem_RawRealloc\nfrom _memray.alloc cimport PyMem_Realloc\nfrom _memray.alloc cimport PyObject_Calloc\nfrom _memray.alloc cimport PyObject_Free\nfrom _memray.alloc cimport PyObject_Malloc\nfrom _memray.alloc cimport PyObject_Realloc\nfrom _memray.alloc cimport aligned_alloc\nfrom _memray.alloc cimport calloc\nfrom _memray.alloc cimport free\nfrom _memray.alloc cimport malloc\nfrom _memray.alloc cimport memalign\nfrom _memray.alloc cimport posix_memalign\nfrom _memray.alloc cimport pvalloc\nfrom _memray.alloc cimport realloc\nfrom _memray.alloc cimport valloc\nfrom _memray.pthread cimport pthread_create\nfrom _memray.pthread cimport pthread_join\nfrom _memray.pthread cimport pthread_t\nfrom cpython.pylifecycle cimport Py_FinalizeEx\nfrom libc.errno cimport errno\nfrom libc.stdint cimport uintptr_t\nfrom libc.stdlib cimport exit as _exit\nfrom libcpp.vector cimport vector\n\nfrom ._destination import Destination\n\n\ncdef extern from *:\n    \"\"\"\n    #ifdef __linux__\n    # include <sys/prctl.h>\n    inline int set_thread_name_impl(const char* new_name)\n    {\n        return prctl(PR_SET_NAME, new_name, NULL, NULL, NULL);\n    }\n    #else\n    # include <errno.h>\n    inline int set_thread_name_impl(const char* new_name)\n    {\n        errno = ENOTSUP;\n        return -1;\n    }\n    #endif\n    \"\"\"\n    int set_thread_name_impl(const char* new_name)\n\n\ndef set_thread_name(new_name):\n    return set_thread_name_impl(new_name)\n\n\ncdef class MemoryAllocator:\n    cdef void* ptr\n\n    def __cinit__(self):\n        self.ptr = NULL\n\n    def free(self):\n        if self.ptr == NULL:\n            raise RuntimeError(\"Pointer cannot be NULL\")\n        free(self.ptr)\n        self.ptr = NULL\n\n    def malloc(self, size_t size):\n        self.ptr = malloc(size)\n        return self.ptr != NULL\n\n    def calloc(self, size_t size):\n        self.ptr = calloc(1, size)\n        return self.ptr != NULL\n\n    def realloc(self, size_t size):\n        self.ptr = malloc(1)\n        self.ptr = realloc(self.ptr, size)\n        return self.ptr != NULL\n\n    def posix_memalign(self, size_t size):\n        rc = posix_memalign(&self.ptr, sizeof(void*), size)\n        return rc == 0 and self.ptr != NULL\n\n    def aligned_alloc(self, size_t size):\n        self.ptr = aligned_alloc(sizeof(void*), size)\n        return self.ptr != NULL\n\n    def memalign(self, size_t size):\n        self.ptr = memalign(sizeof(void*), size)\n        return self.ptr != NULL\n\n    def valloc(self, size_t size):\n        self.ptr = valloc(size)\n        return self.ptr != NULL\n\n    def pvalloc(self, size_t size):\n        self.ptr = pvalloc(size)\n        return self.ptr != NULL\n\n    def run_in_pthread(self, callback):\n        cdef pthread_t thread\n        cdef int ret = pthread_create(&thread, NULL, &_pthread_worker, <void*>callback)\n        if ret != 0:\n            raise RuntimeError(\"Failed to create thread\")\n        with nogil:\n            pthread_join(thread, NULL)\n\n\ncpdef enum PymallocDomain:\n    PYMALLOC_RAW = 1\n    PYMALLOC_MEM = 2\n    PYMALLOC_OBJECT = 3\n\n\ncdef class PymallocMemoryAllocator:\n    cdef void* ptr\n    cdef PymallocDomain domain\n\n    def __cinit__(self, PymallocDomain domain):\n        self.ptr = NULL\n        self.domain = domain\n\n    def free(self):\n        if self.ptr == NULL:\n            raise RuntimeError(\"Pointer cannot be NULL\")\n        if self.domain == PYMALLOC_RAW:\n            PyMem_RawFree(self.ptr)\n        elif self.domain == PYMALLOC_MEM:\n            PyMem_Free(self.ptr)\n        elif self.domain == PYMALLOC_OBJECT:\n            PyObject_Free(self.ptr)\n        else:\n            raise RuntimeError(\"Invlid pymalloc domain\")\n        self.ptr = NULL\n\n    def malloc(self, size_t size):\n        if self.domain == PYMALLOC_RAW:\n            self.ptr = PyMem_RawMalloc(size)\n        elif self.domain == PYMALLOC_MEM:\n            self.ptr = PyMem_Malloc(size)\n        elif self.domain == PYMALLOC_OBJECT:\n            self.ptr = PyObject_Malloc(size)\n        else:\n            raise RuntimeError(\"Invlid pymalloc domain\")\n\n        return self.ptr != NULL\n\n    def calloc(self, size_t size):\n        if self.domain == PYMALLOC_RAW:\n            self.ptr = PyMem_RawCalloc(1, size)\n        elif self.domain == PYMALLOC_MEM:\n            self.ptr = PyMem_Calloc(1, size)\n        elif self.domain == PYMALLOC_OBJECT:\n            self.ptr = PyObject_Calloc(1, size)\n        else:\n            raise RuntimeError(\"Invlid pymalloc domain\")\n\n        return self.ptr != NULL\n\n    def realloc(self, size_t size):\n        if self.domain == PYMALLOC_RAW:\n            self.ptr = PyMem_RawRealloc(self.ptr, size)\n        elif self.domain == PYMALLOC_MEM:\n            self.ptr = PyMem_Realloc(self.ptr, size)\n        elif self.domain == PYMALLOC_OBJECT:\n            self.ptr = PyObject_Realloc(self.ptr, size)\n        else:\n            raise RuntimeError(\"Invlid pymalloc domain\")\n\n        return self.ptr != NULL\n\ncdef do_not_optimize_ptr(void* ptr):\n    return ptr == <void*>(1)\n\ndef _cython_nested_allocation(allocator_fn, size):\n    allocator_fn(size)\n    cdef void* p = valloc(size);\n    do_not_optimize_ptr(p)\n    free(p)\n\ncdef class MmapAllocator:\n    cdef uintptr_t _address\n\n    def __cinit__(self, size, address=0):\n        cdef uintptr_t start_address = address\n\n        self._address = <uintptr_t>mmap(<void *>start_address, size, PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0)\n        if <void *>self._address == MAP_FAILED:\n            raise MemoryError\n\n    @property\n    def address(self):\n        return self._address\n\n    def munmap(self, length, offset=0):\n        cdef uintptr_t addr = self._address + <uintptr_t> offset\n        cdef int ret = munmap(<void *>addr, length)\n        if ret != 0:\n            raise MemoryError(f\"munmap rcode: {ret} errno: {errno}\")\n\ncdef void* _pthread_worker(void* arg) noexcept with gil:\n    (<object> arg)()\n\ndef _cython_allocate_in_two_places(size_t size):\n    cdef void* a = allocation_place_a(size)\n    do_not_optimize_ptr(a)\n    cdef void* b = allocation_place_b(size)\n    do_not_optimize_ptr(b)\n    free(a)\n    free(b)\n\ncdef void* allocation_place_a(size_t size):\n    return valloc(size)\n\ncdef void* allocation_place_b(size_t size):\n    return valloc(size)\n\ndef function_caller(func):\n    func()\n\ndef allocate_without_gil_held(int wake_up_main_fd, int wake_up_thread_fd):\n    cdef char buf = 0\n    cdef int write_rc = 0\n    cdef int read_rc = 0\n    cdef void* p = NULL\n    with nogil:\n        while write_rc != 1:\n            write_rc = write(wake_up_main_fd, &buf, 1)\n        while read_rc != 1:\n            read_rc = read(wake_up_thread_fd, &buf, 1)\n        p = valloc(1234)\n    do_not_optimize_ptr(p)\n    free(p)\n    p = valloc(4321)\n    do_not_optimize_ptr(p)\n    free(p)\n\ndef allocate_cpp_vector(size_t size):\n    cdef vector[int] v;\n    cdef size_t nelems = <size_t>(size / sizeof(int))\n    v.reserve(nelems)\n    return v.size()\n\n\ndef fill_cpp_vector(size_t size):\n    cdef vector[int] v\n    cdef size_t nelems = <size_t>(size / sizeof(int))\n    for i in range(nelems):\n        v.push_back(i)\n    return v.size()\n\ndef exit(bint py_finalize=False):\n    if py_finalize:\n        Py_FinalizeEx()\n        _exit(0)\n    else:\n        with nogil:\n            _exit(0)\n\n\ncdef class PrimeCaches:\n    cdef object old_profile\n    def __enter__(self):\n        self.old_profile = sys.getprofile()\n        sys.setprofile(lambda *args: None)\n        return self\n    def __exit__(self, *args):\n        sys.setprofile(self.old_profile)\n"
  },
  {
    "path": "src/memray/_metadata.py",
    "content": "from __future__ import annotations\n\nimport typing\nfrom dataclasses import dataclass\nfrom datetime import datetime\n\nif typing.TYPE_CHECKING:\n    from ._memray import FileFormat\n\n\n@dataclass\nclass Metadata:\n    start_time: datetime\n    end_time: datetime\n    total_allocations: int\n    total_frames: int\n    peak_memory: int\n    command_line: str\n    pid: int\n    main_thread_id: int\n    python_allocator: str\n    has_native_traces: bool\n    trace_python_allocators: bool\n    file_format: FileFormat\n"
  },
  {
    "path": "src/memray/_stats.py",
    "content": "from dataclasses import dataclass\n\nfrom ._metadata import Metadata\n\n\n@dataclass\nclass Stats:\n    metadata: Metadata\n    total_num_allocations: int\n    total_memory_allocated: int\n    peak_memory_allocated: int\n    allocation_count_by_size: dict\n    allocation_count_by_allocator: dict\n    top_locations_by_size: list\n    top_locations_by_count: list\n"
  },
  {
    "path": "src/memray/_stats.pyi",
    "content": "from dataclasses import dataclass\n\nfrom ._memray import PythonStackElement\nfrom ._metadata import Metadata\n\n@dataclass\nclass Stats:\n    metadata: Metadata\n    total_num_allocations: int\n    total_memory_allocated: int\n    peak_memory_allocated: int\n    allocation_count_by_size: dict[int, int]\n    allocation_count_by_allocator: dict[str, int]\n    top_locations_by_size: list[tuple[PythonStackElement, int]]\n    top_locations_by_count: list[tuple[PythonStackElement, int]]\n"
  },
  {
    "path": "src/memray/_test.py",
    "content": "from typing import Callable\n\nfrom ._test_utils import MemoryAllocator as _MemoryAllocator\nfrom ._test_utils import MmapAllocator\nfrom ._test_utils import PrimeCaches\nfrom ._test_utils import PymallocDomain\nfrom ._test_utils import PymallocMemoryAllocator\nfrom ._test_utils import _cython_allocate_in_two_places\nfrom ._test_utils import _cython_nested_allocation\nfrom ._test_utils import allocate_cpp_vector\nfrom ._test_utils import allocate_without_gil_held\nfrom ._test_utils import exit\nfrom ._test_utils import fill_cpp_vector\nfrom ._test_utils import function_caller\nfrom ._test_utils import set_thread_name\n\n\nclass MemoryAllocator:\n    def __init__(self) -> None:\n        self.allocator = _MemoryAllocator()\n\n    def free(self) -> None:\n        return self.allocator.free()\n\n    def malloc(self, size: int) -> bool:\n        return self.allocator.malloc(size)\n\n    def calloc(self, size: int) -> bool:\n        return self.allocator.calloc(size)\n\n    def realloc(self, size: int) -> bool:\n        return self.allocator.realloc(size)\n\n    def posix_memalign(self, size: int) -> bool:\n        return self.allocator.posix_memalign(size)\n\n    def aligned_alloc(self, size: int) -> bool:\n        return self.allocator.aligned_alloc(size)\n\n    def memalign(self, size: int) -> bool:\n        return self.allocator.memalign(size)\n\n    def valloc(self, size: int) -> bool:\n        return self.allocator.valloc(size)\n\n    def pvalloc(self, size: int) -> bool:\n        return self.allocator.pvalloc(size)\n\n    def run_in_pthread(self, callback: Callable[[], None]) -> None:\n        return self.allocator.run_in_pthread(callback)\n\n\n__all__ = [\n    \"allocate_cpp_vector\",\n    \"MemoryAllocator\",\n    \"MmapAllocator\",\n    \"PymallocDomain\",\n    \"PymallocMemoryAllocator\",\n    \"_cython_allocate_in_two_places\",\n    \"_cython_nested_allocation\",\n    \"allocate_without_gil_held\",\n    \"function_caller\",\n    \"set_thread_name\",\n    \"fill_cpp_vector\",\n    \"exit\",\n    \"PrimeCaches\",\n]\n"
  },
  {
    "path": "src/memray/_test_utils.pyi",
    "content": "from typing import Callable\n\nfrom ._memray import PymallocDomain as PymallocDomain\n\nclass MemoryAllocator:\n    def __init__(self) -> None: ...\n    def free(self) -> None: ...\n    def malloc(self, size: int) -> bool: ...\n    def calloc(self, size: int) -> bool: ...\n    def realloc(self, size: int) -> bool: ...\n    def posix_memalign(self, size: int) -> bool: ...\n    def aligned_alloc(self, size: int) -> bool: ...\n    def memalign(self, size: int) -> bool: ...\n    def valloc(self, size: int) -> bool: ...\n    def pvalloc(self, size: int) -> bool: ...\n    def run_in_pthread(self, callback: Callable[[], None]) -> None: ...\n\nclass PymallocMemoryAllocator:\n    def __init__(self, domain: PymallocDomain) -> None: ...\n    def free(self) -> None: ...\n    def malloc(self, size: int) -> None: ...\n    def calloc(self, size: int) -> None: ...\n    def realloc(self, size: int) -> None: ...\n\nclass MmapAllocator:\n    def __init__(self, size: int, address: int = 0) -> None: ...\n    @property\n    def address(self) -> int: ...\n    def munmap(self, length: int, offset: int = 0) -> None: ...\n\ndef _cython_nested_allocation(\n    allocator_fn: Callable[[int], None], size: int\n) -> None: ...\ndef _cython_allocate_in_two_places(size: int) -> None: ...\ndef set_thread_name(name: str) -> int: ...\ndef function_caller(func: Callable[[], None]) -> None: ...\ndef allocate_without_gil_held(wake_up_main_fd: int, wake_up_thread_fd: int) -> None: ...\ndef allocate_cpp_vector(size: int) -> int: ...\ndef fill_cpp_vector(size: int) -> int: ...\ndef exit(py_finalize: bool = False) -> None: ...\n\nclass PrimeCaches:\n    def __init__(self, size: int) -> None: ...\n    def __enter__(self) -> None: ...\n    def __exit__(self, *args: object) -> None: ...\n"
  },
  {
    "path": "src/memray/_thread_name_interceptor.py",
    "content": "import threading\nfrom typing import Callable\n\n\nclass ThreadNameInterceptor:\n    \"\"\"Record the name of each threading.Thread for Memray's reports.\n\n    The name can be set either before or after the thread is started, and from\n    either the same thread or a different thread. Whenever an assignment to\n    either `Thread._name` or `Thread._ident` is performed and the other has\n    already been set, we call a callback with the thread's ident and name.\n    \"\"\"\n\n    def __init__(self, attr: str, callback: Callable[[int, str], None]) -> None:\n        self._attr = attr\n        self._callback = callback\n\n    def __set__(self, instance: threading.Thread, value: object) -> None:\n        instance.__dict__[self._attr] = value\n        ident = instance.__dict__.get(\"_ident\")\n        name = instance.__dict__.get(\"_name\")\n        if ident is not None and name is not None:\n            self._callback(ident, name)\n"
  },
  {
    "path": "src/memray/_version.py",
    "content": "__version__ = \"1.19.2\"\n"
  },
  {
    "path": "src/memray/commands/__init__.py",
    "content": "import argparse\nimport logging\nimport sys\nimport textwrap\nfrom typing import List\nfrom typing import Optional\n\nfrom memray._version import __version__\n\ntry:\n    from typing import Protocol\nexcept ImportError:\n    from typing_extensions import Protocol\n\nfrom memray._errors import MemrayCommandError\nfrom memray._errors import MemrayError\nfrom memray._memray import set_log_level\n\nfrom . import attach\nfrom . import flamegraph\nfrom . import live\nfrom . import parse\nfrom . import run\nfrom . import stats\nfrom . import summary\nfrom . import table\nfrom . import transform\nfrom . import tree\n\n_EPILOG = textwrap.dedent(\n    \"\"\"\\\n    Please submit feedback, ideas, and bug reports by filing a new issue at\n    https://github.com/bloomberg/memray/issues\n    \"\"\"\n)\n\n_DESCRIPTION = textwrap.dedent(\n    \"\"\"\\\n    Memory profiler for Python applications\n\n    Run `memray run` to generate a memory profile report, then use a reporter command\n    such as `memray flamegraph` or `memray table` to convert the results into HTML.\n\n    Example:\n\n        $ python3 -m memray run -o output.bin my_script.py\n        $ python3 -m memray flamegraph output.bin\n    \"\"\"\n)\n\n\nclass Command(Protocol):\n    def prepare_parser(self, parser: argparse.ArgumentParser) -> None:\n        ...\n\n    def run(self, args: argparse.Namespace, parser: argparse.ArgumentParser) -> None:\n        ...\n\n\n_COMMANDS: List[Command] = [\n    run.RunCommand(),\n    flamegraph.FlamegraphCommand(),\n    table.TableCommand(),\n    live.LiveCommand(),\n    tree.TreeCommand(),\n    parse.ParseCommand(),\n    summary.SummaryCommand(),\n    stats.StatsCommand(),\n    transform.TransformCommand(),\n    attach.AttachCommand(),\n    attach.DetachCommand(),\n]\n\n\ndef get_argument_parser() -> argparse.ArgumentParser:\n    parser = argparse.ArgumentParser(\n        description=_DESCRIPTION,\n        prog=\"memray\",\n        formatter_class=argparse.RawTextHelpFormatter,\n        epilog=_EPILOG,\n    )\n    parser.add_argument(\n        \"-v\",\n        \"--verbose\",\n        action=\"count\",\n        default=0,\n        help=\"Increase verbosity. Option is additive and can be specified up to 3 times\",\n    )\n    parser.add_argument(\n        \"-V\",\n        \"--version\",\n        action=\"version\",\n        version=__version__,\n        help=\"Displays the current version of Memray\",\n    )\n\n    subparsers = parser.add_subparsers(\n        help=\"Mode of operation\",\n        dest=\"command\",\n        required=True,\n    )\n\n    for command in _COMMANDS:\n        # Extract the CLI command name from the classes' names\n        assert command.__class__.__name__.endswith(\"Command\")\n        name = command.__class__.__name__[: -len(\"Command\")].lower()\n\n        # Add the subcommand\n        command_parser = subparsers.add_parser(\n            name, help=command.__doc__, description=command.__doc__, epilog=_EPILOG\n        )\n        command_parser.set_defaults(entrypoint=command.run)\n        command.prepare_parser(command_parser)\n\n    return parser\n\n\ndef determine_logging_level_from_verbosity(\n    verbose_level: int,\n) -> int:  # pragma: no cover\n    if verbose_level == 0:\n        return logging.WARNING\n    elif verbose_level == 1:\n        return logging.INFO\n    else:\n        return logging.DEBUG\n\n\ndef main(args: Optional[List[str]] = None) -> int:\n    if args is None:\n        args = sys.argv[1:]\n\n    parser = get_argument_parser()\n    arg_values = parser.parse_args(args=args)\n    set_log_level(determine_logging_level_from_verbosity(arg_values.verbose))\n\n    try:\n        arg_values.entrypoint(arg_values, parser)\n    except MemrayCommandError as e:\n        print(e, file=sys.stderr)\n        return e.exit_code\n    except MemrayError as e:\n        print(e, file=sys.stderr)\n        return 1\n    else:\n        return 0\n"
  },
  {
    "path": "src/memray/commands/_attach.gdb",
    "content": "p \"MEMRAY: Attached to process.\"\n\nset unwindonsignal on\nsharedlibrary libc\nsharedlibrary libdl\nsharedlibrary musl\nsharedlibrary libpython\ninfo sharedlibrary\n\np \"MEMRAY: Checking if process is Python 3.7+.\"\n\np PyMem_Malloc\np PyMem_Calloc\np PyMem_Realloc\np PyMem_Free\n\np \"MEMRAY: Process is Python 3.7+.\"\nset scheduler-locking on\ncall (int)Py_AddPendingCall(&PyCallable_Check, (void*)0)\n\n# When updating this list, also update the \"commands\" call below,\n# and the breakpoints hardcoded for lldb in attach.py\nb malloc\nb calloc\nb realloc\nb free\nb PyMem_Malloc\nb PyMem_Calloc\nb PyMem_Realloc\nb PyMem_Free\nb PyErr_CheckSignals\nb PyCallable_Check\n# Apply commands to all 10 breakpoints above\ncommands 1-10\n    bt\n    disable breakpoints\n    delete breakpoints\n    call (void*)dlopen($libpath, $rtld_now)\n    p (char*)dlerror()\n    eval \"sharedlibrary %s\", $libpath\n    p (int)memray_spawn_client($port) ? \"FAILURE\" : \"SUCCESS\"\nend\nset scheduler-locking off\ncontinue\n"
  },
  {
    "path": "src/memray/commands/_attach.lldb",
    "content": "p \"MEMRAY: Attached to process.\"\n\np \"MEMRAY: Checking if process is Python 3.7+.\"\n\np ((void*(*)(size_t))PyMem_Malloc)\np ((void*(*)(size_t, size_t))PyMem_Calloc)\np ((void*(*)(void *, size_t))PyMem_Realloc)\np ((void(*)(void*))PyMem_Free)\n\np \"MEMRAY: Process is Python 3.7+.\"\n\n# When adding new breakpoints, also update _attach.gdb\nbreakpoint set -b malloc -b calloc -b realloc -b free -b PyMem_Malloc -b PyMem_Calloc -b PyMem_Realloc -b PyMem_Free\n\n# Set commands to execute when breakpoint is reached\nbreakpoint command add -e true\nbreakpoint disable\nexpr auto $dlsym = (void* (*)(void*, const char*))&::dlsym\nexpr auto $dlopen = $dlsym($rtld_default, \"dlopen\")\nexpr auto $dlerror = $dlsym($rtld_default, \"dlerror\")\nexpr auto $dll = ((void*(*)(const char*, int))$dlopen)($libpath, $rtld_now)\np ((char*(*)(void))$dlerror)()\nexpr auto $spawn = $dlsym($dll, \"memray_spawn_client\")\np ((int(*)(int))$spawn)($port)?\"FAILURE\":\"SUCCESS\"\nDONE\n\ncontinue\n"
  },
  {
    "path": "src/memray/commands/attach.py",
    "content": "from __future__ import annotations\n\nimport argparse\nimport contextlib\nimport os\nimport pathlib\nimport platform\nimport shlex\nimport shutil\nimport signal\nimport socket\nimport subprocess\nimport sys\nimport tempfile\nimport textwrap\nimport threading\n\nimport memray\nfrom memray._errors import MemrayCommandError\n\nfrom .live import LiveCommand\nfrom .run import _get_free_port\n\ntry:\n    from typing import Literal\nexcept ImportError:\n    from typing_extensions import Literal\n\nTrackingMode = Literal[\"ACTIVATE\", \"DEACTIVATE\", \"FOR_DURATION\"]\n\n\nGDB_SCRIPT = pathlib.Path(__file__).parent / \"_attach.gdb\"\nLLDB_SCRIPT = pathlib.Path(__file__).parent / \"_attach.lldb\"\nRTLD_DEFAULT = memray._memray.RTLD_DEFAULT\nRTLD_NOW = memray._memray.RTLD_NOW\nPAYLOAD = \"\"\"\nimport atexit\nimport time\nimport threading\nimport resource\nimport sys\nfrom contextlib import suppress\n\nimport memray\n\n\nclass BareExceptionMessage(Exception):\n    def __repr__(self):\n        return self.args[0]\n\n\nclass RepeatingTimer(threading.Thread):\n    def __init__(self, interval, function):\n        self._interval = interval\n        self._function = function\n        self._canceled = threading.Event()\n        super().__init__()\n\n    def cancel(self):\n        self._canceled.set()\n\n    def run(self):\n        while not self._canceled.wait(self._interval):\n            if self._function():\n                break\n\n\ndef deactivate_last_tracker():\n    tracker = getattr(memray, \"_last_tracker\", None)\n    if not tracker:\n        return\n\n    memray._last_tracker = None\n    try:\n        tracker.__exit__(None, None, None)\n    finally:\n        # Clean up resources associated with the Tracker ASAP,\n        # even if an exception was raised.\n        del tracker\n\n    # Stop any waiting threads. This attribute may be unset if an old Memray\n    # version attached 1st, setting last_tracker but not _attach_event_threads.\n    # It could also be unset if we're racing another deactivate call.\n    for thread in memray.__dict__.pop(\"_attach_event_threads\", []):\n        thread.cancel()\n\n\ndef activate_tracker():\n    deactivate_last_tracker()\n    tracker = {tracker_call}\n    try:\n        tracker.__enter__()\n        memray._last_tracker = tracker\n    finally:\n        # Clean up resources associated with the Tracker ASAP,\n        # even if an exception was raised.\n        del tracker\n    memray._attach_event_threads = []\n\n\ndef track_for_duration(duration=5):\n    activate_tracker()\n\n    def deactivate_because_timer_elapsed():\n        print(\n            \"memray: Deactivating tracking:\",\n            duration,\n            \"seconds have elapsed\",\n            file=sys.stderr,\n        )\n        deactivate_last_tracker()\n\n    thread = threading.Timer(duration, deactivate_because_timer_elapsed)\n    thread.daemon = False\n    thread.start()\n    memray._attach_event_threads.append(thread)\n\n\nif not hasattr(memray, \"_last_tracker\"):\n    # This only needs to be registered the first time we attach.\n    atexit.register(deactivate_last_tracker)\n\nif {mode!r} == \"ACTIVATE\":\n    activate_tracker()\nelif {mode!r} == \"DEACTIVATE\":\n    if not getattr(memray, \"_last_tracker\", None):\n        raise BareExceptionMessage(\"no previous `memray attach` call detected\")\n    deactivate_last_tracker()\nelif {mode!r} == \"FOR_DURATION\":\n    track_for_duration({duration})\n\"\"\"\n\n\ndef debugger_inject(debugger: str, pid: int, port: int, verbose: bool) -> str | None:\n    \"\"\"Execute a file in a running Python process using a debugger.\"\"\"\n    injecter = pathlib.Path(memray.__file__).parent / \"_inject.abi3.so\"\n    assert injecter.exists()\n\n    gdb_cmd = [\n        \"gdb\",\n        \"-batch\",\n        \"-p\",\n        str(pid),\n        \"-nx\",\n        \"-nw\",\n        \"-iex=set auto-solib-add off\",\n        f\"-ex=set $rtld_now={RTLD_NOW}\",\n        f'-ex=set $libpath=\"{injecter}\"',\n        f\"-ex=set $port={port}\",\n        f\"-x={GDB_SCRIPT}\",\n    ]\n\n    lldb_cmd = [\n        \"lldb\",\n        \"--batch\",\n        \"-p\",\n        str(pid),\n        \"--no-lldbinit\",\n        \"-o\",\n        f'expr char $libpath[]=\"{injecter}\"',\n        \"-o\",\n        f\"expr int $port={port}\",\n        \"-o\",\n        f\"expr void* $rtld_default=(void*){RTLD_DEFAULT}\",\n        \"-o\",\n        f\"expr int $rtld_now={RTLD_NOW}\",\n        \"--source\",\n        f\"{LLDB_SCRIPT}\",\n    ]\n\n    cmd = gdb_cmd if debugger == \"gdb\" else lldb_cmd\n    if verbose:\n        if sys.version_info >= (3, 8):\n            print(\"Debugger command line:\", shlex.join(cmd))\n        else:\n            print(\"Debugger command line:\", cmd)\n\n    try:\n        output = subprocess.check_output(cmd, text=True, stderr=subprocess.STDOUT)\n        returncode = 0\n    except subprocess.CalledProcessError as exc:\n        output = exc.output\n        returncode = exc.returncode\n\n    if cmd is lldb_cmd:\n        # A bug in lldb sometimes means processes stay stopped after it exits.\n        # Send a signal to wake the process up. Ignore any errors: the process\n        # may have died, or may have never existed, or may be owned by another\n        # user, etc. Processes that aren't stopped will ignore this signal, so\n        # this should be harmless, though it is a huge hack.\n        with contextlib.suppress(OSError):\n            os.kill(pid, signal.SIGCONT)\n\n    if verbose:\n        print(f\"debugger return code: {returncode}\")\n        print(f\"debugger output:\\n{output}\")\n\n    command_output_lines = (\n        line for line in output.splitlines() if not line.startswith(f\"({debugger})\")\n    )\n    if returncode == 0 and any(' \"SUCCESS\"' in line for line in command_output_lines):\n        return None\n\n    # An error occurred. Give the best message we can. This is hacky; we don't\n    # have a good option besides parsing output from the debugger session.\n    if \"--help\" in output:\n        return (\n            \"The debugger failed to parse our command line arguments.\\n\"\n            \"Run with --verbose to see the error message.\"\n        )\n\n    if \"error: attach failed: \" in output or \"ptrace: \" in output:\n        # We failed to attach to the given pid. A few likely reasons...\n        errmsg = \"Failed to attach a debugger to the process.\\n\"\n        try:\n            os.kill(pid, 0)\n        except ProcessLookupError:\n            return errmsg + \"The given process ID does not exist.\"\n        except PermissionError:\n            return errmsg + \"The given process ID is owned by a different user.\"\n\n        return errmsg + \"You most likely do not have permission to trace the process.\"\n\n    if \"MEMRAY: Attached to process.\" not in output:\n        return (\n            f\"Failed to execute our {debugger} script.\\n\"\n            \"Run with --verbose to debug the failure.\"\n        )\n\n    if \"MEMRAY: Checking if process is Python 3.7+.\" in output:\n        if \"MEMRAY: Process is Python 3.7+.\" not in output:\n            return \"The process does not seem to be running Python 3.7 or newer.\"\n\n    return \"An unexpected error occurred. Run with --verbose to debug the failure.\"\n\n\ndef remote_exec_inject(pid: int, port: int, verbose: bool, tmpdir: str) -> str | None:\n    \"\"\"Execute a file in a running Python process using sys.remote_exec.\"\"\"\n    script = textwrap.dedent(\n        f\"\"\"\n        from contextlib import closing\n        from queue import Queue\n        from socket import create_connection\n        from threading import Thread\n\n        exc = None\n\n        def thread_body():\n            try:\n                exec(sockfile.read(), globals())\n            except Exception as exc:\n                globals()[\"exc\"] = exc\n\n        with closing(create_connection((None, {port})).makefile(\"rw\")) as sockfile:\n            thread = Thread(target=thread_body)\n            thread.start()\n            thread.join()\n            if exc is not None:\n                sockfile.write(repr(exc))\n        \"\"\"\n    )\n    script_path = pathlib.Path(tmpdir) / \"attach.py\"\n    script_path.write_text(script, encoding=\"utf-8\")\n    try:\n        getattr(sys, \"remote_exec\")(pid, script_path)\n    except Exception as exc:\n        return f\"Failed to execute script in remote process: {exc!r}\"\n    return None\n\n\ndef inject(method: str, pid: int, port: int, verbose: bool, tmpdir: str) -> str | None:\n    \"\"\"Execute a file in a running Python process.\"\"\"\n    if method == \"sys.remote_exec\":\n        return remote_exec_inject(pid, port, verbose=verbose, tmpdir=tmpdir)\n    return debugger_inject(method, pid, port, verbose=verbose)\n\n\ndef _sys_remote_exec_available(verbose: bool) -> bool:\n    if not hasattr(sys, \"remote_exec\"):\n        if verbose:\n            print(\"sys.remote_exec is not available in this Python version\")\n        return False\n    return True\n\n\ndef _gdb_available(verbose: bool) -> bool:\n    if not shutil.which(\"gdb\"):\n        if verbose:\n            print(\"No gdb executable found\")\n        return False\n    return True\n\n\ndef _lldb_available(verbose: int) -> bool:\n    # We need a version of lldb that supports `--batch`. This should be lldb\n    # 3.5.2 or newer, but the version string format doesn't appear consistent\n    # between macOS and Linux, so it's safer to just check the help output to\n    # make sure that option is documented.\n    try:\n        help_str = subprocess.check_output(\n            [\"lldb\", \"--help\"],\n            text=True,\n            stderr=subprocess.STDOUT,\n        )\n    except FileNotFoundError:\n        if verbose:\n            print(\"No lldb executable found\")\n        return False\n    except subprocess.CalledProcessError as exc:\n        if verbose:\n            print(f\"`lldb --version` failed: {exc.output}\")\n        return False\n\n    if \"--batch\" not in help_str:\n        if verbose:\n            print(\"lldb does not support --batch, which we require\")\n        return False\n\n    return True\n\n\ndef debugger_available(debugger: str, verbose: bool = False) -> bool:\n    return {\n        \"sys.remote_exec\": _sys_remote_exec_available,\n        \"gdb\": _gdb_available,\n        \"lldb\": _lldb_available,\n    }[debugger](verbose=verbose)\n\n\ndef recvall(sock: socket.socket) -> str:\n    return b\"\".join(iter(lambda: sock.recv(4096), b\"\")).decode(\"utf-8\")\n\n\nclass ErrorReaderThread(threading.Thread):\n    def __init__(self, sock: socket.socket) -> None:\n        self._sock = sock\n        super().__init__()\n\n    def run(self) -> None:\n        try:\n            err = recvall(self._sock)\n        except OSError as e:\n            err = f\"Unexpected exception: {e!r}\"\n\n        if not err:\n            self.error = None\n            return\n\n        self.error = err\n        os.kill(os.getpid(), signal.SIGINT)\n\n\nclass _DebuggerCommand:\n    def prepare_parser(self, parser: argparse.ArgumentParser) -> None:\n        parser.add_argument(\n            \"--method\",\n            help=\"Method to use for injecting commands into the remote process\",\n            type=str,\n            default=\"auto\",\n            choices=[\"auto\", \"sys.remote_exec\", \"gdb\", \"lldb\"],\n        )\n\n        parser.add_argument(\n            \"-v\",\n            \"--verbose\",\n            help=\"Print verbose debugging information.\",\n            action=\"store_true\",\n        )\n\n        parser.add_argument(\n            \"pid\",\n            help=\"Process id to affect\",\n            type=int,\n        )\n\n    def resolve_debugger(self, method: str, *, verbose: bool = False) -> str:\n        if method == \"auto\":\n            # Prefer gdb on Linux but lldb on macOS\n            if platform.system() == \"Linux\":\n                debuggers = (\"sys.remote_exec\", \"gdb\", \"lldb\")\n            else:\n                debuggers = (\"sys.remote_exec\", \"lldb\", \"gdb\")\n\n            for debugger in debuggers:\n                if debugger_available(debugger, verbose=verbose):\n                    return debugger\n            raise MemrayCommandError(\n                \"Cannot find a supported lldb or gdb executable\"\n                \" and sys.remote_exec is not available.\",\n                exit_code=1,\n            )\n        elif not debugger_available(method, verbose=verbose):\n            raise MemrayCommandError(\n                \"sys.remote_exec requires Python 3.14 or newer.\"\n                if method == \"sys.remote_exec\"\n                else f\"Cannot find a supported {method} executable.\",\n                exit_code=1,\n            )\n        return method\n\n    def inject_control_channel(\n        self, method: str, pid: int, *, verbose: bool = False\n    ) -> socket.socket:\n        server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n        with contextlib.closing(server), tempfile.TemporaryDirectory() as tmpdir:\n            server.bind((\"localhost\", 0))\n            server.listen(1)\n            sidechannel_port = server.getsockname()[1]\n\n            errmsg = inject(\n                method, pid, sidechannel_port, verbose=verbose, tmpdir=tmpdir\n            )\n            if errmsg:\n                raise MemrayCommandError(errmsg, exit_code=1)\n\n            server.settimeout(10)\n            try:\n                return server.accept()[0]\n            except TimeoutError:\n                raise MemrayCommandError(\n                    f\"Timed out waiting for connection from pid {pid}\",\n                    exit_code=1,\n                )\n\n\nclass AttachCommand(_DebuggerCommand):\n    \"\"\"Begin tracking allocations in an already-started process\"\"\"\n\n    def prepare_parser(self, parser: argparse.ArgumentParser) -> None:\n        parser.add_argument(\n            \"-o\",\n            \"--output\",\n            metavar=\"FILE\",\n            help=(\n                \"Capture allocations into the given file\"\n                \" instead of starting a live tracking session\"\n            ),\n        )\n        parser.add_argument(\n            \"-f\",\n            \"--force\",\n            help=\"If the output file already exists, overwrite it\",\n            action=\"store_true\",\n            default=False,\n        )\n\n        parser.add_argument(\n            \"--aggregate\",\n            help=\"Write aggregated stats to the output file instead of all allocations\",\n            action=\"store_true\",\n            default=False,\n        )\n\n        parser.add_argument(\n            \"--native\",\n            help=\"Track native (C/C++) stack frames as well\",\n            action=\"store_true\",\n            dest=\"native\",\n            default=False,\n        )\n        parser.add_argument(\n            \"--follow-fork\",\n            action=\"store_true\",\n            help=\"Record allocations in child processes forked from the tracked script\",\n            default=False,\n        )\n        parser.add_argument(\n            \"--trace-python-allocators\",\n            action=\"store_true\",\n            help=\"Record allocations made by the pymalloc allocator\",\n            default=False,\n        )\n        compression = parser.add_mutually_exclusive_group()\n        compression.add_argument(\n            \"--compress-on-exit\",\n            help=\"Compress the resulting file using lz4 after tracking completes\",\n            default=True,\n            action=\"store_true\",\n        )\n        compression.add_argument(\n            \"--no-compress\",\n            help=\"Do not compress the resulting file using lz4\",\n            default=False,\n            action=\"store_true\",\n        )\n\n        parser.add_argument(\n            \"--duration\", type=int, help=\"Duration to track for (in seconds)\"\n        )\n\n        super().prepare_parser(parser)\n\n    def run(self, args: argparse.Namespace, parser: argparse.ArgumentParser) -> None:\n        verbose = args.verbose\n        mode: TrackingMode = \"ACTIVATE\"\n        duration = None\n\n        if args.duration:\n            mode = \"FOR_DURATION\"\n            duration = args.duration\n\n        args.method = self.resolve_debugger(args.method, verbose=verbose)\n\n        destination: memray.Destination\n        if args.output:\n            live_port = None\n            destination = memray.FileDestination(\n                path=os.path.abspath(args.output),\n                overwrite=args.force,\n                compress_on_exit=not args.no_compress,\n            )\n        else:\n            live_port = _get_free_port()\n            destination = memray.SocketDestination(server_port=live_port)\n\n        if args.aggregate and not args.output:\n            parser.error(\"Can't use aggregated mode without an output file.\")\n\n        file_format = (\n            \"file_format=memray.FileFormat.AGGREGATED_ALLOCATIONS\"\n            if args.aggregate\n            else \"\"\n        )\n\n        tracker_call = (\n            f\"memray.Tracker(destination=memray.{destination!r},\"\n            f\" native_traces={args.native},\"\n            f\" follow_fork={args.follow_fork},\"\n            f\" trace_python_allocators={args.trace_python_allocators},\"\n            f\"{file_format})\"\n        )\n\n        client = self.inject_control_channel(args.method, args.pid, verbose=verbose)\n        client.sendall(\n            PAYLOAD.format(\n                tracker_call=tracker_call,\n                mode=mode,\n                duration=duration,\n            ).encode(\"utf-8\")\n        )\n        client.shutdown(socket.SHUT_WR)\n\n        if not live_port:\n            err = recvall(client)\n            if err:\n                raise MemrayCommandError(\n                    f\"Failed to start tracking in remote process: {err}\",\n                    exit_code=1,\n                )\n            return\n\n        # If an error prevents the tracked process from binding a server to\n        # live_port, the TUI will hang forever trying to connect. Handle this\n        # by spawning a background thread that watches for an error report over\n        # the side channel and raises a SIGINT to interrupt the TUI if it sees\n        # one. This can race, though: in some cases the TUI will also see an\n        # error (if no header is sent over the socket), and the background\n        # thread may raise a SIGINT that we see only after the live TUI has\n        # already exited. If so we must ignore the extra KeyboardInterrupt.\n        error_reader = ErrorReaderThread(client)\n        error_reader.start()\n        live = LiveCommand()\n\n        with contextlib.suppress(KeyboardInterrupt):\n            try:\n                try:\n                    live.start_live_interface(live_port)\n                finally:\n                    # Note: may get a spurious KeyboardInterrupt!\n                    error_reader.join()\n            except (Exception, KeyboardInterrupt):\n                remote_err = error_reader.error\n                if not remote_err:\n                    raise  # Propagate the exception\n\n                raise MemrayCommandError(\n                    f\"Failed to start tracking in remote process: {remote_err}\",\n                    exit_code=1,\n                ) from None\n\n\nclass DetachCommand(_DebuggerCommand):\n    \"\"\"End the tracking started by a previous ``memray attach`` call\"\"\"\n\n    def run(self, args: argparse.Namespace, parser: argparse.ArgumentParser) -> None:\n        verbose = args.verbose\n        mode: TrackingMode = \"DEACTIVATE\"\n        args.method = self.resolve_debugger(args.method, verbose=verbose)\n        client = self.inject_control_channel(args.method, args.pid, verbose=verbose)\n\n        client.sendall(\n            PAYLOAD.format(\n                tracker_call=None,\n                mode=mode,\n                duration=None,\n            ).encode(\"utf-8\")\n        )\n        client.shutdown(socket.SHUT_WR)\n\n        err = recvall(client)\n        if err:\n            raise MemrayCommandError(\n                f\"Failed to stop tracking in remote process: {err}\",\n                exit_code=1,\n            )\n"
  },
  {
    "path": "src/memray/commands/common.py",
    "content": "import argparse\nimport os\nimport pathlib\nimport sys\nfrom pathlib import Path\nfrom textwrap import dedent\nfrom typing import Iterable\nfrom typing import List\nfrom typing import Optional\nfrom typing import Tuple\n\nif sys.version_info >= (3, 8):\n    from typing import Protocol\nelse:\n    from typing_extensions import Protocol\n\nfrom rich import print as pprint\n\nfrom memray import AllocationRecord\nfrom memray import FileReader\nfrom memray import MemorySnapshot\nfrom memray._errors import MemrayCommandError\nfrom memray._memray import FileFormat\nfrom memray._memray import SymbolicSupport\nfrom memray._memray import TemporalAllocationRecord\nfrom memray._memray import get_symbolic_support\nfrom memray.reporters import BaseReporter\n\n\nclass ReporterFactory(Protocol):\n    def __call__(\n        self,\n        allocations: Iterable[AllocationRecord],\n        *,\n        memory_records: Iterable[MemorySnapshot],\n        native_traces: bool,\n        inverted: bool,\n    ) -> BaseReporter:\n        ...\n\n\nclass TemporalReporterFactory(Protocol):\n    def __call__(\n        self,\n        allocations: Iterable[TemporalAllocationRecord],\n        *,\n        memory_records: Iterable[MemorySnapshot],\n        native_traces: bool,\n        high_water_mark_by_snapshot: Optional[List[int]],\n        inverted: bool,\n    ) -> BaseReporter:\n        ...\n\n\ndef warn_if_not_enough_symbols() -> None:\n    support = get_symbolic_support()\n    if support == SymbolicSupport.NONE:\n        pprint(\n            \":warning: [bold yellow] No symbol information was found for the \"\n            \"Python interpreter [/] :warning:\\n\\n\"\n            \"Without symbolic information reports showing native traces [b]may not \"\n            \"accurately reflect stack traces[/]. Please use an interpreter built with \"\n            \"debug symbols for best results. Check \"\n            \"https://bloomberg.github.io/memray/native_mode.html for more information \"\n            \"regarding how memray resolves symbols.\\n\"\n        )\n    elif support == SymbolicSupport.FUNCTION_NAME_ONLY:\n        pprint(\n            \":warning: [bold yellow] No debug information was found for the \"\n            \"Python interpreter [/] :warning:\\n\\n\"\n            \"Without debug information reports showing native traces [b]may not \"\n            \"include file names and line numbers[/]. Please use an interpreter built with \"\n            \"debug symbols for best results. Check \"\n            \"https://bloomberg.github.io/memray/native_mode.html for more information \"\n            \"regarding how memray resolves symbols.\\n\"\n        )\n    else:\n        return\n\n\ndef warn_if_file_is_not_aggregated_and_is_too_big(\n    reader: FileReader, result_path: Path\n) -> None:\n    FILE_SIZE_LIMIT = 10 * 1000 * 1000\n    if (\n        reader.metadata.file_format == FileFormat.ALL_ALLOCATIONS\n        and result_path.stat().st_size > FILE_SIZE_LIMIT\n    ):\n        pprint(\n            \":warning: [bold yellow] This capture file is large and may take a long\"\n            \" time to process [/] :warning:\\n\\n\"\n            \"Next time, consider using the `--aggregate` option to `memray run` to\"\n            \" reduce the size of the file.\\n\"\n            \"Check https://bloomberg.github.io/memray/run.html#aggregated-capture-files\"\n            \" for more information.\\n\"\n        )\n\n\nclass HighWatermarkCommand:\n    def __init__(\n        self,\n        reporter_factory: ReporterFactory,\n        reporter_name: str,\n        suffix: str = \".html\",\n        temporal_reporter_factory: Optional[TemporalReporterFactory] = None,\n    ) -> None:\n        self.reporter_factory = reporter_factory\n        self.reporter_name = reporter_name\n        self.suffix = suffix\n        self.temporal_reporter_factory = temporal_reporter_factory\n        self.output_file: Optional[Path] = None\n\n    def determine_output_filename(self, results_file: pathlib.Path) -> pathlib.Path:\n        output_name = results_file.with_suffix(self.suffix).name\n        if output_name.startswith(\"memray-\"):\n            output_name = output_name[len(\"memray-\") :]\n\n        return results_file.parent / f\"memray-{self.reporter_name}-{output_name}\"\n\n    def validate_filenames(\n        self, output: Optional[str], results: str, overwrite: bool = False\n    ) -> Tuple[Path, Path]:\n        \"\"\"Ensure that the filenames provided by the user are usable.\"\"\"\n        result_path = Path(results)\n        if not result_path.exists() or not result_path.is_file():\n            raise MemrayCommandError(f\"No such file: {results}\", exit_code=1)\n\n        output_file = Path(\n            output\n            if output is not None\n            else self.determine_output_filename(result_path)\n        )\n        if not overwrite and output_file.exists():\n            raise MemrayCommandError(\n                f\"File already exists, will not overwrite: {output_file}\",\n                exit_code=1,\n            )\n        return result_path, output_file\n\n    def write_report(\n        self,\n        result_path: Path,\n        output_file: Path,\n        show_memory_leaks: bool,\n        temporary_allocation_threshold: int,\n        merge_threads: Optional[bool] = None,\n        inverted: Optional[bool] = None,\n        temporal: bool = False,\n        max_memory_records: Optional[int] = None,\n        no_web: bool = False,\n    ) -> None:\n        try:\n            kwargs = {}\n            if max_memory_records is not None:\n                kwargs[\"max_memory_records\"] = max_memory_records\n            reader = FileReader(os.fspath(result_path), report_progress=True, **kwargs)\n            merge_threads = True if merge_threads is None else merge_threads\n            inverted = False if inverted is None else inverted\n\n            if reader.metadata.has_native_traces:\n                warn_if_not_enough_symbols()\n\n            if not temporal and not temporary_allocation_threshold >= 0:\n                warn_if_file_is_not_aggregated_and_is_too_big(reader, result_path)\n\n            if temporal:\n                assert self.temporal_reporter_factory is not None\n                if show_memory_leaks:\n                    temporal_snapshot = reader.get_temporal_allocation_records(\n                        merge_threads=merge_threads\n                    )\n                    reporter = self.temporal_reporter_factory(\n                        temporal_snapshot,\n                        memory_records=tuple(reader.get_memory_snapshots()),\n                        native_traces=reader.metadata.has_native_traces,\n                        high_water_mark_by_snapshot=None,\n                        inverted=inverted,\n                    )\n                else:\n                    recs, hwms = reader.get_temporal_high_water_mark_allocation_records(\n                        merge_threads=merge_threads\n                    )\n                    reporter = self.temporal_reporter_factory(\n                        recs,\n                        memory_records=tuple(reader.get_memory_snapshots()),\n                        native_traces=reader.metadata.has_native_traces,\n                        high_water_mark_by_snapshot=hwms,\n                        inverted=inverted,\n                    )\n            else:\n                if show_memory_leaks:\n                    snapshot = reader.get_leaked_allocation_records(\n                        merge_threads=merge_threads\n                    )\n                elif temporary_allocation_threshold >= 0:\n                    snapshot = reader.get_temporary_allocation_records(\n                        threshold=temporary_allocation_threshold,\n                        merge_threads=merge_threads,\n                    )\n                else:\n                    snapshot = reader.get_high_watermark_allocation_records(\n                        merge_threads=merge_threads\n                    )\n                reporter = self.reporter_factory(\n                    snapshot,\n                    memory_records=tuple(reader.get_memory_snapshots()),\n                    native_traces=reader.metadata.has_native_traces,\n                    inverted=inverted,\n                )\n        except OSError as e:\n            raise MemrayCommandError(\n                f\"Failed to parse allocation records in {result_path}\\nReason: {e}\",\n                exit_code=1,\n            )\n\n        with open(os.fspath(output_file.expanduser()), \"w\") as f:\n            reporter.render(\n                outfile=f,\n                metadata=reader.metadata,\n                show_memory_leaks=show_memory_leaks,\n                merge_threads=merge_threads,\n                inverted=inverted,\n                no_web=no_web,\n            )\n\n    def prepare_parser(self, parser: argparse.ArgumentParser) -> None:\n        parser.add_argument(\n            \"-o\",\n            \"--output\",\n            help=\"Output file name\",\n            default=None,\n        )\n        parser.add_argument(\n            \"-f\",\n            \"--force\",\n            help=\"If the output file already exists, overwrite it\",\n            action=\"store_true\",\n            default=False,\n        )\n        if self.temporal_reporter_factory:\n            parser.add_argument(\n                \"--temporal\",\n                help=(\n                    \"Generate a dynamic flame graph that can analyze\"\n                    \" allocations in a user-selected time range.\"\n                ),\n                action=\"store_true\",\n                default=False,\n            )\n\n        alloc_type_group = parser.add_mutually_exclusive_group()\n        alloc_type_group.add_argument(\n            \"--leaks\",\n            help=\"Show memory leaks, instead of peak memory usage\",\n            action=\"store_true\",\n            dest=\"show_memory_leaks\",\n            default=False,\n        )\n        alloc_type_group.add_argument(\n            \"--temporary-allocation-threshold\",\n            metavar=\"N\",\n            help=dedent(\n                \"\"\"\n                Report temporary allocations, as opposed to leaked allocations\n                or high watermark allocations.  An allocation is considered\n                temporary if at most N other allocations occur before it is\n                deallocated.  With N=0, an allocation is temporary only if it\n                is immediately deallocated before any other allocation occurs.\n                \"\"\"\n            ),\n            action=\"store\",\n            dest=\"temporary_allocation_threshold\",\n            type=int,\n            default=-1,\n        )\n        alloc_type_group.add_argument(\n            \"--temporary-allocations\",\n            help=\"Equivalent to --temporary-allocation-threshold=1\",\n            action=\"store_const\",\n            dest=\"temporary_allocation_threshold\",\n            const=1,\n        )\n        parser.add_argument(\"results\", help=\"Results of the tracker run\")\n\n    def run(self, args: argparse.Namespace, parser: argparse.ArgumentParser) -> None:\n        temporal = getattr(args, \"temporal\", False)\n        if temporal and args.temporary_allocation_threshold >= 0:\n            parser.error(\"Can't create a temporal flame graph of temporary allocations\")\n\n        result_path, output_file = self.validate_filenames(\n            output=args.output,\n            results=args.results,\n            overwrite=args.force,\n        )\n        self.output_file = output_file\n        kwargs = {}\n        if hasattr(args, \"split_threads\"):\n            kwargs[\"merge_threads\"] = not args.split_threads\n\n        if hasattr(args, \"inverted\"):\n            kwargs[\"inverted\"] = args.inverted\n\n        if hasattr(args, \"max_memory_records\"):\n            kwargs[\"max_memory_records\"] = args.max_memory_records\n\n        if hasattr(args, \"no_web\"):\n            kwargs[\"no_web\"] = args.no_web\n\n        self.write_report(\n            result_path,\n            output_file,\n            args.show_memory_leaks,\n            args.temporary_allocation_threshold,\n            temporal=temporal,\n            **kwargs,\n        )\n\n        print(f\"Wrote {output_file}\")\n"
  },
  {
    "path": "src/memray/commands/flamegraph.py",
    "content": "import argparse\n\nfrom ..reporters.flamegraph import FlameGraphReporter\nfrom .common import HighWatermarkCommand\n\n\nclass FlamegraphCommand(HighWatermarkCommand):\n    \"\"\"Generate an HTML flame graph for peak memory usage\"\"\"\n\n    def __init__(self) -> None:\n        super().__init__(\n            reporter_factory=FlameGraphReporter.from_snapshot,\n            temporal_reporter_factory=FlameGraphReporter.from_temporal_snapshot,\n            reporter_name=\"flamegraph\",\n        )\n\n    def prepare_parser(self, parser: argparse.ArgumentParser) -> None:\n        super().prepare_parser(parser)\n        parser.add_argument(\n            \"--split-threads\",\n            help=\"Do not merge allocations across threads\",\n            action=\"store_true\",\n            default=False,\n        )\n\n        parser.add_argument(\n            \"--inverted\",\n            help=\"Invert flame graph\",\n            action=\"store_true\",\n            default=False,\n        )\n\n        parser.add_argument(\n            \"--max-memory-records\",\n            help=\"Maximum number of memory records to display\",\n            type=int,\n            default=None,\n        )\n\n        parser.add_argument(\n            \"--no-web\",\n            help=\"Use local assets instead of fetching from CDN\",\n            action=\"store_true\",\n            default=False,\n        )\n"
  },
  {
    "path": "src/memray/commands/live.py",
    "content": "import argparse\nfrom contextlib import suppress\nfrom typing import Optional\n\nfrom memray import SocketReader\nfrom memray._errors import MemrayCommandError\nfrom memray.reporters.tui import TUIApp\n\n\nclass LiveCommand:\n    \"\"\"Remotely monitor allocations in a text-based interface\"\"\"\n\n    def prepare_parser(self, parser: argparse.ArgumentParser) -> None:\n        parser.add_argument(\n            \"port\",\n            help=\"Remote port to connect to\",\n            default=None,\n            type=int,\n        )\n\n    def run(self, args: argparse.Namespace, parser: argparse.ArgumentParser) -> None:\n        with suppress(KeyboardInterrupt):\n            self.start_live_interface(args.port)\n\n    def start_live_interface(\n        self, port: int, cmdline_override: Optional[str] = None\n    ) -> None:\n        if port >= 2**16 or port <= 0:\n            raise MemrayCommandError(f\"Invalid port: {port}\", exit_code=1)\n        with SocketReader(port=port) as reader:\n            TUIApp(reader, cmdline_override=cmdline_override).run()\n"
  },
  {
    "path": "src/memray/commands/parse.py",
    "content": "import argparse\nimport os\n\nfrom memray import dump_all_records\nfrom memray._errors import MemrayCommandError\n\n\nclass ParseCommand:\n    \"\"\"Debug a results file by parsing and printing each record in it\"\"\"\n\n    def prepare_parser(self, parser: argparse.ArgumentParser) -> None:\n        parser.add_argument(\"results\", help=\"Results of the tracker run\")\n\n    def run(self, args: argparse.Namespace, parser: argparse.ArgumentParser) -> None:\n        if os.isatty(1):\n            raise MemrayCommandError(\n                \"You must redirect stdout to a file or shell pipeline.\",\n                exit_code=1,\n            )\n\n        try:\n            dump_all_records(args.results)\n        except OSError as e:\n            raise MemrayCommandError(\n                f\"Failed to parse allocation records in {args.results}\\nReason: {e}\",\n                exit_code=1,\n            )\n"
  },
  {
    "path": "src/memray/commands/run.py",
    "content": "import argparse\nimport ast\nimport contextlib\nimport os\nimport pathlib\nimport runpy\nimport socket\nimport subprocess\nimport sys\nimport textwrap\nfrom contextlib import closing\nfrom contextlib import suppress\nfrom typing import Any\nfrom typing import Dict\nfrom typing import List\nfrom typing import Optional\n\nfrom memray import Destination\nfrom memray import FileDestination\nfrom memray import FileFormat\nfrom memray import SocketDestination\nfrom memray import Tracker\nfrom memray._errors import MemrayCommandError\nfrom memray.commands.live import LiveCommand\n\n\ndef _get_free_port() -> int:\n    with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as sock:\n        sock.bind((\"\", 0))\n        sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)\n        return int(sock.getsockname()[1])\n\n\ndef _should_modify_sys_path() -> bool:\n    isolated_mode = sys.flags.isolated\n    safe_path_mode = getattr(sys.flags, \"safe_path\", False)  # New in Python 3.11\n    return not isolated_mode and not safe_path_mode\n\n\ndef _run_tracker(\n    destination: Destination,\n    args: argparse.Namespace,\n    post_run_message: Optional[str] = None,\n) -> None:\n    try:\n        kwargs: Dict[str, Any] = {}\n        if args.follow_fork:\n            kwargs[\"follow_fork\"] = True\n        if args.trace_python_allocators:\n            kwargs[\"trace_python_allocators\"] = True\n        if args.aggregate:\n            kwargs[\"file_format\"] = FileFormat.AGGREGATED_ALLOCATIONS\n        tracker = Tracker(destination=destination, native_traces=args.native, **kwargs)\n    except OSError as error:\n        raise MemrayCommandError(str(error), exit_code=1)\n\n    with tracker:\n        pid = os.getpid()\n        try:\n            if args.run_as_module:\n                if _should_modify_sys_path():\n                    sys.path[0] = os.getcwd()\n                # run_module will replace argv[0] with the script's path\n                sys.argv = [\"\", *args.script_args]\n                runpy.run_module(args.script, run_name=\"__main__\", alter_sys=True)\n            elif args.run_as_cmd:\n                if _should_modify_sys_path():\n                    sys.path[0] = \"\"\n                sys.argv = [\"-c\", *args.script_args]\n                exec(args.script, {\"__name__\": \"__main__\"})\n            else:\n                if _should_modify_sys_path():\n                    sys.path[0] = str(\n                        pathlib.Path(args.script).resolve().parent.absolute()\n                    )\n                sys.argv = [args.script, *args.script_args]\n                runpy.run_path(args.script, run_name=\"__main__\")\n        finally:\n            if not args.quiet and post_run_message is not None and pid == os.getpid():\n                print(post_run_message)\n\n\ndef _child_process(\n    port: int,\n    native: bool,\n    trace_python_allocators: bool,\n    run_as_module: bool,\n    run_as_cmd: bool,\n    quiet: bool,\n    script: str,\n    script_args: List[str],\n) -> None:\n    args = argparse.Namespace(\n        native=native,\n        trace_python_allocators=trace_python_allocators,\n        follow_fork=False,\n        aggregate=False,\n        run_as_module=run_as_module,\n        run_as_cmd=run_as_cmd,\n        quiet=quiet,\n        script=script,\n        script_args=script_args,\n    )\n    _run_tracker(destination=SocketDestination(server_port=port), args=args)\n\n\ndef _run_child_process_and_attach(args: argparse.Namespace) -> None:\n    port = args.live_port\n    if port is None:\n        port = _get_free_port()\n    if not 2**16 > port > 0:\n        raise MemrayCommandError(f\"Invalid port: {port}\", exit_code=1)\n\n    arguments = (\n        f\"{port},{args.native},{args.trace_python_allocators},\"\n        f\"{args.run_as_module},{args.run_as_cmd},{args.quiet},\"\n        f\"{args.script!r},{args.script_args}\"\n    )\n    tracked_app_cmd = [\n        sys.executable,\n        \"-c\",\n        f\"from memray.commands.run import _child_process;_child_process({arguments})\",\n    ]\n    with contextlib.suppress(KeyboardInterrupt):\n        with subprocess.Popen(\n            tracked_app_cmd,\n            stderr=subprocess.PIPE,\n            stdout=subprocess.DEVNULL,\n            text=True,\n        ) as process:\n            try:\n                LiveCommand().start_live_interface(\n                    port, cmdline_override=\" \".join(sys.argv)\n                )\n            except (Exception, KeyboardInterrupt) as error:\n                process.terminate()\n                raise error from None\n            process.terminate()\n            if process.returncode:\n                if process.stderr:\n                    print(process.stderr.read(), file=sys.stderr)\n                raise (MemrayCommandError(exit_code=process.returncode))\n\n\ndef _run_with_socket_output(args: argparse.Namespace) -> None:\n    port = args.live_port\n    if port is None:\n        port = _get_free_port()\n    if not 2**16 > port > 0:\n        raise MemrayCommandError(f\"Invalid port: {port}\", exit_code=1)\n\n    if not args.quiet:\n        memray_cli = f\"memray{sys.version_info.major}.{sys.version_info.minor}\"\n        print(f\"Run '{memray_cli} live {port}' in another shell to see live results\")\n    with suppress(KeyboardInterrupt):\n        _run_tracker(destination=SocketDestination(server_port=port), args=args)\n\n\ndef _run_with_file_output(args: argparse.Namespace) -> None:\n    if args.output is None:\n        script_name = args.script\n        if args.run_as_cmd:\n            script_name = \"string\"\n\n        output = f\"memray-{os.path.basename(script_name)}.{os.getpid()}.bin\"\n        filename = os.path.join(os.path.dirname(script_name), output)\n    else:\n        filename = args.output\n\n    if not args.quiet:\n        print(f\"Writing profile results into {filename}\")\n\n    example_report_generation_message = textwrap.dedent(\n        f\"\"\"\n        [memray] Successfully generated profile results.\n\n        You can now generate reports from the stored allocation records.\n        Some example commands to generate reports:\n\n        {sys.executable} -m memray flamegraph {filename}\n        \"\"\"\n    ).strip()\n\n    destination = FileDestination(\n        path=filename, overwrite=args.force, compress_on_exit=args.compress_on_exit\n    )\n    try:\n        _run_tracker(\n            destination=destination,\n            args=args,\n            post_run_message=example_report_generation_message,\n        )\n    except OSError as error:\n        raise MemrayCommandError(str(error), exit_code=1)\n\n\nclass RunCommand:\n    \"\"\"Run the specified application and track memory usage\"\"\"\n\n    def prepare_parser(self, parser: argparse.ArgumentParser) -> None:\n        parser.usage = \"%(prog)s [-m module | -c cmd | file] [args]\"\n        output_group = parser.add_mutually_exclusive_group()\n        output_group.add_argument(\n            \"-o\",\n            \"--output\",\n            help=\"Output file name (default: <process_name>.<pid>.bin)\",\n        )\n        output_group.add_argument(\n            \"--live\",\n            help=\"Start a live tracking session and immediately connect a live server\",\n            action=\"store_true\",\n            dest=\"live_mode\",\n            default=False,\n        )\n        output_group.add_argument(\n            \"--live-remote\",\n            help=\"Start a live tracking session and wait until a client connects\",\n            action=\"store_true\",\n            dest=\"live_remote_mode\",\n            default=False,\n        )\n        parser.add_argument(\n            \"--live-port\",\n            \"-p\",\n            help=\"Port to use when starting live tracking (default: random free port)\",\n            default=None,\n            type=int,\n        )\n        parser.add_argument(\n            \"--aggregate\",\n            help=\"Write aggregated stats to the output file instead of all allocations\",\n            action=\"store_true\",\n            default=False,\n        )\n\n        parser.add_argument(\n            \"--native\",\n            help=\"Track native (C/C++) stack frames as well\",\n            action=\"store_true\",\n            dest=\"native\",\n            default=False,\n        )\n        parser.add_argument(\n            \"--follow-fork\",\n            action=\"store_true\",\n            help=\"Record allocations in child processes forked from the tracked script\",\n            default=False,\n        )\n        parser.add_argument(\n            \"--trace-python-allocators\",\n            action=\"store_true\",\n            help=\"Record allocations made by the pymalloc allocator\",\n            default=False,\n        )\n        parser.add_argument(\n            \"-q\",\n            \"--quiet\",\n            help=\"Don't show any tracking-specific output while running\",\n            action=\"store_true\",\n        )\n        parser.add_argument(\n            \"-f\",\n            \"--force\",\n            help=\"If the output file already exists, overwrite it\",\n            action=\"store_true\",\n            default=False,\n        )\n        compression = parser.add_mutually_exclusive_group()\n        compression.add_argument(\n            \"--compress-on-exit\",\n            help=\"Compress the resulting file using lz4 after tracking completes\",\n            default=True,\n            action=\"store_true\",\n        )\n        compression.add_argument(\n            \"--no-compress\",\n            help=\"Do not compress the resulting file using lz4\",\n            default=False,\n            action=\"store_true\",\n        )\n        parser.add_argument(\n            \"-c\",\n            help=\"Program passed in as string\",\n            action=\"store_true\",\n            dest=\"run_as_cmd\",\n            default=False,\n        )\n        parser.add_argument(\n            \"-m\",\n            help=\"Run library module as a script (terminates option list)\",\n            action=\"store_true\",\n            dest=\"run_as_module\",\n        )\n        parser.add_argument(\"script\", help=argparse.SUPPRESS, metavar=\"file\")\n        parser.add_argument(\n            \"script_args\",\n            help=argparse.SUPPRESS,\n            nargs=argparse.REMAINDER,\n            metavar=\"module\",\n        )\n\n    def validate_target_file(self, args: argparse.Namespace) -> None:\n        \"\"\"Ensure we are running a Python file\"\"\"\n        if args.run_as_module:\n            return\n        try:\n            if args.run_as_cmd:\n                source = bytes(args.script, \"UTF-8\")\n            else:\n                source = pathlib.Path(args.script).read_bytes()\n            ast.parse(source)\n        except (SyntaxError, ValueError):\n            raise MemrayCommandError(\n                \"Only valid Python files or commands can be executed under memray\",\n                exit_code=1,\n            )\n\n    def run(self, args: argparse.Namespace, parser: argparse.ArgumentParser) -> None:\n        if args.no_compress:\n            args.compress_on_exit = False\n\n        if args.live_port is not None and not args.live_remote_mode:\n            parser.error(\"The --live-port argument requires --live-remote\")\n        if args.follow_fork is True and (args.live_mode or args.live_remote_mode):\n            parser.error(\"--follow-fork cannot be used with the live TUI\")\n        if args.aggregate and (args.live_mode or args.live_remote_mode):\n            parser.error(\"--aggregate cannot be used with the live TUI\")\n        with contextlib.suppress(OSError):\n            if args.run_as_cmd and pathlib.Path(args.script).exists():\n                parser.error(\"remove the option -c to run a file\")\n\n        self.validate_target_file(args)\n\n        if args.live_mode:\n            _run_child_process_and_attach(args)\n        elif args.live_remote_mode:\n            _run_with_socket_output(args)\n        else:\n            _run_with_file_output(args)\n"
  },
  {
    "path": "src/memray/commands/stats.py",
    "content": "import argparse\nimport os\nfrom pathlib import Path\nfrom typing import Optional\n\nfrom memray._errors import MemrayCommandError\nfrom memray._memray import compute_statistics\nfrom memray.reporters.stats import StatsReporter\n\n\nclass StatsCommand:\n    \"\"\"Generate high level stats of the memory usage in the terminal\"\"\"\n\n    def prepare_parser(self, parser: argparse.ArgumentParser) -> None:\n        parser.add_argument(\"results\", help=\"Results of the tracker run\")\n\n        def valid_positive_int(value: str) -> int:\n            try:\n                ivalue = int(value)\n                if ivalue <= 0:\n                    raise ValueError\n            except ValueError:\n                raise argparse.ArgumentTypeError(\n                    f\"{value} is an invalid positive int value\"\n                )\n\n            return ivalue\n\n        parser.add_argument(\n            \"-n\",\n            \"--num-largest\",\n            help=\"Displays the top 'n' largest allocating functions. Default is 5\",\n            type=valid_positive_int,\n            default=5,\n        )\n\n        parser.add_argument(\n            \"--json\",\n            help=\"Exports stats to a JSON file\",\n            action=\"store_true\",\n            default=False,\n        )\n        parser.add_argument(\n            \"-o\",\n            \"--output\",\n            help=\"Output file name for JSON output\",\n            default=None,\n        )\n        parser.add_argument(\n            \"-f\",\n            \"--force\",\n            help=\"If the JSON output file already exists, overwrite it\",\n            action=\"store_true\",\n            default=False,\n        )\n\n    def run(self, args: argparse.Namespace, parser: argparse.ArgumentParser) -> None:\n        result_path = Path(args.results)\n        if not result_path.exists() or not result_path.is_file():\n            raise MemrayCommandError(f\"No such file: {args.results}\", exit_code=1)\n        try:\n            stats = compute_statistics(\n                os.fspath(args.results),\n                report_progress=True,\n                num_largest=args.num_largest,\n            )\n        except OSError as e:\n            raise MemrayCommandError(\n                f\"Failed to compute statistics for {result_path}\\nReason: {e}\",\n                exit_code=1,\n            )\n\n        json_output_file: Optional[Path] = None\n        if args.json:\n            if args.output:\n                json_output_file = Path(args.output)\n            else:\n                filename = str(result_path.name) + \".json\"\n                if filename.startswith(\"memray-\"):\n                    filename = filename[len(\"memray-\") :]\n                filename = \"memray-stats-\" + filename\n                json_output_file = result_path.with_name(filename)\n\n            if not args.force and json_output_file.exists():\n                raise MemrayCommandError(\n                    f\"File already exists, will not overwrite: {json_output_file}\",\n                    exit_code=1,\n                )\n\n        reporter = StatsReporter(stats, args.num_largest)\n        reporter.render(json_output_file=json_output_file)\n        if json_output_file is not None:\n            print(f\"Wrote {json_output_file}\")\n"
  },
  {
    "path": "src/memray/commands/summary.py",
    "content": "import argparse\nimport os\nfrom pathlib import Path\nfrom textwrap import dedent\n\nfrom memray import FileReader\nfrom memray._errors import MemrayCommandError\nfrom memray.commands.common import warn_if_file_is_not_aggregated_and_is_too_big\nfrom memray.commands.common import warn_if_not_enough_symbols\nfrom memray.reporters.summary import SummaryReporter\n\n\nclass SummaryCommand:\n    \"\"\"Generate a terminal-based summary report of the functions that allocate most memory\"\"\"\n\n    def prepare_parser(self, parser: argparse.ArgumentParser) -> None:\n        parser.add_argument(\"results\", help=\"Results of the tracker run\")\n        parser.add_argument(\n            \"-s\",\n            \"--sort-column\",\n            help=\"Column number to sort on\",\n            type=int,\n            default=1,\n        )\n        parser.add_argument(\n            \"-r\",\n            \"--max-rows\",\n            help=\"Maximum number of rows to display\",\n            type=int,\n            default=None,\n        )\n        alloc_type_group = parser.add_mutually_exclusive_group()\n        alloc_type_group.add_argument(\n            \"--temporary-allocation-threshold\",\n            metavar=\"N\",\n            help=dedent(\n                \"\"\"\n                Report temporary allocations, as opposed to leaked allocations\n                or high watermark allocations.  An allocation is considered\n                temporary if at most N other allocations occur before it is\n                deallocated.  With N=0, an allocation is temporary only if it\n                is immediately deallocated before any other allocation occurs.\n                \"\"\"\n            ),\n            action=\"store\",\n            dest=\"temporary_allocation_threshold\",\n            type=int,\n            default=-1,\n        )\n        alloc_type_group.add_argument(\n            \"--temporary-allocations\",\n            help=\"Equivalent to --temporary-allocation-threshold=1\",\n            action=\"store_const\",\n            dest=\"temporary_allocation_threshold\",\n            const=1,\n        )\n\n    def run(self, args: argparse.Namespace, parser: argparse.ArgumentParser) -> None:\n        max_cols = SummaryReporter.N_COLUMNS\n        if args.sort_column < 1 or args.sort_column > max_cols:\n            parser.error(f\"The --sort-column argument must be between 1 and {max_cols}\")\n\n        result_path = Path(args.results)\n        if not result_path.exists() or not result_path.is_file():\n            raise MemrayCommandError(f\"No such file: {args.results}\", exit_code=1)\n\n        try:\n            reader = FileReader(os.fspath(args.results), report_progress=True)\n            if reader.metadata.has_native_traces:\n                warn_if_not_enough_symbols()\n\n            if not args.temporary_allocation_threshold >= 0:\n                warn_if_file_is_not_aggregated_and_is_too_big(reader, result_path)\n\n            if args.temporary_allocation_threshold >= 0:\n                snapshot = iter(\n                    reader.get_temporary_allocation_records(\n                        threshold=args.temporary_allocation_threshold,\n                        merge_threads=False,\n                    )\n                )\n            else:\n                snapshot = iter(\n                    reader.get_high_watermark_allocation_records(merge_threads=True)\n                )\n        except OSError as e:\n            raise MemrayCommandError(\n                f\"Failed to parse allocation records in {result_path}\\nReason: {e}\",\n                exit_code=1,\n            )\n        reporter = SummaryReporter.from_snapshot(\n            snapshot,\n            native=reader.metadata.has_native_traces,\n        )\n        reporter.render(sort_column=args.sort_column, max_rows=args.max_rows)\n"
  },
  {
    "path": "src/memray/commands/table.py",
    "content": "import argparse\n\nfrom ..reporters.table import TableReporter\nfrom .common import HighWatermarkCommand\n\n\nclass TableCommand(HighWatermarkCommand):\n    \"\"\"Generate an HTML table with all records in the peak memory usage\"\"\"\n\n    def __init__(self) -> None:\n        super().__init__(\n            reporter_factory=TableReporter.from_snapshot,\n            reporter_name=\"table\",\n        )\n\n    def prepare_parser(self, parser: argparse.ArgumentParser) -> None:\n        super().prepare_parser(parser)\n        parser.add_argument(\n            \"--no-web\",\n            help=\"Use local assets instead of fetching from CDN\",\n            action=\"store_true\",\n            default=False,\n        )\n"
  },
  {
    "path": "src/memray/commands/transform.py",
    "content": "import argparse\nimport importlib.util\nimport shutil\nimport sys\n\nfrom rich import print as pprint\n\nfrom memray._errors import MemrayCommandError\n\nfrom ..reporters.transform import TransformReporter\nfrom .common import HighWatermarkCommand\n\n\nclass TransformCommand(HighWatermarkCommand):\n    \"\"\"Generate reports files in different formats\"\"\"\n\n    def __init__(self) -> None:\n        super().__init__(\n            reporter_factory=lambda *args, **kwargs: TransformReporter(\n                *args, **kwargs, format=self.reporter_name\n            ),\n            reporter_name=\"transform\",\n        )\n\n    def prepare_parser(self, parser: argparse.ArgumentParser) -> None:\n        formats = \", \".join(TransformReporter.SUFFIX_MAP)\n        parser.add_argument(\n            \"format\",\n            help=f\"Format to use for the report. Available formats: {formats}\",\n        )\n        super().prepare_parser(parser)\n\n    def run(self, args: argparse.Namespace, parser: argparse.ArgumentParser) -> None:\n        the_format = args.format.lower()\n        suffix = TransformReporter.SUFFIX_MAP.get(the_format)\n        if not suffix:\n            raise MemrayCommandError(\n                f\"Format not supported: {args.format}\", exit_code=1\n            )\n\n        self.suffix = suffix\n        self.reporter_name = the_format\n        super().run(args, parser)\n\n        post_run_callable = getattr(self, f\"post_run_{the_format}\", None)\n        if post_run_callable:\n            post_run_callable()\n\n    def post_run_gprof2dot(self) -> None:\n        assert self.output_file is not None\n        command = \"\"\n        if shutil.which(\"gprof2dot\") is not None:\n            command = \"gprof2dot\"\n        elif importlib.util.find_spec(\"gprof2dot\") is not None:\n            command = f\"{sys.executable} -m gprof2dot\"\n        else:\n            pprint(\n                \":exclamation: [red]gprof2dot doesn't seem to be installed. \"\n                \"Please install it to be able to process the transform.[/red]\"\n                \"\\n:point_right: Check out https://github.com/jrfonseca/gprof2dot for \"\n                \"installation instructions\"\n            )\n\n        if not shutil.which(\"dot\"):\n            pprint(\n                \":exclamation: [red]Graphviz doesn't seem to be installed. \"\n                \"Please install it to be able to process the transform.[/red]\"\n                \"\\n:point_right: Check out https://graphviz.org/download/ for \"\n                \"installation instructions\"\n            )\n\n        print()\n        print(\"To generate a graph from the transform file, run for example:\")\n        print(f\"{command} -f json {self.output_file} | dot -Tpng -o output.png\")\n"
  },
  {
    "path": "src/memray/commands/tree.py",
    "content": "import argparse\nimport os\nfrom pathlib import Path\nfrom textwrap import dedent\n\nfrom memray import FileReader\nfrom memray._errors import MemrayCommandError\nfrom memray.commands.common import warn_if_file_is_not_aggregated_and_is_too_big\nfrom memray.commands.common import warn_if_not_enough_symbols\nfrom memray.reporters.tree import TreeReporter\n\n\nclass TreeCommand:\n    \"\"\"Generate a tree view in the terminal for peak memory usage\"\"\"\n\n    def prepare_parser(self, parser: argparse.ArgumentParser) -> None:\n        parser.add_argument(\"results\", help=\"Results of the tracker run\")\n        parser.add_argument(\n            \"-b\",\n            \"--biggest-allocs\",\n            help=\"Show n biggest allocations (defaults to 200)\",\n            type=int,\n            default=200,\n        )\n        alloc_type_group = parser.add_mutually_exclusive_group()\n        alloc_type_group.add_argument(\n            \"--temporary-allocation-threshold\",\n            metavar=\"N\",\n            help=dedent(\n                \"\"\"\n                Report temporary allocations, as opposed to leaked allocations\n                or high watermark allocations.  An allocation is considered\n                temporary if at most N other allocations occur before it is\n                deallocated.  With N=0, an allocation is temporary only if it\n                is immediately deallocated before any other allocation occurs.\n                \"\"\"\n            ),\n            action=\"store\",\n            dest=\"temporary_allocation_threshold\",\n            type=int,\n            default=-1,\n        )\n        alloc_type_group.add_argument(\n            \"--temporary-allocations\",\n            help=\"Equivalent to --temporary-allocation-threshold=1\",\n            action=\"store_const\",\n            dest=\"temporary_allocation_threshold\",\n            const=1,\n        )\n\n    def run(self, args: argparse.Namespace, parser: argparse.ArgumentParser) -> None:\n        result_path = Path(args.results)\n        if not result_path.exists() or not result_path.is_file():\n            raise MemrayCommandError(f\"No such file: {args.results}\", exit_code=1)\n\n        try:\n            reader = FileReader(os.fspath(args.results), report_progress=True)\n            if reader.metadata.has_native_traces:\n                warn_if_not_enough_symbols()\n\n            if not args.temporary_allocation_threshold >= 0:\n                warn_if_file_is_not_aggregated_and_is_too_big(reader, result_path)\n\n            if args.temporary_allocation_threshold >= 0:\n                snapshot = iter(\n                    reader.get_temporary_allocation_records(\n                        threshold=args.temporary_allocation_threshold,\n                        merge_threads=False,\n                    )\n                )\n            else:\n                snapshot = iter(\n                    reader.get_high_watermark_allocation_records(merge_threads=False)\n                )\n            reporter = TreeReporter.from_snapshot(\n                snapshot,\n                biggest_allocs=args.biggest_allocs,\n                native_traces=reader.metadata.has_native_traces,\n            )\n        except OSError as e:\n            raise MemrayCommandError(\n                f\"Failed to parse allocation records in {result_path}\\nReason: {e}\",\n                exit_code=1,\n            )\n        reporter.render()\n"
  },
  {
    "path": "src/memray/py.typed",
    "content": ""
  },
  {
    "path": "src/memray/reporters/__init__.py",
    "content": "import sys\nfrom typing import TextIO\n\nfrom memray import Metadata\n\nif sys.version_info >= (3, 8):\n    from typing import Protocol\nelse:\n    from typing_extensions import Protocol\n\n\nclass BaseReporter(Protocol):\n    def render(\n        self,\n        outfile: TextIO,\n        metadata: Metadata,\n        show_memory_leaks: bool,\n        merge_threads: bool,\n        inverted: bool,\n        no_web: bool = False,\n    ) -> None:\n        ...\n"
  },
  {
    "path": "src/memray/reporters/_textual_hacks.py",
    "content": "import dataclasses\nfrom typing import Any\nfrom typing import Dict\nfrom typing import Tuple\nfrom typing import Union\n\nfrom textual import binding\nfrom textual.app import App\nfrom textual.binding import Binding\nfrom textual.dom import DOMNode\nfrom textual.widgets import Footer\n\n# In Textual 0.61, `App.namespace_bindings` was removed in favor of\n# `Screen.active_bindings`. The two have a slightly different interface:\n# a 2 item `tuple` was updated to a 3 item `namedtuple`.\n# The `Bindings` type alias shows the two possible structures.\n# The `update_key_description` implementation works for both,\n# since we still support Textual versions below 0.61.\n\nBindings = Union[Dict[str, \"binding.ActiveBinding\"], Dict[str, Tuple[DOMNode, Binding]]]\n\n\ndef update_key_description(bindings: Bindings, key: str, description: str) -> None:\n    val = bindings[key]\n    binding = dataclasses.replace(val[1], description=description)\n    if type(val) is tuple:\n        bindings[key] = val[:1] + (binding,) + val[2:]  # type: ignore\n    else:\n        bindings[key] = val._replace(binding=binding)  # type: ignore\n\n\ndef redraw_footer(app: App[Any]) -> None:\n    footer = app.screen.query_one(Footer)\n    if hasattr(footer, \"recompose\"):\n        # Added in Textual v0.53\n        footer.refresh(recompose=True)\n    else:  # pragma: no cover\n        # Hack: trick the Footer into redrawing itself\n        footer.highlight_key = \"q\"  # type: ignore[attr-defined]\n        footer.highlight_key = None  # type: ignore[attr-defined]\n"
  },
  {
    "path": "src/memray/reporters/assets/README.md",
    "content": "# Uncompiled JS assets\n\nThese files are compiled using webpack into the `templates/assets` directory.\nThese sources are included in the source distribution as well as the wheel\ndistribution. The wheel distribution also contains the compiled JS files.\n"
  },
  {
    "path": "src/memray/reporters/assets/__init__.py",
    "content": ""
  },
  {
    "path": "src/memray/reporters/assets/common.js",
    "content": "import _ from \"lodash\";\n\nexport function initMemoryGraph(memory_records) {\n  const time = memory_records.map((a) => new Date(a[0]));\n  const resident_size = memory_records.map((a) => a[1]);\n  const heap_size = memory_records.map((a) => a[2]);\n  const mode = memory_records.length > 1 ? \"lines\" : \"markers\";\n\n  var resident_size_plot = {\n    x: time,\n    y: resident_size,\n    mode: mode,\n    name: \"Resident size\",\n  };\n\n  var heap_size_plot = {\n    x: time,\n    y: heap_size,\n    mode: mode,\n    name: \"Heap size\",\n  };\n\n  var data = [resident_size_plot, heap_size_plot];\n\n  var layout = {\n    xaxis: {\n      title: {\n        text: \"Time\",\n      },\n    },\n    yaxis: {\n      title: {\n        text: \"Memory Size\",\n      },\n      tickformat: \".4~s\",\n      exponentformat: \"B\",\n      ticksuffix: \"B\",\n    },\n  };\n\n  var layout_small = {\n    height: 40,\n    margin: {\n      l: 0,\n      r: 0,\n      b: 0,\n      t: 0,\n      pad: 4,\n    },\n    plot_bgcolor: \"#343a40\", // this matches the color of bg-dark in our navbar\n    yaxis: {\n      tickformat: \".4~s\",\n      exponentformat: \"B\",\n      ticksuffix: \"B\",\n    },\n    showlegend: false,\n  };\n  var config = {\n    responsive: true,\n    displayModeBar: true,\n    modeBarButtonsToAdd: [\n      {\n        name: \"downloadDataAsCsv\",\n        title: \"Download data as CSV\",\n        icon: Plotly.Icons.disk,\n        click: function (gd) {\n          var rows = [];\n          rows.push(\"trace,timestamp,memory_size_bytes\");\n\n          gd.data.forEach((trace, index) => {\n            const x = trace.x || [];\n            const y = trace.y || [];\n            for (var i = 0; i < Math.min(x.length, y.length); i++) {\n              const traceId = trace.name || \"trace\" + index;\n              const timestamp = x[i].getTime();\n              rows.push(`${traceId},${timestamp},${y[i]}`);\n            }\n          });\n\n          const csvContent = rows.join(\"\\r\\n\");\n          const blob = new Blob([csvContent], { type: \"text/csv\" });\n          const url = URL.createObjectURL(blob);\n\n          const a = document.createElement(\"a\");\n          a.href = url;\n          a.download = \"usage_over_time.csv\";\n          document.body.appendChild(a);\n          a.click();\n          document.body.removeChild(a);\n          URL.revokeObjectURL(url);\n        },\n      },\n    ],\n  };\n  var config_small = {\n    responsive: true,\n    displayModeBar: false,\n  };\n\n  Plotly.newPlot(\"memoryGraph\", data, layout, config);\n  Plotly.newPlot(\"smallMemoryGraph\", data, layout_small, config_small);\n\n  document.getElementById(\"smallMemoryGraph\").onclick(() => {\n    resizeMemoryGraph();\n  });\n}\n\nexport function resizeMemoryGraph() {\n  setTimeout(() => {\n    Plotly.Plots.resize(\"memoryGraph\");\n    Plotly.Plots.resize(\"smallMemoryGraph\");\n  }, 100);\n}\n\nexport function humanFileSize(bytes, dp = 1) {\n  if (Math.abs(bytes) < 1000) {\n    return bytes + \" B\";\n  }\n\n  const units = [\"kB\", \"MB\", \"GB\", \"TB\", \"PB\", \"EB\", \"ZB\", \"YB\"];\n  let u = -1;\n  const r = 10 ** dp;\n\n  do {\n    bytes /= 1000;\n    ++u;\n  } while (Math.round(Math.abs(bytes) * r) / r >= 1000 && u < units.length - 1);\n\n  return bytes.toFixed(dp) + \" \" + units[u];\n}\n\nexport function debounced(fn) {\n  var requestID;\n\n  // Return a debouncing wrapper function\n  return function () {\n    if (requestID) {\n      window.cancelAnimationFrame(requestID);\n    }\n\n    const context = this;\n    const args = arguments;\n    requestID = window.requestAnimationFrame(function () {\n      fn.apply(context, args);\n    });\n  };\n}\n\nexport function makeTooltipString(data, totalSize, merge_threads) {\n  let location = \"unknown location\";\n  if (data.location !== undefined) {\n    location = `File ${data.location[1]}, line ${data.location[2]} in ${data.location[0]}`;\n  }\n\n  const plural = data.n_allocations > 1 ? \"s\" : \"\";\n  const allocations_label = `${data.n_allocations} allocation${plural}`;\n  let displayString = `${location}<br>${totalSize} total<br>${allocations_label}`;\n  if (merge_threads === false) {\n    displayString = displayString.concat(`<br>Thread ID: ${data.thread_id}`);\n  }\n  return displayString;\n}\n\n/**\n * Recursively apply a filter to every frame in .children.\n *\n * @param root Root node.\n * @param compFunction Called with the node being traversed. Expected to return true or false.\n * @returns {NonNullable<any>} A copy of the input object with the filtering applied.\n */\nexport function filterFrames(root, compFunction) {\n  function _filter(obj) {\n    if (obj.children && obj.children.length > 0) {\n      obj.children = _.filter(obj.children, _filter);\n    }\n    return compFunction(obj);\n  }\n\n  // Avoid mutating the input\n  let children = _.cloneDeep(root.children);\n  const filtered_children = _.filter(children, _filter);\n  return _.defaults({ children: filtered_children }, root);\n}\n\n/**\n * Recursively filter out the specified thread IDs from the node's `children` attribute.\n *\n * @param root Root node.\n * @param threadId Thread ID to filter.\n * @returns {NonNullable<any>} A copy of the input object with the filtering applied.\n */\nexport function filterChildThreads(root, threadId) {\n  return filterFrames(root, (obj) => obj.thread_id === threadId);\n}\n\n/**\n * Recursively filter out nodes where the given filter function return `false`.\n *\n * @param root Root node.\n * @param func The filter function.\n * @returns {NonNullable<any>} A copy of the input object with the filtering applied.\n */\nfunction filterFramesByFunc(root, func) {\n  function filterChildren(node) {\n    let result = [];\n    if (!func(node)) {\n      for (const child of node.children) {\n        result.push(...filterChildren(child));\n      }\n    } else {\n      result = [];\n      for (const child of node.children) {\n        result.push(...filterChildren(child));\n      }\n      let new_node = _.clone(node);\n      new_node.children = result;\n      result = [new_node];\n    }\n    return result;\n  }\n\n  let children = [];\n  for (let child of root.children) {\n    children.push(...filterChildren(child));\n  }\n  return _.defaults({ children: children }, root);\n}\n\nexport function filterUninteresting(root) {\n  return filterFramesByFunc(root, (node) => {\n    return node.interesting;\n  });\n}\n\nexport function filterImportSystem(root) {\n  return filterFramesByFunc(root, (node) => {\n    return !node.import_system;\n  });\n}\n\n/**\n * Walk the children of the specified node and sum up the total allocations and memory use.\n *\n * @param data Root node.\n * @returns {{n_allocations: number, value: number}}\n */\n\nexport function sumAllocations(data) {\n  let initial = {\n    n_allocations: 0,\n    value: 0,\n  };\n\n  let sum = (result, node) => {\n    result.n_allocations += node.n_allocations;\n    result.value += node.value;\n    return result;\n  };\n\n  return _.reduce(data, sum, initial);\n}\n"
  },
  {
    "path": "src/memray/reporters/assets/common.test.js",
    "content": "import {\n  humanFileSize,\n  makeTooltipString,\n  filterChildThreads,\n  sumAllocations,\n  filterUninteresting,\n  filterImportSystem,\n  filterMergeNodesInverted,\n} from \"./common\";\n\ntest(\"handlesSmallValues\", () => {\n  expect(humanFileSize(0)).toBe(\"0 B\");\n  expect(humanFileSize(128)).toBe(\"128 B\");\n  expect(humanFileSize(999)).toBe(\"999 B\");\n});\n\ndescribe(\"Flame graph tooltip generation\", () => {\n  test(\"Generate label without thread\", () => {\n    const data = {\n      location: [\"foo\", \"foo.py\", \"10\"],\n      n_allocations: 3,\n      thread_id: \"merged thread\",\n    };\n    expect(makeTooltipString(data, \"1kB\", true)).toBe(\n      \"File foo.py, line 10 in foo<br>1kB total<br>3 allocations\",\n    );\n  });\n\n  test(\"Generate label with thread\", () => {\n    const data = {\n      location: [\"foo\", \"foo.py\", \"10\"],\n      n_allocations: 3,\n      thread_id: \"0x1\",\n    };\n    expect(makeTooltipString(data, \"1kB\", false)).toBe(\n      \"File foo.py, line 10 in foo<br>1kB total<br>3 allocations<br>Thread ID: 0x1\",\n    );\n  });\n  test(\"Generate label with single allocation\", () => {\n    const data = {\n      location: [\"foo\", \"foo.py\", \"10\"],\n      n_allocations: 1,\n      thread_id: \"0x1\",\n    };\n    expect(makeTooltipString(data, \"1kB\", false)).toBe(\n      \"File foo.py, line 10 in foo<br>1kB total<br>1 allocation<br>Thread ID: 0x1\",\n    );\n  });\n});\n\ndescribe(\"Filter threads\", () => {\n  const data = {\n    thread_id: \"0x0\",\n    children: [\n      {\n        thread_id: \"0x1\",\n        children: [\n          {\n            thread_id: \"0x1\",\n            children: [\n              {\n                thread_id: \"0x1\",\n                children: [],\n              },\n            ],\n          },\n        ],\n      },\n      {\n        thread_id: \"0x2\",\n        children: [],\n      },\n    ],\n  };\n\n  test(\"Filter a single thread\", () => {\n    const result = filterChildThreads(data, \"0x1\");\n    expect(result).toStrictEqual({\n      thread_id: \"0x0\",\n      children: [\n        {\n          thread_id: \"0x1\",\n          children: [\n            {\n              thread_id: \"0x1\",\n              children: [\n                {\n                  thread_id: \"0x1\",\n                  children: [],\n                },\n              ],\n            },\n          ],\n        },\n      ],\n    });\n  });\n  test(\"Filter multiple threads\", () => {\n    const result = filterChildThreads(data, \"0x2\");\n    expect(result).toStrictEqual({\n      thread_id: \"0x0\",\n      children: [\n        {\n          thread_id: \"0x2\",\n          children: [],\n        },\n      ],\n    });\n  });\n  test(\"Filter empty children\", () => {\n    expect(\n      filterChildThreads(\n        {\n          thread_id: \"0x0\",\n          children: [],\n        },\n        2,\n      ),\n    ).toStrictEqual({\n      thread_id: \"0x0\",\n      children: [],\n    });\n  });\n});\n\ndescribe(\"Recalculate allocations in root node\", () => {\n  const data = {\n    thread_id: \"0x0\",\n    n_allocations: 100,\n    value: 100,\n    children: [\n      {\n        thread_id: \"0x1\",\n        n_allocations: 5,\n        value: 50,\n        children: [\n          {\n            thread_id: \"0x1\",\n            n_allocations: 3,\n            value: 30,\n            children: [\n              {\n                thread_id: \"0x1\",\n                n_allocations: 1,\n                value: 10,\n                children: [],\n              },\n            ],\n          },\n        ],\n      },\n      {\n        thread_id: \"0x1\",\n        n_allocations: 1,\n        value: 10,\n        children: [],\n      },\n    ],\n  };\n  test(\"Recalculate allocations\", () => {\n    const sum = sumAllocations(data.children);\n    expect(sum).toStrictEqual({ n_allocations: 6, value: 60 });\n  });\n});\n\ndescribe(\"Filter uninteresting frames\", () => {\n  const data = {\n    interesting: true,\n    n_allocations: 10,\n    value: 100,\n    children: [\n      {\n        interesting: true,\n        n_allocations: 5,\n        value: 50,\n        children: [\n          {\n            interesting: false,\n            n_allocations: 2,\n            value: 20,\n            children: [\n              {\n                interesting: true,\n                n_allocations: 1,\n                value: 10,\n                children: [],\n              },\n            ],\n          },\n        ],\n      },\n      {\n        interesting: true,\n        n_allocations: 1,\n        value: 10,\n        children: [],\n      },\n    ],\n  };\n\n  test(\"Filter uninteresting\", () => {\n    const result = filterUninteresting(data);\n    expect(result).toStrictEqual({\n      interesting: true,\n      n_allocations: 10,\n      value: 100,\n      children: [\n        {\n          interesting: true,\n          n_allocations: 5,\n          value: 50,\n          children: [\n            {\n              interesting: true,\n              n_allocations: 1,\n              value: 10,\n              children: [],\n            },\n          ],\n        },\n        {\n          interesting: true,\n          n_allocations: 1,\n          value: 10,\n          children: [],\n        },\n      ],\n    });\n  });\n  test(\"Filter uninteresting when first child is not interesting\", () => {\n    const copied_data = JSON.parse(JSON.stringify(data));\n    copied_data.children[0].interesting = false;\n\n    const result = filterUninteresting(copied_data);\n    expect(result).toStrictEqual({\n      interesting: true,\n      n_allocations: 10,\n      value: 100,\n      children: [\n        {\n          interesting: true,\n          n_allocations: 1,\n          value: 10,\n          children: [],\n        },\n        {\n          interesting: true,\n          n_allocations: 1,\n          value: 10,\n          children: [],\n        },\n      ],\n    });\n  });\n\n  test(\"Filter uninteresting in a deep tree\", () => {\n    const result = filterUninteresting({\n      interesting: true,\n      n_allocations: 10,\n      value: 100,\n      children: [\n        {\n          interesting: false,\n          n_allocations: 5,\n          value: 50,\n          children: [\n            {\n              interesting: false,\n              n_allocations: 2,\n              value: 20,\n              children: [\n                {\n                  interesting: true,\n                  n_allocations: 1,\n                  value: 10,\n                  children: [],\n                },\n              ],\n            },\n          ],\n        },\n        {\n          interesting: false,\n          n_allocations: 1,\n          value: 10,\n          children: [],\n        },\n      ],\n    });\n\n    expect(result).toStrictEqual({\n      interesting: true,\n      n_allocations: 10,\n      value: 100,\n      children: [\n        {\n          interesting: true,\n          n_allocations: 1,\n          value: 10,\n          children: [],\n        },\n      ],\n    });\n  });\n  test(\"Filter uninteresting doesn't modify data\", () => {\n    let data = {\n      interesting: true,\n      n_allocations: 10,\n      value: 100,\n      children: [\n        {\n          interesting: true,\n          n_allocations: 5,\n          value: 50,\n          children: [\n            {\n              interesting: false,\n              n_allocations: 2,\n              value: 20,\n              children: [\n                {\n                  interesting: false,\n                  n_allocations: 1,\n                  value: 10,\n                  children: [],\n                },\n              ],\n            },\n          ],\n        },\n      ],\n    };\n    let copied_data = JSON.parse(JSON.stringify(data));\n    filterUninteresting(copied_data);\n    expect(copied_data).toStrictEqual(data);\n  });\n});\n\ndescribe(\"Filter import frames\", () => {\n  const data = {\n    import_system: false,\n    n_allocations: 10,\n    value: 100,\n    children: [\n      {\n        import_system: false,\n        n_allocations: 5,\n        value: 50,\n        children: [\n          {\n            import_system: true,\n            n_allocations: 2,\n            value: 20,\n            children: [\n              {\n                import_system: true,\n                n_allocations: 1,\n                value: 10,\n                children: [],\n              },\n            ],\n          },\n        ],\n      },\n      {\n        import_system: false,\n        n_allocations: 1,\n        value: 10,\n        children: [],\n      },\n    ],\n  };\n\n  test(\"Filter import system\", () => {\n    const result = filterImportSystem(data);\n    expect(result).toStrictEqual({\n      import_system: false,\n      n_allocations: 10,\n      value: 100,\n      children: [\n        {\n          import_system: false,\n          n_allocations: 5,\n          value: 50,\n          children: [],\n        },\n        {\n          import_system: false,\n          n_allocations: 1,\n          value: 10,\n          children: [],\n        },\n      ],\n    });\n  });\n  test(\"Filter import system when everything is import system except root\", () => {\n    const data = {\n      import_system: false,\n      n_allocations: 10,\n      value: 100,\n      children: [\n        {\n          import_system: true,\n          n_allocations: 5,\n          value: 50,\n          children: [\n            {\n              import_system: true,\n              n_allocations: 2,\n              value: 20,\n              children: [\n                {\n                  import_system: true,\n                  n_allocations: 1,\n                  value: 10,\n                  children: [],\n                },\n              ],\n            },\n          ],\n        },\n        {\n          import_system: true,\n          n_allocations: 1,\n          value: 10,\n          children: [],\n        },\n      ],\n    };\n    const result = filterImportSystem(data);\n    expect(result).toStrictEqual({\n      children: [],\n      import_system: false,\n      n_allocations: 10,\n      value: 100,\n    });\n  });\n\n  test(\"Filter import system in a deep tree\", () => {\n    const result = filterImportSystem({\n      import_system: false,\n      n_allocations: 10,\n      value: 100,\n      children: [\n        {\n          import_system: true,\n          n_allocations: 5,\n          value: 50,\n          children: [\n            {\n              import_system: true,\n              n_allocations: 2,\n              value: 20,\n              children: [\n                {\n                  import_system: true,\n                  n_allocations: 1,\n                  value: 10,\n                  children: [],\n                },\n              ],\n            },\n          ],\n        },\n        {\n          import_system: true,\n          n_allocations: 1,\n          value: 10,\n          children: [],\n        },\n      ],\n    });\n\n    expect(result).toStrictEqual({\n      import_system: false,\n      n_allocations: 10,\n      value: 100,\n      children: [],\n    });\n  });\n  test(\"Filter import system doesn't modify data\", () => {\n    let data = {\n      import_system: false,\n      n_allocations: 10,\n      value: 100,\n      children: [\n        {\n          import_system: false,\n          n_allocations: 5,\n          value: 50,\n          children: [\n            {\n              import_system: true,\n              n_allocations: 2,\n              value: 20,\n              children: [\n                {\n                  import_system: true,\n                  n_allocations: 1,\n                  value: 10,\n                  children: [],\n                },\n              ],\n            },\n          ],\n        },\n      ],\n    };\n    let copied_data = JSON.parse(JSON.stringify(data));\n    filterImportSystem(copied_data);\n    expect(copied_data).toStrictEqual(data);\n  });\n});\n"
  },
  {
    "path": "src/memray/reporters/assets/flamegraph.js",
    "content": "import { debounced, initMemoryGraph, resizeMemoryGraph } from \"./common\";\n\nimport {\n  initThreadsDropdown,\n  drawChart,\n  handleFragments,\n  onFilterUninteresting,\n  onFilterImportSystem,\n  onFilterThread,\n  onResetZoom,\n  onResize,\n  onInvert,\n  getFlamegraph,\n} from \"./flamegraph_common\";\n\nwindow.resizeMemoryGraph = resizeMemoryGraph;\n\nfunction packedDataToTree(packedData) {\n  const { strings, nodes, unique_threads } = packedData;\n\n  const node_objects = nodes.name.map((_, i) => ({\n    name: strings[nodes[\"name\"][i]],\n    location: [\n      strings[nodes[\"function\"][i]],\n      strings[nodes[\"filename\"][i]],\n      nodes[\"lineno\"][i],\n    ],\n    value: nodes[\"value\"][i],\n    children: nodes[\"children\"][i],\n    n_allocations: nodes[\"n_allocations\"][i],\n    thread_id: strings[nodes[\"thread_id\"][i]],\n    interesting: nodes[\"interesting\"][i] !== 0,\n    import_system: nodes[\"import_system\"][i] !== 0,\n  }));\n\n  for (const node of node_objects) {\n    node[\"children\"] = node[\"children\"].map((idx) => node_objects[idx]);\n  }\n\n  const root = node_objects[0];\n  root[\"unique_threads\"] = unique_threads.map((tid) => strings[tid]);\n  return root;\n}\n\nfunction initTrees(packedData) {\n  const { strings, nodes, inverted_no_imports_nodes, unique_threads } =\n    packedData;\n  flamegraphData = packedDataToTree({\n    strings: strings,\n    nodes: nodes,\n    unique_threads: unique_threads,\n  });\n\n  invertedNoImportsData = inverted\n    ? packedDataToTree({\n        strings: strings,\n        nodes: inverted_no_imports_nodes,\n        unique_threads: unique_threads,\n      })\n    : null;\n\n  data = flamegraphData;\n}\n\n// Main entrypoint\nfunction main() {\n  initTrees(packed_data);\n  initMemoryGraph(memory_records);\n  initThreadsDropdown(data, merge_threads);\n\n  // Create the flamegraph renderer\n  drawChart(data);\n\n  // Set zoom to correct element\n  if (location.hash) {\n    handleFragments();\n  }\n\n  // Setup event handlers\n  document.getElementById(\"icicles\").onchange = onInvert;\n  document.getElementById(\"flames\").onchange = onInvert;\n  document.getElementById(\"resetZoomButton\").onclick = onResetZoom;\n  document.getElementById(\"resetThreadFilterItem\").onclick = onFilterThread;\n  let hideUninterestingCheckBox = document.getElementById(\"hideUninteresting\");\n  hideUninterestingCheckBox.onclick = onFilterUninteresting.bind(this);\n  let hideImportSystemCheckBox = document.getElementById(\"hideImportSystem\");\n  hideImportSystemCheckBox.onclick = onFilterImportSystem.bind(this);\n  // Enable filtering by default\n  onFilterUninteresting.bind(this)();\n\n  document.onkeyup = (event) => {\n    if (event.code == \"Escape\") {\n      onResetZoom();\n    }\n  };\n  document.getElementById(\"searchTerm\").addEventListener(\"input\", () => {\n    const termElement = document.getElementById(\"searchTerm\");\n    getFlamegraph().search(termElement.value);\n  });\n\n  window.addEventListener(\"popstate\", handleFragments);\n  window.addEventListener(\"resize\", debounced(onResize));\n\n  let statsStartTime = document.getElementById(\"stats-start-time\");\n  let statsEndTime = document.getElementById(\"stats-end-time\");\n  statsStartTime.textContent = new Date(statsStartTime.innerText);\n  statsEndTime.textContent = new Date(statsEndTime.innerText);\n  // Enable tooltips\n  $('[data-toggle-second=\"tooltip\"]').tooltip();\n  $('[data-toggle=\"tooltip\"]').tooltip();\n}\n\ndocument.addEventListener(\"DOMContentLoaded\", main);\n"
  },
  {
    "path": "src/memray/reporters/assets/flamegraph_common.js",
    "content": "import {\n  filterChildThreads,\n  filterUninteresting,\n  filterImportSystem,\n  humanFileSize,\n  makeTooltipString,\n  sumAllocations,\n} from \"./common\";\nimport {\n  autoUpdate,\n  computePosition,\n  flip,\n  offset,\n  shift,\n} from \"@floating-ui/dom\";\n\nconst FILTER_UNINTERESTING = \"filter_uninteresting\";\nconst FILTER_IMPORT_SYSTEM = \"filter_import_system\";\nconst FILTER_THREAD = \"filter_thread\";\n\nclass FilteredChart {\n  constructor() {\n    this.filters = {};\n  }\n  registerFilter(name, func) {\n    this.filters[name] = func;\n  }\n  unRegisterFilter(name) {\n    delete this.filters[name];\n  }\n\n  drawChart(data) {\n    let filtered = data;\n    _.forOwn(this.filters, (func) => {\n      filtered = func(filtered);\n    });\n    drawChart(filtered);\n    // Merge 0 additional elements, triggering a redraw\n    chart.merge([]);\n  }\n}\n\nvar chart = null;\nvar flamegraphTooltip = null;\nlet filteredChart = new FilteredChart();\n\nexport function getFlamegraph() {\n  return chart;\n}\n\nexport function getFilteredChart() {\n  return filteredChart;\n}\n\n// For navigable #[integer] fragments\nfunction getCurrentId() {\n  if (location.hash) {\n    return parseInt(location.hash.substring(1), 10);\n  } else {\n    return 0;\n  }\n}\n\nfunction updateZoomButtom() {\n  document.getElementById(\"resetZoomButton\").disabled = getCurrentId() == 0;\n}\n\nfunction onClick(d) {\n  if (d.id == getCurrentId()) return;\n\n  history.pushState({ id: d.id }, d.data.name, `#${d.id}`);\n  updateZoomButtom();\n}\n\nexport function handleFragments() {\n  const id = getCurrentId();\n  const elem = chart.findById(id);\n  if (!elem) return;\n\n  chart.zoomTo(elem);\n  updateZoomButtom();\n}\n\n// For the invert button\nexport function onInvert() {\n  chart.inverted(this === document.getElementById(\"icicles\"));\n  chart.resetZoom(); // calls onClick\n\n  // Hide the tooltip for the radio button that was just clicked.\n  $('[data-toggle=\"tooltip\"]').tooltip(\"hide\");\n}\n\nexport function onResetZoom() {\n  chart.resetZoom(); // calls onClick\n}\n\n// For window resizing\nfunction getChartWidth() {\n  // Return the display width of the div we're drawing into\n  return document.getElementById(\"chart\").clientWidth;\n}\n\nexport function onResize() {\n  filteredChart.drawChart(data);\n\n  // Set zoom to correct element\n  if (location.hash) {\n    handleFragments();\n  }\n}\n\nexport function onFilterThread() {\n  const thread_id = this.dataset.thread;\n  if (thread_id === \"-0x1\") {\n    // Reset\n    filteredChart.unRegisterFilter(FILTER_THREAD);\n  } else {\n    filteredChart.registerFilter(FILTER_THREAD, (data) => {\n      let filteredData = filterChildThreads(data, thread_id);\n      const totalAllocations = sumAllocations(filteredData.children);\n      _.defaults(totalAllocations, filteredData);\n      filteredData.n_allocations = totalAllocations.n_allocations;\n      filteredData.value = totalAllocations.value;\n      return filteredData;\n    });\n  }\n  filteredChart.drawChart(data);\n}\n\nexport function onFilterUninteresting() {\n  if (this.hideUninterestingFrames === undefined) {\n    // Hide boring frames by default\n    this.hideUninterestingFrames = true;\n  }\n  if (this.hideUninterestingFrames === true) {\n    this.hideUninterestingFrames = true;\n\n    filteredChart.registerFilter(FILTER_UNINTERESTING, (data) => {\n      return filterUninteresting(data);\n    });\n  } else {\n    filteredChart.unRegisterFilter(FILTER_UNINTERESTING);\n  }\n  this.hideUninterestingFrames = !this.hideUninterestingFrames;\n  filteredChart.drawChart(data);\n}\n\nexport function onFilterImportSystem() {\n  if (this.hideImportSystemFrames === undefined) {\n    this.hideImportSystemFrames = true;\n  }\n  if (this.hideImportSystemFrames === true) {\n    this.hideImportSystemFrames = true;\n    if (!inverted) {\n      filteredChart.registerFilter(FILTER_IMPORT_SYSTEM, (data) => {\n        return filterImportSystem(data);\n      });\n    } else {\n      data = invertedNoImportsData;\n      if (temporal) {\n        hideImports = true;\n        intervals = invertedNoImportsIntervals;\n      }\n    }\n  } else {\n    filteredChart.unRegisterFilter(FILTER_IMPORT_SYSTEM);\n    data = flamegraphData;\n    if (temporal) {\n      hideImports = false;\n      intervals = flamegraphIntervals;\n    }\n  }\n  this.hideImportSystemFrames = !this.hideImportSystemFrames;\n  filteredChart.drawChart(data);\n}\n\nfunction getTooltipDirection(d) {\n  const midpoint = (d.x1 + d.x0) / 2;\n  // If the midpoint is in a reasonable location, put it below the element.\n  if (0.25 < midpoint && midpoint < 0.75) {\n    return \"s\";\n  }\n  // We're far from the right\n  if (d.x1 < 0.75) {\n    return \"e\";\n  }\n  // We're far from the left\n  if (d.x0 > 0.25) {\n    return \"w\";\n  }\n  // This shouldn't happen reasonably? If it does, just put it above and\n  // we'll deal with it later. :)\n  return \"n\";\n}\n\nfunction toPlacement(direction) {\n  if (direction === \"s\") {\n    return \"bottom\";\n  }\n  if (direction === \"e\") {\n    return \"right\";\n  }\n  if (direction === \"w\") {\n    return \"left\";\n  }\n  return \"top\";\n}\n\n// d3-flame-graph expects a callable tooltip object with show/hide methods.\nfunction getTooltip() {\n  const tooltipElement = document.createElement(\"div\");\n  tooltipElement.className = \"d3-flame-graph-tip\";\n  tooltipElement.style.position = \"fixed\";\n  tooltipElement.style.top = \"0\";\n  tooltipElement.style.left = \"0\";\n  tooltipElement.style.visibility = \"hidden\";\n  tooltipElement.style.pointerEvents = \"none\";\n  document.body.appendChild(tooltipElement);\n\n  let cleanupAutoUpdate = null;\n  let referenceElement = null;\n  let placement = \"top\";\n\n  const updatePosition = () => {\n    if (!referenceElement) {\n      return;\n    }\n    computePosition(referenceElement, tooltipElement, {\n      strategy: \"fixed\",\n      placement: placement,\n      middleware: [offset(6), flip(), shift({ padding: 8 })],\n    }).then(({ x, y }) => {\n      tooltipElement.style.left = `${x}px`;\n      tooltipElement.style.top = `${y}px`;\n    });\n  };\n\n  const tip = function () {\n    return tip;\n  };\n\n  tip.show = (d, target) => {\n    if (!d || !target) {\n      return;\n    }\n    const totalSize = humanFileSize(d.data.value);\n    tooltipElement.innerHTML = makeTooltipString(\n      d.data,\n      totalSize,\n      merge_threads,\n    );\n    placement = toPlacement(getTooltipDirection(d));\n    referenceElement = target;\n    tooltipElement.style.visibility = \"visible\";\n    // Replace any existing observer when quickly moving between frames\n    if (cleanupAutoUpdate) {\n      cleanupAutoUpdate();\n    }\n    // Keep the tooltip anchored while layout/scroll/resize changes happen\n    cleanupAutoUpdate = autoUpdate(\n      referenceElement,\n      tooltipElement,\n      updatePosition,\n    );\n    updatePosition();\n  };\n\n  tip.hide = () => {\n    referenceElement = null;\n    tooltipElement.style.visibility = \"hidden\";\n    // Stop position observers once the tooltip is hidden\n    if (cleanupAutoUpdate) {\n      cleanupAutoUpdate();\n      cleanupAutoUpdate = null;\n    }\n  };\n\n  tip.destroy = () => {\n    tip.hide();\n    tooltipElement.remove();\n  };\n\n  return tip;\n}\n\n// Our custom color mapping logic\nexport function decimalHash(string) {\n  let sum = 0;\n  for (let i = 0; i < string.length; i++)\n    sum += ((i + 1) * string.codePointAt(i)) / (1 << 8);\n  return sum % 1;\n}\n\nfunction fileExtension(filename) {\n  if (filename === undefined) return filename;\n  return (\n    filename.substring(filename.lastIndexOf(\".\") + 1, filename.length) ||\n    filename\n  );\n}\n\nfunction colorByExtension(extension) {\n  if (extension == \"py\") {\n    return d3.schemePastel1[2];\n  } else if (extension == \"c\" || extension == \"cpp\" || extension == \"h\") {\n    return d3.schemePastel1[5];\n  } else {\n    return d3.schemePastel1[8];\n  }\n}\n\nfunction memrayColorMapper(d, originalColor) {\n  // Highlighted nodes\n  if (d.highlight) {\n    return \"orange\";\n  }\n  // \"builtin\" / nodes that we don't want to highlight\n  if (!d.data.name || !d.data.location) {\n    return \"#EEE\";\n  }\n\n  return colorByExtension(fileExtension(d.data.location[1]));\n}\n\n// Show the 'Threads' dropdown if we have thread data, and populate it\nexport function initThreadsDropdown(data, merge_threads) {\n  if (merge_threads === true) {\n    return;\n  }\n  const threads = data.unique_threads;\n  if (!threads || threads.length <= 1) {\n    return;\n  }\n\n  document.getElementById(\"threadsDropdown\").removeAttribute(\"hidden\");\n  const threadsDropdownList = document.getElementById(\"threadsDropdownList\");\n  for (const thread of threads) {\n    let elem = document.createElement(\"a\");\n    elem.className = \"dropdown-item\";\n    elem.dataset.thread = thread;\n    elem.text = thread;\n    elem.onclick = onFilterThread;\n    threadsDropdownList.appendChild(elem);\n  }\n}\n\nexport function drawChart(chart_data) {\n  // Retain the \"invertedness\" if there's an existing graph.\n  let invert = chart ? chart.inverted() : true;\n\n  // Clear any existing chart\n  if (chart) {\n    chart.destroy();\n    if (flamegraphTooltip) {\n      flamegraphTooltip.destroy();\n      flamegraphTooltip = null;\n    }\n    d3.selectAll(\".d3-flame-graph-tip\").remove();\n  }\n\n  flamegraphTooltip = getTooltip();\n\n  // Create the chart\n  chart = flamegraph()\n    .width(getChartWidth())\n    // smooth transitions\n    .transitionDuration(250)\n    .transitionEase(d3.easeCubic)\n    .inverted(invert)\n    // make each row a little taller\n    .cellHeight(20)\n    // don't show elements that are less than 5px wide\n    .minFrameSize(2)\n    // set our custom handlers\n    .setColorMapper(memrayColorMapper)\n    .onClick(onClick)\n    .tooltip(flamegraphTooltip);\n\n  // Render the chart\n  d3.select(\"#chart\").datum(chart_data).call(chart);\n\n  // Rendering the chart can add a scroll bar, so the width may have changed.\n  chart.width(getChartWidth());\n}\n"
  },
  {
    "path": "src/memray/reporters/assets/table.js",
    "content": "import { humanFileSize, initMemoryGraph, resizeMemoryGraph } from \"./common\";\nwindow.resizeMemoryGraph = resizeMemoryGraph;\n\nfunction main() {\n  data = packed_data;\n\n  initMemoryGraph(memory_records);\n\n  const columns = [\n    {\n      title: \"Thread ID\",\n      data: \"tid\",\n    },\n    {\n      title: \"Size\",\n      data: \"size\",\n      render: function (data, type, row, meta) {\n        if (type === \"sort\" || type === \"type\") {\n          return data;\n        }\n\n        return humanFileSize(data);\n      },\n    },\n    {\n      title: \"Allocator\",\n      data: \"allocator\",\n    },\n    {\n      title: \"Allocations\",\n      data: \"n_allocations\",\n    },\n    {\n      title: \"Location\",\n      data: \"stack_trace\",\n    },\n  ];\n\n  var table = $(\"#the_table\").DataTable({\n    data: data,\n    columns: columns,\n    order: [[2, \"desc\"]],\n    pageLength: 100,\n    dom: \"<t>ip\",\n  });\n  const searchButton = $(\"#searchTerm\");\n  searchButton.on(\"input\", () => {\n    const searchTerm = $(\"#searchTerm\").val();\n    table.search(searchTerm).draw();\n  });\n  // Enable tooltips\n  $('[data-toggle-second=\"tooltip\"]').tooltip();\n  $('[data-toggle=\"tooltip\"]').tooltip();\n}\n\ndocument.addEventListener(\"DOMContentLoaded\", main);\nresizeMemoryGraph();\n"
  },
  {
    "path": "src/memray/reporters/assets/temporal_flamegraph.js",
    "content": "import { debounced } from \"./common\";\n\nimport {\n  initThreadsDropdown,\n  drawChart,\n  handleFragments,\n  onFilterUninteresting,\n  onFilterImportSystem,\n  onFilterThread,\n  onResetZoom,\n  onResize,\n  onInvert,\n  getFilteredChart,\n  getFlamegraph,\n} from \"./flamegraph_common\";\n\nvar active_plot = null;\nvar current_dimensions = null;\n\nvar parent_index_by_child_index = generateParentIndexes(packed_data.nodes);\nvar inverted_no_imports_parent_index_by_child_index = inverted\n  ? generateParentIndexes(packed_data.inverted_no_imports_nodes)\n  : null;\n\nfunction generateParentIndexes(nodes) {\n  let ret = new Array(nodes.children.length);\n  console.log(\"finding parent index for each node\");\n  for (const [parentIndex, children] of nodes.children.entries()) {\n    children.forEach((idx) => (ret[idx] = parentIndex));\n  }\n  console.assert(ret[0] === undefined, \"root node has a parent\");\n  return ret;\n}\n\nfunction generateNodeObjects(strings, nodes) {\n  console.log(\"constructing nodes\");\n  const node_objects = nodes.name.map((_, i) => ({\n    name: strings[nodes[\"name\"][i]],\n    location: [\n      strings[nodes[\"function\"][i]],\n      strings[nodes[\"filename\"][i]],\n      nodes[\"lineno\"][i],\n    ],\n    value: 0,\n    children: nodes[\"children\"][i],\n    n_allocations: 0,\n    thread_id: strings[nodes[\"thread_id\"][i]],\n    interesting: nodes[\"interesting\"][i] !== 0,\n    import_system: nodes[\"import_system\"][i] !== 0,\n  }));\n\n  console.log(\"mapping child indices to child nodes\");\n  for (const [parentIndex, node] of node_objects.entries()) {\n    node[\"children\"] = node[\"children\"].map((idx) => node_objects[idx]);\n  }\n\n  return node_objects;\n}\n\nfunction initTrees(packedData) {\n  const {\n    strings,\n    nodes,\n    inverted_no_imports_nodes,\n    unique_threads,\n    intervals,\n    no_imports_interval_list,\n  } = packedData;\n\n  const flamegraphNodeObjects = generateNodeObjects(strings, nodes);\n  const invertedNoImportsNodeObjects = inverted\n    ? generateNodeObjects(strings, inverted_no_imports_nodes)\n    : null;\n\n  flamegraphIntervals = intervals;\n  invertedNoImportsIntervals = no_imports_interval_list;\n\n  return {\n    flamegraphNodeObjects: flamegraphNodeObjects,\n    invertedNoImportsNodeObjects: invertedNoImportsNodeObjects,\n  };\n}\n\nfunction findHWMAllocations(\n  intervals,\n  node_objects,\n  hwmSnapshot,\n  parent_index_by_child_index,\n) {\n  intervals.forEach((interval) => {\n    let [allocBefore, deallocBefore, nodeIndex, count, bytes] = interval;\n\n    if (\n      allocBefore <= hwmSnapshot &&\n      (deallocBefore === null || deallocBefore > hwmSnapshot)\n    ) {\n      while (nodeIndex !== undefined) {\n        node_objects[nodeIndex].n_allocations += count;\n        node_objects[nodeIndex].value += bytes;\n        nodeIndex = parent_index_by_child_index[nodeIndex];\n      }\n    }\n  });\n}\n\nfunction findLeakedAllocations(\n  intervals,\n  node_objects,\n  rangeStart,\n  rangeEnd,\n  parent_index_by_child_index,\n) {\n  intervals.forEach((interval) => {\n    let [allocBefore, deallocBefore, nodeIndex, count, bytes] = interval;\n\n    if (\n      allocBefore >= rangeStart &&\n      allocBefore <= rangeEnd &&\n      (deallocBefore === null || deallocBefore > rangeEnd)\n    ) {\n      while (nodeIndex !== undefined) {\n        node_objects[nodeIndex].n_allocations += count;\n        node_objects[nodeIndex].value += bytes;\n        nodeIndex = parent_index_by_child_index[nodeIndex];\n      }\n    }\n  });\n}\n\nfunction packedDataToTree(packedData, rangeStart, rangeEnd) {\n  const { flamegraphNodeObjects, invertedNoImportsNodeObjects } =\n    initTrees(packedData);\n\n  const hwms = packedData.high_water_mark_by_snapshot;\n  if (hwms) {\n    console.log(\"finding highest high water mark in range\");\n    let hwmSnapshot = rangeStart;\n    let hwmBytes = hwms[rangeStart];\n    for (let i = rangeStart; i <= rangeEnd; ++i) {\n      if (hwms[i] > hwmBytes) {\n        hwmBytes = hwms[i];\n        hwmSnapshot = i;\n      }\n    }\n    console.log(\n      \"highest water mark between \" +\n        rangeStart +\n        \" and \" +\n        rangeEnd +\n        \" is \" +\n        hwmBytes +\n        \" at \" +\n        hwmSnapshot,\n    );\n\n    let plotUpdate = { shapes: [] };\n    let startTime, endTime;\n    if (hwmSnapshot == memory_records.length) {\n      // HWM was after the last snapshot. Highlight 10ms past it.\n      // Widen the x-axis range so the highlight is shown.\n      plotUpdate[\"xaxis.range[1]\"] = new Date(memory_records.at(-1)[0] + 10);\n      startTime = new Date(memory_records.at(-1)[0]);\n      endTime = new Date(memory_records.at(-1)[0] + 10);\n    } else if (hwmSnapshot == 0) {\n      // HWM was before the first snapshot. Highlight 10ms before it.\n      // Widen the x-axis range so the highlight is shown.\n      plotUpdate[\"xaxis.range[0]\"] = new Date(memory_records[0][0] - 10);\n      startTime = new Date(memory_records[0][0] - 10);\n      endTime = new Date(memory_records[0][0]);\n    } else {\n      // HWM was between two snapshots. Highlight from one to the other.\n      startTime = new Date(memory_records[hwmSnapshot - 1][0]);\n      endTime = new Date(memory_records[hwmSnapshot][0]);\n    }\n\n    plotUpdate[\"shapes\"] = [\n      {\n        type: \"rect\",\n        xref: \"x\",\n        yref: \"paper\",\n        x0: startTime,\n        y0: 0,\n        x1: endTime,\n        y1: 1,\n        fillcolor: \"#fbff00\",\n        opacity: 0.2,\n        line: {\n          width: 0,\n        },\n      },\n    ];\n    Plotly.relayout(\"plot\", plotUpdate);\n\n    // We could binary search rather than using a linear scan...\n    console.log(\"finding hwm allocations\");\n    findHWMAllocations(\n      flamegraphIntervals,\n      flamegraphNodeObjects,\n      hwmSnapshot,\n      parent_index_by_child_index,\n    );\n    if (inverted) {\n      findHWMAllocations(\n        invertedNoImportsIntervals,\n        invertedNoImportsNodeObjects,\n        hwmSnapshot,\n        inverted_no_imports_parent_index_by_child_index,\n      );\n    }\n  } else {\n    // We could binary search rather than using a linear scan...\n    console.log(\"finding leaked allocations\");\n    findLeakedAllocations(\n      flamegraphIntervals,\n      flamegraphNodeObjects,\n      rangeStart,\n      rangeEnd,\n      parent_index_by_child_index,\n    );\n    if (inverted) {\n      findLeakedAllocations(\n        invertedNoImportsIntervals,\n        invertedNoImportsNodeObjects,\n        rangeStart,\n        rangeEnd,\n        inverted_no_imports_parent_index_by_child_index,\n      );\n    }\n  }\n\n  flamegraphNodeObjects.forEach((node) => {\n    node.children = node.children.filter((node) => node.n_allocations > 0);\n  });\n\n  if (inverted) {\n    invertedNoImportsNodeObjects.forEach((node) => {\n      node.children = node.children.filter((node) => node.n_allocations > 0);\n    });\n  }\n\n  flamegraphData = flamegraphNodeObjects[0];\n  invertedNoImportsData = inverted ? invertedNoImportsNodeObjects[0] : null;\n}\n\nfunction initMemoryGraph(memory_records) {\n  console.log(\"init memory graph\");\n  const time = memory_records.map((a) => new Date(a[0]));\n  const resident_size = memory_records.map((a) => a[1]);\n  const heap_size = memory_records.map((a) => a[2]);\n  const mode = memory_records.length > 1 ? \"lines\" : \"markers\";\n\n  var resident_size_plot = {\n    x: time,\n    y: resident_size,\n    mode: mode,\n    name: \"Resident size\",\n  };\n\n  var heap_size_plot = {\n    x: time,\n    y: heap_size,\n    mode: mode,\n    name: \"Heap size\",\n  };\n\n  var plot_data = [resident_size_plot, heap_size_plot];\n  var config = {\n    responsive: true,\n    displayModeBar: false,\n  };\n  var layout = {\n    xaxis: {\n      title: {\n        text: \"Time\",\n      },\n      rangeslider: {\n        visible: true,\n      },\n    },\n    yaxis: {\n      title: {\n        text: \"Memory Size\",\n      },\n      tickformat: \".4~s\",\n      exponentformat: \"B\",\n      ticksuffix: \"B\",\n    },\n  };\n\n  Plotly.newPlot(\"plot\", plot_data, layout, config).then((plot) => {\n    console.assert(active_plot === null);\n    active_plot = plot;\n  });\n}\n\nfunction showLoadingAnimation() {\n  console.log(\"showLoadingAnimation\");\n  document.getElementById(\"loading\").style.display = \"block\";\n  document.getElementById(\"overlay\").style.display = \"block\";\n}\n\nfunction hideLoadingAnimation() {\n  console.log(\"hideLoadingAnimation\");\n  document.getElementById(\"loading\").style.display = \"none\";\n  document.getElementById(\"overlay\").style.display = \"none\";\n}\n\nfunction refreshFlamegraph(event) {\n  console.log(\"refreshing flame graph!\");\n\n  let request_data = getRangeData(event);\n  console.log(\"range data: \" + JSON.stringify(request_data));\n\n  if (\n    current_dimensions != null &&\n    JSON.stringify(request_data) === JSON.stringify(current_dimensions)\n  ) {\n    return;\n  }\n\n  console.log(\"showing loading animation\");\n  showLoadingAnimation();\n\n  current_dimensions = request_data;\n\n  console.log(\"finding range of relevant snapshot\");\n\n  let idx0 = 0;\n  let idx1 = memory_records.length;\n\n  if (request_data) {\n    const t0 = new Date(request_data.string1).getTime();\n    const t0_idx = memory_records.findIndex((rec) => rec[0] >= t0);\n    if (t0_idx != -1) idx0 = t0_idx;\n\n    const t1 = new Date(request_data.string2).getTime();\n    const t1_idx = memory_records.findIndex((rec) => rec[0] > t1);\n    if (t1_idx != -1) idx1 = t1_idx;\n  }\n\n  console.log(\"start index is \" + idx0);\n  console.log(\"end index is \" + idx1);\n  console.log(\"first possible index is 0\");\n  console.log(\"last possible index is \" + memory_records.length);\n\n  console.log(\"constructing tree\");\n  packedDataToTree(packed_data, idx0, idx1);\n\n  data = inverted && hideImports ? invertedNoImportsData : flamegraphData;\n  intervals =\n    inverted && hideImports ? invertedNoImportsIntervals : flamegraphIntervals;\n\n  console.log(\"total allocations in range: \" + data.n_allocations);\n  console.log(\"total bytes in range: \" + data.value);\n\n  console.log(\"drawing chart\");\n  getFilteredChart().drawChart(data);\n  console.log(\"hiding loading animation\");\n  hideLoadingAnimation();\n}\n\nfunction getRangeData(event) {\n  console.log(\"getRangeData\");\n  let request_data = {};\n  if (event.hasOwnProperty(\"xaxis.range[0]\")) {\n    request_data = {\n      string1: event[\"xaxis.range[0]\"],\n      string2: event[\"xaxis.range[1]\"],\n    };\n  } else if (event.hasOwnProperty(\"xaxis.range\")) {\n    request_data = {\n      string1: event[\"xaxis.range\"][0],\n      string2: event[\"xaxis.range\"][1],\n    };\n  } else if (active_plot !== null) {\n    let the_range = active_plot.layout.xaxis.range;\n    request_data = {\n      string1: the_range[0],\n      string2: the_range[1],\n    };\n  } else {\n    return;\n  }\n  return request_data;\n}\n\nvar debounce = null;\nfunction refreshFlamegraphDebounced(event) {\n  console.log(\"refreshFlamegraphDebounced\");\n  if (debounce) {\n    clearTimeout(debounce);\n  }\n  debounce = setTimeout(function () {\n    refreshFlamegraph(event);\n  }, 500);\n}\n\n// Main entrypoint\nfunction main() {\n  console.log(\"main\");\n\n  const unique_threads = packed_data.unique_threads.map(\n    (tid) => packed_data.strings[tid],\n  );\n  initThreadsDropdown({ unique_threads: unique_threads }, merge_threads);\n\n  initMemoryGraph(memory_records);\n\n  // Draw the initial flame graph\n  refreshFlamegraph({});\n\n  // Set zoom to correct element\n  if (location.hash) {\n    handleFragments();\n  }\n\n  // Setup event handlers\n  document.getElementById(\"icicles\").onchange = onInvert;\n  document.getElementById(\"flames\").onchange = onInvert;\n  document.getElementById(\"resetZoomButton\").onclick = onResetZoom;\n  document.getElementById(\"resetThreadFilterItem\").onclick = onFilterThread;\n  let hideUninterestingCheckBox = document.getElementById(\"hideUninteresting\");\n  hideUninterestingCheckBox.onclick = onFilterUninteresting.bind(this);\n  let hideImportSystemCheckBox = document.getElementById(\"hideImportSystem\");\n  hideImportSystemCheckBox.onclick = onFilterImportSystem.bind(this);\n  // Enable filtering by default\n  onFilterUninteresting.bind(this)();\n\n  document.onkeyup = (event) => {\n    if (event.code == \"Escape\") {\n      onResetZoom();\n    }\n  };\n  document.getElementById(\"searchTerm\").addEventListener(\"input\", () => {\n    const termElement = document.getElementById(\"searchTerm\");\n    getFlamegraph().search(termElement.value);\n  });\n\n  window.addEventListener(\"popstate\", handleFragments);\n  window.addEventListener(\"resize\", debounced(onResize));\n\n  // Enable tooltips\n  $('[data-toggle-second=\"tooltip\"]').tooltip();\n  $('[data-toggle=\"tooltip\"]').tooltip();\n\n  // Set up the reload handler\n  console.log(\"setup reload handler\");\n  document\n    .getElementById(\"plot\")\n    .on(\"plotly_relayout\", refreshFlamegraphDebounced);\n\n  // Enable toasts\n  var toastElList = [].slice.call(document.querySelectorAll(\".toast\"));\n  var toastList = toastElList.map(function (toastEl) {\n    return new bootstrap.Toast(toastEl, { delay: 10000 });\n  });\n  toastList.forEach((toast) => toast.show());\n}\n\ndocument.addEventListener(\"DOMContentLoaded\", main);\n"
  },
  {
    "path": "src/memray/reporters/common.py",
    "content": "from typing import Union\n\nfrom memray._memray import AllocationRecord\nfrom memray._memray import TemporalAllocationRecord\n\n\ndef format_thread_name(\n    record: Union[AllocationRecord, TemporalAllocationRecord]\n) -> str:\n    if record.tid == -1:\n        return \"merged thread\"\n    name = record.thread_name\n    thread_id = hex(record.tid)\n    return f\"{thread_id} ({name})\" if name else f\"{thread_id}\"\n"
  },
  {
    "path": "src/memray/reporters/flamegraph.py",
    "content": "import collections\nimport html\nimport itertools\nimport linecache\nimport sys\nfrom typing import Any\nfrom typing import Dict\nfrom typing import Iterable\nfrom typing import List\nfrom typing import Optional\nfrom typing import Sequence\nfrom typing import Set\nfrom typing import TextIO\nfrom typing import Tuple\nfrom typing import TypeVar\nfrom typing import Union\nfrom typing import cast\n\nif sys.version_info >= (3, 8):\n    from typing import TypedDict\nelse:\n    from typing_extensions import TypedDict\n\nfrom memray import AllocationRecord\nfrom memray import MemorySnapshot\nfrom memray import Metadata\nfrom memray._memray import Interval\nfrom memray._memray import TemporalAllocationRecord\nfrom memray.reporters.common import format_thread_name\nfrom memray.reporters.frame_tools import StackFrame\nfrom memray.reporters.frame_tools import is_cpython_internal\nfrom memray.reporters.frame_tools import is_frame_from_import_system\nfrom memray.reporters.frame_tools import is_frame_interesting\nfrom memray.reporters.templates import render_report\n\nPythonStackElement = Tuple[str, str, int]\nMAX_STACKS = int(sys.getrecursionlimit() // 2.5)\n\nT = TypeVar(\"T\")\n\n\nclass RecordData(TypedDict):\n    thread_name: str\n    size: Optional[int]\n    n_allocations: Optional[int]\n    intervals: Optional[List[Interval]]\n\n\nclass FrameNodeDict(TypedDict):\n    name: str\n    location: Tuple[str, str, int]\n    value: int\n    children: List[int]\n    n_allocations: int\n    interesting: bool\n    thread_id: str\n    import_system: bool\n\n\nclass FlameGraphNodeDict(TypedDict):\n    name: List[int]\n    function: List[int]\n    filename: List[int]\n    lineno: List[int]\n    children: List[List[int]]\n    value: List[int]\n    n_allocations: List[int]\n    thread_id: List[int]\n    interesting: List[int]\n    import_system: List[int]\n\n\ndef create_framegraph_node_from_stack_frame(\n    stack_frame: StackFrame,\n    thread_id: str,\n    import_system: bool = False,\n) -> FrameNodeDict:\n    function, filename, lineno = stack_frame\n\n    name = (\n        # Use the source file line.\n        linecache.getline(filename, lineno)\n        # Or just describe where it is from\n        or f\"{function} at {filename}:{lineno}\"\n    )\n    return {\n        \"name\": name,\n        \"location\": (html.escape(function), html.escape(filename), lineno),\n        \"value\": 0,\n        \"children\": [],\n        \"n_allocations\": 0,\n        \"interesting\": (\n            is_frame_interesting(stack_frame)\n            and not is_frame_from_import_system(stack_frame)\n        ),\n        \"thread_id\": thread_id,\n        \"import_system\": import_system,\n    }\n\n\nclass StringRegistry:\n    def __init__(self) -> None:\n        self.strings: List[str] = []\n        self._index_by_string: Dict[str, int] = {}\n\n    def register(self, string: str) -> int:\n        idx = self._index_by_string.setdefault(string, len(self.strings))\n        if idx == len(self.strings):\n            self.strings.append(string)\n        return idx\n\n\nclass FlameGraphReporter:\n    def __init__(\n        self,\n        data: Dict[str, Any],\n        *,\n        memory_records: Iterable[MemorySnapshot],\n    ) -> None:\n        super().__init__()\n        self.data = data\n        self.memory_records = memory_records\n\n    @classmethod\n    def generate_nodes(\n        cls,\n        frames: List[FrameNodeDict],\n        all_strings: StringRegistry,\n        temporal: bool,\n    ) -> FlameGraphNodeDict:\n        nodes = cast(FlameGraphNodeDict, collections.defaultdict(list))\n        for frame in frames:\n            nodes[\"name\"].append(all_strings.register(frame[\"name\"]))\n            nodes[\"function\"].append(all_strings.register(frame[\"location\"][0]))\n            nodes[\"filename\"].append(all_strings.register(frame[\"location\"][1]))\n            nodes[\"lineno\"].append(frame[\"location\"][2])\n            nodes[\"children\"].append(frame[\"children\"])\n            if not temporal:\n                nodes[\"value\"].append(frame[\"value\"])\n                nodes[\"n_allocations\"].append(frame[\"n_allocations\"])\n            nodes[\"thread_id\"].append(all_strings.register(frame[\"thread_id\"]))\n            nodes[\"interesting\"].append(int(frame[\"interesting\"]))\n            nodes[\"import_system\"].append(int(frame[\"import_system\"]))\n        return nodes\n\n    @classmethod\n    def generate_frames(\n        cls,\n        stack_it: Iterable[Tuple[int, PythonStackElement]],\n        frames: List[FrameNodeDict],\n        node_index_by_key: Dict[Tuple[int, StackFrame, str], int],\n        record: RecordData,\n        inverted: bool,\n        interval_list: List[Tuple[int, Optional[int], int, int, int]],\n    ) -> None:\n        current_frame_id = 0\n        current_frame = frames[0]\n\n        if record[\"size\"] is not None:\n            current_frame[\"value\"] += record[\"size\"]\n        if record[\"n_allocations\"] is not None:\n            current_frame[\"n_allocations\"] += record[\"n_allocations\"]\n\n        num_skipped_frames = 0\n        is_import_system = False\n\n        for index, stack_frame in stack_it:\n            node_key = (current_frame_id, stack_frame, record[\"thread_name\"])\n            if node_key not in node_index_by_key:\n                if is_cpython_internal(stack_frame):\n                    num_skipped_frames += 1\n                    continue\n                # update import_system only if we're generting normal flamegraph\n                if not inverted and not is_import_system:\n                    is_import_system = is_frame_from_import_system(stack_frame)\n\n                new_node_id = len(frames)\n                node_index_by_key[node_key] = new_node_id\n                current_frame[\"children\"].append(new_node_id)\n                frames.append(\n                    create_framegraph_node_from_stack_frame(\n                        stack_frame,\n                        import_system=is_import_system,\n                        thread_id=record[\"thread_name\"],\n                    )\n                )\n            current_frame_id = node_index_by_key[node_key]\n            current_frame = frames[current_frame_id]\n            is_import_system = current_frame[\"import_system\"]\n\n            if record[\"size\"] is not None:\n                current_frame[\"value\"] += record[\"size\"]\n            if record[\"n_allocations\"] is not None:\n                current_frame[\"n_allocations\"] += record[\"n_allocations\"]\n\n            if index - num_skipped_frames > MAX_STACKS:\n                current_frame[\"name\"] = \"<STACK TOO DEEP>\"\n                current_frame[\"location\"] = (\"...\", \"...\", 0)\n                break\n\n        if record[\"intervals\"] is not None:\n            interval_list.extend(\n                (\n                    interval.allocated_before_snapshot,\n                    interval.deallocated_before_snapshot,\n                    current_frame_id,\n                    interval.n_allocations,\n                    interval.n_bytes,\n                )\n                for interval in record[\"intervals\"]\n            )\n\n    @classmethod\n    def _create_root_node(cls) -> FrameNodeDict:\n        return {\n            \"name\": \"<root>\",\n            \"location\": (html.escape(\"<tracker>\"), \"<b>memray</b>\", 0),\n            \"value\": 0,\n            \"children\": [],\n            \"n_allocations\": 0,\n            \"thread_id\": \"0x0\",\n            \"interesting\": True,\n            \"import_system\": False,\n        }\n\n    @classmethod\n    def _drop_import_system_frames(\n        cls,\n        stack: Sequence[PythonStackElement],\n    ) -> Iterable[PythonStackElement]:\n        return reversed(\n            list(\n                itertools.takewhile(\n                    lambda e: not is_frame_from_import_system(e),\n                    reversed(stack),\n                )\n            )\n        )\n\n    @classmethod\n    def _from_any_snapshot(\n        cls,\n        allocations: Iterable[Union[AllocationRecord, TemporalAllocationRecord]],\n        *,\n        memory_records: Iterable[MemorySnapshot],\n        native_traces: bool,\n        temporal: bool,\n        inverted: Optional[bool] = None,\n    ) -> \"FlameGraphReporter\":\n        inverted = False if inverted is None else inverted\n\n        frames: List[FrameNodeDict] = [cls._create_root_node()]\n        inverted_no_imports_frames: List[FrameNodeDict] = []\n\n        if inverted:\n            inverted_no_imports_frames = [cls._create_root_node()]\n\n        interval_list: List[Tuple[int, Optional[int], int, int, int]] = []\n        no_imports_interval_list: List[Tuple[int, Optional[int], int, int, int]] = []\n\n        NodeKey = Tuple[int, StackFrame, str]\n        node_index_by_key: Dict[NodeKey, int] = {}\n        inverted_no_imports_node_index_by_key: Dict[NodeKey, int] = {}\n\n        unique_threads: Set[str] = set()\n        for record in allocations:\n            unique_threads.add(format_thread_name(record))\n\n            record_data: RecordData\n            if temporal:\n                assert isinstance(record, TemporalAllocationRecord)\n                record_data = {\n                    \"thread_name\": format_thread_name(record),\n                    \"intervals\": record.intervals,\n                    \"size\": None,\n                    \"n_allocations\": None,\n                }\n            else:\n                assert not isinstance(record, TemporalAllocationRecord)\n                record_data = {\n                    \"thread_name\": format_thread_name(record),\n                    \"intervals\": None,\n                    \"size\": record.size,\n                    \"n_allocations\": record.n_allocations,\n                }\n\n            stack = (\n                tuple(record.hybrid_stack_trace())\n                if native_traces\n                else record.stack_trace()\n            )\n\n            if not inverted:\n                # normal flamegraph\n                cls.generate_frames(\n                    stack_it=enumerate(reversed(stack)),\n                    frames=frames,\n                    node_index_by_key=node_index_by_key,\n                    record=record_data,\n                    inverted=inverted,\n                    interval_list=interval_list,\n                )\n            else:\n                # inverted flamegraph tree with all nodes\n                cls.generate_frames(\n                    stack_it=enumerate(stack),\n                    frames=frames,\n                    node_index_by_key=node_index_by_key,\n                    record=record_data,\n                    inverted=inverted,\n                    interval_list=interval_list,\n                )\n\n                # inverted flamegraph tree without import system nodes\n                cls.generate_frames(\n                    stack_it=enumerate(cls._drop_import_system_frames(stack)),\n                    frames=inverted_no_imports_frames,\n                    node_index_by_key=inverted_no_imports_node_index_by_key,\n                    record=record_data,\n                    inverted=inverted,\n                    interval_list=no_imports_interval_list,\n                )\n\n        all_strings = StringRegistry()\n        nodes = cls.generate_nodes(\n            frames=frames, all_strings=all_strings, temporal=temporal\n        )\n        inverted_no_imports_nodes = cls.generate_nodes(\n            frames=inverted_no_imports_frames,\n            all_strings=all_strings,\n            temporal=temporal,\n        )\n\n        data = {\n            \"unique_threads\": tuple(\n                all_strings.register(t) for t in sorted(unique_threads)\n            ),\n            \"nodes\": nodes,\n            \"inverted_no_imports_nodes\": inverted_no_imports_nodes,\n            \"strings\": all_strings.strings,\n        }\n\n        if temporal:\n            data[\"intervals\"] = interval_list\n            data[\"no_imports_interval_list\"] = no_imports_interval_list\n\n        return cls(data, memory_records=memory_records)\n\n    @classmethod\n    def from_snapshot(\n        cls,\n        allocations: Iterable[AllocationRecord],\n        *,\n        memory_records: Iterable[MemorySnapshot],\n        native_traces: bool,\n        inverted: Optional[bool] = None,\n    ) -> \"FlameGraphReporter\":\n        return cls._from_any_snapshot(\n            allocations,\n            memory_records=memory_records,\n            native_traces=native_traces,\n            temporal=False,\n            inverted=inverted,\n        )\n\n    @classmethod\n    def from_temporal_snapshot(\n        cls,\n        allocations: Iterable[TemporalAllocationRecord],\n        *,\n        memory_records: Iterable[MemorySnapshot],\n        native_traces: bool,\n        high_water_mark_by_snapshot: Optional[List[int]],\n        inverted: Optional[bool] = None,\n    ) -> \"FlameGraphReporter\":\n        ret = cls._from_any_snapshot(\n            allocations,\n            memory_records=memory_records,\n            native_traces=native_traces,\n            temporal=True,\n            inverted=inverted,\n        )\n        ret.data[\"high_water_mark_by_snapshot\"] = high_water_mark_by_snapshot\n        return ret\n\n    def render(\n        self,\n        outfile: TextIO,\n        metadata: Metadata,\n        show_memory_leaks: bool,\n        merge_threads: bool,\n        inverted: bool,\n        no_web: bool = False,\n    ) -> None:\n        kind = \"temporal_flamegraph\" if \"intervals\" in self.data else \"flamegraph\"\n        html_code = render_report(\n            kind=kind,\n            data=self.data,\n            metadata=metadata,\n            memory_records=self.memory_records,\n            show_memory_leaks=show_memory_leaks,\n            merge_threads=merge_threads,\n            inverted=inverted,\n            no_web=no_web,\n        )\n        print(html_code, file=outfile)\n"
  },
  {
    "path": "src/memray/reporters/frame_tools.py",
    "content": "\"\"\"Tools for processing and filtering stack frames.\"\"\"\nimport functools\nimport re\nfrom typing import Tuple\n\nSymbol = str\nFile = str\nLineno = int\nStackFrame = Tuple[Symbol, File, Lineno]\n\nRE_CPYTHON_PATHS = re.compile(r\"(Include|Objects|Modules|Python|cpython).*\\.[c|h]$\")\n\nSYMBOL_IGNORELIST = {\n    \"PyObject_Call\",\n    \"call_function\",\n    \"classmethoddescr_call\",\n    \"cmpwrapper_call\",\n    \"do_call_core\",\n    \"fast_function\",\n    \"function_call\",\n    \"function_code_fastcall\",\n    \"instance_call\",\n    \"instancemethod_call\",\n    \"instancemethod_call\",\n    \"methoddescr_call\",\n    \"proxy_call\",\n    \"slot_tp_call\",\n    \"trace_call_function\",\n    \"type_call\",\n    \"weakref_call\",\n    \"wrap_call\",\n    \"wrapper_call\",\n    \"wrapperdescr_call\",\n}\n\n\n@functools.lru_cache(maxsize=1000)\ndef _is_cpython_internal_symbol(symbol: str, file: str) -> bool:\n    if \"PyEval_EvalFrameEx\" in symbol or \"_PyEval_EvalFrameDefault\" in symbol:\n        is_candidate = True\n    elif symbol.startswith(\"_TAIL_CALL_\") and \".llvm.\" in symbol:\n        # Python 3.14 tail call interpreter uses LLVM-generated functions\n        is_candidate = True\n    elif symbol.startswith((\"PyEval\", \"_Py\")):\n        is_candidate = True\n    elif \"vectorcall\" in symbol.lower():\n        is_candidate = True\n    elif symbol in SYMBOL_IGNORELIST:\n        is_candidate = True\n    elif \"Objects/call.c\" in file:\n        is_candidate = True\n    else:\n        is_candidate = False\n\n    if is_candidate:\n        return re.search(RE_CPYTHON_PATHS, file) is not None\n    return False\n\n\ndef is_cpython_internal(frame: StackFrame) -> bool:\n    symbol, file, _ = frame\n    return _is_cpython_internal_symbol(symbol, file)\n\n\ndef is_frame_interesting(frame: StackFrame) -> bool:\n    function, file, _ = frame\n\n    if file.endswith(\"runpy.py\") or file == \"<frozen runpy>\":\n        return False\n\n    return not _is_cpython_internal_symbol(function, file)\n\n\ndef is_frame_from_import_system(frame: StackFrame) -> bool:\n    function, file, _ = frame\n    if \"frozen importlib\" in file:\n        return True\n    if function in {\"import_name\", \"import_from\", \"import_all_from\"} and file.endswith(\n        \"ceval.c\"\n    ):\n        return True\n    return False\n"
  },
  {
    "path": "src/memray/reporters/stats.py",
    "content": "import datetime\nimport json\nimport math\nfrom collections import Counter\nfrom dataclasses import asdict\nfrom pathlib import Path\nfrom typing import Any\nfrom typing import Dict\nfrom typing import Iterator\nfrom typing import List\nfrom typing import Optional\nfrom typing import Tuple\n\nimport rich\n\nfrom memray._memray import size_fmt\nfrom memray._stats import Stats\n\nPythonStackElement = Tuple[str, str, int]\n\n\ndef get_histogram_databins(data: Dict[int, int], bins: int) -> List[Tuple[int, int]]:\n    if bins <= 0:\n        raise ValueError(f\"Invalid input bins={bins}, should be greater than 0\")\n\n    low = math.log(min(filter(None, data)))\n    high = math.log(max(data))\n    if low == high:\n        low = low / 2\n    step = (high - low) / bins\n\n    # Determine the upper bound in bytes for each bin\n    steps = [int(math.exp(low + step * (i + 1))) for i in range(bins)]\n    dist: Dict[int, int] = Counter()\n    for size, count in data.items():\n        bucket = min(int((math.log(size) - low) // step), bins - 1) if size else 0\n        dist[bucket] += count\n    return [(steps[b], dist[b]) for b in range(bins)]\n\n\ndef describe_histogram_databins(\n    databins: List[Tuple[int, int]]\n) -> List[Dict[str, int]]:\n    ret: List[Dict[str, int]] = []\n    start = 0\n    for i, (end, count) in enumerate(databins):\n        # The max size for the last bucket is inclusive, not exclusive\n        adjustment = 1 if i != len(databins) - 1 else 0\n        ret.append({\"min_bytes\": start, \"max_bytes\": end - adjustment, \"count\": count})\n        start = end\n    return ret\n\n\ndef draw_histogram(\n    data: Dict[int, int], bins: int, *, hist_scale_factor: int = 25\n) -> str:\n    \"\"\"\n    @param data: list of allocation sizes\n    @param bins: number of bins in the histogram\n    @param hist_scale_factor: length of the largest bar in the histogram (# of chars)\n    \"\"\"\n    if len(data) == 0:\n        return \"<no data for histogram>\"\n    if bins <= 0:\n        raise ValueError(f\"Invalid input bins={bins}, should be greater than 0\")\n    if hist_scale_factor <= 0:\n        raise ValueError(\n            f\"Invalid input hist_scale_factor={hist_scale_factor},\"\n            \" should be greater than 0\"\n        )\n\n    data_bins = get_histogram_databins(data, bins=bins)\n    max_data_bin = max([t[1] for t in data_bins])\n    scaled_data_bins = [\n        math.ceil((v / max_data_bin) * hist_scale_factor) for _, v in data_bins\n    ]\n\n    size_max_width = 9  # ###.###XB\n    freq_max_width = max([len(str(f[1])) for f in data_bins])\n    hist_width_total = (\n        len(\"<=\")\n        + size_max_width\n        + len(\" :\")\n        + freq_max_width\n        + len(\" \")\n        + hist_scale_factor\n    )\n\n    result = []\n    result.append(f\"min: {size_fmt(min(data))}\")\n    result.append(\"\\n\\t\")\n    result.append(\"-\" * hist_width_total)\n    result.append(\"\\n\\t\")\n    for i in range(len(scaled_data_bins)):\n        rel_op = \"<=\" if i == len(scaled_data_bins) - 1 else \"< \"\n        result.append(f\"{rel_op}{size_fmt(data_bins[i][0]):<{size_max_width}}:\")\n        result.append(f\" {data_bins[i][1]:>{freq_max_width}} \")\n        result.append(\"▇\" * scaled_data_bins[i])\n        result.append(\"\\n\\t\")\n    result.append(\"-\" * hist_width_total)\n    result.append(f\"\\n\\tmax: {size_fmt(max(data))}\")\n\n    return \"\".join(result)\n\n\nclass StatsReporter:\n    def __init__(self, stats: Stats, num_largest: int):\n        self._stats = stats\n        if num_largest < 1:\n            raise ValueError(f\"Invalid input num_largest={num_largest}, should be >=1\")\n        self.num_largest = num_largest\n\n    def render(self, json_output_file: Optional[Path] = None) -> None:\n        histogram_params = {\n            \"num_bins\": 10,\n            \"histogram_scale_factor\": 25,\n        }\n        if json_output_file:\n            self._render_to_json(histogram_params, json_output_file)\n        else:\n            self._render_to_terminal(histogram_params)\n\n    def _render_to_terminal(self, histogram_params: Dict[str, int]) -> None:\n        rich.print(\"📏 [bold]Total allocations:[/]\")\n        print(f\"\\t{self._stats.total_num_allocations}\")\n\n        print()\n        rich.print(\"📦 [bold]Total memory allocated:[/]\")\n        print(f\"\\t{size_fmt(self._stats.total_memory_allocated)}\")\n\n        print()\n        rich.print(\"📈 [bold]Peak memory usage:[/]\")\n        print(f\"\\t{size_fmt(self._stats.metadata.peak_memory)}\")\n\n        print()\n\n        rich.print(\"📊 [bold]Histogram of allocation size:[/]\")\n        histogram = draw_histogram(\n            self._stats.allocation_count_by_size,\n            histogram_params[\"num_bins\"],\n            hist_scale_factor=histogram_params[\"histogram_scale_factor\"],\n        )\n        print(f\"\\t{histogram}\")\n\n        print()\n        rich.print(\"📂 [bold]Allocator type distribution:[/]\")\n        for allocator_name, count in self._get_allocator_type_distribution():\n            print(f\"\\t {allocator_name}: {count}\")\n\n        print()\n        rich.print(\n            f\"🥇 [bold]Top {self.num_largest} largest allocating locations (by size):[/]\"\n        )\n        for location, size in self._get_top_allocations_by_size():\n            print(f\"\\t- {self._format_location(location)} -> {size_fmt(size)}\")\n\n        print()\n        rich.print(\n            f\"🥇 [bold]Top {self.num_largest} largest allocating \"\n            \"locations (by number of allocations):[/]\"\n        )\n        for location, count in self._get_top_allocations_by_count():\n            print(f\"\\t- {self._format_location(location)} -> {count}\")\n\n    def _render_to_json(self, histogram_params: Dict[str, int], out_path: Path) -> None:\n        alloc_size_hist = describe_histogram_databins(\n            get_histogram_databins(\n                self._stats.allocation_count_by_size, bins=histogram_params[\"num_bins\"]\n            )\n        )\n\n        metadata = asdict(self._stats.metadata)\n        for name, val in metadata.items():\n            if isinstance(val, datetime.datetime):\n                metadata[name] = str(val)\n\n        data: Dict[str, Any] = {\n            \"total_num_allocations\": self._stats.total_num_allocations,\n            \"total_bytes_allocated\": self._stats.total_memory_allocated,\n            \"allocation_size_histogram\": alloc_size_hist,\n            \"allocator_type_distribution\": dict(\n                self._get_allocator_type_distribution()\n            ),\n            \"top_allocations_by_size\": [\n                {\"location\": self._format_location(location), \"size\": size}\n                for location, size in self._get_top_allocations_by_size()\n            ],\n            \"top_allocations_by_count\": [\n                {\"location\": self._format_location(location), \"count\": count}\n                for location, count in self._get_top_allocations_by_count()\n            ],\n            \"metadata\": metadata,\n        }\n\n        with open(out_path, \"w\") as f:\n            json.dump(data, f, indent=2)\n\n    @staticmethod\n    def _format_location(loc: Tuple[str, str, int]) -> str:\n        function, file, line = loc\n        if function == \"<unknown>\":\n            return \"<stack trace unavailable>\"\n        return f\"{function}:{file}:{line}\"\n\n    def _get_top_allocations_by_size(self) -> Iterator[Tuple[PythonStackElement, int]]:\n        for location, size in self._stats.top_locations_by_size:\n            yield (location, size)\n\n    def _get_top_allocations_by_count(self) -> Iterator[Tuple[PythonStackElement, int]]:\n        for location, count in self._stats.top_locations_by_count:\n            yield (location, count)\n\n    def _get_allocator_type_distribution(self) -> Iterator[Tuple[str, int]]:\n        for allocator_name, count in sorted(\n            self._stats.allocation_count_by_allocator.items(),\n            key=lambda item: item[1],\n            reverse=True,\n        ):\n            yield (allocator_name, count)\n"
  },
  {
    "path": "src/memray/reporters/summary.py",
    "content": "import os\nfrom typing import IO\nfrom typing import Iterable\nfrom typing import Optional\n\nfrom rich import print as rprint\nfrom rich.markup import escape\nfrom rich.table import Column\nfrom rich.table import Table\n\nfrom memray import AllocationRecord\nfrom memray._memray import size_fmt\nfrom memray.reporters.tui import aggregate_allocations\n\nMAX_MEMORY_RATIO = 0.95\nDEFAULT_TERMINAL_LINES = 24\n\n\ndef _get_terminal_lines() -> int:\n    try:\n        return os.get_terminal_size().lines\n    except OSError:\n        return DEFAULT_TERMINAL_LINES\n\n\ndef _size_to_color(proportion_of_total: float) -> str:\n    if proportion_of_total > 0.6:\n        return \"red\"\n    elif proportion_of_total > 0.2:\n        return \"yellow\"\n    elif proportion_of_total > 0.05:\n        return \"green\"\n    else:\n        return \"bright_green\"\n\n\nclass SummaryReporter:\n    KEY_TO_COLUMN_NAME = {\n        1: \"total_memory\",\n        2: \"total_memory\",\n        3: \"own_memory\",\n        4: \"own_memory\",\n        5: \"n_allocations\",\n    }\n\n    N_COLUMNS = len(KEY_TO_COLUMN_NAME)\n\n    def __init__(self, data: Iterable[AllocationRecord], native: bool):\n        snapshot = tuple(data)\n        self.current_memory_size = sum(record.size for record in snapshot)\n        self.total_allocations = sum(record.n_allocations for record in snapshot)\n        self.snapshot_data = aggregate_allocations(\n            snapshot,\n            MAX_MEMORY_RATIO * self.current_memory_size,\n            native,\n        )\n\n    @classmethod\n    def from_snapshot(\n        cls, allocations: Iterable[AllocationRecord], native: bool = False\n    ) -> \"SummaryReporter\":\n        return cls(allocations, native=native)\n\n    def render(\n        self,\n        sort_column: int,\n        *,\n        max_rows: Optional[int] = None,\n        file: Optional[IO[str]] = None,\n    ) -> None:\n        # If no rows need to be split across 2 lines, using 5 fewer rows in\n        # the data table than the number of terminal lines lets us fit entirely\n        # on 1 full page regardless of whether the user has a 1 line or 2 line\n        # shell prompt. With a 2 line prompt we lose the top dashed line.\n        max_rows = max_rows or max(_get_terminal_lines() - 5, 10)\n        table = Table(\n            Column(\"Location\", ratio=5),\n            Column(\"Total Memory\", ratio=1, justify=\"right\"),\n            Column(\"Total Memory %\", ratio=1, justify=\"right\"),\n            Column(\"Own Memory\", ratio=1, justify=\"right\"),\n            Column(\"Own Memory % \", ratio=1, justify=\"right\"),\n            Column(\"Allocation Count\", ratio=1, justify=\"right\"),\n            expand=True,\n        )\n        table.columns[sort_column].header = f\"<{table.columns[sort_column].header}>\"\n\n        sorted_allocations = sorted(\n            self.snapshot_data.items(),\n            key=lambda item: getattr(item[1], self.KEY_TO_COLUMN_NAME[sort_column]),\n            reverse=True,\n        )[:max_rows]\n        for location, result in sorted_allocations:\n            color_location = (\n                f\"[bold magenta]{escape(location.function)}[/] at \"\n                f\"[cyan]{escape(location.file)}[/]\"\n            )\n            total_color = _size_to_color(result.total_memory / self.current_memory_size)\n            own_color = _size_to_color(result.own_memory / self.current_memory_size)\n            allocation_colors = _size_to_color(\n                result.n_allocations / self.total_allocations\n            )\n            percent_total = result.total_memory / self.current_memory_size * 100\n            percent_own = result.own_memory / self.current_memory_size * 100\n            table.add_row(\n                color_location,\n                f\"[{total_color}]{size_fmt(result.total_memory)}[/{total_color}]\",\n                f\"[{total_color}]{percent_total:.2f}%[/{total_color}]\",\n                f\"[{own_color}]{size_fmt(result.own_memory)}[/{own_color}]\",\n                f\"[{own_color}]{percent_own:.2f}%[/{own_color}]\",\n                f\"[{allocation_colors}]{result.n_allocations}[/{allocation_colors}]\",\n            )\n\n        rprint(table, file=file)\n"
  },
  {
    "path": "src/memray/reporters/table.py",
    "content": "import html\nfrom typing import Any\nfrom typing import Dict\nfrom typing import Iterable\nfrom typing import List\nfrom typing import TextIO\n\nfrom memray import AllocationRecord\nfrom memray import AllocatorType\nfrom memray import MemorySnapshot\nfrom memray import Metadata\nfrom memray.reporters.common import format_thread_name\nfrom memray.reporters.templates import render_report\n\n\nclass TableReporter:\n    def __init__(\n        self,\n        data: List[Dict[str, Any]],\n        *,\n        memory_records: Iterable[MemorySnapshot],\n    ):\n        super().__init__()\n        self.data = data\n        self.memory_records = memory_records\n\n    @classmethod\n    def from_snapshot(\n        cls,\n        allocations: Iterable[AllocationRecord],\n        *,\n        memory_records: Iterable[MemorySnapshot],\n        native_traces: bool,\n        **kwargs: Any,\n    ) -> \"TableReporter\":\n        result = []\n        for record in allocations:\n            stack_trace = (\n                list(record.hybrid_stack_trace(max_stacks=1))\n                if native_traces\n                else record.stack_trace(max_stacks=1)\n            )\n            stack = \"???\"\n            if stack_trace:\n                function, file, line = stack_trace[0]\n                stack = f\"{function} at {file}:{line}\"\n\n            allocator = AllocatorType(record.allocator)\n            result.append(\n                {\n                    \"tid\": format_thread_name(record),\n                    \"size\": record.size,\n                    \"allocator\": allocator.name.lower(),\n                    \"n_allocations\": record.n_allocations,\n                    \"stack_trace\": html.escape(stack),\n                }\n            )\n\n        return cls(result, memory_records=memory_records)\n\n    def render(\n        self,\n        outfile: TextIO,\n        metadata: Metadata,\n        show_memory_leaks: bool,\n        merge_threads: bool,\n        inverted: bool,\n        no_web: bool = False,\n    ) -> None:\n        if not merge_threads:\n            raise NotImplementedError(\"TableReporter only supports merged threads.\")\n        if inverted:\n            raise NotImplementedError(\n                \"TableReporter does not support inverted argument\"\n            )\n        html_code = render_report(\n            kind=\"table\",\n            data=self.data,\n            metadata=metadata,\n            memory_records=self.memory_records,\n            show_memory_leaks=show_memory_leaks,\n            merge_threads=merge_threads,\n            inverted=inverted,\n            no_web=no_web,\n        )\n        print(html_code, file=outfile)\n"
  },
  {
    "path": "src/memray/reporters/templates/__init__.py",
    "content": "\"\"\"Templates to render reports in HTML.\"\"\"\nfrom functools import lru_cache\nfrom typing import Any\nfrom typing import Dict\nfrom typing import Iterable\nfrom typing import Union\n\nimport jinja2\nfrom markupsafe import Markup\n\nfrom memray import MemorySnapshot\nfrom memray import Metadata\n\n\n@lru_cache(maxsize=1)\ndef get_render_environment() -> jinja2.Environment:\n    loader = jinja2.PackageLoader(\"memray.reporters\")\n    env = jinja2.Environment(loader=loader)\n\n    def include_file(name: str) -> Markup:\n        \"\"\"Include a file from the templates directory without\n        interpolating its contents\"\"\"\n        source, *_ = loader.get_source(env, name)\n        return Markup(source)\n\n    env.globals[\"include_file\"] = include_file\n    env.policies[\"json.dumps_kwargs\"] = {\"sort_keys\": True, \"separators\": (\",\", \":\")}\n    return env\n\n\ndef get_report_title(\n    *, kind: str, show_memory_leaks: bool, inverted: bool = False\n) -> str:\n    parts = []\n    if inverted:\n        parts.append(\"inverted\")\n    parts.append(kind)\n    parts.append(\"report\")\n    if show_memory_leaks:\n        parts.append(\"(memory leaks)\")\n    return \" \".join(parts)\n\n\ndef render_report(\n    *,\n    kind: str,\n    data: Union[Dict[str, Any], Iterable[Dict[str, Any]]],\n    metadata: Metadata,\n    memory_records: Iterable[MemorySnapshot],\n    show_memory_leaks: bool,\n    merge_threads: bool,\n    inverted: bool,\n    no_web: bool = False,\n) -> str:\n    env = get_render_environment()\n    template = env.get_template(kind + \".html\")\n\n    pretty_kind = kind.replace(\"_\", \" \")\n    title = get_report_title(\n        kind=pretty_kind,\n        show_memory_leaks=show_memory_leaks,\n        inverted=inverted,\n    )\n    return template.render(\n        kind=pretty_kind,\n        title=title,\n        data=data,\n        metadata=metadata,\n        memory_records=memory_records,\n        show_memory_leaks=show_memory_leaks,\n        merge_threads=merge_threads,\n        inverted=inverted,\n        no_web=no_web,\n    )\n"
  },
  {
    "path": "src/memray/reporters/templates/assets/.gitattributes",
    "content": "*.js -diff\nvendor/* -diff\n"
  },
  {
    "path": "src/memray/reporters/templates/assets/flamegraph.css",
    "content": "/* Blocks */\n.d3-flame-graph rect {\n  fill-opacity: 0.8;\n  stroke: #1111;\n  stroke-width: 1px;\n}\n.d3-flame-graph .frame:hover rect {\n  stroke: #1118;\n  stroke-width: 1px;\n  cursor: pointer;\n}\n\n.d3-flame-graph-label {\n  color: black;\n  pointer-events: none;\n\n  font-size: 13px;\n  line-height: 1.5;\n\n  text-align: left;\n  text-overflow: ellipsis;\n  overflow: hidden;\n  white-space: nowrap;\n\n  padding: 0;\n  margin-left: 4px;\n  margin-right: 4px;\n}\n\n/* Bacckground stuff */\n.d3-flame-graph .fade {\n  opacity: 0.6 !important;\n}\n\n/* Tooltip */\n.d3-flame-graph-tip {\n  z-index: 10;\n\n  background: black;\n  border: none;\n  color: white;\n\n  text-align: left;\n\n  min-width: 250px;\n  border-radius: 2px;\n  padding: 2px 4px;\n}\n\n.tooltip-inner {\n  max-width: 300px;\n}\n\n/* Loading animation */\n\n#loading {\n  position: absolute;\n  top: 50%;\n  left: 50%;\n  transform: translate(-50%, -50%);\n  text-align: center;\n}\n\n.loading-spinner {\n  border: 4px solid #f3f3f3;\n  border-top: 4px solid #3498db;\n  border-radius: 50%;\n  width: 50px;\n  height: 50px;\n  animation: spin 2s linear infinite;\n}\n\n@keyframes spin {\n  0% {\n    transform: rotate(0deg);\n  }\n  100% {\n    transform: rotate(360deg);\n  }\n}\n\n#overlay {\n  position: fixed;\n  top: 0;\n  left: 0;\n  width: 100%;\n  height: 100%;\n  background-color: rgba(0, 0, 0, 0.5); /* semi-transparent black */\n  z-index: 99; /* make sure it's on top of other elements */\n}\n\n.flamegraph-icon {\n  display: flex;\n  align-items: center;\n  justify-content: center;\n}\n\n.flipped svg { transform: scale(1,-1); }\n"
  },
  {
    "path": "src/memray/reporters/templates/assets/flamegraph.js",
    "content": "(()=>{var t={543(t,n,e){var r;\n/**\n * @license\n * Lodash <https://lodash.com/>\n * Copyright OpenJS Foundation and other contributors <https://openjsf.org/>\n * Released under MIT license <https://lodash.com/license>\n * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>\n * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n */t=e.nmd(t),function(){var i,o=\"Expected a function\",u=\"__lodash_hash_undefined__\",a=\"__lodash_placeholder__\",c=16,f=32,l=64,s=128,h=256,p=1/0,v=9007199254740991,d=NaN,g=4294967295,_=[[\"ary\",s],[\"bind\",1],[\"bindKey\",2],[\"curry\",8],[\"curryRight\",c],[\"flip\",512],[\"partial\",f],[\"partialRight\",l],[\"rearg\",h]],y=\"[object Arguments]\",m=\"[object Array]\",w=\"[object Boolean]\",b=\"[object Date]\",x=\"[object Error]\",A=\"[object Function]\",E=\"[object GeneratorFunction]\",R=\"[object Map]\",j=\"[object Number]\",k=\"[object Object]\",I=\"[object Promise]\",O=\"[object RegExp]\",S=\"[object Set]\",L=\"[object String]\",B=\"[object Symbol]\",T=\"[object WeakMap]\",C=\"[object ArrayBuffer]\",z=\"[object DataView]\",F=\"[object Float32Array]\",D=\"[object Float64Array]\",W=\"[object Int8Array]\",P=\"[object Int16Array]\",$=\"[object Int32Array]\",M=\"[object Uint8Array]\",U=\"[object Uint8ClampedArray]\",N=\"[object Uint16Array]\",q=\"[object Uint32Array]\",H=/\\b__p \\+= '';/g,V=/\\b(__p \\+=) '' \\+/g,Z=/(__e\\(.*?\\)|\\b__t\\)) \\+\\n'';/g,G=/&(?:amp|lt|gt|quot|#39);/g,K=/[&<>\"']/g,Y=RegExp(G.source),Q=RegExp(K.source),J=/<%-([\\s\\S]+?)%>/g,X=/<%([\\s\\S]+?)%>/g,tt=/<%=([\\s\\S]+?)%>/g,nt=/\\.|\\[(?:[^[\\]]*|([\"'])(?:(?!\\1)[^\\\\]|\\\\.)*?\\1)\\]/,et=/^\\w*$/,rt=/[^.[\\]]+|\\[(?:(-?\\d+(?:\\.\\d+)?)|([\"'])((?:(?!\\2)[^\\\\]|\\\\.)*?)\\2)\\]|(?=(?:\\.|\\[\\])(?:\\.|\\[\\]|$))/g,it=/[\\\\^$.*+?()[\\]{}|]/g,ot=RegExp(it.source),ut=/^\\s+/,at=/\\s/,ct=/\\{(?:\\n\\/\\* \\[wrapped with .+\\] \\*\\/)?\\n?/,ft=/\\{\\n\\/\\* \\[wrapped with (.+)\\] \\*/,lt=/,? & /,st=/[^\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\x7f]+/g,ht=/[()=,{}\\[\\]\\/\\s]/,pt=/\\\\(\\\\)?/g,vt=/\\$\\{([^\\\\}]*(?:\\\\.[^\\\\}]*)*)\\}/g,dt=/\\w*$/,gt=/^[-+]0x[0-9a-f]+$/i,_t=/^0b[01]+$/i,yt=/^\\[object .+?Constructor\\]$/,mt=/^0o[0-7]+$/i,wt=/^(?:0|[1-9]\\d*)$/,bt=/[\\xc0-\\xd6\\xd8-\\xf6\\xf8-\\xff\\u0100-\\u017f]/g,xt=/($^)/,At=/['\\n\\r\\u2028\\u2029\\\\]/g,Et=\"\\\\ud800-\\\\udfff\",Rt=\"\\\\u0300-\\\\u036f\\\\ufe20-\\\\ufe2f\\\\u20d0-\\\\u20ff\",jt=\"\\\\u2700-\\\\u27bf\",kt=\"a-z\\\\xdf-\\\\xf6\\\\xf8-\\\\xff\",It=\"A-Z\\\\xc0-\\\\xd6\\\\xd8-\\\\xde\",Ot=\"\\\\ufe0e\\\\ufe0f\",St=\"\\\\xac\\\\xb1\\\\xd7\\\\xf7\\\\x00-\\\\x2f\\\\x3a-\\\\x40\\\\x5b-\\\\x60\\\\x7b-\\\\xbf\\\\u2000-\\\\u206f \\\\t\\\\x0b\\\\f\\\\xa0\\\\ufeff\\\\n\\\\r\\\\u2028\\\\u2029\\\\u1680\\\\u180e\\\\u2000\\\\u2001\\\\u2002\\\\u2003\\\\u2004\\\\u2005\\\\u2006\\\\u2007\\\\u2008\\\\u2009\\\\u200a\\\\u202f\\\\u205f\\\\u3000\",Lt=\"['’]\",Bt=\"[\"+Et+\"]\",Tt=\"[\"+St+\"]\",Ct=\"[\"+Rt+\"]\",zt=\"\\\\d+\",Ft=\"[\"+jt+\"]\",Dt=\"[\"+kt+\"]\",Wt=\"[^\"+Et+St+zt+jt+kt+It+\"]\",Pt=\"\\\\ud83c[\\\\udffb-\\\\udfff]\",$t=\"[^\"+Et+\"]\",Mt=\"(?:\\\\ud83c[\\\\udde6-\\\\uddff]){2}\",Ut=\"[\\\\ud800-\\\\udbff][\\\\udc00-\\\\udfff]\",Nt=\"[\"+It+\"]\",qt=\"\\\\u200d\",Ht=\"(?:\"+Dt+\"|\"+Wt+\")\",Vt=\"(?:\"+Nt+\"|\"+Wt+\")\",Zt=\"(?:['’](?:d|ll|m|re|s|t|ve))?\",Gt=\"(?:['’](?:D|LL|M|RE|S|T|VE))?\",Kt=\"(?:\"+Ct+\"|\"+Pt+\")\"+\"?\",Yt=\"[\"+Ot+\"]?\",Qt=Yt+Kt+(\"(?:\"+qt+\"(?:\"+[$t,Mt,Ut].join(\"|\")+\")\"+Yt+Kt+\")*\"),Jt=\"(?:\"+[Ft,Mt,Ut].join(\"|\")+\")\"+Qt,Xt=\"(?:\"+[$t+Ct+\"?\",Ct,Mt,Ut,Bt].join(\"|\")+\")\",tn=RegExp(Lt,\"g\"),nn=RegExp(Ct,\"g\"),en=RegExp(Pt+\"(?=\"+Pt+\")|\"+Xt+Qt,\"g\"),rn=RegExp([Nt+\"?\"+Dt+\"+\"+Zt+\"(?=\"+[Tt,Nt,\"$\"].join(\"|\")+\")\",Vt+\"+\"+Gt+\"(?=\"+[Tt,Nt+Ht,\"$\"].join(\"|\")+\")\",Nt+\"?\"+Ht+\"+\"+Zt,Nt+\"+\"+Gt,\"\\\\d*(?:1ST|2ND|3RD|(?![123])\\\\dTH)(?=\\\\b|[a-z_])\",\"\\\\d*(?:1st|2nd|3rd|(?![123])\\\\dth)(?=\\\\b|[A-Z_])\",zt,Jt].join(\"|\"),\"g\"),on=RegExp(\"[\"+qt+Et+Rt+Ot+\"]\"),un=/[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/,an=[\"Array\",\"Buffer\",\"DataView\",\"Date\",\"Error\",\"Float32Array\",\"Float64Array\",\"Function\",\"Int8Array\",\"Int16Array\",\"Int32Array\",\"Map\",\"Math\",\"Object\",\"Promise\",\"RegExp\",\"Set\",\"String\",\"Symbol\",\"TypeError\",\"Uint8Array\",\"Uint8ClampedArray\",\"Uint16Array\",\"Uint32Array\",\"WeakMap\",\"_\",\"clearTimeout\",\"isFinite\",\"parseInt\",\"setTimeout\"],cn=-1,fn={};fn[F]=fn[D]=fn[W]=fn[P]=fn[$]=fn[M]=fn[U]=fn[N]=fn[q]=!0,fn[y]=fn[m]=fn[C]=fn[w]=fn[z]=fn[b]=fn[x]=fn[A]=fn[R]=fn[j]=fn[k]=fn[O]=fn[S]=fn[L]=fn[T]=!1;var ln={};ln[y]=ln[m]=ln[C]=ln[z]=ln[w]=ln[b]=ln[F]=ln[D]=ln[W]=ln[P]=ln[$]=ln[R]=ln[j]=ln[k]=ln[O]=ln[S]=ln[L]=ln[B]=ln[M]=ln[U]=ln[N]=ln[q]=!0,ln[x]=ln[A]=ln[T]=!1;var sn={\"\\\\\":\"\\\\\",\"'\":\"'\",\"\\n\":\"n\",\"\\r\":\"r\",\"\\u2028\":\"u2028\",\"\\u2029\":\"u2029\"},hn=parseFloat,pn=parseInt,vn=\"object\"==typeof e.g&&e.g&&e.g.Object===Object&&e.g,dn=\"object\"==typeof self&&self&&self.Object===Object&&self,gn=vn||dn||Function(\"return this\")(),_n=n&&!n.nodeType&&n,yn=_n&&t&&!t.nodeType&&t,mn=yn&&yn.exports===_n,wn=mn&&vn.process,bn=function(){try{var t=yn&&yn.require&&yn.require(\"util\").types;return t||wn&&wn.binding&&wn.binding(\"util\")}catch(t){}}(),xn=bn&&bn.isArrayBuffer,An=bn&&bn.isDate,En=bn&&bn.isMap,Rn=bn&&bn.isRegExp,jn=bn&&bn.isSet,kn=bn&&bn.isTypedArray;function In(t,n,e){switch(e.length){case 0:return t.call(n);case 1:return t.call(n,e[0]);case 2:return t.call(n,e[0],e[1]);case 3:return t.call(n,e[0],e[1],e[2])}return t.apply(n,e)}function On(t,n,e,r){for(var i=-1,o=null==t?0:t.length;++i<o;){var u=t[i];n(r,u,e(u),t)}return r}function Sn(t,n){for(var e=-1,r=null==t?0:t.length;++e<r&&!1!==n(t[e],e,t););return t}function Ln(t,n){for(var e=null==t?0:t.length;e--&&!1!==n(t[e],e,t););return t}function Bn(t,n){for(var e=-1,r=null==t?0:t.length;++e<r;)if(!n(t[e],e,t))return!1;return!0}function Tn(t,n){for(var e=-1,r=null==t?0:t.length,i=0,o=[];++e<r;){var u=t[e];n(u,e,t)&&(o[i++]=u)}return o}function Cn(t,n){return!!(null==t?0:t.length)&&qn(t,n,0)>-1}function zn(t,n,e){for(var r=-1,i=null==t?0:t.length;++r<i;)if(e(n,t[r]))return!0;return!1}function Fn(t,n){for(var e=-1,r=null==t?0:t.length,i=Array(r);++e<r;)i[e]=n(t[e],e,t);return i}function Dn(t,n){for(var e=-1,r=n.length,i=t.length;++e<r;)t[i+e]=n[e];return t}function Wn(t,n,e,r){var i=-1,o=null==t?0:t.length;for(r&&o&&(e=t[++i]);++i<o;)e=n(e,t[i],i,t);return e}function Pn(t,n,e,r){var i=null==t?0:t.length;for(r&&i&&(e=t[--i]);i--;)e=n(e,t[i],i,t);return e}function $n(t,n){for(var e=-1,r=null==t?0:t.length;++e<r;)if(n(t[e],e,t))return!0;return!1}var Mn=Gn(\"length\");function Un(t,n,e){var r;return e(t,function(t,e,i){if(n(t,e,i))return r=e,!1}),r}function Nn(t,n,e,r){for(var i=t.length,o=e+(r?1:-1);r?o--:++o<i;)if(n(t[o],o,t))return o;return-1}function qn(t,n,e){return n==n?function(t,n,e){var r=e-1,i=t.length;for(;++r<i;)if(t[r]===n)return r;return-1}(t,n,e):Nn(t,Vn,e)}function Hn(t,n,e,r){for(var i=e-1,o=t.length;++i<o;)if(r(t[i],n))return i;return-1}function Vn(t){return t!=t}function Zn(t,n){var e=null==t?0:t.length;return e?Qn(t,n)/e:d}function Gn(t){return function(n){return null==n?i:n[t]}}function Kn(t){return function(n){return null==t?i:t[n]}}function Yn(t,n,e,r,i){return i(t,function(t,i,o){e=r?(r=!1,t):n(e,t,i,o)}),e}function Qn(t,n){for(var e,r=-1,o=t.length;++r<o;){var u=n(t[r]);u!==i&&(e=e===i?u:e+u)}return e}function Jn(t,n){for(var e=-1,r=Array(t);++e<t;)r[e]=n(e);return r}function Xn(t){return t?t.slice(0,ge(t)+1).replace(ut,\"\"):t}function te(t){return function(n){return t(n)}}function ne(t,n){return Fn(n,function(n){return t[n]})}function ee(t,n){return t.has(n)}function re(t,n){for(var e=-1,r=t.length;++e<r&&qn(n,t[e],0)>-1;);return e}function ie(t,n){for(var e=t.length;e--&&qn(n,t[e],0)>-1;);return e}var oe=Kn({À:\"A\",Á:\"A\",Â:\"A\",Ã:\"A\",Ä:\"A\",Å:\"A\",à:\"a\",á:\"a\",â:\"a\",ã:\"a\",ä:\"a\",å:\"a\",Ç:\"C\",ç:\"c\",Ð:\"D\",ð:\"d\",È:\"E\",É:\"E\",Ê:\"E\",Ë:\"E\",è:\"e\",é:\"e\",ê:\"e\",ë:\"e\",Ì:\"I\",Í:\"I\",Î:\"I\",Ï:\"I\",ì:\"i\",í:\"i\",î:\"i\",ï:\"i\",Ñ:\"N\",ñ:\"n\",Ò:\"O\",Ó:\"O\",Ô:\"O\",Õ:\"O\",Ö:\"O\",Ø:\"O\",ò:\"o\",ó:\"o\",ô:\"o\",õ:\"o\",ö:\"o\",ø:\"o\",Ù:\"U\",Ú:\"U\",Û:\"U\",Ü:\"U\",ù:\"u\",ú:\"u\",û:\"u\",ü:\"u\",Ý:\"Y\",ý:\"y\",ÿ:\"y\",Æ:\"Ae\",æ:\"ae\",Þ:\"Th\",þ:\"th\",ß:\"ss\",Ā:\"A\",Ă:\"A\",Ą:\"A\",ā:\"a\",ă:\"a\",ą:\"a\",Ć:\"C\",Ĉ:\"C\",Ċ:\"C\",Č:\"C\",ć:\"c\",ĉ:\"c\",ċ:\"c\",č:\"c\",Ď:\"D\",Đ:\"D\",ď:\"d\",đ:\"d\",Ē:\"E\",Ĕ:\"E\",Ė:\"E\",Ę:\"E\",Ě:\"E\",ē:\"e\",ĕ:\"e\",ė:\"e\",ę:\"e\",ě:\"e\",Ĝ:\"G\",Ğ:\"G\",Ġ:\"G\",Ģ:\"G\",ĝ:\"g\",ğ:\"g\",ġ:\"g\",ģ:\"g\",Ĥ:\"H\",Ħ:\"H\",ĥ:\"h\",ħ:\"h\",Ĩ:\"I\",Ī:\"I\",Ĭ:\"I\",Į:\"I\",İ:\"I\",ĩ:\"i\",ī:\"i\",ĭ:\"i\",į:\"i\",ı:\"i\",Ĵ:\"J\",ĵ:\"j\",Ķ:\"K\",ķ:\"k\",ĸ:\"k\",Ĺ:\"L\",Ļ:\"L\",Ľ:\"L\",Ŀ:\"L\",Ł:\"L\",ĺ:\"l\",ļ:\"l\",ľ:\"l\",ŀ:\"l\",ł:\"l\",Ń:\"N\",Ņ:\"N\",Ň:\"N\",Ŋ:\"N\",ń:\"n\",ņ:\"n\",ň:\"n\",ŋ:\"n\",Ō:\"O\",Ŏ:\"O\",Ő:\"O\",ō:\"o\",ŏ:\"o\",ő:\"o\",Ŕ:\"R\",Ŗ:\"R\",Ř:\"R\",ŕ:\"r\",ŗ:\"r\",ř:\"r\",Ś:\"S\",Ŝ:\"S\",Ş:\"S\",Š:\"S\",ś:\"s\",ŝ:\"s\",ş:\"s\",š:\"s\",Ţ:\"T\",Ť:\"T\",Ŧ:\"T\",ţ:\"t\",ť:\"t\",ŧ:\"t\",Ũ:\"U\",Ū:\"U\",Ŭ:\"U\",Ů:\"U\",Ű:\"U\",Ų:\"U\",ũ:\"u\",ū:\"u\",ŭ:\"u\",ů:\"u\",ű:\"u\",ų:\"u\",Ŵ:\"W\",ŵ:\"w\",Ŷ:\"Y\",ŷ:\"y\",Ÿ:\"Y\",Ź:\"Z\",Ż:\"Z\",Ž:\"Z\",ź:\"z\",ż:\"z\",ž:\"z\",Ĳ:\"IJ\",ĳ:\"ij\",Œ:\"Oe\",œ:\"oe\",ŉ:\"'n\",ſ:\"s\"}),ue=Kn({\"&\":\"&amp;\",\"<\":\"&lt;\",\">\":\"&gt;\",'\"':\"&quot;\",\"'\":\"&#39;\"});function ae(t){return\"\\\\\"+sn[t]}function ce(t){return on.test(t)}function fe(t){var n=-1,e=Array(t.size);return t.forEach(function(t,r){e[++n]=[r,t]}),e}function le(t,n){return function(e){return t(n(e))}}function se(t,n){for(var e=-1,r=t.length,i=0,o=[];++e<r;){var u=t[e];u!==n&&u!==a||(t[e]=a,o[i++]=e)}return o}function he(t){var n=-1,e=Array(t.size);return t.forEach(function(t){e[++n]=t}),e}function pe(t){var n=-1,e=Array(t.size);return t.forEach(function(t){e[++n]=[t,t]}),e}function ve(t){return ce(t)?function(t){var n=en.lastIndex=0;for(;en.test(t);)++n;return n}(t):Mn(t)}function de(t){return ce(t)?function(t){return t.match(en)||[]}(t):function(t){return t.split(\"\")}(t)}function ge(t){for(var n=t.length;n--&&at.test(t.charAt(n)););return n}var _e=Kn({\"&amp;\":\"&\",\"&lt;\":\"<\",\"&gt;\":\">\",\"&quot;\":'\"',\"&#39;\":\"'\"});var ye=function t(n){var e,r=(n=null==n?gn:ye.defaults(gn.Object(),n,ye.pick(gn,an))).Array,at=n.Date,Et=n.Error,Rt=n.Function,jt=n.Math,kt=n.Object,It=n.RegExp,Ot=n.String,St=n.TypeError,Lt=r.prototype,Bt=Rt.prototype,Tt=kt.prototype,Ct=n[\"__core-js_shared__\"],zt=Bt.toString,Ft=Tt.hasOwnProperty,Dt=0,Wt=(e=/[^.]+$/.exec(Ct&&Ct.keys&&Ct.keys.IE_PROTO||\"\"))?\"Symbol(src)_1.\"+e:\"\",Pt=Tt.toString,$t=zt.call(kt),Mt=gn._,Ut=It(\"^\"+zt.call(Ft).replace(it,\"\\\\$&\").replace(/hasOwnProperty|(function).*?(?=\\\\\\()| for .+?(?=\\\\\\])/g,\"$1.*?\")+\"$\"),Nt=mn?n.Buffer:i,qt=n.Symbol,Ht=n.Uint8Array,Vt=Nt?Nt.allocUnsafe:i,Zt=le(kt.getPrototypeOf,kt),Gt=kt.create,Kt=Tt.propertyIsEnumerable,Yt=Lt.splice,Qt=qt?qt.isConcatSpreadable:i,Jt=qt?qt.iterator:i,Xt=qt?qt.toStringTag:i,en=function(){try{var t=ho(kt,\"defineProperty\");return t({},\"\",{}),t}catch(t){}}(),on=n.clearTimeout!==gn.clearTimeout&&n.clearTimeout,sn=at&&at.now!==gn.Date.now&&at.now,vn=n.setTimeout!==gn.setTimeout&&n.setTimeout,dn=jt.ceil,_n=jt.floor,yn=kt.getOwnPropertySymbols,wn=Nt?Nt.isBuffer:i,bn=n.isFinite,Mn=Lt.join,Kn=le(kt.keys,kt),me=jt.max,we=jt.min,be=at.now,xe=n.parseInt,Ae=jt.random,Ee=Lt.reverse,Re=ho(n,\"DataView\"),je=ho(n,\"Map\"),ke=ho(n,\"Promise\"),Ie=ho(n,\"Set\"),Oe=ho(n,\"WeakMap\"),Se=ho(kt,\"create\"),Le=Oe&&new Oe,Be={},Te=Po(Re),Ce=Po(je),ze=Po(ke),Fe=Po(Ie),De=Po(Oe),We=qt?qt.prototype:i,Pe=We?We.valueOf:i,$e=We?We.toString:i;function Me(t){if(ea(t)&&!Hu(t)&&!(t instanceof He)){if(t instanceof qe)return t;if(Ft.call(t,\"__wrapped__\"))return $o(t)}return new qe(t)}var Ue=function(){function t(){}return function(n){if(!na(n))return{};if(Gt)return Gt(n);t.prototype=n;var e=new t;return t.prototype=i,e}}();function Ne(){}function qe(t,n){this.__wrapped__=t,this.__actions__=[],this.__chain__=!!n,this.__index__=0,this.__values__=i}function He(t){this.__wrapped__=t,this.__actions__=[],this.__dir__=1,this.__filtered__=!1,this.__iteratees__=[],this.__takeCount__=g,this.__views__=[]}function Ve(t){var n=-1,e=null==t?0:t.length;for(this.clear();++n<e;){var r=t[n];this.set(r[0],r[1])}}function Ze(t){var n=-1,e=null==t?0:t.length;for(this.clear();++n<e;){var r=t[n];this.set(r[0],r[1])}}function Ge(t){var n=-1,e=null==t?0:t.length;for(this.clear();++n<e;){var r=t[n];this.set(r[0],r[1])}}function Ke(t){var n=-1,e=null==t?0:t.length;for(this.__data__=new Ge;++n<e;)this.add(t[n])}function Ye(t){var n=this.__data__=new Ze(t);this.size=n.size}function Qe(t,n){var e=Hu(t),r=!e&&qu(t),i=!e&&!r&&Ku(t),o=!e&&!r&&!i&&la(t),u=e||r||i||o,a=u?Jn(t.length,Ot):[],c=a.length;for(var f in t)!n&&!Ft.call(t,f)||u&&(\"length\"==f||i&&(\"offset\"==f||\"parent\"==f)||o&&(\"buffer\"==f||\"byteLength\"==f||\"byteOffset\"==f)||wo(f,c))||a.push(f);return a}function Je(t){var n=t.length;return n?t[Kr(0,n-1)]:i}function Xe(t,n){return Fo(Si(t),cr(n,0,t.length))}function tr(t){return Fo(Si(t))}function nr(t,n,e){(e!==i&&!Mu(t[n],e)||e===i&&!(n in t))&&ur(t,n,e)}function er(t,n,e){var r=t[n];Ft.call(t,n)&&Mu(r,e)&&(e!==i||n in t)||ur(t,n,e)}function rr(t,n){for(var e=t.length;e--;)if(Mu(t[e][0],n))return e;return-1}function ir(t,n,e,r){return pr(t,function(t,i,o){n(r,t,e(t),o)}),r}function or(t,n){return t&&Li(n,Ba(n),t)}function ur(t,n,e){\"__proto__\"==n&&en?en(t,n,{configurable:!0,enumerable:!0,value:e,writable:!0}):t[n]=e}function ar(t,n){for(var e=-1,o=n.length,u=r(o),a=null==t;++e<o;)u[e]=a?i:ka(t,n[e]);return u}function cr(t,n,e){return t==t&&(e!==i&&(t=t<=e?t:e),n!==i&&(t=t>=n?t:n)),t}function fr(t,n,e,r,o,u){var a,c=1&n,f=2&n,l=4&n;if(e&&(a=o?e(t,r,o,u):e(t)),a!==i)return a;if(!na(t))return t;var s=Hu(t);if(s){if(a=function(t){var n=t.length,e=new t.constructor(n);n&&\"string\"==typeof t[0]&&Ft.call(t,\"index\")&&(e.index=t.index,e.input=t.input);return e}(t),!c)return Si(t,a)}else{var h=go(t),p=h==A||h==E;if(Ku(t))return Ei(t,c);if(h==k||h==y||p&&!o){if(a=f||p?{}:yo(t),!c)return f?function(t,n){return Li(t,vo(t),n)}(t,function(t,n){return t&&Li(n,Ta(n),t)}(a,t)):function(t,n){return Li(t,po(t),n)}(t,or(a,t))}else{if(!ln[h])return o?t:{};a=function(t,n,e){var r=t.constructor;switch(n){case C:return Ri(t);case w:case b:return new r(+t);case z:return function(t,n){var e=n?Ri(t.buffer):t.buffer;return new t.constructor(e,t.byteOffset,t.byteLength)}(t,e);case F:case D:case W:case P:case $:case M:case U:case N:case q:return ji(t,e);case R:return new r;case j:case L:return new r(t);case O:return function(t){var n=new t.constructor(t.source,dt.exec(t));return n.lastIndex=t.lastIndex,n}(t);case S:return new r;case B:return i=t,Pe?kt(Pe.call(i)):{}}var i}(t,h,c)}}u||(u=new Ye);var v=u.get(t);if(v)return v;u.set(t,a),aa(t)?t.forEach(function(r){a.add(fr(r,n,e,r,t,u))}):ra(t)&&t.forEach(function(r,i){a.set(i,fr(r,n,e,i,t,u))});var d=s?i:(l?f?oo:io:f?Ta:Ba)(t);return Sn(d||t,function(r,i){d&&(r=t[i=r]),er(a,i,fr(r,n,e,i,t,u))}),a}function lr(t,n,e){var r=e.length;if(null==t)return!r;for(t=kt(t);r--;){var o=e[r],u=n[o],a=t[o];if(a===i&&!(o in t)||!u(a))return!1}return!0}function sr(t,n,e){if(\"function\"!=typeof t)throw new St(o);return Bo(function(){t.apply(i,e)},n)}function hr(t,n,e,r){var i=-1,o=Cn,u=!0,a=t.length,c=[],f=n.length;if(!a)return c;e&&(n=Fn(n,te(e))),r?(o=zn,u=!1):n.length>=200&&(o=ee,u=!1,n=new Ke(n));t:for(;++i<a;){var l=t[i],s=null==e?l:e(l);if(l=r||0!==l?l:0,u&&s==s){for(var h=f;h--;)if(n[h]===s)continue t;c.push(l)}else o(n,s,r)||c.push(l)}return c}Me.templateSettings={escape:J,evaluate:X,interpolate:tt,variable:\"\",imports:{_:Me}},Me.prototype=Ne.prototype,Me.prototype.constructor=Me,qe.prototype=Ue(Ne.prototype),qe.prototype.constructor=qe,He.prototype=Ue(Ne.prototype),He.prototype.constructor=He,Ve.prototype.clear=function(){this.__data__=Se?Se(null):{},this.size=0},Ve.prototype.delete=function(t){var n=this.has(t)&&delete this.__data__[t];return this.size-=n?1:0,n},Ve.prototype.get=function(t){var n=this.__data__;if(Se){var e=n[t];return e===u?i:e}return Ft.call(n,t)?n[t]:i},Ve.prototype.has=function(t){var n=this.__data__;return Se?n[t]!==i:Ft.call(n,t)},Ve.prototype.set=function(t,n){var e=this.__data__;return this.size+=this.has(t)?0:1,e[t]=Se&&n===i?u:n,this},Ze.prototype.clear=function(){this.__data__=[],this.size=0},Ze.prototype.delete=function(t){var n=this.__data__,e=rr(n,t);return!(e<0)&&(e==n.length-1?n.pop():Yt.call(n,e,1),--this.size,!0)},Ze.prototype.get=function(t){var n=this.__data__,e=rr(n,t);return e<0?i:n[e][1]},Ze.prototype.has=function(t){return rr(this.__data__,t)>-1},Ze.prototype.set=function(t,n){var e=this.__data__,r=rr(e,t);return r<0?(++this.size,e.push([t,n])):e[r][1]=n,this},Ge.prototype.clear=function(){this.size=0,this.__data__={hash:new Ve,map:new(je||Ze),string:new Ve}},Ge.prototype.delete=function(t){var n=lo(this,t).delete(t);return this.size-=n?1:0,n},Ge.prototype.get=function(t){return lo(this,t).get(t)},Ge.prototype.has=function(t){return lo(this,t).has(t)},Ge.prototype.set=function(t,n){var e=lo(this,t),r=e.size;return e.set(t,n),this.size+=e.size==r?0:1,this},Ke.prototype.add=Ke.prototype.push=function(t){return this.__data__.set(t,u),this},Ke.prototype.has=function(t){return this.__data__.has(t)},Ye.prototype.clear=function(){this.__data__=new Ze,this.size=0},Ye.prototype.delete=function(t){var n=this.__data__,e=n.delete(t);return this.size=n.size,e},Ye.prototype.get=function(t){return this.__data__.get(t)},Ye.prototype.has=function(t){return this.__data__.has(t)},Ye.prototype.set=function(t,n){var e=this.__data__;if(e instanceof Ze){var r=e.__data__;if(!je||r.length<199)return r.push([t,n]),this.size=++e.size,this;e=this.__data__=new Ge(r)}return e.set(t,n),this.size=e.size,this};var pr=Ci(br),vr=Ci(xr,!0);function dr(t,n){var e=!0;return pr(t,function(t,r,i){return e=!!n(t,r,i)}),e}function gr(t,n,e){for(var r=-1,o=t.length;++r<o;){var u=t[r],a=n(u);if(null!=a&&(c===i?a==a&&!fa(a):e(a,c)))var c=a,f=u}return f}function _r(t,n){var e=[];return pr(t,function(t,r,i){n(t,r,i)&&e.push(t)}),e}function yr(t,n,e,r,i){var o=-1,u=t.length;for(e||(e=mo),i||(i=[]);++o<u;){var a=t[o];n>0&&e(a)?n>1?yr(a,n-1,e,r,i):Dn(i,a):r||(i[i.length]=a)}return i}var mr=zi(),wr=zi(!0);function br(t,n){return t&&mr(t,n,Ba)}function xr(t,n){return t&&wr(t,n,Ba)}function Ar(t,n){return Tn(n,function(n){return Ju(t[n])})}function Er(t,n){for(var e=0,r=(n=wi(n,t)).length;null!=t&&e<r;)t=t[Wo(n[e++])];return e&&e==r?t:i}function Rr(t,n,e){var r=n(t);return Hu(t)?r:Dn(r,e(t))}function jr(t){return null==t?t===i?\"[object Undefined]\":\"[object Null]\":Xt&&Xt in kt(t)?function(t){var n=Ft.call(t,Xt),e=t[Xt];try{t[Xt]=i;var r=!0}catch(t){}var o=Pt.call(t);r&&(n?t[Xt]=e:delete t[Xt]);return o}(t):function(t){return Pt.call(t)}(t)}function kr(t,n){return t>n}function Ir(t,n){return null!=t&&Ft.call(t,n)}function Or(t,n){return null!=t&&n in kt(t)}function Sr(t,n,e){for(var o=e?zn:Cn,u=t[0].length,a=t.length,c=a,f=r(a),l=1/0,s=[];c--;){var h=t[c];c&&n&&(h=Fn(h,te(n))),l=we(h.length,l),f[c]=!e&&(n||u>=120&&h.length>=120)?new Ke(c&&h):i}h=t[0];var p=-1,v=f[0];t:for(;++p<u&&s.length<l;){var d=h[p],g=n?n(d):d;if(d=e||0!==d?d:0,!(v?ee(v,g):o(s,g,e))){for(c=a;--c;){var _=f[c];if(!(_?ee(_,g):o(t[c],g,e)))continue t}v&&v.push(g),s.push(d)}}return s}function Lr(t,n,e){var r=null==(t=Oo(t,n=wi(n,t)))?t:t[Wo(Qo(n))];return null==r?i:In(r,t,e)}function Br(t){return ea(t)&&jr(t)==y}function Tr(t,n,e,r,o){return t===n||(null==t||null==n||!ea(t)&&!ea(n)?t!=t&&n!=n:function(t,n,e,r,o,u){var a=Hu(t),c=Hu(n),f=a?m:go(t),l=c?m:go(n),s=(f=f==y?k:f)==k,h=(l=l==y?k:l)==k,p=f==l;if(p&&Ku(t)){if(!Ku(n))return!1;a=!0,s=!1}if(p&&!s)return u||(u=new Ye),a||la(t)?eo(t,n,e,r,o,u):function(t,n,e,r,i,o,u){switch(e){case z:if(t.byteLength!=n.byteLength||t.byteOffset!=n.byteOffset)return!1;t=t.buffer,n=n.buffer;case C:return!(t.byteLength!=n.byteLength||!o(new Ht(t),new Ht(n)));case w:case b:case j:return Mu(+t,+n);case x:return t.name==n.name&&t.message==n.message;case O:case L:return t==n+\"\";case R:var a=fe;case S:var c=1&r;if(a||(a=he),t.size!=n.size&&!c)return!1;var f=u.get(t);if(f)return f==n;r|=2,u.set(t,n);var l=eo(a(t),a(n),r,i,o,u);return u.delete(t),l;case B:if(Pe)return Pe.call(t)==Pe.call(n)}return!1}(t,n,f,e,r,o,u);if(!(1&e)){var v=s&&Ft.call(t,\"__wrapped__\"),d=h&&Ft.call(n,\"__wrapped__\");if(v||d){var g=v?t.value():t,_=d?n.value():n;return u||(u=new Ye),o(g,_,e,r,u)}}if(!p)return!1;return u||(u=new Ye),function(t,n,e,r,o,u){var a=1&e,c=io(t),f=c.length,l=io(n),s=l.length;if(f!=s&&!a)return!1;var h=f;for(;h--;){var p=c[h];if(!(a?p in n:Ft.call(n,p)))return!1}var v=u.get(t),d=u.get(n);if(v&&d)return v==n&&d==t;var g=!0;u.set(t,n),u.set(n,t);var _=a;for(;++h<f;){var y=t[p=c[h]],m=n[p];if(r)var w=a?r(m,y,p,n,t,u):r(y,m,p,t,n,u);if(!(w===i?y===m||o(y,m,e,r,u):w)){g=!1;break}_||(_=\"constructor\"==p)}if(g&&!_){var b=t.constructor,x=n.constructor;b==x||!(\"constructor\"in t)||!(\"constructor\"in n)||\"function\"==typeof b&&b instanceof b&&\"function\"==typeof x&&x instanceof x||(g=!1)}return u.delete(t),u.delete(n),g}(t,n,e,r,o,u)}(t,n,e,r,Tr,o))}function Cr(t,n,e,r){var o=e.length,u=o,a=!r;if(null==t)return!u;for(t=kt(t);o--;){var c=e[o];if(a&&c[2]?c[1]!==t[c[0]]:!(c[0]in t))return!1}for(;++o<u;){var f=(c=e[o])[0],l=t[f],s=c[1];if(a&&c[2]){if(l===i&&!(f in t))return!1}else{var h=new Ye;if(r)var p=r(l,s,f,t,n,h);if(!(p===i?Tr(s,l,3,r,h):p))return!1}}return!0}function zr(t){return!(!na(t)||(n=t,Wt&&Wt in n))&&(Ju(t)?Ut:yt).test(Po(t));var n}function Fr(t){return\"function\"==typeof t?t:null==t?ic:\"object\"==typeof t?Hu(t)?Ur(t[0],t[1]):Mr(t):pc(t)}function Dr(t){if(!Ro(t))return Kn(t);var n=[];for(var e in kt(t))Ft.call(t,e)&&\"constructor\"!=e&&n.push(e);return n}function Wr(t){if(!na(t))return function(t){var n=[];if(null!=t)for(var e in kt(t))n.push(e);return n}(t);var n=Ro(t),e=[];for(var r in t)(\"constructor\"!=r||!n&&Ft.call(t,r))&&e.push(r);return e}function Pr(t,n){return t<n}function $r(t,n){var e=-1,i=Zu(t)?r(t.length):[];return pr(t,function(t,r,o){i[++e]=n(t,r,o)}),i}function Mr(t){var n=so(t);return 1==n.length&&n[0][2]?ko(n[0][0],n[0][1]):function(e){return e===t||Cr(e,t,n)}}function Ur(t,n){return xo(t)&&jo(n)?ko(Wo(t),n):function(e){var r=ka(e,t);return r===i&&r===n?Ia(e,t):Tr(n,r,3)}}function Nr(t,n,e,r,o){t!==n&&mr(n,function(u,a){if(o||(o=new Ye),na(u))!function(t,n,e,r,o,u,a){var c=So(t,e),f=So(n,e),l=a.get(f);if(l)return void nr(t,e,l);var s=u?u(c,f,e+\"\",t,n,a):i,h=s===i;if(h){var p=Hu(f),v=!p&&Ku(f),d=!p&&!v&&la(f);s=f,p||v||d?Hu(c)?s=c:Gu(c)?s=Si(c):v?(h=!1,s=Ei(f,!0)):d?(h=!1,s=ji(f,!0)):s=[]:oa(f)||qu(f)?(s=c,qu(c)?s=ya(c):na(c)&&!Ju(c)||(s=yo(f))):h=!1}h&&(a.set(f,s),o(s,f,r,u,a),a.delete(f));nr(t,e,s)}(t,n,a,e,Nr,r,o);else{var c=r?r(So(t,a),u,a+\"\",t,n,o):i;c===i&&(c=u),nr(t,a,c)}},Ta)}function qr(t,n){var e=t.length;if(e)return wo(n+=n<0?e:0,e)?t[n]:i}function Hr(t,n,e){n=n.length?Fn(n,function(t){return Hu(t)?function(n){return Er(n,1===t.length?t[0]:t)}:t}):[ic];var r=-1;n=Fn(n,te(fo()));var i=$r(t,function(t,e,i){var o=Fn(n,function(n){return n(t)});return{criteria:o,index:++r,value:t}});return function(t,n){var e=t.length;for(t.sort(n);e--;)t[e]=t[e].value;return t}(i,function(t,n){return function(t,n,e){var r=-1,i=t.criteria,o=n.criteria,u=i.length,a=e.length;for(;++r<u;){var c=ki(i[r],o[r]);if(c)return r>=a?c:c*(\"desc\"==e[r]?-1:1)}return t.index-n.index}(t,n,e)})}function Vr(t,n,e){for(var r=-1,i=n.length,o={};++r<i;){var u=n[r],a=Er(t,u);e(a,u)&&ti(o,wi(u,t),a)}return o}function Zr(t,n,e,r){var i=r?Hn:qn,o=-1,u=n.length,a=t;for(t===n&&(n=Si(n)),e&&(a=Fn(t,te(e)));++o<u;)for(var c=0,f=n[o],l=e?e(f):f;(c=i(a,l,c,r))>-1;)a!==t&&Yt.call(a,c,1),Yt.call(t,c,1);return t}function Gr(t,n){for(var e=t?n.length:0,r=e-1;e--;){var i=n[e];if(e==r||i!==o){var o=i;wo(i)?Yt.call(t,i,1):hi(t,i)}}return t}function Kr(t,n){return t+_n(Ae()*(n-t+1))}function Yr(t,n){var e=\"\";if(!t||n<1||n>v)return e;do{n%2&&(e+=t),(n=_n(n/2))&&(t+=t)}while(n);return e}function Qr(t,n){return To(Io(t,n,ic),t+\"\")}function Jr(t){return Je(Ma(t))}function Xr(t,n){var e=Ma(t);return Fo(e,cr(n,0,e.length))}function ti(t,n,e,r){if(!na(t))return t;for(var o=-1,u=(n=wi(n,t)).length,a=u-1,c=t;null!=c&&++o<u;){var f=Wo(n[o]),l=e;if(\"__proto__\"===f||\"constructor\"===f||\"prototype\"===f)return t;if(o!=a){var s=c[f];(l=r?r(s,f,c):i)===i&&(l=na(s)?s:wo(n[o+1])?[]:{})}er(c,f,l),c=c[f]}return t}var ni=Le?function(t,n){return Le.set(t,n),t}:ic,ei=en?function(t,n){return en(t,\"toString\",{configurable:!0,enumerable:!1,value:nc(n),writable:!0})}:ic;function ri(t){return Fo(Ma(t))}function ii(t,n,e){var i=-1,o=t.length;n<0&&(n=-n>o?0:o+n),(e=e>o?o:e)<0&&(e+=o),o=n>e?0:e-n>>>0,n>>>=0;for(var u=r(o);++i<o;)u[i]=t[i+n];return u}function oi(t,n){var e;return pr(t,function(t,r,i){return!(e=n(t,r,i))}),!!e}function ui(t,n,e){var r=0,i=null==t?r:t.length;if(\"number\"==typeof n&&n==n&&i<=2147483647){for(;r<i;){var o=r+i>>>1,u=t[o];null!==u&&!fa(u)&&(e?u<=n:u<n)?r=o+1:i=o}return i}return ai(t,n,ic,e)}function ai(t,n,e,r){var o=0,u=null==t?0:t.length;if(0===u)return 0;for(var a=(n=e(n))!=n,c=null===n,f=fa(n),l=n===i;o<u;){var s=_n((o+u)/2),h=e(t[s]),p=h!==i,v=null===h,d=h==h,g=fa(h);if(a)var _=r||d;else _=l?d&&(r||p):c?d&&p&&(r||!v):f?d&&p&&!v&&(r||!g):!v&&!g&&(r?h<=n:h<n);_?o=s+1:u=s}return we(u,4294967294)}function ci(t,n){for(var e=-1,r=t.length,i=0,o=[];++e<r;){var u=t[e],a=n?n(u):u;if(!e||!Mu(a,c)){var c=a;o[i++]=0===u?0:u}}return o}function fi(t){return\"number\"==typeof t?t:fa(t)?d:+t}function li(t){if(\"string\"==typeof t)return t;if(Hu(t))return Fn(t,li)+\"\";if(fa(t))return $e?$e.call(t):\"\";var n=t+\"\";return\"0\"==n&&1/t==-1/0?\"-0\":n}function si(t,n,e){var r=-1,i=Cn,o=t.length,u=!0,a=[],c=a;if(e)u=!1,i=zn;else if(o>=200){var f=n?null:Yi(t);if(f)return he(f);u=!1,i=ee,c=new Ke}else c=n?[]:a;t:for(;++r<o;){var l=t[r],s=n?n(l):l;if(l=e||0!==l?l:0,u&&s==s){for(var h=c.length;h--;)if(c[h]===s)continue t;n&&c.push(s),a.push(l)}else i(c,s,e)||(c!==a&&c.push(s),a.push(l))}return a}function hi(t,n){var e=-1,r=(n=wi(n,t)).length;if(!r)return!0;for(var i=null==t||\"object\"!=typeof t&&\"function\"!=typeof t;++e<r;){var o=n[e];if(\"string\"==typeof o){if(\"__proto__\"===o&&!Ft.call(t,\"__proto__\"))return!1;if(\"constructor\"===o&&e+1<r&&\"string\"==typeof n[e+1]&&\"prototype\"===n[e+1]){if(i&&0===e)continue;return!1}}}var u=Oo(t,n);return null==u||delete u[Wo(Qo(n))]}function pi(t,n,e,r){return ti(t,n,e(Er(t,n)),r)}function vi(t,n,e,r){for(var i=t.length,o=r?i:-1;(r?o--:++o<i)&&n(t[o],o,t););return e?ii(t,r?0:o,r?o+1:i):ii(t,r?o+1:0,r?i:o)}function di(t,n){var e=t;return e instanceof He&&(e=e.value()),Wn(n,function(t,n){return n.func.apply(n.thisArg,Dn([t],n.args))},e)}function gi(t,n,e){var i=t.length;if(i<2)return i?si(t[0]):[];for(var o=-1,u=r(i);++o<i;)for(var a=t[o],c=-1;++c<i;)c!=o&&(u[o]=hr(u[o]||a,t[c],n,e));return si(yr(u,1),n,e)}function _i(t,n,e){for(var r=-1,o=t.length,u=n.length,a={};++r<o;){var c=r<u?n[r]:i;e(a,t[r],c)}return a}function yi(t){return Gu(t)?t:[]}function mi(t){return\"function\"==typeof t?t:ic}function wi(t,n){return Hu(t)?t:xo(t,n)?[t]:Do(ma(t))}var bi=Qr;function xi(t,n,e){var r=t.length;return e=e===i?r:e,!n&&e>=r?t:ii(t,n,e)}var Ai=on||function(t){return gn.clearTimeout(t)};function Ei(t,n){if(n)return t.slice();var e=t.length,r=Vt?Vt(e):new t.constructor(e);return t.copy(r),r}function Ri(t){var n=new t.constructor(t.byteLength);return new Ht(n).set(new Ht(t)),n}function ji(t,n){var e=n?Ri(t.buffer):t.buffer;return new t.constructor(e,t.byteOffset,t.length)}function ki(t,n){if(t!==n){var e=t!==i,r=null===t,o=t==t,u=fa(t),a=n!==i,c=null===n,f=n==n,l=fa(n);if(!c&&!l&&!u&&t>n||u&&a&&f&&!c&&!l||r&&a&&f||!e&&f||!o)return 1;if(!r&&!u&&!l&&t<n||l&&e&&o&&!r&&!u||c&&e&&o||!a&&o||!f)return-1}return 0}function Ii(t,n,e,i){for(var o=-1,u=t.length,a=e.length,c=-1,f=n.length,l=me(u-a,0),s=r(f+l),h=!i;++c<f;)s[c]=n[c];for(;++o<a;)(h||o<u)&&(s[e[o]]=t[o]);for(;l--;)s[c++]=t[o++];return s}function Oi(t,n,e,i){for(var o=-1,u=t.length,a=-1,c=e.length,f=-1,l=n.length,s=me(u-c,0),h=r(s+l),p=!i;++o<s;)h[o]=t[o];for(var v=o;++f<l;)h[v+f]=n[f];for(;++a<c;)(p||o<u)&&(h[v+e[a]]=t[o++]);return h}function Si(t,n){var e=-1,i=t.length;for(n||(n=r(i));++e<i;)n[e]=t[e];return n}function Li(t,n,e,r){var o=!e;e||(e={});for(var u=-1,a=n.length;++u<a;){var c=n[u],f=r?r(e[c],t[c],c,e,t):i;f===i&&(f=t[c]),o?ur(e,c,f):er(e,c,f)}return e}function Bi(t,n){return function(e,r){var i=Hu(e)?On:ir,o=n?n():{};return i(e,t,fo(r,2),o)}}function Ti(t){return Qr(function(n,e){var r=-1,o=e.length,u=o>1?e[o-1]:i,a=o>2?e[2]:i;for(u=t.length>3&&\"function\"==typeof u?(o--,u):i,a&&bo(e[0],e[1],a)&&(u=o<3?i:u,o=1),n=kt(n);++r<o;){var c=e[r];c&&t(n,c,r,u)}return n})}function Ci(t,n){return function(e,r){if(null==e)return e;if(!Zu(e))return t(e,r);for(var i=e.length,o=n?i:-1,u=kt(e);(n?o--:++o<i)&&!1!==r(u[o],o,u););return e}}function zi(t){return function(n,e,r){for(var i=-1,o=kt(n),u=r(n),a=u.length;a--;){var c=u[t?a:++i];if(!1===e(o[c],c,o))break}return n}}function Fi(t){return function(n){var e=ce(n=ma(n))?de(n):i,r=e?e[0]:n.charAt(0),o=e?xi(e,1).join(\"\"):n.slice(1);return r[t]()+o}}function Di(t){return function(n){return Wn(Ja(qa(n).replace(tn,\"\")),t,\"\")}}function Wi(t){return function(){var n=arguments;switch(n.length){case 0:return new t;case 1:return new t(n[0]);case 2:return new t(n[0],n[1]);case 3:return new t(n[0],n[1],n[2]);case 4:return new t(n[0],n[1],n[2],n[3]);case 5:return new t(n[0],n[1],n[2],n[3],n[4]);case 6:return new t(n[0],n[1],n[2],n[3],n[4],n[5]);case 7:return new t(n[0],n[1],n[2],n[3],n[4],n[5],n[6])}var e=Ue(t.prototype),r=t.apply(e,n);return na(r)?r:e}}function Pi(t){return function(n,e,r){var o=kt(n);if(!Zu(n)){var u=fo(e,3);n=Ba(n),e=function(t){return u(o[t],t,o)}}var a=t(n,e,r);return a>-1?o[u?n[a]:a]:i}}function $i(t){return ro(function(n){var e=n.length,r=e,u=qe.prototype.thru;for(t&&n.reverse();r--;){var a=n[r];if(\"function\"!=typeof a)throw new St(o);if(u&&!c&&\"wrapper\"==ao(a))var c=new qe([],!0)}for(r=c?r:e;++r<e;){var f=ao(a=n[r]),l=\"wrapper\"==f?uo(a):i;c=l&&Ao(l[0])&&424==l[1]&&!l[4].length&&1==l[9]?c[ao(l[0])].apply(c,l[3]):1==a.length&&Ao(a)?c[f]():c.thru(a)}return function(){var t=arguments,r=t[0];if(c&&1==t.length&&Hu(r))return c.plant(r).value();for(var i=0,o=e?n[i].apply(this,t):r;++i<e;)o=n[i].call(this,o);return o}})}function Mi(t,n,e,o,u,a,c,f,l,h){var p=n&s,v=1&n,d=2&n,g=24&n,_=512&n,y=d?i:Wi(t);return function s(){for(var m=arguments.length,w=r(m),b=m;b--;)w[b]=arguments[b];if(g)var x=co(s),A=function(t,n){for(var e=t.length,r=0;e--;)t[e]===n&&++r;return r}(w,x);if(o&&(w=Ii(w,o,u,g)),a&&(w=Oi(w,a,c,g)),m-=A,g&&m<h){var E=se(w,x);return Gi(t,n,Mi,s.placeholder,e,w,E,f,l,h-m)}var R=v?e:this,j=d?R[t]:t;return m=w.length,f?w=function(t,n){var e=t.length,r=we(n.length,e),o=Si(t);for(;r--;){var u=n[r];t[r]=wo(u,e)?o[u]:i}return t}(w,f):_&&m>1&&w.reverse(),p&&l<m&&(w.length=l),this&&this!==gn&&this instanceof s&&(j=y||Wi(j)),j.apply(R,w)}}function Ui(t,n){return function(e,r){return function(t,n,e,r){return br(t,function(t,i,o){n(r,e(t),i,o)}),r}(e,t,n(r),{})}}function Ni(t,n){return function(e,r){var o;if(e===i&&r===i)return n;if(e!==i&&(o=e),r!==i){if(o===i)return r;\"string\"==typeof e||\"string\"==typeof r?(e=li(e),r=li(r)):(e=fi(e),r=fi(r)),o=t(e,r)}return o}}function qi(t){return ro(function(n){return n=Fn(n,te(fo())),Qr(function(e){var r=this;return t(n,function(t){return In(t,r,e)})})})}function Hi(t,n){var e=(n=n===i?\" \":li(n)).length;if(e<2)return e?Yr(n,t):n;var r=Yr(n,dn(t/ve(n)));return ce(n)?xi(de(r),0,t).join(\"\"):r.slice(0,t)}function Vi(t){return function(n,e,o){return o&&\"number\"!=typeof o&&bo(n,e,o)&&(e=o=i),n=va(n),e===i?(e=n,n=0):e=va(e),function(t,n,e,i){for(var o=-1,u=me(dn((n-t)/(e||1)),0),a=r(u);u--;)a[i?u:++o]=t,t+=e;return a}(n,e,o=o===i?n<e?1:-1:va(o),t)}}function Zi(t){return function(n,e){return\"string\"==typeof n&&\"string\"==typeof e||(n=_a(n),e=_a(e)),t(n,e)}}function Gi(t,n,e,r,o,u,a,c,s,h){var p=8&n;n|=p?f:l,4&(n&=~(p?l:f))||(n&=-4);var v=[t,n,o,p?u:i,p?a:i,p?i:u,p?i:a,c,s,h],d=e.apply(i,v);return Ao(t)&&Lo(d,v),d.placeholder=r,Co(d,t,n)}function Ki(t){var n=jt[t];return function(t,e){if(t=_a(t),(e=null==e?0:we(da(e),292))&&bn(t)){var r=(ma(t)+\"e\").split(\"e\");return+((r=(ma(n(r[0]+\"e\"+(+r[1]+e)))+\"e\").split(\"e\"))[0]+\"e\"+(+r[1]-e))}return n(t)}}var Yi=Ie&&1/he(new Ie([,-0]))[1]==p?function(t){return new Ie(t)}:fc;function Qi(t){return function(n){var e=go(n);return e==R?fe(n):e==S?pe(n):function(t,n){return Fn(n,function(n){return[n,t[n]]})}(n,t(n))}}function Ji(t,n,e,u,p,v,d,g){var _=2&n;if(!_&&\"function\"!=typeof t)throw new St(o);var y=u?u.length:0;if(y||(n&=-97,u=p=i),d=d===i?d:me(da(d),0),g=g===i?g:da(g),y-=p?p.length:0,n&l){var m=u,w=p;u=p=i}var b=_?i:uo(t),x=[t,n,e,u,p,m,w,v,d,g];if(b&&function(t,n){var e=t[1],r=n[1],i=e|r,o=i<131,u=r==s&&8==e||r==s&&e==h&&t[7].length<=n[8]||384==r&&n[7].length<=n[8]&&8==e;if(!o&&!u)return t;1&r&&(t[2]=n[2],i|=1&e?0:4);var c=n[3];if(c){var f=t[3];t[3]=f?Ii(f,c,n[4]):c,t[4]=f?se(t[3],a):n[4]}(c=n[5])&&(f=t[5],t[5]=f?Oi(f,c,n[6]):c,t[6]=f?se(t[5],a):n[6]);(c=n[7])&&(t[7]=c);r&s&&(t[8]=null==t[8]?n[8]:we(t[8],n[8]));null==t[9]&&(t[9]=n[9]);t[0]=n[0],t[1]=i}(x,b),t=x[0],n=x[1],e=x[2],u=x[3],p=x[4],!(g=x[9]=x[9]===i?_?0:t.length:me(x[9]-y,0))&&24&n&&(n&=-25),n&&1!=n)A=8==n||n==c?function(t,n,e){var o=Wi(t);return function u(){for(var a=arguments.length,c=r(a),f=a,l=co(u);f--;)c[f]=arguments[f];var s=a<3&&c[0]!==l&&c[a-1]!==l?[]:se(c,l);return(a-=s.length)<e?Gi(t,n,Mi,u.placeholder,i,c,s,i,i,e-a):In(this&&this!==gn&&this instanceof u?o:t,this,c)}}(t,n,g):n!=f&&33!=n||p.length?Mi.apply(i,x):function(t,n,e,i){var o=1&n,u=Wi(t);return function n(){for(var a=-1,c=arguments.length,f=-1,l=i.length,s=r(l+c),h=this&&this!==gn&&this instanceof n?u:t;++f<l;)s[f]=i[f];for(;c--;)s[f++]=arguments[++a];return In(h,o?e:this,s)}}(t,n,e,u);else var A=function(t,n,e){var r=1&n,i=Wi(t);return function n(){return(this&&this!==gn&&this instanceof n?i:t).apply(r?e:this,arguments)}}(t,n,e);return Co((b?ni:Lo)(A,x),t,n)}function Xi(t,n,e,r){return t===i||Mu(t,Tt[e])&&!Ft.call(r,e)?n:t}function to(t,n,e,r,o,u){return na(t)&&na(n)&&(u.set(n,t),Nr(t,n,i,to,u),u.delete(n)),t}function no(t){return oa(t)?i:t}function eo(t,n,e,r,o,u){var a=1&e,c=t.length,f=n.length;if(c!=f&&!(a&&f>c))return!1;var l=u.get(t),s=u.get(n);if(l&&s)return l==n&&s==t;var h=-1,p=!0,v=2&e?new Ke:i;for(u.set(t,n),u.set(n,t);++h<c;){var d=t[h],g=n[h];if(r)var _=a?r(g,d,h,n,t,u):r(d,g,h,t,n,u);if(_!==i){if(_)continue;p=!1;break}if(v){if(!$n(n,function(t,n){if(!ee(v,n)&&(d===t||o(d,t,e,r,u)))return v.push(n)})){p=!1;break}}else if(d!==g&&!o(d,g,e,r,u)){p=!1;break}}return u.delete(t),u.delete(n),p}function ro(t){return To(Io(t,i,Vo),t+\"\")}function io(t){return Rr(t,Ba,po)}function oo(t){return Rr(t,Ta,vo)}var uo=Le?function(t){return Le.get(t)}:fc;function ao(t){for(var n=t.name+\"\",e=Be[n],r=Ft.call(Be,n)?e.length:0;r--;){var i=e[r],o=i.func;if(null==o||o==t)return i.name}return n}function co(t){return(Ft.call(Me,\"placeholder\")?Me:t).placeholder}function fo(){var t=Me.iteratee||oc;return t=t===oc?Fr:t,arguments.length?t(arguments[0],arguments[1]):t}function lo(t,n){var e,r,i=t.__data__;return(\"string\"==(r=typeof(e=n))||\"number\"==r||\"symbol\"==r||\"boolean\"==r?\"__proto__\"!==e:null===e)?i[\"string\"==typeof n?\"string\":\"hash\"]:i.map}function so(t){for(var n=Ba(t),e=n.length;e--;){var r=n[e],i=t[r];n[e]=[r,i,jo(i)]}return n}function ho(t,n){var e=function(t,n){return null==t?i:t[n]}(t,n);return zr(e)?e:i}var po=yn?function(t){return null==t?[]:(t=kt(t),Tn(yn(t),function(n){return Kt.call(t,n)}))}:gc,vo=yn?function(t){for(var n=[];t;)Dn(n,po(t)),t=Zt(t);return n}:gc,go=jr;function _o(t,n,e){for(var r=-1,i=(n=wi(n,t)).length,o=!1;++r<i;){var u=Wo(n[r]);if(!(o=null!=t&&e(t,u)))break;t=t[u]}return o||++r!=i?o:!!(i=null==t?0:t.length)&&ta(i)&&wo(u,i)&&(Hu(t)||qu(t))}function yo(t){return\"function\"!=typeof t.constructor||Ro(t)?{}:Ue(Zt(t))}function mo(t){return Hu(t)||qu(t)||!!(Qt&&t&&t[Qt])}function wo(t,n){var e=typeof t;return!!(n=null==n?v:n)&&(\"number\"==e||\"symbol\"!=e&&wt.test(t))&&t>-1&&t%1==0&&t<n}function bo(t,n,e){if(!na(e))return!1;var r=typeof n;return!!(\"number\"==r?Zu(e)&&wo(n,e.length):\"string\"==r&&n in e)&&Mu(e[n],t)}function xo(t,n){if(Hu(t))return!1;var e=typeof t;return!(\"number\"!=e&&\"symbol\"!=e&&\"boolean\"!=e&&null!=t&&!fa(t))||(et.test(t)||!nt.test(t)||null!=n&&t in kt(n))}function Ao(t){var n=ao(t),e=Me[n];if(\"function\"!=typeof e||!(n in He.prototype))return!1;if(t===e)return!0;var r=uo(e);return!!r&&t===r[0]}(Re&&go(new Re(new ArrayBuffer(1)))!=z||je&&go(new je)!=R||ke&&go(ke.resolve())!=I||Ie&&go(new Ie)!=S||Oe&&go(new Oe)!=T)&&(go=function(t){var n=jr(t),e=n==k?t.constructor:i,r=e?Po(e):\"\";if(r)switch(r){case Te:return z;case Ce:return R;case ze:return I;case Fe:return S;case De:return T}return n});var Eo=Ct?Ju:_c;function Ro(t){var n=t&&t.constructor;return t===(\"function\"==typeof n&&n.prototype||Tt)}function jo(t){return t==t&&!na(t)}function ko(t,n){return function(e){return null!=e&&(e[t]===n&&(n!==i||t in kt(e)))}}function Io(t,n,e){return n=me(n===i?t.length-1:n,0),function(){for(var i=arguments,o=-1,u=me(i.length-n,0),a=r(u);++o<u;)a[o]=i[n+o];o=-1;for(var c=r(n+1);++o<n;)c[o]=i[o];return c[n]=e(a),In(t,this,c)}}function Oo(t,n){return n.length<2?t:Er(t,ii(n,0,-1))}function So(t,n){if((\"constructor\"!==n||\"function\"!=typeof t[n])&&\"__proto__\"!=n)return t[n]}var Lo=zo(ni),Bo=vn||function(t,n){return gn.setTimeout(t,n)},To=zo(ei);function Co(t,n,e){var r=n+\"\";return To(t,function(t,n){var e=n.length;if(!e)return t;var r=e-1;return n[r]=(e>1?\"& \":\"\")+n[r],n=n.join(e>2?\", \":\" \"),t.replace(ct,\"{\\n/* [wrapped with \"+n+\"] */\\n\")}(r,function(t,n){return Sn(_,function(e){var r=\"_.\"+e[0];n&e[1]&&!Cn(t,r)&&t.push(r)}),t.sort()}(function(t){var n=t.match(ft);return n?n[1].split(lt):[]}(r),e)))}function zo(t){var n=0,e=0;return function(){var r=be(),o=16-(r-e);if(e=r,o>0){if(++n>=800)return arguments[0]}else n=0;return t.apply(i,arguments)}}function Fo(t,n){var e=-1,r=t.length,o=r-1;for(n=n===i?r:n;++e<n;){var u=Kr(e,o),a=t[u];t[u]=t[e],t[e]=a}return t.length=n,t}var Do=function(t){var n=zu(t,function(t){return 500===e.size&&e.clear(),t}),e=n.cache;return n}(function(t){var n=[];return 46===t.charCodeAt(0)&&n.push(\"\"),t.replace(rt,function(t,e,r,i){n.push(r?i.replace(pt,\"$1\"):e||t)}),n});function Wo(t){if(\"string\"==typeof t||fa(t))return t;var n=t+\"\";return\"0\"==n&&1/t==-1/0?\"-0\":n}function Po(t){if(null!=t){try{return zt.call(t)}catch(t){}try{return t+\"\"}catch(t){}}return\"\"}function $o(t){if(t instanceof He)return t.clone();var n=new qe(t.__wrapped__,t.__chain__);return n.__actions__=Si(t.__actions__),n.__index__=t.__index__,n.__values__=t.__values__,n}var Mo=Qr(function(t,n){return Gu(t)?hr(t,yr(n,1,Gu,!0)):[]}),Uo=Qr(function(t,n){var e=Qo(n);return Gu(e)&&(e=i),Gu(t)?hr(t,yr(n,1,Gu,!0),fo(e,2)):[]}),No=Qr(function(t,n){var e=Qo(n);return Gu(e)&&(e=i),Gu(t)?hr(t,yr(n,1,Gu,!0),i,e):[]});function qo(t,n,e){var r=null==t?0:t.length;if(!r)return-1;var i=null==e?0:da(e);return i<0&&(i=me(r+i,0)),Nn(t,fo(n,3),i)}function Ho(t,n,e){var r=null==t?0:t.length;if(!r)return-1;var o=r-1;return e!==i&&(o=da(e),o=e<0?me(r+o,0):we(o,r-1)),Nn(t,fo(n,3),o,!0)}function Vo(t){return(null==t?0:t.length)?yr(t,1):[]}function Zo(t){return t&&t.length?t[0]:i}var Go=Qr(function(t){var n=Fn(t,yi);return n.length&&n[0]===t[0]?Sr(n):[]}),Ko=Qr(function(t){var n=Qo(t),e=Fn(t,yi);return n===Qo(e)?n=i:e.pop(),e.length&&e[0]===t[0]?Sr(e,fo(n,2)):[]}),Yo=Qr(function(t){var n=Qo(t),e=Fn(t,yi);return(n=\"function\"==typeof n?n:i)&&e.pop(),e.length&&e[0]===t[0]?Sr(e,i,n):[]});function Qo(t){var n=null==t?0:t.length;return n?t[n-1]:i}var Jo=Qr(Xo);function Xo(t,n){return t&&t.length&&n&&n.length?Zr(t,n):t}var tu=ro(function(t,n){var e=null==t?0:t.length,r=ar(t,n);return Gr(t,Fn(n,function(t){return wo(t,e)?+t:t}).sort(ki)),r});function nu(t){return null==t?t:Ee.call(t)}var eu=Qr(function(t){return si(yr(t,1,Gu,!0))}),ru=Qr(function(t){var n=Qo(t);return Gu(n)&&(n=i),si(yr(t,1,Gu,!0),fo(n,2))}),iu=Qr(function(t){var n=Qo(t);return n=\"function\"==typeof n?n:i,si(yr(t,1,Gu,!0),i,n)});function ou(t){if(!t||!t.length)return[];var n=0;return t=Tn(t,function(t){if(Gu(t))return n=me(t.length,n),!0}),Jn(n,function(n){return Fn(t,Gn(n))})}function uu(t,n){if(!t||!t.length)return[];var e=ou(t);return null==n?e:Fn(e,function(t){return In(n,i,t)})}var au=Qr(function(t,n){return Gu(t)?hr(t,n):[]}),cu=Qr(function(t){return gi(Tn(t,Gu))}),fu=Qr(function(t){var n=Qo(t);return Gu(n)&&(n=i),gi(Tn(t,Gu),fo(n,2))}),lu=Qr(function(t){var n=Qo(t);return n=\"function\"==typeof n?n:i,gi(Tn(t,Gu),i,n)}),su=Qr(ou);var hu=Qr(function(t){var n=t.length,e=n>1?t[n-1]:i;return e=\"function\"==typeof e?(t.pop(),e):i,uu(t,e)});function pu(t){var n=Me(t);return n.__chain__=!0,n}function vu(t,n){return n(t)}var du=ro(function(t){var n=t.length,e=n?t[0]:0,r=this.__wrapped__,o=function(n){return ar(n,t)};return!(n>1||this.__actions__.length)&&r instanceof He&&wo(e)?((r=r.slice(e,+e+(n?1:0))).__actions__.push({func:vu,args:[o],thisArg:i}),new qe(r,this.__chain__).thru(function(t){return n&&!t.length&&t.push(i),t})):this.thru(o)});var gu=Bi(function(t,n,e){Ft.call(t,e)?++t[e]:ur(t,e,1)});var _u=Pi(qo),yu=Pi(Ho);function mu(t,n){return(Hu(t)?Sn:pr)(t,fo(n,3))}function wu(t,n){return(Hu(t)?Ln:vr)(t,fo(n,3))}var bu=Bi(function(t,n,e){Ft.call(t,e)?t[e].push(n):ur(t,e,[n])});var xu=Qr(function(t,n,e){var i=-1,o=\"function\"==typeof n,u=Zu(t)?r(t.length):[];return pr(t,function(t){u[++i]=o?In(n,t,e):Lr(t,n,e)}),u}),Au=Bi(function(t,n,e){ur(t,e,n)});function Eu(t,n){return(Hu(t)?Fn:$r)(t,fo(n,3))}var Ru=Bi(function(t,n,e){t[e?0:1].push(n)},function(){return[[],[]]});var ju=Qr(function(t,n){if(null==t)return[];var e=n.length;return e>1&&bo(t,n[0],n[1])?n=[]:e>2&&bo(n[0],n[1],n[2])&&(n=[n[0]]),Hr(t,yr(n,1),[])}),ku=sn||function(){return gn.Date.now()};function Iu(t,n,e){return n=e?i:n,n=t&&null==n?t.length:n,Ji(t,s,i,i,i,i,n)}function Ou(t,n){var e;if(\"function\"!=typeof n)throw new St(o);return t=da(t),function(){return--t>0&&(e=n.apply(this,arguments)),t<=1&&(n=i),e}}var Su=Qr(function(t,n,e){var r=1;if(e.length){var i=se(e,co(Su));r|=f}return Ji(t,r,n,e,i)}),Lu=Qr(function(t,n,e){var r=3;if(e.length){var i=se(e,co(Lu));r|=f}return Ji(n,r,t,e,i)});function Bu(t,n,e){var r,u,a,c,f,l,s=0,h=!1,p=!1,v=!0;if(\"function\"!=typeof t)throw new St(o);function d(n){var e=r,o=u;return r=u=i,s=n,c=t.apply(o,e)}function g(t){var e=t-l;return l===i||e>=n||e<0||p&&t-s>=a}function _(){var t=ku();if(g(t))return y(t);f=Bo(_,function(t){var e=n-(t-l);return p?we(e,a-(t-s)):e}(t))}function y(t){return f=i,v&&r?d(t):(r=u=i,c)}function m(){var t=ku(),e=g(t);if(r=arguments,u=this,l=t,e){if(f===i)return function(t){return s=t,f=Bo(_,n),h?d(t):c}(l);if(p)return Ai(f),f=Bo(_,n),d(l)}return f===i&&(f=Bo(_,n)),c}return n=_a(n)||0,na(e)&&(h=!!e.leading,a=(p=\"maxWait\"in e)?me(_a(e.maxWait)||0,n):a,v=\"trailing\"in e?!!e.trailing:v),m.cancel=function(){f!==i&&Ai(f),s=0,r=l=u=f=i},m.flush=function(){return f===i?c:y(ku())},m}var Tu=Qr(function(t,n){return sr(t,1,n)}),Cu=Qr(function(t,n,e){return sr(t,_a(n)||0,e)});function zu(t,n){if(\"function\"!=typeof t||null!=n&&\"function\"!=typeof n)throw new St(o);var e=function(){var r=arguments,i=n?n.apply(this,r):r[0],o=e.cache;if(o.has(i))return o.get(i);var u=t.apply(this,r);return e.cache=o.set(i,u)||o,u};return e.cache=new(zu.Cache||Ge),e}function Fu(t){if(\"function\"!=typeof t)throw new St(o);return function(){var n=arguments;switch(n.length){case 0:return!t.call(this);case 1:return!t.call(this,n[0]);case 2:return!t.call(this,n[0],n[1]);case 3:return!t.call(this,n[0],n[1],n[2])}return!t.apply(this,n)}}zu.Cache=Ge;var Du=bi(function(t,n){var e=(n=1==n.length&&Hu(n[0])?Fn(n[0],te(fo())):Fn(yr(n,1),te(fo()))).length;return Qr(function(r){for(var i=-1,o=we(r.length,e);++i<o;)r[i]=n[i].call(this,r[i]);return In(t,this,r)})}),Wu=Qr(function(t,n){var e=se(n,co(Wu));return Ji(t,f,i,n,e)}),Pu=Qr(function(t,n){var e=se(n,co(Pu));return Ji(t,l,i,n,e)}),$u=ro(function(t,n){return Ji(t,h,i,i,i,n)});function Mu(t,n){return t===n||t!=t&&n!=n}var Uu=Zi(kr),Nu=Zi(function(t,n){return t>=n}),qu=Br(function(){return arguments}())?Br:function(t){return ea(t)&&Ft.call(t,\"callee\")&&!Kt.call(t,\"callee\")},Hu=r.isArray,Vu=xn?te(xn):function(t){return ea(t)&&jr(t)==C};function Zu(t){return null!=t&&ta(t.length)&&!Ju(t)}function Gu(t){return ea(t)&&Zu(t)}var Ku=wn||_c,Yu=An?te(An):function(t){return ea(t)&&jr(t)==b};function Qu(t){if(!ea(t))return!1;var n=jr(t);return n==x||\"[object DOMException]\"==n||\"string\"==typeof t.message&&\"string\"==typeof t.name&&!oa(t)}function Ju(t){if(!na(t))return!1;var n=jr(t);return n==A||n==E||\"[object AsyncFunction]\"==n||\"[object Proxy]\"==n}function Xu(t){return\"number\"==typeof t&&t==da(t)}function ta(t){return\"number\"==typeof t&&t>-1&&t%1==0&&t<=v}function na(t){var n=typeof t;return null!=t&&(\"object\"==n||\"function\"==n)}function ea(t){return null!=t&&\"object\"==typeof t}var ra=En?te(En):function(t){return ea(t)&&go(t)==R};function ia(t){return\"number\"==typeof t||ea(t)&&jr(t)==j}function oa(t){if(!ea(t)||jr(t)!=k)return!1;var n=Zt(t);if(null===n)return!0;var e=Ft.call(n,\"constructor\")&&n.constructor;return\"function\"==typeof e&&e instanceof e&&zt.call(e)==$t}var ua=Rn?te(Rn):function(t){return ea(t)&&jr(t)==O};var aa=jn?te(jn):function(t){return ea(t)&&go(t)==S};function ca(t){return\"string\"==typeof t||!Hu(t)&&ea(t)&&jr(t)==L}function fa(t){return\"symbol\"==typeof t||ea(t)&&jr(t)==B}var la=kn?te(kn):function(t){return ea(t)&&ta(t.length)&&!!fn[jr(t)]};var sa=Zi(Pr),ha=Zi(function(t,n){return t<=n});function pa(t){if(!t)return[];if(Zu(t))return ca(t)?de(t):Si(t);if(Jt&&t[Jt])return function(t){for(var n,e=[];!(n=t.next()).done;)e.push(n.value);return e}(t[Jt]());var n=go(t);return(n==R?fe:n==S?he:Ma)(t)}function va(t){return t?(t=_a(t))===p||t===-1/0?17976931348623157e292*(t<0?-1:1):t==t?t:0:0===t?t:0}function da(t){var n=va(t),e=n%1;return n==n?e?n-e:n:0}function ga(t){return t?cr(da(t),0,g):0}function _a(t){if(\"number\"==typeof t)return t;if(fa(t))return d;if(na(t)){var n=\"function\"==typeof t.valueOf?t.valueOf():t;t=na(n)?n+\"\":n}if(\"string\"!=typeof t)return 0===t?t:+t;t=Xn(t);var e=_t.test(t);return e||mt.test(t)?pn(t.slice(2),e?2:8):gt.test(t)?d:+t}function ya(t){return Li(t,Ta(t))}function ma(t){return null==t?\"\":li(t)}var wa=Ti(function(t,n){if(Ro(n)||Zu(n))Li(n,Ba(n),t);else for(var e in n)Ft.call(n,e)&&er(t,e,n[e])}),ba=Ti(function(t,n){Li(n,Ta(n),t)}),xa=Ti(function(t,n,e,r){Li(n,Ta(n),t,r)}),Aa=Ti(function(t,n,e,r){Li(n,Ba(n),t,r)}),Ea=ro(ar);var Ra=Qr(function(t,n){t=kt(t);var e=-1,r=n.length,o=r>2?n[2]:i;for(o&&bo(n[0],n[1],o)&&(r=1);++e<r;)for(var u=n[e],a=Ta(u),c=-1,f=a.length;++c<f;){var l=a[c],s=t[l];(s===i||Mu(s,Tt[l])&&!Ft.call(t,l))&&(t[l]=u[l])}return t}),ja=Qr(function(t){return t.push(i,to),In(za,i,t)});function ka(t,n,e){var r=null==t?i:Er(t,n);return r===i?e:r}function Ia(t,n){return null!=t&&_o(t,n,Or)}var Oa=Ui(function(t,n,e){null!=n&&\"function\"!=typeof n.toString&&(n=Pt.call(n)),t[n]=e},nc(ic)),Sa=Ui(function(t,n,e){null!=n&&\"function\"!=typeof n.toString&&(n=Pt.call(n)),Ft.call(t,n)?t[n].push(e):t[n]=[e]},fo),La=Qr(Lr);function Ba(t){return Zu(t)?Qe(t):Dr(t)}function Ta(t){return Zu(t)?Qe(t,!0):Wr(t)}var Ca=Ti(function(t,n,e){Nr(t,n,e)}),za=Ti(function(t,n,e,r){Nr(t,n,e,r)}),Fa=ro(function(t,n){var e={};if(null==t)return e;var r=!1;n=Fn(n,function(n){return n=wi(n,t),r||(r=n.length>1),n}),Li(t,oo(t),e),r&&(e=fr(e,7,no));for(var i=n.length;i--;)hi(e,n[i]);return e});var Da=ro(function(t,n){return null==t?{}:function(t,n){return Vr(t,n,function(n,e){return Ia(t,e)})}(t,n)});function Wa(t,n){if(null==t)return{};var e=Fn(oo(t),function(t){return[t]});return n=fo(n),Vr(t,e,function(t,e){return n(t,e[0])})}var Pa=Qi(Ba),$a=Qi(Ta);function Ma(t){return null==t?[]:ne(t,Ba(t))}var Ua=Di(function(t,n,e){return n=n.toLowerCase(),t+(e?Na(n):n)});function Na(t){return Qa(ma(t).toLowerCase())}function qa(t){return(t=ma(t))&&t.replace(bt,oe).replace(nn,\"\")}var Ha=Di(function(t,n,e){return t+(e?\"-\":\"\")+n.toLowerCase()}),Va=Di(function(t,n,e){return t+(e?\" \":\"\")+n.toLowerCase()}),Za=Fi(\"toLowerCase\");var Ga=Di(function(t,n,e){return t+(e?\"_\":\"\")+n.toLowerCase()});var Ka=Di(function(t,n,e){return t+(e?\" \":\"\")+Qa(n)});var Ya=Di(function(t,n,e){return t+(e?\" \":\"\")+n.toUpperCase()}),Qa=Fi(\"toUpperCase\");function Ja(t,n,e){return t=ma(t),(n=e?i:n)===i?function(t){return un.test(t)}(t)?function(t){return t.match(rn)||[]}(t):function(t){return t.match(st)||[]}(t):t.match(n)||[]}var Xa=Qr(function(t,n){try{return In(t,i,n)}catch(t){return Qu(t)?t:new Et(t)}}),tc=ro(function(t,n){return Sn(n,function(n){n=Wo(n),ur(t,n,Su(t[n],t))}),t});function nc(t){return function(){return t}}var ec=$i(),rc=$i(!0);function ic(t){return t}function oc(t){return Fr(\"function\"==typeof t?t:fr(t,1))}var uc=Qr(function(t,n){return function(e){return Lr(e,t,n)}}),ac=Qr(function(t,n){return function(e){return Lr(t,e,n)}});function cc(t,n,e){var r=Ba(n),i=Ar(n,r);null!=e||na(n)&&(i.length||!r.length)||(e=n,n=t,t=this,i=Ar(n,Ba(n)));var o=!(na(e)&&\"chain\"in e&&!e.chain),u=Ju(t);return Sn(i,function(e){var r=n[e];t[e]=r,u&&(t.prototype[e]=function(){var n=this.__chain__;if(o||n){var e=t(this.__wrapped__);return(e.__actions__=Si(this.__actions__)).push({func:r,args:arguments,thisArg:t}),e.__chain__=n,e}return r.apply(t,Dn([this.value()],arguments))})}),t}function fc(){}var lc=qi(Fn),sc=qi(Bn),hc=qi($n);function pc(t){return xo(t)?Gn(Wo(t)):function(t){return function(n){return Er(n,t)}}(t)}var vc=Vi(),dc=Vi(!0);function gc(){return[]}function _c(){return!1}var yc=Ni(function(t,n){return t+n},0),mc=Ki(\"ceil\"),wc=Ni(function(t,n){return t/n},1),bc=Ki(\"floor\");var xc,Ac=Ni(function(t,n){return t*n},1),Ec=Ki(\"round\"),Rc=Ni(function(t,n){return t-n},0);return Me.after=function(t,n){if(\"function\"!=typeof n)throw new St(o);return t=da(t),function(){if(--t<1)return n.apply(this,arguments)}},Me.ary=Iu,Me.assign=wa,Me.assignIn=ba,Me.assignInWith=xa,Me.assignWith=Aa,Me.at=Ea,Me.before=Ou,Me.bind=Su,Me.bindAll=tc,Me.bindKey=Lu,Me.castArray=function(){if(!arguments.length)return[];var t=arguments[0];return Hu(t)?t:[t]},Me.chain=pu,Me.chunk=function(t,n,e){n=(e?bo(t,n,e):n===i)?1:me(da(n),0);var o=null==t?0:t.length;if(!o||n<1)return[];for(var u=0,a=0,c=r(dn(o/n));u<o;)c[a++]=ii(t,u,u+=n);return c},Me.compact=function(t){for(var n=-1,e=null==t?0:t.length,r=0,i=[];++n<e;){var o=t[n];o&&(i[r++]=o)}return i},Me.concat=function(){var t=arguments.length;if(!t)return[];for(var n=r(t-1),e=arguments[0],i=t;i--;)n[i-1]=arguments[i];return Dn(Hu(e)?Si(e):[e],yr(n,1))},Me.cond=function(t){var n=null==t?0:t.length,e=fo();return t=n?Fn(t,function(t){if(\"function\"!=typeof t[1])throw new St(o);return[e(t[0]),t[1]]}):[],Qr(function(e){for(var r=-1;++r<n;){var i=t[r];if(In(i[0],this,e))return In(i[1],this,e)}})},Me.conforms=function(t){return function(t){var n=Ba(t);return function(e){return lr(e,t,n)}}(fr(t,1))},Me.constant=nc,Me.countBy=gu,Me.create=function(t,n){var e=Ue(t);return null==n?e:or(e,n)},Me.curry=function t(n,e,r){var o=Ji(n,8,i,i,i,i,i,e=r?i:e);return o.placeholder=t.placeholder,o},Me.curryRight=function t(n,e,r){var o=Ji(n,c,i,i,i,i,i,e=r?i:e);return o.placeholder=t.placeholder,o},Me.debounce=Bu,Me.defaults=Ra,Me.defaultsDeep=ja,Me.defer=Tu,Me.delay=Cu,Me.difference=Mo,Me.differenceBy=Uo,Me.differenceWith=No,Me.drop=function(t,n,e){var r=null==t?0:t.length;return r?ii(t,(n=e||n===i?1:da(n))<0?0:n,r):[]},Me.dropRight=function(t,n,e){var r=null==t?0:t.length;return r?ii(t,0,(n=r-(n=e||n===i?1:da(n)))<0?0:n):[]},Me.dropRightWhile=function(t,n){return t&&t.length?vi(t,fo(n,3),!0,!0):[]},Me.dropWhile=function(t,n){return t&&t.length?vi(t,fo(n,3),!0):[]},Me.fill=function(t,n,e,r){var o=null==t?0:t.length;return o?(e&&\"number\"!=typeof e&&bo(t,n,e)&&(e=0,r=o),function(t,n,e,r){var o=t.length;for((e=da(e))<0&&(e=-e>o?0:o+e),(r=r===i||r>o?o:da(r))<0&&(r+=o),r=e>r?0:ga(r);e<r;)t[e++]=n;return t}(t,n,e,r)):[]},Me.filter=function(t,n){return(Hu(t)?Tn:_r)(t,fo(n,3))},Me.flatMap=function(t,n){return yr(Eu(t,n),1)},Me.flatMapDeep=function(t,n){return yr(Eu(t,n),p)},Me.flatMapDepth=function(t,n,e){return e=e===i?1:da(e),yr(Eu(t,n),e)},Me.flatten=Vo,Me.flattenDeep=function(t){return(null==t?0:t.length)?yr(t,p):[]},Me.flattenDepth=function(t,n){return(null==t?0:t.length)?yr(t,n=n===i?1:da(n)):[]},Me.flip=function(t){return Ji(t,512)},Me.flow=ec,Me.flowRight=rc,Me.fromPairs=function(t){for(var n=-1,e=null==t?0:t.length,r={};++n<e;){var i=t[n];r[i[0]]=i[1]}return r},Me.functions=function(t){return null==t?[]:Ar(t,Ba(t))},Me.functionsIn=function(t){return null==t?[]:Ar(t,Ta(t))},Me.groupBy=bu,Me.initial=function(t){return(null==t?0:t.length)?ii(t,0,-1):[]},Me.intersection=Go,Me.intersectionBy=Ko,Me.intersectionWith=Yo,Me.invert=Oa,Me.invertBy=Sa,Me.invokeMap=xu,Me.iteratee=oc,Me.keyBy=Au,Me.keys=Ba,Me.keysIn=Ta,Me.map=Eu,Me.mapKeys=function(t,n){var e={};return n=fo(n,3),br(t,function(t,r,i){ur(e,n(t,r,i),t)}),e},Me.mapValues=function(t,n){var e={};return n=fo(n,3),br(t,function(t,r,i){ur(e,r,n(t,r,i))}),e},Me.matches=function(t){return Mr(fr(t,1))},Me.matchesProperty=function(t,n){return Ur(t,fr(n,1))},Me.memoize=zu,Me.merge=Ca,Me.mergeWith=za,Me.method=uc,Me.methodOf=ac,Me.mixin=cc,Me.negate=Fu,Me.nthArg=function(t){return t=da(t),Qr(function(n){return qr(n,t)})},Me.omit=Fa,Me.omitBy=function(t,n){return Wa(t,Fu(fo(n)))},Me.once=function(t){return Ou(2,t)},Me.orderBy=function(t,n,e,r){return null==t?[]:(Hu(n)||(n=null==n?[]:[n]),Hu(e=r?i:e)||(e=null==e?[]:[e]),Hr(t,n,e))},Me.over=lc,Me.overArgs=Du,Me.overEvery=sc,Me.overSome=hc,Me.partial=Wu,Me.partialRight=Pu,Me.partition=Ru,Me.pick=Da,Me.pickBy=Wa,Me.property=pc,Me.propertyOf=function(t){return function(n){return null==t?i:Er(t,n)}},Me.pull=Jo,Me.pullAll=Xo,Me.pullAllBy=function(t,n,e){return t&&t.length&&n&&n.length?Zr(t,n,fo(e,2)):t},Me.pullAllWith=function(t,n,e){return t&&t.length&&n&&n.length?Zr(t,n,i,e):t},Me.pullAt=tu,Me.range=vc,Me.rangeRight=dc,Me.rearg=$u,Me.reject=function(t,n){return(Hu(t)?Tn:_r)(t,Fu(fo(n,3)))},Me.remove=function(t,n){var e=[];if(!t||!t.length)return e;var r=-1,i=[],o=t.length;for(n=fo(n,3);++r<o;){var u=t[r];n(u,r,t)&&(e.push(u),i.push(r))}return Gr(t,i),e},Me.rest=function(t,n){if(\"function\"!=typeof t)throw new St(o);return Qr(t,n=n===i?n:da(n))},Me.reverse=nu,Me.sampleSize=function(t,n,e){return n=(e?bo(t,n,e):n===i)?1:da(n),(Hu(t)?Xe:Xr)(t,n)},Me.set=function(t,n,e){return null==t?t:ti(t,n,e)},Me.setWith=function(t,n,e,r){return r=\"function\"==typeof r?r:i,null==t?t:ti(t,n,e,r)},Me.shuffle=function(t){return(Hu(t)?tr:ri)(t)},Me.slice=function(t,n,e){var r=null==t?0:t.length;return r?(e&&\"number\"!=typeof e&&bo(t,n,e)?(n=0,e=r):(n=null==n?0:da(n),e=e===i?r:da(e)),ii(t,n,e)):[]},Me.sortBy=ju,Me.sortedUniq=function(t){return t&&t.length?ci(t):[]},Me.sortedUniqBy=function(t,n){return t&&t.length?ci(t,fo(n,2)):[]},Me.split=function(t,n,e){return e&&\"number\"!=typeof e&&bo(t,n,e)&&(n=e=i),(e=e===i?g:e>>>0)?(t=ma(t))&&(\"string\"==typeof n||null!=n&&!ua(n))&&!(n=li(n))&&ce(t)?xi(de(t),0,e):t.split(n,e):[]},Me.spread=function(t,n){if(\"function\"!=typeof t)throw new St(o);return n=null==n?0:me(da(n),0),Qr(function(e){var r=e[n],i=xi(e,0,n);return r&&Dn(i,r),In(t,this,i)})},Me.tail=function(t){var n=null==t?0:t.length;return n?ii(t,1,n):[]},Me.take=function(t,n,e){return t&&t.length?ii(t,0,(n=e||n===i?1:da(n))<0?0:n):[]},Me.takeRight=function(t,n,e){var r=null==t?0:t.length;return r?ii(t,(n=r-(n=e||n===i?1:da(n)))<0?0:n,r):[]},Me.takeRightWhile=function(t,n){return t&&t.length?vi(t,fo(n,3),!1,!0):[]},Me.takeWhile=function(t,n){return t&&t.length?vi(t,fo(n,3)):[]},Me.tap=function(t,n){return n(t),t},Me.throttle=function(t,n,e){var r=!0,i=!0;if(\"function\"!=typeof t)throw new St(o);return na(e)&&(r=\"leading\"in e?!!e.leading:r,i=\"trailing\"in e?!!e.trailing:i),Bu(t,n,{leading:r,maxWait:n,trailing:i})},Me.thru=vu,Me.toArray=pa,Me.toPairs=Pa,Me.toPairsIn=$a,Me.toPath=function(t){return Hu(t)?Fn(t,Wo):fa(t)?[t]:Si(Do(ma(t)))},Me.toPlainObject=ya,Me.transform=function(t,n,e){var r=Hu(t),i=r||Ku(t)||la(t);if(n=fo(n,4),null==e){var o=t&&t.constructor;e=i?r?new o:[]:na(t)&&Ju(o)?Ue(Zt(t)):{}}return(i?Sn:br)(t,function(t,r,i){return n(e,t,r,i)}),e},Me.unary=function(t){return Iu(t,1)},Me.union=eu,Me.unionBy=ru,Me.unionWith=iu,Me.uniq=function(t){return t&&t.length?si(t):[]},Me.uniqBy=function(t,n){return t&&t.length?si(t,fo(n,2)):[]},Me.uniqWith=function(t,n){return n=\"function\"==typeof n?n:i,t&&t.length?si(t,i,n):[]},Me.unset=function(t,n){return null==t||hi(t,n)},Me.unzip=ou,Me.unzipWith=uu,Me.update=function(t,n,e){return null==t?t:pi(t,n,mi(e))},Me.updateWith=function(t,n,e,r){return r=\"function\"==typeof r?r:i,null==t?t:pi(t,n,mi(e),r)},Me.values=Ma,Me.valuesIn=function(t){return null==t?[]:ne(t,Ta(t))},Me.without=au,Me.words=Ja,Me.wrap=function(t,n){return Wu(mi(n),t)},Me.xor=cu,Me.xorBy=fu,Me.xorWith=lu,Me.zip=su,Me.zipObject=function(t,n){return _i(t||[],n||[],er)},Me.zipObjectDeep=function(t,n){return _i(t||[],n||[],ti)},Me.zipWith=hu,Me.entries=Pa,Me.entriesIn=$a,Me.extend=ba,Me.extendWith=xa,cc(Me,Me),Me.add=yc,Me.attempt=Xa,Me.camelCase=Ua,Me.capitalize=Na,Me.ceil=mc,Me.clamp=function(t,n,e){return e===i&&(e=n,n=i),e!==i&&(e=(e=_a(e))==e?e:0),n!==i&&(n=(n=_a(n))==n?n:0),cr(_a(t),n,e)},Me.clone=function(t){return fr(t,4)},Me.cloneDeep=function(t){return fr(t,5)},Me.cloneDeepWith=function(t,n){return fr(t,5,n=\"function\"==typeof n?n:i)},Me.cloneWith=function(t,n){return fr(t,4,n=\"function\"==typeof n?n:i)},Me.conformsTo=function(t,n){return null==n||lr(t,n,Ba(n))},Me.deburr=qa,Me.defaultTo=function(t,n){return null==t||t!=t?n:t},Me.divide=wc,Me.endsWith=function(t,n,e){t=ma(t),n=li(n);var r=t.length,o=e=e===i?r:cr(da(e),0,r);return(e-=n.length)>=0&&t.slice(e,o)==n},Me.eq=Mu,Me.escape=function(t){return(t=ma(t))&&Q.test(t)?t.replace(K,ue):t},Me.escapeRegExp=function(t){return(t=ma(t))&&ot.test(t)?t.replace(it,\"\\\\$&\"):t},Me.every=function(t,n,e){var r=Hu(t)?Bn:dr;return e&&bo(t,n,e)&&(n=i),r(t,fo(n,3))},Me.find=_u,Me.findIndex=qo,Me.findKey=function(t,n){return Un(t,fo(n,3),br)},Me.findLast=yu,Me.findLastIndex=Ho,Me.findLastKey=function(t,n){return Un(t,fo(n,3),xr)},Me.floor=bc,Me.forEach=mu,Me.forEachRight=wu,Me.forIn=function(t,n){return null==t?t:mr(t,fo(n,3),Ta)},Me.forInRight=function(t,n){return null==t?t:wr(t,fo(n,3),Ta)},Me.forOwn=function(t,n){return t&&br(t,fo(n,3))},Me.forOwnRight=function(t,n){return t&&xr(t,fo(n,3))},Me.get=ka,Me.gt=Uu,Me.gte=Nu,Me.has=function(t,n){return null!=t&&_o(t,n,Ir)},Me.hasIn=Ia,Me.head=Zo,Me.identity=ic,Me.includes=function(t,n,e,r){t=Zu(t)?t:Ma(t),e=e&&!r?da(e):0;var i=t.length;return e<0&&(e=me(i+e,0)),ca(t)?e<=i&&t.indexOf(n,e)>-1:!!i&&qn(t,n,e)>-1},Me.indexOf=function(t,n,e){var r=null==t?0:t.length;if(!r)return-1;var i=null==e?0:da(e);return i<0&&(i=me(r+i,0)),qn(t,n,i)},Me.inRange=function(t,n,e){return n=va(n),e===i?(e=n,n=0):e=va(e),function(t,n,e){return t>=we(n,e)&&t<me(n,e)}(t=_a(t),n,e)},Me.invoke=La,Me.isArguments=qu,Me.isArray=Hu,Me.isArrayBuffer=Vu,Me.isArrayLike=Zu,Me.isArrayLikeObject=Gu,Me.isBoolean=function(t){return!0===t||!1===t||ea(t)&&jr(t)==w},Me.isBuffer=Ku,Me.isDate=Yu,Me.isElement=function(t){return ea(t)&&1===t.nodeType&&!oa(t)},Me.isEmpty=function(t){if(null==t)return!0;if(Zu(t)&&(Hu(t)||\"string\"==typeof t||\"function\"==typeof t.splice||Ku(t)||la(t)||qu(t)))return!t.length;var n=go(t);if(n==R||n==S)return!t.size;if(Ro(t))return!Dr(t).length;for(var e in t)if(Ft.call(t,e))return!1;return!0},Me.isEqual=function(t,n){return Tr(t,n)},Me.isEqualWith=function(t,n,e){var r=(e=\"function\"==typeof e?e:i)?e(t,n):i;return r===i?Tr(t,n,i,e):!!r},Me.isError=Qu,Me.isFinite=function(t){return\"number\"==typeof t&&bn(t)},Me.isFunction=Ju,Me.isInteger=Xu,Me.isLength=ta,Me.isMap=ra,Me.isMatch=function(t,n){return t===n||Cr(t,n,so(n))},Me.isMatchWith=function(t,n,e){return e=\"function\"==typeof e?e:i,Cr(t,n,so(n),e)},Me.isNaN=function(t){return ia(t)&&t!=+t},Me.isNative=function(t){if(Eo(t))throw new Et(\"Unsupported core-js use. Try https://npms.io/search?q=ponyfill.\");return zr(t)},Me.isNil=function(t){return null==t},Me.isNull=function(t){return null===t},Me.isNumber=ia,Me.isObject=na,Me.isObjectLike=ea,Me.isPlainObject=oa,Me.isRegExp=ua,Me.isSafeInteger=function(t){return Xu(t)&&t>=-9007199254740991&&t<=v},Me.isSet=aa,Me.isString=ca,Me.isSymbol=fa,Me.isTypedArray=la,Me.isUndefined=function(t){return t===i},Me.isWeakMap=function(t){return ea(t)&&go(t)==T},Me.isWeakSet=function(t){return ea(t)&&\"[object WeakSet]\"==jr(t)},Me.join=function(t,n){return null==t?\"\":Mn.call(t,n)},Me.kebabCase=Ha,Me.last=Qo,Me.lastIndexOf=function(t,n,e){var r=null==t?0:t.length;if(!r)return-1;var o=r;return e!==i&&(o=(o=da(e))<0?me(r+o,0):we(o,r-1)),n==n?function(t,n,e){for(var r=e+1;r--;)if(t[r]===n)return r;return r}(t,n,o):Nn(t,Vn,o,!0)},Me.lowerCase=Va,Me.lowerFirst=Za,Me.lt=sa,Me.lte=ha,Me.max=function(t){return t&&t.length?gr(t,ic,kr):i},Me.maxBy=function(t,n){return t&&t.length?gr(t,fo(n,2),kr):i},Me.mean=function(t){return Zn(t,ic)},Me.meanBy=function(t,n){return Zn(t,fo(n,2))},Me.min=function(t){return t&&t.length?gr(t,ic,Pr):i},Me.minBy=function(t,n){return t&&t.length?gr(t,fo(n,2),Pr):i},Me.stubArray=gc,Me.stubFalse=_c,Me.stubObject=function(){return{}},Me.stubString=function(){return\"\"},Me.stubTrue=function(){return!0},Me.multiply=Ac,Me.nth=function(t,n){return t&&t.length?qr(t,da(n)):i},Me.noConflict=function(){return gn._===this&&(gn._=Mt),this},Me.noop=fc,Me.now=ku,Me.pad=function(t,n,e){t=ma(t);var r=(n=da(n))?ve(t):0;if(!n||r>=n)return t;var i=(n-r)/2;return Hi(_n(i),e)+t+Hi(dn(i),e)},Me.padEnd=function(t,n,e){t=ma(t);var r=(n=da(n))?ve(t):0;return n&&r<n?t+Hi(n-r,e):t},Me.padStart=function(t,n,e){t=ma(t);var r=(n=da(n))?ve(t):0;return n&&r<n?Hi(n-r,e)+t:t},Me.parseInt=function(t,n,e){return e||null==n?n=0:n&&(n=+n),xe(ma(t).replace(ut,\"\"),n||0)},Me.random=function(t,n,e){if(e&&\"boolean\"!=typeof e&&bo(t,n,e)&&(n=e=i),e===i&&(\"boolean\"==typeof n?(e=n,n=i):\"boolean\"==typeof t&&(e=t,t=i)),t===i&&n===i?(t=0,n=1):(t=va(t),n===i?(n=t,t=0):n=va(n)),t>n){var r=t;t=n,n=r}if(e||t%1||n%1){var o=Ae();return we(t+o*(n-t+hn(\"1e-\"+((o+\"\").length-1))),n)}return Kr(t,n)},Me.reduce=function(t,n,e){var r=Hu(t)?Wn:Yn,i=arguments.length<3;return r(t,fo(n,4),e,i,pr)},Me.reduceRight=function(t,n,e){var r=Hu(t)?Pn:Yn,i=arguments.length<3;return r(t,fo(n,4),e,i,vr)},Me.repeat=function(t,n,e){return n=(e?bo(t,n,e):n===i)?1:da(n),Yr(ma(t),n)},Me.replace=function(){var t=arguments,n=ma(t[0]);return t.length<3?n:n.replace(t[1],t[2])},Me.result=function(t,n,e){var r=-1,o=(n=wi(n,t)).length;for(o||(o=1,t=i);++r<o;){var u=null==t?i:t[Wo(n[r])];u===i&&(r=o,u=e),t=Ju(u)?u.call(t):u}return t},Me.round=Ec,Me.runInContext=t,Me.sample=function(t){return(Hu(t)?Je:Jr)(t)},Me.size=function(t){if(null==t)return 0;if(Zu(t))return ca(t)?ve(t):t.length;var n=go(t);return n==R||n==S?t.size:Dr(t).length},Me.snakeCase=Ga,Me.some=function(t,n,e){var r=Hu(t)?$n:oi;return e&&bo(t,n,e)&&(n=i),r(t,fo(n,3))},Me.sortedIndex=function(t,n){return ui(t,n)},Me.sortedIndexBy=function(t,n,e){return ai(t,n,fo(e,2))},Me.sortedIndexOf=function(t,n){var e=null==t?0:t.length;if(e){var r=ui(t,n);if(r<e&&Mu(t[r],n))return r}return-1},Me.sortedLastIndex=function(t,n){return ui(t,n,!0)},Me.sortedLastIndexBy=function(t,n,e){return ai(t,n,fo(e,2),!0)},Me.sortedLastIndexOf=function(t,n){if(null==t?0:t.length){var e=ui(t,n,!0)-1;if(Mu(t[e],n))return e}return-1},Me.startCase=Ka,Me.startsWith=function(t,n,e){return t=ma(t),e=null==e?0:cr(da(e),0,t.length),n=li(n),t.slice(e,e+n.length)==n},Me.subtract=Rc,Me.sum=function(t){return t&&t.length?Qn(t,ic):0},Me.sumBy=function(t,n){return t&&t.length?Qn(t,fo(n,2)):0},Me.template=function(t,n,e){var r=Me.templateSettings;e&&bo(t,n,e)&&(n=i),t=ma(t),n=xa({},n,r,Xi);var o,u,a=xa({},n.imports,r.imports,Xi),c=Ba(a),f=ne(a,c),l=0,s=n.interpolate||xt,h=\"__p += '\",p=It((n.escape||xt).source+\"|\"+s.source+\"|\"+(s===tt?vt:xt).source+\"|\"+(n.evaluate||xt).source+\"|$\",\"g\"),v=\"//# sourceURL=\"+(Ft.call(n,\"sourceURL\")?(n.sourceURL+\"\").replace(/\\s/g,\" \"):\"lodash.templateSources[\"+ ++cn+\"]\")+\"\\n\";t.replace(p,function(n,e,r,i,a,c){return r||(r=i),h+=t.slice(l,c).replace(At,ae),e&&(o=!0,h+=\"' +\\n__e(\"+e+\") +\\n'\"),a&&(u=!0,h+=\"';\\n\"+a+\";\\n__p += '\"),r&&(h+=\"' +\\n((__t = (\"+r+\")) == null ? '' : __t) +\\n'\"),l=c+n.length,n}),h+=\"';\\n\";var d=Ft.call(n,\"variable\")&&n.variable;if(d){if(ht.test(d))throw new Et(\"Invalid `variable` option passed into `_.template`\")}else h=\"with (obj) {\\n\"+h+\"\\n}\\n\";h=(u?h.replace(H,\"\"):h).replace(V,\"$1\").replace(Z,\"$1;\"),h=\"function(\"+(d||\"obj\")+\") {\\n\"+(d?\"\":\"obj || (obj = {});\\n\")+\"var __t, __p = ''\"+(o?\", __e = _.escape\":\"\")+(u?\", __j = Array.prototype.join;\\nfunction print() { __p += __j.call(arguments, '') }\\n\":\";\\n\")+h+\"return __p\\n}\";var g=Xa(function(){return Rt(c,v+\"return \"+h).apply(i,f)});if(g.source=h,Qu(g))throw g;return g},Me.times=function(t,n){if((t=da(t))<1||t>v)return[];var e=g,r=we(t,g);n=fo(n),t-=g;for(var i=Jn(r,n);++e<t;)n(e);return i},Me.toFinite=va,Me.toInteger=da,Me.toLength=ga,Me.toLower=function(t){return ma(t).toLowerCase()},Me.toNumber=_a,Me.toSafeInteger=function(t){return t?cr(da(t),-9007199254740991,v):0===t?t:0},Me.toString=ma,Me.toUpper=function(t){return ma(t).toUpperCase()},Me.trim=function(t,n,e){if((t=ma(t))&&(e||n===i))return Xn(t);if(!t||!(n=li(n)))return t;var r=de(t),o=de(n);return xi(r,re(r,o),ie(r,o)+1).join(\"\")},Me.trimEnd=function(t,n,e){if((t=ma(t))&&(e||n===i))return t.slice(0,ge(t)+1);if(!t||!(n=li(n)))return t;var r=de(t);return xi(r,0,ie(r,de(n))+1).join(\"\")},Me.trimStart=function(t,n,e){if((t=ma(t))&&(e||n===i))return t.replace(ut,\"\");if(!t||!(n=li(n)))return t;var r=de(t);return xi(r,re(r,de(n))).join(\"\")},Me.truncate=function(t,n){var e=30,r=\"...\";if(na(n)){var o=\"separator\"in n?n.separator:o;e=\"length\"in n?da(n.length):e,r=\"omission\"in n?li(n.omission):r}var u=(t=ma(t)).length;if(ce(t)){var a=de(t);u=a.length}if(e>=u)return t;var c=e-ve(r);if(c<1)return r;var f=a?xi(a,0,c).join(\"\"):t.slice(0,c);if(o===i)return f+r;if(a&&(c+=f.length-c),ua(o)){if(t.slice(c).search(o)){var l,s=f;for(o.global||(o=It(o.source,ma(dt.exec(o))+\"g\")),o.lastIndex=0;l=o.exec(s);)var h=l.index;f=f.slice(0,h===i?c:h)}}else if(t.indexOf(li(o),c)!=c){var p=f.lastIndexOf(o);p>-1&&(f=f.slice(0,p))}return f+r},Me.unescape=function(t){return(t=ma(t))&&Y.test(t)?t.replace(G,_e):t},Me.uniqueId=function(t){var n=++Dt;return ma(t)+n},Me.upperCase=Ya,Me.upperFirst=Qa,Me.each=mu,Me.eachRight=wu,Me.first=Zo,cc(Me,(xc={},br(Me,function(t,n){Ft.call(Me.prototype,n)||(xc[n]=t)}),xc),{chain:!1}),Me.VERSION=\"4.17.23\",Sn([\"bind\",\"bindKey\",\"curry\",\"curryRight\",\"partial\",\"partialRight\"],function(t){Me[t].placeholder=Me}),Sn([\"drop\",\"take\"],function(t,n){He.prototype[t]=function(e){e=e===i?1:me(da(e),0);var r=this.__filtered__&&!n?new He(this):this.clone();return r.__filtered__?r.__takeCount__=we(e,r.__takeCount__):r.__views__.push({size:we(e,g),type:t+(r.__dir__<0?\"Right\":\"\")}),r},He.prototype[t+\"Right\"]=function(n){return this.reverse()[t](n).reverse()}}),Sn([\"filter\",\"map\",\"takeWhile\"],function(t,n){var e=n+1,r=1==e||3==e;He.prototype[t]=function(t){var n=this.clone();return n.__iteratees__.push({iteratee:fo(t,3),type:e}),n.__filtered__=n.__filtered__||r,n}}),Sn([\"head\",\"last\"],function(t,n){var e=\"take\"+(n?\"Right\":\"\");He.prototype[t]=function(){return this[e](1).value()[0]}}),Sn([\"initial\",\"tail\"],function(t,n){var e=\"drop\"+(n?\"\":\"Right\");He.prototype[t]=function(){return this.__filtered__?new He(this):this[e](1)}}),He.prototype.compact=function(){return this.filter(ic)},He.prototype.find=function(t){return this.filter(t).head()},He.prototype.findLast=function(t){return this.reverse().find(t)},He.prototype.invokeMap=Qr(function(t,n){return\"function\"==typeof t?new He(this):this.map(function(e){return Lr(e,t,n)})}),He.prototype.reject=function(t){return this.filter(Fu(fo(t)))},He.prototype.slice=function(t,n){t=da(t);var e=this;return e.__filtered__&&(t>0||n<0)?new He(e):(t<0?e=e.takeRight(-t):t&&(e=e.drop(t)),n!==i&&(e=(n=da(n))<0?e.dropRight(-n):e.take(n-t)),e)},He.prototype.takeRightWhile=function(t){return this.reverse().takeWhile(t).reverse()},He.prototype.toArray=function(){return this.take(g)},br(He.prototype,function(t,n){var e=/^(?:filter|find|map|reject)|While$/.test(n),r=/^(?:head|last)$/.test(n),o=Me[r?\"take\"+(\"last\"==n?\"Right\":\"\"):n],u=r||/^find/.test(n);o&&(Me.prototype[n]=function(){var n=this.__wrapped__,a=r?[1]:arguments,c=n instanceof He,f=a[0],l=c||Hu(n),s=function(t){var n=o.apply(Me,Dn([t],a));return r&&h?n[0]:n};l&&e&&\"function\"==typeof f&&1!=f.length&&(c=l=!1);var h=this.__chain__,p=!!this.__actions__.length,v=u&&!h,d=c&&!p;if(!u&&l){n=d?n:new He(this);var g=t.apply(n,a);return g.__actions__.push({func:vu,args:[s],thisArg:i}),new qe(g,h)}return v&&d?t.apply(this,a):(g=this.thru(s),v?r?g.value()[0]:g.value():g)})}),Sn([\"pop\",\"push\",\"shift\",\"sort\",\"splice\",\"unshift\"],function(t){var n=Lt[t],e=/^(?:push|sort|unshift)$/.test(t)?\"tap\":\"thru\",r=/^(?:pop|shift)$/.test(t);Me.prototype[t]=function(){var t=arguments;if(r&&!this.__chain__){var i=this.value();return n.apply(Hu(i)?i:[],t)}return this[e](function(e){return n.apply(Hu(e)?e:[],t)})}}),br(He.prototype,function(t,n){var e=Me[n];if(e){var r=e.name+\"\";Ft.call(Be,r)||(Be[r]=[]),Be[r].push({name:n,func:e})}}),Be[Mi(i,2).name]=[{name:\"wrapper\",func:i}],He.prototype.clone=function(){var t=new He(this.__wrapped__);return t.__actions__=Si(this.__actions__),t.__dir__=this.__dir__,t.__filtered__=this.__filtered__,t.__iteratees__=Si(this.__iteratees__),t.__takeCount__=this.__takeCount__,t.__views__=Si(this.__views__),t},He.prototype.reverse=function(){if(this.__filtered__){var t=new He(this);t.__dir__=-1,t.__filtered__=!0}else(t=this.clone()).__dir__*=-1;return t},He.prototype.value=function(){var t=this.__wrapped__.value(),n=this.__dir__,e=Hu(t),r=n<0,i=e?t.length:0,o=function(t,n,e){var r=-1,i=e.length;for(;++r<i;){var o=e[r],u=o.size;switch(o.type){case\"drop\":t+=u;break;case\"dropRight\":n-=u;break;case\"take\":n=we(n,t+u);break;case\"takeRight\":t=me(t,n-u)}}return{start:t,end:n}}(0,i,this.__views__),u=o.start,a=o.end,c=a-u,f=r?a:u-1,l=this.__iteratees__,s=l.length,h=0,p=we(c,this.__takeCount__);if(!e||!r&&i==c&&p==c)return di(t,this.__actions__);var v=[];t:for(;c--&&h<p;){for(var d=-1,g=t[f+=n];++d<s;){var _=l[d],y=_.iteratee,m=_.type,w=y(g);if(2==m)g=w;else if(!w){if(1==m)continue t;break t}}v[h++]=g}return v},Me.prototype.at=du,Me.prototype.chain=function(){return pu(this)},Me.prototype.commit=function(){return new qe(this.value(),this.__chain__)},Me.prototype.next=function(){this.__values__===i&&(this.__values__=pa(this.value()));var t=this.__index__>=this.__values__.length;return{done:t,value:t?i:this.__values__[this.__index__++]}},Me.prototype.plant=function(t){for(var n,e=this;e instanceof Ne;){var r=$o(e);r.__index__=0,r.__values__=i,n?o.__wrapped__=r:n=r;var o=r;e=e.__wrapped__}return o.__wrapped__=t,n},Me.prototype.reverse=function(){var t=this.__wrapped__;if(t instanceof He){var n=t;return this.__actions__.length&&(n=new He(this)),(n=n.reverse()).__actions__.push({func:vu,args:[nu],thisArg:i}),new qe(n,this.__chain__)}return this.thru(nu)},Me.prototype.toJSON=Me.prototype.valueOf=Me.prototype.value=function(){return di(this.__wrapped__,this.__actions__)},Me.prototype.first=Me.prototype.head,Jt&&(Me.prototype[Jt]=function(){return this}),Me}();gn._=ye,(r=function(){return ye}.call(n,e,n,t))===i||(t.exports=r)}.call(this)},224(t,n,e){\"use strict\";e.d(n,{Hw:()=>p,Kc:()=>o,P2:()=>v,Qx:()=>l,bn:()=>a,iD:()=>u,kO:()=>h,ni:()=>f,qr:()=>c});var r=e(543),i=e.n(r);function o(t){const n=t.map(t=>new Date(t[0])),e=t.map(t=>t[1]),r=t.map(t=>t[2]),i=t.length>1?\"lines\":\"markers\";var o=[{x:n,y:e,mode:i,name:\"Resident size\"},{x:n,y:r,mode:i,name:\"Heap size\"}],a={responsive:!0,displayModeBar:!0,modeBarButtonsToAdd:[{name:\"downloadDataAsCsv\",title:\"Download data as CSV\",icon:Plotly.Icons.disk,click:function(t){var n=[];n.push(\"trace,timestamp,memory_size_bytes\"),t.data.forEach((t,e)=>{const r=t.x||[],i=t.y||[];for(var o=0;o<Math.min(r.length,i.length);o++){const u=t.name||\"trace\"+e,a=r[o].getTime();n.push(`${u},${a},${i[o]}`)}});const e=n.join(\"\\r\\n\"),r=new Blob([e],{type:\"text/csv\"}),i=URL.createObjectURL(r),o=document.createElement(\"a\");o.href=i,o.download=\"usage_over_time.csv\",document.body.appendChild(o),o.click(),document.body.removeChild(o),URL.revokeObjectURL(i)}}]};Plotly.newPlot(\"memoryGraph\",o,{xaxis:{title:{text:\"Time\"}},yaxis:{title:{text:\"Memory Size\"},tickformat:\".4~s\",exponentformat:\"B\",ticksuffix:\"B\"}},a),Plotly.newPlot(\"smallMemoryGraph\",o,{height:40,margin:{l:0,r:0,b:0,t:0,pad:4},plot_bgcolor:\"#343a40\",yaxis:{tickformat:\".4~s\",exponentformat:\"B\",ticksuffix:\"B\"},showlegend:!1},{responsive:!0,displayModeBar:!1}),document.getElementById(\"smallMemoryGraph\").onclick(()=>{u()})}function u(){setTimeout(()=>{Plotly.Plots.resize(\"memoryGraph\"),Plotly.Plots.resize(\"smallMemoryGraph\")},100)}function a(t,n=1){if(Math.abs(t)<1e3)return t+\" B\";const e=[\"kB\",\"MB\",\"GB\",\"TB\",\"PB\",\"EB\",\"ZB\",\"YB\"];let r=-1;const i=10**n;do{t/=1e3,++r}while(Math.round(Math.abs(t)*i)/i>=1e3&&r<e.length-1);return t.toFixed(n)+\" \"+e[r]}function c(t){var n;return function(){n&&window.cancelAnimationFrame(n);const e=this,r=arguments;n=window.requestAnimationFrame(function(){t.apply(e,r)})}}function f(t,n,e){let r=\"unknown location\";void 0!==t.location&&(r=`File ${t.location[1]}, line ${t.location[2]} in ${t.location[0]}`);const i=t.n_allocations>1?\"s\":\"\";let o=`${r}<br>${n} total<br>${`${t.n_allocations} allocation${i}`}`;return!1===e&&(o=o.concat(`<br>Thread ID: ${t.thread_id}`)),o}function l(t,n){return function(t,n){let e=i().cloneDeep(t.children);const r=i().filter(e,function t(e){return e.children&&e.children.length>0&&(e.children=i().filter(e.children,t)),n(e)});return i().defaults({children:r},t)}(t,t=>t.thread_id===n)}function s(t,n){function e(t){let r=[];if(n(t)){r=[];for(const n of t.children)r.push(...e(n));let n=i().clone(t);n.children=r,r=[n]}else for(const n of t.children)r.push(...e(n));return r}let r=[];for(let n of t.children)r.push(...e(n));return i().defaults({children:r},t)}function h(t){return s(t,t=>t.interesting)}function p(t){return s(t,t=>!t.import_system)}function v(t){return i().reduce(t,(t,n)=>(t.n_allocations+=n.n_allocations,t.value+=n.value,t),{n_allocations:0,value:0})}},279(t,n,e){\"use strict\";e.d(n,{$d:()=>Gt,QA:()=>Ct,kj:()=>Wt,zb:()=>Zt,Yu:()=>Ht,un:()=>Nt,bt:()=>qt,Ke:()=>Pt,mU:()=>$t,EV:()=>Ut});var r=e(224);const i=Math.min,o=Math.max,u=Math.round,a=Math.floor,c=t=>({x:t,y:t}),f={left:\"right\",right:\"left\",bottom:\"top\",top:\"bottom\"},l={start:\"end\",end:\"start\"};function s(t,n,e){return o(t,i(n,e))}function h(t,n){return\"function\"==typeof t?t(n):t}function p(t){return t.split(\"-\")[0]}function v(t){return t.split(\"-\")[1]}function d(t){return\"x\"===t?\"y\":\"x\"}function g(t){return\"y\"===t?\"height\":\"width\"}const y=new Set([\"top\",\"bottom\"]);function m(t){return y.has(p(t))?\"y\":\"x\"}function w(t){return d(m(t))}function b(t){return t.replace(/start|end/g,t=>l[t])}const x=[\"left\",\"right\"],A=[\"right\",\"left\"],E=[\"top\",\"bottom\"],R=[\"bottom\",\"top\"];function j(t,n,e,r){const i=v(t);let o=function(t,n,e){switch(t){case\"top\":case\"bottom\":return e?n?A:x:n?x:A;case\"left\":case\"right\":return n?E:R;default:return[]}}(p(t),\"start\"===e,r);return i&&(o=o.map(t=>t+\"-\"+i),n&&(o=o.concat(o.map(b)))),o}function k(t){return t.replace(/left|right|bottom|top/g,t=>f[t])}function I(t){const{x:n,y:e,width:r,height:i}=t;return{width:r,height:i,top:e,left:n,right:n+r,bottom:e+i,x:n,y:e}}function O(t,n,e){let{reference:r,floating:i}=t;const o=m(n),u=w(n),a=g(u),c=p(n),f=\"y\"===o,l=r.x+r.width/2-i.width/2,s=r.y+r.height/2-i.height/2,h=r[a]/2-i[a]/2;let d;switch(c){case\"top\":d={x:l,y:r.y-i.height};break;case\"bottom\":d={x:l,y:r.y+r.height};break;case\"right\":d={x:r.x+r.width,y:s};break;case\"left\":d={x:r.x-i.width,y:s};break;default:d={x:r.x,y:r.y}}switch(v(n)){case\"start\":d[u]-=h*(e&&f?-1:1);break;case\"end\":d[u]+=h*(e&&f?-1:1)}return d}async function S(t,n){var e;void 0===n&&(n={});const{x:r,y:i,platform:o,rects:u,elements:a,strategy:c}=t,{boundary:f=\"clippingAncestors\",rootBoundary:l=\"viewport\",elementContext:s=\"floating\",altBoundary:p=!1,padding:v=0}=h(n,t),d=function(t){return\"number\"!=typeof t?function(t){return{top:0,right:0,bottom:0,left:0,...t}}(t):{top:t,right:t,bottom:t,left:t}}(v),g=a[p?\"floating\"===s?\"reference\":\"floating\":s],_=I(await o.getClippingRect({element:null==(e=await(null==o.isElement?void 0:o.isElement(g)))||e?g:g.contextElement||await(null==o.getDocumentElement?void 0:o.getDocumentElement(a.floating)),boundary:f,rootBoundary:l,strategy:c})),y=\"floating\"===s?{x:r,y:i,width:u.floating.width,height:u.floating.height}:u.reference,m=await(null==o.getOffsetParent?void 0:o.getOffsetParent(a.floating)),w=await(null==o.isElement?void 0:o.isElement(m))&&await(null==o.getScale?void 0:o.getScale(m))||{x:1,y:1},b=I(o.convertOffsetParentRelativeRectToViewportRelativeRect?await o.convertOffsetParentRelativeRectToViewportRelativeRect({elements:a,rect:y,offsetParent:m,strategy:c}):y);return{top:(_.top-b.top+d.top)/w.y,bottom:(b.bottom-_.bottom+d.bottom)/w.y,left:(_.left-b.left+d.left)/w.x,right:(b.right-_.right+d.right)/w.x}}const L=new Set([\"left\",\"top\"]);function B(){return\"undefined\"!=typeof window}function T(t){return F(t)?(t.nodeName||\"\").toLowerCase():\"#document\"}function C(t){var n;return(null==t||null==(n=t.ownerDocument)?void 0:n.defaultView)||window}function z(t){var n;return null==(n=(F(t)?t.ownerDocument:t.document)||window.document)?void 0:n.documentElement}function F(t){return!!B()&&(t instanceof Node||t instanceof C(t).Node)}function D(t){return!!B()&&(t instanceof Element||t instanceof C(t).Element)}function W(t){return!!B()&&(t instanceof HTMLElement||t instanceof C(t).HTMLElement)}function P(t){return!(!B()||\"undefined\"==typeof ShadowRoot)&&(t instanceof ShadowRoot||t instanceof C(t).ShadowRoot)}const M=new Set([\"inline\",\"contents\"]);function U(t){const{overflow:n,overflowX:e,overflowY:r,display:i}=tt(t);return/auto|scroll|overlay|hidden|clip/.test(n+r+e)&&!M.has(i)}const N=new Set([\"table\",\"td\",\"th\"]);function q(t){return N.has(T(t))}const H=[\":popover-open\",\":modal\"];function V(t){return H.some(n=>{try{return t.matches(n)}catch(t){return!1}})}const Z=[\"transform\",\"translate\",\"scale\",\"rotate\",\"perspective\"],G=[\"transform\",\"translate\",\"scale\",\"rotate\",\"perspective\",\"filter\"],K=[\"paint\",\"layout\",\"strict\",\"content\"];function Y(t){const n=Q(),e=D(t)?tt(t):t;return Z.some(t=>!!e[t]&&\"none\"!==e[t])||!!e.containerType&&\"normal\"!==e.containerType||!n&&!!e.backdropFilter&&\"none\"!==e.backdropFilter||!n&&!!e.filter&&\"none\"!==e.filter||G.some(t=>(e.willChange||\"\").includes(t))||K.some(t=>(e.contain||\"\").includes(t))}function Q(){return!(\"undefined\"==typeof CSS||!CSS.supports)&&CSS.supports(\"-webkit-backdrop-filter\",\"none\")}const J=new Set([\"html\",\"body\",\"#document\"]);function X(t){return J.has(T(t))}function tt(t){return C(t).getComputedStyle(t)}function nt(t){return D(t)?{scrollLeft:t.scrollLeft,scrollTop:t.scrollTop}:{scrollLeft:t.scrollX,scrollTop:t.scrollY}}function et(t){if(\"html\"===T(t))return t;const n=t.assignedSlot||t.parentNode||P(t)&&t.host||z(t);return P(n)?n.host:n}function rt(t){const n=et(t);return X(n)?t.ownerDocument?t.ownerDocument.body:t.body:W(n)&&U(n)?n:rt(n)}function it(t,n,e){var r;void 0===n&&(n=[]),void 0===e&&(e=!0);const i=rt(t),o=i===(null==(r=t.ownerDocument)?void 0:r.body),u=C(i);if(o){const t=ot(u);return n.concat(u,u.visualViewport||[],U(i)?i:[],t&&e?it(t):[])}return n.concat(i,it(i,[],e))}function ot(t){return t.parent&&Object.getPrototypeOf(t.parent)?t.frameElement:null}function ut(t){const n=tt(t);let e=parseFloat(n.width)||0,r=parseFloat(n.height)||0;const i=W(t),o=i?t.offsetWidth:e,a=i?t.offsetHeight:r,c=u(e)!==o||u(r)!==a;return c&&(e=o,r=a),{width:e,height:r,$:c}}function at(t){return D(t)?t:t.contextElement}function ct(t){const n=at(t);if(!W(n))return c(1);const e=n.getBoundingClientRect(),{width:r,height:i,$:o}=ut(n);let a=(o?u(e.width):e.width)/r,f=(o?u(e.height):e.height)/i;return a&&Number.isFinite(a)||(a=1),f&&Number.isFinite(f)||(f=1),{x:a,y:f}}const ft=c(0);function lt(t){const n=C(t);return Q()&&n.visualViewport?{x:n.visualViewport.offsetLeft,y:n.visualViewport.offsetTop}:ft}function st(t,n,e,r){void 0===n&&(n=!1),void 0===e&&(e=!1);const i=t.getBoundingClientRect(),o=at(t);let u=c(1);n&&(r?D(r)&&(u=ct(r)):u=ct(t));const a=function(t,n,e){return void 0===n&&(n=!1),!(!e||n&&e!==C(t))&&n}(o,e,r)?lt(o):c(0);let f=(i.left+a.x)/u.x,l=(i.top+a.y)/u.y,s=i.width/u.x,h=i.height/u.y;if(o){const t=C(o),n=r&&D(r)?C(r):r;let e=t,i=ot(e);for(;i&&r&&n!==e;){const t=ct(i),n=i.getBoundingClientRect(),r=tt(i),o=n.left+(i.clientLeft+parseFloat(r.paddingLeft))*t.x,u=n.top+(i.clientTop+parseFloat(r.paddingTop))*t.y;f*=t.x,l*=t.y,s*=t.x,h*=t.y,f+=o,l+=u,e=C(i),i=ot(e)}}return I({width:s,height:h,x:f,y:l})}function ht(t,n){const e=nt(t).scrollLeft;return n?n.left+e:st(z(t)).left+e}function pt(t,n){const e=t.getBoundingClientRect();return{x:e.left+n.scrollLeft-ht(t,e),y:e.top+n.scrollTop}}const vt=new Set([\"absolute\",\"fixed\"]);function dt(t,n,e){let r;if(\"viewport\"===n)r=function(t,n){const e=C(t),r=z(t),i=e.visualViewport;let o=r.clientWidth,u=r.clientHeight,a=0,c=0;if(i){o=i.width,u=i.height;const t=Q();(!t||t&&\"fixed\"===n)&&(a=i.offsetLeft,c=i.offsetTop)}const f=ht(r);if(f<=0){const t=r.ownerDocument,n=t.body,e=getComputedStyle(n),i=\"CSS1Compat\"===t.compatMode&&parseFloat(e.marginLeft)+parseFloat(e.marginRight)||0,u=Math.abs(r.clientWidth-n.clientWidth-i);u<=25&&(o-=u)}else f<=25&&(o+=f);return{width:o,height:u,x:a,y:c}}(t,e);else if(\"document\"===n)r=function(t){const n=z(t),e=nt(t),r=t.ownerDocument.body,i=o(n.scrollWidth,n.clientWidth,r.scrollWidth,r.clientWidth),u=o(n.scrollHeight,n.clientHeight,r.scrollHeight,r.clientHeight);let a=-e.scrollLeft+ht(t);const c=-e.scrollTop;return\"rtl\"===tt(r).direction&&(a+=o(n.clientWidth,r.clientWidth)-i),{width:i,height:u,x:a,y:c}}(z(t));else if(D(n))r=function(t,n){const e=st(t,!0,\"fixed\"===n),r=e.top+t.clientTop,i=e.left+t.clientLeft,o=W(t)?ct(t):c(1);return{width:t.clientWidth*o.x,height:t.clientHeight*o.y,x:i*o.x,y:r*o.y}}(n,e);else{const e=lt(t);r={x:n.x-e.x,y:n.y-e.y,width:n.width,height:n.height}}return I(r)}function gt(t,n){const e=et(t);return!(e===n||!D(e)||X(e))&&(\"fixed\"===tt(e).position||gt(e,n))}function _t(t,n,e){const r=W(n),i=z(n),o=\"fixed\"===e,u=st(t,!0,o,n);let a={scrollLeft:0,scrollTop:0};const f=c(0);function l(){f.x=ht(i)}if(r||!r&&!o)if((\"body\"!==T(n)||U(i))&&(a=nt(n)),r){const t=st(n,!0,o,n);f.x=t.x+n.clientLeft,f.y=t.y+n.clientTop}else i&&l();o&&!r&&i&&l();const s=!i||r||o?c(0):pt(i,a);return{x:u.left+a.scrollLeft-f.x-s.x,y:u.top+a.scrollTop-f.y-s.y,width:u.width,height:u.height}}function yt(t){return\"static\"===tt(t).position}function mt(t,n){if(!W(t)||\"fixed\"===tt(t).position)return null;if(n)return n(t);let e=t.offsetParent;return z(t)===e&&(e=e.ownerDocument.body),e}function wt(t,n){const e=C(t);if(V(t))return e;if(!W(t)){let n=et(t);for(;n&&!X(n);){if(D(n)&&!yt(n))return n;n=et(n)}return e}let r=mt(t,n);for(;r&&q(r)&&yt(r);)r=mt(r,n);return r&&X(r)&&yt(r)&&!Y(r)?e:r||function(t){let n=et(t);for(;W(n)&&!X(n);){if(Y(n))return n;if(V(n))return null;n=et(n)}return null}(t)||e}const bt={convertOffsetParentRelativeRectToViewportRelativeRect:function(t){let{elements:n,rect:e,offsetParent:r,strategy:i}=t;const o=\"fixed\"===i,u=z(r),a=!!n&&V(n.floating);if(r===u||a&&o)return e;let f={scrollLeft:0,scrollTop:0},l=c(1);const s=c(0),h=W(r);if((h||!h&&!o)&&((\"body\"!==T(r)||U(u))&&(f=nt(r)),W(r))){const t=st(r);l=ct(r),s.x=t.x+r.clientLeft,s.y=t.y+r.clientTop}const p=!u||h||o?c(0):pt(u,f);return{width:e.width*l.x,height:e.height*l.y,x:e.x*l.x-f.scrollLeft*l.x+s.x+p.x,y:e.y*l.y-f.scrollTop*l.y+s.y+p.y}},getDocumentElement:z,getClippingRect:function(t){let{element:n,boundary:e,rootBoundary:r,strategy:u}=t;const a=[...\"clippingAncestors\"===e?V(n)?[]:function(t,n){const e=n.get(t);if(e)return e;let r=it(t,[],!1).filter(t=>D(t)&&\"body\"!==T(t)),i=null;const o=\"fixed\"===tt(t).position;let u=o?et(t):t;for(;D(u)&&!X(u);){const n=tt(u),e=Y(u);e||\"fixed\"!==n.position||(i=null),(o?!e&&!i:!e&&\"static\"===n.position&&i&&vt.has(i.position)||U(u)&&!e&&gt(t,u))?r=r.filter(t=>t!==u):i=n,u=et(u)}return n.set(t,r),r}(n,this._c):[].concat(e),r],c=a[0],f=a.reduce((t,e)=>{const r=dt(n,e,u);return t.top=o(r.top,t.top),t.right=i(r.right,t.right),t.bottom=i(r.bottom,t.bottom),t.left=o(r.left,t.left),t},dt(n,c,u));return{width:f.right-f.left,height:f.bottom-f.top,x:f.left,y:f.top}},getOffsetParent:wt,getElementRects:async function(t){const n=this.getOffsetParent||wt,e=this.getDimensions,r=await e(t.floating);return{reference:_t(t.reference,await n(t.floating),t.strategy),floating:{x:0,y:0,width:r.width,height:r.height}}},getClientRects:function(t){return Array.from(t.getClientRects())},getDimensions:function(t){const{width:n,height:e}=ut(t);return{width:n,height:e}},getScale:ct,isElement:D,isRTL:function(t){return\"rtl\"===tt(t).direction}};function xt(t,n){return t.x===n.x&&t.y===n.y&&t.width===n.width&&t.height===n.height}function At(t,n,e,r){void 0===r&&(r={});const{ancestorScroll:u=!0,ancestorResize:c=!0,elementResize:f=\"function\"==typeof ResizeObserver,layoutShift:l=\"function\"==typeof IntersectionObserver,animationFrame:s=!1}=r,h=at(t),p=u||c?[...h?it(h):[],...it(n)]:[];p.forEach(t=>{u&&t.addEventListener(\"scroll\",e,{passive:!0}),c&&t.addEventListener(\"resize\",e)});const v=h&&l?function(t,n){let e,r=null;const u=z(t);function c(){var t;clearTimeout(e),null==(t=r)||t.disconnect(),r=null}return function f(l,s){void 0===l&&(l=!1),void 0===s&&(s=1),c();const h=t.getBoundingClientRect(),{left:p,top:v,width:d,height:g}=h;if(l||n(),!d||!g)return;const _={rootMargin:-a(v)+\"px \"+-a(u.clientWidth-(p+d))+\"px \"+-a(u.clientHeight-(v+g))+\"px \"+-a(p)+\"px\",threshold:o(0,i(1,s))||1};let y=!0;function m(n){const r=n[0].intersectionRatio;if(r!==s){if(!y)return f();r?f(!1,r):e=setTimeout(()=>{f(!1,1e-7)},1e3)}1!==r||xt(h,t.getBoundingClientRect())||f(),y=!1}try{r=new IntersectionObserver(m,{..._,root:u.ownerDocument})}catch(t){r=new IntersectionObserver(m,_)}r.observe(t)}(!0),c}(h,e):null;let d,g=-1,_=null;f&&(_=new ResizeObserver(t=>{let[r]=t;r&&r.target===h&&_&&(_.unobserve(n),cancelAnimationFrame(g),g=requestAnimationFrame(()=>{var t;null==(t=_)||t.observe(n)})),e()}),h&&!s&&_.observe(h),_.observe(n));let y=s?st(t):null;return s&&function n(){const r=st(t);y&&!xt(y,r)&&e();y=r,d=requestAnimationFrame(n)}(),e(),()=>{var t;p.forEach(t=>{u&&t.removeEventListener(\"scroll\",e),c&&t.removeEventListener(\"resize\",e)}),null==v||v(),null==(t=_)||t.disconnect(),_=null,s&&cancelAnimationFrame(d)}}const Et=function(t){return void 0===t&&(t=0),{name:\"offset\",options:t,async fn(n){var e,r;const{x:i,y:o,placement:u,middlewareData:a}=n,c=await async function(t,n){const{placement:e,platform:r,elements:i}=t,o=await(null==r.isRTL?void 0:r.isRTL(i.floating)),u=p(e),a=v(e),c=\"y\"===m(e),f=L.has(u)?-1:1,l=o&&c?-1:1,s=h(n,t);let{mainAxis:d,crossAxis:g,alignmentAxis:_}=\"number\"==typeof s?{mainAxis:s,crossAxis:0,alignmentAxis:null}:{mainAxis:s.mainAxis||0,crossAxis:s.crossAxis||0,alignmentAxis:s.alignmentAxis};return a&&\"number\"==typeof _&&(g=\"end\"===a?-1*_:_),c?{x:g*l,y:d*f}:{x:d*f,y:g*l}}(n,t);return u===(null==(e=a.offset)?void 0:e.placement)&&null!=(r=a.arrow)&&r.alignmentOffset?{}:{x:i+c.x,y:o+c.y,data:{...c,placement:u}}}}},Rt=function(t){return void 0===t&&(t={}),{name:\"shift\",options:t,async fn(n){const{x:e,y:r,placement:i,platform:o}=n,{mainAxis:u=!0,crossAxis:a=!1,limiter:c={fn:t=>{let{x:n,y:e}=t;return{x:n,y:e}}},...f}=h(t,n),l={x:e,y:r},v=await o.detectOverflow(n,f),g=m(p(i)),_=d(g);let y=l[_],w=l[g];if(u){const t=\"y\"===_?\"bottom\":\"right\";y=s(y+v[\"y\"===_?\"top\":\"left\"],y,y-v[t])}if(a){const t=\"y\"===g?\"bottom\":\"right\";w=s(w+v[\"y\"===g?\"top\":\"left\"],w,w-v[t])}const b=c.fn({...n,[_]:y,[g]:w});return{...b,data:{x:b.x-e,y:b.y-r,enabled:{[_]:u,[g]:a}}}}}},jt=function(t){return void 0===t&&(t={}),{name:\"flip\",options:t,async fn(n){var e,r;const{placement:i,middlewareData:o,rects:u,initialPlacement:a,platform:c,elements:f}=n,{mainAxis:l=!0,crossAxis:s=!0,fallbackPlacements:d,fallbackStrategy:_=\"bestFit\",fallbackAxisSideDirection:y=\"none\",flipAlignment:x=!0,...A}=h(t,n);if(null!=(e=o.arrow)&&e.alignmentOffset)return{};const E=p(i),R=m(a),I=p(a)===a,O=await(null==c.isRTL?void 0:c.isRTL(f.floating)),S=d||(I||!x?[k(a)]:function(t){const n=k(t);return[b(t),n,b(n)]}(a)),L=\"none\"!==y;!d&&L&&S.push(...j(a,x,y,O));const B=[a,...S],T=await c.detectOverflow(n,A),C=[];let z=(null==(r=o.flip)?void 0:r.overflows)||[];if(l&&C.push(T[E]),s){const t=function(t,n,e){void 0===e&&(e=!1);const r=v(t),i=w(t),o=g(i);let u=\"x\"===i?r===(e?\"end\":\"start\")?\"right\":\"left\":\"start\"===r?\"bottom\":\"top\";return n.reference[o]>n.floating[o]&&(u=k(u)),[u,k(u)]}(i,u,O);C.push(T[t[0]],T[t[1]])}if(z=[...z,{placement:i,overflows:C}],!C.every(t=>t<=0)){var F,D;const t=((null==(F=o.flip)?void 0:F.index)||0)+1,n=B[t];if(n){if(!(\"alignment\"===s&&R!==m(n))||z.every(t=>m(t.placement)!==R||t.overflows[0]>0))return{data:{index:t,overflows:z},reset:{placement:n}}}let e=null==(D=z.filter(t=>t.overflows[0]<=0).sort((t,n)=>t.overflows[1]-n.overflows[1])[0])?void 0:D.placement;if(!e)switch(_){case\"bestFit\":{var W;const t=null==(W=z.filter(t=>{if(L){const n=m(t.placement);return n===R||\"y\"===n}return!0}).map(t=>[t.placement,t.overflows.filter(t=>t>0).reduce((t,n)=>t+n,0)]).sort((t,n)=>t[1]-n[1])[0])?void 0:W[0];t&&(e=t);break}case\"initialPlacement\":e=a}if(i!==e)return{reset:{placement:e}}}return{}}}},kt=(t,n,e)=>{const r=new Map,i={platform:bt,...e},o={...i.platform,_c:r};return(async(t,n,e)=>{const{placement:r=\"bottom\",strategy:i=\"absolute\",middleware:o=[],platform:u}=e,a=o.filter(Boolean),c=await(null==u.isRTL?void 0:u.isRTL(n));let f=await u.getElementRects({reference:t,floating:n,strategy:i}),{x:l,y:s}=O(f,r,c),h=r,p={},v=0;for(let e=0;e<a.length;e++){var d;const{name:o,fn:g}=a[e],{x:_,y,data:m,reset:w}=await g({x:l,y:s,initialPlacement:r,placement:h,strategy:i,middlewareData:p,rects:f,platform:{...u,detectOverflow:null!=(d=u.detectOverflow)?d:S},elements:{reference:t,floating:n}});l=null!=_?_:l,s=null!=y?y:s,p={...p,[o]:{...p[o],...m}},w&&v<=50&&(v++,\"object\"==typeof w&&(w.placement&&(h=w.placement),w.rects&&(f=!0===w.rects?await u.getElementRects({reference:t,floating:n,strategy:i}):w.rects),({x:l,y:s}=O(f,h,c))),e=-1)}return{x:l,y:s,placement:h,strategy:i,middlewareData:p}})(t,n,{...i,platform:o})},It=\"filter_uninteresting\",Ot=\"filter_import_system\",St=\"filter_thread\";var Lt=null,Bt=null;let Tt=new class{constructor(){this.filters={}}registerFilter(t,n){this.filters[t]=n}unRegisterFilter(t){delete this.filters[t]}drawChart(t){let n=t;_.forOwn(this.filters,t=>{n=t(n)}),Gt(n),Lt.merge([])}};function Ct(){return Lt}function zt(){return location.hash?parseInt(location.hash.substring(1),10):0}function Ft(){document.getElementById(\"resetZoomButton\").disabled=0==zt()}function Dt(t){t.id!=zt()&&(history.pushState({id:t.id},t.data.name,`#${t.id}`),Ft())}function Wt(){const t=zt(),n=Lt.findById(t);n&&(Lt.zoomTo(n),Ft())}function Pt(){Lt.inverted(this===document.getElementById(\"icicles\")),Lt.resetZoom(),$('[data-toggle=\"tooltip\"]').tooltip(\"hide\")}function $t(){Lt.resetZoom()}function Mt(){return document.getElementById(\"chart\").clientWidth}function Ut(){Tt.drawChart(data),location.hash&&Wt()}function Nt(){const t=this.dataset.thread;\"-0x1\"===t?Tt.unRegisterFilter(St):Tt.registerFilter(St,n=>{let e=(0,r.Qx)(n,t);const i=(0,r.P2)(e.children);return _.defaults(i,e),e.n_allocations=i.n_allocations,e.value=i.value,e}),Tt.drawChart(data)}function qt(){void 0===this.hideUninterestingFrames&&(this.hideUninterestingFrames=!0),!0===this.hideUninterestingFrames?(this.hideUninterestingFrames=!0,Tt.registerFilter(It,t=>(0,r.kO)(t))):Tt.unRegisterFilter(It),this.hideUninterestingFrames=!this.hideUninterestingFrames,Tt.drawChart(data)}function Ht(){void 0===this.hideImportSystemFrames&&(this.hideImportSystemFrames=!0),!0===this.hideImportSystemFrames?(this.hideImportSystemFrames=!0,inverted?(data=invertedNoImportsData,temporal&&(hideImports=!0,intervals=invertedNoImportsIntervals)):Tt.registerFilter(Ot,t=>(0,r.Hw)(t))):(Tt.unRegisterFilter(Ot),data=flamegraphData,temporal&&(hideImports=!1,intervals=flamegraphIntervals)),this.hideImportSystemFrames=!this.hideImportSystemFrames,Tt.drawChart(data)}function Vt(t,n){return t.highlight?\"orange\":t.data.name&&t.data.location?(r=t.data.location[1],\"py\"==(e=void 0===r?r:r.substring(r.lastIndexOf(\".\")+1,r.length)||r)?d3.schemePastel1[2]:\"c\"==e||\"cpp\"==e||\"h\"==e?d3.schemePastel1[5]:d3.schemePastel1[8]):\"#EEE\";var e,r}function Zt(t,n){if(!0===n)return;const e=t.unique_threads;if(!e||e.length<=1)return;document.getElementById(\"threadsDropdown\").removeAttribute(\"hidden\");const r=document.getElementById(\"threadsDropdownList\");for(const t of e){let n=document.createElement(\"a\");n.className=\"dropdown-item\",n.dataset.thread=t,n.text=t,n.onclick=Nt,r.appendChild(n)}}function Gt(t){let n=!Lt||Lt.inverted();Lt&&(Lt.destroy(),Bt&&(Bt.destroy(),Bt=null),d3.selectAll(\".d3-flame-graph-tip\").remove()),Bt=function(){const t=document.createElement(\"div\");t.className=\"d3-flame-graph-tip\",t.style.position=\"fixed\",t.style.top=\"0\",t.style.left=\"0\",t.style.visibility=\"hidden\",t.style.pointerEvents=\"none\",document.body.appendChild(t);let n=null,e=null,i=\"top\";const o=()=>{e&&kt(e,t,{strategy:\"fixed\",placement:i,middleware:[Et(6),jt(),Rt({padding:8})]}).then(({x:n,y:e})=>{t.style.left=`${n}px`,t.style.top=`${e}px`})},u=function(){return u};return u.show=(u,a)=>{if(!u||!a)return;const c=(0,r.bn)(u.data.value);var f;t.innerHTML=(0,r.ni)(u.data,c,merge_threads),f=function(t){const n=(t.x1+t.x0)/2;return.25<n&&n<.75?\"s\":t.x1<.75?\"e\":t.x0>.25?\"w\":\"n\"}(u),i=\"s\"===f?\"bottom\":\"e\"===f?\"right\":\"w\"===f?\"left\":\"top\",e=a,t.style.visibility=\"visible\",n&&n(),n=At(e,t,o),o()},u.hide=()=>{e=null,t.style.visibility=\"hidden\",n&&(n(),n=null)},u.destroy=()=>{u.hide(),t.remove()},u}(),Lt=flamegraph().width(Mt()).transitionDuration(250).transitionEase(d3.easeCubic).inverted(n).cellHeight(20).minFrameSize(2).setColorMapper(Vt).onClick(Dt).tooltip(Bt),d3.select(\"#chart\").datum(t).call(Lt),Lt.width(Mt())}}},n={};function e(r){var i=n[r];if(void 0!==i)return i.exports;var o=n[r]={id:r,loaded:!1,exports:{}};return t[r].call(o.exports,o,o.exports,e),o.loaded=!0,o.exports}e.n=t=>{var n=t&&t.__esModule?()=>t.default:()=>t;return e.d(n,{a:n}),n},e.d=(t,n)=>{for(var r in n)e.o(n,r)&&!e.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:n[r]})},e.g=function(){if(\"object\"==typeof globalThis)return globalThis;try{return this||new Function(\"return this\")()}catch(t){if(\"object\"==typeof window)return window}}(),e.o=(t,n)=>Object.prototype.hasOwnProperty.call(t,n),e.nmd=t=>(t.paths=[],t.children||(t.children=[]),t),(()=>{\"use strict\";var t=e(224),n=e(279);function r(t){const{strings:n,nodes:e,unique_threads:r}=t,i=e.name.map((t,r)=>({name:n[e.name[r]],location:[n[e.function[r]],n[e.filename[r]],e.lineno[r]],value:e.value[r],children:e.children[r],n_allocations:e.n_allocations[r],thread_id:n[e.thread_id[r]],interesting:0!==e.interesting[r],import_system:0!==e.import_system[r]}));for(const t of i)t.children=t.children.map(t=>i[t]);const o=i[0];return o.unique_threads=r.map(t=>n[t]),o}window.resizeMemoryGraph=t.iD,document.addEventListener(\"DOMContentLoaded\",function(){!function(t){const{strings:n,nodes:e,inverted_no_imports_nodes:i,unique_threads:o}=t;flamegraphData=r({strings:n,nodes:e,unique_threads:o}),invertedNoImportsData=inverted?r({strings:n,nodes:i,unique_threads:o}):null,data=flamegraphData}(packed_data),(0,t.Kc)(memory_records),(0,n.zb)(data,merge_threads),(0,n.$d)(data),location.hash&&(0,n.kj)(),document.getElementById(\"icicles\").onchange=n.Ke,document.getElementById(\"flames\").onchange=n.Ke,document.getElementById(\"resetZoomButton\").onclick=n.mU,document.getElementById(\"resetThreadFilterItem\").onclick=n.un,document.getElementById(\"hideUninteresting\").onclick=n.bt.bind(this),document.getElementById(\"hideImportSystem\").onclick=n.Yu.bind(this),n.bt.bind(this)(),document.onkeyup=t=>{\"Escape\"==t.code&&(0,n.mU)()},document.getElementById(\"searchTerm\").addEventListener(\"input\",()=>{const t=document.getElementById(\"searchTerm\");(0,n.QA)().search(t.value)}),window.addEventListener(\"popstate\",n.kj),window.addEventListener(\"resize\",(0,t.qr)(n.EV));let e=document.getElementById(\"stats-start-time\"),i=document.getElementById(\"stats-end-time\");e.textContent=new Date(e.innerText),i.textContent=new Date(i.innerText),$('[data-toggle-second=\"tooltip\"]').tooltip(),$('[data-toggle=\"tooltip\"]').tooltip()})})()})();"
  },
  {
    "path": "src/memray/reporters/templates/assets/flamegraph_common.js",
    "content": "(()=>{var t={543(t,n,r){var e;\n/**\n * @license\n * Lodash <https://lodash.com/>\n * Copyright OpenJS Foundation and other contributors <https://openjsf.org/>\n * Released under MIT license <https://lodash.com/license>\n * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>\n * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n */t=r.nmd(t),function(){var i,u=\"Expected a function\",o=\"__lodash_hash_undefined__\",a=\"__lodash_placeholder__\",f=16,c=32,l=64,s=128,h=256,p=1/0,v=9007199254740991,g=NaN,d=4294967295,_=[[\"ary\",s],[\"bind\",1],[\"bindKey\",2],[\"curry\",8],[\"curryRight\",f],[\"flip\",512],[\"partial\",c],[\"partialRight\",l],[\"rearg\",h]],y=\"[object Arguments]\",m=\"[object Array]\",w=\"[object Boolean]\",b=\"[object Date]\",x=\"[object Error]\",A=\"[object Function]\",R=\"[object GeneratorFunction]\",j=\"[object Map]\",E=\"[object Number]\",O=\"[object Object]\",S=\"[object Promise]\",k=\"[object RegExp]\",L=\"[object Set]\",T=\"[object String]\",I=\"[object Symbol]\",C=\"[object WeakMap]\",z=\"[object ArrayBuffer]\",B=\"[object DataView]\",W=\"[object Float32Array]\",D=\"[object Float64Array]\",F=\"[object Int8Array]\",$=\"[object Int16Array]\",P=\"[object Int32Array]\",M=\"[object Uint8Array]\",U=\"[object Uint8ClampedArray]\",N=\"[object Uint16Array]\",q=\"[object Uint32Array]\",H=/\\b__p \\+= '';/g,V=/\\b(__p \\+=) '' \\+/g,Z=/(__e\\(.*?\\)|\\b__t\\)) \\+\\n'';/g,K=/&(?:amp|lt|gt|quot|#39);/g,G=/[&<>\"']/g,Y=RegExp(K.source),J=RegExp(G.source),X=/<%-([\\s\\S]+?)%>/g,Q=/<%([\\s\\S]+?)%>/g,tt=/<%=([\\s\\S]+?)%>/g,nt=/\\.|\\[(?:[^[\\]]*|([\"'])(?:(?!\\1)[^\\\\]|\\\\.)*?\\1)\\]/,rt=/^\\w*$/,et=/[^.[\\]]+|\\[(?:(-?\\d+(?:\\.\\d+)?)|([\"'])((?:(?!\\2)[^\\\\]|\\\\.)*?)\\2)\\]|(?=(?:\\.|\\[\\])(?:\\.|\\[\\]|$))/g,it=/[\\\\^$.*+?()[\\]{}|]/g,ut=RegExp(it.source),ot=/^\\s+/,at=/\\s/,ft=/\\{(?:\\n\\/\\* \\[wrapped with .+\\] \\*\\/)?\\n?/,ct=/\\{\\n\\/\\* \\[wrapped with (.+)\\] \\*/,lt=/,? & /,st=/[^\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\x7f]+/g,ht=/[()=,{}\\[\\]\\/\\s]/,pt=/\\\\(\\\\)?/g,vt=/\\$\\{([^\\\\}]*(?:\\\\.[^\\\\}]*)*)\\}/g,gt=/\\w*$/,dt=/^[-+]0x[0-9a-f]+$/i,_t=/^0b[01]+$/i,yt=/^\\[object .+?Constructor\\]$/,mt=/^0o[0-7]+$/i,wt=/^(?:0|[1-9]\\d*)$/,bt=/[\\xc0-\\xd6\\xd8-\\xf6\\xf8-\\xff\\u0100-\\u017f]/g,xt=/($^)/,At=/['\\n\\r\\u2028\\u2029\\\\]/g,Rt=\"\\\\ud800-\\\\udfff\",jt=\"\\\\u0300-\\\\u036f\\\\ufe20-\\\\ufe2f\\\\u20d0-\\\\u20ff\",Et=\"\\\\u2700-\\\\u27bf\",Ot=\"a-z\\\\xdf-\\\\xf6\\\\xf8-\\\\xff\",St=\"A-Z\\\\xc0-\\\\xd6\\\\xd8-\\\\xde\",kt=\"\\\\ufe0e\\\\ufe0f\",Lt=\"\\\\xac\\\\xb1\\\\xd7\\\\xf7\\\\x00-\\\\x2f\\\\x3a-\\\\x40\\\\x5b-\\\\x60\\\\x7b-\\\\xbf\\\\u2000-\\\\u206f \\\\t\\\\x0b\\\\f\\\\xa0\\\\ufeff\\\\n\\\\r\\\\u2028\\\\u2029\\\\u1680\\\\u180e\\\\u2000\\\\u2001\\\\u2002\\\\u2003\\\\u2004\\\\u2005\\\\u2006\\\\u2007\\\\u2008\\\\u2009\\\\u200a\\\\u202f\\\\u205f\\\\u3000\",Tt=\"['’]\",It=\"[\"+Rt+\"]\",Ct=\"[\"+Lt+\"]\",zt=\"[\"+jt+\"]\",Bt=\"\\\\d+\",Wt=\"[\"+Et+\"]\",Dt=\"[\"+Ot+\"]\",Ft=\"[^\"+Rt+Lt+Bt+Et+Ot+St+\"]\",$t=\"\\\\ud83c[\\\\udffb-\\\\udfff]\",Pt=\"[^\"+Rt+\"]\",Mt=\"(?:\\\\ud83c[\\\\udde6-\\\\uddff]){2}\",Ut=\"[\\\\ud800-\\\\udbff][\\\\udc00-\\\\udfff]\",Nt=\"[\"+St+\"]\",qt=\"\\\\u200d\",Ht=\"(?:\"+Dt+\"|\"+Ft+\")\",Vt=\"(?:\"+Nt+\"|\"+Ft+\")\",Zt=\"(?:['’](?:d|ll|m|re|s|t|ve))?\",Kt=\"(?:['’](?:D|LL|M|RE|S|T|VE))?\",Gt=\"(?:\"+zt+\"|\"+$t+\")\"+\"?\",Yt=\"[\"+kt+\"]?\",Jt=Yt+Gt+(\"(?:\"+qt+\"(?:\"+[Pt,Mt,Ut].join(\"|\")+\")\"+Yt+Gt+\")*\"),Xt=\"(?:\"+[Wt,Mt,Ut].join(\"|\")+\")\"+Jt,Qt=\"(?:\"+[Pt+zt+\"?\",zt,Mt,Ut,It].join(\"|\")+\")\",tn=RegExp(Tt,\"g\"),nn=RegExp(zt,\"g\"),rn=RegExp($t+\"(?=\"+$t+\")|\"+Qt+Jt,\"g\"),en=RegExp([Nt+\"?\"+Dt+\"+\"+Zt+\"(?=\"+[Ct,Nt,\"$\"].join(\"|\")+\")\",Vt+\"+\"+Kt+\"(?=\"+[Ct,Nt+Ht,\"$\"].join(\"|\")+\")\",Nt+\"?\"+Ht+\"+\"+Zt,Nt+\"+\"+Kt,\"\\\\d*(?:1ST|2ND|3RD|(?![123])\\\\dTH)(?=\\\\b|[a-z_])\",\"\\\\d*(?:1st|2nd|3rd|(?![123])\\\\dth)(?=\\\\b|[A-Z_])\",Bt,Xt].join(\"|\"),\"g\"),un=RegExp(\"[\"+qt+Rt+jt+kt+\"]\"),on=/[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/,an=[\"Array\",\"Buffer\",\"DataView\",\"Date\",\"Error\",\"Float32Array\",\"Float64Array\",\"Function\",\"Int8Array\",\"Int16Array\",\"Int32Array\",\"Map\",\"Math\",\"Object\",\"Promise\",\"RegExp\",\"Set\",\"String\",\"Symbol\",\"TypeError\",\"Uint8Array\",\"Uint8ClampedArray\",\"Uint16Array\",\"Uint32Array\",\"WeakMap\",\"_\",\"clearTimeout\",\"isFinite\",\"parseInt\",\"setTimeout\"],fn=-1,cn={};cn[W]=cn[D]=cn[F]=cn[$]=cn[P]=cn[M]=cn[U]=cn[N]=cn[q]=!0,cn[y]=cn[m]=cn[z]=cn[w]=cn[B]=cn[b]=cn[x]=cn[A]=cn[j]=cn[E]=cn[O]=cn[k]=cn[L]=cn[T]=cn[C]=!1;var ln={};ln[y]=ln[m]=ln[z]=ln[B]=ln[w]=ln[b]=ln[W]=ln[D]=ln[F]=ln[$]=ln[P]=ln[j]=ln[E]=ln[O]=ln[k]=ln[L]=ln[T]=ln[I]=ln[M]=ln[U]=ln[N]=ln[q]=!0,ln[x]=ln[A]=ln[C]=!1;var sn={\"\\\\\":\"\\\\\",\"'\":\"'\",\"\\n\":\"n\",\"\\r\":\"r\",\"\\u2028\":\"u2028\",\"\\u2029\":\"u2029\"},hn=parseFloat,pn=parseInt,vn=\"object\"==typeof r.g&&r.g&&r.g.Object===Object&&r.g,gn=\"object\"==typeof self&&self&&self.Object===Object&&self,dn=vn||gn||Function(\"return this\")(),_n=n&&!n.nodeType&&n,yn=_n&&t&&!t.nodeType&&t,mn=yn&&yn.exports===_n,wn=mn&&vn.process,bn=function(){try{var t=yn&&yn.require&&yn.require(\"util\").types;return t||wn&&wn.binding&&wn.binding(\"util\")}catch(t){}}(),xn=bn&&bn.isArrayBuffer,An=bn&&bn.isDate,Rn=bn&&bn.isMap,jn=bn&&bn.isRegExp,En=bn&&bn.isSet,On=bn&&bn.isTypedArray;function Sn(t,n,r){switch(r.length){case 0:return t.call(n);case 1:return t.call(n,r[0]);case 2:return t.call(n,r[0],r[1]);case 3:return t.call(n,r[0],r[1],r[2])}return t.apply(n,r)}function kn(t,n,r,e){for(var i=-1,u=null==t?0:t.length;++i<u;){var o=t[i];n(e,o,r(o),t)}return e}function Ln(t,n){for(var r=-1,e=null==t?0:t.length;++r<e&&!1!==n(t[r],r,t););return t}function Tn(t,n){for(var r=null==t?0:t.length;r--&&!1!==n(t[r],r,t););return t}function In(t,n){for(var r=-1,e=null==t?0:t.length;++r<e;)if(!n(t[r],r,t))return!1;return!0}function Cn(t,n){for(var r=-1,e=null==t?0:t.length,i=0,u=[];++r<e;){var o=t[r];n(o,r,t)&&(u[i++]=o)}return u}function zn(t,n){return!!(null==t?0:t.length)&&qn(t,n,0)>-1}function Bn(t,n,r){for(var e=-1,i=null==t?0:t.length;++e<i;)if(r(n,t[e]))return!0;return!1}function Wn(t,n){for(var r=-1,e=null==t?0:t.length,i=Array(e);++r<e;)i[r]=n(t[r],r,t);return i}function Dn(t,n){for(var r=-1,e=n.length,i=t.length;++r<e;)t[i+r]=n[r];return t}function Fn(t,n,r,e){var i=-1,u=null==t?0:t.length;for(e&&u&&(r=t[++i]);++i<u;)r=n(r,t[i],i,t);return r}function $n(t,n,r,e){var i=null==t?0:t.length;for(e&&i&&(r=t[--i]);i--;)r=n(r,t[i],i,t);return r}function Pn(t,n){for(var r=-1,e=null==t?0:t.length;++r<e;)if(n(t[r],r,t))return!0;return!1}var Mn=Kn(\"length\");function Un(t,n,r){var e;return r(t,function(t,r,i){if(n(t,r,i))return e=r,!1}),e}function Nn(t,n,r,e){for(var i=t.length,u=r+(e?1:-1);e?u--:++u<i;)if(n(t[u],u,t))return u;return-1}function qn(t,n,r){return n==n?function(t,n,r){var e=r-1,i=t.length;for(;++e<i;)if(t[e]===n)return e;return-1}(t,n,r):Nn(t,Vn,r)}function Hn(t,n,r,e){for(var i=r-1,u=t.length;++i<u;)if(e(t[i],n))return i;return-1}function Vn(t){return t!=t}function Zn(t,n){var r=null==t?0:t.length;return r?Jn(t,n)/r:g}function Kn(t){return function(n){return null==n?i:n[t]}}function Gn(t){return function(n){return null==t?i:t[n]}}function Yn(t,n,r,e,i){return i(t,function(t,i,u){r=e?(e=!1,t):n(r,t,i,u)}),r}function Jn(t,n){for(var r,e=-1,u=t.length;++e<u;){var o=n(t[e]);o!==i&&(r=r===i?o:r+o)}return r}function Xn(t,n){for(var r=-1,e=Array(t);++r<t;)e[r]=n(r);return e}function Qn(t){return t?t.slice(0,dr(t)+1).replace(ot,\"\"):t}function tr(t){return function(n){return t(n)}}function nr(t,n){return Wn(n,function(n){return t[n]})}function rr(t,n){return t.has(n)}function er(t,n){for(var r=-1,e=t.length;++r<e&&qn(n,t[r],0)>-1;);return r}function ir(t,n){for(var r=t.length;r--&&qn(n,t[r],0)>-1;);return r}var ur=Gn({À:\"A\",Á:\"A\",Â:\"A\",Ã:\"A\",Ä:\"A\",Å:\"A\",à:\"a\",á:\"a\",â:\"a\",ã:\"a\",ä:\"a\",å:\"a\",Ç:\"C\",ç:\"c\",Ð:\"D\",ð:\"d\",È:\"E\",É:\"E\",Ê:\"E\",Ë:\"E\",è:\"e\",é:\"e\",ê:\"e\",ë:\"e\",Ì:\"I\",Í:\"I\",Î:\"I\",Ï:\"I\",ì:\"i\",í:\"i\",î:\"i\",ï:\"i\",Ñ:\"N\",ñ:\"n\",Ò:\"O\",Ó:\"O\",Ô:\"O\",Õ:\"O\",Ö:\"O\",Ø:\"O\",ò:\"o\",ó:\"o\",ô:\"o\",õ:\"o\",ö:\"o\",ø:\"o\",Ù:\"U\",Ú:\"U\",Û:\"U\",Ü:\"U\",ù:\"u\",ú:\"u\",û:\"u\",ü:\"u\",Ý:\"Y\",ý:\"y\",ÿ:\"y\",Æ:\"Ae\",æ:\"ae\",Þ:\"Th\",þ:\"th\",ß:\"ss\",Ā:\"A\",Ă:\"A\",Ą:\"A\",ā:\"a\",ă:\"a\",ą:\"a\",Ć:\"C\",Ĉ:\"C\",Ċ:\"C\",Č:\"C\",ć:\"c\",ĉ:\"c\",ċ:\"c\",č:\"c\",Ď:\"D\",Đ:\"D\",ď:\"d\",đ:\"d\",Ē:\"E\",Ĕ:\"E\",Ė:\"E\",Ę:\"E\",Ě:\"E\",ē:\"e\",ĕ:\"e\",ė:\"e\",ę:\"e\",ě:\"e\",Ĝ:\"G\",Ğ:\"G\",Ġ:\"G\",Ģ:\"G\",ĝ:\"g\",ğ:\"g\",ġ:\"g\",ģ:\"g\",Ĥ:\"H\",Ħ:\"H\",ĥ:\"h\",ħ:\"h\",Ĩ:\"I\",Ī:\"I\",Ĭ:\"I\",Į:\"I\",İ:\"I\",ĩ:\"i\",ī:\"i\",ĭ:\"i\",į:\"i\",ı:\"i\",Ĵ:\"J\",ĵ:\"j\",Ķ:\"K\",ķ:\"k\",ĸ:\"k\",Ĺ:\"L\",Ļ:\"L\",Ľ:\"L\",Ŀ:\"L\",Ł:\"L\",ĺ:\"l\",ļ:\"l\",ľ:\"l\",ŀ:\"l\",ł:\"l\",Ń:\"N\",Ņ:\"N\",Ň:\"N\",Ŋ:\"N\",ń:\"n\",ņ:\"n\",ň:\"n\",ŋ:\"n\",Ō:\"O\",Ŏ:\"O\",Ő:\"O\",ō:\"o\",ŏ:\"o\",ő:\"o\",Ŕ:\"R\",Ŗ:\"R\",Ř:\"R\",ŕ:\"r\",ŗ:\"r\",ř:\"r\",Ś:\"S\",Ŝ:\"S\",Ş:\"S\",Š:\"S\",ś:\"s\",ŝ:\"s\",ş:\"s\",š:\"s\",Ţ:\"T\",Ť:\"T\",Ŧ:\"T\",ţ:\"t\",ť:\"t\",ŧ:\"t\",Ũ:\"U\",Ū:\"U\",Ŭ:\"U\",Ů:\"U\",Ű:\"U\",Ų:\"U\",ũ:\"u\",ū:\"u\",ŭ:\"u\",ů:\"u\",ű:\"u\",ų:\"u\",Ŵ:\"W\",ŵ:\"w\",Ŷ:\"Y\",ŷ:\"y\",Ÿ:\"Y\",Ź:\"Z\",Ż:\"Z\",Ž:\"Z\",ź:\"z\",ż:\"z\",ž:\"z\",Ĳ:\"IJ\",ĳ:\"ij\",Œ:\"Oe\",œ:\"oe\",ŉ:\"'n\",ſ:\"s\"}),or=Gn({\"&\":\"&amp;\",\"<\":\"&lt;\",\">\":\"&gt;\",'\"':\"&quot;\",\"'\":\"&#39;\"});function ar(t){return\"\\\\\"+sn[t]}function fr(t){return un.test(t)}function cr(t){var n=-1,r=Array(t.size);return t.forEach(function(t,e){r[++n]=[e,t]}),r}function lr(t,n){return function(r){return t(n(r))}}function sr(t,n){for(var r=-1,e=t.length,i=0,u=[];++r<e;){var o=t[r];o!==n&&o!==a||(t[r]=a,u[i++]=r)}return u}function hr(t){var n=-1,r=Array(t.size);return t.forEach(function(t){r[++n]=t}),r}function pr(t){var n=-1,r=Array(t.size);return t.forEach(function(t){r[++n]=[t,t]}),r}function vr(t){return fr(t)?function(t){var n=rn.lastIndex=0;for(;rn.test(t);)++n;return n}(t):Mn(t)}function gr(t){return fr(t)?function(t){return t.match(rn)||[]}(t):function(t){return t.split(\"\")}(t)}function dr(t){for(var n=t.length;n--&&at.test(t.charAt(n)););return n}var _r=Gn({\"&amp;\":\"&\",\"&lt;\":\"<\",\"&gt;\":\">\",\"&quot;\":'\"',\"&#39;\":\"'\"});var yr=function t(n){var r,e=(n=null==n?dn:yr.defaults(dn.Object(),n,yr.pick(dn,an))).Array,at=n.Date,Rt=n.Error,jt=n.Function,Et=n.Math,Ot=n.Object,St=n.RegExp,kt=n.String,Lt=n.TypeError,Tt=e.prototype,It=jt.prototype,Ct=Ot.prototype,zt=n[\"__core-js_shared__\"],Bt=It.toString,Wt=Ct.hasOwnProperty,Dt=0,Ft=(r=/[^.]+$/.exec(zt&&zt.keys&&zt.keys.IE_PROTO||\"\"))?\"Symbol(src)_1.\"+r:\"\",$t=Ct.toString,Pt=Bt.call(Ot),Mt=dn._,Ut=St(\"^\"+Bt.call(Wt).replace(it,\"\\\\$&\").replace(/hasOwnProperty|(function).*?(?=\\\\\\()| for .+?(?=\\\\\\])/g,\"$1.*?\")+\"$\"),Nt=mn?n.Buffer:i,qt=n.Symbol,Ht=n.Uint8Array,Vt=Nt?Nt.allocUnsafe:i,Zt=lr(Ot.getPrototypeOf,Ot),Kt=Ot.create,Gt=Ct.propertyIsEnumerable,Yt=Tt.splice,Jt=qt?qt.isConcatSpreadable:i,Xt=qt?qt.iterator:i,Qt=qt?qt.toStringTag:i,rn=function(){try{var t=hu(Ot,\"defineProperty\");return t({},\"\",{}),t}catch(t){}}(),un=n.clearTimeout!==dn.clearTimeout&&n.clearTimeout,sn=at&&at.now!==dn.Date.now&&at.now,vn=n.setTimeout!==dn.setTimeout&&n.setTimeout,gn=Et.ceil,_n=Et.floor,yn=Ot.getOwnPropertySymbols,wn=Nt?Nt.isBuffer:i,bn=n.isFinite,Mn=Tt.join,Gn=lr(Ot.keys,Ot),mr=Et.max,wr=Et.min,br=at.now,xr=n.parseInt,Ar=Et.random,Rr=Tt.reverse,jr=hu(n,\"DataView\"),Er=hu(n,\"Map\"),Or=hu(n,\"Promise\"),Sr=hu(n,\"Set\"),kr=hu(n,\"WeakMap\"),Lr=hu(Ot,\"create\"),Tr=kr&&new kr,Ir={},Cr=Fu(jr),zr=Fu(Er),Br=Fu(Or),Wr=Fu(Sr),Dr=Fu(kr),Fr=qt?qt.prototype:i,$r=Fr?Fr.valueOf:i,Pr=Fr?Fr.toString:i;function Mr(t){if(ra(t)&&!Ho(t)&&!(t instanceof Hr)){if(t instanceof qr)return t;if(Wt.call(t,\"__wrapped__\"))return $u(t)}return new qr(t)}var Ur=function(){function t(){}return function(n){if(!na(n))return{};if(Kt)return Kt(n);t.prototype=n;var r=new t;return t.prototype=i,r}}();function Nr(){}function qr(t,n){this.__wrapped__=t,this.__actions__=[],this.__chain__=!!n,this.__index__=0,this.__values__=i}function Hr(t){this.__wrapped__=t,this.__actions__=[],this.__dir__=1,this.__filtered__=!1,this.__iteratees__=[],this.__takeCount__=d,this.__views__=[]}function Vr(t){var n=-1,r=null==t?0:t.length;for(this.clear();++n<r;){var e=t[n];this.set(e[0],e[1])}}function Zr(t){var n=-1,r=null==t?0:t.length;for(this.clear();++n<r;){var e=t[n];this.set(e[0],e[1])}}function Kr(t){var n=-1,r=null==t?0:t.length;for(this.clear();++n<r;){var e=t[n];this.set(e[0],e[1])}}function Gr(t){var n=-1,r=null==t?0:t.length;for(this.__data__=new Kr;++n<r;)this.add(t[n])}function Yr(t){var n=this.__data__=new Zr(t);this.size=n.size}function Jr(t,n){var r=Ho(t),e=!r&&qo(t),i=!r&&!e&&Go(t),u=!r&&!e&&!i&&la(t),o=r||e||i||u,a=o?Xn(t.length,kt):[],f=a.length;for(var c in t)!n&&!Wt.call(t,c)||o&&(\"length\"==c||i&&(\"offset\"==c||\"parent\"==c)||u&&(\"buffer\"==c||\"byteLength\"==c||\"byteOffset\"==c)||mu(c,f))||a.push(c);return a}function Xr(t){var n=t.length;return n?t[Ge(0,n-1)]:i}function Qr(t,n){return Bu(Li(t),fe(n,0,t.length))}function te(t){return Bu(Li(t))}function ne(t,n,r){(r!==i&&!Mo(t[n],r)||r===i&&!(n in t))&&oe(t,n,r)}function re(t,n,r){var e=t[n];Wt.call(t,n)&&Mo(e,r)&&(r!==i||n in t)||oe(t,n,r)}function ee(t,n){for(var r=t.length;r--;)if(Mo(t[r][0],n))return r;return-1}function ie(t,n,r,e){return pe(t,function(t,i,u){n(e,t,r(t),u)}),e}function ue(t,n){return t&&Ti(n,Ia(n),t)}function oe(t,n,r){\"__proto__\"==n&&rn?rn(t,n,{configurable:!0,enumerable:!0,value:r,writable:!0}):t[n]=r}function ae(t,n){for(var r=-1,u=n.length,o=e(u),a=null==t;++r<u;)o[r]=a?i:Oa(t,n[r]);return o}function fe(t,n,r){return t==t&&(r!==i&&(t=t<=r?t:r),n!==i&&(t=t>=n?t:n)),t}function ce(t,n,r,e,u,o){var a,f=1&n,c=2&n,l=4&n;if(r&&(a=u?r(t,e,u,o):r(t)),a!==i)return a;if(!na(t))return t;var s=Ho(t);if(s){if(a=function(t){var n=t.length,r=new t.constructor(n);n&&\"string\"==typeof t[0]&&Wt.call(t,\"index\")&&(r.index=t.index,r.input=t.input);return r}(t),!f)return Li(t,a)}else{var h=gu(t),p=h==A||h==R;if(Go(t))return Ri(t,f);if(h==O||h==y||p&&!u){if(a=c||p?{}:_u(t),!f)return c?function(t,n){return Ti(t,vu(t),n)}(t,function(t,n){return t&&Ti(n,Ca(n),t)}(a,t)):function(t,n){return Ti(t,pu(t),n)}(t,ue(a,t))}else{if(!ln[h])return u?t:{};a=function(t,n,r){var e=t.constructor;switch(n){case z:return ji(t);case w:case b:return new e(+t);case B:return function(t,n){var r=n?ji(t.buffer):t.buffer;return new t.constructor(r,t.byteOffset,t.byteLength)}(t,r);case W:case D:case F:case $:case P:case M:case U:case N:case q:return Ei(t,r);case j:return new e;case E:case T:return new e(t);case k:return function(t){var n=new t.constructor(t.source,gt.exec(t));return n.lastIndex=t.lastIndex,n}(t);case L:return new e;case I:return i=t,$r?Ot($r.call(i)):{}}var i}(t,h,f)}}o||(o=new Yr);var v=o.get(t);if(v)return v;o.set(t,a),aa(t)?t.forEach(function(e){a.add(ce(e,n,r,e,t,o))}):ea(t)&&t.forEach(function(e,i){a.set(i,ce(e,n,r,i,t,o))});var g=s?i:(l?c?uu:iu:c?Ca:Ia)(t);return Ln(g||t,function(e,i){g&&(e=t[i=e]),re(a,i,ce(e,n,r,i,t,o))}),a}function le(t,n,r){var e=r.length;if(null==t)return!e;for(t=Ot(t);e--;){var u=r[e],o=n[u],a=t[u];if(a===i&&!(u in t)||!o(a))return!1}return!0}function se(t,n,r){if(\"function\"!=typeof t)throw new Lt(u);return Tu(function(){t.apply(i,r)},n)}function he(t,n,r,e){var i=-1,u=zn,o=!0,a=t.length,f=[],c=n.length;if(!a)return f;r&&(n=Wn(n,tr(r))),e?(u=Bn,o=!1):n.length>=200&&(u=rr,o=!1,n=new Gr(n));t:for(;++i<a;){var l=t[i],s=null==r?l:r(l);if(l=e||0!==l?l:0,o&&s==s){for(var h=c;h--;)if(n[h]===s)continue t;f.push(l)}else u(n,s,e)||f.push(l)}return f}Mr.templateSettings={escape:X,evaluate:Q,interpolate:tt,variable:\"\",imports:{_:Mr}},Mr.prototype=Nr.prototype,Mr.prototype.constructor=Mr,qr.prototype=Ur(Nr.prototype),qr.prototype.constructor=qr,Hr.prototype=Ur(Nr.prototype),Hr.prototype.constructor=Hr,Vr.prototype.clear=function(){this.__data__=Lr?Lr(null):{},this.size=0},Vr.prototype.delete=function(t){var n=this.has(t)&&delete this.__data__[t];return this.size-=n?1:0,n},Vr.prototype.get=function(t){var n=this.__data__;if(Lr){var r=n[t];return r===o?i:r}return Wt.call(n,t)?n[t]:i},Vr.prototype.has=function(t){var n=this.__data__;return Lr?n[t]!==i:Wt.call(n,t)},Vr.prototype.set=function(t,n){var r=this.__data__;return this.size+=this.has(t)?0:1,r[t]=Lr&&n===i?o:n,this},Zr.prototype.clear=function(){this.__data__=[],this.size=0},Zr.prototype.delete=function(t){var n=this.__data__,r=ee(n,t);return!(r<0)&&(r==n.length-1?n.pop():Yt.call(n,r,1),--this.size,!0)},Zr.prototype.get=function(t){var n=this.__data__,r=ee(n,t);return r<0?i:n[r][1]},Zr.prototype.has=function(t){return ee(this.__data__,t)>-1},Zr.prototype.set=function(t,n){var r=this.__data__,e=ee(r,t);return e<0?(++this.size,r.push([t,n])):r[e][1]=n,this},Kr.prototype.clear=function(){this.size=0,this.__data__={hash:new Vr,map:new(Er||Zr),string:new Vr}},Kr.prototype.delete=function(t){var n=lu(this,t).delete(t);return this.size-=n?1:0,n},Kr.prototype.get=function(t){return lu(this,t).get(t)},Kr.prototype.has=function(t){return lu(this,t).has(t)},Kr.prototype.set=function(t,n){var r=lu(this,t),e=r.size;return r.set(t,n),this.size+=r.size==e?0:1,this},Gr.prototype.add=Gr.prototype.push=function(t){return this.__data__.set(t,o),this},Gr.prototype.has=function(t){return this.__data__.has(t)},Yr.prototype.clear=function(){this.__data__=new Zr,this.size=0},Yr.prototype.delete=function(t){var n=this.__data__,r=n.delete(t);return this.size=n.size,r},Yr.prototype.get=function(t){return this.__data__.get(t)},Yr.prototype.has=function(t){return this.__data__.has(t)},Yr.prototype.set=function(t,n){var r=this.__data__;if(r instanceof Zr){var e=r.__data__;if(!Er||e.length<199)return e.push([t,n]),this.size=++r.size,this;r=this.__data__=new Kr(e)}return r.set(t,n),this.size=r.size,this};var pe=zi(be),ve=zi(xe,!0);function ge(t,n){var r=!0;return pe(t,function(t,e,i){return r=!!n(t,e,i)}),r}function de(t,n,r){for(var e=-1,u=t.length;++e<u;){var o=t[e],a=n(o);if(null!=a&&(f===i?a==a&&!ca(a):r(a,f)))var f=a,c=o}return c}function _e(t,n){var r=[];return pe(t,function(t,e,i){n(t,e,i)&&r.push(t)}),r}function ye(t,n,r,e,i){var u=-1,o=t.length;for(r||(r=yu),i||(i=[]);++u<o;){var a=t[u];n>0&&r(a)?n>1?ye(a,n-1,r,e,i):Dn(i,a):e||(i[i.length]=a)}return i}var me=Bi(),we=Bi(!0);function be(t,n){return t&&me(t,n,Ia)}function xe(t,n){return t&&we(t,n,Ia)}function Ae(t,n){return Cn(n,function(n){return Xo(t[n])})}function Re(t,n){for(var r=0,e=(n=wi(n,t)).length;null!=t&&r<e;)t=t[Du(n[r++])];return r&&r==e?t:i}function je(t,n,r){var e=n(t);return Ho(t)?e:Dn(e,r(t))}function Ee(t){return null==t?t===i?\"[object Undefined]\":\"[object Null]\":Qt&&Qt in Ot(t)?function(t){var n=Wt.call(t,Qt),r=t[Qt];try{t[Qt]=i;var e=!0}catch(t){}var u=$t.call(t);e&&(n?t[Qt]=r:delete t[Qt]);return u}(t):function(t){return $t.call(t)}(t)}function Oe(t,n){return t>n}function Se(t,n){return null!=t&&Wt.call(t,n)}function ke(t,n){return null!=t&&n in Ot(t)}function Le(t,n,r){for(var u=r?Bn:zn,o=t[0].length,a=t.length,f=a,c=e(a),l=1/0,s=[];f--;){var h=t[f];f&&n&&(h=Wn(h,tr(n))),l=wr(h.length,l),c[f]=!r&&(n||o>=120&&h.length>=120)?new Gr(f&&h):i}h=t[0];var p=-1,v=c[0];t:for(;++p<o&&s.length<l;){var g=h[p],d=n?n(g):g;if(g=r||0!==g?g:0,!(v?rr(v,d):u(s,d,r))){for(f=a;--f;){var _=c[f];if(!(_?rr(_,d):u(t[f],d,r)))continue t}v&&v.push(d),s.push(g)}}return s}function Te(t,n,r){var e=null==(t=Su(t,n=wi(n,t)))?t:t[Du(Yu(n))];return null==e?i:Sn(e,t,r)}function Ie(t){return ra(t)&&Ee(t)==y}function Ce(t,n,r,e,u){return t===n||(null==t||null==n||!ra(t)&&!ra(n)?t!=t&&n!=n:function(t,n,r,e,u,o){var a=Ho(t),f=Ho(n),c=a?m:gu(t),l=f?m:gu(n),s=(c=c==y?O:c)==O,h=(l=l==y?O:l)==O,p=c==l;if(p&&Go(t)){if(!Go(n))return!1;a=!0,s=!1}if(p&&!s)return o||(o=new Yr),a||la(t)?ru(t,n,r,e,u,o):function(t,n,r,e,i,u,o){switch(r){case B:if(t.byteLength!=n.byteLength||t.byteOffset!=n.byteOffset)return!1;t=t.buffer,n=n.buffer;case z:return!(t.byteLength!=n.byteLength||!u(new Ht(t),new Ht(n)));case w:case b:case E:return Mo(+t,+n);case x:return t.name==n.name&&t.message==n.message;case k:case T:return t==n+\"\";case j:var a=cr;case L:var f=1&e;if(a||(a=hr),t.size!=n.size&&!f)return!1;var c=o.get(t);if(c)return c==n;e|=2,o.set(t,n);var l=ru(a(t),a(n),e,i,u,o);return o.delete(t),l;case I:if($r)return $r.call(t)==$r.call(n)}return!1}(t,n,c,r,e,u,o);if(!(1&r)){var v=s&&Wt.call(t,\"__wrapped__\"),g=h&&Wt.call(n,\"__wrapped__\");if(v||g){var d=v?t.value():t,_=g?n.value():n;return o||(o=new Yr),u(d,_,r,e,o)}}if(!p)return!1;return o||(o=new Yr),function(t,n,r,e,u,o){var a=1&r,f=iu(t),c=f.length,l=iu(n),s=l.length;if(c!=s&&!a)return!1;var h=c;for(;h--;){var p=f[h];if(!(a?p in n:Wt.call(n,p)))return!1}var v=o.get(t),g=o.get(n);if(v&&g)return v==n&&g==t;var d=!0;o.set(t,n),o.set(n,t);var _=a;for(;++h<c;){var y=t[p=f[h]],m=n[p];if(e)var w=a?e(m,y,p,n,t,o):e(y,m,p,t,n,o);if(!(w===i?y===m||u(y,m,r,e,o):w)){d=!1;break}_||(_=\"constructor\"==p)}if(d&&!_){var b=t.constructor,x=n.constructor;b==x||!(\"constructor\"in t)||!(\"constructor\"in n)||\"function\"==typeof b&&b instanceof b&&\"function\"==typeof x&&x instanceof x||(d=!1)}return o.delete(t),o.delete(n),d}(t,n,r,e,u,o)}(t,n,r,e,Ce,u))}function ze(t,n,r,e){var u=r.length,o=u,a=!e;if(null==t)return!o;for(t=Ot(t);u--;){var f=r[u];if(a&&f[2]?f[1]!==t[f[0]]:!(f[0]in t))return!1}for(;++u<o;){var c=(f=r[u])[0],l=t[c],s=f[1];if(a&&f[2]){if(l===i&&!(c in t))return!1}else{var h=new Yr;if(e)var p=e(l,s,c,t,n,h);if(!(p===i?Ce(s,l,3,e,h):p))return!1}}return!0}function Be(t){return!(!na(t)||(n=t,Ft&&Ft in n))&&(Xo(t)?Ut:yt).test(Fu(t));var n}function We(t){return\"function\"==typeof t?t:null==t?uf:\"object\"==typeof t?Ho(t)?Ue(t[0],t[1]):Me(t):vf(t)}function De(t){if(!Ru(t))return Gn(t);var n=[];for(var r in Ot(t))Wt.call(t,r)&&\"constructor\"!=r&&n.push(r);return n}function Fe(t){if(!na(t))return function(t){var n=[];if(null!=t)for(var r in Ot(t))n.push(r);return n}(t);var n=Ru(t),r=[];for(var e in t)(\"constructor\"!=e||!n&&Wt.call(t,e))&&r.push(e);return r}function $e(t,n){return t<n}function Pe(t,n){var r=-1,i=Zo(t)?e(t.length):[];return pe(t,function(t,e,u){i[++r]=n(t,e,u)}),i}function Me(t){var n=su(t);return 1==n.length&&n[0][2]?Eu(n[0][0],n[0][1]):function(r){return r===t||ze(r,t,n)}}function Ue(t,n){return bu(t)&&ju(n)?Eu(Du(t),n):function(r){var e=Oa(r,t);return e===i&&e===n?Sa(r,t):Ce(n,e,3)}}function Ne(t,n,r,e,u){t!==n&&me(n,function(o,a){if(u||(u=new Yr),na(o))!function(t,n,r,e,u,o,a){var f=ku(t,r),c=ku(n,r),l=a.get(c);if(l)return void ne(t,r,l);var s=o?o(f,c,r+\"\",t,n,a):i,h=s===i;if(h){var p=Ho(c),v=!p&&Go(c),g=!p&&!v&&la(c);s=c,p||v||g?Ho(f)?s=f:Ko(f)?s=Li(f):v?(h=!1,s=Ri(c,!0)):g?(h=!1,s=Ei(c,!0)):s=[]:ua(c)||qo(c)?(s=f,qo(f)?s=ya(f):na(f)&&!Xo(f)||(s=_u(c))):h=!1}h&&(a.set(c,s),u(s,c,e,o,a),a.delete(c));ne(t,r,s)}(t,n,a,r,Ne,e,u);else{var f=e?e(ku(t,a),o,a+\"\",t,n,u):i;f===i&&(f=o),ne(t,a,f)}},Ca)}function qe(t,n){var r=t.length;if(r)return mu(n+=n<0?r:0,r)?t[n]:i}function He(t,n,r){n=n.length?Wn(n,function(t){return Ho(t)?function(n){return Re(n,1===t.length?t[0]:t)}:t}):[uf];var e=-1;n=Wn(n,tr(cu()));var i=Pe(t,function(t,r,i){var u=Wn(n,function(n){return n(t)});return{criteria:u,index:++e,value:t}});return function(t,n){var r=t.length;for(t.sort(n);r--;)t[r]=t[r].value;return t}(i,function(t,n){return function(t,n,r){var e=-1,i=t.criteria,u=n.criteria,o=i.length,a=r.length;for(;++e<o;){var f=Oi(i[e],u[e]);if(f)return e>=a?f:f*(\"desc\"==r[e]?-1:1)}return t.index-n.index}(t,n,r)})}function Ve(t,n,r){for(var e=-1,i=n.length,u={};++e<i;){var o=n[e],a=Re(t,o);r(a,o)&&ti(u,wi(o,t),a)}return u}function Ze(t,n,r,e){var i=e?Hn:qn,u=-1,o=n.length,a=t;for(t===n&&(n=Li(n)),r&&(a=Wn(t,tr(r)));++u<o;)for(var f=0,c=n[u],l=r?r(c):c;(f=i(a,l,f,e))>-1;)a!==t&&Yt.call(a,f,1),Yt.call(t,f,1);return t}function Ke(t,n){for(var r=t?n.length:0,e=r-1;r--;){var i=n[r];if(r==e||i!==u){var u=i;mu(i)?Yt.call(t,i,1):hi(t,i)}}return t}function Ge(t,n){return t+_n(Ar()*(n-t+1))}function Ye(t,n){var r=\"\";if(!t||n<1||n>v)return r;do{n%2&&(r+=t),(n=_n(n/2))&&(t+=t)}while(n);return r}function Je(t,n){return Iu(Ou(t,n,uf),t+\"\")}function Xe(t){return Xr(Ma(t))}function Qe(t,n){var r=Ma(t);return Bu(r,fe(n,0,r.length))}function ti(t,n,r,e){if(!na(t))return t;for(var u=-1,o=(n=wi(n,t)).length,a=o-1,f=t;null!=f&&++u<o;){var c=Du(n[u]),l=r;if(\"__proto__\"===c||\"constructor\"===c||\"prototype\"===c)return t;if(u!=a){var s=f[c];(l=e?e(s,c,f):i)===i&&(l=na(s)?s:mu(n[u+1])?[]:{})}re(f,c,l),f=f[c]}return t}var ni=Tr?function(t,n){return Tr.set(t,n),t}:uf,ri=rn?function(t,n){return rn(t,\"toString\",{configurable:!0,enumerable:!1,value:nf(n),writable:!0})}:uf;function ei(t){return Bu(Ma(t))}function ii(t,n,r){var i=-1,u=t.length;n<0&&(n=-n>u?0:u+n),(r=r>u?u:r)<0&&(r+=u),u=n>r?0:r-n>>>0,n>>>=0;for(var o=e(u);++i<u;)o[i]=t[i+n];return o}function ui(t,n){var r;return pe(t,function(t,e,i){return!(r=n(t,e,i))}),!!r}function oi(t,n,r){var e=0,i=null==t?e:t.length;if(\"number\"==typeof n&&n==n&&i<=2147483647){for(;e<i;){var u=e+i>>>1,o=t[u];null!==o&&!ca(o)&&(r?o<=n:o<n)?e=u+1:i=u}return i}return ai(t,n,uf,r)}function ai(t,n,r,e){var u=0,o=null==t?0:t.length;if(0===o)return 0;for(var a=(n=r(n))!=n,f=null===n,c=ca(n),l=n===i;u<o;){var s=_n((u+o)/2),h=r(t[s]),p=h!==i,v=null===h,g=h==h,d=ca(h);if(a)var _=e||g;else _=l?g&&(e||p):f?g&&p&&(e||!v):c?g&&p&&!v&&(e||!d):!v&&!d&&(e?h<=n:h<n);_?u=s+1:o=s}return wr(o,4294967294)}function fi(t,n){for(var r=-1,e=t.length,i=0,u=[];++r<e;){var o=t[r],a=n?n(o):o;if(!r||!Mo(a,f)){var f=a;u[i++]=0===o?0:o}}return u}function ci(t){return\"number\"==typeof t?t:ca(t)?g:+t}function li(t){if(\"string\"==typeof t)return t;if(Ho(t))return Wn(t,li)+\"\";if(ca(t))return Pr?Pr.call(t):\"\";var n=t+\"\";return\"0\"==n&&1/t==-1/0?\"-0\":n}function si(t,n,r){var e=-1,i=zn,u=t.length,o=!0,a=[],f=a;if(r)o=!1,i=Bn;else if(u>=200){var c=n?null:Yi(t);if(c)return hr(c);o=!1,i=rr,f=new Gr}else f=n?[]:a;t:for(;++e<u;){var l=t[e],s=n?n(l):l;if(l=r||0!==l?l:0,o&&s==s){for(var h=f.length;h--;)if(f[h]===s)continue t;n&&f.push(s),a.push(l)}else i(f,s,r)||(f!==a&&f.push(s),a.push(l))}return a}function hi(t,n){var r=-1,e=(n=wi(n,t)).length;if(!e)return!0;for(var i=null==t||\"object\"!=typeof t&&\"function\"!=typeof t;++r<e;){var u=n[r];if(\"string\"==typeof u){if(\"__proto__\"===u&&!Wt.call(t,\"__proto__\"))return!1;if(\"constructor\"===u&&r+1<e&&\"string\"==typeof n[r+1]&&\"prototype\"===n[r+1]){if(i&&0===r)continue;return!1}}}var o=Su(t,n);return null==o||delete o[Du(Yu(n))]}function pi(t,n,r,e){return ti(t,n,r(Re(t,n)),e)}function vi(t,n,r,e){for(var i=t.length,u=e?i:-1;(e?u--:++u<i)&&n(t[u],u,t););return r?ii(t,e?0:u,e?u+1:i):ii(t,e?u+1:0,e?i:u)}function gi(t,n){var r=t;return r instanceof Hr&&(r=r.value()),Fn(n,function(t,n){return n.func.apply(n.thisArg,Dn([t],n.args))},r)}function di(t,n,r){var i=t.length;if(i<2)return i?si(t[0]):[];for(var u=-1,o=e(i);++u<i;)for(var a=t[u],f=-1;++f<i;)f!=u&&(o[u]=he(o[u]||a,t[f],n,r));return si(ye(o,1),n,r)}function _i(t,n,r){for(var e=-1,u=t.length,o=n.length,a={};++e<u;){var f=e<o?n[e]:i;r(a,t[e],f)}return a}function yi(t){return Ko(t)?t:[]}function mi(t){return\"function\"==typeof t?t:uf}function wi(t,n){return Ho(t)?t:bu(t,n)?[t]:Wu(ma(t))}var bi=Je;function xi(t,n,r){var e=t.length;return r=r===i?e:r,!n&&r>=e?t:ii(t,n,r)}var Ai=un||function(t){return dn.clearTimeout(t)};function Ri(t,n){if(n)return t.slice();var r=t.length,e=Vt?Vt(r):new t.constructor(r);return t.copy(e),e}function ji(t){var n=new t.constructor(t.byteLength);return new Ht(n).set(new Ht(t)),n}function Ei(t,n){var r=n?ji(t.buffer):t.buffer;return new t.constructor(r,t.byteOffset,t.length)}function Oi(t,n){if(t!==n){var r=t!==i,e=null===t,u=t==t,o=ca(t),a=n!==i,f=null===n,c=n==n,l=ca(n);if(!f&&!l&&!o&&t>n||o&&a&&c&&!f&&!l||e&&a&&c||!r&&c||!u)return 1;if(!e&&!o&&!l&&t<n||l&&r&&u&&!e&&!o||f&&r&&u||!a&&u||!c)return-1}return 0}function Si(t,n,r,i){for(var u=-1,o=t.length,a=r.length,f=-1,c=n.length,l=mr(o-a,0),s=e(c+l),h=!i;++f<c;)s[f]=n[f];for(;++u<a;)(h||u<o)&&(s[r[u]]=t[u]);for(;l--;)s[f++]=t[u++];return s}function ki(t,n,r,i){for(var u=-1,o=t.length,a=-1,f=r.length,c=-1,l=n.length,s=mr(o-f,0),h=e(s+l),p=!i;++u<s;)h[u]=t[u];for(var v=u;++c<l;)h[v+c]=n[c];for(;++a<f;)(p||u<o)&&(h[v+r[a]]=t[u++]);return h}function Li(t,n){var r=-1,i=t.length;for(n||(n=e(i));++r<i;)n[r]=t[r];return n}function Ti(t,n,r,e){var u=!r;r||(r={});for(var o=-1,a=n.length;++o<a;){var f=n[o],c=e?e(r[f],t[f],f,r,t):i;c===i&&(c=t[f]),u?oe(r,f,c):re(r,f,c)}return r}function Ii(t,n){return function(r,e){var i=Ho(r)?kn:ie,u=n?n():{};return i(r,t,cu(e,2),u)}}function Ci(t){return Je(function(n,r){var e=-1,u=r.length,o=u>1?r[u-1]:i,a=u>2?r[2]:i;for(o=t.length>3&&\"function\"==typeof o?(u--,o):i,a&&wu(r[0],r[1],a)&&(o=u<3?i:o,u=1),n=Ot(n);++e<u;){var f=r[e];f&&t(n,f,e,o)}return n})}function zi(t,n){return function(r,e){if(null==r)return r;if(!Zo(r))return t(r,e);for(var i=r.length,u=n?i:-1,o=Ot(r);(n?u--:++u<i)&&!1!==e(o[u],u,o););return r}}function Bi(t){return function(n,r,e){for(var i=-1,u=Ot(n),o=e(n),a=o.length;a--;){var f=o[t?a:++i];if(!1===r(u[f],f,u))break}return n}}function Wi(t){return function(n){var r=fr(n=ma(n))?gr(n):i,e=r?r[0]:n.charAt(0),u=r?xi(r,1).join(\"\"):n.slice(1);return e[t]()+u}}function Di(t){return function(n){return Fn(Xa(qa(n).replace(tn,\"\")),t,\"\")}}function Fi(t){return function(){var n=arguments;switch(n.length){case 0:return new t;case 1:return new t(n[0]);case 2:return new t(n[0],n[1]);case 3:return new t(n[0],n[1],n[2]);case 4:return new t(n[0],n[1],n[2],n[3]);case 5:return new t(n[0],n[1],n[2],n[3],n[4]);case 6:return new t(n[0],n[1],n[2],n[3],n[4],n[5]);case 7:return new t(n[0],n[1],n[2],n[3],n[4],n[5],n[6])}var r=Ur(t.prototype),e=t.apply(r,n);return na(e)?e:r}}function $i(t){return function(n,r,e){var u=Ot(n);if(!Zo(n)){var o=cu(r,3);n=Ia(n),r=function(t){return o(u[t],t,u)}}var a=t(n,r,e);return a>-1?u[o?n[a]:a]:i}}function Pi(t){return eu(function(n){var r=n.length,e=r,o=qr.prototype.thru;for(t&&n.reverse();e--;){var a=n[e];if(\"function\"!=typeof a)throw new Lt(u);if(o&&!f&&\"wrapper\"==au(a))var f=new qr([],!0)}for(e=f?e:r;++e<r;){var c=au(a=n[e]),l=\"wrapper\"==c?ou(a):i;f=l&&xu(l[0])&&424==l[1]&&!l[4].length&&1==l[9]?f[au(l[0])].apply(f,l[3]):1==a.length&&xu(a)?f[c]():f.thru(a)}return function(){var t=arguments,e=t[0];if(f&&1==t.length&&Ho(e))return f.plant(e).value();for(var i=0,u=r?n[i].apply(this,t):e;++i<r;)u=n[i].call(this,u);return u}})}function Mi(t,n,r,u,o,a,f,c,l,h){var p=n&s,v=1&n,g=2&n,d=24&n,_=512&n,y=g?i:Fi(t);return function s(){for(var m=arguments.length,w=e(m),b=m;b--;)w[b]=arguments[b];if(d)var x=fu(s),A=function(t,n){for(var r=t.length,e=0;r--;)t[r]===n&&++e;return e}(w,x);if(u&&(w=Si(w,u,o,d)),a&&(w=ki(w,a,f,d)),m-=A,d&&m<h){var R=sr(w,x);return Ki(t,n,Mi,s.placeholder,r,w,R,c,l,h-m)}var j=v?r:this,E=g?j[t]:t;return m=w.length,c?w=function(t,n){var r=t.length,e=wr(n.length,r),u=Li(t);for(;e--;){var o=n[e];t[e]=mu(o,r)?u[o]:i}return t}(w,c):_&&m>1&&w.reverse(),p&&l<m&&(w.length=l),this&&this!==dn&&this instanceof s&&(E=y||Fi(E)),E.apply(j,w)}}function Ui(t,n){return function(r,e){return function(t,n,r,e){return be(t,function(t,i,u){n(e,r(t),i,u)}),e}(r,t,n(e),{})}}function Ni(t,n){return function(r,e){var u;if(r===i&&e===i)return n;if(r!==i&&(u=r),e!==i){if(u===i)return e;\"string\"==typeof r||\"string\"==typeof e?(r=li(r),e=li(e)):(r=ci(r),e=ci(e)),u=t(r,e)}return u}}function qi(t){return eu(function(n){return n=Wn(n,tr(cu())),Je(function(r){var e=this;return t(n,function(t){return Sn(t,e,r)})})})}function Hi(t,n){var r=(n=n===i?\" \":li(n)).length;if(r<2)return r?Ye(n,t):n;var e=Ye(n,gn(t/vr(n)));return fr(n)?xi(gr(e),0,t).join(\"\"):e.slice(0,t)}function Vi(t){return function(n,r,u){return u&&\"number\"!=typeof u&&wu(n,r,u)&&(r=u=i),n=va(n),r===i?(r=n,n=0):r=va(r),function(t,n,r,i){for(var u=-1,o=mr(gn((n-t)/(r||1)),0),a=e(o);o--;)a[i?o:++u]=t,t+=r;return a}(n,r,u=u===i?n<r?1:-1:va(u),t)}}function Zi(t){return function(n,r){return\"string\"==typeof n&&\"string\"==typeof r||(n=_a(n),r=_a(r)),t(n,r)}}function Ki(t,n,r,e,u,o,a,f,s,h){var p=8&n;n|=p?c:l,4&(n&=~(p?l:c))||(n&=-4);var v=[t,n,u,p?o:i,p?a:i,p?i:o,p?i:a,f,s,h],g=r.apply(i,v);return xu(t)&&Lu(g,v),g.placeholder=e,Cu(g,t,n)}function Gi(t){var n=Et[t];return function(t,r){if(t=_a(t),(r=null==r?0:wr(ga(r),292))&&bn(t)){var e=(ma(t)+\"e\").split(\"e\");return+((e=(ma(n(e[0]+\"e\"+(+e[1]+r)))+\"e\").split(\"e\"))[0]+\"e\"+(+e[1]-r))}return n(t)}}var Yi=Sr&&1/hr(new Sr([,-0]))[1]==p?function(t){return new Sr(t)}:lf;function Ji(t){return function(n){var r=gu(n);return r==j?cr(n):r==L?pr(n):function(t,n){return Wn(n,function(n){return[n,t[n]]})}(n,t(n))}}function Xi(t,n,r,o,p,v,g,d){var _=2&n;if(!_&&\"function\"!=typeof t)throw new Lt(u);var y=o?o.length:0;if(y||(n&=-97,o=p=i),g=g===i?g:mr(ga(g),0),d=d===i?d:ga(d),y-=p?p.length:0,n&l){var m=o,w=p;o=p=i}var b=_?i:ou(t),x=[t,n,r,o,p,m,w,v,g,d];if(b&&function(t,n){var r=t[1],e=n[1],i=r|e,u=i<131,o=e==s&&8==r||e==s&&r==h&&t[7].length<=n[8]||384==e&&n[7].length<=n[8]&&8==r;if(!u&&!o)return t;1&e&&(t[2]=n[2],i|=1&r?0:4);var f=n[3];if(f){var c=t[3];t[3]=c?Si(c,f,n[4]):f,t[4]=c?sr(t[3],a):n[4]}(f=n[5])&&(c=t[5],t[5]=c?ki(c,f,n[6]):f,t[6]=c?sr(t[5],a):n[6]);(f=n[7])&&(t[7]=f);e&s&&(t[8]=null==t[8]?n[8]:wr(t[8],n[8]));null==t[9]&&(t[9]=n[9]);t[0]=n[0],t[1]=i}(x,b),t=x[0],n=x[1],r=x[2],o=x[3],p=x[4],!(d=x[9]=x[9]===i?_?0:t.length:mr(x[9]-y,0))&&24&n&&(n&=-25),n&&1!=n)A=8==n||n==f?function(t,n,r){var u=Fi(t);return function o(){for(var a=arguments.length,f=e(a),c=a,l=fu(o);c--;)f[c]=arguments[c];var s=a<3&&f[0]!==l&&f[a-1]!==l?[]:sr(f,l);return(a-=s.length)<r?Ki(t,n,Mi,o.placeholder,i,f,s,i,i,r-a):Sn(this&&this!==dn&&this instanceof o?u:t,this,f)}}(t,n,d):n!=c&&33!=n||p.length?Mi.apply(i,x):function(t,n,r,i){var u=1&n,o=Fi(t);return function n(){for(var a=-1,f=arguments.length,c=-1,l=i.length,s=e(l+f),h=this&&this!==dn&&this instanceof n?o:t;++c<l;)s[c]=i[c];for(;f--;)s[c++]=arguments[++a];return Sn(h,u?r:this,s)}}(t,n,r,o);else var A=function(t,n,r){var e=1&n,i=Fi(t);return function n(){return(this&&this!==dn&&this instanceof n?i:t).apply(e?r:this,arguments)}}(t,n,r);return Cu((b?ni:Lu)(A,x),t,n)}function Qi(t,n,r,e){return t===i||Mo(t,Ct[r])&&!Wt.call(e,r)?n:t}function tu(t,n,r,e,u,o){return na(t)&&na(n)&&(o.set(n,t),Ne(t,n,i,tu,o),o.delete(n)),t}function nu(t){return ua(t)?i:t}function ru(t,n,r,e,u,o){var a=1&r,f=t.length,c=n.length;if(f!=c&&!(a&&c>f))return!1;var l=o.get(t),s=o.get(n);if(l&&s)return l==n&&s==t;var h=-1,p=!0,v=2&r?new Gr:i;for(o.set(t,n),o.set(n,t);++h<f;){var g=t[h],d=n[h];if(e)var _=a?e(d,g,h,n,t,o):e(g,d,h,t,n,o);if(_!==i){if(_)continue;p=!1;break}if(v){if(!Pn(n,function(t,n){if(!rr(v,n)&&(g===t||u(g,t,r,e,o)))return v.push(n)})){p=!1;break}}else if(g!==d&&!u(g,d,r,e,o)){p=!1;break}}return o.delete(t),o.delete(n),p}function eu(t){return Iu(Ou(t,i,Hu),t+\"\")}function iu(t){return je(t,Ia,pu)}function uu(t){return je(t,Ca,vu)}var ou=Tr?function(t){return Tr.get(t)}:lf;function au(t){for(var n=t.name+\"\",r=Ir[n],e=Wt.call(Ir,n)?r.length:0;e--;){var i=r[e],u=i.func;if(null==u||u==t)return i.name}return n}function fu(t){return(Wt.call(Mr,\"placeholder\")?Mr:t).placeholder}function cu(){var t=Mr.iteratee||of;return t=t===of?We:t,arguments.length?t(arguments[0],arguments[1]):t}function lu(t,n){var r,e,i=t.__data__;return(\"string\"==(e=typeof(r=n))||\"number\"==e||\"symbol\"==e||\"boolean\"==e?\"__proto__\"!==r:null===r)?i[\"string\"==typeof n?\"string\":\"hash\"]:i.map}function su(t){for(var n=Ia(t),r=n.length;r--;){var e=n[r],i=t[e];n[r]=[e,i,ju(i)]}return n}function hu(t,n){var r=function(t,n){return null==t?i:t[n]}(t,n);return Be(r)?r:i}var pu=yn?function(t){return null==t?[]:(t=Ot(t),Cn(yn(t),function(n){return Gt.call(t,n)}))}:_f,vu=yn?function(t){for(var n=[];t;)Dn(n,pu(t)),t=Zt(t);return n}:_f,gu=Ee;function du(t,n,r){for(var e=-1,i=(n=wi(n,t)).length,u=!1;++e<i;){var o=Du(n[e]);if(!(u=null!=t&&r(t,o)))break;t=t[o]}return u||++e!=i?u:!!(i=null==t?0:t.length)&&ta(i)&&mu(o,i)&&(Ho(t)||qo(t))}function _u(t){return\"function\"!=typeof t.constructor||Ru(t)?{}:Ur(Zt(t))}function yu(t){return Ho(t)||qo(t)||!!(Jt&&t&&t[Jt])}function mu(t,n){var r=typeof t;return!!(n=null==n?v:n)&&(\"number\"==r||\"symbol\"!=r&&wt.test(t))&&t>-1&&t%1==0&&t<n}function wu(t,n,r){if(!na(r))return!1;var e=typeof n;return!!(\"number\"==e?Zo(r)&&mu(n,r.length):\"string\"==e&&n in r)&&Mo(r[n],t)}function bu(t,n){if(Ho(t))return!1;var r=typeof t;return!(\"number\"!=r&&\"symbol\"!=r&&\"boolean\"!=r&&null!=t&&!ca(t))||(rt.test(t)||!nt.test(t)||null!=n&&t in Ot(n))}function xu(t){var n=au(t),r=Mr[n];if(\"function\"!=typeof r||!(n in Hr.prototype))return!1;if(t===r)return!0;var e=ou(r);return!!e&&t===e[0]}(jr&&gu(new jr(new ArrayBuffer(1)))!=B||Er&&gu(new Er)!=j||Or&&gu(Or.resolve())!=S||Sr&&gu(new Sr)!=L||kr&&gu(new kr)!=C)&&(gu=function(t){var n=Ee(t),r=n==O?t.constructor:i,e=r?Fu(r):\"\";if(e)switch(e){case Cr:return B;case zr:return j;case Br:return S;case Wr:return L;case Dr:return C}return n});var Au=zt?Xo:yf;function Ru(t){var n=t&&t.constructor;return t===(\"function\"==typeof n&&n.prototype||Ct)}function ju(t){return t==t&&!na(t)}function Eu(t,n){return function(r){return null!=r&&(r[t]===n&&(n!==i||t in Ot(r)))}}function Ou(t,n,r){return n=mr(n===i?t.length-1:n,0),function(){for(var i=arguments,u=-1,o=mr(i.length-n,0),a=e(o);++u<o;)a[u]=i[n+u];u=-1;for(var f=e(n+1);++u<n;)f[u]=i[u];return f[n]=r(a),Sn(t,this,f)}}function Su(t,n){return n.length<2?t:Re(t,ii(n,0,-1))}function ku(t,n){if((\"constructor\"!==n||\"function\"!=typeof t[n])&&\"__proto__\"!=n)return t[n]}var Lu=zu(ni),Tu=vn||function(t,n){return dn.setTimeout(t,n)},Iu=zu(ri);function Cu(t,n,r){var e=n+\"\";return Iu(t,function(t,n){var r=n.length;if(!r)return t;var e=r-1;return n[e]=(r>1?\"& \":\"\")+n[e],n=n.join(r>2?\", \":\" \"),t.replace(ft,\"{\\n/* [wrapped with \"+n+\"] */\\n\")}(e,function(t,n){return Ln(_,function(r){var e=\"_.\"+r[0];n&r[1]&&!zn(t,e)&&t.push(e)}),t.sort()}(function(t){var n=t.match(ct);return n?n[1].split(lt):[]}(e),r)))}function zu(t){var n=0,r=0;return function(){var e=br(),u=16-(e-r);if(r=e,u>0){if(++n>=800)return arguments[0]}else n=0;return t.apply(i,arguments)}}function Bu(t,n){var r=-1,e=t.length,u=e-1;for(n=n===i?e:n;++r<n;){var o=Ge(r,u),a=t[o];t[o]=t[r],t[r]=a}return t.length=n,t}var Wu=function(t){var n=Bo(t,function(t){return 500===r.size&&r.clear(),t}),r=n.cache;return n}(function(t){var n=[];return 46===t.charCodeAt(0)&&n.push(\"\"),t.replace(et,function(t,r,e,i){n.push(e?i.replace(pt,\"$1\"):r||t)}),n});function Du(t){if(\"string\"==typeof t||ca(t))return t;var n=t+\"\";return\"0\"==n&&1/t==-1/0?\"-0\":n}function Fu(t){if(null!=t){try{return Bt.call(t)}catch(t){}try{return t+\"\"}catch(t){}}return\"\"}function $u(t){if(t instanceof Hr)return t.clone();var n=new qr(t.__wrapped__,t.__chain__);return n.__actions__=Li(t.__actions__),n.__index__=t.__index__,n.__values__=t.__values__,n}var Pu=Je(function(t,n){return Ko(t)?he(t,ye(n,1,Ko,!0)):[]}),Mu=Je(function(t,n){var r=Yu(n);return Ko(r)&&(r=i),Ko(t)?he(t,ye(n,1,Ko,!0),cu(r,2)):[]}),Uu=Je(function(t,n){var r=Yu(n);return Ko(r)&&(r=i),Ko(t)?he(t,ye(n,1,Ko,!0),i,r):[]});function Nu(t,n,r){var e=null==t?0:t.length;if(!e)return-1;var i=null==r?0:ga(r);return i<0&&(i=mr(e+i,0)),Nn(t,cu(n,3),i)}function qu(t,n,r){var e=null==t?0:t.length;if(!e)return-1;var u=e-1;return r!==i&&(u=ga(r),u=r<0?mr(e+u,0):wr(u,e-1)),Nn(t,cu(n,3),u,!0)}function Hu(t){return(null==t?0:t.length)?ye(t,1):[]}function Vu(t){return t&&t.length?t[0]:i}var Zu=Je(function(t){var n=Wn(t,yi);return n.length&&n[0]===t[0]?Le(n):[]}),Ku=Je(function(t){var n=Yu(t),r=Wn(t,yi);return n===Yu(r)?n=i:r.pop(),r.length&&r[0]===t[0]?Le(r,cu(n,2)):[]}),Gu=Je(function(t){var n=Yu(t),r=Wn(t,yi);return(n=\"function\"==typeof n?n:i)&&r.pop(),r.length&&r[0]===t[0]?Le(r,i,n):[]});function Yu(t){var n=null==t?0:t.length;return n?t[n-1]:i}var Ju=Je(Xu);function Xu(t,n){return t&&t.length&&n&&n.length?Ze(t,n):t}var Qu=eu(function(t,n){var r=null==t?0:t.length,e=ae(t,n);return Ke(t,Wn(n,function(t){return mu(t,r)?+t:t}).sort(Oi)),e});function to(t){return null==t?t:Rr.call(t)}var no=Je(function(t){return si(ye(t,1,Ko,!0))}),ro=Je(function(t){var n=Yu(t);return Ko(n)&&(n=i),si(ye(t,1,Ko,!0),cu(n,2))}),eo=Je(function(t){var n=Yu(t);return n=\"function\"==typeof n?n:i,si(ye(t,1,Ko,!0),i,n)});function io(t){if(!t||!t.length)return[];var n=0;return t=Cn(t,function(t){if(Ko(t))return n=mr(t.length,n),!0}),Xn(n,function(n){return Wn(t,Kn(n))})}function uo(t,n){if(!t||!t.length)return[];var r=io(t);return null==n?r:Wn(r,function(t){return Sn(n,i,t)})}var oo=Je(function(t,n){return Ko(t)?he(t,n):[]}),ao=Je(function(t){return di(Cn(t,Ko))}),fo=Je(function(t){var n=Yu(t);return Ko(n)&&(n=i),di(Cn(t,Ko),cu(n,2))}),co=Je(function(t){var n=Yu(t);return n=\"function\"==typeof n?n:i,di(Cn(t,Ko),i,n)}),lo=Je(io);var so=Je(function(t){var n=t.length,r=n>1?t[n-1]:i;return r=\"function\"==typeof r?(t.pop(),r):i,uo(t,r)});function ho(t){var n=Mr(t);return n.__chain__=!0,n}function po(t,n){return n(t)}var vo=eu(function(t){var n=t.length,r=n?t[0]:0,e=this.__wrapped__,u=function(n){return ae(n,t)};return!(n>1||this.__actions__.length)&&e instanceof Hr&&mu(r)?((e=e.slice(r,+r+(n?1:0))).__actions__.push({func:po,args:[u],thisArg:i}),new qr(e,this.__chain__).thru(function(t){return n&&!t.length&&t.push(i),t})):this.thru(u)});var go=Ii(function(t,n,r){Wt.call(t,r)?++t[r]:oe(t,r,1)});var _o=$i(Nu),yo=$i(qu);function mo(t,n){return(Ho(t)?Ln:pe)(t,cu(n,3))}function wo(t,n){return(Ho(t)?Tn:ve)(t,cu(n,3))}var bo=Ii(function(t,n,r){Wt.call(t,r)?t[r].push(n):oe(t,r,[n])});var xo=Je(function(t,n,r){var i=-1,u=\"function\"==typeof n,o=Zo(t)?e(t.length):[];return pe(t,function(t){o[++i]=u?Sn(n,t,r):Te(t,n,r)}),o}),Ao=Ii(function(t,n,r){oe(t,r,n)});function Ro(t,n){return(Ho(t)?Wn:Pe)(t,cu(n,3))}var jo=Ii(function(t,n,r){t[r?0:1].push(n)},function(){return[[],[]]});var Eo=Je(function(t,n){if(null==t)return[];var r=n.length;return r>1&&wu(t,n[0],n[1])?n=[]:r>2&&wu(n[0],n[1],n[2])&&(n=[n[0]]),He(t,ye(n,1),[])}),Oo=sn||function(){return dn.Date.now()};function So(t,n,r){return n=r?i:n,n=t&&null==n?t.length:n,Xi(t,s,i,i,i,i,n)}function ko(t,n){var r;if(\"function\"!=typeof n)throw new Lt(u);return t=ga(t),function(){return--t>0&&(r=n.apply(this,arguments)),t<=1&&(n=i),r}}var Lo=Je(function(t,n,r){var e=1;if(r.length){var i=sr(r,fu(Lo));e|=c}return Xi(t,e,n,r,i)}),To=Je(function(t,n,r){var e=3;if(r.length){var i=sr(r,fu(To));e|=c}return Xi(n,e,t,r,i)});function Io(t,n,r){var e,o,a,f,c,l,s=0,h=!1,p=!1,v=!0;if(\"function\"!=typeof t)throw new Lt(u);function g(n){var r=e,u=o;return e=o=i,s=n,f=t.apply(u,r)}function d(t){var r=t-l;return l===i||r>=n||r<0||p&&t-s>=a}function _(){var t=Oo();if(d(t))return y(t);c=Tu(_,function(t){var r=n-(t-l);return p?wr(r,a-(t-s)):r}(t))}function y(t){return c=i,v&&e?g(t):(e=o=i,f)}function m(){var t=Oo(),r=d(t);if(e=arguments,o=this,l=t,r){if(c===i)return function(t){return s=t,c=Tu(_,n),h?g(t):f}(l);if(p)return Ai(c),c=Tu(_,n),g(l)}return c===i&&(c=Tu(_,n)),f}return n=_a(n)||0,na(r)&&(h=!!r.leading,a=(p=\"maxWait\"in r)?mr(_a(r.maxWait)||0,n):a,v=\"trailing\"in r?!!r.trailing:v),m.cancel=function(){c!==i&&Ai(c),s=0,e=l=o=c=i},m.flush=function(){return c===i?f:y(Oo())},m}var Co=Je(function(t,n){return se(t,1,n)}),zo=Je(function(t,n,r){return se(t,_a(n)||0,r)});function Bo(t,n){if(\"function\"!=typeof t||null!=n&&\"function\"!=typeof n)throw new Lt(u);var r=function(){var e=arguments,i=n?n.apply(this,e):e[0],u=r.cache;if(u.has(i))return u.get(i);var o=t.apply(this,e);return r.cache=u.set(i,o)||u,o};return r.cache=new(Bo.Cache||Kr),r}function Wo(t){if(\"function\"!=typeof t)throw new Lt(u);return function(){var n=arguments;switch(n.length){case 0:return!t.call(this);case 1:return!t.call(this,n[0]);case 2:return!t.call(this,n[0],n[1]);case 3:return!t.call(this,n[0],n[1],n[2])}return!t.apply(this,n)}}Bo.Cache=Kr;var Do=bi(function(t,n){var r=(n=1==n.length&&Ho(n[0])?Wn(n[0],tr(cu())):Wn(ye(n,1),tr(cu()))).length;return Je(function(e){for(var i=-1,u=wr(e.length,r);++i<u;)e[i]=n[i].call(this,e[i]);return Sn(t,this,e)})}),Fo=Je(function(t,n){var r=sr(n,fu(Fo));return Xi(t,c,i,n,r)}),$o=Je(function(t,n){var r=sr(n,fu($o));return Xi(t,l,i,n,r)}),Po=eu(function(t,n){return Xi(t,h,i,i,i,n)});function Mo(t,n){return t===n||t!=t&&n!=n}var Uo=Zi(Oe),No=Zi(function(t,n){return t>=n}),qo=Ie(function(){return arguments}())?Ie:function(t){return ra(t)&&Wt.call(t,\"callee\")&&!Gt.call(t,\"callee\")},Ho=e.isArray,Vo=xn?tr(xn):function(t){return ra(t)&&Ee(t)==z};function Zo(t){return null!=t&&ta(t.length)&&!Xo(t)}function Ko(t){return ra(t)&&Zo(t)}var Go=wn||yf,Yo=An?tr(An):function(t){return ra(t)&&Ee(t)==b};function Jo(t){if(!ra(t))return!1;var n=Ee(t);return n==x||\"[object DOMException]\"==n||\"string\"==typeof t.message&&\"string\"==typeof t.name&&!ua(t)}function Xo(t){if(!na(t))return!1;var n=Ee(t);return n==A||n==R||\"[object AsyncFunction]\"==n||\"[object Proxy]\"==n}function Qo(t){return\"number\"==typeof t&&t==ga(t)}function ta(t){return\"number\"==typeof t&&t>-1&&t%1==0&&t<=v}function na(t){var n=typeof t;return null!=t&&(\"object\"==n||\"function\"==n)}function ra(t){return null!=t&&\"object\"==typeof t}var ea=Rn?tr(Rn):function(t){return ra(t)&&gu(t)==j};function ia(t){return\"number\"==typeof t||ra(t)&&Ee(t)==E}function ua(t){if(!ra(t)||Ee(t)!=O)return!1;var n=Zt(t);if(null===n)return!0;var r=Wt.call(n,\"constructor\")&&n.constructor;return\"function\"==typeof r&&r instanceof r&&Bt.call(r)==Pt}var oa=jn?tr(jn):function(t){return ra(t)&&Ee(t)==k};var aa=En?tr(En):function(t){return ra(t)&&gu(t)==L};function fa(t){return\"string\"==typeof t||!Ho(t)&&ra(t)&&Ee(t)==T}function ca(t){return\"symbol\"==typeof t||ra(t)&&Ee(t)==I}var la=On?tr(On):function(t){return ra(t)&&ta(t.length)&&!!cn[Ee(t)]};var sa=Zi($e),ha=Zi(function(t,n){return t<=n});function pa(t){if(!t)return[];if(Zo(t))return fa(t)?gr(t):Li(t);if(Xt&&t[Xt])return function(t){for(var n,r=[];!(n=t.next()).done;)r.push(n.value);return r}(t[Xt]());var n=gu(t);return(n==j?cr:n==L?hr:Ma)(t)}function va(t){return t?(t=_a(t))===p||t===-1/0?17976931348623157e292*(t<0?-1:1):t==t?t:0:0===t?t:0}function ga(t){var n=va(t),r=n%1;return n==n?r?n-r:n:0}function da(t){return t?fe(ga(t),0,d):0}function _a(t){if(\"number\"==typeof t)return t;if(ca(t))return g;if(na(t)){var n=\"function\"==typeof t.valueOf?t.valueOf():t;t=na(n)?n+\"\":n}if(\"string\"!=typeof t)return 0===t?t:+t;t=Qn(t);var r=_t.test(t);return r||mt.test(t)?pn(t.slice(2),r?2:8):dt.test(t)?g:+t}function ya(t){return Ti(t,Ca(t))}function ma(t){return null==t?\"\":li(t)}var wa=Ci(function(t,n){if(Ru(n)||Zo(n))Ti(n,Ia(n),t);else for(var r in n)Wt.call(n,r)&&re(t,r,n[r])}),ba=Ci(function(t,n){Ti(n,Ca(n),t)}),xa=Ci(function(t,n,r,e){Ti(n,Ca(n),t,e)}),Aa=Ci(function(t,n,r,e){Ti(n,Ia(n),t,e)}),Ra=eu(ae);var ja=Je(function(t,n){t=Ot(t);var r=-1,e=n.length,u=e>2?n[2]:i;for(u&&wu(n[0],n[1],u)&&(e=1);++r<e;)for(var o=n[r],a=Ca(o),f=-1,c=a.length;++f<c;){var l=a[f],s=t[l];(s===i||Mo(s,Ct[l])&&!Wt.call(t,l))&&(t[l]=o[l])}return t}),Ea=Je(function(t){return t.push(i,tu),Sn(Ba,i,t)});function Oa(t,n,r){var e=null==t?i:Re(t,n);return e===i?r:e}function Sa(t,n){return null!=t&&du(t,n,ke)}var ka=Ui(function(t,n,r){null!=n&&\"function\"!=typeof n.toString&&(n=$t.call(n)),t[n]=r},nf(uf)),La=Ui(function(t,n,r){null!=n&&\"function\"!=typeof n.toString&&(n=$t.call(n)),Wt.call(t,n)?t[n].push(r):t[n]=[r]},cu),Ta=Je(Te);function Ia(t){return Zo(t)?Jr(t):De(t)}function Ca(t){return Zo(t)?Jr(t,!0):Fe(t)}var za=Ci(function(t,n,r){Ne(t,n,r)}),Ba=Ci(function(t,n,r,e){Ne(t,n,r,e)}),Wa=eu(function(t,n){var r={};if(null==t)return r;var e=!1;n=Wn(n,function(n){return n=wi(n,t),e||(e=n.length>1),n}),Ti(t,uu(t),r),e&&(r=ce(r,7,nu));for(var i=n.length;i--;)hi(r,n[i]);return r});var Da=eu(function(t,n){return null==t?{}:function(t,n){return Ve(t,n,function(n,r){return Sa(t,r)})}(t,n)});function Fa(t,n){if(null==t)return{};var r=Wn(uu(t),function(t){return[t]});return n=cu(n),Ve(t,r,function(t,r){return n(t,r[0])})}var $a=Ji(Ia),Pa=Ji(Ca);function Ma(t){return null==t?[]:nr(t,Ia(t))}var Ua=Di(function(t,n,r){return n=n.toLowerCase(),t+(r?Na(n):n)});function Na(t){return Ja(ma(t).toLowerCase())}function qa(t){return(t=ma(t))&&t.replace(bt,ur).replace(nn,\"\")}var Ha=Di(function(t,n,r){return t+(r?\"-\":\"\")+n.toLowerCase()}),Va=Di(function(t,n,r){return t+(r?\" \":\"\")+n.toLowerCase()}),Za=Wi(\"toLowerCase\");var Ka=Di(function(t,n,r){return t+(r?\"_\":\"\")+n.toLowerCase()});var Ga=Di(function(t,n,r){return t+(r?\" \":\"\")+Ja(n)});var Ya=Di(function(t,n,r){return t+(r?\" \":\"\")+n.toUpperCase()}),Ja=Wi(\"toUpperCase\");function Xa(t,n,r){return t=ma(t),(n=r?i:n)===i?function(t){return on.test(t)}(t)?function(t){return t.match(en)||[]}(t):function(t){return t.match(st)||[]}(t):t.match(n)||[]}var Qa=Je(function(t,n){try{return Sn(t,i,n)}catch(t){return Jo(t)?t:new Rt(t)}}),tf=eu(function(t,n){return Ln(n,function(n){n=Du(n),oe(t,n,Lo(t[n],t))}),t});function nf(t){return function(){return t}}var rf=Pi(),ef=Pi(!0);function uf(t){return t}function of(t){return We(\"function\"==typeof t?t:ce(t,1))}var af=Je(function(t,n){return function(r){return Te(r,t,n)}}),ff=Je(function(t,n){return function(r){return Te(t,r,n)}});function cf(t,n,r){var e=Ia(n),i=Ae(n,e);null!=r||na(n)&&(i.length||!e.length)||(r=n,n=t,t=this,i=Ae(n,Ia(n)));var u=!(na(r)&&\"chain\"in r&&!r.chain),o=Xo(t);return Ln(i,function(r){var e=n[r];t[r]=e,o&&(t.prototype[r]=function(){var n=this.__chain__;if(u||n){var r=t(this.__wrapped__);return(r.__actions__=Li(this.__actions__)).push({func:e,args:arguments,thisArg:t}),r.__chain__=n,r}return e.apply(t,Dn([this.value()],arguments))})}),t}function lf(){}var sf=qi(Wn),hf=qi(In),pf=qi(Pn);function vf(t){return bu(t)?Kn(Du(t)):function(t){return function(n){return Re(n,t)}}(t)}var gf=Vi(),df=Vi(!0);function _f(){return[]}function yf(){return!1}var mf=Ni(function(t,n){return t+n},0),wf=Gi(\"ceil\"),bf=Ni(function(t,n){return t/n},1),xf=Gi(\"floor\");var Af,Rf=Ni(function(t,n){return t*n},1),jf=Gi(\"round\"),Ef=Ni(function(t,n){return t-n},0);return Mr.after=function(t,n){if(\"function\"!=typeof n)throw new Lt(u);return t=ga(t),function(){if(--t<1)return n.apply(this,arguments)}},Mr.ary=So,Mr.assign=wa,Mr.assignIn=ba,Mr.assignInWith=xa,Mr.assignWith=Aa,Mr.at=Ra,Mr.before=ko,Mr.bind=Lo,Mr.bindAll=tf,Mr.bindKey=To,Mr.castArray=function(){if(!arguments.length)return[];var t=arguments[0];return Ho(t)?t:[t]},Mr.chain=ho,Mr.chunk=function(t,n,r){n=(r?wu(t,n,r):n===i)?1:mr(ga(n),0);var u=null==t?0:t.length;if(!u||n<1)return[];for(var o=0,a=0,f=e(gn(u/n));o<u;)f[a++]=ii(t,o,o+=n);return f},Mr.compact=function(t){for(var n=-1,r=null==t?0:t.length,e=0,i=[];++n<r;){var u=t[n];u&&(i[e++]=u)}return i},Mr.concat=function(){var t=arguments.length;if(!t)return[];for(var n=e(t-1),r=arguments[0],i=t;i--;)n[i-1]=arguments[i];return Dn(Ho(r)?Li(r):[r],ye(n,1))},Mr.cond=function(t){var n=null==t?0:t.length,r=cu();return t=n?Wn(t,function(t){if(\"function\"!=typeof t[1])throw new Lt(u);return[r(t[0]),t[1]]}):[],Je(function(r){for(var e=-1;++e<n;){var i=t[e];if(Sn(i[0],this,r))return Sn(i[1],this,r)}})},Mr.conforms=function(t){return function(t){var n=Ia(t);return function(r){return le(r,t,n)}}(ce(t,1))},Mr.constant=nf,Mr.countBy=go,Mr.create=function(t,n){var r=Ur(t);return null==n?r:ue(r,n)},Mr.curry=function t(n,r,e){var u=Xi(n,8,i,i,i,i,i,r=e?i:r);return u.placeholder=t.placeholder,u},Mr.curryRight=function t(n,r,e){var u=Xi(n,f,i,i,i,i,i,r=e?i:r);return u.placeholder=t.placeholder,u},Mr.debounce=Io,Mr.defaults=ja,Mr.defaultsDeep=Ea,Mr.defer=Co,Mr.delay=zo,Mr.difference=Pu,Mr.differenceBy=Mu,Mr.differenceWith=Uu,Mr.drop=function(t,n,r){var e=null==t?0:t.length;return e?ii(t,(n=r||n===i?1:ga(n))<0?0:n,e):[]},Mr.dropRight=function(t,n,r){var e=null==t?0:t.length;return e?ii(t,0,(n=e-(n=r||n===i?1:ga(n)))<0?0:n):[]},Mr.dropRightWhile=function(t,n){return t&&t.length?vi(t,cu(n,3),!0,!0):[]},Mr.dropWhile=function(t,n){return t&&t.length?vi(t,cu(n,3),!0):[]},Mr.fill=function(t,n,r,e){var u=null==t?0:t.length;return u?(r&&\"number\"!=typeof r&&wu(t,n,r)&&(r=0,e=u),function(t,n,r,e){var u=t.length;for((r=ga(r))<0&&(r=-r>u?0:u+r),(e=e===i||e>u?u:ga(e))<0&&(e+=u),e=r>e?0:da(e);r<e;)t[r++]=n;return t}(t,n,r,e)):[]},Mr.filter=function(t,n){return(Ho(t)?Cn:_e)(t,cu(n,3))},Mr.flatMap=function(t,n){return ye(Ro(t,n),1)},Mr.flatMapDeep=function(t,n){return ye(Ro(t,n),p)},Mr.flatMapDepth=function(t,n,r){return r=r===i?1:ga(r),ye(Ro(t,n),r)},Mr.flatten=Hu,Mr.flattenDeep=function(t){return(null==t?0:t.length)?ye(t,p):[]},Mr.flattenDepth=function(t,n){return(null==t?0:t.length)?ye(t,n=n===i?1:ga(n)):[]},Mr.flip=function(t){return Xi(t,512)},Mr.flow=rf,Mr.flowRight=ef,Mr.fromPairs=function(t){for(var n=-1,r=null==t?0:t.length,e={};++n<r;){var i=t[n];e[i[0]]=i[1]}return e},Mr.functions=function(t){return null==t?[]:Ae(t,Ia(t))},Mr.functionsIn=function(t){return null==t?[]:Ae(t,Ca(t))},Mr.groupBy=bo,Mr.initial=function(t){return(null==t?0:t.length)?ii(t,0,-1):[]},Mr.intersection=Zu,Mr.intersectionBy=Ku,Mr.intersectionWith=Gu,Mr.invert=ka,Mr.invertBy=La,Mr.invokeMap=xo,Mr.iteratee=of,Mr.keyBy=Ao,Mr.keys=Ia,Mr.keysIn=Ca,Mr.map=Ro,Mr.mapKeys=function(t,n){var r={};return n=cu(n,3),be(t,function(t,e,i){oe(r,n(t,e,i),t)}),r},Mr.mapValues=function(t,n){var r={};return n=cu(n,3),be(t,function(t,e,i){oe(r,e,n(t,e,i))}),r},Mr.matches=function(t){return Me(ce(t,1))},Mr.matchesProperty=function(t,n){return Ue(t,ce(n,1))},Mr.memoize=Bo,Mr.merge=za,Mr.mergeWith=Ba,Mr.method=af,Mr.methodOf=ff,Mr.mixin=cf,Mr.negate=Wo,Mr.nthArg=function(t){return t=ga(t),Je(function(n){return qe(n,t)})},Mr.omit=Wa,Mr.omitBy=function(t,n){return Fa(t,Wo(cu(n)))},Mr.once=function(t){return ko(2,t)},Mr.orderBy=function(t,n,r,e){return null==t?[]:(Ho(n)||(n=null==n?[]:[n]),Ho(r=e?i:r)||(r=null==r?[]:[r]),He(t,n,r))},Mr.over=sf,Mr.overArgs=Do,Mr.overEvery=hf,Mr.overSome=pf,Mr.partial=Fo,Mr.partialRight=$o,Mr.partition=jo,Mr.pick=Da,Mr.pickBy=Fa,Mr.property=vf,Mr.propertyOf=function(t){return function(n){return null==t?i:Re(t,n)}},Mr.pull=Ju,Mr.pullAll=Xu,Mr.pullAllBy=function(t,n,r){return t&&t.length&&n&&n.length?Ze(t,n,cu(r,2)):t},Mr.pullAllWith=function(t,n,r){return t&&t.length&&n&&n.length?Ze(t,n,i,r):t},Mr.pullAt=Qu,Mr.range=gf,Mr.rangeRight=df,Mr.rearg=Po,Mr.reject=function(t,n){return(Ho(t)?Cn:_e)(t,Wo(cu(n,3)))},Mr.remove=function(t,n){var r=[];if(!t||!t.length)return r;var e=-1,i=[],u=t.length;for(n=cu(n,3);++e<u;){var o=t[e];n(o,e,t)&&(r.push(o),i.push(e))}return Ke(t,i),r},Mr.rest=function(t,n){if(\"function\"!=typeof t)throw new Lt(u);return Je(t,n=n===i?n:ga(n))},Mr.reverse=to,Mr.sampleSize=function(t,n,r){return n=(r?wu(t,n,r):n===i)?1:ga(n),(Ho(t)?Qr:Qe)(t,n)},Mr.set=function(t,n,r){return null==t?t:ti(t,n,r)},Mr.setWith=function(t,n,r,e){return e=\"function\"==typeof e?e:i,null==t?t:ti(t,n,r,e)},Mr.shuffle=function(t){return(Ho(t)?te:ei)(t)},Mr.slice=function(t,n,r){var e=null==t?0:t.length;return e?(r&&\"number\"!=typeof r&&wu(t,n,r)?(n=0,r=e):(n=null==n?0:ga(n),r=r===i?e:ga(r)),ii(t,n,r)):[]},Mr.sortBy=Eo,Mr.sortedUniq=function(t){return t&&t.length?fi(t):[]},Mr.sortedUniqBy=function(t,n){return t&&t.length?fi(t,cu(n,2)):[]},Mr.split=function(t,n,r){return r&&\"number\"!=typeof r&&wu(t,n,r)&&(n=r=i),(r=r===i?d:r>>>0)?(t=ma(t))&&(\"string\"==typeof n||null!=n&&!oa(n))&&!(n=li(n))&&fr(t)?xi(gr(t),0,r):t.split(n,r):[]},Mr.spread=function(t,n){if(\"function\"!=typeof t)throw new Lt(u);return n=null==n?0:mr(ga(n),0),Je(function(r){var e=r[n],i=xi(r,0,n);return e&&Dn(i,e),Sn(t,this,i)})},Mr.tail=function(t){var n=null==t?0:t.length;return n?ii(t,1,n):[]},Mr.take=function(t,n,r){return t&&t.length?ii(t,0,(n=r||n===i?1:ga(n))<0?0:n):[]},Mr.takeRight=function(t,n,r){var e=null==t?0:t.length;return e?ii(t,(n=e-(n=r||n===i?1:ga(n)))<0?0:n,e):[]},Mr.takeRightWhile=function(t,n){return t&&t.length?vi(t,cu(n,3),!1,!0):[]},Mr.takeWhile=function(t,n){return t&&t.length?vi(t,cu(n,3)):[]},Mr.tap=function(t,n){return n(t),t},Mr.throttle=function(t,n,r){var e=!0,i=!0;if(\"function\"!=typeof t)throw new Lt(u);return na(r)&&(e=\"leading\"in r?!!r.leading:e,i=\"trailing\"in r?!!r.trailing:i),Io(t,n,{leading:e,maxWait:n,trailing:i})},Mr.thru=po,Mr.toArray=pa,Mr.toPairs=$a,Mr.toPairsIn=Pa,Mr.toPath=function(t){return Ho(t)?Wn(t,Du):ca(t)?[t]:Li(Wu(ma(t)))},Mr.toPlainObject=ya,Mr.transform=function(t,n,r){var e=Ho(t),i=e||Go(t)||la(t);if(n=cu(n,4),null==r){var u=t&&t.constructor;r=i?e?new u:[]:na(t)&&Xo(u)?Ur(Zt(t)):{}}return(i?Ln:be)(t,function(t,e,i){return n(r,t,e,i)}),r},Mr.unary=function(t){return So(t,1)},Mr.union=no,Mr.unionBy=ro,Mr.unionWith=eo,Mr.uniq=function(t){return t&&t.length?si(t):[]},Mr.uniqBy=function(t,n){return t&&t.length?si(t,cu(n,2)):[]},Mr.uniqWith=function(t,n){return n=\"function\"==typeof n?n:i,t&&t.length?si(t,i,n):[]},Mr.unset=function(t,n){return null==t||hi(t,n)},Mr.unzip=io,Mr.unzipWith=uo,Mr.update=function(t,n,r){return null==t?t:pi(t,n,mi(r))},Mr.updateWith=function(t,n,r,e){return e=\"function\"==typeof e?e:i,null==t?t:pi(t,n,mi(r),e)},Mr.values=Ma,Mr.valuesIn=function(t){return null==t?[]:nr(t,Ca(t))},Mr.without=oo,Mr.words=Xa,Mr.wrap=function(t,n){return Fo(mi(n),t)},Mr.xor=ao,Mr.xorBy=fo,Mr.xorWith=co,Mr.zip=lo,Mr.zipObject=function(t,n){return _i(t||[],n||[],re)},Mr.zipObjectDeep=function(t,n){return _i(t||[],n||[],ti)},Mr.zipWith=so,Mr.entries=$a,Mr.entriesIn=Pa,Mr.extend=ba,Mr.extendWith=xa,cf(Mr,Mr),Mr.add=mf,Mr.attempt=Qa,Mr.camelCase=Ua,Mr.capitalize=Na,Mr.ceil=wf,Mr.clamp=function(t,n,r){return r===i&&(r=n,n=i),r!==i&&(r=(r=_a(r))==r?r:0),n!==i&&(n=(n=_a(n))==n?n:0),fe(_a(t),n,r)},Mr.clone=function(t){return ce(t,4)},Mr.cloneDeep=function(t){return ce(t,5)},Mr.cloneDeepWith=function(t,n){return ce(t,5,n=\"function\"==typeof n?n:i)},Mr.cloneWith=function(t,n){return ce(t,4,n=\"function\"==typeof n?n:i)},Mr.conformsTo=function(t,n){return null==n||le(t,n,Ia(n))},Mr.deburr=qa,Mr.defaultTo=function(t,n){return null==t||t!=t?n:t},Mr.divide=bf,Mr.endsWith=function(t,n,r){t=ma(t),n=li(n);var e=t.length,u=r=r===i?e:fe(ga(r),0,e);return(r-=n.length)>=0&&t.slice(r,u)==n},Mr.eq=Mo,Mr.escape=function(t){return(t=ma(t))&&J.test(t)?t.replace(G,or):t},Mr.escapeRegExp=function(t){return(t=ma(t))&&ut.test(t)?t.replace(it,\"\\\\$&\"):t},Mr.every=function(t,n,r){var e=Ho(t)?In:ge;return r&&wu(t,n,r)&&(n=i),e(t,cu(n,3))},Mr.find=_o,Mr.findIndex=Nu,Mr.findKey=function(t,n){return Un(t,cu(n,3),be)},Mr.findLast=yo,Mr.findLastIndex=qu,Mr.findLastKey=function(t,n){return Un(t,cu(n,3),xe)},Mr.floor=xf,Mr.forEach=mo,Mr.forEachRight=wo,Mr.forIn=function(t,n){return null==t?t:me(t,cu(n,3),Ca)},Mr.forInRight=function(t,n){return null==t?t:we(t,cu(n,3),Ca)},Mr.forOwn=function(t,n){return t&&be(t,cu(n,3))},Mr.forOwnRight=function(t,n){return t&&xe(t,cu(n,3))},Mr.get=Oa,Mr.gt=Uo,Mr.gte=No,Mr.has=function(t,n){return null!=t&&du(t,n,Se)},Mr.hasIn=Sa,Mr.head=Vu,Mr.identity=uf,Mr.includes=function(t,n,r,e){t=Zo(t)?t:Ma(t),r=r&&!e?ga(r):0;var i=t.length;return r<0&&(r=mr(i+r,0)),fa(t)?r<=i&&t.indexOf(n,r)>-1:!!i&&qn(t,n,r)>-1},Mr.indexOf=function(t,n,r){var e=null==t?0:t.length;if(!e)return-1;var i=null==r?0:ga(r);return i<0&&(i=mr(e+i,0)),qn(t,n,i)},Mr.inRange=function(t,n,r){return n=va(n),r===i?(r=n,n=0):r=va(r),function(t,n,r){return t>=wr(n,r)&&t<mr(n,r)}(t=_a(t),n,r)},Mr.invoke=Ta,Mr.isArguments=qo,Mr.isArray=Ho,Mr.isArrayBuffer=Vo,Mr.isArrayLike=Zo,Mr.isArrayLikeObject=Ko,Mr.isBoolean=function(t){return!0===t||!1===t||ra(t)&&Ee(t)==w},Mr.isBuffer=Go,Mr.isDate=Yo,Mr.isElement=function(t){return ra(t)&&1===t.nodeType&&!ua(t)},Mr.isEmpty=function(t){if(null==t)return!0;if(Zo(t)&&(Ho(t)||\"string\"==typeof t||\"function\"==typeof t.splice||Go(t)||la(t)||qo(t)))return!t.length;var n=gu(t);if(n==j||n==L)return!t.size;if(Ru(t))return!De(t).length;for(var r in t)if(Wt.call(t,r))return!1;return!0},Mr.isEqual=function(t,n){return Ce(t,n)},Mr.isEqualWith=function(t,n,r){var e=(r=\"function\"==typeof r?r:i)?r(t,n):i;return e===i?Ce(t,n,i,r):!!e},Mr.isError=Jo,Mr.isFinite=function(t){return\"number\"==typeof t&&bn(t)},Mr.isFunction=Xo,Mr.isInteger=Qo,Mr.isLength=ta,Mr.isMap=ea,Mr.isMatch=function(t,n){return t===n||ze(t,n,su(n))},Mr.isMatchWith=function(t,n,r){return r=\"function\"==typeof r?r:i,ze(t,n,su(n),r)},Mr.isNaN=function(t){return ia(t)&&t!=+t},Mr.isNative=function(t){if(Au(t))throw new Rt(\"Unsupported core-js use. Try https://npms.io/search?q=ponyfill.\");return Be(t)},Mr.isNil=function(t){return null==t},Mr.isNull=function(t){return null===t},Mr.isNumber=ia,Mr.isObject=na,Mr.isObjectLike=ra,Mr.isPlainObject=ua,Mr.isRegExp=oa,Mr.isSafeInteger=function(t){return Qo(t)&&t>=-9007199254740991&&t<=v},Mr.isSet=aa,Mr.isString=fa,Mr.isSymbol=ca,Mr.isTypedArray=la,Mr.isUndefined=function(t){return t===i},Mr.isWeakMap=function(t){return ra(t)&&gu(t)==C},Mr.isWeakSet=function(t){return ra(t)&&\"[object WeakSet]\"==Ee(t)},Mr.join=function(t,n){return null==t?\"\":Mn.call(t,n)},Mr.kebabCase=Ha,Mr.last=Yu,Mr.lastIndexOf=function(t,n,r){var e=null==t?0:t.length;if(!e)return-1;var u=e;return r!==i&&(u=(u=ga(r))<0?mr(e+u,0):wr(u,e-1)),n==n?function(t,n,r){for(var e=r+1;e--;)if(t[e]===n)return e;return e}(t,n,u):Nn(t,Vn,u,!0)},Mr.lowerCase=Va,Mr.lowerFirst=Za,Mr.lt=sa,Mr.lte=ha,Mr.max=function(t){return t&&t.length?de(t,uf,Oe):i},Mr.maxBy=function(t,n){return t&&t.length?de(t,cu(n,2),Oe):i},Mr.mean=function(t){return Zn(t,uf)},Mr.meanBy=function(t,n){return Zn(t,cu(n,2))},Mr.min=function(t){return t&&t.length?de(t,uf,$e):i},Mr.minBy=function(t,n){return t&&t.length?de(t,cu(n,2),$e):i},Mr.stubArray=_f,Mr.stubFalse=yf,Mr.stubObject=function(){return{}},Mr.stubString=function(){return\"\"},Mr.stubTrue=function(){return!0},Mr.multiply=Rf,Mr.nth=function(t,n){return t&&t.length?qe(t,ga(n)):i},Mr.noConflict=function(){return dn._===this&&(dn._=Mt),this},Mr.noop=lf,Mr.now=Oo,Mr.pad=function(t,n,r){t=ma(t);var e=(n=ga(n))?vr(t):0;if(!n||e>=n)return t;var i=(n-e)/2;return Hi(_n(i),r)+t+Hi(gn(i),r)},Mr.padEnd=function(t,n,r){t=ma(t);var e=(n=ga(n))?vr(t):0;return n&&e<n?t+Hi(n-e,r):t},Mr.padStart=function(t,n,r){t=ma(t);var e=(n=ga(n))?vr(t):0;return n&&e<n?Hi(n-e,r)+t:t},Mr.parseInt=function(t,n,r){return r||null==n?n=0:n&&(n=+n),xr(ma(t).replace(ot,\"\"),n||0)},Mr.random=function(t,n,r){if(r&&\"boolean\"!=typeof r&&wu(t,n,r)&&(n=r=i),r===i&&(\"boolean\"==typeof n?(r=n,n=i):\"boolean\"==typeof t&&(r=t,t=i)),t===i&&n===i?(t=0,n=1):(t=va(t),n===i?(n=t,t=0):n=va(n)),t>n){var e=t;t=n,n=e}if(r||t%1||n%1){var u=Ar();return wr(t+u*(n-t+hn(\"1e-\"+((u+\"\").length-1))),n)}return Ge(t,n)},Mr.reduce=function(t,n,r){var e=Ho(t)?Fn:Yn,i=arguments.length<3;return e(t,cu(n,4),r,i,pe)},Mr.reduceRight=function(t,n,r){var e=Ho(t)?$n:Yn,i=arguments.length<3;return e(t,cu(n,4),r,i,ve)},Mr.repeat=function(t,n,r){return n=(r?wu(t,n,r):n===i)?1:ga(n),Ye(ma(t),n)},Mr.replace=function(){var t=arguments,n=ma(t[0]);return t.length<3?n:n.replace(t[1],t[2])},Mr.result=function(t,n,r){var e=-1,u=(n=wi(n,t)).length;for(u||(u=1,t=i);++e<u;){var o=null==t?i:t[Du(n[e])];o===i&&(e=u,o=r),t=Xo(o)?o.call(t):o}return t},Mr.round=jf,Mr.runInContext=t,Mr.sample=function(t){return(Ho(t)?Xr:Xe)(t)},Mr.size=function(t){if(null==t)return 0;if(Zo(t))return fa(t)?vr(t):t.length;var n=gu(t);return n==j||n==L?t.size:De(t).length},Mr.snakeCase=Ka,Mr.some=function(t,n,r){var e=Ho(t)?Pn:ui;return r&&wu(t,n,r)&&(n=i),e(t,cu(n,3))},Mr.sortedIndex=function(t,n){return oi(t,n)},Mr.sortedIndexBy=function(t,n,r){return ai(t,n,cu(r,2))},Mr.sortedIndexOf=function(t,n){var r=null==t?0:t.length;if(r){var e=oi(t,n);if(e<r&&Mo(t[e],n))return e}return-1},Mr.sortedLastIndex=function(t,n){return oi(t,n,!0)},Mr.sortedLastIndexBy=function(t,n,r){return ai(t,n,cu(r,2),!0)},Mr.sortedLastIndexOf=function(t,n){if(null==t?0:t.length){var r=oi(t,n,!0)-1;if(Mo(t[r],n))return r}return-1},Mr.startCase=Ga,Mr.startsWith=function(t,n,r){return t=ma(t),r=null==r?0:fe(ga(r),0,t.length),n=li(n),t.slice(r,r+n.length)==n},Mr.subtract=Ef,Mr.sum=function(t){return t&&t.length?Jn(t,uf):0},Mr.sumBy=function(t,n){return t&&t.length?Jn(t,cu(n,2)):0},Mr.template=function(t,n,r){var e=Mr.templateSettings;r&&wu(t,n,r)&&(n=i),t=ma(t),n=xa({},n,e,Qi);var u,o,a=xa({},n.imports,e.imports,Qi),f=Ia(a),c=nr(a,f),l=0,s=n.interpolate||xt,h=\"__p += '\",p=St((n.escape||xt).source+\"|\"+s.source+\"|\"+(s===tt?vt:xt).source+\"|\"+(n.evaluate||xt).source+\"|$\",\"g\"),v=\"//# sourceURL=\"+(Wt.call(n,\"sourceURL\")?(n.sourceURL+\"\").replace(/\\s/g,\" \"):\"lodash.templateSources[\"+ ++fn+\"]\")+\"\\n\";t.replace(p,function(n,r,e,i,a,f){return e||(e=i),h+=t.slice(l,f).replace(At,ar),r&&(u=!0,h+=\"' +\\n__e(\"+r+\") +\\n'\"),a&&(o=!0,h+=\"';\\n\"+a+\";\\n__p += '\"),e&&(h+=\"' +\\n((__t = (\"+e+\")) == null ? '' : __t) +\\n'\"),l=f+n.length,n}),h+=\"';\\n\";var g=Wt.call(n,\"variable\")&&n.variable;if(g){if(ht.test(g))throw new Rt(\"Invalid `variable` option passed into `_.template`\")}else h=\"with (obj) {\\n\"+h+\"\\n}\\n\";h=(o?h.replace(H,\"\"):h).replace(V,\"$1\").replace(Z,\"$1;\"),h=\"function(\"+(g||\"obj\")+\") {\\n\"+(g?\"\":\"obj || (obj = {});\\n\")+\"var __t, __p = ''\"+(u?\", __e = _.escape\":\"\")+(o?\", __j = Array.prototype.join;\\nfunction print() { __p += __j.call(arguments, '') }\\n\":\";\\n\")+h+\"return __p\\n}\";var d=Qa(function(){return jt(f,v+\"return \"+h).apply(i,c)});if(d.source=h,Jo(d))throw d;return d},Mr.times=function(t,n){if((t=ga(t))<1||t>v)return[];var r=d,e=wr(t,d);n=cu(n),t-=d;for(var i=Xn(e,n);++r<t;)n(r);return i},Mr.toFinite=va,Mr.toInteger=ga,Mr.toLength=da,Mr.toLower=function(t){return ma(t).toLowerCase()},Mr.toNumber=_a,Mr.toSafeInteger=function(t){return t?fe(ga(t),-9007199254740991,v):0===t?t:0},Mr.toString=ma,Mr.toUpper=function(t){return ma(t).toUpperCase()},Mr.trim=function(t,n,r){if((t=ma(t))&&(r||n===i))return Qn(t);if(!t||!(n=li(n)))return t;var e=gr(t),u=gr(n);return xi(e,er(e,u),ir(e,u)+1).join(\"\")},Mr.trimEnd=function(t,n,r){if((t=ma(t))&&(r||n===i))return t.slice(0,dr(t)+1);if(!t||!(n=li(n)))return t;var e=gr(t);return xi(e,0,ir(e,gr(n))+1).join(\"\")},Mr.trimStart=function(t,n,r){if((t=ma(t))&&(r||n===i))return t.replace(ot,\"\");if(!t||!(n=li(n)))return t;var e=gr(t);return xi(e,er(e,gr(n))).join(\"\")},Mr.truncate=function(t,n){var r=30,e=\"...\";if(na(n)){var u=\"separator\"in n?n.separator:u;r=\"length\"in n?ga(n.length):r,e=\"omission\"in n?li(n.omission):e}var o=(t=ma(t)).length;if(fr(t)){var a=gr(t);o=a.length}if(r>=o)return t;var f=r-vr(e);if(f<1)return e;var c=a?xi(a,0,f).join(\"\"):t.slice(0,f);if(u===i)return c+e;if(a&&(f+=c.length-f),oa(u)){if(t.slice(f).search(u)){var l,s=c;for(u.global||(u=St(u.source,ma(gt.exec(u))+\"g\")),u.lastIndex=0;l=u.exec(s);)var h=l.index;c=c.slice(0,h===i?f:h)}}else if(t.indexOf(li(u),f)!=f){var p=c.lastIndexOf(u);p>-1&&(c=c.slice(0,p))}return c+e},Mr.unescape=function(t){return(t=ma(t))&&Y.test(t)?t.replace(K,_r):t},Mr.uniqueId=function(t){var n=++Dt;return ma(t)+n},Mr.upperCase=Ya,Mr.upperFirst=Ja,Mr.each=mo,Mr.eachRight=wo,Mr.first=Vu,cf(Mr,(Af={},be(Mr,function(t,n){Wt.call(Mr.prototype,n)||(Af[n]=t)}),Af),{chain:!1}),Mr.VERSION=\"4.17.23\",Ln([\"bind\",\"bindKey\",\"curry\",\"curryRight\",\"partial\",\"partialRight\"],function(t){Mr[t].placeholder=Mr}),Ln([\"drop\",\"take\"],function(t,n){Hr.prototype[t]=function(r){r=r===i?1:mr(ga(r),0);var e=this.__filtered__&&!n?new Hr(this):this.clone();return e.__filtered__?e.__takeCount__=wr(r,e.__takeCount__):e.__views__.push({size:wr(r,d),type:t+(e.__dir__<0?\"Right\":\"\")}),e},Hr.prototype[t+\"Right\"]=function(n){return this.reverse()[t](n).reverse()}}),Ln([\"filter\",\"map\",\"takeWhile\"],function(t,n){var r=n+1,e=1==r||3==r;Hr.prototype[t]=function(t){var n=this.clone();return n.__iteratees__.push({iteratee:cu(t,3),type:r}),n.__filtered__=n.__filtered__||e,n}}),Ln([\"head\",\"last\"],function(t,n){var r=\"take\"+(n?\"Right\":\"\");Hr.prototype[t]=function(){return this[r](1).value()[0]}}),Ln([\"initial\",\"tail\"],function(t,n){var r=\"drop\"+(n?\"\":\"Right\");Hr.prototype[t]=function(){return this.__filtered__?new Hr(this):this[r](1)}}),Hr.prototype.compact=function(){return this.filter(uf)},Hr.prototype.find=function(t){return this.filter(t).head()},Hr.prototype.findLast=function(t){return this.reverse().find(t)},Hr.prototype.invokeMap=Je(function(t,n){return\"function\"==typeof t?new Hr(this):this.map(function(r){return Te(r,t,n)})}),Hr.prototype.reject=function(t){return this.filter(Wo(cu(t)))},Hr.prototype.slice=function(t,n){t=ga(t);var r=this;return r.__filtered__&&(t>0||n<0)?new Hr(r):(t<0?r=r.takeRight(-t):t&&(r=r.drop(t)),n!==i&&(r=(n=ga(n))<0?r.dropRight(-n):r.take(n-t)),r)},Hr.prototype.takeRightWhile=function(t){return this.reverse().takeWhile(t).reverse()},Hr.prototype.toArray=function(){return this.take(d)},be(Hr.prototype,function(t,n){var r=/^(?:filter|find|map|reject)|While$/.test(n),e=/^(?:head|last)$/.test(n),u=Mr[e?\"take\"+(\"last\"==n?\"Right\":\"\"):n],o=e||/^find/.test(n);u&&(Mr.prototype[n]=function(){var n=this.__wrapped__,a=e?[1]:arguments,f=n instanceof Hr,c=a[0],l=f||Ho(n),s=function(t){var n=u.apply(Mr,Dn([t],a));return e&&h?n[0]:n};l&&r&&\"function\"==typeof c&&1!=c.length&&(f=l=!1);var h=this.__chain__,p=!!this.__actions__.length,v=o&&!h,g=f&&!p;if(!o&&l){n=g?n:new Hr(this);var d=t.apply(n,a);return d.__actions__.push({func:po,args:[s],thisArg:i}),new qr(d,h)}return v&&g?t.apply(this,a):(d=this.thru(s),v?e?d.value()[0]:d.value():d)})}),Ln([\"pop\",\"push\",\"shift\",\"sort\",\"splice\",\"unshift\"],function(t){var n=Tt[t],r=/^(?:push|sort|unshift)$/.test(t)?\"tap\":\"thru\",e=/^(?:pop|shift)$/.test(t);Mr.prototype[t]=function(){var t=arguments;if(e&&!this.__chain__){var i=this.value();return n.apply(Ho(i)?i:[],t)}return this[r](function(r){return n.apply(Ho(r)?r:[],t)})}}),be(Hr.prototype,function(t,n){var r=Mr[n];if(r){var e=r.name+\"\";Wt.call(Ir,e)||(Ir[e]=[]),Ir[e].push({name:n,func:r})}}),Ir[Mi(i,2).name]=[{name:\"wrapper\",func:i}],Hr.prototype.clone=function(){var t=new Hr(this.__wrapped__);return t.__actions__=Li(this.__actions__),t.__dir__=this.__dir__,t.__filtered__=this.__filtered__,t.__iteratees__=Li(this.__iteratees__),t.__takeCount__=this.__takeCount__,t.__views__=Li(this.__views__),t},Hr.prototype.reverse=function(){if(this.__filtered__){var t=new Hr(this);t.__dir__=-1,t.__filtered__=!0}else(t=this.clone()).__dir__*=-1;return t},Hr.prototype.value=function(){var t=this.__wrapped__.value(),n=this.__dir__,r=Ho(t),e=n<0,i=r?t.length:0,u=function(t,n,r){var e=-1,i=r.length;for(;++e<i;){var u=r[e],o=u.size;switch(u.type){case\"drop\":t+=o;break;case\"dropRight\":n-=o;break;case\"take\":n=wr(n,t+o);break;case\"takeRight\":t=mr(t,n-o)}}return{start:t,end:n}}(0,i,this.__views__),o=u.start,a=u.end,f=a-o,c=e?a:o-1,l=this.__iteratees__,s=l.length,h=0,p=wr(f,this.__takeCount__);if(!r||!e&&i==f&&p==f)return gi(t,this.__actions__);var v=[];t:for(;f--&&h<p;){for(var g=-1,d=t[c+=n];++g<s;){var _=l[g],y=_.iteratee,m=_.type,w=y(d);if(2==m)d=w;else if(!w){if(1==m)continue t;break t}}v[h++]=d}return v},Mr.prototype.at=vo,Mr.prototype.chain=function(){return ho(this)},Mr.prototype.commit=function(){return new qr(this.value(),this.__chain__)},Mr.prototype.next=function(){this.__values__===i&&(this.__values__=pa(this.value()));var t=this.__index__>=this.__values__.length;return{done:t,value:t?i:this.__values__[this.__index__++]}},Mr.prototype.plant=function(t){for(var n,r=this;r instanceof Nr;){var e=$u(r);e.__index__=0,e.__values__=i,n?u.__wrapped__=e:n=e;var u=e;r=r.__wrapped__}return u.__wrapped__=t,n},Mr.prototype.reverse=function(){var t=this.__wrapped__;if(t instanceof Hr){var n=t;return this.__actions__.length&&(n=new Hr(this)),(n=n.reverse()).__actions__.push({func:po,args:[to],thisArg:i}),new qr(n,this.__chain__)}return this.thru(to)},Mr.prototype.toJSON=Mr.prototype.valueOf=Mr.prototype.value=function(){return gi(this.__wrapped__,this.__actions__)},Mr.prototype.first=Mr.prototype.head,Xt&&(Mr.prototype[Xt]=function(){return this}),Mr}();dn._=yr,(e=function(){return yr}.call(n,r,n,t))===i||(t.exports=e)}.call(this)},224(t,n,r){\"use strict\";r.d(n,{bn:()=>e,ni:()=>i});r(543);function e(t,n=1){if(Math.abs(t)<1e3)return t+\" B\";const r=[\"kB\",\"MB\",\"GB\",\"TB\",\"PB\",\"EB\",\"ZB\",\"YB\"];let e=-1;const i=10**n;do{t/=1e3,++e}while(Math.round(Math.abs(t)*i)/i>=1e3&&e<r.length-1);return t.toFixed(n)+\" \"+r[e]}function i(t,n,r){let e=\"unknown location\";void 0!==t.location&&(e=`File ${t.location[1]}, line ${t.location[2]} in ${t.location[0]}`);const i=t.n_allocations>1?\"s\":\"\";let u=`${e}<br>${n} total<br>${`${t.n_allocations} allocation${i}`}`;return!1===r&&(u=u.concat(`<br>Thread ID: ${t.thread_id}`)),u}}},n={};function r(e){var i=n[e];if(void 0!==i)return i.exports;var u=n[e]={id:e,loaded:!1,exports:{}};return t[e].call(u.exports,u,u.exports,r),u.loaded=!0,u.exports}r.n=t=>{var n=t&&t.__esModule?()=>t.default:()=>t;return r.d(n,{a:n}),n},r.d=(t,n)=>{for(var e in n)r.o(n,e)&&!r.o(t,e)&&Object.defineProperty(t,e,{enumerable:!0,get:n[e]})},r.g=function(){if(\"object\"==typeof globalThis)return globalThis;try{return this||new Function(\"return this\")()}catch(t){if(\"object\"==typeof window)return window}}(),r.o=(t,n)=>Object.prototype.hasOwnProperty.call(t,n),r.nmd=t=>(t.paths=[],t.children||(t.children=[]),t),(()=>{\"use strict\";var t=r(224);const n=Math.min,e=Math.max,i=Math.round,u=Math.floor,o=t=>({x:t,y:t}),a={left:\"right\",right:\"left\",bottom:\"top\",top:\"bottom\"},f={start:\"end\",end:\"start\"};function c(t,r,i){return e(t,n(r,i))}function l(t,n){return\"function\"==typeof t?t(n):t}function s(t){return t.split(\"-\")[0]}function h(t){return t.split(\"-\")[1]}function p(t){return\"x\"===t?\"y\":\"x\"}function v(t){return\"y\"===t?\"height\":\"width\"}const g=new Set([\"top\",\"bottom\"]);function d(t){return g.has(s(t))?\"y\":\"x\"}function y(t){return p(d(t))}function m(t){return t.replace(/start|end/g,t=>f[t])}const w=[\"left\",\"right\"],b=[\"right\",\"left\"],x=[\"top\",\"bottom\"],A=[\"bottom\",\"top\"];function R(t,n,r,e){const i=h(t);let u=function(t,n,r){switch(t){case\"top\":case\"bottom\":return r?n?b:w:n?w:b;case\"left\":case\"right\":return n?x:A;default:return[]}}(s(t),\"start\"===r,e);return i&&(u=u.map(t=>t+\"-\"+i),n&&(u=u.concat(u.map(m)))),u}function j(t){return t.replace(/left|right|bottom|top/g,t=>a[t])}function E(t){const{x:n,y:r,width:e,height:i}=t;return{width:e,height:i,top:r,left:n,right:n+e,bottom:r+i,x:n,y:r}}function O(t,n,r){let{reference:e,floating:i}=t;const u=d(n),o=y(n),a=v(o),f=s(n),c=\"y\"===u,l=e.x+e.width/2-i.width/2,p=e.y+e.height/2-i.height/2,g=e[a]/2-i[a]/2;let _;switch(f){case\"top\":_={x:l,y:e.y-i.height};break;case\"bottom\":_={x:l,y:e.y+e.height};break;case\"right\":_={x:e.x+e.width,y:p};break;case\"left\":_={x:e.x-i.width,y:p};break;default:_={x:e.x,y:e.y}}switch(h(n)){case\"start\":_[o]-=g*(r&&c?-1:1);break;case\"end\":_[o]+=g*(r&&c?-1:1)}return _}async function S(t,n){var r;void 0===n&&(n={});const{x:e,y:i,platform:u,rects:o,elements:a,strategy:f}=t,{boundary:c=\"clippingAncestors\",rootBoundary:s=\"viewport\",elementContext:h=\"floating\",altBoundary:p=!1,padding:v=0}=l(n,t),g=function(t){return\"number\"!=typeof t?function(t){return{top:0,right:0,bottom:0,left:0,...t}}(t):{top:t,right:t,bottom:t,left:t}}(v),d=a[p?\"floating\"===h?\"reference\":\"floating\":h],_=E(await u.getClippingRect({element:null==(r=await(null==u.isElement?void 0:u.isElement(d)))||r?d:d.contextElement||await(null==u.getDocumentElement?void 0:u.getDocumentElement(a.floating)),boundary:c,rootBoundary:s,strategy:f})),y=\"floating\"===h?{x:e,y:i,width:o.floating.width,height:o.floating.height}:o.reference,m=await(null==u.getOffsetParent?void 0:u.getOffsetParent(a.floating)),w=await(null==u.isElement?void 0:u.isElement(m))&&await(null==u.getScale?void 0:u.getScale(m))||{x:1,y:1},b=E(u.convertOffsetParentRelativeRectToViewportRelativeRect?await u.convertOffsetParentRelativeRectToViewportRelativeRect({elements:a,rect:y,offsetParent:m,strategy:f}):y);return{top:(_.top-b.top+g.top)/w.y,bottom:(b.bottom-_.bottom+g.bottom)/w.y,left:(_.left-b.left+g.left)/w.x,right:(b.right-_.right+g.right)/w.x}}const k=new Set([\"left\",\"top\"]);function L(){return\"undefined\"!=typeof window}function T(t){return z(t)?(t.nodeName||\"\").toLowerCase():\"#document\"}function I(t){var n;return(null==t||null==(n=t.ownerDocument)?void 0:n.defaultView)||window}function C(t){var n;return null==(n=(z(t)?t.ownerDocument:t.document)||window.document)?void 0:n.documentElement}function z(t){return!!L()&&(t instanceof Node||t instanceof I(t).Node)}function B(t){return!!L()&&(t instanceof Element||t instanceof I(t).Element)}function W(t){return!!L()&&(t instanceof HTMLElement||t instanceof I(t).HTMLElement)}function D(t){return!(!L()||\"undefined\"==typeof ShadowRoot)&&(t instanceof ShadowRoot||t instanceof I(t).ShadowRoot)}const F=new Set([\"inline\",\"contents\"]);function $(t){const{overflow:n,overflowX:r,overflowY:e,display:i}=J(t);return/auto|scroll|overlay|hidden|clip/.test(n+e+r)&&!F.has(i)}const P=new Set([\"table\",\"td\",\"th\"]);function M(t){return P.has(T(t))}const U=[\":popover-open\",\":modal\"];function N(t){return U.some(n=>{try{return t.matches(n)}catch(t){return!1}})}const q=[\"transform\",\"translate\",\"scale\",\"rotate\",\"perspective\"],H=[\"transform\",\"translate\",\"scale\",\"rotate\",\"perspective\",\"filter\"],V=[\"paint\",\"layout\",\"strict\",\"content\"];function Z(t){const n=K(),r=B(t)?J(t):t;return q.some(t=>!!r[t]&&\"none\"!==r[t])||!!r.containerType&&\"normal\"!==r.containerType||!n&&!!r.backdropFilter&&\"none\"!==r.backdropFilter||!n&&!!r.filter&&\"none\"!==r.filter||H.some(t=>(r.willChange||\"\").includes(t))||V.some(t=>(r.contain||\"\").includes(t))}function K(){return!(\"undefined\"==typeof CSS||!CSS.supports)&&CSS.supports(\"-webkit-backdrop-filter\",\"none\")}const G=new Set([\"html\",\"body\",\"#document\"]);function Y(t){return G.has(T(t))}function J(t){return I(t).getComputedStyle(t)}function X(t){return B(t)?{scrollLeft:t.scrollLeft,scrollTop:t.scrollTop}:{scrollLeft:t.scrollX,scrollTop:t.scrollY}}function Q(t){if(\"html\"===T(t))return t;const n=t.assignedSlot||t.parentNode||D(t)&&t.host||C(t);return D(n)?n.host:n}function tt(t){const n=Q(t);return Y(n)?t.ownerDocument?t.ownerDocument.body:t.body:W(n)&&$(n)?n:tt(n)}function nt(t,n,r){var e;void 0===n&&(n=[]),void 0===r&&(r=!0);const i=tt(t),u=i===(null==(e=t.ownerDocument)?void 0:e.body),o=I(i);if(u){const t=rt(o);return n.concat(o,o.visualViewport||[],$(i)?i:[],t&&r?nt(t):[])}return n.concat(i,nt(i,[],r))}function rt(t){return t.parent&&Object.getPrototypeOf(t.parent)?t.frameElement:null}function et(t){const n=J(t);let r=parseFloat(n.width)||0,e=parseFloat(n.height)||0;const u=W(t),o=u?t.offsetWidth:r,a=u?t.offsetHeight:e,f=i(r)!==o||i(e)!==a;return f&&(r=o,e=a),{width:r,height:e,$:f}}function it(t){return B(t)?t:t.contextElement}function ut(t){const n=it(t);if(!W(n))return o(1);const r=n.getBoundingClientRect(),{width:e,height:u,$:a}=et(n);let f=(a?i(r.width):r.width)/e,c=(a?i(r.height):r.height)/u;return f&&Number.isFinite(f)||(f=1),c&&Number.isFinite(c)||(c=1),{x:f,y:c}}const ot=o(0);function at(t){const n=I(t);return K()&&n.visualViewport?{x:n.visualViewport.offsetLeft,y:n.visualViewport.offsetTop}:ot}function ft(t,n,r,e){void 0===n&&(n=!1),void 0===r&&(r=!1);const i=t.getBoundingClientRect(),u=it(t);let a=o(1);n&&(e?B(e)&&(a=ut(e)):a=ut(t));const f=function(t,n,r){return void 0===n&&(n=!1),!(!r||n&&r!==I(t))&&n}(u,r,e)?at(u):o(0);let c=(i.left+f.x)/a.x,l=(i.top+f.y)/a.y,s=i.width/a.x,h=i.height/a.y;if(u){const t=I(u),n=e&&B(e)?I(e):e;let r=t,i=rt(r);for(;i&&e&&n!==r;){const t=ut(i),n=i.getBoundingClientRect(),e=J(i),u=n.left+(i.clientLeft+parseFloat(e.paddingLeft))*t.x,o=n.top+(i.clientTop+parseFloat(e.paddingTop))*t.y;c*=t.x,l*=t.y,s*=t.x,h*=t.y,c+=u,l+=o,r=I(i),i=rt(r)}}return E({width:s,height:h,x:c,y:l})}function ct(t,n){const r=X(t).scrollLeft;return n?n.left+r:ft(C(t)).left+r}function lt(t,n){const r=t.getBoundingClientRect();return{x:r.left+n.scrollLeft-ct(t,r),y:r.top+n.scrollTop}}const st=new Set([\"absolute\",\"fixed\"]);function ht(t,n,r){let i;if(\"viewport\"===n)i=function(t,n){const r=I(t),e=C(t),i=r.visualViewport;let u=e.clientWidth,o=e.clientHeight,a=0,f=0;if(i){u=i.width,o=i.height;const t=K();(!t||t&&\"fixed\"===n)&&(a=i.offsetLeft,f=i.offsetTop)}const c=ct(e);if(c<=0){const t=e.ownerDocument,n=t.body,r=getComputedStyle(n),i=\"CSS1Compat\"===t.compatMode&&parseFloat(r.marginLeft)+parseFloat(r.marginRight)||0,o=Math.abs(e.clientWidth-n.clientWidth-i);o<=25&&(u-=o)}else c<=25&&(u+=c);return{width:u,height:o,x:a,y:f}}(t,r);else if(\"document\"===n)i=function(t){const n=C(t),r=X(t),i=t.ownerDocument.body,u=e(n.scrollWidth,n.clientWidth,i.scrollWidth,i.clientWidth),o=e(n.scrollHeight,n.clientHeight,i.scrollHeight,i.clientHeight);let a=-r.scrollLeft+ct(t);const f=-r.scrollTop;return\"rtl\"===J(i).direction&&(a+=e(n.clientWidth,i.clientWidth)-u),{width:u,height:o,x:a,y:f}}(C(t));else if(B(n))i=function(t,n){const r=ft(t,!0,\"fixed\"===n),e=r.top+t.clientTop,i=r.left+t.clientLeft,u=W(t)?ut(t):o(1);return{width:t.clientWidth*u.x,height:t.clientHeight*u.y,x:i*u.x,y:e*u.y}}(n,r);else{const r=at(t);i={x:n.x-r.x,y:n.y-r.y,width:n.width,height:n.height}}return E(i)}function pt(t,n){const r=Q(t);return!(r===n||!B(r)||Y(r))&&(\"fixed\"===J(r).position||pt(r,n))}function vt(t,n,r){const e=W(n),i=C(n),u=\"fixed\"===r,a=ft(t,!0,u,n);let f={scrollLeft:0,scrollTop:0};const c=o(0);function l(){c.x=ct(i)}if(e||!e&&!u)if((\"body\"!==T(n)||$(i))&&(f=X(n)),e){const t=ft(n,!0,u,n);c.x=t.x+n.clientLeft,c.y=t.y+n.clientTop}else i&&l();u&&!e&&i&&l();const s=!i||e||u?o(0):lt(i,f);return{x:a.left+f.scrollLeft-c.x-s.x,y:a.top+f.scrollTop-c.y-s.y,width:a.width,height:a.height}}function gt(t){return\"static\"===J(t).position}function dt(t,n){if(!W(t)||\"fixed\"===J(t).position)return null;if(n)return n(t);let r=t.offsetParent;return C(t)===r&&(r=r.ownerDocument.body),r}function _t(t,n){const r=I(t);if(N(t))return r;if(!W(t)){let n=Q(t);for(;n&&!Y(n);){if(B(n)&&!gt(n))return n;n=Q(n)}return r}let e=dt(t,n);for(;e&&M(e)&&gt(e);)e=dt(e,n);return e&&Y(e)&&gt(e)&&!Z(e)?r:e||function(t){let n=Q(t);for(;W(n)&&!Y(n);){if(Z(n))return n;if(N(n))return null;n=Q(n)}return null}(t)||r}const yt={convertOffsetParentRelativeRectToViewportRelativeRect:function(t){let{elements:n,rect:r,offsetParent:e,strategy:i}=t;const u=\"fixed\"===i,a=C(e),f=!!n&&N(n.floating);if(e===a||f&&u)return r;let c={scrollLeft:0,scrollTop:0},l=o(1);const s=o(0),h=W(e);if((h||!h&&!u)&&((\"body\"!==T(e)||$(a))&&(c=X(e)),W(e))){const t=ft(e);l=ut(e),s.x=t.x+e.clientLeft,s.y=t.y+e.clientTop}const p=!a||h||u?o(0):lt(a,c);return{width:r.width*l.x,height:r.height*l.y,x:r.x*l.x-c.scrollLeft*l.x+s.x+p.x,y:r.y*l.y-c.scrollTop*l.y+s.y+p.y}},getDocumentElement:C,getClippingRect:function(t){let{element:r,boundary:i,rootBoundary:u,strategy:o}=t;const a=[...\"clippingAncestors\"===i?N(r)?[]:function(t,n){const r=n.get(t);if(r)return r;let e=nt(t,[],!1).filter(t=>B(t)&&\"body\"!==T(t)),i=null;const u=\"fixed\"===J(t).position;let o=u?Q(t):t;for(;B(o)&&!Y(o);){const n=J(o),r=Z(o);r||\"fixed\"!==n.position||(i=null),(u?!r&&!i:!r&&\"static\"===n.position&&i&&st.has(i.position)||$(o)&&!r&&pt(t,o))?e=e.filter(t=>t!==o):i=n,o=Q(o)}return n.set(t,e),e}(r,this._c):[].concat(i),u],f=a[0],c=a.reduce((t,i)=>{const u=ht(r,i,o);return t.top=e(u.top,t.top),t.right=n(u.right,t.right),t.bottom=n(u.bottom,t.bottom),t.left=e(u.left,t.left),t},ht(r,f,o));return{width:c.right-c.left,height:c.bottom-c.top,x:c.left,y:c.top}},getOffsetParent:_t,getElementRects:async function(t){const n=this.getOffsetParent||_t,r=this.getDimensions,e=await r(t.floating);return{reference:vt(t.reference,await n(t.floating),t.strategy),floating:{x:0,y:0,width:e.width,height:e.height}}},getClientRects:function(t){return Array.from(t.getClientRects())},getDimensions:function(t){const{width:n,height:r}=et(t);return{width:n,height:r}},getScale:ut,isElement:B,isRTL:function(t){return\"rtl\"===J(t).direction}};function mt(t,n){return t.x===n.x&&t.y===n.y&&t.width===n.width&&t.height===n.height}function wt(t,r,i,o){void 0===o&&(o={});const{ancestorScroll:a=!0,ancestorResize:f=!0,elementResize:c=\"function\"==typeof ResizeObserver,layoutShift:l=\"function\"==typeof IntersectionObserver,animationFrame:s=!1}=o,h=it(t),p=a||f?[...h?nt(h):[],...nt(r)]:[];p.forEach(t=>{a&&t.addEventListener(\"scroll\",i,{passive:!0}),f&&t.addEventListener(\"resize\",i)});const v=h&&l?function(t,r){let i,o=null;const a=C(t);function f(){var t;clearTimeout(i),null==(t=o)||t.disconnect(),o=null}return function c(l,s){void 0===l&&(l=!1),void 0===s&&(s=1),f();const h=t.getBoundingClientRect(),{left:p,top:v,width:g,height:d}=h;if(l||r(),!g||!d)return;const _={rootMargin:-u(v)+\"px \"+-u(a.clientWidth-(p+g))+\"px \"+-u(a.clientHeight-(v+d))+\"px \"+-u(p)+\"px\",threshold:e(0,n(1,s))||1};let y=!0;function m(n){const r=n[0].intersectionRatio;if(r!==s){if(!y)return c();r?c(!1,r):i=setTimeout(()=>{c(!1,1e-7)},1e3)}1!==r||mt(h,t.getBoundingClientRect())||c(),y=!1}try{o=new IntersectionObserver(m,{..._,root:a.ownerDocument})}catch(t){o=new IntersectionObserver(m,_)}o.observe(t)}(!0),f}(h,i):null;let g,d=-1,_=null;c&&(_=new ResizeObserver(t=>{let[n]=t;n&&n.target===h&&_&&(_.unobserve(r),cancelAnimationFrame(d),d=requestAnimationFrame(()=>{var t;null==(t=_)||t.observe(r)})),i()}),h&&!s&&_.observe(h),_.observe(r));let y=s?ft(t):null;return s&&function n(){const r=ft(t);y&&!mt(y,r)&&i();y=r,g=requestAnimationFrame(n)}(),i(),()=>{var t;p.forEach(t=>{a&&t.removeEventListener(\"scroll\",i),f&&t.removeEventListener(\"resize\",i)}),null==v||v(),null==(t=_)||t.disconnect(),_=null,s&&cancelAnimationFrame(g)}}const bt=function(t){return void 0===t&&(t=0),{name:\"offset\",options:t,async fn(n){var r,e;const{x:i,y:u,placement:o,middlewareData:a}=n,f=await async function(t,n){const{placement:r,platform:e,elements:i}=t,u=await(null==e.isRTL?void 0:e.isRTL(i.floating)),o=s(r),a=h(r),f=\"y\"===d(r),c=k.has(o)?-1:1,p=u&&f?-1:1,v=l(n,t);let{mainAxis:g,crossAxis:_,alignmentAxis:y}=\"number\"==typeof v?{mainAxis:v,crossAxis:0,alignmentAxis:null}:{mainAxis:v.mainAxis||0,crossAxis:v.crossAxis||0,alignmentAxis:v.alignmentAxis};return a&&\"number\"==typeof y&&(_=\"end\"===a?-1*y:y),f?{x:_*p,y:g*c}:{x:g*c,y:_*p}}(n,t);return o===(null==(r=a.offset)?void 0:r.placement)&&null!=(e=a.arrow)&&e.alignmentOffset?{}:{x:i+f.x,y:u+f.y,data:{...f,placement:o}}}}},xt=function(t){return void 0===t&&(t={}),{name:\"shift\",options:t,async fn(n){const{x:r,y:e,placement:i,platform:u}=n,{mainAxis:o=!0,crossAxis:a=!1,limiter:f={fn:t=>{let{x:n,y:r}=t;return{x:n,y:r}}},...h}=l(t,n),v={x:r,y:e},g=await u.detectOverflow(n,h),_=d(s(i)),y=p(_);let m=v[y],w=v[_];if(o){const t=\"y\"===y?\"bottom\":\"right\";m=c(m+g[\"y\"===y?\"top\":\"left\"],m,m-g[t])}if(a){const t=\"y\"===_?\"bottom\":\"right\";w=c(w+g[\"y\"===_?\"top\":\"left\"],w,w-g[t])}const b=f.fn({...n,[y]:m,[_]:w});return{...b,data:{x:b.x-r,y:b.y-e,enabled:{[y]:o,[_]:a}}}}}},At=function(t){return void 0===t&&(t={}),{name:\"flip\",options:t,async fn(n){var r,e;const{placement:i,middlewareData:u,rects:o,initialPlacement:a,platform:f,elements:c}=n,{mainAxis:p=!0,crossAxis:g=!0,fallbackPlacements:_,fallbackStrategy:w=\"bestFit\",fallbackAxisSideDirection:b=\"none\",flipAlignment:x=!0,...A}=l(t,n);if(null!=(r=u.arrow)&&r.alignmentOffset)return{};const E=s(i),O=d(a),S=s(a)===a,k=await(null==f.isRTL?void 0:f.isRTL(c.floating)),L=_||(S||!x?[j(a)]:function(t){const n=j(t);return[m(t),n,m(n)]}(a)),T=\"none\"!==b;!_&&T&&L.push(...R(a,x,b,k));const I=[a,...L],C=await f.detectOverflow(n,A),z=[];let B=(null==(e=u.flip)?void 0:e.overflows)||[];if(p&&z.push(C[E]),g){const t=function(t,n,r){void 0===r&&(r=!1);const e=h(t),i=y(t),u=v(i);let o=\"x\"===i?e===(r?\"end\":\"start\")?\"right\":\"left\":\"start\"===e?\"bottom\":\"top\";return n.reference[u]>n.floating[u]&&(o=j(o)),[o,j(o)]}(i,o,k);z.push(C[t[0]],C[t[1]])}if(B=[...B,{placement:i,overflows:z}],!z.every(t=>t<=0)){var W,D;const t=((null==(W=u.flip)?void 0:W.index)||0)+1,n=I[t];if(n){if(!(\"alignment\"===g&&O!==d(n))||B.every(t=>d(t.placement)!==O||t.overflows[0]>0))return{data:{index:t,overflows:B},reset:{placement:n}}}let r=null==(D=B.filter(t=>t.overflows[0]<=0).sort((t,n)=>t.overflows[1]-n.overflows[1])[0])?void 0:D.placement;if(!r)switch(w){case\"bestFit\":{var F;const t=null==(F=B.filter(t=>{if(T){const n=d(t.placement);return n===O||\"y\"===n}return!0}).map(t=>[t.placement,t.overflows.filter(t=>t>0).reduce((t,n)=>t+n,0)]).sort((t,n)=>t[1]-n[1])[0])?void 0:F[0];t&&(r=t);break}case\"initialPlacement\":r=a}if(i!==r)return{reset:{placement:r}}}return{}}}},Rt=(t,n,r)=>{const e=new Map,i={platform:yt,...r},u={...i.platform,_c:e};return(async(t,n,r)=>{const{placement:e=\"bottom\",strategy:i=\"absolute\",middleware:u=[],platform:o}=r,a=u.filter(Boolean),f=await(null==o.isRTL?void 0:o.isRTL(n));let c=await o.getElementRects({reference:t,floating:n,strategy:i}),{x:l,y:s}=O(c,e,f),h=e,p={},v=0;for(let r=0;r<a.length;r++){var g;const{name:u,fn:d}=a[r],{x:_,y,data:m,reset:w}=await d({x:l,y:s,initialPlacement:e,placement:h,strategy:i,middlewareData:p,rects:c,platform:{...o,detectOverflow:null!=(g=o.detectOverflow)?g:S},elements:{reference:t,floating:n}});l=null!=_?_:l,s=null!=y?y:s,p={...p,[u]:{...p[u],...m}},w&&v<=50&&(v++,\"object\"==typeof w&&(w.placement&&(h=w.placement),w.rects&&(c=!0===w.rects?await o.getElementRects({reference:t,floating:n,strategy:i}):w.rects),({x:l,y:s}=O(c,h,f))),r=-1)}return{x:l,y:s,placement:h,strategy:i,middlewareData:p}})(t,n,{...i,platform:u})};var jt=null,Et=null;new class{constructor(){this.filters={}}registerFilter(t,n){this.filters[t]=n}unRegisterFilter(t){delete this.filters[t]}drawChart(n){let r=n;_.forOwn(this.filters,t=>{r=t(r)}),function(n){let r=!jt||jt.inverted();jt&&(jt.destroy(),Et&&(Et.destroy(),Et=null),d3.selectAll(\".d3-flame-graph-tip\").remove());Et=function(){const n=document.createElement(\"div\");n.className=\"d3-flame-graph-tip\",n.style.position=\"fixed\",n.style.top=\"0\",n.style.left=\"0\",n.style.visibility=\"hidden\",n.style.pointerEvents=\"none\",document.body.appendChild(n);let r=null,e=null,i=\"top\";const u=()=>{e&&Rt(e,n,{strategy:\"fixed\",placement:i,middleware:[bt(6),At(),xt({padding:8})]}).then(({x:t,y:r})=>{n.style.left=`${t}px`,n.style.top=`${r}px`})},o=function(){return o};return o.show=(o,a)=>{if(!o||!a)return;const f=(0,t.bn)(o.data.value);n.innerHTML=(0,t.ni)(o.data,f,merge_threads),i=function(t){if(\"s\"===t)return\"bottom\";if(\"e\"===t)return\"right\";if(\"w\"===t)return\"left\";return\"top\"}(function(t){const n=(t.x1+t.x0)/2;if(.25<n&&n<.75)return\"s\";if(t.x1<.75)return\"e\";if(t.x0>.25)return\"w\";return\"n\"}(o)),e=a,n.style.visibility=\"visible\",r&&r(),r=wt(e,n,u),u()},o.hide=()=>{e=null,n.style.visibility=\"hidden\",r&&(r(),r=null)},o.destroy=()=>{o.hide(),n.remove()},o}(),jt=flamegraph().width(Lt()).transitionDuration(250).transitionEase(d3.easeCubic).inverted(r).cellHeight(20).minFrameSize(2).setColorMapper(Tt).onClick(kt).tooltip(Et),d3.select(\"#chart\").datum(n).call(jt),jt.width(Lt())}(r),jt.merge([])}};function Ot(){return location.hash?parseInt(location.hash.substring(1),10):0}function St(){document.getElementById(\"resetZoomButton\").disabled=0==Ot()}function kt(t){t.id!=Ot()&&(history.pushState({id:t.id},t.data.name,`#${t.id}`),St())}function Lt(){return document.getElementById(\"chart\").clientWidth}function Tt(t,n){return t.highlight?\"orange\":t.data.name&&t.data.location?(e=t.data.location[1],\"py\"==(r=void 0===e?e:e.substring(e.lastIndexOf(\".\")+1,e.length)||e)?d3.schemePastel1[2]:\"c\"==r||\"cpp\"==r||\"h\"==r?d3.schemePastel1[5]:d3.schemePastel1[8]):\"#EEE\";var r,e}})()})();"
  },
  {
    "path": "src/memray/reporters/templates/assets/table.css",
    "content": ".tooltip-inner {\n  max-width: 300px;\n}\n"
  },
  {
    "path": "src/memray/reporters/templates/assets/table.js",
    "content": "(()=>{var n={543(n,t,r){var e;\n/**\n * @license\n * Lodash <https://lodash.com/>\n * Copyright OpenJS Foundation and other contributors <https://openjsf.org/>\n * Released under MIT license <https://lodash.com/license>\n * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>\n * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n */n=r.nmd(n),function(){var u,i=\"Expected a function\",o=\"__lodash_hash_undefined__\",a=\"__lodash_placeholder__\",f=16,c=32,l=64,s=128,h=256,p=1/0,v=9007199254740991,_=NaN,g=4294967295,y=[[\"ary\",s],[\"bind\",1],[\"bindKey\",2],[\"curry\",8],[\"curryRight\",f],[\"flip\",512],[\"partial\",c],[\"partialRight\",l],[\"rearg\",h]],d=\"[object Arguments]\",m=\"[object Array]\",b=\"[object Boolean]\",w=\"[object Date]\",x=\"[object Error]\",j=\"[object Function]\",A=\"[object GeneratorFunction]\",k=\"[object Map]\",z=\"[object Number]\",O=\"[object Object]\",I=\"[object Promise]\",R=\"[object RegExp]\",E=\"[object Set]\",B=\"[object String]\",S=\"[object Symbol]\",L=\"[object WeakMap]\",C=\"[object ArrayBuffer]\",T=\"[object DataView]\",W=\"[object Float32Array]\",U=\"[object Float64Array]\",$=\"[object Int8Array]\",M=\"[object Int16Array]\",D=\"[object Int32Array]\",P=\"[object Uint8Array]\",F=\"[object Uint8ClampedArray]\",N=\"[object Uint16Array]\",q=\"[object Uint32Array]\",G=/\\b__p \\+= '';/g,Z=/\\b(__p \\+=) '' \\+/g,K=/(__e\\(.*?\\)|\\b__t\\)) \\+\\n'';/g,V=/&(?:amp|lt|gt|quot|#39);/g,H=/[&<>\"']/g,Y=RegExp(V.source),J=RegExp(H.source),Q=/<%-([\\s\\S]+?)%>/g,X=/<%([\\s\\S]+?)%>/g,nn=/<%=([\\s\\S]+?)%>/g,tn=/\\.|\\[(?:[^[\\]]*|([\"'])(?:(?!\\1)[^\\\\]|\\\\.)*?\\1)\\]/,rn=/^\\w*$/,en=/[^.[\\]]+|\\[(?:(-?\\d+(?:\\.\\d+)?)|([\"'])((?:(?!\\2)[^\\\\]|\\\\.)*?)\\2)\\]|(?=(?:\\.|\\[\\])(?:\\.|\\[\\]|$))/g,un=/[\\\\^$.*+?()[\\]{}|]/g,on=RegExp(un.source),an=/^\\s+/,fn=/\\s/,cn=/\\{(?:\\n\\/\\* \\[wrapped with .+\\] \\*\\/)?\\n?/,ln=/\\{\\n\\/\\* \\[wrapped with (.+)\\] \\*/,sn=/,? & /,hn=/[^\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\x7f]+/g,pn=/[()=,{}\\[\\]\\/\\s]/,vn=/\\\\(\\\\)?/g,_n=/\\$\\{([^\\\\}]*(?:\\\\.[^\\\\}]*)*)\\}/g,gn=/\\w*$/,yn=/^[-+]0x[0-9a-f]+$/i,dn=/^0b[01]+$/i,mn=/^\\[object .+?Constructor\\]$/,bn=/^0o[0-7]+$/i,wn=/^(?:0|[1-9]\\d*)$/,xn=/[\\xc0-\\xd6\\xd8-\\xf6\\xf8-\\xff\\u0100-\\u017f]/g,jn=/($^)/,An=/['\\n\\r\\u2028\\u2029\\\\]/g,kn=\"\\\\ud800-\\\\udfff\",zn=\"\\\\u0300-\\\\u036f\\\\ufe20-\\\\ufe2f\\\\u20d0-\\\\u20ff\",On=\"\\\\u2700-\\\\u27bf\",In=\"a-z\\\\xdf-\\\\xf6\\\\xf8-\\\\xff\",Rn=\"A-Z\\\\xc0-\\\\xd6\\\\xd8-\\\\xde\",En=\"\\\\ufe0e\\\\ufe0f\",Bn=\"\\\\xac\\\\xb1\\\\xd7\\\\xf7\\\\x00-\\\\x2f\\\\x3a-\\\\x40\\\\x5b-\\\\x60\\\\x7b-\\\\xbf\\\\u2000-\\\\u206f \\\\t\\\\x0b\\\\f\\\\xa0\\\\ufeff\\\\n\\\\r\\\\u2028\\\\u2029\\\\u1680\\\\u180e\\\\u2000\\\\u2001\\\\u2002\\\\u2003\\\\u2004\\\\u2005\\\\u2006\\\\u2007\\\\u2008\\\\u2009\\\\u200a\\\\u202f\\\\u205f\\\\u3000\",Sn=\"['’]\",Ln=\"[\"+kn+\"]\",Cn=\"[\"+Bn+\"]\",Tn=\"[\"+zn+\"]\",Wn=\"\\\\d+\",Un=\"[\"+On+\"]\",$n=\"[\"+In+\"]\",Mn=\"[^\"+kn+Bn+Wn+On+In+Rn+\"]\",Dn=\"\\\\ud83c[\\\\udffb-\\\\udfff]\",Pn=\"[^\"+kn+\"]\",Fn=\"(?:\\\\ud83c[\\\\udde6-\\\\uddff]){2}\",Nn=\"[\\\\ud800-\\\\udbff][\\\\udc00-\\\\udfff]\",qn=\"[\"+Rn+\"]\",Gn=\"\\\\u200d\",Zn=\"(?:\"+$n+\"|\"+Mn+\")\",Kn=\"(?:\"+qn+\"|\"+Mn+\")\",Vn=\"(?:['’](?:d|ll|m|re|s|t|ve))?\",Hn=\"(?:['’](?:D|LL|M|RE|S|T|VE))?\",Yn=\"(?:\"+Tn+\"|\"+Dn+\")\"+\"?\",Jn=\"[\"+En+\"]?\",Qn=Jn+Yn+(\"(?:\"+Gn+\"(?:\"+[Pn,Fn,Nn].join(\"|\")+\")\"+Jn+Yn+\")*\"),Xn=\"(?:\"+[Un,Fn,Nn].join(\"|\")+\")\"+Qn,nt=\"(?:\"+[Pn+Tn+\"?\",Tn,Fn,Nn,Ln].join(\"|\")+\")\",tt=RegExp(Sn,\"g\"),rt=RegExp(Tn,\"g\"),et=RegExp(Dn+\"(?=\"+Dn+\")|\"+nt+Qn,\"g\"),ut=RegExp([qn+\"?\"+$n+\"+\"+Vn+\"(?=\"+[Cn,qn,\"$\"].join(\"|\")+\")\",Kn+\"+\"+Hn+\"(?=\"+[Cn,qn+Zn,\"$\"].join(\"|\")+\")\",qn+\"?\"+Zn+\"+\"+Vn,qn+\"+\"+Hn,\"\\\\d*(?:1ST|2ND|3RD|(?![123])\\\\dTH)(?=\\\\b|[a-z_])\",\"\\\\d*(?:1st|2nd|3rd|(?![123])\\\\dth)(?=\\\\b|[A-Z_])\",Wn,Xn].join(\"|\"),\"g\"),it=RegExp(\"[\"+Gn+kn+zn+En+\"]\"),ot=/[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/,at=[\"Array\",\"Buffer\",\"DataView\",\"Date\",\"Error\",\"Float32Array\",\"Float64Array\",\"Function\",\"Int8Array\",\"Int16Array\",\"Int32Array\",\"Map\",\"Math\",\"Object\",\"Promise\",\"RegExp\",\"Set\",\"String\",\"Symbol\",\"TypeError\",\"Uint8Array\",\"Uint8ClampedArray\",\"Uint16Array\",\"Uint32Array\",\"WeakMap\",\"_\",\"clearTimeout\",\"isFinite\",\"parseInt\",\"setTimeout\"],ft=-1,ct={};ct[W]=ct[U]=ct[$]=ct[M]=ct[D]=ct[P]=ct[F]=ct[N]=ct[q]=!0,ct[d]=ct[m]=ct[C]=ct[b]=ct[T]=ct[w]=ct[x]=ct[j]=ct[k]=ct[z]=ct[O]=ct[R]=ct[E]=ct[B]=ct[L]=!1;var lt={};lt[d]=lt[m]=lt[C]=lt[T]=lt[b]=lt[w]=lt[W]=lt[U]=lt[$]=lt[M]=lt[D]=lt[k]=lt[z]=lt[O]=lt[R]=lt[E]=lt[B]=lt[S]=lt[P]=lt[F]=lt[N]=lt[q]=!0,lt[x]=lt[j]=lt[L]=!1;var st={\"\\\\\":\"\\\\\",\"'\":\"'\",\"\\n\":\"n\",\"\\r\":\"r\",\"\\u2028\":\"u2028\",\"\\u2029\":\"u2029\"},ht=parseFloat,pt=parseInt,vt=\"object\"==typeof r.g&&r.g&&r.g.Object===Object&&r.g,_t=\"object\"==typeof self&&self&&self.Object===Object&&self,gt=vt||_t||Function(\"return this\")(),yt=t&&!t.nodeType&&t,dt=yt&&n&&!n.nodeType&&n,mt=dt&&dt.exports===yt,bt=mt&&vt.process,wt=function(){try{var n=dt&&dt.require&&dt.require(\"util\").types;return n||bt&&bt.binding&&bt.binding(\"util\")}catch(n){}}(),xt=wt&&wt.isArrayBuffer,jt=wt&&wt.isDate,At=wt&&wt.isMap,kt=wt&&wt.isRegExp,zt=wt&&wt.isSet,Ot=wt&&wt.isTypedArray;function It(n,t,r){switch(r.length){case 0:return n.call(t);case 1:return n.call(t,r[0]);case 2:return n.call(t,r[0],r[1]);case 3:return n.call(t,r[0],r[1],r[2])}return n.apply(t,r)}function Rt(n,t,r,e){for(var u=-1,i=null==n?0:n.length;++u<i;){var o=n[u];t(e,o,r(o),n)}return e}function Et(n,t){for(var r=-1,e=null==n?0:n.length;++r<e&&!1!==t(n[r],r,n););return n}function Bt(n,t){for(var r=null==n?0:n.length;r--&&!1!==t(n[r],r,n););return n}function St(n,t){for(var r=-1,e=null==n?0:n.length;++r<e;)if(!t(n[r],r,n))return!1;return!0}function Lt(n,t){for(var r=-1,e=null==n?0:n.length,u=0,i=[];++r<e;){var o=n[r];t(o,r,n)&&(i[u++]=o)}return i}function Ct(n,t){return!!(null==n?0:n.length)&&qt(n,t,0)>-1}function Tt(n,t,r){for(var e=-1,u=null==n?0:n.length;++e<u;)if(r(t,n[e]))return!0;return!1}function Wt(n,t){for(var r=-1,e=null==n?0:n.length,u=Array(e);++r<e;)u[r]=t(n[r],r,n);return u}function Ut(n,t){for(var r=-1,e=t.length,u=n.length;++r<e;)n[u+r]=t[r];return n}function $t(n,t,r,e){var u=-1,i=null==n?0:n.length;for(e&&i&&(r=n[++u]);++u<i;)r=t(r,n[u],u,n);return r}function Mt(n,t,r,e){var u=null==n?0:n.length;for(e&&u&&(r=n[--u]);u--;)r=t(r,n[u],u,n);return r}function Dt(n,t){for(var r=-1,e=null==n?0:n.length;++r<e;)if(t(n[r],r,n))return!0;return!1}var Pt=Vt(\"length\");function Ft(n,t,r){var e;return r(n,function(n,r,u){if(t(n,r,u))return e=r,!1}),e}function Nt(n,t,r,e){for(var u=n.length,i=r+(e?1:-1);e?i--:++i<u;)if(t(n[i],i,n))return i;return-1}function qt(n,t,r){return t==t?function(n,t,r){var e=r-1,u=n.length;for(;++e<u;)if(n[e]===t)return e;return-1}(n,t,r):Nt(n,Zt,r)}function Gt(n,t,r,e){for(var u=r-1,i=n.length;++u<i;)if(e(n[u],t))return u;return-1}function Zt(n){return n!=n}function Kt(n,t){var r=null==n?0:n.length;return r?Jt(n,t)/r:_}function Vt(n){return function(t){return null==t?u:t[n]}}function Ht(n){return function(t){return null==n?u:n[t]}}function Yt(n,t,r,e,u){return u(n,function(n,u,i){r=e?(e=!1,n):t(r,n,u,i)}),r}function Jt(n,t){for(var r,e=-1,i=n.length;++e<i;){var o=t(n[e]);o!==u&&(r=r===u?o:r+o)}return r}function Qt(n,t){for(var r=-1,e=Array(n);++r<n;)e[r]=t(r);return e}function Xt(n){return n?n.slice(0,gr(n)+1).replace(an,\"\"):n}function nr(n){return function(t){return n(t)}}function tr(n,t){return Wt(t,function(t){return n[t]})}function rr(n,t){return n.has(t)}function er(n,t){for(var r=-1,e=n.length;++r<e&&qt(t,n[r],0)>-1;);return r}function ur(n,t){for(var r=n.length;r--&&qt(t,n[r],0)>-1;);return r}var ir=Ht({À:\"A\",Á:\"A\",Â:\"A\",Ã:\"A\",Ä:\"A\",Å:\"A\",à:\"a\",á:\"a\",â:\"a\",ã:\"a\",ä:\"a\",å:\"a\",Ç:\"C\",ç:\"c\",Ð:\"D\",ð:\"d\",È:\"E\",É:\"E\",Ê:\"E\",Ë:\"E\",è:\"e\",é:\"e\",ê:\"e\",ë:\"e\",Ì:\"I\",Í:\"I\",Î:\"I\",Ï:\"I\",ì:\"i\",í:\"i\",î:\"i\",ï:\"i\",Ñ:\"N\",ñ:\"n\",Ò:\"O\",Ó:\"O\",Ô:\"O\",Õ:\"O\",Ö:\"O\",Ø:\"O\",ò:\"o\",ó:\"o\",ô:\"o\",õ:\"o\",ö:\"o\",ø:\"o\",Ù:\"U\",Ú:\"U\",Û:\"U\",Ü:\"U\",ù:\"u\",ú:\"u\",û:\"u\",ü:\"u\",Ý:\"Y\",ý:\"y\",ÿ:\"y\",Æ:\"Ae\",æ:\"ae\",Þ:\"Th\",þ:\"th\",ß:\"ss\",Ā:\"A\",Ă:\"A\",Ą:\"A\",ā:\"a\",ă:\"a\",ą:\"a\",Ć:\"C\",Ĉ:\"C\",Ċ:\"C\",Č:\"C\",ć:\"c\",ĉ:\"c\",ċ:\"c\",č:\"c\",Ď:\"D\",Đ:\"D\",ď:\"d\",đ:\"d\",Ē:\"E\",Ĕ:\"E\",Ė:\"E\",Ę:\"E\",Ě:\"E\",ē:\"e\",ĕ:\"e\",ė:\"e\",ę:\"e\",ě:\"e\",Ĝ:\"G\",Ğ:\"G\",Ġ:\"G\",Ģ:\"G\",ĝ:\"g\",ğ:\"g\",ġ:\"g\",ģ:\"g\",Ĥ:\"H\",Ħ:\"H\",ĥ:\"h\",ħ:\"h\",Ĩ:\"I\",Ī:\"I\",Ĭ:\"I\",Į:\"I\",İ:\"I\",ĩ:\"i\",ī:\"i\",ĭ:\"i\",į:\"i\",ı:\"i\",Ĵ:\"J\",ĵ:\"j\",Ķ:\"K\",ķ:\"k\",ĸ:\"k\",Ĺ:\"L\",Ļ:\"L\",Ľ:\"L\",Ŀ:\"L\",Ł:\"L\",ĺ:\"l\",ļ:\"l\",ľ:\"l\",ŀ:\"l\",ł:\"l\",Ń:\"N\",Ņ:\"N\",Ň:\"N\",Ŋ:\"N\",ń:\"n\",ņ:\"n\",ň:\"n\",ŋ:\"n\",Ō:\"O\",Ŏ:\"O\",Ő:\"O\",ō:\"o\",ŏ:\"o\",ő:\"o\",Ŕ:\"R\",Ŗ:\"R\",Ř:\"R\",ŕ:\"r\",ŗ:\"r\",ř:\"r\",Ś:\"S\",Ŝ:\"S\",Ş:\"S\",Š:\"S\",ś:\"s\",ŝ:\"s\",ş:\"s\",š:\"s\",Ţ:\"T\",Ť:\"T\",Ŧ:\"T\",ţ:\"t\",ť:\"t\",ŧ:\"t\",Ũ:\"U\",Ū:\"U\",Ŭ:\"U\",Ů:\"U\",Ű:\"U\",Ų:\"U\",ũ:\"u\",ū:\"u\",ŭ:\"u\",ů:\"u\",ű:\"u\",ų:\"u\",Ŵ:\"W\",ŵ:\"w\",Ŷ:\"Y\",ŷ:\"y\",Ÿ:\"Y\",Ź:\"Z\",Ż:\"Z\",Ž:\"Z\",ź:\"z\",ż:\"z\",ž:\"z\",Ĳ:\"IJ\",ĳ:\"ij\",Œ:\"Oe\",œ:\"oe\",ŉ:\"'n\",ſ:\"s\"}),or=Ht({\"&\":\"&amp;\",\"<\":\"&lt;\",\">\":\"&gt;\",'\"':\"&quot;\",\"'\":\"&#39;\"});function ar(n){return\"\\\\\"+st[n]}function fr(n){return it.test(n)}function cr(n){var t=-1,r=Array(n.size);return n.forEach(function(n,e){r[++t]=[e,n]}),r}function lr(n,t){return function(r){return n(t(r))}}function sr(n,t){for(var r=-1,e=n.length,u=0,i=[];++r<e;){var o=n[r];o!==t&&o!==a||(n[r]=a,i[u++]=r)}return i}function hr(n){var t=-1,r=Array(n.size);return n.forEach(function(n){r[++t]=n}),r}function pr(n){var t=-1,r=Array(n.size);return n.forEach(function(n){r[++t]=[n,n]}),r}function vr(n){return fr(n)?function(n){var t=et.lastIndex=0;for(;et.test(n);)++t;return t}(n):Pt(n)}function _r(n){return fr(n)?function(n){return n.match(et)||[]}(n):function(n){return n.split(\"\")}(n)}function gr(n){for(var t=n.length;t--&&fn.test(n.charAt(t)););return t}var yr=Ht({\"&amp;\":\"&\",\"&lt;\":\"<\",\"&gt;\":\">\",\"&quot;\":'\"',\"&#39;\":\"'\"});var dr=function n(t){var r,e=(t=null==t?gt:dr.defaults(gt.Object(),t,dr.pick(gt,at))).Array,fn=t.Date,kn=t.Error,zn=t.Function,On=t.Math,In=t.Object,Rn=t.RegExp,En=t.String,Bn=t.TypeError,Sn=e.prototype,Ln=zn.prototype,Cn=In.prototype,Tn=t[\"__core-js_shared__\"],Wn=Ln.toString,Un=Cn.hasOwnProperty,$n=0,Mn=(r=/[^.]+$/.exec(Tn&&Tn.keys&&Tn.keys.IE_PROTO||\"\"))?\"Symbol(src)_1.\"+r:\"\",Dn=Cn.toString,Pn=Wn.call(In),Fn=gt._,Nn=Rn(\"^\"+Wn.call(Un).replace(un,\"\\\\$&\").replace(/hasOwnProperty|(function).*?(?=\\\\\\()| for .+?(?=\\\\\\])/g,\"$1.*?\")+\"$\"),qn=mt?t.Buffer:u,Gn=t.Symbol,Zn=t.Uint8Array,Kn=qn?qn.allocUnsafe:u,Vn=lr(In.getPrototypeOf,In),Hn=In.create,Yn=Cn.propertyIsEnumerable,Jn=Sn.splice,Qn=Gn?Gn.isConcatSpreadable:u,Xn=Gn?Gn.iterator:u,nt=Gn?Gn.toStringTag:u,et=function(){try{var n=hi(In,\"defineProperty\");return n({},\"\",{}),n}catch(n){}}(),it=t.clearTimeout!==gt.clearTimeout&&t.clearTimeout,st=fn&&fn.now!==gt.Date.now&&fn.now,vt=t.setTimeout!==gt.setTimeout&&t.setTimeout,_t=On.ceil,yt=On.floor,dt=In.getOwnPropertySymbols,bt=qn?qn.isBuffer:u,wt=t.isFinite,Pt=Sn.join,Ht=lr(In.keys,In),mr=On.max,br=On.min,wr=fn.now,xr=t.parseInt,jr=On.random,Ar=Sn.reverse,kr=hi(t,\"DataView\"),zr=hi(t,\"Map\"),Or=hi(t,\"Promise\"),Ir=hi(t,\"Set\"),Rr=hi(t,\"WeakMap\"),Er=hi(In,\"create\"),Br=Rr&&new Rr,Sr={},Lr=$i(kr),Cr=$i(zr),Tr=$i(Or),Wr=$i(Ir),Ur=$i(Rr),$r=Gn?Gn.prototype:u,Mr=$r?$r.valueOf:u,Dr=$r?$r.toString:u;function Pr(n){if(ra(n)&&!Go(n)&&!(n instanceof Gr)){if(n instanceof qr)return n;if(Un.call(n,\"__wrapped__\"))return Mi(n)}return new qr(n)}var Fr=function(){function n(){}return function(t){if(!ta(t))return{};if(Hn)return Hn(t);n.prototype=t;var r=new n;return n.prototype=u,r}}();function Nr(){}function qr(n,t){this.__wrapped__=n,this.__actions__=[],this.__chain__=!!t,this.__index__=0,this.__values__=u}function Gr(n){this.__wrapped__=n,this.__actions__=[],this.__dir__=1,this.__filtered__=!1,this.__iteratees__=[],this.__takeCount__=g,this.__views__=[]}function Zr(n){var t=-1,r=null==n?0:n.length;for(this.clear();++t<r;){var e=n[t];this.set(e[0],e[1])}}function Kr(n){var t=-1,r=null==n?0:n.length;for(this.clear();++t<r;){var e=n[t];this.set(e[0],e[1])}}function Vr(n){var t=-1,r=null==n?0:n.length;for(this.clear();++t<r;){var e=n[t];this.set(e[0],e[1])}}function Hr(n){var t=-1,r=null==n?0:n.length;for(this.__data__=new Vr;++t<r;)this.add(n[t])}function Yr(n){var t=this.__data__=new Kr(n);this.size=t.size}function Jr(n,t){var r=Go(n),e=!r&&qo(n),u=!r&&!e&&Ho(n),i=!r&&!e&&!u&&la(n),o=r||e||u||i,a=o?Qt(n.length,En):[],f=a.length;for(var c in n)!t&&!Un.call(n,c)||o&&(\"length\"==c||u&&(\"offset\"==c||\"parent\"==c)||i&&(\"buffer\"==c||\"byteLength\"==c||\"byteOffset\"==c)||mi(c,f))||a.push(c);return a}function Qr(n){var t=n.length;return t?n[He(0,t-1)]:u}function Xr(n,t){return Ti(Eu(n),fe(t,0,n.length))}function ne(n){return Ti(Eu(n))}function te(n,t,r){(r!==u&&!Po(n[t],r)||r===u&&!(t in n))&&oe(n,t,r)}function re(n,t,r){var e=n[t];Un.call(n,t)&&Po(e,r)&&(r!==u||t in n)||oe(n,t,r)}function ee(n,t){for(var r=n.length;r--;)if(Po(n[r][0],t))return r;return-1}function ue(n,t,r,e){return pe(n,function(n,u,i){t(e,n,r(n),i)}),e}function ie(n,t){return n&&Bu(t,Sa(t),n)}function oe(n,t,r){\"__proto__\"==t&&et?et(n,t,{configurable:!0,enumerable:!0,value:r,writable:!0}):n[t]=r}function ae(n,t){for(var r=-1,i=t.length,o=e(i),a=null==n;++r<i;)o[r]=a?u:Oa(n,t[r]);return o}function fe(n,t,r){return n==n&&(r!==u&&(n=n<=r?n:r),t!==u&&(n=n>=t?n:t)),n}function ce(n,t,r,e,i,o){var a,f=1&t,c=2&t,l=4&t;if(r&&(a=i?r(n,e,i,o):r(n)),a!==u)return a;if(!ta(n))return n;var s=Go(n);if(s){if(a=function(n){var t=n.length,r=new n.constructor(t);t&&\"string\"==typeof n[0]&&Un.call(n,\"index\")&&(r.index=n.index,r.input=n.input);return r}(n),!f)return Eu(n,a)}else{var h=_i(n),p=h==j||h==A;if(Ho(n))return Au(n,f);if(h==O||h==d||p&&!i){if(a=c||p?{}:yi(n),!f)return c?function(n,t){return Bu(n,vi(n),t)}(n,function(n,t){return n&&Bu(t,La(t),n)}(a,n)):function(n,t){return Bu(n,pi(n),t)}(n,ie(a,n))}else{if(!lt[h])return i?n:{};a=function(n,t,r){var e=n.constructor;switch(t){case C:return ku(n);case b:case w:return new e(+n);case T:return function(n,t){var r=t?ku(n.buffer):n.buffer;return new n.constructor(r,n.byteOffset,n.byteLength)}(n,r);case W:case U:case $:case M:case D:case P:case F:case N:case q:return zu(n,r);case k:return new e;case z:case B:return new e(n);case R:return function(n){var t=new n.constructor(n.source,gn.exec(n));return t.lastIndex=n.lastIndex,t}(n);case E:return new e;case S:return u=n,Mr?In(Mr.call(u)):{}}var u}(n,h,f)}}o||(o=new Yr);var v=o.get(n);if(v)return v;o.set(n,a),aa(n)?n.forEach(function(e){a.add(ce(e,t,r,e,n,o))}):ea(n)&&n.forEach(function(e,u){a.set(u,ce(e,t,r,u,n,o))});var _=s?u:(l?c?ii:ui:c?La:Sa)(n);return Et(_||n,function(e,u){_&&(e=n[u=e]),re(a,u,ce(e,t,r,u,n,o))}),a}function le(n,t,r){var e=r.length;if(null==n)return!e;for(n=In(n);e--;){var i=r[e],o=t[i],a=n[i];if(a===u&&!(i in n)||!o(a))return!1}return!0}function se(n,t,r){if(\"function\"!=typeof n)throw new Bn(i);return Bi(function(){n.apply(u,r)},t)}function he(n,t,r,e){var u=-1,i=Ct,o=!0,a=n.length,f=[],c=t.length;if(!a)return f;r&&(t=Wt(t,nr(r))),e?(i=Tt,o=!1):t.length>=200&&(i=rr,o=!1,t=new Hr(t));n:for(;++u<a;){var l=n[u],s=null==r?l:r(l);if(l=e||0!==l?l:0,o&&s==s){for(var h=c;h--;)if(t[h]===s)continue n;f.push(l)}else i(t,s,e)||f.push(l)}return f}Pr.templateSettings={escape:Q,evaluate:X,interpolate:nn,variable:\"\",imports:{_:Pr}},Pr.prototype=Nr.prototype,Pr.prototype.constructor=Pr,qr.prototype=Fr(Nr.prototype),qr.prototype.constructor=qr,Gr.prototype=Fr(Nr.prototype),Gr.prototype.constructor=Gr,Zr.prototype.clear=function(){this.__data__=Er?Er(null):{},this.size=0},Zr.prototype.delete=function(n){var t=this.has(n)&&delete this.__data__[n];return this.size-=t?1:0,t},Zr.prototype.get=function(n){var t=this.__data__;if(Er){var r=t[n];return r===o?u:r}return Un.call(t,n)?t[n]:u},Zr.prototype.has=function(n){var t=this.__data__;return Er?t[n]!==u:Un.call(t,n)},Zr.prototype.set=function(n,t){var r=this.__data__;return this.size+=this.has(n)?0:1,r[n]=Er&&t===u?o:t,this},Kr.prototype.clear=function(){this.__data__=[],this.size=0},Kr.prototype.delete=function(n){var t=this.__data__,r=ee(t,n);return!(r<0)&&(r==t.length-1?t.pop():Jn.call(t,r,1),--this.size,!0)},Kr.prototype.get=function(n){var t=this.__data__,r=ee(t,n);return r<0?u:t[r][1]},Kr.prototype.has=function(n){return ee(this.__data__,n)>-1},Kr.prototype.set=function(n,t){var r=this.__data__,e=ee(r,n);return e<0?(++this.size,r.push([n,t])):r[e][1]=t,this},Vr.prototype.clear=function(){this.size=0,this.__data__={hash:new Zr,map:new(zr||Kr),string:new Zr}},Vr.prototype.delete=function(n){var t=li(this,n).delete(n);return this.size-=t?1:0,t},Vr.prototype.get=function(n){return li(this,n).get(n)},Vr.prototype.has=function(n){return li(this,n).has(n)},Vr.prototype.set=function(n,t){var r=li(this,n),e=r.size;return r.set(n,t),this.size+=r.size==e?0:1,this},Hr.prototype.add=Hr.prototype.push=function(n){return this.__data__.set(n,o),this},Hr.prototype.has=function(n){return this.__data__.has(n)},Yr.prototype.clear=function(){this.__data__=new Kr,this.size=0},Yr.prototype.delete=function(n){var t=this.__data__,r=t.delete(n);return this.size=t.size,r},Yr.prototype.get=function(n){return this.__data__.get(n)},Yr.prototype.has=function(n){return this.__data__.has(n)},Yr.prototype.set=function(n,t){var r=this.__data__;if(r instanceof Kr){var e=r.__data__;if(!zr||e.length<199)return e.push([n,t]),this.size=++r.size,this;r=this.__data__=new Vr(e)}return r.set(n,t),this.size=r.size,this};var pe=Cu(we),ve=Cu(xe,!0);function _e(n,t){var r=!0;return pe(n,function(n,e,u){return r=!!t(n,e,u)}),r}function ge(n,t,r){for(var e=-1,i=n.length;++e<i;){var o=n[e],a=t(o);if(null!=a&&(f===u?a==a&&!ca(a):r(a,f)))var f=a,c=o}return c}function ye(n,t){var r=[];return pe(n,function(n,e,u){t(n,e,u)&&r.push(n)}),r}function de(n,t,r,e,u){var i=-1,o=n.length;for(r||(r=di),u||(u=[]);++i<o;){var a=n[i];t>0&&r(a)?t>1?de(a,t-1,r,e,u):Ut(u,a):e||(u[u.length]=a)}return u}var me=Tu(),be=Tu(!0);function we(n,t){return n&&me(n,t,Sa)}function xe(n,t){return n&&be(n,t,Sa)}function je(n,t){return Lt(t,function(t){return Qo(n[t])})}function Ae(n,t){for(var r=0,e=(t=bu(t,n)).length;null!=n&&r<e;)n=n[Ui(t[r++])];return r&&r==e?n:u}function ke(n,t,r){var e=t(n);return Go(n)?e:Ut(e,r(n))}function ze(n){return null==n?n===u?\"[object Undefined]\":\"[object Null]\":nt&&nt in In(n)?function(n){var t=Un.call(n,nt),r=n[nt];try{n[nt]=u;var e=!0}catch(n){}var i=Dn.call(n);e&&(t?n[nt]=r:delete n[nt]);return i}(n):function(n){return Dn.call(n)}(n)}function Oe(n,t){return n>t}function Ie(n,t){return null!=n&&Un.call(n,t)}function Re(n,t){return null!=n&&t in In(n)}function Ee(n,t,r){for(var i=r?Tt:Ct,o=n[0].length,a=n.length,f=a,c=e(a),l=1/0,s=[];f--;){var h=n[f];f&&t&&(h=Wt(h,nr(t))),l=br(h.length,l),c[f]=!r&&(t||o>=120&&h.length>=120)?new Hr(f&&h):u}h=n[0];var p=-1,v=c[0];n:for(;++p<o&&s.length<l;){var _=h[p],g=t?t(_):_;if(_=r||0!==_?_:0,!(v?rr(v,g):i(s,g,r))){for(f=a;--f;){var y=c[f];if(!(y?rr(y,g):i(n[f],g,r)))continue n}v&&v.push(g),s.push(_)}}return s}function Be(n,t,r){var e=null==(n=Ii(n,t=bu(t,n)))?n:n[Ui(Yi(t))];return null==e?u:It(e,n,r)}function Se(n){return ra(n)&&ze(n)==d}function Le(n,t,r,e,i){return n===t||(null==n||null==t||!ra(n)&&!ra(t)?n!=n&&t!=t:function(n,t,r,e,i,o){var a=Go(n),f=Go(t),c=a?m:_i(n),l=f?m:_i(t),s=(c=c==d?O:c)==O,h=(l=l==d?O:l)==O,p=c==l;if(p&&Ho(n)){if(!Ho(t))return!1;a=!0,s=!1}if(p&&!s)return o||(o=new Yr),a||la(n)?ri(n,t,r,e,i,o):function(n,t,r,e,u,i,o){switch(r){case T:if(n.byteLength!=t.byteLength||n.byteOffset!=t.byteOffset)return!1;n=n.buffer,t=t.buffer;case C:return!(n.byteLength!=t.byteLength||!i(new Zn(n),new Zn(t)));case b:case w:case z:return Po(+n,+t);case x:return n.name==t.name&&n.message==t.message;case R:case B:return n==t+\"\";case k:var a=cr;case E:var f=1&e;if(a||(a=hr),n.size!=t.size&&!f)return!1;var c=o.get(n);if(c)return c==t;e|=2,o.set(n,t);var l=ri(a(n),a(t),e,u,i,o);return o.delete(n),l;case S:if(Mr)return Mr.call(n)==Mr.call(t)}return!1}(n,t,c,r,e,i,o);if(!(1&r)){var v=s&&Un.call(n,\"__wrapped__\"),_=h&&Un.call(t,\"__wrapped__\");if(v||_){var g=v?n.value():n,y=_?t.value():t;return o||(o=new Yr),i(g,y,r,e,o)}}if(!p)return!1;return o||(o=new Yr),function(n,t,r,e,i,o){var a=1&r,f=ui(n),c=f.length,l=ui(t),s=l.length;if(c!=s&&!a)return!1;var h=c;for(;h--;){var p=f[h];if(!(a?p in t:Un.call(t,p)))return!1}var v=o.get(n),_=o.get(t);if(v&&_)return v==t&&_==n;var g=!0;o.set(n,t),o.set(t,n);var y=a;for(;++h<c;){var d=n[p=f[h]],m=t[p];if(e)var b=a?e(m,d,p,t,n,o):e(d,m,p,n,t,o);if(!(b===u?d===m||i(d,m,r,e,o):b)){g=!1;break}y||(y=\"constructor\"==p)}if(g&&!y){var w=n.constructor,x=t.constructor;w==x||!(\"constructor\"in n)||!(\"constructor\"in t)||\"function\"==typeof w&&w instanceof w&&\"function\"==typeof x&&x instanceof x||(g=!1)}return o.delete(n),o.delete(t),g}(n,t,r,e,i,o)}(n,t,r,e,Le,i))}function Ce(n,t,r,e){var i=r.length,o=i,a=!e;if(null==n)return!o;for(n=In(n);i--;){var f=r[i];if(a&&f[2]?f[1]!==n[f[0]]:!(f[0]in n))return!1}for(;++i<o;){var c=(f=r[i])[0],l=n[c],s=f[1];if(a&&f[2]){if(l===u&&!(c in n))return!1}else{var h=new Yr;if(e)var p=e(l,s,c,n,t,h);if(!(p===u?Le(s,l,3,e,h):p))return!1}}return!0}function Te(n){return!(!ta(n)||(t=n,Mn&&Mn in t))&&(Qo(n)?Nn:mn).test($i(n));var t}function We(n){return\"function\"==typeof n?n:null==n?uf:\"object\"==typeof n?Go(n)?Fe(n[0],n[1]):Pe(n):vf(n)}function Ue(n){if(!Ai(n))return Ht(n);var t=[];for(var r in In(n))Un.call(n,r)&&\"constructor\"!=r&&t.push(r);return t}function $e(n){if(!ta(n))return function(n){var t=[];if(null!=n)for(var r in In(n))t.push(r);return t}(n);var t=Ai(n),r=[];for(var e in n)(\"constructor\"!=e||!t&&Un.call(n,e))&&r.push(e);return r}function Me(n,t){return n<t}function De(n,t){var r=-1,u=Ko(n)?e(n.length):[];return pe(n,function(n,e,i){u[++r]=t(n,e,i)}),u}function Pe(n){var t=si(n);return 1==t.length&&t[0][2]?zi(t[0][0],t[0][1]):function(r){return r===n||Ce(r,n,t)}}function Fe(n,t){return wi(n)&&ki(t)?zi(Ui(n),t):function(r){var e=Oa(r,n);return e===u&&e===t?Ia(r,n):Le(t,e,3)}}function Ne(n,t,r,e,i){n!==t&&me(t,function(o,a){if(i||(i=new Yr),ta(o))!function(n,t,r,e,i,o,a){var f=Ri(n,r),c=Ri(t,r),l=a.get(c);if(l)return void te(n,r,l);var s=o?o(f,c,r+\"\",n,t,a):u,h=s===u;if(h){var p=Go(c),v=!p&&Ho(c),_=!p&&!v&&la(c);s=c,p||v||_?Go(f)?s=f:Vo(f)?s=Eu(f):v?(h=!1,s=Au(c,!0)):_?(h=!1,s=zu(c,!0)):s=[]:ia(c)||qo(c)?(s=f,qo(f)?s=da(f):ta(f)&&!Qo(f)||(s=yi(c))):h=!1}h&&(a.set(c,s),i(s,c,e,o,a),a.delete(c));te(n,r,s)}(n,t,a,r,Ne,e,i);else{var f=e?e(Ri(n,a),o,a+\"\",n,t,i):u;f===u&&(f=o),te(n,a,f)}},La)}function qe(n,t){var r=n.length;if(r)return mi(t+=t<0?r:0,r)?n[t]:u}function Ge(n,t,r){t=t.length?Wt(t,function(n){return Go(n)?function(t){return Ae(t,1===n.length?n[0]:n)}:n}):[uf];var e=-1;t=Wt(t,nr(ci()));var u=De(n,function(n,r,u){var i=Wt(t,function(t){return t(n)});return{criteria:i,index:++e,value:n}});return function(n,t){var r=n.length;for(n.sort(t);r--;)n[r]=n[r].value;return n}(u,function(n,t){return function(n,t,r){var e=-1,u=n.criteria,i=t.criteria,o=u.length,a=r.length;for(;++e<o;){var f=Ou(u[e],i[e]);if(f)return e>=a?f:f*(\"desc\"==r[e]?-1:1)}return n.index-t.index}(n,t,r)})}function Ze(n,t,r){for(var e=-1,u=t.length,i={};++e<u;){var o=t[e],a=Ae(n,o);r(a,o)&&nu(i,bu(o,n),a)}return i}function Ke(n,t,r,e){var u=e?Gt:qt,i=-1,o=t.length,a=n;for(n===t&&(t=Eu(t)),r&&(a=Wt(n,nr(r)));++i<o;)for(var f=0,c=t[i],l=r?r(c):c;(f=u(a,l,f,e))>-1;)a!==n&&Jn.call(a,f,1),Jn.call(n,f,1);return n}function Ve(n,t){for(var r=n?t.length:0,e=r-1;r--;){var u=t[r];if(r==e||u!==i){var i=u;mi(u)?Jn.call(n,u,1):hu(n,u)}}return n}function He(n,t){return n+yt(jr()*(t-n+1))}function Ye(n,t){var r=\"\";if(!n||t<1||t>v)return r;do{t%2&&(r+=n),(t=yt(t/2))&&(n+=n)}while(t);return r}function Je(n,t){return Si(Oi(n,t,uf),n+\"\")}function Qe(n){return Qr(Pa(n))}function Xe(n,t){var r=Pa(n);return Ti(r,fe(t,0,r.length))}function nu(n,t,r,e){if(!ta(n))return n;for(var i=-1,o=(t=bu(t,n)).length,a=o-1,f=n;null!=f&&++i<o;){var c=Ui(t[i]),l=r;if(\"__proto__\"===c||\"constructor\"===c||\"prototype\"===c)return n;if(i!=a){var s=f[c];(l=e?e(s,c,f):u)===u&&(l=ta(s)?s:mi(t[i+1])?[]:{})}re(f,c,l),f=f[c]}return n}var tu=Br?function(n,t){return Br.set(n,t),n}:uf,ru=et?function(n,t){return et(n,\"toString\",{configurable:!0,enumerable:!1,value:tf(t),writable:!0})}:uf;function eu(n){return Ti(Pa(n))}function uu(n,t,r){var u=-1,i=n.length;t<0&&(t=-t>i?0:i+t),(r=r>i?i:r)<0&&(r+=i),i=t>r?0:r-t>>>0,t>>>=0;for(var o=e(i);++u<i;)o[u]=n[u+t];return o}function iu(n,t){var r;return pe(n,function(n,e,u){return!(r=t(n,e,u))}),!!r}function ou(n,t,r){var e=0,u=null==n?e:n.length;if(\"number\"==typeof t&&t==t&&u<=2147483647){for(;e<u;){var i=e+u>>>1,o=n[i];null!==o&&!ca(o)&&(r?o<=t:o<t)?e=i+1:u=i}return u}return au(n,t,uf,r)}function au(n,t,r,e){var i=0,o=null==n?0:n.length;if(0===o)return 0;for(var a=(t=r(t))!=t,f=null===t,c=ca(t),l=t===u;i<o;){var s=yt((i+o)/2),h=r(n[s]),p=h!==u,v=null===h,_=h==h,g=ca(h);if(a)var y=e||_;else y=l?_&&(e||p):f?_&&p&&(e||!v):c?_&&p&&!v&&(e||!g):!v&&!g&&(e?h<=t:h<t);y?i=s+1:o=s}return br(o,4294967294)}function fu(n,t){for(var r=-1,e=n.length,u=0,i=[];++r<e;){var o=n[r],a=t?t(o):o;if(!r||!Po(a,f)){var f=a;i[u++]=0===o?0:o}}return i}function cu(n){return\"number\"==typeof n?n:ca(n)?_:+n}function lu(n){if(\"string\"==typeof n)return n;if(Go(n))return Wt(n,lu)+\"\";if(ca(n))return Dr?Dr.call(n):\"\";var t=n+\"\";return\"0\"==t&&1/n==-1/0?\"-0\":t}function su(n,t,r){var e=-1,u=Ct,i=n.length,o=!0,a=[],f=a;if(r)o=!1,u=Tt;else if(i>=200){var c=t?null:Yu(n);if(c)return hr(c);o=!1,u=rr,f=new Hr}else f=t?[]:a;n:for(;++e<i;){var l=n[e],s=t?t(l):l;if(l=r||0!==l?l:0,o&&s==s){for(var h=f.length;h--;)if(f[h]===s)continue n;t&&f.push(s),a.push(l)}else u(f,s,r)||(f!==a&&f.push(s),a.push(l))}return a}function hu(n,t){var r=-1,e=(t=bu(t,n)).length;if(!e)return!0;for(var u=null==n||\"object\"!=typeof n&&\"function\"!=typeof n;++r<e;){var i=t[r];if(\"string\"==typeof i){if(\"__proto__\"===i&&!Un.call(n,\"__proto__\"))return!1;if(\"constructor\"===i&&r+1<e&&\"string\"==typeof t[r+1]&&\"prototype\"===t[r+1]){if(u&&0===r)continue;return!1}}}var o=Ii(n,t);return null==o||delete o[Ui(Yi(t))]}function pu(n,t,r,e){return nu(n,t,r(Ae(n,t)),e)}function vu(n,t,r,e){for(var u=n.length,i=e?u:-1;(e?i--:++i<u)&&t(n[i],i,n););return r?uu(n,e?0:i,e?i+1:u):uu(n,e?i+1:0,e?u:i)}function _u(n,t){var r=n;return r instanceof Gr&&(r=r.value()),$t(t,function(n,t){return t.func.apply(t.thisArg,Ut([n],t.args))},r)}function gu(n,t,r){var u=n.length;if(u<2)return u?su(n[0]):[];for(var i=-1,o=e(u);++i<u;)for(var a=n[i],f=-1;++f<u;)f!=i&&(o[i]=he(o[i]||a,n[f],t,r));return su(de(o,1),t,r)}function yu(n,t,r){for(var e=-1,i=n.length,o=t.length,a={};++e<i;){var f=e<o?t[e]:u;r(a,n[e],f)}return a}function du(n){return Vo(n)?n:[]}function mu(n){return\"function\"==typeof n?n:uf}function bu(n,t){return Go(n)?n:wi(n,t)?[n]:Wi(ma(n))}var wu=Je;function xu(n,t,r){var e=n.length;return r=r===u?e:r,!t&&r>=e?n:uu(n,t,r)}var ju=it||function(n){return gt.clearTimeout(n)};function Au(n,t){if(t)return n.slice();var r=n.length,e=Kn?Kn(r):new n.constructor(r);return n.copy(e),e}function ku(n){var t=new n.constructor(n.byteLength);return new Zn(t).set(new Zn(n)),t}function zu(n,t){var r=t?ku(n.buffer):n.buffer;return new n.constructor(r,n.byteOffset,n.length)}function Ou(n,t){if(n!==t){var r=n!==u,e=null===n,i=n==n,o=ca(n),a=t!==u,f=null===t,c=t==t,l=ca(t);if(!f&&!l&&!o&&n>t||o&&a&&c&&!f&&!l||e&&a&&c||!r&&c||!i)return 1;if(!e&&!o&&!l&&n<t||l&&r&&i&&!e&&!o||f&&r&&i||!a&&i||!c)return-1}return 0}function Iu(n,t,r,u){for(var i=-1,o=n.length,a=r.length,f=-1,c=t.length,l=mr(o-a,0),s=e(c+l),h=!u;++f<c;)s[f]=t[f];for(;++i<a;)(h||i<o)&&(s[r[i]]=n[i]);for(;l--;)s[f++]=n[i++];return s}function Ru(n,t,r,u){for(var i=-1,o=n.length,a=-1,f=r.length,c=-1,l=t.length,s=mr(o-f,0),h=e(s+l),p=!u;++i<s;)h[i]=n[i];for(var v=i;++c<l;)h[v+c]=t[c];for(;++a<f;)(p||i<o)&&(h[v+r[a]]=n[i++]);return h}function Eu(n,t){var r=-1,u=n.length;for(t||(t=e(u));++r<u;)t[r]=n[r];return t}function Bu(n,t,r,e){var i=!r;r||(r={});for(var o=-1,a=t.length;++o<a;){var f=t[o],c=e?e(r[f],n[f],f,r,n):u;c===u&&(c=n[f]),i?oe(r,f,c):re(r,f,c)}return r}function Su(n,t){return function(r,e){var u=Go(r)?Rt:ue,i=t?t():{};return u(r,n,ci(e,2),i)}}function Lu(n){return Je(function(t,r){var e=-1,i=r.length,o=i>1?r[i-1]:u,a=i>2?r[2]:u;for(o=n.length>3&&\"function\"==typeof o?(i--,o):u,a&&bi(r[0],r[1],a)&&(o=i<3?u:o,i=1),t=In(t);++e<i;){var f=r[e];f&&n(t,f,e,o)}return t})}function Cu(n,t){return function(r,e){if(null==r)return r;if(!Ko(r))return n(r,e);for(var u=r.length,i=t?u:-1,o=In(r);(t?i--:++i<u)&&!1!==e(o[i],i,o););return r}}function Tu(n){return function(t,r,e){for(var u=-1,i=In(t),o=e(t),a=o.length;a--;){var f=o[n?a:++u];if(!1===r(i[f],f,i))break}return t}}function Wu(n){return function(t){var r=fr(t=ma(t))?_r(t):u,e=r?r[0]:t.charAt(0),i=r?xu(r,1).join(\"\"):t.slice(1);return e[n]()+i}}function Uu(n){return function(t){return $t(Qa(qa(t).replace(tt,\"\")),n,\"\")}}function $u(n){return function(){var t=arguments;switch(t.length){case 0:return new n;case 1:return new n(t[0]);case 2:return new n(t[0],t[1]);case 3:return new n(t[0],t[1],t[2]);case 4:return new n(t[0],t[1],t[2],t[3]);case 5:return new n(t[0],t[1],t[2],t[3],t[4]);case 6:return new n(t[0],t[1],t[2],t[3],t[4],t[5]);case 7:return new n(t[0],t[1],t[2],t[3],t[4],t[5],t[6])}var r=Fr(n.prototype),e=n.apply(r,t);return ta(e)?e:r}}function Mu(n){return function(t,r,e){var i=In(t);if(!Ko(t)){var o=ci(r,3);t=Sa(t),r=function(n){return o(i[n],n,i)}}var a=n(t,r,e);return a>-1?i[o?t[a]:a]:u}}function Du(n){return ei(function(t){var r=t.length,e=r,o=qr.prototype.thru;for(n&&t.reverse();e--;){var a=t[e];if(\"function\"!=typeof a)throw new Bn(i);if(o&&!f&&\"wrapper\"==ai(a))var f=new qr([],!0)}for(e=f?e:r;++e<r;){var c=ai(a=t[e]),l=\"wrapper\"==c?oi(a):u;f=l&&xi(l[0])&&424==l[1]&&!l[4].length&&1==l[9]?f[ai(l[0])].apply(f,l[3]):1==a.length&&xi(a)?f[c]():f.thru(a)}return function(){var n=arguments,e=n[0];if(f&&1==n.length&&Go(e))return f.plant(e).value();for(var u=0,i=r?t[u].apply(this,n):e;++u<r;)i=t[u].call(this,i);return i}})}function Pu(n,t,r,i,o,a,f,c,l,h){var p=t&s,v=1&t,_=2&t,g=24&t,y=512&t,d=_?u:$u(n);return function s(){for(var m=arguments.length,b=e(m),w=m;w--;)b[w]=arguments[w];if(g)var x=fi(s),j=function(n,t){for(var r=n.length,e=0;r--;)n[r]===t&&++e;return e}(b,x);if(i&&(b=Iu(b,i,o,g)),a&&(b=Ru(b,a,f,g)),m-=j,g&&m<h){var A=sr(b,x);return Vu(n,t,Pu,s.placeholder,r,b,A,c,l,h-m)}var k=v?r:this,z=_?k[n]:n;return m=b.length,c?b=function(n,t){var r=n.length,e=br(t.length,r),i=Eu(n);for(;e--;){var o=t[e];n[e]=mi(o,r)?i[o]:u}return n}(b,c):y&&m>1&&b.reverse(),p&&l<m&&(b.length=l),this&&this!==gt&&this instanceof s&&(z=d||$u(z)),z.apply(k,b)}}function Fu(n,t){return function(r,e){return function(n,t,r,e){return we(n,function(n,u,i){t(e,r(n),u,i)}),e}(r,n,t(e),{})}}function Nu(n,t){return function(r,e){var i;if(r===u&&e===u)return t;if(r!==u&&(i=r),e!==u){if(i===u)return e;\"string\"==typeof r||\"string\"==typeof e?(r=lu(r),e=lu(e)):(r=cu(r),e=cu(e)),i=n(r,e)}return i}}function qu(n){return ei(function(t){return t=Wt(t,nr(ci())),Je(function(r){var e=this;return n(t,function(n){return It(n,e,r)})})})}function Gu(n,t){var r=(t=t===u?\" \":lu(t)).length;if(r<2)return r?Ye(t,n):t;var e=Ye(t,_t(n/vr(t)));return fr(t)?xu(_r(e),0,n).join(\"\"):e.slice(0,n)}function Zu(n){return function(t,r,i){return i&&\"number\"!=typeof i&&bi(t,r,i)&&(r=i=u),t=va(t),r===u?(r=t,t=0):r=va(r),function(n,t,r,u){for(var i=-1,o=mr(_t((t-n)/(r||1)),0),a=e(o);o--;)a[u?o:++i]=n,n+=r;return a}(t,r,i=i===u?t<r?1:-1:va(i),n)}}function Ku(n){return function(t,r){return\"string\"==typeof t&&\"string\"==typeof r||(t=ya(t),r=ya(r)),n(t,r)}}function Vu(n,t,r,e,i,o,a,f,s,h){var p=8&t;t|=p?c:l,4&(t&=~(p?l:c))||(t&=-4);var v=[n,t,i,p?o:u,p?a:u,p?u:o,p?u:a,f,s,h],_=r.apply(u,v);return xi(n)&&Ei(_,v),_.placeholder=e,Li(_,n,t)}function Hu(n){var t=On[n];return function(n,r){if(n=ya(n),(r=null==r?0:br(_a(r),292))&&wt(n)){var e=(ma(n)+\"e\").split(\"e\");return+((e=(ma(t(e[0]+\"e\"+(+e[1]+r)))+\"e\").split(\"e\"))[0]+\"e\"+(+e[1]-r))}return t(n)}}var Yu=Ir&&1/hr(new Ir([,-0]))[1]==p?function(n){return new Ir(n)}:lf;function Ju(n){return function(t){var r=_i(t);return r==k?cr(t):r==E?pr(t):function(n,t){return Wt(t,function(t){return[t,n[t]]})}(t,n(t))}}function Qu(n,t,r,o,p,v,_,g){var y=2&t;if(!y&&\"function\"!=typeof n)throw new Bn(i);var d=o?o.length:0;if(d||(t&=-97,o=p=u),_=_===u?_:mr(_a(_),0),g=g===u?g:_a(g),d-=p?p.length:0,t&l){var m=o,b=p;o=p=u}var w=y?u:oi(n),x=[n,t,r,o,p,m,b,v,_,g];if(w&&function(n,t){var r=n[1],e=t[1],u=r|e,i=u<131,o=e==s&&8==r||e==s&&r==h&&n[7].length<=t[8]||384==e&&t[7].length<=t[8]&&8==r;if(!i&&!o)return n;1&e&&(n[2]=t[2],u|=1&r?0:4);var f=t[3];if(f){var c=n[3];n[3]=c?Iu(c,f,t[4]):f,n[4]=c?sr(n[3],a):t[4]}(f=t[5])&&(c=n[5],n[5]=c?Ru(c,f,t[6]):f,n[6]=c?sr(n[5],a):t[6]);(f=t[7])&&(n[7]=f);e&s&&(n[8]=null==n[8]?t[8]:br(n[8],t[8]));null==n[9]&&(n[9]=t[9]);n[0]=t[0],n[1]=u}(x,w),n=x[0],t=x[1],r=x[2],o=x[3],p=x[4],!(g=x[9]=x[9]===u?y?0:n.length:mr(x[9]-d,0))&&24&t&&(t&=-25),t&&1!=t)j=8==t||t==f?function(n,t,r){var i=$u(n);return function o(){for(var a=arguments.length,f=e(a),c=a,l=fi(o);c--;)f[c]=arguments[c];var s=a<3&&f[0]!==l&&f[a-1]!==l?[]:sr(f,l);return(a-=s.length)<r?Vu(n,t,Pu,o.placeholder,u,f,s,u,u,r-a):It(this&&this!==gt&&this instanceof o?i:n,this,f)}}(n,t,g):t!=c&&33!=t||p.length?Pu.apply(u,x):function(n,t,r,u){var i=1&t,o=$u(n);return function t(){for(var a=-1,f=arguments.length,c=-1,l=u.length,s=e(l+f),h=this&&this!==gt&&this instanceof t?o:n;++c<l;)s[c]=u[c];for(;f--;)s[c++]=arguments[++a];return It(h,i?r:this,s)}}(n,t,r,o);else var j=function(n,t,r){var e=1&t,u=$u(n);return function t(){return(this&&this!==gt&&this instanceof t?u:n).apply(e?r:this,arguments)}}(n,t,r);return Li((w?tu:Ei)(j,x),n,t)}function Xu(n,t,r,e){return n===u||Po(n,Cn[r])&&!Un.call(e,r)?t:n}function ni(n,t,r,e,i,o){return ta(n)&&ta(t)&&(o.set(t,n),Ne(n,t,u,ni,o),o.delete(t)),n}function ti(n){return ia(n)?u:n}function ri(n,t,r,e,i,o){var a=1&r,f=n.length,c=t.length;if(f!=c&&!(a&&c>f))return!1;var l=o.get(n),s=o.get(t);if(l&&s)return l==t&&s==n;var h=-1,p=!0,v=2&r?new Hr:u;for(o.set(n,t),o.set(t,n);++h<f;){var _=n[h],g=t[h];if(e)var y=a?e(g,_,h,t,n,o):e(_,g,h,n,t,o);if(y!==u){if(y)continue;p=!1;break}if(v){if(!Dt(t,function(n,t){if(!rr(v,t)&&(_===n||i(_,n,r,e,o)))return v.push(t)})){p=!1;break}}else if(_!==g&&!i(_,g,r,e,o)){p=!1;break}}return o.delete(n),o.delete(t),p}function ei(n){return Si(Oi(n,u,Gi),n+\"\")}function ui(n){return ke(n,Sa,pi)}function ii(n){return ke(n,La,vi)}var oi=Br?function(n){return Br.get(n)}:lf;function ai(n){for(var t=n.name+\"\",r=Sr[t],e=Un.call(Sr,t)?r.length:0;e--;){var u=r[e],i=u.func;if(null==i||i==n)return u.name}return t}function fi(n){return(Un.call(Pr,\"placeholder\")?Pr:n).placeholder}function ci(){var n=Pr.iteratee||of;return n=n===of?We:n,arguments.length?n(arguments[0],arguments[1]):n}function li(n,t){var r,e,u=n.__data__;return(\"string\"==(e=typeof(r=t))||\"number\"==e||\"symbol\"==e||\"boolean\"==e?\"__proto__\"!==r:null===r)?u[\"string\"==typeof t?\"string\":\"hash\"]:u.map}function si(n){for(var t=Sa(n),r=t.length;r--;){var e=t[r],u=n[e];t[r]=[e,u,ki(u)]}return t}function hi(n,t){var r=function(n,t){return null==n?u:n[t]}(n,t);return Te(r)?r:u}var pi=dt?function(n){return null==n?[]:(n=In(n),Lt(dt(n),function(t){return Yn.call(n,t)}))}:yf,vi=dt?function(n){for(var t=[];n;)Ut(t,pi(n)),n=Vn(n);return t}:yf,_i=ze;function gi(n,t,r){for(var e=-1,u=(t=bu(t,n)).length,i=!1;++e<u;){var o=Ui(t[e]);if(!(i=null!=n&&r(n,o)))break;n=n[o]}return i||++e!=u?i:!!(u=null==n?0:n.length)&&na(u)&&mi(o,u)&&(Go(n)||qo(n))}function yi(n){return\"function\"!=typeof n.constructor||Ai(n)?{}:Fr(Vn(n))}function di(n){return Go(n)||qo(n)||!!(Qn&&n&&n[Qn])}function mi(n,t){var r=typeof n;return!!(t=null==t?v:t)&&(\"number\"==r||\"symbol\"!=r&&wn.test(n))&&n>-1&&n%1==0&&n<t}function bi(n,t,r){if(!ta(r))return!1;var e=typeof t;return!!(\"number\"==e?Ko(r)&&mi(t,r.length):\"string\"==e&&t in r)&&Po(r[t],n)}function wi(n,t){if(Go(n))return!1;var r=typeof n;return!(\"number\"!=r&&\"symbol\"!=r&&\"boolean\"!=r&&null!=n&&!ca(n))||(rn.test(n)||!tn.test(n)||null!=t&&n in In(t))}function xi(n){var t=ai(n),r=Pr[t];if(\"function\"!=typeof r||!(t in Gr.prototype))return!1;if(n===r)return!0;var e=oi(r);return!!e&&n===e[0]}(kr&&_i(new kr(new ArrayBuffer(1)))!=T||zr&&_i(new zr)!=k||Or&&_i(Or.resolve())!=I||Ir&&_i(new Ir)!=E||Rr&&_i(new Rr)!=L)&&(_i=function(n){var t=ze(n),r=t==O?n.constructor:u,e=r?$i(r):\"\";if(e)switch(e){case Lr:return T;case Cr:return k;case Tr:return I;case Wr:return E;case Ur:return L}return t});var ji=Tn?Qo:df;function Ai(n){var t=n&&n.constructor;return n===(\"function\"==typeof t&&t.prototype||Cn)}function ki(n){return n==n&&!ta(n)}function zi(n,t){return function(r){return null!=r&&(r[n]===t&&(t!==u||n in In(r)))}}function Oi(n,t,r){return t=mr(t===u?n.length-1:t,0),function(){for(var u=arguments,i=-1,o=mr(u.length-t,0),a=e(o);++i<o;)a[i]=u[t+i];i=-1;for(var f=e(t+1);++i<t;)f[i]=u[i];return f[t]=r(a),It(n,this,f)}}function Ii(n,t){return t.length<2?n:Ae(n,uu(t,0,-1))}function Ri(n,t){if((\"constructor\"!==t||\"function\"!=typeof n[t])&&\"__proto__\"!=t)return n[t]}var Ei=Ci(tu),Bi=vt||function(n,t){return gt.setTimeout(n,t)},Si=Ci(ru);function Li(n,t,r){var e=t+\"\";return Si(n,function(n,t){var r=t.length;if(!r)return n;var e=r-1;return t[e]=(r>1?\"& \":\"\")+t[e],t=t.join(r>2?\", \":\" \"),n.replace(cn,\"{\\n/* [wrapped with \"+t+\"] */\\n\")}(e,function(n,t){return Et(y,function(r){var e=\"_.\"+r[0];t&r[1]&&!Ct(n,e)&&n.push(e)}),n.sort()}(function(n){var t=n.match(ln);return t?t[1].split(sn):[]}(e),r)))}function Ci(n){var t=0,r=0;return function(){var e=wr(),i=16-(e-r);if(r=e,i>0){if(++t>=800)return arguments[0]}else t=0;return n.apply(u,arguments)}}function Ti(n,t){var r=-1,e=n.length,i=e-1;for(t=t===u?e:t;++r<t;){var o=He(r,i),a=n[o];n[o]=n[r],n[r]=a}return n.length=t,n}var Wi=function(n){var t=To(n,function(n){return 500===r.size&&r.clear(),n}),r=t.cache;return t}(function(n){var t=[];return 46===n.charCodeAt(0)&&t.push(\"\"),n.replace(en,function(n,r,e,u){t.push(e?u.replace(vn,\"$1\"):r||n)}),t});function Ui(n){if(\"string\"==typeof n||ca(n))return n;var t=n+\"\";return\"0\"==t&&1/n==-1/0?\"-0\":t}function $i(n){if(null!=n){try{return Wn.call(n)}catch(n){}try{return n+\"\"}catch(n){}}return\"\"}function Mi(n){if(n instanceof Gr)return n.clone();var t=new qr(n.__wrapped__,n.__chain__);return t.__actions__=Eu(n.__actions__),t.__index__=n.__index__,t.__values__=n.__values__,t}var Di=Je(function(n,t){return Vo(n)?he(n,de(t,1,Vo,!0)):[]}),Pi=Je(function(n,t){var r=Yi(t);return Vo(r)&&(r=u),Vo(n)?he(n,de(t,1,Vo,!0),ci(r,2)):[]}),Fi=Je(function(n,t){var r=Yi(t);return Vo(r)&&(r=u),Vo(n)?he(n,de(t,1,Vo,!0),u,r):[]});function Ni(n,t,r){var e=null==n?0:n.length;if(!e)return-1;var u=null==r?0:_a(r);return u<0&&(u=mr(e+u,0)),Nt(n,ci(t,3),u)}function qi(n,t,r){var e=null==n?0:n.length;if(!e)return-1;var i=e-1;return r!==u&&(i=_a(r),i=r<0?mr(e+i,0):br(i,e-1)),Nt(n,ci(t,3),i,!0)}function Gi(n){return(null==n?0:n.length)?de(n,1):[]}function Zi(n){return n&&n.length?n[0]:u}var Ki=Je(function(n){var t=Wt(n,du);return t.length&&t[0]===n[0]?Ee(t):[]}),Vi=Je(function(n){var t=Yi(n),r=Wt(n,du);return t===Yi(r)?t=u:r.pop(),r.length&&r[0]===n[0]?Ee(r,ci(t,2)):[]}),Hi=Je(function(n){var t=Yi(n),r=Wt(n,du);return(t=\"function\"==typeof t?t:u)&&r.pop(),r.length&&r[0]===n[0]?Ee(r,u,t):[]});function Yi(n){var t=null==n?0:n.length;return t?n[t-1]:u}var Ji=Je(Qi);function Qi(n,t){return n&&n.length&&t&&t.length?Ke(n,t):n}var Xi=ei(function(n,t){var r=null==n?0:n.length,e=ae(n,t);return Ve(n,Wt(t,function(n){return mi(n,r)?+n:n}).sort(Ou)),e});function no(n){return null==n?n:Ar.call(n)}var to=Je(function(n){return su(de(n,1,Vo,!0))}),ro=Je(function(n){var t=Yi(n);return Vo(t)&&(t=u),su(de(n,1,Vo,!0),ci(t,2))}),eo=Je(function(n){var t=Yi(n);return t=\"function\"==typeof t?t:u,su(de(n,1,Vo,!0),u,t)});function uo(n){if(!n||!n.length)return[];var t=0;return n=Lt(n,function(n){if(Vo(n))return t=mr(n.length,t),!0}),Qt(t,function(t){return Wt(n,Vt(t))})}function io(n,t){if(!n||!n.length)return[];var r=uo(n);return null==t?r:Wt(r,function(n){return It(t,u,n)})}var oo=Je(function(n,t){return Vo(n)?he(n,t):[]}),ao=Je(function(n){return gu(Lt(n,Vo))}),fo=Je(function(n){var t=Yi(n);return Vo(t)&&(t=u),gu(Lt(n,Vo),ci(t,2))}),co=Je(function(n){var t=Yi(n);return t=\"function\"==typeof t?t:u,gu(Lt(n,Vo),u,t)}),lo=Je(uo);var so=Je(function(n){var t=n.length,r=t>1?n[t-1]:u;return r=\"function\"==typeof r?(n.pop(),r):u,io(n,r)});function ho(n){var t=Pr(n);return t.__chain__=!0,t}function po(n,t){return t(n)}var vo=ei(function(n){var t=n.length,r=t?n[0]:0,e=this.__wrapped__,i=function(t){return ae(t,n)};return!(t>1||this.__actions__.length)&&e instanceof Gr&&mi(r)?((e=e.slice(r,+r+(t?1:0))).__actions__.push({func:po,args:[i],thisArg:u}),new qr(e,this.__chain__).thru(function(n){return t&&!n.length&&n.push(u),n})):this.thru(i)});var _o=Su(function(n,t,r){Un.call(n,r)?++n[r]:oe(n,r,1)});var go=Mu(Ni),yo=Mu(qi);function mo(n,t){return(Go(n)?Et:pe)(n,ci(t,3))}function bo(n,t){return(Go(n)?Bt:ve)(n,ci(t,3))}var wo=Su(function(n,t,r){Un.call(n,r)?n[r].push(t):oe(n,r,[t])});var xo=Je(function(n,t,r){var u=-1,i=\"function\"==typeof t,o=Ko(n)?e(n.length):[];return pe(n,function(n){o[++u]=i?It(t,n,r):Be(n,t,r)}),o}),jo=Su(function(n,t,r){oe(n,r,t)});function Ao(n,t){return(Go(n)?Wt:De)(n,ci(t,3))}var ko=Su(function(n,t,r){n[r?0:1].push(t)},function(){return[[],[]]});var zo=Je(function(n,t){if(null==n)return[];var r=t.length;return r>1&&bi(n,t[0],t[1])?t=[]:r>2&&bi(t[0],t[1],t[2])&&(t=[t[0]]),Ge(n,de(t,1),[])}),Oo=st||function(){return gt.Date.now()};function Io(n,t,r){return t=r?u:t,t=n&&null==t?n.length:t,Qu(n,s,u,u,u,u,t)}function Ro(n,t){var r;if(\"function\"!=typeof t)throw new Bn(i);return n=_a(n),function(){return--n>0&&(r=t.apply(this,arguments)),n<=1&&(t=u),r}}var Eo=Je(function(n,t,r){var e=1;if(r.length){var u=sr(r,fi(Eo));e|=c}return Qu(n,e,t,r,u)}),Bo=Je(function(n,t,r){var e=3;if(r.length){var u=sr(r,fi(Bo));e|=c}return Qu(t,e,n,r,u)});function So(n,t,r){var e,o,a,f,c,l,s=0,h=!1,p=!1,v=!0;if(\"function\"!=typeof n)throw new Bn(i);function _(t){var r=e,i=o;return e=o=u,s=t,f=n.apply(i,r)}function g(n){var r=n-l;return l===u||r>=t||r<0||p&&n-s>=a}function y(){var n=Oo();if(g(n))return d(n);c=Bi(y,function(n){var r=t-(n-l);return p?br(r,a-(n-s)):r}(n))}function d(n){return c=u,v&&e?_(n):(e=o=u,f)}function m(){var n=Oo(),r=g(n);if(e=arguments,o=this,l=n,r){if(c===u)return function(n){return s=n,c=Bi(y,t),h?_(n):f}(l);if(p)return ju(c),c=Bi(y,t),_(l)}return c===u&&(c=Bi(y,t)),f}return t=ya(t)||0,ta(r)&&(h=!!r.leading,a=(p=\"maxWait\"in r)?mr(ya(r.maxWait)||0,t):a,v=\"trailing\"in r?!!r.trailing:v),m.cancel=function(){c!==u&&ju(c),s=0,e=l=o=c=u},m.flush=function(){return c===u?f:d(Oo())},m}var Lo=Je(function(n,t){return se(n,1,t)}),Co=Je(function(n,t,r){return se(n,ya(t)||0,r)});function To(n,t){if(\"function\"!=typeof n||null!=t&&\"function\"!=typeof t)throw new Bn(i);var r=function(){var e=arguments,u=t?t.apply(this,e):e[0],i=r.cache;if(i.has(u))return i.get(u);var o=n.apply(this,e);return r.cache=i.set(u,o)||i,o};return r.cache=new(To.Cache||Vr),r}function Wo(n){if(\"function\"!=typeof n)throw new Bn(i);return function(){var t=arguments;switch(t.length){case 0:return!n.call(this);case 1:return!n.call(this,t[0]);case 2:return!n.call(this,t[0],t[1]);case 3:return!n.call(this,t[0],t[1],t[2])}return!n.apply(this,t)}}To.Cache=Vr;var Uo=wu(function(n,t){var r=(t=1==t.length&&Go(t[0])?Wt(t[0],nr(ci())):Wt(de(t,1),nr(ci()))).length;return Je(function(e){for(var u=-1,i=br(e.length,r);++u<i;)e[u]=t[u].call(this,e[u]);return It(n,this,e)})}),$o=Je(function(n,t){var r=sr(t,fi($o));return Qu(n,c,u,t,r)}),Mo=Je(function(n,t){var r=sr(t,fi(Mo));return Qu(n,l,u,t,r)}),Do=ei(function(n,t){return Qu(n,h,u,u,u,t)});function Po(n,t){return n===t||n!=n&&t!=t}var Fo=Ku(Oe),No=Ku(function(n,t){return n>=t}),qo=Se(function(){return arguments}())?Se:function(n){return ra(n)&&Un.call(n,\"callee\")&&!Yn.call(n,\"callee\")},Go=e.isArray,Zo=xt?nr(xt):function(n){return ra(n)&&ze(n)==C};function Ko(n){return null!=n&&na(n.length)&&!Qo(n)}function Vo(n){return ra(n)&&Ko(n)}var Ho=bt||df,Yo=jt?nr(jt):function(n){return ra(n)&&ze(n)==w};function Jo(n){if(!ra(n))return!1;var t=ze(n);return t==x||\"[object DOMException]\"==t||\"string\"==typeof n.message&&\"string\"==typeof n.name&&!ia(n)}function Qo(n){if(!ta(n))return!1;var t=ze(n);return t==j||t==A||\"[object AsyncFunction]\"==t||\"[object Proxy]\"==t}function Xo(n){return\"number\"==typeof n&&n==_a(n)}function na(n){return\"number\"==typeof n&&n>-1&&n%1==0&&n<=v}function ta(n){var t=typeof n;return null!=n&&(\"object\"==t||\"function\"==t)}function ra(n){return null!=n&&\"object\"==typeof n}var ea=At?nr(At):function(n){return ra(n)&&_i(n)==k};function ua(n){return\"number\"==typeof n||ra(n)&&ze(n)==z}function ia(n){if(!ra(n)||ze(n)!=O)return!1;var t=Vn(n);if(null===t)return!0;var r=Un.call(t,\"constructor\")&&t.constructor;return\"function\"==typeof r&&r instanceof r&&Wn.call(r)==Pn}var oa=kt?nr(kt):function(n){return ra(n)&&ze(n)==R};var aa=zt?nr(zt):function(n){return ra(n)&&_i(n)==E};function fa(n){return\"string\"==typeof n||!Go(n)&&ra(n)&&ze(n)==B}function ca(n){return\"symbol\"==typeof n||ra(n)&&ze(n)==S}var la=Ot?nr(Ot):function(n){return ra(n)&&na(n.length)&&!!ct[ze(n)]};var sa=Ku(Me),ha=Ku(function(n,t){return n<=t});function pa(n){if(!n)return[];if(Ko(n))return fa(n)?_r(n):Eu(n);if(Xn&&n[Xn])return function(n){for(var t,r=[];!(t=n.next()).done;)r.push(t.value);return r}(n[Xn]());var t=_i(n);return(t==k?cr:t==E?hr:Pa)(n)}function va(n){return n?(n=ya(n))===p||n===-1/0?17976931348623157e292*(n<0?-1:1):n==n?n:0:0===n?n:0}function _a(n){var t=va(n),r=t%1;return t==t?r?t-r:t:0}function ga(n){return n?fe(_a(n),0,g):0}function ya(n){if(\"number\"==typeof n)return n;if(ca(n))return _;if(ta(n)){var t=\"function\"==typeof n.valueOf?n.valueOf():n;n=ta(t)?t+\"\":t}if(\"string\"!=typeof n)return 0===n?n:+n;n=Xt(n);var r=dn.test(n);return r||bn.test(n)?pt(n.slice(2),r?2:8):yn.test(n)?_:+n}function da(n){return Bu(n,La(n))}function ma(n){return null==n?\"\":lu(n)}var ba=Lu(function(n,t){if(Ai(t)||Ko(t))Bu(t,Sa(t),n);else for(var r in t)Un.call(t,r)&&re(n,r,t[r])}),wa=Lu(function(n,t){Bu(t,La(t),n)}),xa=Lu(function(n,t,r,e){Bu(t,La(t),n,e)}),ja=Lu(function(n,t,r,e){Bu(t,Sa(t),n,e)}),Aa=ei(ae);var ka=Je(function(n,t){n=In(n);var r=-1,e=t.length,i=e>2?t[2]:u;for(i&&bi(t[0],t[1],i)&&(e=1);++r<e;)for(var o=t[r],a=La(o),f=-1,c=a.length;++f<c;){var l=a[f],s=n[l];(s===u||Po(s,Cn[l])&&!Un.call(n,l))&&(n[l]=o[l])}return n}),za=Je(function(n){return n.push(u,ni),It(Ta,u,n)});function Oa(n,t,r){var e=null==n?u:Ae(n,t);return e===u?r:e}function Ia(n,t){return null!=n&&gi(n,t,Re)}var Ra=Fu(function(n,t,r){null!=t&&\"function\"!=typeof t.toString&&(t=Dn.call(t)),n[t]=r},tf(uf)),Ea=Fu(function(n,t,r){null!=t&&\"function\"!=typeof t.toString&&(t=Dn.call(t)),Un.call(n,t)?n[t].push(r):n[t]=[r]},ci),Ba=Je(Be);function Sa(n){return Ko(n)?Jr(n):Ue(n)}function La(n){return Ko(n)?Jr(n,!0):$e(n)}var Ca=Lu(function(n,t,r){Ne(n,t,r)}),Ta=Lu(function(n,t,r,e){Ne(n,t,r,e)}),Wa=ei(function(n,t){var r={};if(null==n)return r;var e=!1;t=Wt(t,function(t){return t=bu(t,n),e||(e=t.length>1),t}),Bu(n,ii(n),r),e&&(r=ce(r,7,ti));for(var u=t.length;u--;)hu(r,t[u]);return r});var Ua=ei(function(n,t){return null==n?{}:function(n,t){return Ze(n,t,function(t,r){return Ia(n,r)})}(n,t)});function $a(n,t){if(null==n)return{};var r=Wt(ii(n),function(n){return[n]});return t=ci(t),Ze(n,r,function(n,r){return t(n,r[0])})}var Ma=Ju(Sa),Da=Ju(La);function Pa(n){return null==n?[]:tr(n,Sa(n))}var Fa=Uu(function(n,t,r){return t=t.toLowerCase(),n+(r?Na(t):t)});function Na(n){return Ja(ma(n).toLowerCase())}function qa(n){return(n=ma(n))&&n.replace(xn,ir).replace(rt,\"\")}var Ga=Uu(function(n,t,r){return n+(r?\"-\":\"\")+t.toLowerCase()}),Za=Uu(function(n,t,r){return n+(r?\" \":\"\")+t.toLowerCase()}),Ka=Wu(\"toLowerCase\");var Va=Uu(function(n,t,r){return n+(r?\"_\":\"\")+t.toLowerCase()});var Ha=Uu(function(n,t,r){return n+(r?\" \":\"\")+Ja(t)});var Ya=Uu(function(n,t,r){return n+(r?\" \":\"\")+t.toUpperCase()}),Ja=Wu(\"toUpperCase\");function Qa(n,t,r){return n=ma(n),(t=r?u:t)===u?function(n){return ot.test(n)}(n)?function(n){return n.match(ut)||[]}(n):function(n){return n.match(hn)||[]}(n):n.match(t)||[]}var Xa=Je(function(n,t){try{return It(n,u,t)}catch(n){return Jo(n)?n:new kn(n)}}),nf=ei(function(n,t){return Et(t,function(t){t=Ui(t),oe(n,t,Eo(n[t],n))}),n});function tf(n){return function(){return n}}var rf=Du(),ef=Du(!0);function uf(n){return n}function of(n){return We(\"function\"==typeof n?n:ce(n,1))}var af=Je(function(n,t){return function(r){return Be(r,n,t)}}),ff=Je(function(n,t){return function(r){return Be(n,r,t)}});function cf(n,t,r){var e=Sa(t),u=je(t,e);null!=r||ta(t)&&(u.length||!e.length)||(r=t,t=n,n=this,u=je(t,Sa(t)));var i=!(ta(r)&&\"chain\"in r&&!r.chain),o=Qo(n);return Et(u,function(r){var e=t[r];n[r]=e,o&&(n.prototype[r]=function(){var t=this.__chain__;if(i||t){var r=n(this.__wrapped__);return(r.__actions__=Eu(this.__actions__)).push({func:e,args:arguments,thisArg:n}),r.__chain__=t,r}return e.apply(n,Ut([this.value()],arguments))})}),n}function lf(){}var sf=qu(Wt),hf=qu(St),pf=qu(Dt);function vf(n){return wi(n)?Vt(Ui(n)):function(n){return function(t){return Ae(t,n)}}(n)}var _f=Zu(),gf=Zu(!0);function yf(){return[]}function df(){return!1}var mf=Nu(function(n,t){return n+t},0),bf=Hu(\"ceil\"),wf=Nu(function(n,t){return n/t},1),xf=Hu(\"floor\");var jf,Af=Nu(function(n,t){return n*t},1),kf=Hu(\"round\"),zf=Nu(function(n,t){return n-t},0);return Pr.after=function(n,t){if(\"function\"!=typeof t)throw new Bn(i);return n=_a(n),function(){if(--n<1)return t.apply(this,arguments)}},Pr.ary=Io,Pr.assign=ba,Pr.assignIn=wa,Pr.assignInWith=xa,Pr.assignWith=ja,Pr.at=Aa,Pr.before=Ro,Pr.bind=Eo,Pr.bindAll=nf,Pr.bindKey=Bo,Pr.castArray=function(){if(!arguments.length)return[];var n=arguments[0];return Go(n)?n:[n]},Pr.chain=ho,Pr.chunk=function(n,t,r){t=(r?bi(n,t,r):t===u)?1:mr(_a(t),0);var i=null==n?0:n.length;if(!i||t<1)return[];for(var o=0,a=0,f=e(_t(i/t));o<i;)f[a++]=uu(n,o,o+=t);return f},Pr.compact=function(n){for(var t=-1,r=null==n?0:n.length,e=0,u=[];++t<r;){var i=n[t];i&&(u[e++]=i)}return u},Pr.concat=function(){var n=arguments.length;if(!n)return[];for(var t=e(n-1),r=arguments[0],u=n;u--;)t[u-1]=arguments[u];return Ut(Go(r)?Eu(r):[r],de(t,1))},Pr.cond=function(n){var t=null==n?0:n.length,r=ci();return n=t?Wt(n,function(n){if(\"function\"!=typeof n[1])throw new Bn(i);return[r(n[0]),n[1]]}):[],Je(function(r){for(var e=-1;++e<t;){var u=n[e];if(It(u[0],this,r))return It(u[1],this,r)}})},Pr.conforms=function(n){return function(n){var t=Sa(n);return function(r){return le(r,n,t)}}(ce(n,1))},Pr.constant=tf,Pr.countBy=_o,Pr.create=function(n,t){var r=Fr(n);return null==t?r:ie(r,t)},Pr.curry=function n(t,r,e){var i=Qu(t,8,u,u,u,u,u,r=e?u:r);return i.placeholder=n.placeholder,i},Pr.curryRight=function n(t,r,e){var i=Qu(t,f,u,u,u,u,u,r=e?u:r);return i.placeholder=n.placeholder,i},Pr.debounce=So,Pr.defaults=ka,Pr.defaultsDeep=za,Pr.defer=Lo,Pr.delay=Co,Pr.difference=Di,Pr.differenceBy=Pi,Pr.differenceWith=Fi,Pr.drop=function(n,t,r){var e=null==n?0:n.length;return e?uu(n,(t=r||t===u?1:_a(t))<0?0:t,e):[]},Pr.dropRight=function(n,t,r){var e=null==n?0:n.length;return e?uu(n,0,(t=e-(t=r||t===u?1:_a(t)))<0?0:t):[]},Pr.dropRightWhile=function(n,t){return n&&n.length?vu(n,ci(t,3),!0,!0):[]},Pr.dropWhile=function(n,t){return n&&n.length?vu(n,ci(t,3),!0):[]},Pr.fill=function(n,t,r,e){var i=null==n?0:n.length;return i?(r&&\"number\"!=typeof r&&bi(n,t,r)&&(r=0,e=i),function(n,t,r,e){var i=n.length;for((r=_a(r))<0&&(r=-r>i?0:i+r),(e=e===u||e>i?i:_a(e))<0&&(e+=i),e=r>e?0:ga(e);r<e;)n[r++]=t;return n}(n,t,r,e)):[]},Pr.filter=function(n,t){return(Go(n)?Lt:ye)(n,ci(t,3))},Pr.flatMap=function(n,t){return de(Ao(n,t),1)},Pr.flatMapDeep=function(n,t){return de(Ao(n,t),p)},Pr.flatMapDepth=function(n,t,r){return r=r===u?1:_a(r),de(Ao(n,t),r)},Pr.flatten=Gi,Pr.flattenDeep=function(n){return(null==n?0:n.length)?de(n,p):[]},Pr.flattenDepth=function(n,t){return(null==n?0:n.length)?de(n,t=t===u?1:_a(t)):[]},Pr.flip=function(n){return Qu(n,512)},Pr.flow=rf,Pr.flowRight=ef,Pr.fromPairs=function(n){for(var t=-1,r=null==n?0:n.length,e={};++t<r;){var u=n[t];e[u[0]]=u[1]}return e},Pr.functions=function(n){return null==n?[]:je(n,Sa(n))},Pr.functionsIn=function(n){return null==n?[]:je(n,La(n))},Pr.groupBy=wo,Pr.initial=function(n){return(null==n?0:n.length)?uu(n,0,-1):[]},Pr.intersection=Ki,Pr.intersectionBy=Vi,Pr.intersectionWith=Hi,Pr.invert=Ra,Pr.invertBy=Ea,Pr.invokeMap=xo,Pr.iteratee=of,Pr.keyBy=jo,Pr.keys=Sa,Pr.keysIn=La,Pr.map=Ao,Pr.mapKeys=function(n,t){var r={};return t=ci(t,3),we(n,function(n,e,u){oe(r,t(n,e,u),n)}),r},Pr.mapValues=function(n,t){var r={};return t=ci(t,3),we(n,function(n,e,u){oe(r,e,t(n,e,u))}),r},Pr.matches=function(n){return Pe(ce(n,1))},Pr.matchesProperty=function(n,t){return Fe(n,ce(t,1))},Pr.memoize=To,Pr.merge=Ca,Pr.mergeWith=Ta,Pr.method=af,Pr.methodOf=ff,Pr.mixin=cf,Pr.negate=Wo,Pr.nthArg=function(n){return n=_a(n),Je(function(t){return qe(t,n)})},Pr.omit=Wa,Pr.omitBy=function(n,t){return $a(n,Wo(ci(t)))},Pr.once=function(n){return Ro(2,n)},Pr.orderBy=function(n,t,r,e){return null==n?[]:(Go(t)||(t=null==t?[]:[t]),Go(r=e?u:r)||(r=null==r?[]:[r]),Ge(n,t,r))},Pr.over=sf,Pr.overArgs=Uo,Pr.overEvery=hf,Pr.overSome=pf,Pr.partial=$o,Pr.partialRight=Mo,Pr.partition=ko,Pr.pick=Ua,Pr.pickBy=$a,Pr.property=vf,Pr.propertyOf=function(n){return function(t){return null==n?u:Ae(n,t)}},Pr.pull=Ji,Pr.pullAll=Qi,Pr.pullAllBy=function(n,t,r){return n&&n.length&&t&&t.length?Ke(n,t,ci(r,2)):n},Pr.pullAllWith=function(n,t,r){return n&&n.length&&t&&t.length?Ke(n,t,u,r):n},Pr.pullAt=Xi,Pr.range=_f,Pr.rangeRight=gf,Pr.rearg=Do,Pr.reject=function(n,t){return(Go(n)?Lt:ye)(n,Wo(ci(t,3)))},Pr.remove=function(n,t){var r=[];if(!n||!n.length)return r;var e=-1,u=[],i=n.length;for(t=ci(t,3);++e<i;){var o=n[e];t(o,e,n)&&(r.push(o),u.push(e))}return Ve(n,u),r},Pr.rest=function(n,t){if(\"function\"!=typeof n)throw new Bn(i);return Je(n,t=t===u?t:_a(t))},Pr.reverse=no,Pr.sampleSize=function(n,t,r){return t=(r?bi(n,t,r):t===u)?1:_a(t),(Go(n)?Xr:Xe)(n,t)},Pr.set=function(n,t,r){return null==n?n:nu(n,t,r)},Pr.setWith=function(n,t,r,e){return e=\"function\"==typeof e?e:u,null==n?n:nu(n,t,r,e)},Pr.shuffle=function(n){return(Go(n)?ne:eu)(n)},Pr.slice=function(n,t,r){var e=null==n?0:n.length;return e?(r&&\"number\"!=typeof r&&bi(n,t,r)?(t=0,r=e):(t=null==t?0:_a(t),r=r===u?e:_a(r)),uu(n,t,r)):[]},Pr.sortBy=zo,Pr.sortedUniq=function(n){return n&&n.length?fu(n):[]},Pr.sortedUniqBy=function(n,t){return n&&n.length?fu(n,ci(t,2)):[]},Pr.split=function(n,t,r){return r&&\"number\"!=typeof r&&bi(n,t,r)&&(t=r=u),(r=r===u?g:r>>>0)?(n=ma(n))&&(\"string\"==typeof t||null!=t&&!oa(t))&&!(t=lu(t))&&fr(n)?xu(_r(n),0,r):n.split(t,r):[]},Pr.spread=function(n,t){if(\"function\"!=typeof n)throw new Bn(i);return t=null==t?0:mr(_a(t),0),Je(function(r){var e=r[t],u=xu(r,0,t);return e&&Ut(u,e),It(n,this,u)})},Pr.tail=function(n){var t=null==n?0:n.length;return t?uu(n,1,t):[]},Pr.take=function(n,t,r){return n&&n.length?uu(n,0,(t=r||t===u?1:_a(t))<0?0:t):[]},Pr.takeRight=function(n,t,r){var e=null==n?0:n.length;return e?uu(n,(t=e-(t=r||t===u?1:_a(t)))<0?0:t,e):[]},Pr.takeRightWhile=function(n,t){return n&&n.length?vu(n,ci(t,3),!1,!0):[]},Pr.takeWhile=function(n,t){return n&&n.length?vu(n,ci(t,3)):[]},Pr.tap=function(n,t){return t(n),n},Pr.throttle=function(n,t,r){var e=!0,u=!0;if(\"function\"!=typeof n)throw new Bn(i);return ta(r)&&(e=\"leading\"in r?!!r.leading:e,u=\"trailing\"in r?!!r.trailing:u),So(n,t,{leading:e,maxWait:t,trailing:u})},Pr.thru=po,Pr.toArray=pa,Pr.toPairs=Ma,Pr.toPairsIn=Da,Pr.toPath=function(n){return Go(n)?Wt(n,Ui):ca(n)?[n]:Eu(Wi(ma(n)))},Pr.toPlainObject=da,Pr.transform=function(n,t,r){var e=Go(n),u=e||Ho(n)||la(n);if(t=ci(t,4),null==r){var i=n&&n.constructor;r=u?e?new i:[]:ta(n)&&Qo(i)?Fr(Vn(n)):{}}return(u?Et:we)(n,function(n,e,u){return t(r,n,e,u)}),r},Pr.unary=function(n){return Io(n,1)},Pr.union=to,Pr.unionBy=ro,Pr.unionWith=eo,Pr.uniq=function(n){return n&&n.length?su(n):[]},Pr.uniqBy=function(n,t){return n&&n.length?su(n,ci(t,2)):[]},Pr.uniqWith=function(n,t){return t=\"function\"==typeof t?t:u,n&&n.length?su(n,u,t):[]},Pr.unset=function(n,t){return null==n||hu(n,t)},Pr.unzip=uo,Pr.unzipWith=io,Pr.update=function(n,t,r){return null==n?n:pu(n,t,mu(r))},Pr.updateWith=function(n,t,r,e){return e=\"function\"==typeof e?e:u,null==n?n:pu(n,t,mu(r),e)},Pr.values=Pa,Pr.valuesIn=function(n){return null==n?[]:tr(n,La(n))},Pr.without=oo,Pr.words=Qa,Pr.wrap=function(n,t){return $o(mu(t),n)},Pr.xor=ao,Pr.xorBy=fo,Pr.xorWith=co,Pr.zip=lo,Pr.zipObject=function(n,t){return yu(n||[],t||[],re)},Pr.zipObjectDeep=function(n,t){return yu(n||[],t||[],nu)},Pr.zipWith=so,Pr.entries=Ma,Pr.entriesIn=Da,Pr.extend=wa,Pr.extendWith=xa,cf(Pr,Pr),Pr.add=mf,Pr.attempt=Xa,Pr.camelCase=Fa,Pr.capitalize=Na,Pr.ceil=bf,Pr.clamp=function(n,t,r){return r===u&&(r=t,t=u),r!==u&&(r=(r=ya(r))==r?r:0),t!==u&&(t=(t=ya(t))==t?t:0),fe(ya(n),t,r)},Pr.clone=function(n){return ce(n,4)},Pr.cloneDeep=function(n){return ce(n,5)},Pr.cloneDeepWith=function(n,t){return ce(n,5,t=\"function\"==typeof t?t:u)},Pr.cloneWith=function(n,t){return ce(n,4,t=\"function\"==typeof t?t:u)},Pr.conformsTo=function(n,t){return null==t||le(n,t,Sa(t))},Pr.deburr=qa,Pr.defaultTo=function(n,t){return null==n||n!=n?t:n},Pr.divide=wf,Pr.endsWith=function(n,t,r){n=ma(n),t=lu(t);var e=n.length,i=r=r===u?e:fe(_a(r),0,e);return(r-=t.length)>=0&&n.slice(r,i)==t},Pr.eq=Po,Pr.escape=function(n){return(n=ma(n))&&J.test(n)?n.replace(H,or):n},Pr.escapeRegExp=function(n){return(n=ma(n))&&on.test(n)?n.replace(un,\"\\\\$&\"):n},Pr.every=function(n,t,r){var e=Go(n)?St:_e;return r&&bi(n,t,r)&&(t=u),e(n,ci(t,3))},Pr.find=go,Pr.findIndex=Ni,Pr.findKey=function(n,t){return Ft(n,ci(t,3),we)},Pr.findLast=yo,Pr.findLastIndex=qi,Pr.findLastKey=function(n,t){return Ft(n,ci(t,3),xe)},Pr.floor=xf,Pr.forEach=mo,Pr.forEachRight=bo,Pr.forIn=function(n,t){return null==n?n:me(n,ci(t,3),La)},Pr.forInRight=function(n,t){return null==n?n:be(n,ci(t,3),La)},Pr.forOwn=function(n,t){return n&&we(n,ci(t,3))},Pr.forOwnRight=function(n,t){return n&&xe(n,ci(t,3))},Pr.get=Oa,Pr.gt=Fo,Pr.gte=No,Pr.has=function(n,t){return null!=n&&gi(n,t,Ie)},Pr.hasIn=Ia,Pr.head=Zi,Pr.identity=uf,Pr.includes=function(n,t,r,e){n=Ko(n)?n:Pa(n),r=r&&!e?_a(r):0;var u=n.length;return r<0&&(r=mr(u+r,0)),fa(n)?r<=u&&n.indexOf(t,r)>-1:!!u&&qt(n,t,r)>-1},Pr.indexOf=function(n,t,r){var e=null==n?0:n.length;if(!e)return-1;var u=null==r?0:_a(r);return u<0&&(u=mr(e+u,0)),qt(n,t,u)},Pr.inRange=function(n,t,r){return t=va(t),r===u?(r=t,t=0):r=va(r),function(n,t,r){return n>=br(t,r)&&n<mr(t,r)}(n=ya(n),t,r)},Pr.invoke=Ba,Pr.isArguments=qo,Pr.isArray=Go,Pr.isArrayBuffer=Zo,Pr.isArrayLike=Ko,Pr.isArrayLikeObject=Vo,Pr.isBoolean=function(n){return!0===n||!1===n||ra(n)&&ze(n)==b},Pr.isBuffer=Ho,Pr.isDate=Yo,Pr.isElement=function(n){return ra(n)&&1===n.nodeType&&!ia(n)},Pr.isEmpty=function(n){if(null==n)return!0;if(Ko(n)&&(Go(n)||\"string\"==typeof n||\"function\"==typeof n.splice||Ho(n)||la(n)||qo(n)))return!n.length;var t=_i(n);if(t==k||t==E)return!n.size;if(Ai(n))return!Ue(n).length;for(var r in n)if(Un.call(n,r))return!1;return!0},Pr.isEqual=function(n,t){return Le(n,t)},Pr.isEqualWith=function(n,t,r){var e=(r=\"function\"==typeof r?r:u)?r(n,t):u;return e===u?Le(n,t,u,r):!!e},Pr.isError=Jo,Pr.isFinite=function(n){return\"number\"==typeof n&&wt(n)},Pr.isFunction=Qo,Pr.isInteger=Xo,Pr.isLength=na,Pr.isMap=ea,Pr.isMatch=function(n,t){return n===t||Ce(n,t,si(t))},Pr.isMatchWith=function(n,t,r){return r=\"function\"==typeof r?r:u,Ce(n,t,si(t),r)},Pr.isNaN=function(n){return ua(n)&&n!=+n},Pr.isNative=function(n){if(ji(n))throw new kn(\"Unsupported core-js use. Try https://npms.io/search?q=ponyfill.\");return Te(n)},Pr.isNil=function(n){return null==n},Pr.isNull=function(n){return null===n},Pr.isNumber=ua,Pr.isObject=ta,Pr.isObjectLike=ra,Pr.isPlainObject=ia,Pr.isRegExp=oa,Pr.isSafeInteger=function(n){return Xo(n)&&n>=-9007199254740991&&n<=v},Pr.isSet=aa,Pr.isString=fa,Pr.isSymbol=ca,Pr.isTypedArray=la,Pr.isUndefined=function(n){return n===u},Pr.isWeakMap=function(n){return ra(n)&&_i(n)==L},Pr.isWeakSet=function(n){return ra(n)&&\"[object WeakSet]\"==ze(n)},Pr.join=function(n,t){return null==n?\"\":Pt.call(n,t)},Pr.kebabCase=Ga,Pr.last=Yi,Pr.lastIndexOf=function(n,t,r){var e=null==n?0:n.length;if(!e)return-1;var i=e;return r!==u&&(i=(i=_a(r))<0?mr(e+i,0):br(i,e-1)),t==t?function(n,t,r){for(var e=r+1;e--;)if(n[e]===t)return e;return e}(n,t,i):Nt(n,Zt,i,!0)},Pr.lowerCase=Za,Pr.lowerFirst=Ka,Pr.lt=sa,Pr.lte=ha,Pr.max=function(n){return n&&n.length?ge(n,uf,Oe):u},Pr.maxBy=function(n,t){return n&&n.length?ge(n,ci(t,2),Oe):u},Pr.mean=function(n){return Kt(n,uf)},Pr.meanBy=function(n,t){return Kt(n,ci(t,2))},Pr.min=function(n){return n&&n.length?ge(n,uf,Me):u},Pr.minBy=function(n,t){return n&&n.length?ge(n,ci(t,2),Me):u},Pr.stubArray=yf,Pr.stubFalse=df,Pr.stubObject=function(){return{}},Pr.stubString=function(){return\"\"},Pr.stubTrue=function(){return!0},Pr.multiply=Af,Pr.nth=function(n,t){return n&&n.length?qe(n,_a(t)):u},Pr.noConflict=function(){return gt._===this&&(gt._=Fn),this},Pr.noop=lf,Pr.now=Oo,Pr.pad=function(n,t,r){n=ma(n);var e=(t=_a(t))?vr(n):0;if(!t||e>=t)return n;var u=(t-e)/2;return Gu(yt(u),r)+n+Gu(_t(u),r)},Pr.padEnd=function(n,t,r){n=ma(n);var e=(t=_a(t))?vr(n):0;return t&&e<t?n+Gu(t-e,r):n},Pr.padStart=function(n,t,r){n=ma(n);var e=(t=_a(t))?vr(n):0;return t&&e<t?Gu(t-e,r)+n:n},Pr.parseInt=function(n,t,r){return r||null==t?t=0:t&&(t=+t),xr(ma(n).replace(an,\"\"),t||0)},Pr.random=function(n,t,r){if(r&&\"boolean\"!=typeof r&&bi(n,t,r)&&(t=r=u),r===u&&(\"boolean\"==typeof t?(r=t,t=u):\"boolean\"==typeof n&&(r=n,n=u)),n===u&&t===u?(n=0,t=1):(n=va(n),t===u?(t=n,n=0):t=va(t)),n>t){var e=n;n=t,t=e}if(r||n%1||t%1){var i=jr();return br(n+i*(t-n+ht(\"1e-\"+((i+\"\").length-1))),t)}return He(n,t)},Pr.reduce=function(n,t,r){var e=Go(n)?$t:Yt,u=arguments.length<3;return e(n,ci(t,4),r,u,pe)},Pr.reduceRight=function(n,t,r){var e=Go(n)?Mt:Yt,u=arguments.length<3;return e(n,ci(t,4),r,u,ve)},Pr.repeat=function(n,t,r){return t=(r?bi(n,t,r):t===u)?1:_a(t),Ye(ma(n),t)},Pr.replace=function(){var n=arguments,t=ma(n[0]);return n.length<3?t:t.replace(n[1],n[2])},Pr.result=function(n,t,r){var e=-1,i=(t=bu(t,n)).length;for(i||(i=1,n=u);++e<i;){var o=null==n?u:n[Ui(t[e])];o===u&&(e=i,o=r),n=Qo(o)?o.call(n):o}return n},Pr.round=kf,Pr.runInContext=n,Pr.sample=function(n){return(Go(n)?Qr:Qe)(n)},Pr.size=function(n){if(null==n)return 0;if(Ko(n))return fa(n)?vr(n):n.length;var t=_i(n);return t==k||t==E?n.size:Ue(n).length},Pr.snakeCase=Va,Pr.some=function(n,t,r){var e=Go(n)?Dt:iu;return r&&bi(n,t,r)&&(t=u),e(n,ci(t,3))},Pr.sortedIndex=function(n,t){return ou(n,t)},Pr.sortedIndexBy=function(n,t,r){return au(n,t,ci(r,2))},Pr.sortedIndexOf=function(n,t){var r=null==n?0:n.length;if(r){var e=ou(n,t);if(e<r&&Po(n[e],t))return e}return-1},Pr.sortedLastIndex=function(n,t){return ou(n,t,!0)},Pr.sortedLastIndexBy=function(n,t,r){return au(n,t,ci(r,2),!0)},Pr.sortedLastIndexOf=function(n,t){if(null==n?0:n.length){var r=ou(n,t,!0)-1;if(Po(n[r],t))return r}return-1},Pr.startCase=Ha,Pr.startsWith=function(n,t,r){return n=ma(n),r=null==r?0:fe(_a(r),0,n.length),t=lu(t),n.slice(r,r+t.length)==t},Pr.subtract=zf,Pr.sum=function(n){return n&&n.length?Jt(n,uf):0},Pr.sumBy=function(n,t){return n&&n.length?Jt(n,ci(t,2)):0},Pr.template=function(n,t,r){var e=Pr.templateSettings;r&&bi(n,t,r)&&(t=u),n=ma(n),t=xa({},t,e,Xu);var i,o,a=xa({},t.imports,e.imports,Xu),f=Sa(a),c=tr(a,f),l=0,s=t.interpolate||jn,h=\"__p += '\",p=Rn((t.escape||jn).source+\"|\"+s.source+\"|\"+(s===nn?_n:jn).source+\"|\"+(t.evaluate||jn).source+\"|$\",\"g\"),v=\"//# sourceURL=\"+(Un.call(t,\"sourceURL\")?(t.sourceURL+\"\").replace(/\\s/g,\" \"):\"lodash.templateSources[\"+ ++ft+\"]\")+\"\\n\";n.replace(p,function(t,r,e,u,a,f){return e||(e=u),h+=n.slice(l,f).replace(An,ar),r&&(i=!0,h+=\"' +\\n__e(\"+r+\") +\\n'\"),a&&(o=!0,h+=\"';\\n\"+a+\";\\n__p += '\"),e&&(h+=\"' +\\n((__t = (\"+e+\")) == null ? '' : __t) +\\n'\"),l=f+t.length,t}),h+=\"';\\n\";var _=Un.call(t,\"variable\")&&t.variable;if(_){if(pn.test(_))throw new kn(\"Invalid `variable` option passed into `_.template`\")}else h=\"with (obj) {\\n\"+h+\"\\n}\\n\";h=(o?h.replace(G,\"\"):h).replace(Z,\"$1\").replace(K,\"$1;\"),h=\"function(\"+(_||\"obj\")+\") {\\n\"+(_?\"\":\"obj || (obj = {});\\n\")+\"var __t, __p = ''\"+(i?\", __e = _.escape\":\"\")+(o?\", __j = Array.prototype.join;\\nfunction print() { __p += __j.call(arguments, '') }\\n\":\";\\n\")+h+\"return __p\\n}\";var g=Xa(function(){return zn(f,v+\"return \"+h).apply(u,c)});if(g.source=h,Jo(g))throw g;return g},Pr.times=function(n,t){if((n=_a(n))<1||n>v)return[];var r=g,e=br(n,g);t=ci(t),n-=g;for(var u=Qt(e,t);++r<n;)t(r);return u},Pr.toFinite=va,Pr.toInteger=_a,Pr.toLength=ga,Pr.toLower=function(n){return ma(n).toLowerCase()},Pr.toNumber=ya,Pr.toSafeInteger=function(n){return n?fe(_a(n),-9007199254740991,v):0===n?n:0},Pr.toString=ma,Pr.toUpper=function(n){return ma(n).toUpperCase()},Pr.trim=function(n,t,r){if((n=ma(n))&&(r||t===u))return Xt(n);if(!n||!(t=lu(t)))return n;var e=_r(n),i=_r(t);return xu(e,er(e,i),ur(e,i)+1).join(\"\")},Pr.trimEnd=function(n,t,r){if((n=ma(n))&&(r||t===u))return n.slice(0,gr(n)+1);if(!n||!(t=lu(t)))return n;var e=_r(n);return xu(e,0,ur(e,_r(t))+1).join(\"\")},Pr.trimStart=function(n,t,r){if((n=ma(n))&&(r||t===u))return n.replace(an,\"\");if(!n||!(t=lu(t)))return n;var e=_r(n);return xu(e,er(e,_r(t))).join(\"\")},Pr.truncate=function(n,t){var r=30,e=\"...\";if(ta(t)){var i=\"separator\"in t?t.separator:i;r=\"length\"in t?_a(t.length):r,e=\"omission\"in t?lu(t.omission):e}var o=(n=ma(n)).length;if(fr(n)){var a=_r(n);o=a.length}if(r>=o)return n;var f=r-vr(e);if(f<1)return e;var c=a?xu(a,0,f).join(\"\"):n.slice(0,f);if(i===u)return c+e;if(a&&(f+=c.length-f),oa(i)){if(n.slice(f).search(i)){var l,s=c;for(i.global||(i=Rn(i.source,ma(gn.exec(i))+\"g\")),i.lastIndex=0;l=i.exec(s);)var h=l.index;c=c.slice(0,h===u?f:h)}}else if(n.indexOf(lu(i),f)!=f){var p=c.lastIndexOf(i);p>-1&&(c=c.slice(0,p))}return c+e},Pr.unescape=function(n){return(n=ma(n))&&Y.test(n)?n.replace(V,yr):n},Pr.uniqueId=function(n){var t=++$n;return ma(n)+t},Pr.upperCase=Ya,Pr.upperFirst=Ja,Pr.each=mo,Pr.eachRight=bo,Pr.first=Zi,cf(Pr,(jf={},we(Pr,function(n,t){Un.call(Pr.prototype,t)||(jf[t]=n)}),jf),{chain:!1}),Pr.VERSION=\"4.17.23\",Et([\"bind\",\"bindKey\",\"curry\",\"curryRight\",\"partial\",\"partialRight\"],function(n){Pr[n].placeholder=Pr}),Et([\"drop\",\"take\"],function(n,t){Gr.prototype[n]=function(r){r=r===u?1:mr(_a(r),0);var e=this.__filtered__&&!t?new Gr(this):this.clone();return e.__filtered__?e.__takeCount__=br(r,e.__takeCount__):e.__views__.push({size:br(r,g),type:n+(e.__dir__<0?\"Right\":\"\")}),e},Gr.prototype[n+\"Right\"]=function(t){return this.reverse()[n](t).reverse()}}),Et([\"filter\",\"map\",\"takeWhile\"],function(n,t){var r=t+1,e=1==r||3==r;Gr.prototype[n]=function(n){var t=this.clone();return t.__iteratees__.push({iteratee:ci(n,3),type:r}),t.__filtered__=t.__filtered__||e,t}}),Et([\"head\",\"last\"],function(n,t){var r=\"take\"+(t?\"Right\":\"\");Gr.prototype[n]=function(){return this[r](1).value()[0]}}),Et([\"initial\",\"tail\"],function(n,t){var r=\"drop\"+(t?\"\":\"Right\");Gr.prototype[n]=function(){return this.__filtered__?new Gr(this):this[r](1)}}),Gr.prototype.compact=function(){return this.filter(uf)},Gr.prototype.find=function(n){return this.filter(n).head()},Gr.prototype.findLast=function(n){return this.reverse().find(n)},Gr.prototype.invokeMap=Je(function(n,t){return\"function\"==typeof n?new Gr(this):this.map(function(r){return Be(r,n,t)})}),Gr.prototype.reject=function(n){return this.filter(Wo(ci(n)))},Gr.prototype.slice=function(n,t){n=_a(n);var r=this;return r.__filtered__&&(n>0||t<0)?new Gr(r):(n<0?r=r.takeRight(-n):n&&(r=r.drop(n)),t!==u&&(r=(t=_a(t))<0?r.dropRight(-t):r.take(t-n)),r)},Gr.prototype.takeRightWhile=function(n){return this.reverse().takeWhile(n).reverse()},Gr.prototype.toArray=function(){return this.take(g)},we(Gr.prototype,function(n,t){var r=/^(?:filter|find|map|reject)|While$/.test(t),e=/^(?:head|last)$/.test(t),i=Pr[e?\"take\"+(\"last\"==t?\"Right\":\"\"):t],o=e||/^find/.test(t);i&&(Pr.prototype[t]=function(){var t=this.__wrapped__,a=e?[1]:arguments,f=t instanceof Gr,c=a[0],l=f||Go(t),s=function(n){var t=i.apply(Pr,Ut([n],a));return e&&h?t[0]:t};l&&r&&\"function\"==typeof c&&1!=c.length&&(f=l=!1);var h=this.__chain__,p=!!this.__actions__.length,v=o&&!h,_=f&&!p;if(!o&&l){t=_?t:new Gr(this);var g=n.apply(t,a);return g.__actions__.push({func:po,args:[s],thisArg:u}),new qr(g,h)}return v&&_?n.apply(this,a):(g=this.thru(s),v?e?g.value()[0]:g.value():g)})}),Et([\"pop\",\"push\",\"shift\",\"sort\",\"splice\",\"unshift\"],function(n){var t=Sn[n],r=/^(?:push|sort|unshift)$/.test(n)?\"tap\":\"thru\",e=/^(?:pop|shift)$/.test(n);Pr.prototype[n]=function(){var n=arguments;if(e&&!this.__chain__){var u=this.value();return t.apply(Go(u)?u:[],n)}return this[r](function(r){return t.apply(Go(r)?r:[],n)})}}),we(Gr.prototype,function(n,t){var r=Pr[t];if(r){var e=r.name+\"\";Un.call(Sr,e)||(Sr[e]=[]),Sr[e].push({name:t,func:r})}}),Sr[Pu(u,2).name]=[{name:\"wrapper\",func:u}],Gr.prototype.clone=function(){var n=new Gr(this.__wrapped__);return n.__actions__=Eu(this.__actions__),n.__dir__=this.__dir__,n.__filtered__=this.__filtered__,n.__iteratees__=Eu(this.__iteratees__),n.__takeCount__=this.__takeCount__,n.__views__=Eu(this.__views__),n},Gr.prototype.reverse=function(){if(this.__filtered__){var n=new Gr(this);n.__dir__=-1,n.__filtered__=!0}else(n=this.clone()).__dir__*=-1;return n},Gr.prototype.value=function(){var n=this.__wrapped__.value(),t=this.__dir__,r=Go(n),e=t<0,u=r?n.length:0,i=function(n,t,r){var e=-1,u=r.length;for(;++e<u;){var i=r[e],o=i.size;switch(i.type){case\"drop\":n+=o;break;case\"dropRight\":t-=o;break;case\"take\":t=br(t,n+o);break;case\"takeRight\":n=mr(n,t-o)}}return{start:n,end:t}}(0,u,this.__views__),o=i.start,a=i.end,f=a-o,c=e?a:o-1,l=this.__iteratees__,s=l.length,h=0,p=br(f,this.__takeCount__);if(!r||!e&&u==f&&p==f)return _u(n,this.__actions__);var v=[];n:for(;f--&&h<p;){for(var _=-1,g=n[c+=t];++_<s;){var y=l[_],d=y.iteratee,m=y.type,b=d(g);if(2==m)g=b;else if(!b){if(1==m)continue n;break n}}v[h++]=g}return v},Pr.prototype.at=vo,Pr.prototype.chain=function(){return ho(this)},Pr.prototype.commit=function(){return new qr(this.value(),this.__chain__)},Pr.prototype.next=function(){this.__values__===u&&(this.__values__=pa(this.value()));var n=this.__index__>=this.__values__.length;return{done:n,value:n?u:this.__values__[this.__index__++]}},Pr.prototype.plant=function(n){for(var t,r=this;r instanceof Nr;){var e=Mi(r);e.__index__=0,e.__values__=u,t?i.__wrapped__=e:t=e;var i=e;r=r.__wrapped__}return i.__wrapped__=n,t},Pr.prototype.reverse=function(){var n=this.__wrapped__;if(n instanceof Gr){var t=n;return this.__actions__.length&&(t=new Gr(this)),(t=t.reverse()).__actions__.push({func:po,args:[no],thisArg:u}),new qr(t,this.__chain__)}return this.thru(no)},Pr.prototype.toJSON=Pr.prototype.valueOf=Pr.prototype.value=function(){return _u(this.__wrapped__,this.__actions__)},Pr.prototype.first=Pr.prototype.head,Xn&&(Pr.prototype[Xn]=function(){return this}),Pr}();gt._=dr,(e=function(){return dr}.call(t,r,t,n))===u||(n.exports=e)}.call(this)}},t={};function r(e){var u=t[e];if(void 0!==u)return u.exports;var i=t[e]={id:e,loaded:!1,exports:{}};return n[e].call(i.exports,i,i.exports,r),i.loaded=!0,i.exports}r.g=function(){if(\"object\"==typeof globalThis)return globalThis;try{return this||new Function(\"return this\")()}catch(n){if(\"object\"==typeof window)return window}}(),r.nmd=n=>(n.paths=[],n.children||(n.children=[]),n),(()=>{\"use strict\";r(543);function n(){setTimeout(()=>{Plotly.Plots.resize(\"memoryGraph\"),Plotly.Plots.resize(\"smallMemoryGraph\")},100)}window.resizeMemoryGraph=n,document.addEventListener(\"DOMContentLoaded\",function(){data=packed_data,function(t){const r=t.map(n=>new Date(n[0])),e=t.map(n=>n[1]),u=t.map(n=>n[2]),i=t.length>1?\"lines\":\"markers\";var o=[{x:r,y:e,mode:i,name:\"Resident size\"},{x:r,y:u,mode:i,name:\"Heap size\"}],a={responsive:!0,displayModeBar:!0,modeBarButtonsToAdd:[{name:\"downloadDataAsCsv\",title:\"Download data as CSV\",icon:Plotly.Icons.disk,click:function(n){var t=[];t.push(\"trace,timestamp,memory_size_bytes\"),n.data.forEach((n,r)=>{const e=n.x||[],u=n.y||[];for(var i=0;i<Math.min(e.length,u.length);i++){const o=n.name||\"trace\"+r,a=e[i].getTime();t.push(`${o},${a},${u[i]}`)}});const r=t.join(\"\\r\\n\"),e=new Blob([r],{type:\"text/csv\"}),u=URL.createObjectURL(e),i=document.createElement(\"a\");i.href=u,i.download=\"usage_over_time.csv\",document.body.appendChild(i),i.click(),document.body.removeChild(i),URL.revokeObjectURL(u)}}]};Plotly.newPlot(\"memoryGraph\",o,{xaxis:{title:{text:\"Time\"}},yaxis:{title:{text:\"Memory Size\"},tickformat:\".4~s\",exponentformat:\"B\",ticksuffix:\"B\"}},a),Plotly.newPlot(\"smallMemoryGraph\",o,{height:40,margin:{l:0,r:0,b:0,t:0,pad:4},plot_bgcolor:\"#343a40\",yaxis:{tickformat:\".4~s\",exponentformat:\"B\",ticksuffix:\"B\"},showlegend:!1},{responsive:!0,displayModeBar:!1}),document.getElementById(\"smallMemoryGraph\").onclick(()=>{n()})}(memory_records);const t=[{title:\"Thread ID\",data:\"tid\"},{title:\"Size\",data:\"size\",render:function(n,t,r,e){return\"sort\"===t||\"type\"===t?n:function(n,t=1){if(Math.abs(n)<1e3)return n+\" B\";const r=[\"kB\",\"MB\",\"GB\",\"TB\",\"PB\",\"EB\",\"ZB\",\"YB\"];let e=-1;const u=10**t;do{n/=1e3,++e}while(Math.round(Math.abs(n)*u)/u>=1e3&&e<r.length-1);return n.toFixed(t)+\" \"+r[e]}(n)}},{title:\"Allocator\",data:\"allocator\"},{title:\"Allocations\",data:\"n_allocations\"},{title:\"Location\",data:\"stack_trace\"}];var r=$(\"#the_table\").DataTable({data,columns:t,order:[[2,\"desc\"]],pageLength:100,dom:\"<t>ip\"});$(\"#searchTerm\").on(\"input\",()=>{const n=$(\"#searchTerm\").val();r.search(n).draw()}),$('[data-toggle-second=\"tooltip\"]').tooltip(),$('[data-toggle=\"tooltip\"]').tooltip()}),n()})()})();"
  },
  {
    "path": "src/memray/reporters/templates/assets/temporal_flamegraph.js",
    "content": "(()=>{var t={543(t,n,e){var r;\n/**\n * @license\n * Lodash <https://lodash.com/>\n * Copyright OpenJS Foundation and other contributors <https://openjsf.org/>\n * Released under MIT license <https://lodash.com/license>\n * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>\n * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n */t=e.nmd(t),function(){var i,o=\"Expected a function\",u=\"__lodash_hash_undefined__\",a=\"__lodash_placeholder__\",c=16,l=32,f=64,s=128,h=256,p=1/0,d=9007199254740991,v=NaN,g=4294967295,_=[[\"ary\",s],[\"bind\",1],[\"bindKey\",2],[\"curry\",8],[\"curryRight\",c],[\"flip\",512],[\"partial\",l],[\"partialRight\",f],[\"rearg\",h]],y=\"[object Arguments]\",m=\"[object Array]\",w=\"[object Boolean]\",b=\"[object Date]\",x=\"[object Error]\",I=\"[object Function]\",E=\"[object GeneratorFunction]\",A=\"[object Map]\",R=\"[object Number]\",j=\"[object Object]\",k=\"[object Promise]\",O=\"[object RegExp]\",S=\"[object Set]\",L=\"[object String]\",T=\"[object Symbol]\",B=\"[object WeakMap]\",D=\"[object ArrayBuffer]\",C=\"[object DataView]\",z=\"[object Float32Array]\",F=\"[object Float64Array]\",W=\"[object Int8Array]\",P=\"[object Int16Array]\",N=\"[object Int32Array]\",$=\"[object Uint8Array]\",U=\"[object Uint8ClampedArray]\",M=\"[object Uint16Array]\",q=\"[object Uint32Array]\",H=/\\b__p \\+= '';/g,V=/\\b(__p \\+=) '' \\+/g,Z=/(__e\\(.*?\\)|\\b__t\\)) \\+\\n'';/g,K=/&(?:amp|lt|gt|quot|#39);/g,Y=/[&<>\"']/g,G=RegExp(K.source),J=RegExp(Y.source),Q=/<%-([\\s\\S]+?)%>/g,X=/<%([\\s\\S]+?)%>/g,tt=/<%=([\\s\\S]+?)%>/g,nt=/\\.|\\[(?:[^[\\]]*|([\"'])(?:(?!\\1)[^\\\\]|\\\\.)*?\\1)\\]/,et=/^\\w*$/,rt=/[^.[\\]]+|\\[(?:(-?\\d+(?:\\.\\d+)?)|([\"'])((?:(?!\\2)[^\\\\]|\\\\.)*?)\\2)\\]|(?=(?:\\.|\\[\\])(?:\\.|\\[\\]|$))/g,it=/[\\\\^$.*+?()[\\]{}|]/g,ot=RegExp(it.source),ut=/^\\s+/,at=/\\s/,ct=/\\{(?:\\n\\/\\* \\[wrapped with .+\\] \\*\\/)?\\n?/,lt=/\\{\\n\\/\\* \\[wrapped with (.+)\\] \\*/,ft=/,? & /,st=/[^\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\x7f]+/g,ht=/[()=,{}\\[\\]\\/\\s]/,pt=/\\\\(\\\\)?/g,dt=/\\$\\{([^\\\\}]*(?:\\\\.[^\\\\}]*)*)\\}/g,vt=/\\w*$/,gt=/^[-+]0x[0-9a-f]+$/i,_t=/^0b[01]+$/i,yt=/^\\[object .+?Constructor\\]$/,mt=/^0o[0-7]+$/i,wt=/^(?:0|[1-9]\\d*)$/,bt=/[\\xc0-\\xd6\\xd8-\\xf6\\xf8-\\xff\\u0100-\\u017f]/g,xt=/($^)/,It=/['\\n\\r\\u2028\\u2029\\\\]/g,Et=\"\\\\ud800-\\\\udfff\",At=\"\\\\u0300-\\\\u036f\\\\ufe20-\\\\ufe2f\\\\u20d0-\\\\u20ff\",Rt=\"\\\\u2700-\\\\u27bf\",jt=\"a-z\\\\xdf-\\\\xf6\\\\xf8-\\\\xff\",kt=\"A-Z\\\\xc0-\\\\xd6\\\\xd8-\\\\xde\",Ot=\"\\\\ufe0e\\\\ufe0f\",St=\"\\\\xac\\\\xb1\\\\xd7\\\\xf7\\\\x00-\\\\x2f\\\\x3a-\\\\x40\\\\x5b-\\\\x60\\\\x7b-\\\\xbf\\\\u2000-\\\\u206f \\\\t\\\\x0b\\\\f\\\\xa0\\\\ufeff\\\\n\\\\r\\\\u2028\\\\u2029\\\\u1680\\\\u180e\\\\u2000\\\\u2001\\\\u2002\\\\u2003\\\\u2004\\\\u2005\\\\u2006\\\\u2007\\\\u2008\\\\u2009\\\\u200a\\\\u202f\\\\u205f\\\\u3000\",Lt=\"['’]\",Tt=\"[\"+Et+\"]\",Bt=\"[\"+St+\"]\",Dt=\"[\"+At+\"]\",Ct=\"\\\\d+\",zt=\"[\"+Rt+\"]\",Ft=\"[\"+jt+\"]\",Wt=\"[^\"+Et+St+Ct+Rt+jt+kt+\"]\",Pt=\"\\\\ud83c[\\\\udffb-\\\\udfff]\",Nt=\"[^\"+Et+\"]\",$t=\"(?:\\\\ud83c[\\\\udde6-\\\\uddff]){2}\",Ut=\"[\\\\ud800-\\\\udbff][\\\\udc00-\\\\udfff]\",Mt=\"[\"+kt+\"]\",qt=\"\\\\u200d\",Ht=\"(?:\"+Ft+\"|\"+Wt+\")\",Vt=\"(?:\"+Mt+\"|\"+Wt+\")\",Zt=\"(?:['’](?:d|ll|m|re|s|t|ve))?\",Kt=\"(?:['’](?:D|LL|M|RE|S|T|VE))?\",Yt=\"(?:\"+Dt+\"|\"+Pt+\")\"+\"?\",Gt=\"[\"+Ot+\"]?\",Jt=Gt+Yt+(\"(?:\"+qt+\"(?:\"+[Nt,$t,Ut].join(\"|\")+\")\"+Gt+Yt+\")*\"),Qt=\"(?:\"+[zt,$t,Ut].join(\"|\")+\")\"+Jt,Xt=\"(?:\"+[Nt+Dt+\"?\",Dt,$t,Ut,Tt].join(\"|\")+\")\",tn=RegExp(Lt,\"g\"),nn=RegExp(Dt,\"g\"),en=RegExp(Pt+\"(?=\"+Pt+\")|\"+Xt+Jt,\"g\"),rn=RegExp([Mt+\"?\"+Ft+\"+\"+Zt+\"(?=\"+[Bt,Mt,\"$\"].join(\"|\")+\")\",Vt+\"+\"+Kt+\"(?=\"+[Bt,Mt+Ht,\"$\"].join(\"|\")+\")\",Mt+\"?\"+Ht+\"+\"+Zt,Mt+\"+\"+Kt,\"\\\\d*(?:1ST|2ND|3RD|(?![123])\\\\dTH)(?=\\\\b|[a-z_])\",\"\\\\d*(?:1st|2nd|3rd|(?![123])\\\\dth)(?=\\\\b|[A-Z_])\",Ct,Qt].join(\"|\"),\"g\"),on=RegExp(\"[\"+qt+Et+At+Ot+\"]\"),un=/[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/,an=[\"Array\",\"Buffer\",\"DataView\",\"Date\",\"Error\",\"Float32Array\",\"Float64Array\",\"Function\",\"Int8Array\",\"Int16Array\",\"Int32Array\",\"Map\",\"Math\",\"Object\",\"Promise\",\"RegExp\",\"Set\",\"String\",\"Symbol\",\"TypeError\",\"Uint8Array\",\"Uint8ClampedArray\",\"Uint16Array\",\"Uint32Array\",\"WeakMap\",\"_\",\"clearTimeout\",\"isFinite\",\"parseInt\",\"setTimeout\"],cn=-1,ln={};ln[z]=ln[F]=ln[W]=ln[P]=ln[N]=ln[$]=ln[U]=ln[M]=ln[q]=!0,ln[y]=ln[m]=ln[D]=ln[w]=ln[C]=ln[b]=ln[x]=ln[I]=ln[A]=ln[R]=ln[j]=ln[O]=ln[S]=ln[L]=ln[B]=!1;var fn={};fn[y]=fn[m]=fn[D]=fn[C]=fn[w]=fn[b]=fn[z]=fn[F]=fn[W]=fn[P]=fn[N]=fn[A]=fn[R]=fn[j]=fn[O]=fn[S]=fn[L]=fn[T]=fn[$]=fn[U]=fn[M]=fn[q]=!0,fn[x]=fn[I]=fn[B]=!1;var sn={\"\\\\\":\"\\\\\",\"'\":\"'\",\"\\n\":\"n\",\"\\r\":\"r\",\"\\u2028\":\"u2028\",\"\\u2029\":\"u2029\"},hn=parseFloat,pn=parseInt,dn=\"object\"==typeof e.g&&e.g&&e.g.Object===Object&&e.g,vn=\"object\"==typeof self&&self&&self.Object===Object&&self,gn=dn||vn||Function(\"return this\")(),_n=n&&!n.nodeType&&n,yn=_n&&t&&!t.nodeType&&t,mn=yn&&yn.exports===_n,wn=mn&&dn.process,bn=function(){try{var t=yn&&yn.require&&yn.require(\"util\").types;return t||wn&&wn.binding&&wn.binding(\"util\")}catch(t){}}(),xn=bn&&bn.isArrayBuffer,In=bn&&bn.isDate,En=bn&&bn.isMap,An=bn&&bn.isRegExp,Rn=bn&&bn.isSet,jn=bn&&bn.isTypedArray;function kn(t,n,e){switch(e.length){case 0:return t.call(n);case 1:return t.call(n,e[0]);case 2:return t.call(n,e[0],e[1]);case 3:return t.call(n,e[0],e[1],e[2])}return t.apply(n,e)}function On(t,n,e,r){for(var i=-1,o=null==t?0:t.length;++i<o;){var u=t[i];n(r,u,e(u),t)}return r}function Sn(t,n){for(var e=-1,r=null==t?0:t.length;++e<r&&!1!==n(t[e],e,t););return t}function Ln(t,n){for(var e=null==t?0:t.length;e--&&!1!==n(t[e],e,t););return t}function Tn(t,n){for(var e=-1,r=null==t?0:t.length;++e<r;)if(!n(t[e],e,t))return!1;return!0}function Bn(t,n){for(var e=-1,r=null==t?0:t.length,i=0,o=[];++e<r;){var u=t[e];n(u,e,t)&&(o[i++]=u)}return o}function Dn(t,n){return!!(null==t?0:t.length)&&qn(t,n,0)>-1}function Cn(t,n,e){for(var r=-1,i=null==t?0:t.length;++r<i;)if(e(n,t[r]))return!0;return!1}function zn(t,n){for(var e=-1,r=null==t?0:t.length,i=Array(r);++e<r;)i[e]=n(t[e],e,t);return i}function Fn(t,n){for(var e=-1,r=n.length,i=t.length;++e<r;)t[i+e]=n[e];return t}function Wn(t,n,e,r){var i=-1,o=null==t?0:t.length;for(r&&o&&(e=t[++i]);++i<o;)e=n(e,t[i],i,t);return e}function Pn(t,n,e,r){var i=null==t?0:t.length;for(r&&i&&(e=t[--i]);i--;)e=n(e,t[i],i,t);return e}function Nn(t,n){for(var e=-1,r=null==t?0:t.length;++e<r;)if(n(t[e],e,t))return!0;return!1}var $n=Kn(\"length\");function Un(t,n,e){var r;return e(t,function(t,e,i){if(n(t,e,i))return r=e,!1}),r}function Mn(t,n,e,r){for(var i=t.length,o=e+(r?1:-1);r?o--:++o<i;)if(n(t[o],o,t))return o;return-1}function qn(t,n,e){return n==n?function(t,n,e){var r=e-1,i=t.length;for(;++r<i;)if(t[r]===n)return r;return-1}(t,n,e):Mn(t,Vn,e)}function Hn(t,n,e,r){for(var i=e-1,o=t.length;++i<o;)if(r(t[i],n))return i;return-1}function Vn(t){return t!=t}function Zn(t,n){var e=null==t?0:t.length;return e?Jn(t,n)/e:v}function Kn(t){return function(n){return null==n?i:n[t]}}function Yn(t){return function(n){return null==t?i:t[n]}}function Gn(t,n,e,r,i){return i(t,function(t,i,o){e=r?(r=!1,t):n(e,t,i,o)}),e}function Jn(t,n){for(var e,r=-1,o=t.length;++r<o;){var u=n(t[r]);u!==i&&(e=e===i?u:e+u)}return e}function Qn(t,n){for(var e=-1,r=Array(t);++e<t;)r[e]=n(e);return r}function Xn(t){return t?t.slice(0,ge(t)+1).replace(ut,\"\"):t}function te(t){return function(n){return t(n)}}function ne(t,n){return zn(n,function(n){return t[n]})}function ee(t,n){return t.has(n)}function re(t,n){for(var e=-1,r=t.length;++e<r&&qn(n,t[e],0)>-1;);return e}function ie(t,n){for(var e=t.length;e--&&qn(n,t[e],0)>-1;);return e}var oe=Yn({À:\"A\",Á:\"A\",Â:\"A\",Ã:\"A\",Ä:\"A\",Å:\"A\",à:\"a\",á:\"a\",â:\"a\",ã:\"a\",ä:\"a\",å:\"a\",Ç:\"C\",ç:\"c\",Ð:\"D\",ð:\"d\",È:\"E\",É:\"E\",Ê:\"E\",Ë:\"E\",è:\"e\",é:\"e\",ê:\"e\",ë:\"e\",Ì:\"I\",Í:\"I\",Î:\"I\",Ï:\"I\",ì:\"i\",í:\"i\",î:\"i\",ï:\"i\",Ñ:\"N\",ñ:\"n\",Ò:\"O\",Ó:\"O\",Ô:\"O\",Õ:\"O\",Ö:\"O\",Ø:\"O\",ò:\"o\",ó:\"o\",ô:\"o\",õ:\"o\",ö:\"o\",ø:\"o\",Ù:\"U\",Ú:\"U\",Û:\"U\",Ü:\"U\",ù:\"u\",ú:\"u\",û:\"u\",ü:\"u\",Ý:\"Y\",ý:\"y\",ÿ:\"y\",Æ:\"Ae\",æ:\"ae\",Þ:\"Th\",þ:\"th\",ß:\"ss\",Ā:\"A\",Ă:\"A\",Ą:\"A\",ā:\"a\",ă:\"a\",ą:\"a\",Ć:\"C\",Ĉ:\"C\",Ċ:\"C\",Č:\"C\",ć:\"c\",ĉ:\"c\",ċ:\"c\",č:\"c\",Ď:\"D\",Đ:\"D\",ď:\"d\",đ:\"d\",Ē:\"E\",Ĕ:\"E\",Ė:\"E\",Ę:\"E\",Ě:\"E\",ē:\"e\",ĕ:\"e\",ė:\"e\",ę:\"e\",ě:\"e\",Ĝ:\"G\",Ğ:\"G\",Ġ:\"G\",Ģ:\"G\",ĝ:\"g\",ğ:\"g\",ġ:\"g\",ģ:\"g\",Ĥ:\"H\",Ħ:\"H\",ĥ:\"h\",ħ:\"h\",Ĩ:\"I\",Ī:\"I\",Ĭ:\"I\",Į:\"I\",İ:\"I\",ĩ:\"i\",ī:\"i\",ĭ:\"i\",į:\"i\",ı:\"i\",Ĵ:\"J\",ĵ:\"j\",Ķ:\"K\",ķ:\"k\",ĸ:\"k\",Ĺ:\"L\",Ļ:\"L\",Ľ:\"L\",Ŀ:\"L\",Ł:\"L\",ĺ:\"l\",ļ:\"l\",ľ:\"l\",ŀ:\"l\",ł:\"l\",Ń:\"N\",Ņ:\"N\",Ň:\"N\",Ŋ:\"N\",ń:\"n\",ņ:\"n\",ň:\"n\",ŋ:\"n\",Ō:\"O\",Ŏ:\"O\",Ő:\"O\",ō:\"o\",ŏ:\"o\",ő:\"o\",Ŕ:\"R\",Ŗ:\"R\",Ř:\"R\",ŕ:\"r\",ŗ:\"r\",ř:\"r\",Ś:\"S\",Ŝ:\"S\",Ş:\"S\",Š:\"S\",ś:\"s\",ŝ:\"s\",ş:\"s\",š:\"s\",Ţ:\"T\",Ť:\"T\",Ŧ:\"T\",ţ:\"t\",ť:\"t\",ŧ:\"t\",Ũ:\"U\",Ū:\"U\",Ŭ:\"U\",Ů:\"U\",Ű:\"U\",Ų:\"U\",ũ:\"u\",ū:\"u\",ŭ:\"u\",ů:\"u\",ű:\"u\",ų:\"u\",Ŵ:\"W\",ŵ:\"w\",Ŷ:\"Y\",ŷ:\"y\",Ÿ:\"Y\",Ź:\"Z\",Ż:\"Z\",Ž:\"Z\",ź:\"z\",ż:\"z\",ž:\"z\",Ĳ:\"IJ\",ĳ:\"ij\",Œ:\"Oe\",œ:\"oe\",ŉ:\"'n\",ſ:\"s\"}),ue=Yn({\"&\":\"&amp;\",\"<\":\"&lt;\",\">\":\"&gt;\",'\"':\"&quot;\",\"'\":\"&#39;\"});function ae(t){return\"\\\\\"+sn[t]}function ce(t){return on.test(t)}function le(t){var n=-1,e=Array(t.size);return t.forEach(function(t,r){e[++n]=[r,t]}),e}function fe(t,n){return function(e){return t(n(e))}}function se(t,n){for(var e=-1,r=t.length,i=0,o=[];++e<r;){var u=t[e];u!==n&&u!==a||(t[e]=a,o[i++]=e)}return o}function he(t){var n=-1,e=Array(t.size);return t.forEach(function(t){e[++n]=t}),e}function pe(t){var n=-1,e=Array(t.size);return t.forEach(function(t){e[++n]=[t,t]}),e}function de(t){return ce(t)?function(t){var n=en.lastIndex=0;for(;en.test(t);)++n;return n}(t):$n(t)}function ve(t){return ce(t)?function(t){return t.match(en)||[]}(t):function(t){return t.split(\"\")}(t)}function ge(t){for(var n=t.length;n--&&at.test(t.charAt(n)););return n}var _e=Yn({\"&amp;\":\"&\",\"&lt;\":\"<\",\"&gt;\":\">\",\"&quot;\":'\"',\"&#39;\":\"'\"});var ye=function t(n){var e,r=(n=null==n?gn:ye.defaults(gn.Object(),n,ye.pick(gn,an))).Array,at=n.Date,Et=n.Error,At=n.Function,Rt=n.Math,jt=n.Object,kt=n.RegExp,Ot=n.String,St=n.TypeError,Lt=r.prototype,Tt=At.prototype,Bt=jt.prototype,Dt=n[\"__core-js_shared__\"],Ct=Tt.toString,zt=Bt.hasOwnProperty,Ft=0,Wt=(e=/[^.]+$/.exec(Dt&&Dt.keys&&Dt.keys.IE_PROTO||\"\"))?\"Symbol(src)_1.\"+e:\"\",Pt=Bt.toString,Nt=Ct.call(jt),$t=gn._,Ut=kt(\"^\"+Ct.call(zt).replace(it,\"\\\\$&\").replace(/hasOwnProperty|(function).*?(?=\\\\\\()| for .+?(?=\\\\\\])/g,\"$1.*?\")+\"$\"),Mt=mn?n.Buffer:i,qt=n.Symbol,Ht=n.Uint8Array,Vt=Mt?Mt.allocUnsafe:i,Zt=fe(jt.getPrototypeOf,jt),Kt=jt.create,Yt=Bt.propertyIsEnumerable,Gt=Lt.splice,Jt=qt?qt.isConcatSpreadable:i,Qt=qt?qt.iterator:i,Xt=qt?qt.toStringTag:i,en=function(){try{var t=ho(jt,\"defineProperty\");return t({},\"\",{}),t}catch(t){}}(),on=n.clearTimeout!==gn.clearTimeout&&n.clearTimeout,sn=at&&at.now!==gn.Date.now&&at.now,dn=n.setTimeout!==gn.setTimeout&&n.setTimeout,vn=Rt.ceil,_n=Rt.floor,yn=jt.getOwnPropertySymbols,wn=Mt?Mt.isBuffer:i,bn=n.isFinite,$n=Lt.join,Yn=fe(jt.keys,jt),me=Rt.max,we=Rt.min,be=at.now,xe=n.parseInt,Ie=Rt.random,Ee=Lt.reverse,Ae=ho(n,\"DataView\"),Re=ho(n,\"Map\"),je=ho(n,\"Promise\"),ke=ho(n,\"Set\"),Oe=ho(n,\"WeakMap\"),Se=ho(jt,\"create\"),Le=Oe&&new Oe,Te={},Be=Po(Ae),De=Po(Re),Ce=Po(je),ze=Po(ke),Fe=Po(Oe),We=qt?qt.prototype:i,Pe=We?We.valueOf:i,Ne=We?We.toString:i;function $e(t){if(ea(t)&&!Hu(t)&&!(t instanceof He)){if(t instanceof qe)return t;if(zt.call(t,\"__wrapped__\"))return No(t)}return new qe(t)}var Ue=function(){function t(){}return function(n){if(!na(n))return{};if(Kt)return Kt(n);t.prototype=n;var e=new t;return t.prototype=i,e}}();function Me(){}function qe(t,n){this.__wrapped__=t,this.__actions__=[],this.__chain__=!!n,this.__index__=0,this.__values__=i}function He(t){this.__wrapped__=t,this.__actions__=[],this.__dir__=1,this.__filtered__=!1,this.__iteratees__=[],this.__takeCount__=g,this.__views__=[]}function Ve(t){var n=-1,e=null==t?0:t.length;for(this.clear();++n<e;){var r=t[n];this.set(r[0],r[1])}}function Ze(t){var n=-1,e=null==t?0:t.length;for(this.clear();++n<e;){var r=t[n];this.set(r[0],r[1])}}function Ke(t){var n=-1,e=null==t?0:t.length;for(this.clear();++n<e;){var r=t[n];this.set(r[0],r[1])}}function Ye(t){var n=-1,e=null==t?0:t.length;for(this.__data__=new Ke;++n<e;)this.add(t[n])}function Ge(t){var n=this.__data__=new Ze(t);this.size=n.size}function Je(t,n){var e=Hu(t),r=!e&&qu(t),i=!e&&!r&&Yu(t),o=!e&&!r&&!i&&fa(t),u=e||r||i||o,a=u?Qn(t.length,Ot):[],c=a.length;for(var l in t)!n&&!zt.call(t,l)||u&&(\"length\"==l||i&&(\"offset\"==l||\"parent\"==l)||o&&(\"buffer\"==l||\"byteLength\"==l||\"byteOffset\"==l)||wo(l,c))||a.push(l);return a}function Qe(t){var n=t.length;return n?t[Yr(0,n-1)]:i}function Xe(t,n){return zo(Si(t),cr(n,0,t.length))}function tr(t){return zo(Si(t))}function nr(t,n,e){(e!==i&&!$u(t[n],e)||e===i&&!(n in t))&&ur(t,n,e)}function er(t,n,e){var r=t[n];zt.call(t,n)&&$u(r,e)&&(e!==i||n in t)||ur(t,n,e)}function rr(t,n){for(var e=t.length;e--;)if($u(t[e][0],n))return e;return-1}function ir(t,n,e,r){return pr(t,function(t,i,o){n(r,t,e(t),o)}),r}function or(t,n){return t&&Li(n,Ta(n),t)}function ur(t,n,e){\"__proto__\"==n&&en?en(t,n,{configurable:!0,enumerable:!0,value:e,writable:!0}):t[n]=e}function ar(t,n){for(var e=-1,o=n.length,u=r(o),a=null==t;++e<o;)u[e]=a?i:ja(t,n[e]);return u}function cr(t,n,e){return t==t&&(e!==i&&(t=t<=e?t:e),n!==i&&(t=t>=n?t:n)),t}function lr(t,n,e,r,o,u){var a,c=1&n,l=2&n,f=4&n;if(e&&(a=o?e(t,r,o,u):e(t)),a!==i)return a;if(!na(t))return t;var s=Hu(t);if(s){if(a=function(t){var n=t.length,e=new t.constructor(n);n&&\"string\"==typeof t[0]&&zt.call(t,\"index\")&&(e.index=t.index,e.input=t.input);return e}(t),!c)return Si(t,a)}else{var h=go(t),p=h==I||h==E;if(Yu(t))return Ei(t,c);if(h==j||h==y||p&&!o){if(a=l||p?{}:yo(t),!c)return l?function(t,n){return Li(t,vo(t),n)}(t,function(t,n){return t&&Li(n,Ba(n),t)}(a,t)):function(t,n){return Li(t,po(t),n)}(t,or(a,t))}else{if(!fn[h])return o?t:{};a=function(t,n,e){var r=t.constructor;switch(n){case D:return Ai(t);case w:case b:return new r(+t);case C:return function(t,n){var e=n?Ai(t.buffer):t.buffer;return new t.constructor(e,t.byteOffset,t.byteLength)}(t,e);case z:case F:case W:case P:case N:case $:case U:case M:case q:return Ri(t,e);case A:return new r;case R:case L:return new r(t);case O:return function(t){var n=new t.constructor(t.source,vt.exec(t));return n.lastIndex=t.lastIndex,n}(t);case S:return new r;case T:return i=t,Pe?jt(Pe.call(i)):{}}var i}(t,h,c)}}u||(u=new Ge);var d=u.get(t);if(d)return d;u.set(t,a),aa(t)?t.forEach(function(r){a.add(lr(r,n,e,r,t,u))}):ra(t)&&t.forEach(function(r,i){a.set(i,lr(r,n,e,i,t,u))});var v=s?i:(f?l?oo:io:l?Ba:Ta)(t);return Sn(v||t,function(r,i){v&&(r=t[i=r]),er(a,i,lr(r,n,e,i,t,u))}),a}function fr(t,n,e){var r=e.length;if(null==t)return!r;for(t=jt(t);r--;){var o=e[r],u=n[o],a=t[o];if(a===i&&!(o in t)||!u(a))return!1}return!0}function sr(t,n,e){if(\"function\"!=typeof t)throw new St(o);return To(function(){t.apply(i,e)},n)}function hr(t,n,e,r){var i=-1,o=Dn,u=!0,a=t.length,c=[],l=n.length;if(!a)return c;e&&(n=zn(n,te(e))),r?(o=Cn,u=!1):n.length>=200&&(o=ee,u=!1,n=new Ye(n));t:for(;++i<a;){var f=t[i],s=null==e?f:e(f);if(f=r||0!==f?f:0,u&&s==s){for(var h=l;h--;)if(n[h]===s)continue t;c.push(f)}else o(n,s,r)||c.push(f)}return c}$e.templateSettings={escape:Q,evaluate:X,interpolate:tt,variable:\"\",imports:{_:$e}},$e.prototype=Me.prototype,$e.prototype.constructor=$e,qe.prototype=Ue(Me.prototype),qe.prototype.constructor=qe,He.prototype=Ue(Me.prototype),He.prototype.constructor=He,Ve.prototype.clear=function(){this.__data__=Se?Se(null):{},this.size=0},Ve.prototype.delete=function(t){var n=this.has(t)&&delete this.__data__[t];return this.size-=n?1:0,n},Ve.prototype.get=function(t){var n=this.__data__;if(Se){var e=n[t];return e===u?i:e}return zt.call(n,t)?n[t]:i},Ve.prototype.has=function(t){var n=this.__data__;return Se?n[t]!==i:zt.call(n,t)},Ve.prototype.set=function(t,n){var e=this.__data__;return this.size+=this.has(t)?0:1,e[t]=Se&&n===i?u:n,this},Ze.prototype.clear=function(){this.__data__=[],this.size=0},Ze.prototype.delete=function(t){var n=this.__data__,e=rr(n,t);return!(e<0)&&(e==n.length-1?n.pop():Gt.call(n,e,1),--this.size,!0)},Ze.prototype.get=function(t){var n=this.__data__,e=rr(n,t);return e<0?i:n[e][1]},Ze.prototype.has=function(t){return rr(this.__data__,t)>-1},Ze.prototype.set=function(t,n){var e=this.__data__,r=rr(e,t);return r<0?(++this.size,e.push([t,n])):e[r][1]=n,this},Ke.prototype.clear=function(){this.size=0,this.__data__={hash:new Ve,map:new(Re||Ze),string:new Ve}},Ke.prototype.delete=function(t){var n=fo(this,t).delete(t);return this.size-=n?1:0,n},Ke.prototype.get=function(t){return fo(this,t).get(t)},Ke.prototype.has=function(t){return fo(this,t).has(t)},Ke.prototype.set=function(t,n){var e=fo(this,t),r=e.size;return e.set(t,n),this.size+=e.size==r?0:1,this},Ye.prototype.add=Ye.prototype.push=function(t){return this.__data__.set(t,u),this},Ye.prototype.has=function(t){return this.__data__.has(t)},Ge.prototype.clear=function(){this.__data__=new Ze,this.size=0},Ge.prototype.delete=function(t){var n=this.__data__,e=n.delete(t);return this.size=n.size,e},Ge.prototype.get=function(t){return this.__data__.get(t)},Ge.prototype.has=function(t){return this.__data__.has(t)},Ge.prototype.set=function(t,n){var e=this.__data__;if(e instanceof Ze){var r=e.__data__;if(!Re||r.length<199)return r.push([t,n]),this.size=++e.size,this;e=this.__data__=new Ke(r)}return e.set(t,n),this.size=e.size,this};var pr=Di(br),dr=Di(xr,!0);function vr(t,n){var e=!0;return pr(t,function(t,r,i){return e=!!n(t,r,i)}),e}function gr(t,n,e){for(var r=-1,o=t.length;++r<o;){var u=t[r],a=n(u);if(null!=a&&(c===i?a==a&&!la(a):e(a,c)))var c=a,l=u}return l}function _r(t,n){var e=[];return pr(t,function(t,r,i){n(t,r,i)&&e.push(t)}),e}function yr(t,n,e,r,i){var o=-1,u=t.length;for(e||(e=mo),i||(i=[]);++o<u;){var a=t[o];n>0&&e(a)?n>1?yr(a,n-1,e,r,i):Fn(i,a):r||(i[i.length]=a)}return i}var mr=Ci(),wr=Ci(!0);function br(t,n){return t&&mr(t,n,Ta)}function xr(t,n){return t&&wr(t,n,Ta)}function Ir(t,n){return Bn(n,function(n){return Qu(t[n])})}function Er(t,n){for(var e=0,r=(n=wi(n,t)).length;null!=t&&e<r;)t=t[Wo(n[e++])];return e&&e==r?t:i}function Ar(t,n,e){var r=n(t);return Hu(t)?r:Fn(r,e(t))}function Rr(t){return null==t?t===i?\"[object Undefined]\":\"[object Null]\":Xt&&Xt in jt(t)?function(t){var n=zt.call(t,Xt),e=t[Xt];try{t[Xt]=i;var r=!0}catch(t){}var o=Pt.call(t);r&&(n?t[Xt]=e:delete t[Xt]);return o}(t):function(t){return Pt.call(t)}(t)}function jr(t,n){return t>n}function kr(t,n){return null!=t&&zt.call(t,n)}function Or(t,n){return null!=t&&n in jt(t)}function Sr(t,n,e){for(var o=e?Cn:Dn,u=t[0].length,a=t.length,c=a,l=r(a),f=1/0,s=[];c--;){var h=t[c];c&&n&&(h=zn(h,te(n))),f=we(h.length,f),l[c]=!e&&(n||u>=120&&h.length>=120)?new Ye(c&&h):i}h=t[0];var p=-1,d=l[0];t:for(;++p<u&&s.length<f;){var v=h[p],g=n?n(v):v;if(v=e||0!==v?v:0,!(d?ee(d,g):o(s,g,e))){for(c=a;--c;){var _=l[c];if(!(_?ee(_,g):o(t[c],g,e)))continue t}d&&d.push(g),s.push(v)}}return s}function Lr(t,n,e){var r=null==(t=Oo(t,n=wi(n,t)))?t:t[Wo(Jo(n))];return null==r?i:kn(r,t,e)}function Tr(t){return ea(t)&&Rr(t)==y}function Br(t,n,e,r,o){return t===n||(null==t||null==n||!ea(t)&&!ea(n)?t!=t&&n!=n:function(t,n,e,r,o,u){var a=Hu(t),c=Hu(n),l=a?m:go(t),f=c?m:go(n),s=(l=l==y?j:l)==j,h=(f=f==y?j:f)==j,p=l==f;if(p&&Yu(t)){if(!Yu(n))return!1;a=!0,s=!1}if(p&&!s)return u||(u=new Ge),a||fa(t)?eo(t,n,e,r,o,u):function(t,n,e,r,i,o,u){switch(e){case C:if(t.byteLength!=n.byteLength||t.byteOffset!=n.byteOffset)return!1;t=t.buffer,n=n.buffer;case D:return!(t.byteLength!=n.byteLength||!o(new Ht(t),new Ht(n)));case w:case b:case R:return $u(+t,+n);case x:return t.name==n.name&&t.message==n.message;case O:case L:return t==n+\"\";case A:var a=le;case S:var c=1&r;if(a||(a=he),t.size!=n.size&&!c)return!1;var l=u.get(t);if(l)return l==n;r|=2,u.set(t,n);var f=eo(a(t),a(n),r,i,o,u);return u.delete(t),f;case T:if(Pe)return Pe.call(t)==Pe.call(n)}return!1}(t,n,l,e,r,o,u);if(!(1&e)){var d=s&&zt.call(t,\"__wrapped__\"),v=h&&zt.call(n,\"__wrapped__\");if(d||v){var g=d?t.value():t,_=v?n.value():n;return u||(u=new Ge),o(g,_,e,r,u)}}if(!p)return!1;return u||(u=new Ge),function(t,n,e,r,o,u){var a=1&e,c=io(t),l=c.length,f=io(n),s=f.length;if(l!=s&&!a)return!1;var h=l;for(;h--;){var p=c[h];if(!(a?p in n:zt.call(n,p)))return!1}var d=u.get(t),v=u.get(n);if(d&&v)return d==n&&v==t;var g=!0;u.set(t,n),u.set(n,t);var _=a;for(;++h<l;){var y=t[p=c[h]],m=n[p];if(r)var w=a?r(m,y,p,n,t,u):r(y,m,p,t,n,u);if(!(w===i?y===m||o(y,m,e,r,u):w)){g=!1;break}_||(_=\"constructor\"==p)}if(g&&!_){var b=t.constructor,x=n.constructor;b==x||!(\"constructor\"in t)||!(\"constructor\"in n)||\"function\"==typeof b&&b instanceof b&&\"function\"==typeof x&&x instanceof x||(g=!1)}return u.delete(t),u.delete(n),g}(t,n,e,r,o,u)}(t,n,e,r,Br,o))}function Dr(t,n,e,r){var o=e.length,u=o,a=!r;if(null==t)return!u;for(t=jt(t);o--;){var c=e[o];if(a&&c[2]?c[1]!==t[c[0]]:!(c[0]in t))return!1}for(;++o<u;){var l=(c=e[o])[0],f=t[l],s=c[1];if(a&&c[2]){if(f===i&&!(l in t))return!1}else{var h=new Ge;if(r)var p=r(f,s,l,t,n,h);if(!(p===i?Br(s,f,3,r,h):p))return!1}}return!0}function Cr(t){return!(!na(t)||(n=t,Wt&&Wt in n))&&(Qu(t)?Ut:yt).test(Po(t));var n}function zr(t){return\"function\"==typeof t?t:null==t?ic:\"object\"==typeof t?Hu(t)?Ur(t[0],t[1]):$r(t):pc(t)}function Fr(t){if(!Ao(t))return Yn(t);var n=[];for(var e in jt(t))zt.call(t,e)&&\"constructor\"!=e&&n.push(e);return n}function Wr(t){if(!na(t))return function(t){var n=[];if(null!=t)for(var e in jt(t))n.push(e);return n}(t);var n=Ao(t),e=[];for(var r in t)(\"constructor\"!=r||!n&&zt.call(t,r))&&e.push(r);return e}function Pr(t,n){return t<n}function Nr(t,n){var e=-1,i=Zu(t)?r(t.length):[];return pr(t,function(t,r,o){i[++e]=n(t,r,o)}),i}function $r(t){var n=so(t);return 1==n.length&&n[0][2]?jo(n[0][0],n[0][1]):function(e){return e===t||Dr(e,t,n)}}function Ur(t,n){return xo(t)&&Ro(n)?jo(Wo(t),n):function(e){var r=ja(e,t);return r===i&&r===n?ka(e,t):Br(n,r,3)}}function Mr(t,n,e,r,o){t!==n&&mr(n,function(u,a){if(o||(o=new Ge),na(u))!function(t,n,e,r,o,u,a){var c=So(t,e),l=So(n,e),f=a.get(l);if(f)return void nr(t,e,f);var s=u?u(c,l,e+\"\",t,n,a):i,h=s===i;if(h){var p=Hu(l),d=!p&&Yu(l),v=!p&&!d&&fa(l);s=l,p||d||v?Hu(c)?s=c:Ku(c)?s=Si(c):d?(h=!1,s=Ei(l,!0)):v?(h=!1,s=Ri(l,!0)):s=[]:oa(l)||qu(l)?(s=c,qu(c)?s=ya(c):na(c)&&!Qu(c)||(s=yo(l))):h=!1}h&&(a.set(l,s),o(s,l,r,u,a),a.delete(l));nr(t,e,s)}(t,n,a,e,Mr,r,o);else{var c=r?r(So(t,a),u,a+\"\",t,n,o):i;c===i&&(c=u),nr(t,a,c)}},Ba)}function qr(t,n){var e=t.length;if(e)return wo(n+=n<0?e:0,e)?t[n]:i}function Hr(t,n,e){n=n.length?zn(n,function(t){return Hu(t)?function(n){return Er(n,1===t.length?t[0]:t)}:t}):[ic];var r=-1;n=zn(n,te(lo()));var i=Nr(t,function(t,e,i){var o=zn(n,function(n){return n(t)});return{criteria:o,index:++r,value:t}});return function(t,n){var e=t.length;for(t.sort(n);e--;)t[e]=t[e].value;return t}(i,function(t,n){return function(t,n,e){var r=-1,i=t.criteria,o=n.criteria,u=i.length,a=e.length;for(;++r<u;){var c=ji(i[r],o[r]);if(c)return r>=a?c:c*(\"desc\"==e[r]?-1:1)}return t.index-n.index}(t,n,e)})}function Vr(t,n,e){for(var r=-1,i=n.length,o={};++r<i;){var u=n[r],a=Er(t,u);e(a,u)&&ti(o,wi(u,t),a)}return o}function Zr(t,n,e,r){var i=r?Hn:qn,o=-1,u=n.length,a=t;for(t===n&&(n=Si(n)),e&&(a=zn(t,te(e)));++o<u;)for(var c=0,l=n[o],f=e?e(l):l;(c=i(a,f,c,r))>-1;)a!==t&&Gt.call(a,c,1),Gt.call(t,c,1);return t}function Kr(t,n){for(var e=t?n.length:0,r=e-1;e--;){var i=n[e];if(e==r||i!==o){var o=i;wo(i)?Gt.call(t,i,1):hi(t,i)}}return t}function Yr(t,n){return t+_n(Ie()*(n-t+1))}function Gr(t,n){var e=\"\";if(!t||n<1||n>d)return e;do{n%2&&(e+=t),(n=_n(n/2))&&(t+=t)}while(n);return e}function Jr(t,n){return Bo(ko(t,n,ic),t+\"\")}function Qr(t){return Qe($a(t))}function Xr(t,n){var e=$a(t);return zo(e,cr(n,0,e.length))}function ti(t,n,e,r){if(!na(t))return t;for(var o=-1,u=(n=wi(n,t)).length,a=u-1,c=t;null!=c&&++o<u;){var l=Wo(n[o]),f=e;if(\"__proto__\"===l||\"constructor\"===l||\"prototype\"===l)return t;if(o!=a){var s=c[l];(f=r?r(s,l,c):i)===i&&(f=na(s)?s:wo(n[o+1])?[]:{})}er(c,l,f),c=c[l]}return t}var ni=Le?function(t,n){return Le.set(t,n),t}:ic,ei=en?function(t,n){return en(t,\"toString\",{configurable:!0,enumerable:!1,value:nc(n),writable:!0})}:ic;function ri(t){return zo($a(t))}function ii(t,n,e){var i=-1,o=t.length;n<0&&(n=-n>o?0:o+n),(e=e>o?o:e)<0&&(e+=o),o=n>e?0:e-n>>>0,n>>>=0;for(var u=r(o);++i<o;)u[i]=t[i+n];return u}function oi(t,n){var e;return pr(t,function(t,r,i){return!(e=n(t,r,i))}),!!e}function ui(t,n,e){var r=0,i=null==t?r:t.length;if(\"number\"==typeof n&&n==n&&i<=2147483647){for(;r<i;){var o=r+i>>>1,u=t[o];null!==u&&!la(u)&&(e?u<=n:u<n)?r=o+1:i=o}return i}return ai(t,n,ic,e)}function ai(t,n,e,r){var o=0,u=null==t?0:t.length;if(0===u)return 0;for(var a=(n=e(n))!=n,c=null===n,l=la(n),f=n===i;o<u;){var s=_n((o+u)/2),h=e(t[s]),p=h!==i,d=null===h,v=h==h,g=la(h);if(a)var _=r||v;else _=f?v&&(r||p):c?v&&p&&(r||!d):l?v&&p&&!d&&(r||!g):!d&&!g&&(r?h<=n:h<n);_?o=s+1:u=s}return we(u,4294967294)}function ci(t,n){for(var e=-1,r=t.length,i=0,o=[];++e<r;){var u=t[e],a=n?n(u):u;if(!e||!$u(a,c)){var c=a;o[i++]=0===u?0:u}}return o}function li(t){return\"number\"==typeof t?t:la(t)?v:+t}function fi(t){if(\"string\"==typeof t)return t;if(Hu(t))return zn(t,fi)+\"\";if(la(t))return Ne?Ne.call(t):\"\";var n=t+\"\";return\"0\"==n&&1/t==-1/0?\"-0\":n}function si(t,n,e){var r=-1,i=Dn,o=t.length,u=!0,a=[],c=a;if(e)u=!1,i=Cn;else if(o>=200){var l=n?null:Gi(t);if(l)return he(l);u=!1,i=ee,c=new Ye}else c=n?[]:a;t:for(;++r<o;){var f=t[r],s=n?n(f):f;if(f=e||0!==f?f:0,u&&s==s){for(var h=c.length;h--;)if(c[h]===s)continue t;n&&c.push(s),a.push(f)}else i(c,s,e)||(c!==a&&c.push(s),a.push(f))}return a}function hi(t,n){var e=-1,r=(n=wi(n,t)).length;if(!r)return!0;for(var i=null==t||\"object\"!=typeof t&&\"function\"!=typeof t;++e<r;){var o=n[e];if(\"string\"==typeof o){if(\"__proto__\"===o&&!zt.call(t,\"__proto__\"))return!1;if(\"constructor\"===o&&e+1<r&&\"string\"==typeof n[e+1]&&\"prototype\"===n[e+1]){if(i&&0===e)continue;return!1}}}var u=Oo(t,n);return null==u||delete u[Wo(Jo(n))]}function pi(t,n,e,r){return ti(t,n,e(Er(t,n)),r)}function di(t,n,e,r){for(var i=t.length,o=r?i:-1;(r?o--:++o<i)&&n(t[o],o,t););return e?ii(t,r?0:o,r?o+1:i):ii(t,r?o+1:0,r?i:o)}function vi(t,n){var e=t;return e instanceof He&&(e=e.value()),Wn(n,function(t,n){return n.func.apply(n.thisArg,Fn([t],n.args))},e)}function gi(t,n,e){var i=t.length;if(i<2)return i?si(t[0]):[];for(var o=-1,u=r(i);++o<i;)for(var a=t[o],c=-1;++c<i;)c!=o&&(u[o]=hr(u[o]||a,t[c],n,e));return si(yr(u,1),n,e)}function _i(t,n,e){for(var r=-1,o=t.length,u=n.length,a={};++r<o;){var c=r<u?n[r]:i;e(a,t[r],c)}return a}function yi(t){return Ku(t)?t:[]}function mi(t){return\"function\"==typeof t?t:ic}function wi(t,n){return Hu(t)?t:xo(t,n)?[t]:Fo(ma(t))}var bi=Jr;function xi(t,n,e){var r=t.length;return e=e===i?r:e,!n&&e>=r?t:ii(t,n,e)}var Ii=on||function(t){return gn.clearTimeout(t)};function Ei(t,n){if(n)return t.slice();var e=t.length,r=Vt?Vt(e):new t.constructor(e);return t.copy(r),r}function Ai(t){var n=new t.constructor(t.byteLength);return new Ht(n).set(new Ht(t)),n}function Ri(t,n){var e=n?Ai(t.buffer):t.buffer;return new t.constructor(e,t.byteOffset,t.length)}function ji(t,n){if(t!==n){var e=t!==i,r=null===t,o=t==t,u=la(t),a=n!==i,c=null===n,l=n==n,f=la(n);if(!c&&!f&&!u&&t>n||u&&a&&l&&!c&&!f||r&&a&&l||!e&&l||!o)return 1;if(!r&&!u&&!f&&t<n||f&&e&&o&&!r&&!u||c&&e&&o||!a&&o||!l)return-1}return 0}function ki(t,n,e,i){for(var o=-1,u=t.length,a=e.length,c=-1,l=n.length,f=me(u-a,0),s=r(l+f),h=!i;++c<l;)s[c]=n[c];for(;++o<a;)(h||o<u)&&(s[e[o]]=t[o]);for(;f--;)s[c++]=t[o++];return s}function Oi(t,n,e,i){for(var o=-1,u=t.length,a=-1,c=e.length,l=-1,f=n.length,s=me(u-c,0),h=r(s+f),p=!i;++o<s;)h[o]=t[o];for(var d=o;++l<f;)h[d+l]=n[l];for(;++a<c;)(p||o<u)&&(h[d+e[a]]=t[o++]);return h}function Si(t,n){var e=-1,i=t.length;for(n||(n=r(i));++e<i;)n[e]=t[e];return n}function Li(t,n,e,r){var o=!e;e||(e={});for(var u=-1,a=n.length;++u<a;){var c=n[u],l=r?r(e[c],t[c],c,e,t):i;l===i&&(l=t[c]),o?ur(e,c,l):er(e,c,l)}return e}function Ti(t,n){return function(e,r){var i=Hu(e)?On:ir,o=n?n():{};return i(e,t,lo(r,2),o)}}function Bi(t){return Jr(function(n,e){var r=-1,o=e.length,u=o>1?e[o-1]:i,a=o>2?e[2]:i;for(u=t.length>3&&\"function\"==typeof u?(o--,u):i,a&&bo(e[0],e[1],a)&&(u=o<3?i:u,o=1),n=jt(n);++r<o;){var c=e[r];c&&t(n,c,r,u)}return n})}function Di(t,n){return function(e,r){if(null==e)return e;if(!Zu(e))return t(e,r);for(var i=e.length,o=n?i:-1,u=jt(e);(n?o--:++o<i)&&!1!==r(u[o],o,u););return e}}function Ci(t){return function(n,e,r){for(var i=-1,o=jt(n),u=r(n),a=u.length;a--;){var c=u[t?a:++i];if(!1===e(o[c],c,o))break}return n}}function zi(t){return function(n){var e=ce(n=ma(n))?ve(n):i,r=e?e[0]:n.charAt(0),o=e?xi(e,1).join(\"\"):n.slice(1);return r[t]()+o}}function Fi(t){return function(n){return Wn(Qa(qa(n).replace(tn,\"\")),t,\"\")}}function Wi(t){return function(){var n=arguments;switch(n.length){case 0:return new t;case 1:return new t(n[0]);case 2:return new t(n[0],n[1]);case 3:return new t(n[0],n[1],n[2]);case 4:return new t(n[0],n[1],n[2],n[3]);case 5:return new t(n[0],n[1],n[2],n[3],n[4]);case 6:return new t(n[0],n[1],n[2],n[3],n[4],n[5]);case 7:return new t(n[0],n[1],n[2],n[3],n[4],n[5],n[6])}var e=Ue(t.prototype),r=t.apply(e,n);return na(r)?r:e}}function Pi(t){return function(n,e,r){var o=jt(n);if(!Zu(n)){var u=lo(e,3);n=Ta(n),e=function(t){return u(o[t],t,o)}}var a=t(n,e,r);return a>-1?o[u?n[a]:a]:i}}function Ni(t){return ro(function(n){var e=n.length,r=e,u=qe.prototype.thru;for(t&&n.reverse();r--;){var a=n[r];if(\"function\"!=typeof a)throw new St(o);if(u&&!c&&\"wrapper\"==ao(a))var c=new qe([],!0)}for(r=c?r:e;++r<e;){var l=ao(a=n[r]),f=\"wrapper\"==l?uo(a):i;c=f&&Io(f[0])&&424==f[1]&&!f[4].length&&1==f[9]?c[ao(f[0])].apply(c,f[3]):1==a.length&&Io(a)?c[l]():c.thru(a)}return function(){var t=arguments,r=t[0];if(c&&1==t.length&&Hu(r))return c.plant(r).value();for(var i=0,o=e?n[i].apply(this,t):r;++i<e;)o=n[i].call(this,o);return o}})}function $i(t,n,e,o,u,a,c,l,f,h){var p=n&s,d=1&n,v=2&n,g=24&n,_=512&n,y=v?i:Wi(t);return function s(){for(var m=arguments.length,w=r(m),b=m;b--;)w[b]=arguments[b];if(g)var x=co(s),I=function(t,n){for(var e=t.length,r=0;e--;)t[e]===n&&++r;return r}(w,x);if(o&&(w=ki(w,o,u,g)),a&&(w=Oi(w,a,c,g)),m-=I,g&&m<h){var E=se(w,x);return Ki(t,n,$i,s.placeholder,e,w,E,l,f,h-m)}var A=d?e:this,R=v?A[t]:t;return m=w.length,l?w=function(t,n){var e=t.length,r=we(n.length,e),o=Si(t);for(;r--;){var u=n[r];t[r]=wo(u,e)?o[u]:i}return t}(w,l):_&&m>1&&w.reverse(),p&&f<m&&(w.length=f),this&&this!==gn&&this instanceof s&&(R=y||Wi(R)),R.apply(A,w)}}function Ui(t,n){return function(e,r){return function(t,n,e,r){return br(t,function(t,i,o){n(r,e(t),i,o)}),r}(e,t,n(r),{})}}function Mi(t,n){return function(e,r){var o;if(e===i&&r===i)return n;if(e!==i&&(o=e),r!==i){if(o===i)return r;\"string\"==typeof e||\"string\"==typeof r?(e=fi(e),r=fi(r)):(e=li(e),r=li(r)),o=t(e,r)}return o}}function qi(t){return ro(function(n){return n=zn(n,te(lo())),Jr(function(e){var r=this;return t(n,function(t){return kn(t,r,e)})})})}function Hi(t,n){var e=(n=n===i?\" \":fi(n)).length;if(e<2)return e?Gr(n,t):n;var r=Gr(n,vn(t/de(n)));return ce(n)?xi(ve(r),0,t).join(\"\"):r.slice(0,t)}function Vi(t){return function(n,e,o){return o&&\"number\"!=typeof o&&bo(n,e,o)&&(e=o=i),n=da(n),e===i?(e=n,n=0):e=da(e),function(t,n,e,i){for(var o=-1,u=me(vn((n-t)/(e||1)),0),a=r(u);u--;)a[i?u:++o]=t,t+=e;return a}(n,e,o=o===i?n<e?1:-1:da(o),t)}}function Zi(t){return function(n,e){return\"string\"==typeof n&&\"string\"==typeof e||(n=_a(n),e=_a(e)),t(n,e)}}function Ki(t,n,e,r,o,u,a,c,s,h){var p=8&n;n|=p?l:f,4&(n&=~(p?f:l))||(n&=-4);var d=[t,n,o,p?u:i,p?a:i,p?i:u,p?i:a,c,s,h],v=e.apply(i,d);return Io(t)&&Lo(v,d),v.placeholder=r,Do(v,t,n)}function Yi(t){var n=Rt[t];return function(t,e){if(t=_a(t),(e=null==e?0:we(va(e),292))&&bn(t)){var r=(ma(t)+\"e\").split(\"e\");return+((r=(ma(n(r[0]+\"e\"+(+r[1]+e)))+\"e\").split(\"e\"))[0]+\"e\"+(+r[1]-e))}return n(t)}}var Gi=ke&&1/he(new ke([,-0]))[1]==p?function(t){return new ke(t)}:lc;function Ji(t){return function(n){var e=go(n);return e==A?le(n):e==S?pe(n):function(t,n){return zn(n,function(n){return[n,t[n]]})}(n,t(n))}}function Qi(t,n,e,u,p,d,v,g){var _=2&n;if(!_&&\"function\"!=typeof t)throw new St(o);var y=u?u.length:0;if(y||(n&=-97,u=p=i),v=v===i?v:me(va(v),0),g=g===i?g:va(g),y-=p?p.length:0,n&f){var m=u,w=p;u=p=i}var b=_?i:uo(t),x=[t,n,e,u,p,m,w,d,v,g];if(b&&function(t,n){var e=t[1],r=n[1],i=e|r,o=i<131,u=r==s&&8==e||r==s&&e==h&&t[7].length<=n[8]||384==r&&n[7].length<=n[8]&&8==e;if(!o&&!u)return t;1&r&&(t[2]=n[2],i|=1&e?0:4);var c=n[3];if(c){var l=t[3];t[3]=l?ki(l,c,n[4]):c,t[4]=l?se(t[3],a):n[4]}(c=n[5])&&(l=t[5],t[5]=l?Oi(l,c,n[6]):c,t[6]=l?se(t[5],a):n[6]);(c=n[7])&&(t[7]=c);r&s&&(t[8]=null==t[8]?n[8]:we(t[8],n[8]));null==t[9]&&(t[9]=n[9]);t[0]=n[0],t[1]=i}(x,b),t=x[0],n=x[1],e=x[2],u=x[3],p=x[4],!(g=x[9]=x[9]===i?_?0:t.length:me(x[9]-y,0))&&24&n&&(n&=-25),n&&1!=n)I=8==n||n==c?function(t,n,e){var o=Wi(t);return function u(){for(var a=arguments.length,c=r(a),l=a,f=co(u);l--;)c[l]=arguments[l];var s=a<3&&c[0]!==f&&c[a-1]!==f?[]:se(c,f);return(a-=s.length)<e?Ki(t,n,$i,u.placeholder,i,c,s,i,i,e-a):kn(this&&this!==gn&&this instanceof u?o:t,this,c)}}(t,n,g):n!=l&&33!=n||p.length?$i.apply(i,x):function(t,n,e,i){var o=1&n,u=Wi(t);return function n(){for(var a=-1,c=arguments.length,l=-1,f=i.length,s=r(f+c),h=this&&this!==gn&&this instanceof n?u:t;++l<f;)s[l]=i[l];for(;c--;)s[l++]=arguments[++a];return kn(h,o?e:this,s)}}(t,n,e,u);else var I=function(t,n,e){var r=1&n,i=Wi(t);return function n(){return(this&&this!==gn&&this instanceof n?i:t).apply(r?e:this,arguments)}}(t,n,e);return Do((b?ni:Lo)(I,x),t,n)}function Xi(t,n,e,r){return t===i||$u(t,Bt[e])&&!zt.call(r,e)?n:t}function to(t,n,e,r,o,u){return na(t)&&na(n)&&(u.set(n,t),Mr(t,n,i,to,u),u.delete(n)),t}function no(t){return oa(t)?i:t}function eo(t,n,e,r,o,u){var a=1&e,c=t.length,l=n.length;if(c!=l&&!(a&&l>c))return!1;var f=u.get(t),s=u.get(n);if(f&&s)return f==n&&s==t;var h=-1,p=!0,d=2&e?new Ye:i;for(u.set(t,n),u.set(n,t);++h<c;){var v=t[h],g=n[h];if(r)var _=a?r(g,v,h,n,t,u):r(v,g,h,t,n,u);if(_!==i){if(_)continue;p=!1;break}if(d){if(!Nn(n,function(t,n){if(!ee(d,n)&&(v===t||o(v,t,e,r,u)))return d.push(n)})){p=!1;break}}else if(v!==g&&!o(v,g,e,r,u)){p=!1;break}}return u.delete(t),u.delete(n),p}function ro(t){return Bo(ko(t,i,Vo),t+\"\")}function io(t){return Ar(t,Ta,po)}function oo(t){return Ar(t,Ba,vo)}var uo=Le?function(t){return Le.get(t)}:lc;function ao(t){for(var n=t.name+\"\",e=Te[n],r=zt.call(Te,n)?e.length:0;r--;){var i=e[r],o=i.func;if(null==o||o==t)return i.name}return n}function co(t){return(zt.call($e,\"placeholder\")?$e:t).placeholder}function lo(){var t=$e.iteratee||oc;return t=t===oc?zr:t,arguments.length?t(arguments[0],arguments[1]):t}function fo(t,n){var e,r,i=t.__data__;return(\"string\"==(r=typeof(e=n))||\"number\"==r||\"symbol\"==r||\"boolean\"==r?\"__proto__\"!==e:null===e)?i[\"string\"==typeof n?\"string\":\"hash\"]:i.map}function so(t){for(var n=Ta(t),e=n.length;e--;){var r=n[e],i=t[r];n[e]=[r,i,Ro(i)]}return n}function ho(t,n){var e=function(t,n){return null==t?i:t[n]}(t,n);return Cr(e)?e:i}var po=yn?function(t){return null==t?[]:(t=jt(t),Bn(yn(t),function(n){return Yt.call(t,n)}))}:gc,vo=yn?function(t){for(var n=[];t;)Fn(n,po(t)),t=Zt(t);return n}:gc,go=Rr;function _o(t,n,e){for(var r=-1,i=(n=wi(n,t)).length,o=!1;++r<i;){var u=Wo(n[r]);if(!(o=null!=t&&e(t,u)))break;t=t[u]}return o||++r!=i?o:!!(i=null==t?0:t.length)&&ta(i)&&wo(u,i)&&(Hu(t)||qu(t))}function yo(t){return\"function\"!=typeof t.constructor||Ao(t)?{}:Ue(Zt(t))}function mo(t){return Hu(t)||qu(t)||!!(Jt&&t&&t[Jt])}function wo(t,n){var e=typeof t;return!!(n=null==n?d:n)&&(\"number\"==e||\"symbol\"!=e&&wt.test(t))&&t>-1&&t%1==0&&t<n}function bo(t,n,e){if(!na(e))return!1;var r=typeof n;return!!(\"number\"==r?Zu(e)&&wo(n,e.length):\"string\"==r&&n in e)&&$u(e[n],t)}function xo(t,n){if(Hu(t))return!1;var e=typeof t;return!(\"number\"!=e&&\"symbol\"!=e&&\"boolean\"!=e&&null!=t&&!la(t))||(et.test(t)||!nt.test(t)||null!=n&&t in jt(n))}function Io(t){var n=ao(t),e=$e[n];if(\"function\"!=typeof e||!(n in He.prototype))return!1;if(t===e)return!0;var r=uo(e);return!!r&&t===r[0]}(Ae&&go(new Ae(new ArrayBuffer(1)))!=C||Re&&go(new Re)!=A||je&&go(je.resolve())!=k||ke&&go(new ke)!=S||Oe&&go(new Oe)!=B)&&(go=function(t){var n=Rr(t),e=n==j?t.constructor:i,r=e?Po(e):\"\";if(r)switch(r){case Be:return C;case De:return A;case Ce:return k;case ze:return S;case Fe:return B}return n});var Eo=Dt?Qu:_c;function Ao(t){var n=t&&t.constructor;return t===(\"function\"==typeof n&&n.prototype||Bt)}function Ro(t){return t==t&&!na(t)}function jo(t,n){return function(e){return null!=e&&(e[t]===n&&(n!==i||t in jt(e)))}}function ko(t,n,e){return n=me(n===i?t.length-1:n,0),function(){for(var i=arguments,o=-1,u=me(i.length-n,0),a=r(u);++o<u;)a[o]=i[n+o];o=-1;for(var c=r(n+1);++o<n;)c[o]=i[o];return c[n]=e(a),kn(t,this,c)}}function Oo(t,n){return n.length<2?t:Er(t,ii(n,0,-1))}function So(t,n){if((\"constructor\"!==n||\"function\"!=typeof t[n])&&\"__proto__\"!=n)return t[n]}var Lo=Co(ni),To=dn||function(t,n){return gn.setTimeout(t,n)},Bo=Co(ei);function Do(t,n,e){var r=n+\"\";return Bo(t,function(t,n){var e=n.length;if(!e)return t;var r=e-1;return n[r]=(e>1?\"& \":\"\")+n[r],n=n.join(e>2?\", \":\" \"),t.replace(ct,\"{\\n/* [wrapped with \"+n+\"] */\\n\")}(r,function(t,n){return Sn(_,function(e){var r=\"_.\"+e[0];n&e[1]&&!Dn(t,r)&&t.push(r)}),t.sort()}(function(t){var n=t.match(lt);return n?n[1].split(ft):[]}(r),e)))}function Co(t){var n=0,e=0;return function(){var r=be(),o=16-(r-e);if(e=r,o>0){if(++n>=800)return arguments[0]}else n=0;return t.apply(i,arguments)}}function zo(t,n){var e=-1,r=t.length,o=r-1;for(n=n===i?r:n;++e<n;){var u=Yr(e,o),a=t[u];t[u]=t[e],t[e]=a}return t.length=n,t}var Fo=function(t){var n=Cu(t,function(t){return 500===e.size&&e.clear(),t}),e=n.cache;return n}(function(t){var n=[];return 46===t.charCodeAt(0)&&n.push(\"\"),t.replace(rt,function(t,e,r,i){n.push(r?i.replace(pt,\"$1\"):e||t)}),n});function Wo(t){if(\"string\"==typeof t||la(t))return t;var n=t+\"\";return\"0\"==n&&1/t==-1/0?\"-0\":n}function Po(t){if(null!=t){try{return Ct.call(t)}catch(t){}try{return t+\"\"}catch(t){}}return\"\"}function No(t){if(t instanceof He)return t.clone();var n=new qe(t.__wrapped__,t.__chain__);return n.__actions__=Si(t.__actions__),n.__index__=t.__index__,n.__values__=t.__values__,n}var $o=Jr(function(t,n){return Ku(t)?hr(t,yr(n,1,Ku,!0)):[]}),Uo=Jr(function(t,n){var e=Jo(n);return Ku(e)&&(e=i),Ku(t)?hr(t,yr(n,1,Ku,!0),lo(e,2)):[]}),Mo=Jr(function(t,n){var e=Jo(n);return Ku(e)&&(e=i),Ku(t)?hr(t,yr(n,1,Ku,!0),i,e):[]});function qo(t,n,e){var r=null==t?0:t.length;if(!r)return-1;var i=null==e?0:va(e);return i<0&&(i=me(r+i,0)),Mn(t,lo(n,3),i)}function Ho(t,n,e){var r=null==t?0:t.length;if(!r)return-1;var o=r-1;return e!==i&&(o=va(e),o=e<0?me(r+o,0):we(o,r-1)),Mn(t,lo(n,3),o,!0)}function Vo(t){return(null==t?0:t.length)?yr(t,1):[]}function Zo(t){return t&&t.length?t[0]:i}var Ko=Jr(function(t){var n=zn(t,yi);return n.length&&n[0]===t[0]?Sr(n):[]}),Yo=Jr(function(t){var n=Jo(t),e=zn(t,yi);return n===Jo(e)?n=i:e.pop(),e.length&&e[0]===t[0]?Sr(e,lo(n,2)):[]}),Go=Jr(function(t){var n=Jo(t),e=zn(t,yi);return(n=\"function\"==typeof n?n:i)&&e.pop(),e.length&&e[0]===t[0]?Sr(e,i,n):[]});function Jo(t){var n=null==t?0:t.length;return n?t[n-1]:i}var Qo=Jr(Xo);function Xo(t,n){return t&&t.length&&n&&n.length?Zr(t,n):t}var tu=ro(function(t,n){var e=null==t?0:t.length,r=ar(t,n);return Kr(t,zn(n,function(t){return wo(t,e)?+t:t}).sort(ji)),r});function nu(t){return null==t?t:Ee.call(t)}var eu=Jr(function(t){return si(yr(t,1,Ku,!0))}),ru=Jr(function(t){var n=Jo(t);return Ku(n)&&(n=i),si(yr(t,1,Ku,!0),lo(n,2))}),iu=Jr(function(t){var n=Jo(t);return n=\"function\"==typeof n?n:i,si(yr(t,1,Ku,!0),i,n)});function ou(t){if(!t||!t.length)return[];var n=0;return t=Bn(t,function(t){if(Ku(t))return n=me(t.length,n),!0}),Qn(n,function(n){return zn(t,Kn(n))})}function uu(t,n){if(!t||!t.length)return[];var e=ou(t);return null==n?e:zn(e,function(t){return kn(n,i,t)})}var au=Jr(function(t,n){return Ku(t)?hr(t,n):[]}),cu=Jr(function(t){return gi(Bn(t,Ku))}),lu=Jr(function(t){var n=Jo(t);return Ku(n)&&(n=i),gi(Bn(t,Ku),lo(n,2))}),fu=Jr(function(t){var n=Jo(t);return n=\"function\"==typeof n?n:i,gi(Bn(t,Ku),i,n)}),su=Jr(ou);var hu=Jr(function(t){var n=t.length,e=n>1?t[n-1]:i;return e=\"function\"==typeof e?(t.pop(),e):i,uu(t,e)});function pu(t){var n=$e(t);return n.__chain__=!0,n}function du(t,n){return n(t)}var vu=ro(function(t){var n=t.length,e=n?t[0]:0,r=this.__wrapped__,o=function(n){return ar(n,t)};return!(n>1||this.__actions__.length)&&r instanceof He&&wo(e)?((r=r.slice(e,+e+(n?1:0))).__actions__.push({func:du,args:[o],thisArg:i}),new qe(r,this.__chain__).thru(function(t){return n&&!t.length&&t.push(i),t})):this.thru(o)});var gu=Ti(function(t,n,e){zt.call(t,e)?++t[e]:ur(t,e,1)});var _u=Pi(qo),yu=Pi(Ho);function mu(t,n){return(Hu(t)?Sn:pr)(t,lo(n,3))}function wu(t,n){return(Hu(t)?Ln:dr)(t,lo(n,3))}var bu=Ti(function(t,n,e){zt.call(t,e)?t[e].push(n):ur(t,e,[n])});var xu=Jr(function(t,n,e){var i=-1,o=\"function\"==typeof n,u=Zu(t)?r(t.length):[];return pr(t,function(t){u[++i]=o?kn(n,t,e):Lr(t,n,e)}),u}),Iu=Ti(function(t,n,e){ur(t,e,n)});function Eu(t,n){return(Hu(t)?zn:Nr)(t,lo(n,3))}var Au=Ti(function(t,n,e){t[e?0:1].push(n)},function(){return[[],[]]});var Ru=Jr(function(t,n){if(null==t)return[];var e=n.length;return e>1&&bo(t,n[0],n[1])?n=[]:e>2&&bo(n[0],n[1],n[2])&&(n=[n[0]]),Hr(t,yr(n,1),[])}),ju=sn||function(){return gn.Date.now()};function ku(t,n,e){return n=e?i:n,n=t&&null==n?t.length:n,Qi(t,s,i,i,i,i,n)}function Ou(t,n){var e;if(\"function\"!=typeof n)throw new St(o);return t=va(t),function(){return--t>0&&(e=n.apply(this,arguments)),t<=1&&(n=i),e}}var Su=Jr(function(t,n,e){var r=1;if(e.length){var i=se(e,co(Su));r|=l}return Qi(t,r,n,e,i)}),Lu=Jr(function(t,n,e){var r=3;if(e.length){var i=se(e,co(Lu));r|=l}return Qi(n,r,t,e,i)});function Tu(t,n,e){var r,u,a,c,l,f,s=0,h=!1,p=!1,d=!0;if(\"function\"!=typeof t)throw new St(o);function v(n){var e=r,o=u;return r=u=i,s=n,c=t.apply(o,e)}function g(t){var e=t-f;return f===i||e>=n||e<0||p&&t-s>=a}function _(){var t=ju();if(g(t))return y(t);l=To(_,function(t){var e=n-(t-f);return p?we(e,a-(t-s)):e}(t))}function y(t){return l=i,d&&r?v(t):(r=u=i,c)}function m(){var t=ju(),e=g(t);if(r=arguments,u=this,f=t,e){if(l===i)return function(t){return s=t,l=To(_,n),h?v(t):c}(f);if(p)return Ii(l),l=To(_,n),v(f)}return l===i&&(l=To(_,n)),c}return n=_a(n)||0,na(e)&&(h=!!e.leading,a=(p=\"maxWait\"in e)?me(_a(e.maxWait)||0,n):a,d=\"trailing\"in e?!!e.trailing:d),m.cancel=function(){l!==i&&Ii(l),s=0,r=f=u=l=i},m.flush=function(){return l===i?c:y(ju())},m}var Bu=Jr(function(t,n){return sr(t,1,n)}),Du=Jr(function(t,n,e){return sr(t,_a(n)||0,e)});function Cu(t,n){if(\"function\"!=typeof t||null!=n&&\"function\"!=typeof n)throw new St(o);var e=function(){var r=arguments,i=n?n.apply(this,r):r[0],o=e.cache;if(o.has(i))return o.get(i);var u=t.apply(this,r);return e.cache=o.set(i,u)||o,u};return e.cache=new(Cu.Cache||Ke),e}function zu(t){if(\"function\"!=typeof t)throw new St(o);return function(){var n=arguments;switch(n.length){case 0:return!t.call(this);case 1:return!t.call(this,n[0]);case 2:return!t.call(this,n[0],n[1]);case 3:return!t.call(this,n[0],n[1],n[2])}return!t.apply(this,n)}}Cu.Cache=Ke;var Fu=bi(function(t,n){var e=(n=1==n.length&&Hu(n[0])?zn(n[0],te(lo())):zn(yr(n,1),te(lo()))).length;return Jr(function(r){for(var i=-1,o=we(r.length,e);++i<o;)r[i]=n[i].call(this,r[i]);return kn(t,this,r)})}),Wu=Jr(function(t,n){var e=se(n,co(Wu));return Qi(t,l,i,n,e)}),Pu=Jr(function(t,n){var e=se(n,co(Pu));return Qi(t,f,i,n,e)}),Nu=ro(function(t,n){return Qi(t,h,i,i,i,n)});function $u(t,n){return t===n||t!=t&&n!=n}var Uu=Zi(jr),Mu=Zi(function(t,n){return t>=n}),qu=Tr(function(){return arguments}())?Tr:function(t){return ea(t)&&zt.call(t,\"callee\")&&!Yt.call(t,\"callee\")},Hu=r.isArray,Vu=xn?te(xn):function(t){return ea(t)&&Rr(t)==D};function Zu(t){return null!=t&&ta(t.length)&&!Qu(t)}function Ku(t){return ea(t)&&Zu(t)}var Yu=wn||_c,Gu=In?te(In):function(t){return ea(t)&&Rr(t)==b};function Ju(t){if(!ea(t))return!1;var n=Rr(t);return n==x||\"[object DOMException]\"==n||\"string\"==typeof t.message&&\"string\"==typeof t.name&&!oa(t)}function Qu(t){if(!na(t))return!1;var n=Rr(t);return n==I||n==E||\"[object AsyncFunction]\"==n||\"[object Proxy]\"==n}function Xu(t){return\"number\"==typeof t&&t==va(t)}function ta(t){return\"number\"==typeof t&&t>-1&&t%1==0&&t<=d}function na(t){var n=typeof t;return null!=t&&(\"object\"==n||\"function\"==n)}function ea(t){return null!=t&&\"object\"==typeof t}var ra=En?te(En):function(t){return ea(t)&&go(t)==A};function ia(t){return\"number\"==typeof t||ea(t)&&Rr(t)==R}function oa(t){if(!ea(t)||Rr(t)!=j)return!1;var n=Zt(t);if(null===n)return!0;var e=zt.call(n,\"constructor\")&&n.constructor;return\"function\"==typeof e&&e instanceof e&&Ct.call(e)==Nt}var ua=An?te(An):function(t){return ea(t)&&Rr(t)==O};var aa=Rn?te(Rn):function(t){return ea(t)&&go(t)==S};function ca(t){return\"string\"==typeof t||!Hu(t)&&ea(t)&&Rr(t)==L}function la(t){return\"symbol\"==typeof t||ea(t)&&Rr(t)==T}var fa=jn?te(jn):function(t){return ea(t)&&ta(t.length)&&!!ln[Rr(t)]};var sa=Zi(Pr),ha=Zi(function(t,n){return t<=n});function pa(t){if(!t)return[];if(Zu(t))return ca(t)?ve(t):Si(t);if(Qt&&t[Qt])return function(t){for(var n,e=[];!(n=t.next()).done;)e.push(n.value);return e}(t[Qt]());var n=go(t);return(n==A?le:n==S?he:$a)(t)}function da(t){return t?(t=_a(t))===p||t===-1/0?17976931348623157e292*(t<0?-1:1):t==t?t:0:0===t?t:0}function va(t){var n=da(t),e=n%1;return n==n?e?n-e:n:0}function ga(t){return t?cr(va(t),0,g):0}function _a(t){if(\"number\"==typeof t)return t;if(la(t))return v;if(na(t)){var n=\"function\"==typeof t.valueOf?t.valueOf():t;t=na(n)?n+\"\":n}if(\"string\"!=typeof t)return 0===t?t:+t;t=Xn(t);var e=_t.test(t);return e||mt.test(t)?pn(t.slice(2),e?2:8):gt.test(t)?v:+t}function ya(t){return Li(t,Ba(t))}function ma(t){return null==t?\"\":fi(t)}var wa=Bi(function(t,n){if(Ao(n)||Zu(n))Li(n,Ta(n),t);else for(var e in n)zt.call(n,e)&&er(t,e,n[e])}),ba=Bi(function(t,n){Li(n,Ba(n),t)}),xa=Bi(function(t,n,e,r){Li(n,Ba(n),t,r)}),Ia=Bi(function(t,n,e,r){Li(n,Ta(n),t,r)}),Ea=ro(ar);var Aa=Jr(function(t,n){t=jt(t);var e=-1,r=n.length,o=r>2?n[2]:i;for(o&&bo(n[0],n[1],o)&&(r=1);++e<r;)for(var u=n[e],a=Ba(u),c=-1,l=a.length;++c<l;){var f=a[c],s=t[f];(s===i||$u(s,Bt[f])&&!zt.call(t,f))&&(t[f]=u[f])}return t}),Ra=Jr(function(t){return t.push(i,to),kn(Ca,i,t)});function ja(t,n,e){var r=null==t?i:Er(t,n);return r===i?e:r}function ka(t,n){return null!=t&&_o(t,n,Or)}var Oa=Ui(function(t,n,e){null!=n&&\"function\"!=typeof n.toString&&(n=Pt.call(n)),t[n]=e},nc(ic)),Sa=Ui(function(t,n,e){null!=n&&\"function\"!=typeof n.toString&&(n=Pt.call(n)),zt.call(t,n)?t[n].push(e):t[n]=[e]},lo),La=Jr(Lr);function Ta(t){return Zu(t)?Je(t):Fr(t)}function Ba(t){return Zu(t)?Je(t,!0):Wr(t)}var Da=Bi(function(t,n,e){Mr(t,n,e)}),Ca=Bi(function(t,n,e,r){Mr(t,n,e,r)}),za=ro(function(t,n){var e={};if(null==t)return e;var r=!1;n=zn(n,function(n){return n=wi(n,t),r||(r=n.length>1),n}),Li(t,oo(t),e),r&&(e=lr(e,7,no));for(var i=n.length;i--;)hi(e,n[i]);return e});var Fa=ro(function(t,n){return null==t?{}:function(t,n){return Vr(t,n,function(n,e){return ka(t,e)})}(t,n)});function Wa(t,n){if(null==t)return{};var e=zn(oo(t),function(t){return[t]});return n=lo(n),Vr(t,e,function(t,e){return n(t,e[0])})}var Pa=Ji(Ta),Na=Ji(Ba);function $a(t){return null==t?[]:ne(t,Ta(t))}var Ua=Fi(function(t,n,e){return n=n.toLowerCase(),t+(e?Ma(n):n)});function Ma(t){return Ja(ma(t).toLowerCase())}function qa(t){return(t=ma(t))&&t.replace(bt,oe).replace(nn,\"\")}var Ha=Fi(function(t,n,e){return t+(e?\"-\":\"\")+n.toLowerCase()}),Va=Fi(function(t,n,e){return t+(e?\" \":\"\")+n.toLowerCase()}),Za=zi(\"toLowerCase\");var Ka=Fi(function(t,n,e){return t+(e?\"_\":\"\")+n.toLowerCase()});var Ya=Fi(function(t,n,e){return t+(e?\" \":\"\")+Ja(n)});var Ga=Fi(function(t,n,e){return t+(e?\" \":\"\")+n.toUpperCase()}),Ja=zi(\"toUpperCase\");function Qa(t,n,e){return t=ma(t),(n=e?i:n)===i?function(t){return un.test(t)}(t)?function(t){return t.match(rn)||[]}(t):function(t){return t.match(st)||[]}(t):t.match(n)||[]}var Xa=Jr(function(t,n){try{return kn(t,i,n)}catch(t){return Ju(t)?t:new Et(t)}}),tc=ro(function(t,n){return Sn(n,function(n){n=Wo(n),ur(t,n,Su(t[n],t))}),t});function nc(t){return function(){return t}}var ec=Ni(),rc=Ni(!0);function ic(t){return t}function oc(t){return zr(\"function\"==typeof t?t:lr(t,1))}var uc=Jr(function(t,n){return function(e){return Lr(e,t,n)}}),ac=Jr(function(t,n){return function(e){return Lr(t,e,n)}});function cc(t,n,e){var r=Ta(n),i=Ir(n,r);null!=e||na(n)&&(i.length||!r.length)||(e=n,n=t,t=this,i=Ir(n,Ta(n)));var o=!(na(e)&&\"chain\"in e&&!e.chain),u=Qu(t);return Sn(i,function(e){var r=n[e];t[e]=r,u&&(t.prototype[e]=function(){var n=this.__chain__;if(o||n){var e=t(this.__wrapped__);return(e.__actions__=Si(this.__actions__)).push({func:r,args:arguments,thisArg:t}),e.__chain__=n,e}return r.apply(t,Fn([this.value()],arguments))})}),t}function lc(){}var fc=qi(zn),sc=qi(Tn),hc=qi(Nn);function pc(t){return xo(t)?Kn(Wo(t)):function(t){return function(n){return Er(n,t)}}(t)}var dc=Vi(),vc=Vi(!0);function gc(){return[]}function _c(){return!1}var yc=Mi(function(t,n){return t+n},0),mc=Yi(\"ceil\"),wc=Mi(function(t,n){return t/n},1),bc=Yi(\"floor\");var xc,Ic=Mi(function(t,n){return t*n},1),Ec=Yi(\"round\"),Ac=Mi(function(t,n){return t-n},0);return $e.after=function(t,n){if(\"function\"!=typeof n)throw new St(o);return t=va(t),function(){if(--t<1)return n.apply(this,arguments)}},$e.ary=ku,$e.assign=wa,$e.assignIn=ba,$e.assignInWith=xa,$e.assignWith=Ia,$e.at=Ea,$e.before=Ou,$e.bind=Su,$e.bindAll=tc,$e.bindKey=Lu,$e.castArray=function(){if(!arguments.length)return[];var t=arguments[0];return Hu(t)?t:[t]},$e.chain=pu,$e.chunk=function(t,n,e){n=(e?bo(t,n,e):n===i)?1:me(va(n),0);var o=null==t?0:t.length;if(!o||n<1)return[];for(var u=0,a=0,c=r(vn(o/n));u<o;)c[a++]=ii(t,u,u+=n);return c},$e.compact=function(t){for(var n=-1,e=null==t?0:t.length,r=0,i=[];++n<e;){var o=t[n];o&&(i[r++]=o)}return i},$e.concat=function(){var t=arguments.length;if(!t)return[];for(var n=r(t-1),e=arguments[0],i=t;i--;)n[i-1]=arguments[i];return Fn(Hu(e)?Si(e):[e],yr(n,1))},$e.cond=function(t){var n=null==t?0:t.length,e=lo();return t=n?zn(t,function(t){if(\"function\"!=typeof t[1])throw new St(o);return[e(t[0]),t[1]]}):[],Jr(function(e){for(var r=-1;++r<n;){var i=t[r];if(kn(i[0],this,e))return kn(i[1],this,e)}})},$e.conforms=function(t){return function(t){var n=Ta(t);return function(e){return fr(e,t,n)}}(lr(t,1))},$e.constant=nc,$e.countBy=gu,$e.create=function(t,n){var e=Ue(t);return null==n?e:or(e,n)},$e.curry=function t(n,e,r){var o=Qi(n,8,i,i,i,i,i,e=r?i:e);return o.placeholder=t.placeholder,o},$e.curryRight=function t(n,e,r){var o=Qi(n,c,i,i,i,i,i,e=r?i:e);return o.placeholder=t.placeholder,o},$e.debounce=Tu,$e.defaults=Aa,$e.defaultsDeep=Ra,$e.defer=Bu,$e.delay=Du,$e.difference=$o,$e.differenceBy=Uo,$e.differenceWith=Mo,$e.drop=function(t,n,e){var r=null==t?0:t.length;return r?ii(t,(n=e||n===i?1:va(n))<0?0:n,r):[]},$e.dropRight=function(t,n,e){var r=null==t?0:t.length;return r?ii(t,0,(n=r-(n=e||n===i?1:va(n)))<0?0:n):[]},$e.dropRightWhile=function(t,n){return t&&t.length?di(t,lo(n,3),!0,!0):[]},$e.dropWhile=function(t,n){return t&&t.length?di(t,lo(n,3),!0):[]},$e.fill=function(t,n,e,r){var o=null==t?0:t.length;return o?(e&&\"number\"!=typeof e&&bo(t,n,e)&&(e=0,r=o),function(t,n,e,r){var o=t.length;for((e=va(e))<0&&(e=-e>o?0:o+e),(r=r===i||r>o?o:va(r))<0&&(r+=o),r=e>r?0:ga(r);e<r;)t[e++]=n;return t}(t,n,e,r)):[]},$e.filter=function(t,n){return(Hu(t)?Bn:_r)(t,lo(n,3))},$e.flatMap=function(t,n){return yr(Eu(t,n),1)},$e.flatMapDeep=function(t,n){return yr(Eu(t,n),p)},$e.flatMapDepth=function(t,n,e){return e=e===i?1:va(e),yr(Eu(t,n),e)},$e.flatten=Vo,$e.flattenDeep=function(t){return(null==t?0:t.length)?yr(t,p):[]},$e.flattenDepth=function(t,n){return(null==t?0:t.length)?yr(t,n=n===i?1:va(n)):[]},$e.flip=function(t){return Qi(t,512)},$e.flow=ec,$e.flowRight=rc,$e.fromPairs=function(t){for(var n=-1,e=null==t?0:t.length,r={};++n<e;){var i=t[n];r[i[0]]=i[1]}return r},$e.functions=function(t){return null==t?[]:Ir(t,Ta(t))},$e.functionsIn=function(t){return null==t?[]:Ir(t,Ba(t))},$e.groupBy=bu,$e.initial=function(t){return(null==t?0:t.length)?ii(t,0,-1):[]},$e.intersection=Ko,$e.intersectionBy=Yo,$e.intersectionWith=Go,$e.invert=Oa,$e.invertBy=Sa,$e.invokeMap=xu,$e.iteratee=oc,$e.keyBy=Iu,$e.keys=Ta,$e.keysIn=Ba,$e.map=Eu,$e.mapKeys=function(t,n){var e={};return n=lo(n,3),br(t,function(t,r,i){ur(e,n(t,r,i),t)}),e},$e.mapValues=function(t,n){var e={};return n=lo(n,3),br(t,function(t,r,i){ur(e,r,n(t,r,i))}),e},$e.matches=function(t){return $r(lr(t,1))},$e.matchesProperty=function(t,n){return Ur(t,lr(n,1))},$e.memoize=Cu,$e.merge=Da,$e.mergeWith=Ca,$e.method=uc,$e.methodOf=ac,$e.mixin=cc,$e.negate=zu,$e.nthArg=function(t){return t=va(t),Jr(function(n){return qr(n,t)})},$e.omit=za,$e.omitBy=function(t,n){return Wa(t,zu(lo(n)))},$e.once=function(t){return Ou(2,t)},$e.orderBy=function(t,n,e,r){return null==t?[]:(Hu(n)||(n=null==n?[]:[n]),Hu(e=r?i:e)||(e=null==e?[]:[e]),Hr(t,n,e))},$e.over=fc,$e.overArgs=Fu,$e.overEvery=sc,$e.overSome=hc,$e.partial=Wu,$e.partialRight=Pu,$e.partition=Au,$e.pick=Fa,$e.pickBy=Wa,$e.property=pc,$e.propertyOf=function(t){return function(n){return null==t?i:Er(t,n)}},$e.pull=Qo,$e.pullAll=Xo,$e.pullAllBy=function(t,n,e){return t&&t.length&&n&&n.length?Zr(t,n,lo(e,2)):t},$e.pullAllWith=function(t,n,e){return t&&t.length&&n&&n.length?Zr(t,n,i,e):t},$e.pullAt=tu,$e.range=dc,$e.rangeRight=vc,$e.rearg=Nu,$e.reject=function(t,n){return(Hu(t)?Bn:_r)(t,zu(lo(n,3)))},$e.remove=function(t,n){var e=[];if(!t||!t.length)return e;var r=-1,i=[],o=t.length;for(n=lo(n,3);++r<o;){var u=t[r];n(u,r,t)&&(e.push(u),i.push(r))}return Kr(t,i),e},$e.rest=function(t,n){if(\"function\"!=typeof t)throw new St(o);return Jr(t,n=n===i?n:va(n))},$e.reverse=nu,$e.sampleSize=function(t,n,e){return n=(e?bo(t,n,e):n===i)?1:va(n),(Hu(t)?Xe:Xr)(t,n)},$e.set=function(t,n,e){return null==t?t:ti(t,n,e)},$e.setWith=function(t,n,e,r){return r=\"function\"==typeof r?r:i,null==t?t:ti(t,n,e,r)},$e.shuffle=function(t){return(Hu(t)?tr:ri)(t)},$e.slice=function(t,n,e){var r=null==t?0:t.length;return r?(e&&\"number\"!=typeof e&&bo(t,n,e)?(n=0,e=r):(n=null==n?0:va(n),e=e===i?r:va(e)),ii(t,n,e)):[]},$e.sortBy=Ru,$e.sortedUniq=function(t){return t&&t.length?ci(t):[]},$e.sortedUniqBy=function(t,n){return t&&t.length?ci(t,lo(n,2)):[]},$e.split=function(t,n,e){return e&&\"number\"!=typeof e&&bo(t,n,e)&&(n=e=i),(e=e===i?g:e>>>0)?(t=ma(t))&&(\"string\"==typeof n||null!=n&&!ua(n))&&!(n=fi(n))&&ce(t)?xi(ve(t),0,e):t.split(n,e):[]},$e.spread=function(t,n){if(\"function\"!=typeof t)throw new St(o);return n=null==n?0:me(va(n),0),Jr(function(e){var r=e[n],i=xi(e,0,n);return r&&Fn(i,r),kn(t,this,i)})},$e.tail=function(t){var n=null==t?0:t.length;return n?ii(t,1,n):[]},$e.take=function(t,n,e){return t&&t.length?ii(t,0,(n=e||n===i?1:va(n))<0?0:n):[]},$e.takeRight=function(t,n,e){var r=null==t?0:t.length;return r?ii(t,(n=r-(n=e||n===i?1:va(n)))<0?0:n,r):[]},$e.takeRightWhile=function(t,n){return t&&t.length?di(t,lo(n,3),!1,!0):[]},$e.takeWhile=function(t,n){return t&&t.length?di(t,lo(n,3)):[]},$e.tap=function(t,n){return n(t),t},$e.throttle=function(t,n,e){var r=!0,i=!0;if(\"function\"!=typeof t)throw new St(o);return na(e)&&(r=\"leading\"in e?!!e.leading:r,i=\"trailing\"in e?!!e.trailing:i),Tu(t,n,{leading:r,maxWait:n,trailing:i})},$e.thru=du,$e.toArray=pa,$e.toPairs=Pa,$e.toPairsIn=Na,$e.toPath=function(t){return Hu(t)?zn(t,Wo):la(t)?[t]:Si(Fo(ma(t)))},$e.toPlainObject=ya,$e.transform=function(t,n,e){var r=Hu(t),i=r||Yu(t)||fa(t);if(n=lo(n,4),null==e){var o=t&&t.constructor;e=i?r?new o:[]:na(t)&&Qu(o)?Ue(Zt(t)):{}}return(i?Sn:br)(t,function(t,r,i){return n(e,t,r,i)}),e},$e.unary=function(t){return ku(t,1)},$e.union=eu,$e.unionBy=ru,$e.unionWith=iu,$e.uniq=function(t){return t&&t.length?si(t):[]},$e.uniqBy=function(t,n){return t&&t.length?si(t,lo(n,2)):[]},$e.uniqWith=function(t,n){return n=\"function\"==typeof n?n:i,t&&t.length?si(t,i,n):[]},$e.unset=function(t,n){return null==t||hi(t,n)},$e.unzip=ou,$e.unzipWith=uu,$e.update=function(t,n,e){return null==t?t:pi(t,n,mi(e))},$e.updateWith=function(t,n,e,r){return r=\"function\"==typeof r?r:i,null==t?t:pi(t,n,mi(e),r)},$e.values=$a,$e.valuesIn=function(t){return null==t?[]:ne(t,Ba(t))},$e.without=au,$e.words=Qa,$e.wrap=function(t,n){return Wu(mi(n),t)},$e.xor=cu,$e.xorBy=lu,$e.xorWith=fu,$e.zip=su,$e.zipObject=function(t,n){return _i(t||[],n||[],er)},$e.zipObjectDeep=function(t,n){return _i(t||[],n||[],ti)},$e.zipWith=hu,$e.entries=Pa,$e.entriesIn=Na,$e.extend=ba,$e.extendWith=xa,cc($e,$e),$e.add=yc,$e.attempt=Xa,$e.camelCase=Ua,$e.capitalize=Ma,$e.ceil=mc,$e.clamp=function(t,n,e){return e===i&&(e=n,n=i),e!==i&&(e=(e=_a(e))==e?e:0),n!==i&&(n=(n=_a(n))==n?n:0),cr(_a(t),n,e)},$e.clone=function(t){return lr(t,4)},$e.cloneDeep=function(t){return lr(t,5)},$e.cloneDeepWith=function(t,n){return lr(t,5,n=\"function\"==typeof n?n:i)},$e.cloneWith=function(t,n){return lr(t,4,n=\"function\"==typeof n?n:i)},$e.conformsTo=function(t,n){return null==n||fr(t,n,Ta(n))},$e.deburr=qa,$e.defaultTo=function(t,n){return null==t||t!=t?n:t},$e.divide=wc,$e.endsWith=function(t,n,e){t=ma(t),n=fi(n);var r=t.length,o=e=e===i?r:cr(va(e),0,r);return(e-=n.length)>=0&&t.slice(e,o)==n},$e.eq=$u,$e.escape=function(t){return(t=ma(t))&&J.test(t)?t.replace(Y,ue):t},$e.escapeRegExp=function(t){return(t=ma(t))&&ot.test(t)?t.replace(it,\"\\\\$&\"):t},$e.every=function(t,n,e){var r=Hu(t)?Tn:vr;return e&&bo(t,n,e)&&(n=i),r(t,lo(n,3))},$e.find=_u,$e.findIndex=qo,$e.findKey=function(t,n){return Un(t,lo(n,3),br)},$e.findLast=yu,$e.findLastIndex=Ho,$e.findLastKey=function(t,n){return Un(t,lo(n,3),xr)},$e.floor=bc,$e.forEach=mu,$e.forEachRight=wu,$e.forIn=function(t,n){return null==t?t:mr(t,lo(n,3),Ba)},$e.forInRight=function(t,n){return null==t?t:wr(t,lo(n,3),Ba)},$e.forOwn=function(t,n){return t&&br(t,lo(n,3))},$e.forOwnRight=function(t,n){return t&&xr(t,lo(n,3))},$e.get=ja,$e.gt=Uu,$e.gte=Mu,$e.has=function(t,n){return null!=t&&_o(t,n,kr)},$e.hasIn=ka,$e.head=Zo,$e.identity=ic,$e.includes=function(t,n,e,r){t=Zu(t)?t:$a(t),e=e&&!r?va(e):0;var i=t.length;return e<0&&(e=me(i+e,0)),ca(t)?e<=i&&t.indexOf(n,e)>-1:!!i&&qn(t,n,e)>-1},$e.indexOf=function(t,n,e){var r=null==t?0:t.length;if(!r)return-1;var i=null==e?0:va(e);return i<0&&(i=me(r+i,0)),qn(t,n,i)},$e.inRange=function(t,n,e){return n=da(n),e===i?(e=n,n=0):e=da(e),function(t,n,e){return t>=we(n,e)&&t<me(n,e)}(t=_a(t),n,e)},$e.invoke=La,$e.isArguments=qu,$e.isArray=Hu,$e.isArrayBuffer=Vu,$e.isArrayLike=Zu,$e.isArrayLikeObject=Ku,$e.isBoolean=function(t){return!0===t||!1===t||ea(t)&&Rr(t)==w},$e.isBuffer=Yu,$e.isDate=Gu,$e.isElement=function(t){return ea(t)&&1===t.nodeType&&!oa(t)},$e.isEmpty=function(t){if(null==t)return!0;if(Zu(t)&&(Hu(t)||\"string\"==typeof t||\"function\"==typeof t.splice||Yu(t)||fa(t)||qu(t)))return!t.length;var n=go(t);if(n==A||n==S)return!t.size;if(Ao(t))return!Fr(t).length;for(var e in t)if(zt.call(t,e))return!1;return!0},$e.isEqual=function(t,n){return Br(t,n)},$e.isEqualWith=function(t,n,e){var r=(e=\"function\"==typeof e?e:i)?e(t,n):i;return r===i?Br(t,n,i,e):!!r},$e.isError=Ju,$e.isFinite=function(t){return\"number\"==typeof t&&bn(t)},$e.isFunction=Qu,$e.isInteger=Xu,$e.isLength=ta,$e.isMap=ra,$e.isMatch=function(t,n){return t===n||Dr(t,n,so(n))},$e.isMatchWith=function(t,n,e){return e=\"function\"==typeof e?e:i,Dr(t,n,so(n),e)},$e.isNaN=function(t){return ia(t)&&t!=+t},$e.isNative=function(t){if(Eo(t))throw new Et(\"Unsupported core-js use. Try https://npms.io/search?q=ponyfill.\");return Cr(t)},$e.isNil=function(t){return null==t},$e.isNull=function(t){return null===t},$e.isNumber=ia,$e.isObject=na,$e.isObjectLike=ea,$e.isPlainObject=oa,$e.isRegExp=ua,$e.isSafeInteger=function(t){return Xu(t)&&t>=-9007199254740991&&t<=d},$e.isSet=aa,$e.isString=ca,$e.isSymbol=la,$e.isTypedArray=fa,$e.isUndefined=function(t){return t===i},$e.isWeakMap=function(t){return ea(t)&&go(t)==B},$e.isWeakSet=function(t){return ea(t)&&\"[object WeakSet]\"==Rr(t)},$e.join=function(t,n){return null==t?\"\":$n.call(t,n)},$e.kebabCase=Ha,$e.last=Jo,$e.lastIndexOf=function(t,n,e){var r=null==t?0:t.length;if(!r)return-1;var o=r;return e!==i&&(o=(o=va(e))<0?me(r+o,0):we(o,r-1)),n==n?function(t,n,e){for(var r=e+1;r--;)if(t[r]===n)return r;return r}(t,n,o):Mn(t,Vn,o,!0)},$e.lowerCase=Va,$e.lowerFirst=Za,$e.lt=sa,$e.lte=ha,$e.max=function(t){return t&&t.length?gr(t,ic,jr):i},$e.maxBy=function(t,n){return t&&t.length?gr(t,lo(n,2),jr):i},$e.mean=function(t){return Zn(t,ic)},$e.meanBy=function(t,n){return Zn(t,lo(n,2))},$e.min=function(t){return t&&t.length?gr(t,ic,Pr):i},$e.minBy=function(t,n){return t&&t.length?gr(t,lo(n,2),Pr):i},$e.stubArray=gc,$e.stubFalse=_c,$e.stubObject=function(){return{}},$e.stubString=function(){return\"\"},$e.stubTrue=function(){return!0},$e.multiply=Ic,$e.nth=function(t,n){return t&&t.length?qr(t,va(n)):i},$e.noConflict=function(){return gn._===this&&(gn._=$t),this},$e.noop=lc,$e.now=ju,$e.pad=function(t,n,e){t=ma(t);var r=(n=va(n))?de(t):0;if(!n||r>=n)return t;var i=(n-r)/2;return Hi(_n(i),e)+t+Hi(vn(i),e)},$e.padEnd=function(t,n,e){t=ma(t);var r=(n=va(n))?de(t):0;return n&&r<n?t+Hi(n-r,e):t},$e.padStart=function(t,n,e){t=ma(t);var r=(n=va(n))?de(t):0;return n&&r<n?Hi(n-r,e)+t:t},$e.parseInt=function(t,n,e){return e||null==n?n=0:n&&(n=+n),xe(ma(t).replace(ut,\"\"),n||0)},$e.random=function(t,n,e){if(e&&\"boolean\"!=typeof e&&bo(t,n,e)&&(n=e=i),e===i&&(\"boolean\"==typeof n?(e=n,n=i):\"boolean\"==typeof t&&(e=t,t=i)),t===i&&n===i?(t=0,n=1):(t=da(t),n===i?(n=t,t=0):n=da(n)),t>n){var r=t;t=n,n=r}if(e||t%1||n%1){var o=Ie();return we(t+o*(n-t+hn(\"1e-\"+((o+\"\").length-1))),n)}return Yr(t,n)},$e.reduce=function(t,n,e){var r=Hu(t)?Wn:Gn,i=arguments.length<3;return r(t,lo(n,4),e,i,pr)},$e.reduceRight=function(t,n,e){var r=Hu(t)?Pn:Gn,i=arguments.length<3;return r(t,lo(n,4),e,i,dr)},$e.repeat=function(t,n,e){return n=(e?bo(t,n,e):n===i)?1:va(n),Gr(ma(t),n)},$e.replace=function(){var t=arguments,n=ma(t[0]);return t.length<3?n:n.replace(t[1],t[2])},$e.result=function(t,n,e){var r=-1,o=(n=wi(n,t)).length;for(o||(o=1,t=i);++r<o;){var u=null==t?i:t[Wo(n[r])];u===i&&(r=o,u=e),t=Qu(u)?u.call(t):u}return t},$e.round=Ec,$e.runInContext=t,$e.sample=function(t){return(Hu(t)?Qe:Qr)(t)},$e.size=function(t){if(null==t)return 0;if(Zu(t))return ca(t)?de(t):t.length;var n=go(t);return n==A||n==S?t.size:Fr(t).length},$e.snakeCase=Ka,$e.some=function(t,n,e){var r=Hu(t)?Nn:oi;return e&&bo(t,n,e)&&(n=i),r(t,lo(n,3))},$e.sortedIndex=function(t,n){return ui(t,n)},$e.sortedIndexBy=function(t,n,e){return ai(t,n,lo(e,2))},$e.sortedIndexOf=function(t,n){var e=null==t?0:t.length;if(e){var r=ui(t,n);if(r<e&&$u(t[r],n))return r}return-1},$e.sortedLastIndex=function(t,n){return ui(t,n,!0)},$e.sortedLastIndexBy=function(t,n,e){return ai(t,n,lo(e,2),!0)},$e.sortedLastIndexOf=function(t,n){if(null==t?0:t.length){var e=ui(t,n,!0)-1;if($u(t[e],n))return e}return-1},$e.startCase=Ya,$e.startsWith=function(t,n,e){return t=ma(t),e=null==e?0:cr(va(e),0,t.length),n=fi(n),t.slice(e,e+n.length)==n},$e.subtract=Ac,$e.sum=function(t){return t&&t.length?Jn(t,ic):0},$e.sumBy=function(t,n){return t&&t.length?Jn(t,lo(n,2)):0},$e.template=function(t,n,e){var r=$e.templateSettings;e&&bo(t,n,e)&&(n=i),t=ma(t),n=xa({},n,r,Xi);var o,u,a=xa({},n.imports,r.imports,Xi),c=Ta(a),l=ne(a,c),f=0,s=n.interpolate||xt,h=\"__p += '\",p=kt((n.escape||xt).source+\"|\"+s.source+\"|\"+(s===tt?dt:xt).source+\"|\"+(n.evaluate||xt).source+\"|$\",\"g\"),d=\"//# sourceURL=\"+(zt.call(n,\"sourceURL\")?(n.sourceURL+\"\").replace(/\\s/g,\" \"):\"lodash.templateSources[\"+ ++cn+\"]\")+\"\\n\";t.replace(p,function(n,e,r,i,a,c){return r||(r=i),h+=t.slice(f,c).replace(It,ae),e&&(o=!0,h+=\"' +\\n__e(\"+e+\") +\\n'\"),a&&(u=!0,h+=\"';\\n\"+a+\";\\n__p += '\"),r&&(h+=\"' +\\n((__t = (\"+r+\")) == null ? '' : __t) +\\n'\"),f=c+n.length,n}),h+=\"';\\n\";var v=zt.call(n,\"variable\")&&n.variable;if(v){if(ht.test(v))throw new Et(\"Invalid `variable` option passed into `_.template`\")}else h=\"with (obj) {\\n\"+h+\"\\n}\\n\";h=(u?h.replace(H,\"\"):h).replace(V,\"$1\").replace(Z,\"$1;\"),h=\"function(\"+(v||\"obj\")+\") {\\n\"+(v?\"\":\"obj || (obj = {});\\n\")+\"var __t, __p = ''\"+(o?\", __e = _.escape\":\"\")+(u?\", __j = Array.prototype.join;\\nfunction print() { __p += __j.call(arguments, '') }\\n\":\";\\n\")+h+\"return __p\\n}\";var g=Xa(function(){return At(c,d+\"return \"+h).apply(i,l)});if(g.source=h,Ju(g))throw g;return g},$e.times=function(t,n){if((t=va(t))<1||t>d)return[];var e=g,r=we(t,g);n=lo(n),t-=g;for(var i=Qn(r,n);++e<t;)n(e);return i},$e.toFinite=da,$e.toInteger=va,$e.toLength=ga,$e.toLower=function(t){return ma(t).toLowerCase()},$e.toNumber=_a,$e.toSafeInteger=function(t){return t?cr(va(t),-9007199254740991,d):0===t?t:0},$e.toString=ma,$e.toUpper=function(t){return ma(t).toUpperCase()},$e.trim=function(t,n,e){if((t=ma(t))&&(e||n===i))return Xn(t);if(!t||!(n=fi(n)))return t;var r=ve(t),o=ve(n);return xi(r,re(r,o),ie(r,o)+1).join(\"\")},$e.trimEnd=function(t,n,e){if((t=ma(t))&&(e||n===i))return t.slice(0,ge(t)+1);if(!t||!(n=fi(n)))return t;var r=ve(t);return xi(r,0,ie(r,ve(n))+1).join(\"\")},$e.trimStart=function(t,n,e){if((t=ma(t))&&(e||n===i))return t.replace(ut,\"\");if(!t||!(n=fi(n)))return t;var r=ve(t);return xi(r,re(r,ve(n))).join(\"\")},$e.truncate=function(t,n){var e=30,r=\"...\";if(na(n)){var o=\"separator\"in n?n.separator:o;e=\"length\"in n?va(n.length):e,r=\"omission\"in n?fi(n.omission):r}var u=(t=ma(t)).length;if(ce(t)){var a=ve(t);u=a.length}if(e>=u)return t;var c=e-de(r);if(c<1)return r;var l=a?xi(a,0,c).join(\"\"):t.slice(0,c);if(o===i)return l+r;if(a&&(c+=l.length-c),ua(o)){if(t.slice(c).search(o)){var f,s=l;for(o.global||(o=kt(o.source,ma(vt.exec(o))+\"g\")),o.lastIndex=0;f=o.exec(s);)var h=f.index;l=l.slice(0,h===i?c:h)}}else if(t.indexOf(fi(o),c)!=c){var p=l.lastIndexOf(o);p>-1&&(l=l.slice(0,p))}return l+r},$e.unescape=function(t){return(t=ma(t))&&G.test(t)?t.replace(K,_e):t},$e.uniqueId=function(t){var n=++Ft;return ma(t)+n},$e.upperCase=Ga,$e.upperFirst=Ja,$e.each=mu,$e.eachRight=wu,$e.first=Zo,cc($e,(xc={},br($e,function(t,n){zt.call($e.prototype,n)||(xc[n]=t)}),xc),{chain:!1}),$e.VERSION=\"4.17.23\",Sn([\"bind\",\"bindKey\",\"curry\",\"curryRight\",\"partial\",\"partialRight\"],function(t){$e[t].placeholder=$e}),Sn([\"drop\",\"take\"],function(t,n){He.prototype[t]=function(e){e=e===i?1:me(va(e),0);var r=this.__filtered__&&!n?new He(this):this.clone();return r.__filtered__?r.__takeCount__=we(e,r.__takeCount__):r.__views__.push({size:we(e,g),type:t+(r.__dir__<0?\"Right\":\"\")}),r},He.prototype[t+\"Right\"]=function(n){return this.reverse()[t](n).reverse()}}),Sn([\"filter\",\"map\",\"takeWhile\"],function(t,n){var e=n+1,r=1==e||3==e;He.prototype[t]=function(t){var n=this.clone();return n.__iteratees__.push({iteratee:lo(t,3),type:e}),n.__filtered__=n.__filtered__||r,n}}),Sn([\"head\",\"last\"],function(t,n){var e=\"take\"+(n?\"Right\":\"\");He.prototype[t]=function(){return this[e](1).value()[0]}}),Sn([\"initial\",\"tail\"],function(t,n){var e=\"drop\"+(n?\"\":\"Right\");He.prototype[t]=function(){return this.__filtered__?new He(this):this[e](1)}}),He.prototype.compact=function(){return this.filter(ic)},He.prototype.find=function(t){return this.filter(t).head()},He.prototype.findLast=function(t){return this.reverse().find(t)},He.prototype.invokeMap=Jr(function(t,n){return\"function\"==typeof t?new He(this):this.map(function(e){return Lr(e,t,n)})}),He.prototype.reject=function(t){return this.filter(zu(lo(t)))},He.prototype.slice=function(t,n){t=va(t);var e=this;return e.__filtered__&&(t>0||n<0)?new He(e):(t<0?e=e.takeRight(-t):t&&(e=e.drop(t)),n!==i&&(e=(n=va(n))<0?e.dropRight(-n):e.take(n-t)),e)},He.prototype.takeRightWhile=function(t){return this.reverse().takeWhile(t).reverse()},He.prototype.toArray=function(){return this.take(g)},br(He.prototype,function(t,n){var e=/^(?:filter|find|map|reject)|While$/.test(n),r=/^(?:head|last)$/.test(n),o=$e[r?\"take\"+(\"last\"==n?\"Right\":\"\"):n],u=r||/^find/.test(n);o&&($e.prototype[n]=function(){var n=this.__wrapped__,a=r?[1]:arguments,c=n instanceof He,l=a[0],f=c||Hu(n),s=function(t){var n=o.apply($e,Fn([t],a));return r&&h?n[0]:n};f&&e&&\"function\"==typeof l&&1!=l.length&&(c=f=!1);var h=this.__chain__,p=!!this.__actions__.length,d=u&&!h,v=c&&!p;if(!u&&f){n=v?n:new He(this);var g=t.apply(n,a);return g.__actions__.push({func:du,args:[s],thisArg:i}),new qe(g,h)}return d&&v?t.apply(this,a):(g=this.thru(s),d?r?g.value()[0]:g.value():g)})}),Sn([\"pop\",\"push\",\"shift\",\"sort\",\"splice\",\"unshift\"],function(t){var n=Lt[t],e=/^(?:push|sort|unshift)$/.test(t)?\"tap\":\"thru\",r=/^(?:pop|shift)$/.test(t);$e.prototype[t]=function(){var t=arguments;if(r&&!this.__chain__){var i=this.value();return n.apply(Hu(i)?i:[],t)}return this[e](function(e){return n.apply(Hu(e)?e:[],t)})}}),br(He.prototype,function(t,n){var e=$e[n];if(e){var r=e.name+\"\";zt.call(Te,r)||(Te[r]=[]),Te[r].push({name:n,func:e})}}),Te[$i(i,2).name]=[{name:\"wrapper\",func:i}],He.prototype.clone=function(){var t=new He(this.__wrapped__);return t.__actions__=Si(this.__actions__),t.__dir__=this.__dir__,t.__filtered__=this.__filtered__,t.__iteratees__=Si(this.__iteratees__),t.__takeCount__=this.__takeCount__,t.__views__=Si(this.__views__),t},He.prototype.reverse=function(){if(this.__filtered__){var t=new He(this);t.__dir__=-1,t.__filtered__=!0}else(t=this.clone()).__dir__*=-1;return t},He.prototype.value=function(){var t=this.__wrapped__.value(),n=this.__dir__,e=Hu(t),r=n<0,i=e?t.length:0,o=function(t,n,e){var r=-1,i=e.length;for(;++r<i;){var o=e[r],u=o.size;switch(o.type){case\"drop\":t+=u;break;case\"dropRight\":n-=u;break;case\"take\":n=we(n,t+u);break;case\"takeRight\":t=me(t,n-u)}}return{start:t,end:n}}(0,i,this.__views__),u=o.start,a=o.end,c=a-u,l=r?a:u-1,f=this.__iteratees__,s=f.length,h=0,p=we(c,this.__takeCount__);if(!e||!r&&i==c&&p==c)return vi(t,this.__actions__);var d=[];t:for(;c--&&h<p;){for(var v=-1,g=t[l+=n];++v<s;){var _=f[v],y=_.iteratee,m=_.type,w=y(g);if(2==m)g=w;else if(!w){if(1==m)continue t;break t}}d[h++]=g}return d},$e.prototype.at=vu,$e.prototype.chain=function(){return pu(this)},$e.prototype.commit=function(){return new qe(this.value(),this.__chain__)},$e.prototype.next=function(){this.__values__===i&&(this.__values__=pa(this.value()));var t=this.__index__>=this.__values__.length;return{done:t,value:t?i:this.__values__[this.__index__++]}},$e.prototype.plant=function(t){for(var n,e=this;e instanceof Me;){var r=No(e);r.__index__=0,r.__values__=i,n?o.__wrapped__=r:n=r;var o=r;e=e.__wrapped__}return o.__wrapped__=t,n},$e.prototype.reverse=function(){var t=this.__wrapped__;if(t instanceof He){var n=t;return this.__actions__.length&&(n=new He(this)),(n=n.reverse()).__actions__.push({func:du,args:[nu],thisArg:i}),new qe(n,this.__chain__)}return this.thru(nu)},$e.prototype.toJSON=$e.prototype.valueOf=$e.prototype.value=function(){return vi(this.__wrapped__,this.__actions__)},$e.prototype.first=$e.prototype.head,Qt&&($e.prototype[Qt]=function(){return this}),$e}();gn._=ye,(r=function(){return ye}.call(n,e,n,t))===i||(t.exports=r)}.call(this)},224(t,n,e){\"use strict\";e.d(n,{Hw:()=>s,P2:()=>h,Qx:()=>c,bn:()=>o,kO:()=>f,ni:()=>a,qr:()=>u});var r=e(543),i=e.n(r);function o(t,n=1){if(Math.abs(t)<1e3)return t+\" B\";const e=[\"kB\",\"MB\",\"GB\",\"TB\",\"PB\",\"EB\",\"ZB\",\"YB\"];let r=-1;const i=10**n;do{t/=1e3,++r}while(Math.round(Math.abs(t)*i)/i>=1e3&&r<e.length-1);return t.toFixed(n)+\" \"+e[r]}function u(t){var n;return function(){n&&window.cancelAnimationFrame(n);const e=this,r=arguments;n=window.requestAnimationFrame(function(){t.apply(e,r)})}}function a(t,n,e){let r=\"unknown location\";void 0!==t.location&&(r=`File ${t.location[1]}, line ${t.location[2]} in ${t.location[0]}`);const i=t.n_allocations>1?\"s\":\"\";let o=`${r}<br>${n} total<br>${`${t.n_allocations} allocation${i}`}`;return!1===e&&(o=o.concat(`<br>Thread ID: ${t.thread_id}`)),o}function c(t,n){return function(t,n){let e=i().cloneDeep(t.children);const r=i().filter(e,function t(e){return e.children&&e.children.length>0&&(e.children=i().filter(e.children,t)),n(e)});return i().defaults({children:r},t)}(t,t=>t.thread_id===n)}function l(t,n){function e(t){let r=[];if(n(t)){r=[];for(const n of t.children)r.push(...e(n));let n=i().clone(t);n.children=r,r=[n]}else for(const n of t.children)r.push(...e(n));return r}let r=[];for(let n of t.children)r.push(...e(n));return i().defaults({children:r},t)}function f(t){return l(t,t=>t.interesting)}function s(t){return l(t,t=>!t.import_system)}function h(t){return i().reduce(t,(t,n)=>(t.n_allocations+=n.n_allocations,t.value+=n.value,t),{n_allocations:0,value:0})}},279(t,n,e){\"use strict\";e.d(n,{Iv:()=>Ct,QA:()=>Dt,kj:()=>Pt,zb:()=>Kt,Yu:()=>Vt,un:()=>qt,bt:()=>Ht,Ke:()=>Nt,mU:()=>$t,EV:()=>Mt});var r=e(224);const i=Math.min,o=Math.max,u=Math.round,a=Math.floor,c=t=>({x:t,y:t}),l={left:\"right\",right:\"left\",bottom:\"top\",top:\"bottom\"},f={start:\"end\",end:\"start\"};function s(t,n,e){return o(t,i(n,e))}function h(t,n){return\"function\"==typeof t?t(n):t}function p(t){return t.split(\"-\")[0]}function d(t){return t.split(\"-\")[1]}function v(t){return\"x\"===t?\"y\":\"x\"}function g(t){return\"y\"===t?\"height\":\"width\"}const y=new Set([\"top\",\"bottom\"]);function m(t){return y.has(p(t))?\"y\":\"x\"}function w(t){return v(m(t))}function b(t){return t.replace(/start|end/g,t=>f[t])}const x=[\"left\",\"right\"],I=[\"right\",\"left\"],E=[\"top\",\"bottom\"],A=[\"bottom\",\"top\"];function R(t,n,e,r){const i=d(t);let o=function(t,n,e){switch(t){case\"top\":case\"bottom\":return e?n?I:x:n?x:I;case\"left\":case\"right\":return n?E:A;default:return[]}}(p(t),\"start\"===e,r);return i&&(o=o.map(t=>t+\"-\"+i),n&&(o=o.concat(o.map(b)))),o}function j(t){return t.replace(/left|right|bottom|top/g,t=>l[t])}function k(t){const{x:n,y:e,width:r,height:i}=t;return{width:r,height:i,top:e,left:n,right:n+r,bottom:e+i,x:n,y:e}}function O(t,n,e){let{reference:r,floating:i}=t;const o=m(n),u=w(n),a=g(u),c=p(n),l=\"y\"===o,f=r.x+r.width/2-i.width/2,s=r.y+r.height/2-i.height/2,h=r[a]/2-i[a]/2;let v;switch(c){case\"top\":v={x:f,y:r.y-i.height};break;case\"bottom\":v={x:f,y:r.y+r.height};break;case\"right\":v={x:r.x+r.width,y:s};break;case\"left\":v={x:r.x-i.width,y:s};break;default:v={x:r.x,y:r.y}}switch(d(n)){case\"start\":v[u]-=h*(e&&l?-1:1);break;case\"end\":v[u]+=h*(e&&l?-1:1)}return v}async function S(t,n){var e;void 0===n&&(n={});const{x:r,y:i,platform:o,rects:u,elements:a,strategy:c}=t,{boundary:l=\"clippingAncestors\",rootBoundary:f=\"viewport\",elementContext:s=\"floating\",altBoundary:p=!1,padding:d=0}=h(n,t),v=function(t){return\"number\"!=typeof t?function(t){return{top:0,right:0,bottom:0,left:0,...t}}(t):{top:t,right:t,bottom:t,left:t}}(d),g=a[p?\"floating\"===s?\"reference\":\"floating\":s],_=k(await o.getClippingRect({element:null==(e=await(null==o.isElement?void 0:o.isElement(g)))||e?g:g.contextElement||await(null==o.getDocumentElement?void 0:o.getDocumentElement(a.floating)),boundary:l,rootBoundary:f,strategy:c})),y=\"floating\"===s?{x:r,y:i,width:u.floating.width,height:u.floating.height}:u.reference,m=await(null==o.getOffsetParent?void 0:o.getOffsetParent(a.floating)),w=await(null==o.isElement?void 0:o.isElement(m))&&await(null==o.getScale?void 0:o.getScale(m))||{x:1,y:1},b=k(o.convertOffsetParentRelativeRectToViewportRelativeRect?await o.convertOffsetParentRelativeRectToViewportRelativeRect({elements:a,rect:y,offsetParent:m,strategy:c}):y);return{top:(_.top-b.top+v.top)/w.y,bottom:(b.bottom-_.bottom+v.bottom)/w.y,left:(_.left-b.left+v.left)/w.x,right:(b.right-_.right+v.right)/w.x}}const L=new Set([\"left\",\"top\"]);function T(){return\"undefined\"!=typeof window}function B(t){return z(t)?(t.nodeName||\"\").toLowerCase():\"#document\"}function D(t){var n;return(null==t||null==(n=t.ownerDocument)?void 0:n.defaultView)||window}function C(t){var n;return null==(n=(z(t)?t.ownerDocument:t.document)||window.document)?void 0:n.documentElement}function z(t){return!!T()&&(t instanceof Node||t instanceof D(t).Node)}function F(t){return!!T()&&(t instanceof Element||t instanceof D(t).Element)}function W(t){return!!T()&&(t instanceof HTMLElement||t instanceof D(t).HTMLElement)}function P(t){return!(!T()||\"undefined\"==typeof ShadowRoot)&&(t instanceof ShadowRoot||t instanceof D(t).ShadowRoot)}const N=new Set([\"inline\",\"contents\"]);function U(t){const{overflow:n,overflowX:e,overflowY:r,display:i}=tt(t);return/auto|scroll|overlay|hidden|clip/.test(n+r+e)&&!N.has(i)}const M=new Set([\"table\",\"td\",\"th\"]);function q(t){return M.has(B(t))}const H=[\":popover-open\",\":modal\"];function V(t){return H.some(n=>{try{return t.matches(n)}catch(t){return!1}})}const Z=[\"transform\",\"translate\",\"scale\",\"rotate\",\"perspective\"],K=[\"transform\",\"translate\",\"scale\",\"rotate\",\"perspective\",\"filter\"],Y=[\"paint\",\"layout\",\"strict\",\"content\"];function G(t){const n=J(),e=F(t)?tt(t):t;return Z.some(t=>!!e[t]&&\"none\"!==e[t])||!!e.containerType&&\"normal\"!==e.containerType||!n&&!!e.backdropFilter&&\"none\"!==e.backdropFilter||!n&&!!e.filter&&\"none\"!==e.filter||K.some(t=>(e.willChange||\"\").includes(t))||Y.some(t=>(e.contain||\"\").includes(t))}function J(){return!(\"undefined\"==typeof CSS||!CSS.supports)&&CSS.supports(\"-webkit-backdrop-filter\",\"none\")}const Q=new Set([\"html\",\"body\",\"#document\"]);function X(t){return Q.has(B(t))}function tt(t){return D(t).getComputedStyle(t)}function nt(t){return F(t)?{scrollLeft:t.scrollLeft,scrollTop:t.scrollTop}:{scrollLeft:t.scrollX,scrollTop:t.scrollY}}function et(t){if(\"html\"===B(t))return t;const n=t.assignedSlot||t.parentNode||P(t)&&t.host||C(t);return P(n)?n.host:n}function rt(t){const n=et(t);return X(n)?t.ownerDocument?t.ownerDocument.body:t.body:W(n)&&U(n)?n:rt(n)}function it(t,n,e){var r;void 0===n&&(n=[]),void 0===e&&(e=!0);const i=rt(t),o=i===(null==(r=t.ownerDocument)?void 0:r.body),u=D(i);if(o){const t=ot(u);return n.concat(u,u.visualViewport||[],U(i)?i:[],t&&e?it(t):[])}return n.concat(i,it(i,[],e))}function ot(t){return t.parent&&Object.getPrototypeOf(t.parent)?t.frameElement:null}function ut(t){const n=tt(t);let e=parseFloat(n.width)||0,r=parseFloat(n.height)||0;const i=W(t),o=i?t.offsetWidth:e,a=i?t.offsetHeight:r,c=u(e)!==o||u(r)!==a;return c&&(e=o,r=a),{width:e,height:r,$:c}}function at(t){return F(t)?t:t.contextElement}function ct(t){const n=at(t);if(!W(n))return c(1);const e=n.getBoundingClientRect(),{width:r,height:i,$:o}=ut(n);let a=(o?u(e.width):e.width)/r,l=(o?u(e.height):e.height)/i;return a&&Number.isFinite(a)||(a=1),l&&Number.isFinite(l)||(l=1),{x:a,y:l}}const lt=c(0);function ft(t){const n=D(t);return J()&&n.visualViewport?{x:n.visualViewport.offsetLeft,y:n.visualViewport.offsetTop}:lt}function st(t,n,e,r){void 0===n&&(n=!1),void 0===e&&(e=!1);const i=t.getBoundingClientRect(),o=at(t);let u=c(1);n&&(r?F(r)&&(u=ct(r)):u=ct(t));const a=function(t,n,e){return void 0===n&&(n=!1),!(!e||n&&e!==D(t))&&n}(o,e,r)?ft(o):c(0);let l=(i.left+a.x)/u.x,f=(i.top+a.y)/u.y,s=i.width/u.x,h=i.height/u.y;if(o){const t=D(o),n=r&&F(r)?D(r):r;let e=t,i=ot(e);for(;i&&r&&n!==e;){const t=ct(i),n=i.getBoundingClientRect(),r=tt(i),o=n.left+(i.clientLeft+parseFloat(r.paddingLeft))*t.x,u=n.top+(i.clientTop+parseFloat(r.paddingTop))*t.y;l*=t.x,f*=t.y,s*=t.x,h*=t.y,l+=o,f+=u,e=D(i),i=ot(e)}}return k({width:s,height:h,x:l,y:f})}function ht(t,n){const e=nt(t).scrollLeft;return n?n.left+e:st(C(t)).left+e}function pt(t,n){const e=t.getBoundingClientRect();return{x:e.left+n.scrollLeft-ht(t,e),y:e.top+n.scrollTop}}const dt=new Set([\"absolute\",\"fixed\"]);function vt(t,n,e){let r;if(\"viewport\"===n)r=function(t,n){const e=D(t),r=C(t),i=e.visualViewport;let o=r.clientWidth,u=r.clientHeight,a=0,c=0;if(i){o=i.width,u=i.height;const t=J();(!t||t&&\"fixed\"===n)&&(a=i.offsetLeft,c=i.offsetTop)}const l=ht(r);if(l<=0){const t=r.ownerDocument,n=t.body,e=getComputedStyle(n),i=\"CSS1Compat\"===t.compatMode&&parseFloat(e.marginLeft)+parseFloat(e.marginRight)||0,u=Math.abs(r.clientWidth-n.clientWidth-i);u<=25&&(o-=u)}else l<=25&&(o+=l);return{width:o,height:u,x:a,y:c}}(t,e);else if(\"document\"===n)r=function(t){const n=C(t),e=nt(t),r=t.ownerDocument.body,i=o(n.scrollWidth,n.clientWidth,r.scrollWidth,r.clientWidth),u=o(n.scrollHeight,n.clientHeight,r.scrollHeight,r.clientHeight);let a=-e.scrollLeft+ht(t);const c=-e.scrollTop;return\"rtl\"===tt(r).direction&&(a+=o(n.clientWidth,r.clientWidth)-i),{width:i,height:u,x:a,y:c}}(C(t));else if(F(n))r=function(t,n){const e=st(t,!0,\"fixed\"===n),r=e.top+t.clientTop,i=e.left+t.clientLeft,o=W(t)?ct(t):c(1);return{width:t.clientWidth*o.x,height:t.clientHeight*o.y,x:i*o.x,y:r*o.y}}(n,e);else{const e=ft(t);r={x:n.x-e.x,y:n.y-e.y,width:n.width,height:n.height}}return k(r)}function gt(t,n){const e=et(t);return!(e===n||!F(e)||X(e))&&(\"fixed\"===tt(e).position||gt(e,n))}function _t(t,n,e){const r=W(n),i=C(n),o=\"fixed\"===e,u=st(t,!0,o,n);let a={scrollLeft:0,scrollTop:0};const l=c(0);function f(){l.x=ht(i)}if(r||!r&&!o)if((\"body\"!==B(n)||U(i))&&(a=nt(n)),r){const t=st(n,!0,o,n);l.x=t.x+n.clientLeft,l.y=t.y+n.clientTop}else i&&f();o&&!r&&i&&f();const s=!i||r||o?c(0):pt(i,a);return{x:u.left+a.scrollLeft-l.x-s.x,y:u.top+a.scrollTop-l.y-s.y,width:u.width,height:u.height}}function yt(t){return\"static\"===tt(t).position}function mt(t,n){if(!W(t)||\"fixed\"===tt(t).position)return null;if(n)return n(t);let e=t.offsetParent;return C(t)===e&&(e=e.ownerDocument.body),e}function wt(t,n){const e=D(t);if(V(t))return e;if(!W(t)){let n=et(t);for(;n&&!X(n);){if(F(n)&&!yt(n))return n;n=et(n)}return e}let r=mt(t,n);for(;r&&q(r)&&yt(r);)r=mt(r,n);return r&&X(r)&&yt(r)&&!G(r)?e:r||function(t){let n=et(t);for(;W(n)&&!X(n);){if(G(n))return n;if(V(n))return null;n=et(n)}return null}(t)||e}const bt={convertOffsetParentRelativeRectToViewportRelativeRect:function(t){let{elements:n,rect:e,offsetParent:r,strategy:i}=t;const o=\"fixed\"===i,u=C(r),a=!!n&&V(n.floating);if(r===u||a&&o)return e;let l={scrollLeft:0,scrollTop:0},f=c(1);const s=c(0),h=W(r);if((h||!h&&!o)&&((\"body\"!==B(r)||U(u))&&(l=nt(r)),W(r))){const t=st(r);f=ct(r),s.x=t.x+r.clientLeft,s.y=t.y+r.clientTop}const p=!u||h||o?c(0):pt(u,l);return{width:e.width*f.x,height:e.height*f.y,x:e.x*f.x-l.scrollLeft*f.x+s.x+p.x,y:e.y*f.y-l.scrollTop*f.y+s.y+p.y}},getDocumentElement:C,getClippingRect:function(t){let{element:n,boundary:e,rootBoundary:r,strategy:u}=t;const a=[...\"clippingAncestors\"===e?V(n)?[]:function(t,n){const e=n.get(t);if(e)return e;let r=it(t,[],!1).filter(t=>F(t)&&\"body\"!==B(t)),i=null;const o=\"fixed\"===tt(t).position;let u=o?et(t):t;for(;F(u)&&!X(u);){const n=tt(u),e=G(u);e||\"fixed\"!==n.position||(i=null),(o?!e&&!i:!e&&\"static\"===n.position&&i&&dt.has(i.position)||U(u)&&!e&&gt(t,u))?r=r.filter(t=>t!==u):i=n,u=et(u)}return n.set(t,r),r}(n,this._c):[].concat(e),r],c=a[0],l=a.reduce((t,e)=>{const r=vt(n,e,u);return t.top=o(r.top,t.top),t.right=i(r.right,t.right),t.bottom=i(r.bottom,t.bottom),t.left=o(r.left,t.left),t},vt(n,c,u));return{width:l.right-l.left,height:l.bottom-l.top,x:l.left,y:l.top}},getOffsetParent:wt,getElementRects:async function(t){const n=this.getOffsetParent||wt,e=this.getDimensions,r=await e(t.floating);return{reference:_t(t.reference,await n(t.floating),t.strategy),floating:{x:0,y:0,width:r.width,height:r.height}}},getClientRects:function(t){return Array.from(t.getClientRects())},getDimensions:function(t){const{width:n,height:e}=ut(t);return{width:n,height:e}},getScale:ct,isElement:F,isRTL:function(t){return\"rtl\"===tt(t).direction}};function xt(t,n){return t.x===n.x&&t.y===n.y&&t.width===n.width&&t.height===n.height}function It(t,n,e,r){void 0===r&&(r={});const{ancestorScroll:u=!0,ancestorResize:c=!0,elementResize:l=\"function\"==typeof ResizeObserver,layoutShift:f=\"function\"==typeof IntersectionObserver,animationFrame:s=!1}=r,h=at(t),p=u||c?[...h?it(h):[],...it(n)]:[];p.forEach(t=>{u&&t.addEventListener(\"scroll\",e,{passive:!0}),c&&t.addEventListener(\"resize\",e)});const d=h&&f?function(t,n){let e,r=null;const u=C(t);function c(){var t;clearTimeout(e),null==(t=r)||t.disconnect(),r=null}return function l(f,s){void 0===f&&(f=!1),void 0===s&&(s=1),c();const h=t.getBoundingClientRect(),{left:p,top:d,width:v,height:g}=h;if(f||n(),!v||!g)return;const _={rootMargin:-a(d)+\"px \"+-a(u.clientWidth-(p+v))+\"px \"+-a(u.clientHeight-(d+g))+\"px \"+-a(p)+\"px\",threshold:o(0,i(1,s))||1};let y=!0;function m(n){const r=n[0].intersectionRatio;if(r!==s){if(!y)return l();r?l(!1,r):e=setTimeout(()=>{l(!1,1e-7)},1e3)}1!==r||xt(h,t.getBoundingClientRect())||l(),y=!1}try{r=new IntersectionObserver(m,{..._,root:u.ownerDocument})}catch(t){r=new IntersectionObserver(m,_)}r.observe(t)}(!0),c}(h,e):null;let v,g=-1,_=null;l&&(_=new ResizeObserver(t=>{let[r]=t;r&&r.target===h&&_&&(_.unobserve(n),cancelAnimationFrame(g),g=requestAnimationFrame(()=>{var t;null==(t=_)||t.observe(n)})),e()}),h&&!s&&_.observe(h),_.observe(n));let y=s?st(t):null;return s&&function n(){const r=st(t);y&&!xt(y,r)&&e();y=r,v=requestAnimationFrame(n)}(),e(),()=>{var t;p.forEach(t=>{u&&t.removeEventListener(\"scroll\",e),c&&t.removeEventListener(\"resize\",e)}),null==d||d(),null==(t=_)||t.disconnect(),_=null,s&&cancelAnimationFrame(v)}}const Et=function(t){return void 0===t&&(t=0),{name:\"offset\",options:t,async fn(n){var e,r;const{x:i,y:o,placement:u,middlewareData:a}=n,c=await async function(t,n){const{placement:e,platform:r,elements:i}=t,o=await(null==r.isRTL?void 0:r.isRTL(i.floating)),u=p(e),a=d(e),c=\"y\"===m(e),l=L.has(u)?-1:1,f=o&&c?-1:1,s=h(n,t);let{mainAxis:v,crossAxis:g,alignmentAxis:_}=\"number\"==typeof s?{mainAxis:s,crossAxis:0,alignmentAxis:null}:{mainAxis:s.mainAxis||0,crossAxis:s.crossAxis||0,alignmentAxis:s.alignmentAxis};return a&&\"number\"==typeof _&&(g=\"end\"===a?-1*_:_),c?{x:g*f,y:v*l}:{x:v*l,y:g*f}}(n,t);return u===(null==(e=a.offset)?void 0:e.placement)&&null!=(r=a.arrow)&&r.alignmentOffset?{}:{x:i+c.x,y:o+c.y,data:{...c,placement:u}}}}},At=function(t){return void 0===t&&(t={}),{name:\"shift\",options:t,async fn(n){const{x:e,y:r,placement:i,platform:o}=n,{mainAxis:u=!0,crossAxis:a=!1,limiter:c={fn:t=>{let{x:n,y:e}=t;return{x:n,y:e}}},...l}=h(t,n),f={x:e,y:r},d=await o.detectOverflow(n,l),g=m(p(i)),_=v(g);let y=f[_],w=f[g];if(u){const t=\"y\"===_?\"bottom\":\"right\";y=s(y+d[\"y\"===_?\"top\":\"left\"],y,y-d[t])}if(a){const t=\"y\"===g?\"bottom\":\"right\";w=s(w+d[\"y\"===g?\"top\":\"left\"],w,w-d[t])}const b=c.fn({...n,[_]:y,[g]:w});return{...b,data:{x:b.x-e,y:b.y-r,enabled:{[_]:u,[g]:a}}}}}},Rt=function(t){return void 0===t&&(t={}),{name:\"flip\",options:t,async fn(n){var e,r;const{placement:i,middlewareData:o,rects:u,initialPlacement:a,platform:c,elements:l}=n,{mainAxis:f=!0,crossAxis:s=!0,fallbackPlacements:v,fallbackStrategy:_=\"bestFit\",fallbackAxisSideDirection:y=\"none\",flipAlignment:x=!0,...I}=h(t,n);if(null!=(e=o.arrow)&&e.alignmentOffset)return{};const E=p(i),A=m(a),k=p(a)===a,O=await(null==c.isRTL?void 0:c.isRTL(l.floating)),S=v||(k||!x?[j(a)]:function(t){const n=j(t);return[b(t),n,b(n)]}(a)),L=\"none\"!==y;!v&&L&&S.push(...R(a,x,y,O));const T=[a,...S],B=await c.detectOverflow(n,I),D=[];let C=(null==(r=o.flip)?void 0:r.overflows)||[];if(f&&D.push(B[E]),s){const t=function(t,n,e){void 0===e&&(e=!1);const r=d(t),i=w(t),o=g(i);let u=\"x\"===i?r===(e?\"end\":\"start\")?\"right\":\"left\":\"start\"===r?\"bottom\":\"top\";return n.reference[o]>n.floating[o]&&(u=j(u)),[u,j(u)]}(i,u,O);D.push(B[t[0]],B[t[1]])}if(C=[...C,{placement:i,overflows:D}],!D.every(t=>t<=0)){var z,F;const t=((null==(z=o.flip)?void 0:z.index)||0)+1,n=T[t];if(n){if(!(\"alignment\"===s&&A!==m(n))||C.every(t=>m(t.placement)!==A||t.overflows[0]>0))return{data:{index:t,overflows:C},reset:{placement:n}}}let e=null==(F=C.filter(t=>t.overflows[0]<=0).sort((t,n)=>t.overflows[1]-n.overflows[1])[0])?void 0:F.placement;if(!e)switch(_){case\"bestFit\":{var W;const t=null==(W=C.filter(t=>{if(L){const n=m(t.placement);return n===A||\"y\"===n}return!0}).map(t=>[t.placement,t.overflows.filter(t=>t>0).reduce((t,n)=>t+n,0)]).sort((t,n)=>t[1]-n[1])[0])?void 0:W[0];t&&(e=t);break}case\"initialPlacement\":e=a}if(i!==e)return{reset:{placement:e}}}return{}}}},jt=(t,n,e)=>{const r=new Map,i={platform:bt,...e},o={...i.platform,_c:r};return(async(t,n,e)=>{const{placement:r=\"bottom\",strategy:i=\"absolute\",middleware:o=[],platform:u}=e,a=o.filter(Boolean),c=await(null==u.isRTL?void 0:u.isRTL(n));let l=await u.getElementRects({reference:t,floating:n,strategy:i}),{x:f,y:s}=O(l,r,c),h=r,p={},d=0;for(let e=0;e<a.length;e++){var v;const{name:o,fn:g}=a[e],{x:_,y,data:m,reset:w}=await g({x:f,y:s,initialPlacement:r,placement:h,strategy:i,middlewareData:p,rects:l,platform:{...u,detectOverflow:null!=(v=u.detectOverflow)?v:S},elements:{reference:t,floating:n}});f=null!=_?_:f,s=null!=y?y:s,p={...p,[o]:{...p[o],...m}},w&&d<=50&&(d++,\"object\"==typeof w&&(w.placement&&(h=w.placement),w.rects&&(l=!0===w.rects?await u.getElementRects({reference:t,floating:n,strategy:i}):w.rects),({x:f,y:s}=O(l,h,c))),e=-1)}return{x:f,y:s,placement:h,strategy:i,middlewareData:p}})(t,n,{...i,platform:o})},kt=\"filter_uninteresting\",Ot=\"filter_import_system\",St=\"filter_thread\";var Lt=null,Tt=null;let Bt=new class{constructor(){this.filters={}}registerFilter(t,n){this.filters[t]=n}unRegisterFilter(t){delete this.filters[t]}drawChart(t){let n=t;_.forOwn(this.filters,t=>{n=t(n)}),function(t){let n=!Lt||Lt.inverted();Lt&&(Lt.destroy(),Tt&&(Tt.destroy(),Tt=null),d3.selectAll(\".d3-flame-graph-tip\").remove());Tt=function(){const t=document.createElement(\"div\");t.className=\"d3-flame-graph-tip\",t.style.position=\"fixed\",t.style.top=\"0\",t.style.left=\"0\",t.style.visibility=\"hidden\",t.style.pointerEvents=\"none\",document.body.appendChild(t);let n=null,e=null,i=\"top\";const o=()=>{e&&jt(e,t,{strategy:\"fixed\",placement:i,middleware:[Et(6),Rt(),At({padding:8})]}).then(({x:n,y:e})=>{t.style.left=`${n}px`,t.style.top=`${e}px`})},u=function(){return u};return u.show=(u,a)=>{if(!u||!a)return;const c=(0,r.bn)(u.data.value);t.innerHTML=(0,r.ni)(u.data,c,merge_threads),i=function(t){if(\"s\"===t)return\"bottom\";if(\"e\"===t)return\"right\";if(\"w\"===t)return\"left\";return\"top\"}(function(t){const n=(t.x1+t.x0)/2;if(.25<n&&n<.75)return\"s\";if(t.x1<.75)return\"e\";if(t.x0>.25)return\"w\";return\"n\"}(u)),e=a,t.style.visibility=\"visible\",n&&n(),n=It(e,t,o),o()},u.hide=()=>{e=null,t.style.visibility=\"hidden\",n&&(n(),n=null)},u.destroy=()=>{u.hide(),t.remove()},u}(),Lt=flamegraph().width(Ut()).transitionDuration(250).transitionEase(d3.easeCubic).inverted(n).cellHeight(20).minFrameSize(2).setColorMapper(Zt).onClick(Wt).tooltip(Tt),d3.select(\"#chart\").datum(t).call(Lt),Lt.width(Ut())}(n),Lt.merge([])}};function Dt(){return Lt}function Ct(){return Bt}function zt(){return location.hash?parseInt(location.hash.substring(1),10):0}function Ft(){document.getElementById(\"resetZoomButton\").disabled=0==zt()}function Wt(t){t.id!=zt()&&(history.pushState({id:t.id},t.data.name,`#${t.id}`),Ft())}function Pt(){const t=zt(),n=Lt.findById(t);n&&(Lt.zoomTo(n),Ft())}function Nt(){Lt.inverted(this===document.getElementById(\"icicles\")),Lt.resetZoom(),$('[data-toggle=\"tooltip\"]').tooltip(\"hide\")}function $t(){Lt.resetZoom()}function Ut(){return document.getElementById(\"chart\").clientWidth}function Mt(){Bt.drawChart(data),location.hash&&Pt()}function qt(){const t=this.dataset.thread;\"-0x1\"===t?Bt.unRegisterFilter(St):Bt.registerFilter(St,n=>{let e=(0,r.Qx)(n,t);const i=(0,r.P2)(e.children);return _.defaults(i,e),e.n_allocations=i.n_allocations,e.value=i.value,e}),Bt.drawChart(data)}function Ht(){void 0===this.hideUninterestingFrames&&(this.hideUninterestingFrames=!0),!0===this.hideUninterestingFrames?(this.hideUninterestingFrames=!0,Bt.registerFilter(kt,t=>(0,r.kO)(t))):Bt.unRegisterFilter(kt),this.hideUninterestingFrames=!this.hideUninterestingFrames,Bt.drawChart(data)}function Vt(){void 0===this.hideImportSystemFrames&&(this.hideImportSystemFrames=!0),!0===this.hideImportSystemFrames?(this.hideImportSystemFrames=!0,inverted?(data=invertedNoImportsData,temporal&&(hideImports=!0,intervals=invertedNoImportsIntervals)):Bt.registerFilter(Ot,t=>(0,r.Hw)(t))):(Bt.unRegisterFilter(Ot),data=flamegraphData,temporal&&(hideImports=!1,intervals=flamegraphIntervals)),this.hideImportSystemFrames=!this.hideImportSystemFrames,Bt.drawChart(data)}function Zt(t,n){return t.highlight?\"orange\":t.data.name&&t.data.location?(r=t.data.location[1],\"py\"==(e=void 0===r?r:r.substring(r.lastIndexOf(\".\")+1,r.length)||r)?d3.schemePastel1[2]:\"c\"==e||\"cpp\"==e||\"h\"==e?d3.schemePastel1[5]:d3.schemePastel1[8]):\"#EEE\";var e,r}function Kt(t,n){if(!0===n)return;const e=t.unique_threads;if(!e||e.length<=1)return;document.getElementById(\"threadsDropdown\").removeAttribute(\"hidden\");const r=document.getElementById(\"threadsDropdownList\");for(const t of e){let n=document.createElement(\"a\");n.className=\"dropdown-item\",n.dataset.thread=t,n.text=t,n.onclick=qt,r.appendChild(n)}}}},n={};function e(r){var i=n[r];if(void 0!==i)return i.exports;var o=n[r]={id:r,loaded:!1,exports:{}};return t[r].call(o.exports,o,o.exports,e),o.loaded=!0,o.exports}e.n=t=>{var n=t&&t.__esModule?()=>t.default:()=>t;return e.d(n,{a:n}),n},e.d=(t,n)=>{for(var r in n)e.o(n,r)&&!e.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:n[r]})},e.g=function(){if(\"object\"==typeof globalThis)return globalThis;try{return this||new Function(\"return this\")()}catch(t){if(\"object\"==typeof window)return window}}(),e.o=(t,n)=>Object.prototype.hasOwnProperty.call(t,n),e.nmd=t=>(t.paths=[],t.children||(t.children=[]),t),(()=>{\"use strict\";var t=e(224),n=e(279),r=null,i=null,o=a(packed_data.nodes),u=inverted?a(packed_data.inverted_no_imports_nodes):null;function a(t){let n=new Array(t.children.length);console.log(\"finding parent index for each node\");for(const[e,r]of t.children.entries())r.forEach(t=>n[t]=e);return console.assert(void 0===n[0],\"root node has a parent\"),n}function c(t,n){console.log(\"constructing nodes\");const e=n.name.map((e,r)=>({name:t[n.name[r]],location:[t[n.function[r]],t[n.filename[r]],n.lineno[r]],value:0,children:n.children[r],n_allocations:0,thread_id:t[n.thread_id[r]],interesting:0!==n.interesting[r],import_system:0!==n.import_system[r]}));console.log(\"mapping child indices to child nodes\");for(const[t,n]of e.entries())n.children=n.children.map(t=>e[t]);return e}function l(t,n,e,r){t.forEach(t=>{let[i,o,u,a,c]=t;if(i<=e&&(null===o||o>e))for(;void 0!==u;)n[u].n_allocations+=a,n[u].value+=c,u=r[u]})}function f(t,n,e,r,i){t.forEach(t=>{let[o,u,a,c,l]=t;if(o>=e&&o<=r&&(null===u||u>r))for(;void 0!==a;)n[a].n_allocations+=c,n[a].value+=l,a=i[a]})}function s(t,n,e){const{flamegraphNodeObjects:r,invertedNoImportsNodeObjects:i}=function(t){const{strings:n,nodes:e,inverted_no_imports_nodes:r,unique_threads:i,intervals:o,no_imports_interval_list:u}=t,a=c(n,e),l=inverted?c(n,r):null;return flamegraphIntervals=o,invertedNoImportsIntervals=u,{flamegraphNodeObjects:a,invertedNoImportsNodeObjects:l}}(t),a=t.high_water_mark_by_snapshot;if(a){console.log(\"finding highest high water mark in range\");let t=n,c=a[n];for(let r=n;r<=e;++r)a[r]>c&&(c=a[r],t=r);console.log(\"highest water mark between \"+n+\" and \"+e+\" is \"+c+\" at \"+t);let f,s,h={shapes:[]};t==memory_records.length?(h[\"xaxis.range[1]\"]=new Date(memory_records.at(-1)[0]+10),f=new Date(memory_records.at(-1)[0]),s=new Date(memory_records.at(-1)[0]+10)):0==t?(h[\"xaxis.range[0]\"]=new Date(memory_records[0][0]-10),f=new Date(memory_records[0][0]-10),s=new Date(memory_records[0][0])):(f=new Date(memory_records[t-1][0]),s=new Date(memory_records[t][0])),h.shapes=[{type:\"rect\",xref:\"x\",yref:\"paper\",x0:f,y0:0,x1:s,y1:1,fillcolor:\"#fbff00\",opacity:.2,line:{width:0}}],Plotly.relayout(\"plot\",h),console.log(\"finding hwm allocations\"),l(flamegraphIntervals,r,t,o),inverted&&l(invertedNoImportsIntervals,i,t,u)}else console.log(\"finding leaked allocations\"),f(flamegraphIntervals,r,n,e,o),inverted&&f(invertedNoImportsIntervals,i,n,e,u);r.forEach(t=>{t.children=t.children.filter(t=>t.n_allocations>0)}),inverted&&i.forEach(t=>{t.children=t.children.filter(t=>t.n_allocations>0)}),flamegraphData=r[0],invertedNoImportsData=inverted?i[0]:null}function h(t){console.log(\"refreshing flame graph!\");let e=function(t){console.log(\"getRangeData\");let n={};if(t.hasOwnProperty(\"xaxis.range[0]\"))n={string1:t[\"xaxis.range[0]\"],string2:t[\"xaxis.range[1]\"]};else if(t.hasOwnProperty(\"xaxis.range\"))n={string1:t[\"xaxis.range\"][0],string2:t[\"xaxis.range\"][1]};else{if(null===r)return;{let t=r.layout.xaxis.range;n={string1:t[0],string2:t[1]}}}return n}(t);if(console.log(\"range data: \"+JSON.stringify(e)),null!=i&&JSON.stringify(e)===JSON.stringify(i))return;console.log(\"showing loading animation\"),console.log(\"showLoadingAnimation\"),document.getElementById(\"loading\").style.display=\"block\",document.getElementById(\"overlay\").style.display=\"block\",i=e,console.log(\"finding range of relevant snapshot\");let o=0,u=memory_records.length;if(e){const t=new Date(e.string1).getTime(),n=memory_records.findIndex(n=>n[0]>=t);-1!=n&&(o=n);const r=new Date(e.string2).getTime(),i=memory_records.findIndex(t=>t[0]>r);-1!=i&&(u=i)}console.log(\"start index is \"+o),console.log(\"end index is \"+u),console.log(\"first possible index is 0\"),console.log(\"last possible index is \"+memory_records.length),console.log(\"constructing tree\"),s(packed_data,o,u),data=inverted&&hideImports?invertedNoImportsData:flamegraphData,intervals=inverted&&hideImports?invertedNoImportsIntervals:flamegraphIntervals,console.log(\"total allocations in range: \"+data.n_allocations),console.log(\"total bytes in range: \"+data.value),console.log(\"drawing chart\"),(0,n.Iv)().drawChart(data),console.log(\"hiding loading animation\"),console.log(\"hideLoadingAnimation\"),document.getElementById(\"loading\").style.display=\"none\",document.getElementById(\"overlay\").style.display=\"none\"}var p=null;function d(t){console.log(\"refreshFlamegraphDebounced\"),p&&clearTimeout(p),p=setTimeout(function(){h(t)},500)}document.addEventListener(\"DOMContentLoaded\",function(){console.log(\"main\");const e=packed_data.unique_threads.map(t=>packed_data.strings[t]);(0,n.zb)({unique_threads:e},merge_threads),function(t){console.log(\"init memory graph\");const n=t.map(t=>new Date(t[0])),e=t.map(t=>t[1]),i=t.map(t=>t[2]),o=t.length>1?\"lines\":\"markers\";var u=[{x:n,y:e,mode:o,name:\"Resident size\"},{x:n,y:i,mode:o,name:\"Heap size\"}];Plotly.newPlot(\"plot\",u,{xaxis:{title:{text:\"Time\"},rangeslider:{visible:!0}},yaxis:{title:{text:\"Memory Size\"},tickformat:\".4~s\",exponentformat:\"B\",ticksuffix:\"B\"}},{responsive:!0,displayModeBar:!1}).then(t=>{console.assert(null===r),r=t})}(memory_records),h({}),location.hash&&(0,n.kj)(),document.getElementById(\"icicles\").onchange=n.Ke,document.getElementById(\"flames\").onchange=n.Ke,document.getElementById(\"resetZoomButton\").onclick=n.mU,document.getElementById(\"resetThreadFilterItem\").onclick=n.un,document.getElementById(\"hideUninteresting\").onclick=n.bt.bind(this),document.getElementById(\"hideImportSystem\").onclick=n.Yu.bind(this),n.bt.bind(this)(),document.onkeyup=t=>{\"Escape\"==t.code&&(0,n.mU)()},document.getElementById(\"searchTerm\").addEventListener(\"input\",()=>{const t=document.getElementById(\"searchTerm\");(0,n.QA)().search(t.value)}),window.addEventListener(\"popstate\",n.kj),window.addEventListener(\"resize\",(0,t.qr)(n.EV)),$('[data-toggle-second=\"tooltip\"]').tooltip(),$('[data-toggle=\"tooltip\"]').tooltip(),console.log(\"setup reload handler\"),document.getElementById(\"plot\").on(\"plotly_relayout\",d),[].slice.call(document.querySelectorAll(\".toast\")).map(function(t){return new bootstrap.Toast(t,{delay:1e4})}).forEach(t=>t.show())})})()})();"
  },
  {
    "path": "src/memray/reporters/templates/base.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n\n<head>\n  <meta charset=\"utf-8\" />\n  <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n  <title>memray - {{ title }}</title>\n\n  {%- block styles -%}\n  {% if no_web %}\n  <style>{% include \"assets/vendor/bootstrap.min.css\" %}</style>\n  {% else %}\n  <link rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css\">\n  {% endif %}\n  {%- endblock styles -%}\n</head>\n\n<body>\n  <!-- Header -->\n  <nav class=\"navbar sticky-top navbar-dark bg-dark\">\n    <a class=\"navbar-brand\" href=\"#\">\n      <span class=\"navbar-brand mb-0 mr-2 h1\">memray</span> {{ title }}\n    </a>\n    <div class=\"form-inline\">\n      {% if metadata.python_allocator == 'pymalloc' %}\n      <div class=\"mr-3\">\n        <span class=\"badge badge-primary\" data-toggle=\"tooltip\" data-placement=\"bottom\"\n        title=\" The pymalloc allocator holds pools of memory and only allocates\n        when all these pools are used. This means that allocations reported when\n        pymalloc is active will reflect only the allocations that happen when\n        the pools are full. <b>This is what happens at runtime</b> so it is fully\n        representative of a normal application but <b>the number of allocations\n        and the size may not correspond with the number of Python objects\n        created</b> (as pymalloc is reusing memory).\"\n        data-html=\"true\">\n        Python Allocator: {{metadata.python_allocator}}</span>\n      </div>\n      {% else %}\n      <div class=\"mr-3\">\n        <span class=\"badge badge-success\">Python Allocator: {{metadata.python_allocator}}</span>\n      </div>\n      {% endif %}\n      <div class=\"btn-toolbar\">\n        {% block topbar_buttons %}\n        {% endblock topbar_buttons %}\n        <button type=\"button\" class=\"btn btn-outline-light mr-3\" data-toggle=\"modal\" data-target=\"#statsModal\">Stats</button>\n        <button type=\"button\" class=\"btn btn-outline-light mr-3\" data-toggle=\"modal\" data-target=\"#helpModal\">Help</button>\n      </div>\n      {% block topbar_search %}\n      <input id=\"searchTerm\" class=\"form-control\" type=\"search\" placeholder=\"Search\">\n      {% endblock topbar_search %}\n    </div>\n  </nav>\n  {% block extra_nav %}\n  {% endblock extra_nav %}\n\n  <!-- Main Content -->\n  <main class=\"container-fluid\">\n    <div class=\"row\">\n      <div class=\"col bg-light py-3\">\n        {% if show_memory_leaks\n           and metadata.python_allocator != \"malloc\"\n           and metadata.python_allocator != \"malloc_debug\"\n           and not metadata.trace_python_allocators %}\n        <div class=\"alert alert-warning alert-dismissible fade show\" role=\"alert\">\n          <p><strong>Report generated using <code>--leaks</code> with an arena allocator</strong></p>\n          <p>\n            This memory leaks report was generated with the {{metadata.python_allocator}}\n            allocator active, but without tracking enabled for object\n            deallocations. This will show misleading results because the\n            allocator retains memory in memory pools even after the objects\n            that requested that memory are deallocated, and Memray won't be\n            able to distinguish memory set aside for reuse from leaked memory.\n            For a more useful memory leaks report, you should pass the\n            <code>--trace-python-allocators</code> flag when profiling your application.\n            <a href=\"https://bloomberg.github.io/memray/python_allocators.html\">\n            Click here</a> for more information.\n          </p>\n          <button type=\"button\" class=\"close\" data-dismiss=\"alert\" aria-label=\"Close\">\n            <span aria-hidden=\"true\">&times;</span>\n          </button>\n        </div>\n        {% endif %}\n\n        {% block content %}\n        [memray debug] Please place your content here.\n        {% endblock content %}\n      </div>\n    </div>\n  </main>\n\n  <!-- Stats Modal -->\n  <div class=\"modal fade\" id=\"statsModal\" tabindex=\"-1\" role=\"dialog\" aria-labelledby=\"statsModalLabel\" aria-hidden=\"true\">\n    <div class=\"modal-dialog modal-lg\" role=\"document\">\n      <div class=\"modal-content\">\n        <div class=\"modal-header\">\n          <h5 class=\"modal-title\" id=\"statsModalLabel\">Memray run stats</h5>\n          <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-label=\"Close\">\n            <span aria-hidden=\"true\">&times;</span>\n          </button>\n        </div>\n        <div class=\"modal-body\">\n          Command line: <code>{{ metadata.command_line|e }}</code><br>\n          Start time: <span id=\"stats-start-time\"> {{ metadata.start_time }}</span><br>\n          End time: <span id=\"stats-end-time\"> {{ metadata.end_time }}</span><br>\n          Duration: {{ metadata.end_time - metadata.start_time }}<br>\n          Total number of allocations: {{ metadata.total_allocations }}<br>\n          Total number of frames seen: {{ metadata.total_frames }}<br>\n          Peak memory usage: {{ metadata.peak_memory | filesizeformat }}<br>\n          Python allocator: {{ metadata.python_allocator }}<br>\n        </div>\n        <div class=\"modal-footer\">\n          <button type=\"button\" class=\"btn btn-primary\" data-dismiss=\"modal\">Close</button>\n        </div>\n      </div>\n    </div>\n  </div>\n\n  <!-- Help Modal -->\n  <div class=\"modal fade\" id=\"helpModal\" tabindex=\"-1\" role=\"dialog\" aria-labelledby=\"helpModalLabel\" aria-hidden=\"true\">\n    <div class=\"modal-dialog modal-lg\" role=\"document\">\n      <div class=\"modal-content\">\n        <div class=\"modal-header\">\n          <h5 class=\"modal-title\" id=\"helpModalLabel\">How to interpret {{ kind }} reports</h5>\n          <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-label=\"Close\">\n            <span aria-hidden=\"true\">&times;</span>\n          </button>\n        </div>\n        <div class=\"modal-body\">\n          {% block help %}\n          [memray debug] Place your help here.\n          {% endblock help %}\n        </div>\n        <div class=\"modal-footer\">\n          <button type=\"button\" class=\"btn btn-primary\" data-dismiss=\"modal\">Close</button>\n        </div>\n      </div>\n    </div>\n  </div>\n\n  {% block extra_modal %}\n  {% endblock extra_modal %}\n\n  {% block scripts %}\n  {% if no_web %}\n  <script type=\"text/javascript\">{{ include_file(\"assets/vendor/popper.min.js\") }}</script>\n  <script type=\"text/javascript\">{{ include_file(\"assets/vendor/jquery.min.js\") }}</script>\n  <script type=\"text/javascript\">{{ include_file(\"assets/vendor/bootstrap.min.js\") }}</script>\n  <script type=\"text/javascript\">{{ include_file(\"assets/vendor/lodash.min.js\") }}</script>\n  <script type=\"text/javascript\">{{ include_file(\"assets/vendor/plotly.min.js\") }}</script>\n  {% else %}\n  <script src=\"https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js\"></script>\n  <script src=\"https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js\"></script>\n  <script src=\"https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/js/bootstrap.min.js\"></script>\n  <script src=\"https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js\"></script>\n  <script src=\"https://cdn.jsdelivr.net/npm/plotly.js@2.11.1/dist/plotly.min.js\"></script>\n  {% endif %}\n  <script type=\"text/javascript\">\n    const packed_data = {{ data|tojson }};\n    var data = null;\n    var flamegraphData = null;\n    var invertedNoImportsData = null;\n    const merge_threads = {{ merge_threads|tojson }};\n    const memory_records = {{ memory_records|tojson }};\n    const inverted = {{ inverted|tojson }};\n    const temporal = packed_data.intervals != null;\n  </script>\n  {% endblock scripts %}\n</body>\n\n</html>\n"
  },
  {
    "path": "src/memray/reporters/templates/classic_base.html",
    "content": "{# Extends base.html and adds zoomable memory chart without sliders. #}\n{% extends \"base.html\" %}\n\n{% block topbar_buttons %}\n{{ super() }}\n<button id=\"memoryGraphButton\" class=\"btn btn-outline-light mr-3\" data-toggle=\"modal\" data-target=\"#memoryModal\" onclick=\"javascript:resizeMemoryGraph();\">Memory Graph</button>\n{% endblock %}\n\n{% block extra_nav %}\n<nav class=\"navbar navbar-dark bg-dark px-0\">\n  <div id=\"smallMemoryGraph\" class=\"w-100\" data-toggle=\"modal\" data-target=\"#memoryModal\" onclick=\"javascript:resizeMemoryGraph();\"></div>\n</nav>\n{% endblock %}\n\n{% block extra_modal %}\n  <!-- Memory Modal -->\n  <div class=\"modal fade\" id=\"memoryModal\" tabindex=\"-1\" role=\"dialog\" aria-labelledby=\"memoryModalLabel\" aria-hidden=\"true\">\n    <div class=\"modal-dialog modal-xl\" role=\"document\">\n      <div class=\"modal-content\">\n        <div class=\"modal-header\">\n          <h5 class=\"modal-title\" id=\"memoryModalLabel\">Resident set size over time</h5>\n          <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-label=\"Close\">\n            <span aria-hidden=\"true\">&times;</span>\n          </button>\n        </div>\n        <div class=\"modal-body\">\n          <div id=\"memoryGraph\"></div>\n        </div>\n        <div class=\"modal-footer\">\n          <button type=\"button\" class=\"btn btn-primary\" data-dismiss=\"modal\">Close</button>\n        </div>\n      </div>\n    </div>\n  </div>\n{% endblock %}\n"
  },
  {
    "path": "src/memray/reporters/templates/flamegraph.html",
    "content": "{% extends \"classic_base.html\" %}\n\n{% block topbar_buttons %}\n<div class=\"dropdown\" id=\"threadsDropdown\" hidden>\n  <button class=\"btn btn-outline-light dropdown-toggle mr-3\" type=\"button\" id=\"threadsDropdownButton\" data-toggle=\"dropdown\"\n          aria-haspopup=\"true\" aria-expanded=\"false\" data-toggle-second=\"tooltip\" data-placement=\"right\"\n          title=\"Display only the selected thread\">\n    Filter Thread\n  </button>\n  <div class=\"dropdown-menu\" aria-labelledby=\"threadsDropdownButton\" id=\"threadsDropdownList\">\n    <a class=\"dropdown-item\" data-thread=\"-0x1\" id=\"resetThreadFilterItem\">Reset</a>\n  </div>\n</div>\n<div class=\"form-check mr-3\">\n  <input class=\"form-check-input\" type=\"checkbox\" data-toggle=\"tooltip\" id=\"hideUninteresting\"\n          title=\"Hide CPython eval frames and Memray-related frames\" checked>\n    <label class=\"form-check-label text-white bg-dark\">Hide Irrelevant Frames</label>\n</div>\n<div class=\"form-check mr-3\">\n  <input class=\"form-check-input\" type=\"checkbox\" data-toggle=\"tooltip\" id=\"hideImportSystem\"\n          title=\"Hide frames related to the Python import system\" >\n    <label class=\"form-check-label text-white bg-dark\">Hide Import System Frames</label>\n</div>\n<div class=\"btn-group btn-group-toggle mr-3\" data-toggle=\"buttons\">\n  <label class=\"btn btn-outline-light shadow-none\" data-container=\"body\" data-toggle=\"tooltip\" title=\"Enable flame graph mode: functions above their callers with the root at the bottom\">\n    <input type=\"radio\" name=\"flames/icicles\" id=\"flames\" autocomplete=\"off\">\n    <div class=\"flamegraph-icon flipped\">\n      <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" stroke-width=\"1\" stroke=\"currentColor\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n        <path d=\"M 1 1 h 22 Z M 11 6 h 10 Z M 1 6 h 7 Z M 11 11 h 7 Z M 1 11 h 4 Z M 11 16 h 4 Z M 1 16 h 2 Z M 11 21 h 2 Z\"/>\n      </svg>\n    </div>\n    &nbsp;\n    Flames\n  </label>\n  <label class=\"btn btn-outline-light active shadow-none\" data-container=\"body\" data-toggle=\"tooltip\" title=\"Enable icicle graph mode: functions below their callers with the root at the top\">\n    <input type=\"radio\" name=\"flames/icicles\" id=\"icicles\" autocomplete=\"off\" checked/>\n    Icicles\n    &nbsp;\n    <div class=\"flamegraph-icon\">\n      <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" stroke-width=\"1\" stroke=\"currentColor\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n        <path d=\"M 1 1 h 22 Z M 11 6 h 10 Z M 1 6 h 7 Z M 11 11 h 7 Z M 1 11 h 4 Z M 11 16 h 4 Z M 1 16 h 2 Z M 11 21 h 2 Z\"/>\n      </svg>\n    </div>\n  </label>\n</div>\n<button id=\"resetZoomButton\" class=\"btn btn-outline-light mr-3\">Reset Zoom</button>\n{% if kind == \"flamegraph\" %}\n{{ super() }}\n{% endif %}\n{% endblock %}\n\n{% block content %}\n<div class=\"chart-container\">\n  <div id=\"chart\"></div>\n</div>\n{% endblock %}\n\n{% block help %}\n{% if show_memory_leaks %}\n<p>\n  The flame graph displays stack frames at allocation, for memory that was leaked during the tracking period (i.e. allocated and not deallocated).\n</p>\n<div class=\"alert alert-warning\" role=\"alert\">\n  Note that the Python allocator doesn't necessarily release memory to the system when Python objects are deallocated and these can still appear as \"leaks\". If you want to exclude these, you can run your application with the `PYTHONMALLOC=malloc` environment variable set.\n</div>\n{% else %}\n<p>\n  The flame graph displays a snapshot of memory used across stack frames at the time <b>when the memory usage was at its peak</b>.\n</p>\n{% endif %}\n{% block slider_help %}\n{% endblock %}\n<p>\n  The vertical ordering of the stack frames corresponds to the order of function calls, from parent to children.\n  The horizontal ordering does not represent the passage of time in the application: they simply represent child frames in arbitrary order.\n</p>\n<p>\n  On the flame graph, each bar represents a stack frame and shows the code which triggered the memory allocation.\n  Hovering over the frame you can also see the overall memory allocated in the given frame and its children and the number of times allocations have occurred.\n</p>\n<p>\n  The <b>Show/Hide Irrelevant Frames</b> button can be used to reveal and hide frames which contain allocations in code which might not be\n  relevant for the application. These include frames in the CPython eval loop as well as frames introduced by memray during the analysis.\n</p>\n<p>\n  You can find more information in the <a target=\"_blank\"  href=\"https://bloomberg.github.io/memray/flamegraph.html\">documentation</a>.\n</p>\n{% endblock %}\n\n{% block styles %}\n{{ super() }}\n<style>{% include \"assets/flamegraph.css\" %}</style>\n{% endblock %}\n\n{% block scripts %}\n{{ super() }}\n{% if no_web %}\n<script type=\"text/javascript\">{{ include_file(\"assets/vendor/d3.min.js\") }}</script>\n<script type=\"text/javascript\">{{ include_file(\"assets/vendor/d3-scale-chromatic.min.js\") }}</script>\n<script type=\"text/javascript\">{{ include_file(\"assets/vendor/d3-flamegraph.min.js\") }}</script>\n{% else %}\n<script src=\"https://cdn.jsdelivr.net/npm/d3@7.9.0/dist/d3.min.js\"></script>\n<script src=\"https://cdn.jsdelivr.net/npm/d3-scale-chromatic@3.1.0/dist/d3-scale-chromatic.min.js\"></script>\n<script src=\"https://cdn.jsdelivr.net/npm/d3-flame-graph@4.1.3/dist/d3-flamegraph.min.js\"></script>\n{% endif %}\n\n{% block flamegraph_script %}\n<script type=\"text/javascript\">\n  {{ include_file(\"assets/flamegraph.js\") }}\n</script>\n{% endblock %}\n\n{% endblock %}\n"
  },
  {
    "path": "src/memray/reporters/templates/table.html",
    "content": "{% extends \"classic_base.html\" %}\n\n{% block topbar_buttons %}\n{{ super() }}\n{% endblock %}\n\n{% block content %}\n<div class=\"chart-container\">\n  <table class=\"table table-striped\" id=\"the_table\">\n  </table>\n</div>\n{% endblock %}\n\n{% block help %}\n{% if show_memory_leaks %}\n<p>\n  The table reporter provides a simple tabular representation of memory\n  allocations, for memory that was leaked during the tracking period\n  (i.e. allocated and not deallocated).\n</p>\n<div class=\"alert alert-warning\" role=\"alert\">\n  Note that the Python allocator doesn't necessarily release memory to\n  the system when Python objects are deallocated and these can still\n  appear as \"leaks\". If you want to exclude these, you can run your\n  application with the `PYTHONMALLOC=malloc` environment variable set.\n</div>\n{% else %}\n<p>\n  The table reporter provides a simple tabular representation of memory\n  allocations in the target <b>when the memory usage was at its peak</b>.\n</p>\n{% endif %}\n<p>\n  You can find more information in the <a target=\"_blank\" href=\"https://bloomberg.github.io/memray/table.html\">documentation</a>.\n</p>\n{% endblock %}\n\n{% block styles %}\n{{ super() }}\n<style>{% include \"assets/table.css\" %}</style>\n{% endblock %}\n\n{% block scripts %}\n{{ super() }}\n{% if no_web %}\n<script type=\"text/javascript\">{{ include_file(\"assets/vendor/jquery.dataTables.min.js\") }}</script>\n<script type=\"text/javascript\">{{ include_file(\"assets/vendor/dataTables.bootstrap4.min.js\") }}</script>\n{% else %}\n<script src=\"https://cdn.datatables.net/1.10.23/js/jquery.dataTables.min.js\"></script>\n<script src=\"https://cdn.datatables.net/1.10.23/js/dataTables.bootstrap4.min.js\"></script>\n{% endif %}\n<script type=\"text/javascript\">\n  {{ include_file(\"assets/table.js\") }}\n</script>\n{% endblock %}\n"
  },
  {
    "path": "src/memray/reporters/templates/temporal_flamegraph.html",
    "content": "{% extends \"flamegraph.html\" %}\n\n{% block content %}\n<div class=\"toast\" style=\"position: absolute; top: 5%; left: 40%; z-index: 100;\">\n  <div class=\"toast-header\">\n    <strong class=\"mr-auto\">How to use this plot</strong>\n    <button type=\"button\" class=\"ml-2 mb-1 close\" data-dismiss=\"toast\" aria-label=\"Close\">\n      <span aria-hidden=\"true\">&times;</span>\n    </button>\n  </div>\n  <div class=\"toast-body\">\n    You can move the plot slider to select different ranges for the flame\n    graph. The flame graph shows the allocations that are created in the\n    selected range that are not deallocated before the end of the range.\n  </div>\n</div>\n<div id=\"overlay\" style=\"display: none;\"></div>\n<div class=\"chart-container\">\n  <div id=\"loading\" style=\"display: none; z-index: 100;\">\n    <div class=\"loading-spinner\"></div>\n    <p>Loading...</p>\n  </div>\n\n  <div id=\"plot\"></div>\n  <div id=\"chart\"></div>\n</div>\n{% endblock %}\n\n{% block slider_help %}\n<p>\n  Initially the report shows allocations made at any time and not freed before\n  tracking was deactivated. By using the two sliders on the bottom line chart,\n  you can select a different time range for analysis instead. The flame graph\n  will be updated to reflect allocations made within your chosen time window\n  and not freed within it.\n</p>\n{% endblock %}\n\n{% block flamegraph_script %}\n<script type=\"text/javascript\">\n  {{ include_file(\"assets/temporal_flamegraph.js\") }}\n  var hideImports = false;\n  var intervals = null;\n  var flamegraphIntervals = null;\n  var invertedNoImportsIntervals = null;\n</script>\n{% endblock %}\n"
  },
  {
    "path": "src/memray/reporters/transform.py",
    "content": "import csv\nimport json\nfrom typing import Any\nfrom typing import Dict\nfrom typing import Iterable\nfrom typing import List\nfrom typing import TextIO\nfrom typing import Tuple\n\nfrom memray import AllocationRecord\nfrom memray import AllocatorType\nfrom memray import MemorySnapshot\nfrom memray import Metadata\nfrom memray.reporters.common import format_thread_name\n\nLocation = Tuple[str, str]\n\n\nclass TransformReporter:\n    SUFFIX_MAP = {\n        \"gprof2dot\": \".json\",\n        \"csv\": \".csv\",\n    }\n\n    def __init__(\n        self,\n        allocations: Iterable[AllocationRecord],\n        *,\n        format: str,\n        native_traces: bool,\n        memory_records: Iterable[MemorySnapshot],\n        **kwargs: Any,\n    ) -> None:\n        super().__init__()\n        self.allocations = allocations\n        self.format = format\n        self.native_traces = native_traces\n        self.memory_records = memory_records\n\n    def render_as_gprof2dot(\n        self,\n        outfile: TextIO,\n        **kwargs: Any,\n    ) -> None:\n        location_to_index: Dict[Location, int] = {}\n        all_locations: List[Dict[str, str]] = []\n        events = []\n        for record in self.allocations:\n            stack_trace = (\n                tuple(record.hybrid_stack_trace())\n                if self.native_traces\n                else record.stack_trace()\n            )\n            call_chain = []\n            for func, mod, _ in stack_trace:\n                location = (func, mod)\n                index = location_to_index.get(location)\n                if index is None:\n                    index = len(all_locations)\n                    all_locations.append({\"name\": func, \"module\": mod})\n                    location_to_index[location] = index\n                call_chain.append(index)\n\n            if not call_chain:\n                continue\n            events.append({\"callchain\": call_chain, \"cost\": [record.size]})\n\n        result = {\n            \"version\": 0,\n            \"costs\": [{\"description\": \"Memory\", \"unit\": \"bytes\"}],\n            \"events\": events,\n            \"functions\": all_locations,\n        }\n        json.dump(result, outfile)\n\n    def render(\n        self,\n        outfile: TextIO,\n        metadata: Metadata,\n        show_memory_leaks: bool,\n        merge_threads: bool,\n        inverted: bool,\n        no_web: bool = False,\n    ) -> None:\n        if not merge_threads:\n            raise NotImplementedError(\"TransformReporter only supports merged threads.\")\n        if inverted:\n            raise NotImplementedError(\n                \"TransformReporter does not support inverted argument.\"\n            )\n        renderer = getattr(self, f\"render_as_{self.format}\")\n        renderer(outfile, metadata=metadata, show_memory_leaks=show_memory_leaks)\n\n    def render_as_csv(\n        self,\n        outfile: TextIO,\n        **kwargs: Any,\n    ) -> None:\n        writer = csv.writer(outfile)\n        writer.writerow(\n            [\n                \"allocator\",\n                \"num_allocations\",\n                \"size\",\n                \"tid\",\n                \"thread_name\",\n                \"stack_trace\",\n            ]\n        )\n        for record in self.allocations:\n            stack_trace = (\n                tuple(record.hybrid_stack_trace())\n                if self.native_traces\n                else record.stack_trace()\n            )\n            writer.writerow(\n                [\n                    AllocatorType(record.allocator).name,\n                    record.n_allocations,\n                    record.size,\n                    record.tid,\n                    format_thread_name(record),\n                    \"|\".join(f\"{func};{mod};{line}\" for func, mod, line in stack_trace),\n                ]\n            )\n"
  },
  {
    "path": "src/memray/reporters/tree.css",
    "content": "Label {\n  padding: 1 3;\n}\n\n#frame-detail-grid Label {\n  color: $text;\n  height: auto;\n  width: 100%;\n  background: $panel-lighten-1;\n}\n\n#frame-detail-grid {\n  grid-size: 1 2;\n  grid-gutter: 1 2;\n  padding: 0 1;\n  border: thick $background 80%;\n  background: $surface;\n}\n\n#detailcol {\n  width: 40%;\n  max-width: 100;\n}\n\nTextArea {\n  scrollbar-size-vertical: 0;\n  border: none;\n  padding: 0;\n}\n"
  },
  {
    "path": "src/memray/reporters/tree.py",
    "content": "import asyncio\nimport functools\nimport linecache\nimport sys\nfrom dataclasses import dataclass\nfrom dataclasses import field\nfrom typing import IO\nfrom typing import Any\nfrom typing import Callable\nfrom typing import Dict\nfrom typing import Iterable\nfrom typing import Iterator\nfrom typing import Optional\nfrom typing import Tuple\n\nfrom rich.style import Style\nfrom rich.text import Text\nfrom textual import binding\nfrom textual import work\nfrom textual.app import App\nfrom textual.app import ComposeResult\nfrom textual.binding import Binding\nfrom textual.color import Color\nfrom textual.color import Gradient\nfrom textual.containers import Grid\nfrom textual.containers import Horizontal\nfrom textual.containers import Vertical\nfrom textual.dom import DOMNode\nfrom textual.reactive import reactive\nfrom textual.screen import Screen\nfrom textual.widget import Widget\nfrom textual.widgets import Footer\nfrom textual.widgets import Label\nfrom textual.widgets import TextArea\nfrom textual.widgets import Tree\nfrom textual.widgets.tree import TreeNode\n\nfrom memray import AllocationRecord\nfrom memray._memray import size_fmt\nfrom memray.reporters._textual_hacks import Bindings\nfrom memray.reporters._textual_hacks import redraw_footer\nfrom memray.reporters._textual_hacks import update_key_description\nfrom memray.reporters.common import format_thread_name\nfrom memray.reporters.frame_tools import is_cpython_internal\nfrom memray.reporters.frame_tools import is_frame_from_import_system\nfrom memray.reporters.frame_tools import is_frame_interesting\nfrom memray.reporters.tui import _filename_to_module_name\n\nMAX_STACKS = int(sys.getrecursionlimit() // 2.5)\n\nStackElement = Tuple[str, str, int]\n\nROOT_NODE = (\"<ROOT>\", \"\", 0)\n\n\n@dataclass\nclass Frame:\n    \"\"\"A frame in the tree\"\"\"\n\n    location: Optional[StackElement]\n    value: int\n    children: Dict[StackElement, \"Frame\"] = field(default_factory=dict)\n    n_allocations: int = 0\n    thread_id: str = \"\"\n    interesting: bool = True\n    import_system: bool = False\n\n\n@dataclass\nclass ElidedLocations:\n    \"\"\"Information about allocations locations below the configured threshold.\"\"\"\n\n    cutoff: int = 0\n    n_locations: int = 0\n    n_allocations: int = 0\n    n_bytes: int = 0\n\n\nclass FrameDetailScreen(Widget):\n    \"\"\"A screen that displays information about a frame\"\"\"\n\n    frame = reactive(Frame(location=ROOT_NODE, value=0))\n\n    def __init__(\n        self, *args: Any, elided_locations: ElidedLocations, **kwargs: Any\n    ) -> None:\n        super().__init__(*args, **kwargs)\n        self.__elided_locations = elided_locations\n        self.__is_mounted = False\n\n    def on_mount(self) -> None:\n        self.__is_mounted = True\n\n    @work(exclusive=True)\n    async def update_text_area(self) -> None:\n        await asyncio.sleep(0.1)\n\n        if not self.__is_mounted or self.frame is None:\n            return\n\n        text = self.query_one(\"#textarea\", TextArea)\n\n        if self.frame.location is None or self.frame.location == ROOT_NODE:\n            text.clear()\n            return\n\n        _, file, line = self.frame.location\n        delta = text.size.height // 2\n        lines = linecache.getlines(file)[max(line - delta, 0) : line + delta]\n\n        text.text = \"\\n\".join(tuple(line.rstrip() for line in lines))\n        text.select_line(line - 1 if delta >= line else delta - 1)\n        text.show_line_numbers = False\n\n    def _get_content_by_label_id(self) -> Dict[str, str]:\n        common = {\n            \"allocs\": f\"\\N{floppy disk} Allocations: {self.frame.n_allocations}\",\n            \"size\": f\"\\N{package} Size: {size_fmt(self.frame.value)}\",\n        }\n\n        if self.frame.location is None:\n            cutoff = self.__elided_locations.cutoff\n            return {\n                **common,\n                \"function\": \"\",\n                \"location\": (\n                    f\"Only the top {cutoff} allocation locations are shown in the tree.\"\n                    \" Allocation locations which individually contributed too little\"\n                    \" to meet the threshold are summarized here.\\n\\n\"\n                    \"You can adjust this threshold to include more allocation locations\"\n                    \" by rerunning this reporter with a larger --biggest-allocs value.\"\n                ),\n                \"thread\": \"\",\n            }\n\n        function, file, lineno = self.frame.location\n        if self.frame.location is ROOT_NODE:\n            return {\n                **common,\n                \"function\": \"\",\n                \"location\": \"\",\n                \"thread\": \"\",\n            }\n        return {\n            **common,\n            \"function\": f\"\\N{compass} Function: {function}\",\n            \"location\": (\n                \"\\N{compass} Location: \"\n                + (\n                    f\"{_filename_to_module_name(file)}:{lineno}\"\n                    if lineno != 0\n                    else file\n                )\n            ),\n            \"thread\": f\"\\N{spool of thread} Thread: {self.frame.thread_id}\",\n        }\n\n    def watch_frame(self) -> None:\n        if not self.__is_mounted or self.frame is None:\n            return\n\n        self.update_text_area()\n\n        content_by_label_id = self._get_content_by_label_id()\n        for label_id, content in content_by_label_id.items():\n            label = self.query_one(f\"#{label_id}\", Label)\n            label.update(content)\n            label.set_class(not content, \"hidden\")\n            label.styles.display = \"block\" if content else \"none\"\n\n    def compose(self) -> ComposeResult:\n        if self.frame is None:\n            return\n\n        delta = 3\n\n        if self.frame.location is None or self.frame.location == ROOT_NODE:\n            lines = []\n            selected_line = 0\n        else:\n            _, file, line = self.frame.location\n            lines = linecache.getlines(file)[max(line - delta, 0) : line + delta]\n            selected_line = line - 1 if delta >= line else delta - 1\n\n        text = TextArea(\n            \"\\n\".join(lines), language=\"python\", theme=\"dracula\", id=\"textarea\"\n        )\n        text.select_line(selected_line)\n        text.show_line_numbers = False\n        text.can_focus = False\n        text.cursor_blink = False\n        text.soft_wrap = False\n\n        labels: list[Label] = []\n        content_by_label_id = self._get_content_by_label_id()\n        for label_id in (\"function\", \"location\", \"allocs\", \"size\", \"thread\"):\n            content = content_by_label_id[label_id]\n            label = Label(content, id=label_id)\n            label.styles.display = \"block\" if content else \"none\"\n            labels.append(label)\n\n        node_metadata = Vertical(*labels)\n        yield Grid(\n            text,\n            node_metadata,\n            id=\"frame-detail-grid\",\n        )\n\n\nclass FrameTree(Tree[Frame]):\n    def on_tree_node_selected(self, node: Tree.NodeSelected[Frame]) -> None:\n        if node.node.data is not None:\n            self.app.screen.query_one(FrameDetailScreen).frame = node.node.data\n\n    def on_tree_node_highlighted(self, node: Tree.NodeHighlighted[Frame]) -> None:\n        if node.node.data is not None:\n            self.app.screen.query_one(FrameDetailScreen).frame = node.node.data\n\n\ndef node_is_interesting(node: Frame) -> bool:\n    return node.interesting\n\n\ndef node_is_not_import_system(node: Frame) -> bool:\n    return not node.import_system\n\n\nclass TreeScreen(Screen[None]):\n    BINDINGS = [\n        Binding(\"ctrl+z\", \"app.suspend_process\"),\n        Binding(key=\"q\", action=\"app.quit\", description=\"Quit the app\"),\n        Binding(\n            key=\"i\", action=\"toggle_import_system\", description=\"Hide import system\"\n        ),\n        Binding(\n            key=\"u\", action=\"toggle_uninteresting\", description=\"Hide uninteresting\"\n        ),\n        Binding(\n            key=\"e\", action=\"expand_linear_group\", description=\"Expand linear group\"\n        ),\n    ]\n\n    CSS_PATH = \"tree.css\"\n\n    def __init__(\n        self,\n        data: Frame,\n        elided_locations: ElidedLocations,\n    ):\n        super().__init__()\n        self.data = data\n        self.elided_locations = elided_locations\n        self.import_system_filter: Optional[Callable[[Frame], bool]] = None\n        self.uninteresting_filter: Optional[\n            Callable[[Frame], bool]\n        ] = node_is_interesting\n\n    def expand_first_child(self, node: TreeNode[Frame]) -> None:\n        while node.children:\n            node = node.children[0]\n            node.toggle()\n\n    def compose(self) -> ComposeResult:\n        tree = FrameTree(self.frame_text(self.data, allow_expand=True), self.data)\n        self.repopulate_tree(tree)\n        yield Horizontal(\n            Vertical(tree),\n            Vertical(\n                FrameDetailScreen(elided_locations=self.elided_locations),\n                id=\"detailcol\",\n            ),\n        )\n        yield Footer()\n\n    def repopulate_tree(self, tree: FrameTree) -> None:\n        tree.clear()\n        self.add_children(tree.root, self.data.children.values())\n        self.add_elided_locations_node(tree.root)\n        tree.root.expand()\n        # From Textual 0.73 on, Tree.select_node toggles the node's expanded\n        # state. The new Tree.move_cursor method selects without expanding.\n        getattr(tree, \"move_cursor\", tree.select_node)(tree.root)\n        self.expand_first_child(tree.root)\n\n    def action_expand_linear_group(self) -> None:\n        tree = self.query_one(FrameTree)\n        current_node = tree.cursor_node\n        while current_node:\n            current_node.toggle()\n            if len(current_node.children) != 1:\n                break\n            current_node = current_node.children[0]\n\n    def frame_text(self, node: Frame, *, allow_expand: bool) -> Text:\n        if node.value == 0:\n            return Text(\"<No allocations>\")\n\n        value = node.value\n        root_data = self.data\n        size_str = f\"{size_fmt(value)} ({100 * value / root_data.value:.2f} %)\"\n        size_color = _info_color(node, root_data)\n\n        ret = Text.from_markup(\n            \":open_file_folder:\" if allow_expand else \":page_facing_up:\"\n        )\n        ret.append_text(Text(f\" {size_str} \", style=Style(color=size_color.rich_color)))\n\n        if node.location is not None:\n            function, file, lineno = node.location\n            code_position = (\n                f\"{_filename_to_module_name(file)}:{lineno}\" if lineno != 0 else file\n            )\n            ret.append_text(Text.from_markup(f\"[bold]{function}[/]\"))\n            if code_position:\n                ret.append_text(Text.from_markup(f\"  [dim cyan]{code_position}[/]\"))\n        else:\n            ret.append_text(Text(\"hidden\"))\n        return ret\n\n    def add_children(self, tree: TreeNode[Frame], children: Iterable[Frame]) -> None:\n        # Add children to the tree from largest to smallest\n        children = sorted(children, key=lambda child: child.value, reverse=True)\n\n        if self.import_system_filter is not None:\n            children = tuple(filter(self.import_system_filter, children))\n\n        for child in children:\n            if self.uninteresting_filter is None or self.uninteresting_filter(child):\n                if not tree.allow_expand:\n                    assert tree.data is not None\n                    tree.label = self.frame_text(tree.data, allow_expand=True)\n                    tree.allow_expand = True\n                new_tree = tree.add(\n                    self.frame_text(child, allow_expand=False),\n                    data=child,\n                    allow_expand=False,\n                )\n            else:\n                new_tree = tree\n\n            self.add_children(new_tree, child.children.values())\n\n    def add_elided_locations_node(self, tree: TreeNode[Frame]) -> None:\n        if not self.elided_locations.n_locations:\n            return\n\n        count = self.elided_locations.n_locations\n        value = self.elided_locations.n_bytes\n        number = self.elided_locations.n_allocations\n\n        root_data = self.data\n        percentage = 100 * value / root_data.value\n        size_str = f\"{size_fmt(value)} ({percentage:.2f} %)\"\n        size_color = _percentage_to_color(int(percentage))\n        ret = Text.from_markup(\"\\N{black question mark ornament}\")\n        ret.append_text(Text(f\" {size_str} \", style=Style(color=size_color.rich_color)))\n        ret.append_text(\n            Text.from_markup(\n                f\"{number} allocations from {count} locations\"\n                f\" below the configured threshold\"\n            )\n        )\n\n        tree.add_leaf(ret, data=Frame(location=None, value=value, n_allocations=number))\n\n    def action_toggle_import_system(self) -> None:\n        if self.import_system_filter is None:\n            self.import_system_filter = node_is_not_import_system\n        else:\n            self.import_system_filter = None\n\n        redraw_footer(self.app)\n        self.repopulate_tree(self.query_one(FrameTree))\n\n    def action_toggle_uninteresting(self) -> None:\n        if self.uninteresting_filter is None:\n            self.uninteresting_filter = node_is_interesting\n        else:\n            self.uninteresting_filter = None\n\n        redraw_footer(self.app)\n        self.repopulate_tree(self.query_one(FrameTree))\n\n    def rewrite_bindings(self, bindings: Bindings) -> None:\n        if self.import_system_filter is not None:\n            update_key_description(bindings, \"i\", \"Show import system\")\n        if self.uninteresting_filter is not None:\n            update_key_description(bindings, \"u\", \"Show uninteresting\")\n\n    @property\n    def active_bindings(self) -> Dict[str, \"binding.ActiveBinding\"]:\n        bindings = super().active_bindings.copy()\n        self.rewrite_bindings(bindings)\n        return bindings\n\n\nclass TreeApp(App[None]):\n    def __init__(\n        self,\n        data: Frame,\n        elided_locations: ElidedLocations,\n    ):\n        super().__init__()\n        self.tree_screen = TreeScreen(data, elided_locations)\n\n    def on_mount(self) -> None:\n        self.push_screen(self.tree_screen)\n\n    if hasattr(App, \"namespace_bindings\"):\n        # Removed in Textual 0.61\n        @property\n        def namespace_bindings(self) -> Dict[str, Tuple[DOMNode, Binding]]:\n            bindings = super().namespace_bindings.copy()  # type: ignore[misc]\n            self.tree_screen.rewrite_bindings(bindings)\n            return bindings  # type: ignore[no-any-return]\n\n\n@functools.lru_cache(maxsize=None)\ndef _percentage_to_color(percentage: int) -> Color:\n    gradient = Gradient(\n        (0, Color(97, 193, 44)),\n        (0.4, Color(236, 152, 16)),\n        (0.6, Color.parse(\"darkorange\")),\n        (1, Color.parse(\"indianred\")),\n    )\n    return gradient.get_color(percentage / 100)\n\n\ndef _info_color(node: Frame, root_node: Frame) -> Color:\n    proportion_of_total = node.value / root_node.value\n    return _percentage_to_color(int(proportion_of_total * 100))\n\n\nclass TreeReporter:\n    def __init__(self, data: Frame, elided_locations: ElidedLocations) -> None:\n        super().__init__()\n        self.data = data\n        self.elided_locations = elided_locations\n\n    @classmethod\n    def from_snapshot(\n        cls,\n        allocations: Iterator[AllocationRecord],\n        *,\n        biggest_allocs: int = 200,\n        native_traces: bool,\n    ) -> \"TreeReporter\":\n        data = Frame(location=ROOT_NODE, value=0, import_system=False, interesting=True)\n        sorted_records = sorted(allocations, key=lambda alloc: alloc.size, reverse=True)\n        for record in sorted_records[:biggest_allocs]:\n            size = record.size\n            data.value += size\n            data.n_allocations += record.n_allocations\n\n            current_frame = data\n            stack = (\n                tuple(record.hybrid_stack_trace())\n                if native_traces\n                else record.stack_trace()\n            )\n            for index, stack_frame in enumerate(reversed(stack)):\n                if is_cpython_internal(stack_frame):\n                    continue\n                is_import_system = is_frame_from_import_system(stack_frame)\n                is_interesting = not is_import_system and is_frame_interesting(\n                    stack_frame\n                )\n                if stack_frame not in current_frame.children:\n                    node = Frame(\n                        value=0,\n                        location=stack_frame,\n                        import_system=is_import_system,\n                        interesting=is_interesting,\n                    )\n                    current_frame.children[stack_frame] = node\n\n                current_frame = current_frame.children[stack_frame]\n                current_frame.value += size\n                current_frame.n_allocations += record.n_allocations\n                current_frame.thread_id = format_thread_name(record)\n\n                if index > MAX_STACKS:\n                    break\n\n        elided_locations = ElidedLocations()\n        elided_locations.cutoff = biggest_allocs\n\n        for record in sorted_records[biggest_allocs:]:\n            data.value += record.size\n            data.n_allocations += record.n_allocations\n            elided_locations.n_locations += 1\n            elided_locations.n_bytes += record.size\n            elided_locations.n_allocations += record.n_allocations\n\n        return cls(data, elided_locations)\n\n    def get_app(self) -> TreeApp:\n        return TreeApp(self.data, self.elided_locations)\n\n    def render(\n        self,\n        *,\n        file: Optional[IO[str]] = None,\n    ) -> None:\n        self.get_app().run()\n"
  },
  {
    "path": "src/memray/reporters/tui.css",
    "content": "TUI {\n  layout: vertical;\n}\n\n#head {\n  layout: horizontal;\n  height: 1;\n}\n\n#head_time_display {\n  width: 30;\n  text-align: right;\n  dock: right;\n}\n\nHeader {\n  height: 7;\n}\n\n.narrow Header {\n  height: 11;\n}\n\n#header_container {\n  layout: horizontal;\n}\n\n.narrow #header_container {\n  layout: vertical;\n}\n\n#header_metadata {\n  layout: vertical;\n  width: 100%;\n  height: 7;\n  border: blank;\n  border-title-align: right;\n  border-title-color: $success-lighten-1;\n  overflow: auto auto;\n}\n\n.narrow #header_metadata {\n  border: none;\n  height: 5;\n}\n\n#header_metadata_grid {\n  layout: grid;\n  height: 3;\n  width: auto;\n  grid-size: 2;\n  grid-columns: auto auto;\n  grid-gutter: 0 3;\n  overflow: hidden hidden;\n}\n\n#header_metadata > #status_message {\n  column-span: 2;\n  width: auto;\n  height: 1;\n}\n\nMemoryGraph {\n  dock: right;\n  border: round $success-lighten-1;\n  box-sizing: content-box;\n  height: 4;\n  max-width: 50;\n}\n\n#memory_graph_container {\n  dock: right;\n  box-sizing: content-box;\n  width: 30%;\n  max-width: 52;\n}\n\n.narrow #memory_graph_container {\n  dock: bottom;\n  box-sizing: border-box;\n  width: 100%;\n  max-width: 100%;\n  height: 6;\n}\n\nFooter {\n  background: transparent;\n}\n\nFooter > .footer--key {\n  background: rgb(30, 144, 255);\n}\n\nAllocationTable {\n  height: 1fr;\n}\n\n.narrow AllocationTable {\n  height: 100%;\n}\n\nAllocationTable > ScrollView {\n  height: 100%;\n}\n"
  },
  {
    "path": "src/memray/reporters/tui.py",
    "content": "import contextlib\nimport os\nimport pathlib\nimport sys\nimport threading\nfrom collections import defaultdict\nfrom collections import deque\nfrom dataclasses import dataclass\nfrom datetime import datetime\nfrom functools import total_ordering\nfrom math import ceil\nfrom typing import Any\nfrom typing import DefaultDict\nfrom typing import Dict\nfrom typing import Iterable\nfrom typing import List\nfrom typing import Optional\nfrom typing import Set\nfrom typing import Tuple\nfrom typing import cast\n\nfrom rich.markup import escape\nfrom rich.segment import Segment\nfrom rich.style import Style\nfrom rich.text import Text\nfrom textual import events\nfrom textual import log\nfrom textual.app import App\nfrom textual.app import ComposeResult\nfrom textual.binding import Binding\nfrom textual.color import Color\nfrom textual.color import Gradient\nfrom textual.containers import Container\nfrom textual.containers import HorizontalScroll\nfrom textual.dom import DOMNode\nfrom textual.message import Message\nfrom textual.reactive import reactive\nfrom textual.screen import Screen\nfrom textual.strip import Strip\nfrom textual.widget import Widget\nfrom textual.widgets import DataTable\nfrom textual.widgets import Footer\nfrom textual.widgets import Label\nfrom textual.widgets import Static\nfrom textual.widgets.data_table import RowKey\n\nfrom memray import AllocationRecord\nfrom memray import SocketReader\nfrom memray._memray import size_fmt\nfrom memray.reporters._textual_hacks import Bindings\nfrom memray.reporters._textual_hacks import redraw_footer\nfrom memray.reporters._textual_hacks import update_key_description\n\nMAX_MEMORY_RATIO = 0.95\n\n\n@dataclass(frozen=True)\nclass Location:\n    function: str\n    file: str\n\n\n@dataclass\nclass AllocationEntry:\n    own_memory: int\n    total_memory: int\n    n_allocations: int\n    thread_ids: Set[int]\n\n\n@dataclass(frozen=True, eq=False)\nclass Snapshot:\n    heap_size: int\n    records: List[AllocationRecord]\n    records_by_location: Dict[Location, AllocationEntry]\n\n\n_EMPTY_SNAPSHOT = Snapshot(heap_size=0, records=[], records_by_location={})\n\n\nclass SnapshotFetched(Message):\n    def __init__(self, snapshot: Snapshot, disconnected: bool) -> None:\n        self.snapshot = snapshot\n        self.disconnected = disconnected\n        super().__init__()\n\n\nclass MemoryGraph(Widget):\n    def __init__(\n        self,\n        *args: Any,\n        max_data_points: int,\n        height: int = 4,\n        **kwargs: Any,\n    ) -> None:\n        super().__init__(*args, **kwargs)\n        maxval: float = 1.0\n        minval: float = 0.0\n        self._width = max_data_points\n        self._height = height\n        self._minval = minval\n        self._maxval = maxval\n        values = [minval] * (2 * self._width + 1)\n        self._values = deque(values, maxlen=2 * self._width)\n\n        self._lookup = [\n            [\" \", \"▗\", \"▐\"],\n            [\"▖\", \"▄\", \"▟\"],\n            [\"▌\", \"▙\", \"█\"],\n        ]\n\n        self.border_title = \"Heap Usage\"\n\n    def _value_to_blocks(self, value: float) -> List[int]:\n        dots_per_block = 2\n        if value < self._minval:\n            n_dots = 0\n        elif value > self._maxval:\n            n_dots = dots_per_block * self._height\n        else:\n            n_dots = ceil(\n                (value - self._minval)\n                / (self._maxval - self._minval)\n                * dots_per_block\n                * self._height\n            )\n        blocks = [dots_per_block] * (n_dots // dots_per_block)\n        if n_dots % dots_per_block > 0:\n            blocks += [n_dots % dots_per_block]\n        blocks += [0] * (self._height - len(blocks))\n        return blocks\n\n    def add_value(self, value: float) -> None:\n        if value > self._maxval:\n            self._maxval = value\n        self._values.append(value)\n        if self._maxval > 1:\n            self.border_subtitle = (\n                f\"{size_fmt(int(value))}\"\n                f\" ({int(round(value * 100/self._maxval, 0))}%\"\n                f\" of {size_fmt(int(self._maxval))} max)\"\n            )\n        self.refresh()\n\n    def render_line(self, y: int) -> Strip:\n        graph: list[list[str]] = [[] for _ in range(self._height)]\n        blocks_by_index = [self._value_to_blocks(value) for value in self._values]\n\n        for left, right in zip(blocks_by_index[::2], blocks_by_index[1::2]):\n            for row, char in enumerate(\n                reversed(tuple(self._lookup[li][ri] for li, ri in zip(left, right)))\n            ):\n                graph[row].append(char)\n\n        if y > len(graph):\n            return Strip.blank(self.size.width)\n        data = \" \" * self.size.width\n        data += \"\".join(graph[y])\n        data = data[-self.size.width :]\n        return Strip([Segment(data, self.rich_style)])\n\n\n@total_ordering\nclass SortableText(Text):\n    __slots__ = (\"value\",)\n\n    def __init__(\n        self,\n        value: Any,\n        text: str,\n        color: Color,\n        justify: Any = \"right\",  # \"Any\" is a hack: justify should be Literal\n    ) -> None:\n        self.value = value\n        super().__init__(\n            str(text),\n            Style(color=color.rich_color),\n            justify=justify,\n        )\n\n    def __lt__(self, other: Any) -> bool:\n        if type(other) != SortableText:\n            return NotImplemented\n        return cast(bool, self.value < other.value)\n\n    def __gt__(self, other: Any) -> bool:\n        if type(other) != SortableText:\n            return NotImplemented\n        return cast(bool, self.value > other.value)\n\n    def __eq__(self, other: Any) -> bool:\n        if type(other) != SortableText:\n            return NotImplemented\n        return cast(bool, self.value == other.value)\n\n\ndef aggregate_allocations(\n    allocations: Iterable[AllocationRecord],\n    memory_threshold: float = float(\"inf\"),\n    native_traces: Optional[bool] = False,\n) -> Dict[Location, AllocationEntry]:\n    \"\"\"Take allocation records and for each frame contained, record \"own\"\n    allocations which happened on the frame, and sum up allocations on\n    all of the child frames to calculate \"total\" allocations.\"\"\"\n\n    processed_allocations: DefaultDict[Location, AllocationEntry] = defaultdict(\n        lambda: AllocationEntry(\n            own_memory=0, total_memory=0, n_allocations=0, thread_ids=set()\n        )\n    )\n\n    current_total = 0\n    for allocation in allocations:\n        if current_total >= memory_threshold:\n            break\n        current_total += allocation.size\n\n        stack_trace = list(\n            allocation.hybrid_stack_trace()\n            if native_traces\n            else allocation.stack_trace()\n        )\n        if not stack_trace:\n            frame = processed_allocations[Location(function=\"???\", file=\"???\")]\n            frame.total_memory += allocation.size\n            frame.own_memory += allocation.size\n            frame.n_allocations += allocation.n_allocations\n            frame.thread_ids.add(allocation.tid)\n            continue\n\n        # Walk upwards and sum totals\n        visited = set()\n        for i, (function, file_name, _) in enumerate(stack_trace):\n            location = Location(function=function, file=file_name)\n            frame = processed_allocations[location]\n            if location in visited:\n                continue\n            visited.add(location)\n            if i == 0:\n                frame.own_memory += allocation.size\n            frame.total_memory += allocation.size\n            frame.n_allocations += allocation.n_allocations\n            frame.thread_ids.add(allocation.tid)\n    return processed_allocations\n\n\nclass TimeDisplay(Static):\n    \"\"\"TUI widget to display the current time.\"\"\"\n\n    def on_mount(self) -> None:\n        \"\"\"Event handler called when the widget is added to the app.\"\"\"\n        self.set_interval(0.1, lambda: self.update(datetime.now().ctime()))\n\n\ndef _filename_to_module_name(file: str) -> str:\n    if file.endswith(\".py\"):\n        for path in sys.path:\n            if not os.path.isdir(path):\n                continue\n            with contextlib.suppress(ValueError):\n                relative_path = pathlib.Path(file).relative_to(path)\n                ret = str(relative_path.with_suffix(\"\"))\n                ret = ret.replace(os.sep, \".\").replace(\".__init__\", \"\")\n                return ret\n    return file\n\n\nclass AllocationTable(Widget):\n    \"\"\"Widget to display the TUI table.\"\"\"\n\n    COMPONENT_CLASSES = {\n        \"allocationtable--sorted-column-heading\",\n        \"allocationtable--function-name\",\n    }\n\n    DEFAULT_CSS = \"\"\"\n    AllocationTable .allocationtable--sorted-column-heading {\n        text-style: bold underline;\n    }\n\n    AllocationTable .allocationtable--function-name {\n    }\n    \"\"\"\n\n    default_sort_column_id = 1\n    sort_column_id = reactive(default_sort_column_id)\n    snapshot = reactive(_EMPTY_SNAPSHOT)\n    current_thread = reactive(0)\n    merge_threads = reactive(False, init=False)\n\n    columns = [\n        \"Location\",\n        \"Total Bytes\",\n        \"% Total\",\n        \"Own Bytes\",\n        \"% Own\",\n        \"Allocations\",\n        \"File/Module\",\n    ]\n\n    KEY_TO_COLUMN_NAME = {\n        1: \"total_memory\",\n        3: \"own_memory\",\n        5: \"n_allocations\",\n    }\n\n    HIGHLIGHTED_COLUMNS_BY_SORT_COLUMN = {\n        1: (1, 2),\n        3: (3, 4),\n        5: (5,),\n    }\n\n    SORT_COLUMN_BY_CLICKED_COLUMN = {\n        clicked_col: sort_col\n        for sort_col, clicked_cols in HIGHLIGHTED_COLUMNS_BY_SORT_COLUMN.items()\n        for clicked_col in clicked_cols\n    }\n\n    def __init__(self) -> None:\n        super().__init__()\n        self._composed = False\n\n        gradient = Gradient(\n            (0, Color(97, 193, 44)),\n            (0.4, Color(236, 152, 16)),\n            (0.6, Color.parse(\"darkorange\")),\n            (1, Color.parse(\"indianred\")),\n        )\n        self._color_by_percentage = {i: gradient.get_color(i / 100) for i in range(101)}\n\n    def _get_color(self, value: float, max: float) -> Color:\n        return self._color_by_percentage[int(value * 100 / max)]\n\n    def get_heading(self, column_idx: int) -> Text:\n        sort_column = (\n            self.sort_column_id if self._composed else self.default_sort_column_id\n        )\n        sort_column_style = self.get_component_rich_style(\n            \"allocationtable--sorted-column-heading\",\n            partial=True,\n        )\n        log(\n            f\"self._composed={self._composed} sort_column={sort_column}\"\n            f\" highlighted_cols={self.HIGHLIGHTED_COLUMNS_BY_SORT_COLUMN[sort_column]}\"\n        )\n        if column_idx in (0, len(self.columns) - 1):\n            return Text(self.columns[column_idx], justify=\"center\")\n        elif column_idx in self.HIGHLIGHTED_COLUMNS_BY_SORT_COLUMN[sort_column]:\n            return Text(\n                self.columns[column_idx], justify=\"right\", style=sort_column_style\n            )\n        else:\n            return Text(self.columns[column_idx], justify=\"right\").on(\n                click=f\"screen.sort({self.SORT_COLUMN_BY_CLICKED_COLUMN[column_idx]})\"\n            )\n\n    def compose(self) -> ComposeResult:\n        table: DataTable[Text] = DataTable(\n            id=\"body_table\", header_height=1, show_cursor=False, zebra_stripes=True\n        )\n        table.focus()\n        for column_idx in range(len(self.columns)):\n            table.add_column(self.get_heading(column_idx), key=str(column_idx))\n\n        # Set an initial size for the Location column to avoid too many resizes\n        table.ordered_columns[0].content_width = 50\n\n        self._composed = True\n        yield table\n\n    def watch_current_thread(self) -> None:\n        \"\"\"Called when the current_thread attribute changes.\"\"\"\n        self.populate_table()\n\n    def watch_merge_threads(self) -> None:\n        \"\"\"Called when the merge_threads attribute changes.\"\"\"\n        self.populate_table()\n\n    def watch_snapshot(self) -> None:\n        \"\"\"Called when the snapshot attribute changes.\"\"\"\n        self.populate_table()\n\n    def watch_sort_column_id(self, sort_column_id: int) -> None:\n        \"\"\"Called when the sort_column_id attribute changes.\"\"\"\n        table = self.query_one(\"#body_table\", DataTable)\n\n        for i in range(1, len(self.columns)):\n            table.ordered_columns[i].label = self.get_heading(i)\n\n        table.sort(table.ordered_columns[sort_column_id].key, reverse=True)\n\n    def populate_table(self) -> None:\n        \"\"\"Method to render the TUI table.\"\"\"\n        table = self.query_one(\"#body_table\", DataTable)\n\n        if not table.columns:\n            return\n\n        allocation_entries = self.snapshot.records_by_location\n        total_allocations = self.snapshot.heap_size\n        num_allocations = sum(\n            entry.n_allocations for entry in allocation_entries.values()\n        )\n        sorted_allocations = sorted(\n            allocation_entries.items(),\n            key=lambda item: getattr(\n                item[1], self.KEY_TO_COLUMN_NAME[self.sort_column_id]\n            ),\n            reverse=True,\n        )\n\n        function_column_style = self.get_component_rich_style(\n            \"allocationtable--function-name\", partial=True\n        )\n\n        # Clear previous table rows\n        old_locations = set(table.rows)\n        new_locations = set()\n\n        for location, result in sorted_allocations:\n            if not self.merge_threads and (\n                self.current_thread not in result.thread_ids\n            ):\n                continue\n\n            total_color = self._get_color(result.total_memory, total_allocations)\n            own_color = self._get_color(result.own_memory, total_allocations)\n            allocation_color = self._get_color(result.n_allocations, num_allocations)\n\n            percent_total = result.total_memory / total_allocations * 100\n            percent_own = result.own_memory / total_allocations * 100\n\n            cells = [\n                SortableText(\n                    result.total_memory, size_fmt(result.total_memory), total_color\n                ),\n                SortableText(result.total_memory, f\"{percent_total:.2f}%\", total_color),\n                SortableText(result.own_memory, size_fmt(result.own_memory), own_color),\n                SortableText(result.own_memory, f\"{percent_own:.2f}%\", own_color),\n                SortableText(\n                    result.n_allocations, str(result.n_allocations), allocation_color\n                ),\n            ]\n\n            row_key = str((location.function, location.file))\n            new_locations.add(RowKey(row_key))\n\n            if row_key not in table.rows:\n                table.add_row(\n                    Text(location.function, style=function_column_style),\n                    *cells,\n                    Text(_filename_to_module_name(location.file)),\n                    key=row_key,\n                )\n            else:\n                for col_idx, val in enumerate(cells, 1):\n                    col_key = str(col_idx)\n                    table.update_cell(row_key, col_key, val)\n\n        for old_row_key in old_locations - new_locations:\n            table.remove_row(old_row_key)\n\n        table.sort(str(self.sort_column_id), reverse=True)\n\n\nclass Header(Widget):\n    \"\"\"Widget to display TUI header information.\"\"\"\n\n    pid = reactive(\"\")\n    command_line = reactive(\"\")\n    n_samples = reactive(0)\n    start = datetime.now()\n    last_update = reactive(start)\n\n    def __init__(self, pid: Optional[int], cmd_line: Optional[str]):\n        super().__init__()\n        self.pid = str(pid) if pid is not None else \"???\"\n        if not cmd_line:\n            cmd_line = \"???\"\n        self.command_line = escape(cmd_line)\n\n    def compose(self) -> ComposeResult:\n        header_metadata = HorizontalScroll(\n            Container(\n                Label(f\"[b]PID[/]: {self.pid}\", id=\"pid\"),\n                Label(f\"[b]CMD[/]: {self.command_line}\", shrink=False, id=\"cmd\"),\n                Label(id=\"tid\"),\n                Label(id=\"thread\"),\n                Label(id=\"samples\"),\n                Label(id=\"duration\"),\n                id=\"header_metadata_grid\",\n            ),\n            Label(id=\"status_message\"),\n            id=\"header_metadata\",\n        )\n        header_metadata.border_title = \"(∩｀-´)⊃━☆ﾟ.*･｡ﾟ\"\n        yield Container(\n            header_metadata,\n            Container(MemoryGraph(max_data_points=50), id=\"memory_graph_container\"),\n            id=\"header_container\",\n        )\n\n    def watch_n_samples(self, n_samples: int) -> None:\n        \"\"\"Called when the n_samples attribute changes.\"\"\"\n        self.query_one(\"#samples\", Label).update(f\"[b]Samples[/]: {n_samples}\")\n\n    def watch_last_update(self, last_update: datetime) -> None:\n        \"\"\"Called when the last_update attribute changes.\"\"\"\n        self.query_one(\"#duration\", Label).update(\n            f\"[b]Duration[/]: {(last_update - self.start).total_seconds():.1f} seconds\"\n        )\n\n\nclass TUI(Screen[None]):\n    \"\"\"TUI main application class.\"\"\"\n\n    CSS_PATH = \"tui.css\"\n\n    BINDINGS = [\n        Binding(\"ctrl+z\", \"app.suspend_process\"),\n        Binding(\"q,esc\", \"app.quit\", \"Quit\"),\n        Binding(\"m\", \"toggle_merge_threads\", \"Merge Threads\"),\n        Binding(\"<,left\", \"previous_thread\", \"Previous Thread\"),\n        Binding(\">,right\", \"next_thread\", \"Next Thread\"),\n        Binding(\"t\", \"sort(1)\", \"Sort by Total\"),\n        Binding(\"o\", \"sort(3)\", \"Sort by Own\"),\n        Binding(\"a\", \"sort(5)\", \"Sort by Allocations\"),\n        Binding(\"space\", \"toggle_pause\", \"Pause\"),\n        Binding(\"up\", \"scroll_grid('up')\"),\n        Binding(\"down\", \"scroll_grid('down')\"),\n    ]\n\n    # Start with a non-empty list of threads so that we always have something\n    # to display. This avoids \"Thread 1 of 0\" and fixes a DivideByZeroError\n    # when switching threads before the first allocation is seen.\n    _DUMMY_THREAD_LIST = [0]\n\n    thread_idx = reactive(0)\n    threads = reactive(_DUMMY_THREAD_LIST, always_update=True)\n    snapshot = reactive(_EMPTY_SNAPSHOT)\n    paused = reactive(False, init=False)\n    disconnected = reactive(False, init=False)\n\n    def __init__(self, pid: Optional[int], cmd_line: Optional[str], native: bool):\n        self.pid = pid\n        self.cmd_line = cmd_line\n        self.native = native\n        self._name_by_tid: Dict[int, str] = {}\n        self._max_memory_seen = 0\n        self._merge_threads = True\n        super().__init__()\n\n    @property\n    def current_thread(self) -> int:\n        return self.threads[self.thread_idx]\n\n    def action_previous_thread(self) -> None:\n        \"\"\"An action to switch to previous thread.\"\"\"\n        if not self._merge_threads:\n            self.thread_idx = (self.thread_idx - 1) % len(self.threads)\n\n    def action_next_thread(self) -> None:\n        \"\"\"An action to switch to next thread.\"\"\"\n        if not self._merge_threads:\n            self.thread_idx = (self.thread_idx + 1) % len(self.threads)\n\n    def action_sort(self, col_number: int) -> None:\n        \"\"\"An action to sort the table rows based on a given column attribute.\"\"\"\n        self.update_sort_key(col_number)\n\n    def _populate_header_thread_labels(self, thread_idx: int) -> None:\n        if self._merge_threads:\n            tid_label = \"[b]TID[/]: *\"\n            thread_label = \"[b]All threads[/]\"\n        else:\n            tid_label = f\"[b]TID[/]: {hex(self.current_thread)}\"\n            thread_label = f\"[b]Thread[/] {thread_idx + 1} of {len(self.threads)}\"\n            thread_name = self._name_by_tid.get(self.current_thread)\n            if thread_name:\n                thread_label += f\" ({thread_name})\"\n\n        self.query_one(\"#tid\", Label).update(tid_label)\n        self.query_one(\"#thread\", Label).update(thread_label)\n\n    def action_toggle_merge_threads(self) -> None:\n        \"\"\"An action to toggle showing allocations from all threads together.\"\"\"\n        self._merge_threads = not self._merge_threads\n        redraw_footer(self.app)\n        self.app.screen.query_one(AllocationTable).merge_threads = self._merge_threads\n        self._populate_header_thread_labels(self.thread_idx)\n\n    def action_toggle_pause(self) -> None:\n        \"\"\"Toggle pause on keypress\"\"\"\n        if self.paused or not self.disconnected:\n            self.paused = not self.paused\n            redraw_footer(self.app)\n            if not self.paused:\n                self.display_snapshot()\n\n    def action_scroll_grid(self, direction: str) -> None:\n        \"\"\"Toggle pause on keypress\"\"\"\n        grid = self.query_one(DataTable)\n        getattr(grid, f\"action_scroll_{direction}\")()\n\n    def watch_thread_idx(self, thread_idx: int) -> None:\n        \"\"\"Called when the thread_idx attribute changes.\"\"\"\n        self._populate_header_thread_labels(thread_idx)\n        self.query_one(AllocationTable).current_thread = self.current_thread\n\n    def watch_threads(self) -> None:\n        \"\"\"Called when the threads attribute changes.\"\"\"\n        self._populate_header_thread_labels(self.thread_idx)\n\n    def watch_disconnected(self) -> None:\n        self.update_label()\n        redraw_footer(self.app)\n\n    def watch_paused(self) -> None:\n        self.update_label()\n\n    def watch_snapshot(self, snapshot: Snapshot) -> None:\n        \"\"\"Called automatically when the snapshot attribute is updated\"\"\"\n        self._latest_snapshot = snapshot\n        self.display_snapshot()\n\n    def update_label(self) -> None:\n        status_message = []\n        if self.paused:\n            status_message.append(\"[yellow]Table updates paused[/]\")\n        if self.disconnected:\n            status_message.append(\"[red]Remote has disconnected[/]\")\n        if status_message:\n            status_message.insert(0, \"[b]Status[/]:\")\n\n        log(f\"updating status message to {' '.join(status_message)}\")\n        self.query_one(\"#status_message\", Label).update(\" \".join(status_message))\n\n    def compose(self) -> ComposeResult:\n        yield Container(\n            Label(\"[b]Memray[/b] live tracking\", id=\"head_title\"),\n            TimeDisplay(id=\"head_time_display\"),\n            id=\"head\",\n        )\n        yield Header(pid=self.pid, cmd_line=escape(self.cmd_line or \"\"))\n        yield AllocationTable()\n        yield Footer()\n\n    def display_snapshot(self) -> None:\n        snapshot = self._latest_snapshot\n\n        if snapshot is _EMPTY_SNAPSHOT:\n            return\n\n        header = self.query_one(Header)\n        body = self.query_one(AllocationTable)\n        graph = self.query_one(MemoryGraph)\n\n        # We want to update many header fields even when paused\n        header.n_samples += 1\n        header.last_update = datetime.now()\n\n        graph.add_value(snapshot.heap_size)\n\n        # Other fields should only be updated when not paused.\n        if self.paused:\n            return\n\n        name_by_tid = {record.tid: record.thread_name for record in snapshot.records}\n        new_tids = name_by_tid.keys() - self._name_by_tid.keys()\n        self._name_by_tid.update(name_by_tid)\n\n        if new_tids:\n            threads = self.threads\n            if threads is self._DUMMY_THREAD_LIST:\n                threads = []\n            for tid in sorted(new_tids):\n                threads.append(tid)\n            self.threads = threads\n\n        body.current_thread = self.current_thread\n        if not self.paused:\n            body.snapshot = snapshot\n\n    def update_sort_key(self, col_number: int) -> None:\n        \"\"\"Method called to update the table sort key attribute.\"\"\"\n        body = self.query_one(AllocationTable)\n        body.sort_column_id = col_number\n\n    def rewrite_bindings(self, bindings: Bindings) -> None:\n        if \"space\" in bindings and bindings[\"space\"][1].description == \"Pause\":\n            if self.paused:\n                update_key_description(bindings, \"space\", \"Unpause\")\n            elif self.disconnected:\n                del bindings[\"space\"]\n\n        if self._merge_threads:\n            bindings.pop(\"less_than_sign\")\n            bindings.pop(\"greater_than_sign\")\n            update_key_description(bindings, \"m\", \"Unmerge Threads\")\n\n    @property\n    def active_bindings(self) -> Dict[str, Any]:\n        bindings = super().active_bindings.copy()\n        self.rewrite_bindings(bindings)\n        return bindings\n\n\nclass UpdateThread(threading.Thread):\n    def __init__(self, app: \"TUIApp\", reader: SocketReader) -> None:\n        self._app = app\n        self._reader = reader\n        self._update_requested = threading.Event()\n        self._update_requested.set()\n        self._canceled = threading.Event()\n        super().__init__()\n\n    def run(self) -> None:\n        while self._update_requested.wait():\n            if self._canceled.is_set():\n                return\n            self._update_requested.clear()\n\n            records = list(self._reader.get_current_snapshot(merge_threads=False))\n            heap_size = sum(record.size for record in records)\n            records_by_location = aggregate_allocations(\n                records, MAX_MEMORY_RATIO * heap_size, self._reader.has_native_traces\n            )\n            snapshot = Snapshot(\n                heap_size=heap_size,\n                records=records,\n                records_by_location=records_by_location,\n            )\n\n            self._app.post_message(\n                SnapshotFetched(\n                    snapshot,\n                    not self._reader.is_active,\n                )\n            )\n\n            if not self._reader.is_active:\n                return\n\n    def cancel(self) -> None:\n        self._canceled.set()\n        self._update_requested.set()\n\n    def schedule_update(self) -> None:\n        self._update_requested.set()\n\n\nclass TUIApp(App[None]):\n    \"\"\"TUI main application class.\"\"\"\n\n    CSS_PATH = \"tui.css\"\n\n    def __init__(\n        self,\n        reader: SocketReader,\n        cmdline_override: Optional[str] = None,\n        poll_interval: float = 1.0,\n    ) -> None:\n        self._reader = reader\n        self._poll_interval = poll_interval\n        self._cmdline_override = cmdline_override\n        self._update_thread = UpdateThread(self, self._reader)\n        self.tui: Optional[TUI] = None\n        super().__init__()\n\n    def on_mount(self) -> None:\n        self.set_interval(self._poll_interval, self._update_thread.schedule_update)\n        cmd_line = (\n            self._cmdline_override\n            if self._cmdline_override is not None\n            else self._reader.command_line\n        )\n\n        if cmd_line is not None and \"/memray\" in cmd_line:\n            cmd_args = cmd_line.split()\n            if any(cmd_args[0].endswith(p) for p in (\"/memray\", \"/memray/__main__.py\")):\n                cmd_args[0] = \"memray\"\n                cmd_line = \" \".join(cmd_args)\n\n        self.tui = TUI(\n            pid=self._reader.pid,\n            cmd_line=cmd_line,\n            native=self._reader.has_native_traces,\n        )\n        self.push_screen(self.tui)\n        self._update_thread.start()\n\n    def on_unmount(self) -> None:\n        self._update_thread.cancel()\n        if self._update_thread.is_alive():\n            self._update_thread.join()\n\n    def on_snapshot_fetched(self, message: SnapshotFetched) -> None:\n        \"\"\"Method called to process each fetched snapshot.\"\"\"\n        assert self.tui is not None\n        with self.batch_update():\n            self.tui.snapshot = message.snapshot\n        if message.disconnected:\n            self.tui.disconnected = True\n\n    def on_resize(self, event: events.Resize) -> None:\n        self.set_class(0 <= event.size.width < 81, \"narrow\")\n\n    if hasattr(App, \"namespace_bindings\"):\n        # Removed in Textual 0.61\n        @property\n        def namespace_bindings(self) -> Dict[str, Tuple[DOMNode, Binding]]:\n            bindings = super().namespace_bindings.copy()  # type: ignore[misc]\n            if self.tui:\n                self.tui.rewrite_bindings(bindings)\n            return bindings  # type: ignore[no-any-return]\n"
  },
  {
    "path": "src/vendor/libbacktrace/.gitignore",
    "content": "*~\n*.o\n*.lo\n*.a\n*.la\n"
  },
  {
    "path": "src/vendor/libbacktrace/Isaac.Newton-Opticks.txt",
    "content": "Produced by Suzanne Lybarger, steve harris, Josephine\nPaolucci and the Online Distributed Proofreading Team at\nhttp://www.pgdp.net.\n\n\n\n\n\n\nOPTICKS:\n\nOR, A\n\nTREATISE\n\nOF THE\n\n_Reflections_, _Refractions_,\n_Inflections_ and _Colours_\n\nOF\n\nLIGHT.\n\n_The_ FOURTH EDITION, _corrected_.\n\nBy Sir _ISAAC NEWTON_, Knt.\n\nLONDON:\n\nPrinted for WILLIAM INNYS at the West-End of St. _Paul's_. MDCCXXX.\n\nTITLE PAGE OF THE 1730 EDITION\n\n\n\n\nSIR ISAAC NEWTON'S ADVERTISEMENTS\n\n\n\n\nAdvertisement I\n\n\n_Part of the ensuing Discourse about Light was written at the Desire of\nsome Gentlemen of the_ Royal-Society, _in the Year 1675, and then sent\nto their Secretary, and read at their Meetings, and the rest was added\nabout twelve Years after to complete the Theory; except the third Book,\nand the last Proposition of the Second, which were since put together\nout of scatter'd Papers. To avoid being engaged in Disputes about these\nMatters, I have hitherto delayed the printing, and should still have\ndelayed it, had not the Importunity of Friends prevailed upon me. If any\nother Papers writ on this Subject are got out of my Hands they are\nimperfect, and were perhaps written before I had tried all the\nExperiments here set down, and fully satisfied my self about the Laws of\nRefractions and Composition of Colours. I have here publish'd what I\nthink proper to come abroad, wishing that it may not be translated into\nanother Language without my Consent._\n\n_The Crowns of Colours, which sometimes appear about the Sun and Moon, I\nhave endeavoured to give an Account of; but for want of sufficient\nObservations leave that Matter to be farther examined. The Subject of\nthe Third Book I have also left imperfect, not having tried all the\nExperiments which I intended when I was about these Matters, nor\nrepeated some of those which I did try, until I had satisfied my self\nabout all their Circumstances. To communicate what I have tried, and\nleave the rest to others for farther Enquiry, is all my Design in\npublishing these Papers._\n\n_In a Letter written to Mr._ Leibnitz _in the year 1679, and published\nby Dr._ Wallis, _I mention'd a Method by which I had found some general\nTheorems about squaring Curvilinear Figures, or comparing them with the\nConic Sections, or other the simplest Figures with which they may be\ncompared. And some Years ago I lent out a Manuscript containing such\nTheorems, and having since met with some Things copied out of it, I have\non this Occasion made it publick, prefixing to it an_ Introduction, _and\nsubjoining a_ Scholium _concerning that Method. And I have joined with\nit another small Tract concerning the Curvilinear Figures of the Second\nKind, which was also written many Years ago, and made known to some\nFriends, who have solicited the making it publick._\n\n                                        _I. N._\n\nApril 1, 1704.\n\n\nAdvertisement II\n\n_In this Second Edition of these Opticks I have omitted the Mathematical\nTracts publish'd at the End of the former Edition, as not belonging to\nthe Subject. And at the End of the Third Book I have added some\nQuestions. And to shew that I do not take Gravity for an essential\nProperty of Bodies, I have added one Question concerning its Cause,\nchusing to propose it by way of a Question, because I am not yet\nsatisfied about it for want of Experiments._\n\n                                        _I. N._\n\nJuly 16, 1717.\n\n\nAdvertisement to this Fourth Edition\n\n_This new Edition of Sir_ Isaac Newton's Opticks _is carefully printed\nfrom the Third Edition, as it was corrected by the Author's own Hand,\nand left before his Death with the Bookseller. Since Sir_ Isaac's\nLectiones Opticæ, _which he publickly read in the University of_\nCambridge _in the Years 1669, 1670, and 1671, are lately printed, it has\nbeen thought proper to make at the bottom of the Pages several Citations\nfrom thence, where may be found the Demonstrations, which the Author\nomitted in these_ Opticks.\n\n       *       *       *       *       *\n\nTranscriber's Note: There are several greek letters used in the\ndescriptions of the illustrations. They are signified by [Greek:\nletter]. Square roots are noted by the letters sqrt before the equation.\n\n       *       *       *       *       *\n\nTHE FIRST BOOK OF OPTICKS\n\n\n\n\n_PART I._\n\n\nMy Design in this Book is not to explain the Properties of Light by\nHypotheses, but to propose and prove them by Reason and Experiments: In\norder to which I shall premise the following Definitions and Axioms.\n\n\n\n\n_DEFINITIONS_\n\n\nDEFIN. I.\n\n_By the Rays of Light I understand its least Parts, and those as well\nSuccessive in the same Lines, as Contemporary in several Lines._ For it\nis manifest that Light consists of Parts, both Successive and\nContemporary; because in the same place you may stop that which comes\none moment, and let pass that which comes presently after; and in the\nsame time you may stop it in any one place, and let it pass in any\nother. For that part of Light which is stopp'd cannot be the same with\nthat which is let pass. The least Light or part of Light, which may be\nstopp'd alone without the rest of the Light, or propagated alone, or do\nor suffer any thing alone, which the rest of the Light doth not or\nsuffers not, I call a Ray of Light.\n\n\nDEFIN. II.\n\n_Refrangibility of the Rays of Light, is their Disposition to be\nrefracted or turned out of their Way in passing out of one transparent\nBody or Medium into another. And a greater or less Refrangibility of\nRays, is their Disposition to be turned more or less out of their Way in\nlike Incidences on the same Medium._ Mathematicians usually consider the\nRays of Light to be Lines reaching from the luminous Body to the Body\nilluminated, and the refraction of those Rays to be the bending or\nbreaking of those lines in their passing out of one Medium into another.\nAnd thus may Rays and Refractions be considered, if Light be propagated\nin an instant. But by an Argument taken from the Æquations of the times\nof the Eclipses of _Jupiter's Satellites_, it seems that Light is\npropagated in time, spending in its passage from the Sun to us about\nseven Minutes of time: And therefore I have chosen to define Rays and\nRefractions in such general terms as may agree to Light in both cases.\n\n\nDEFIN. III.\n\n_Reflexibility of Rays, is their Disposition to be reflected or turned\nback into the same Medium from any other Medium upon whose Surface they\nfall. And Rays are more or less reflexible, which are turned back more\nor less easily._ As if Light pass out of a Glass into Air, and by being\ninclined more and more to the common Surface of the Glass and Air,\nbegins at length to be totally reflected by that Surface; those sorts of\nRays which at like Incidences are reflected most copiously, or by\ninclining the Rays begin soonest to be totally reflected, are most\nreflexible.\n\n\nDEFIN. IV.\n\n_The Angle of Incidence is that Angle, which the Line described by the\nincident Ray contains with the Perpendicular to the reflecting or\nrefracting Surface at the Point of Incidence._\n\n\nDEFIN. V.\n\n_The Angle of Reflexion or Refraction, is the Angle which the line\ndescribed by the reflected or refracted Ray containeth with the\nPerpendicular to the reflecting or refracting Surface at the Point of\nIncidence._\n\n\nDEFIN. VI.\n\n_The Sines of Incidence, Reflexion, and Refraction, are the Sines of the\nAngles of Incidence, Reflexion, and Refraction._\n\n\nDEFIN. VII\n\n_The Light whose Rays are all alike Refrangible, I call Simple,\nHomogeneal and Similar; and that whose Rays are some more Refrangible\nthan others, I call Compound, Heterogeneal and Dissimilar._ The former\nLight I call Homogeneal, not because I would affirm it so in all\nrespects, but because the Rays which agree in Refrangibility, agree at\nleast in all those their other Properties which I consider in the\nfollowing Discourse.\n\n\nDEFIN. VIII.\n\n_The Colours of Homogeneal Lights, I call Primary, Homogeneal and\nSimple; and those of Heterogeneal Lights, Heterogeneal and Compound._\nFor these are always compounded of the colours of Homogeneal Lights; as\nwill appear in the following Discourse.\n\n\n\n\n_AXIOMS._\n\n\nAX. I.\n\n_The Angles of Reflexion and Refraction, lie in one and the same Plane\nwith the Angle of Incidence._\n\n\nAX. II.\n\n_The Angle of Reflexion is equal to the Angle of Incidence._\n\n\nAX. III.\n\n_If the refracted Ray be returned directly back to the Point of\nIncidence, it shall be refracted into the Line before described by the\nincident Ray._\n\n\nAX. IV.\n\n_Refraction out of the rarer Medium into the denser, is made towards the\nPerpendicular; that is, so that the Angle of Refraction be less than the\nAngle of Incidence._\n\n\nAX. V.\n\n_The Sine of Incidence is either accurately or very nearly in a given\nRatio to the Sine of Refraction._\n\nWhence if that Proportion be known in any one Inclination of the\nincident Ray, 'tis known in all the Inclinations, and thereby the\nRefraction in all cases of Incidence on the same refracting Body may be\ndetermined. Thus if the Refraction be made out of Air into Water, the\nSine of Incidence of the red Light is to the Sine of its Refraction as 4\nto 3. If out of Air into Glass, the Sines are as 17 to 11. In Light of\nother Colours the Sines have other Proportions: but the difference is so\nlittle that it need seldom be considered.\n\n[Illustration: FIG. 1]\n\nSuppose therefore, that RS [in _Fig._ 1.] represents the Surface of\nstagnating Water, and that C is the point of Incidence in which any Ray\ncoming in the Air from A in the Line AC is reflected or refracted, and I\nwould know whither this Ray shall go after Reflexion or Refraction: I\nerect upon the Surface of the Water from the point of Incidence the\nPerpendicular CP and produce it downwards to Q, and conclude by the\nfirst Axiom, that the Ray after Reflexion and Refraction, shall be\nfound somewhere in the Plane of the Angle of Incidence ACP produced. I\nlet fall therefore upon the Perpendicular CP the Sine of Incidence AD;\nand if the reflected Ray be desired, I produce AD to B so that DB be\nequal to AD, and draw CB. For this Line CB shall be the reflected Ray;\nthe Angle of Reflexion BCP and its Sine BD being equal to the Angle and\nSine of Incidence, as they ought to be by the second Axiom, But if the\nrefracted Ray be desired, I produce AD to H, so that DH may be to AD as\nthe Sine of Refraction to the Sine of Incidence, that is, (if the Light\nbe red) as 3 to 4; and about the Center C and in the Plane ACP with the\nRadius CA describing a Circle ABE, I draw a parallel to the\nPerpendicular CPQ, the Line HE cutting the Circumference in E, and\njoining CE, this Line CE shall be the Line of the refracted Ray. For if\nEF be let fall perpendicularly on the Line PQ, this Line EF shall be the\nSine of Refraction of the Ray CE, the Angle of Refraction being ECQ; and\nthis Sine EF is equal to DH, and consequently in Proportion to the Sine\nof Incidence AD as 3 to 4.\n\nIn like manner, if there be a Prism of Glass (that is, a Glass bounded\nwith two Equal and Parallel Triangular ends, and three plain and well\npolished Sides, which meet in three Parallel Lines running from the\nthree Angles of one end to the three Angles of the other end) and if the\nRefraction of the Light in passing cross this Prism be desired: Let ACB\n[in _Fig._ 2.] represent a Plane cutting this Prism transversly to its\nthree Parallel lines or edges there where the Light passeth through it,\nand let DE be the Ray incident upon the first side of the Prism AC where\nthe Light goes into the Glass; and by putting the Proportion of the Sine\nof Incidence to the Sine of Refraction as 17 to 11 find EF the first\nrefracted Ray. Then taking this Ray for the Incident Ray upon the second\nside of the Glass BC where the Light goes out, find the next refracted\nRay FG by putting the Proportion of the Sine of Incidence to the Sine of\nRefraction as 11 to 17. For if the Sine of Incidence out of Air into\nGlass be to the Sine of Refraction as 17 to 11, the Sine of Incidence\nout of Glass into Air must on the contrary be to the Sine of Refraction\nas 11 to 17, by the third Axiom.\n\n[Illustration: FIG. 2.]\n\nMuch after the same manner, if ACBD [in _Fig._ 3.] represent a Glass\nspherically convex on both sides (usually called a _Lens_, such as is a\nBurning-glass, or Spectacle-glass, or an Object-glass of a Telescope)\nand it be required to know how Light falling upon it from any lucid\npoint Q shall be refracted, let QM represent a Ray falling upon any\npoint M of its first spherical Surface ACB, and by erecting a\nPerpendicular to the Glass at the point M, find the first refracted Ray\nMN by the Proportion of the Sines 17 to 11. Let that Ray in going out of\nthe Glass be incident upon N, and then find the second refracted Ray\nN_q_ by the Proportion of the Sines 11 to 17. And after the same manner\nmay the Refraction be found when the Lens is convex on one side and\nplane or concave on the other, or concave on both sides.\n\n[Illustration: FIG. 3.]\n\n\nAX. VI.\n\n_Homogeneal Rays which flow from several Points of any Object, and fall\nperpendicularly or almost perpendicularly on any reflecting or\nrefracting Plane or spherical Surface, shall afterwards diverge from so\nmany other Points, or be parallel to so many other Lines, or converge to\nso many other Points, either accurately or without any sensible Error.\nAnd the same thing will happen, if the Rays be reflected or refracted\nsuccessively by two or three or more Plane or Spherical Surfaces._\n\nThe Point from which Rays diverge or to which they converge may be\ncalled their _Focus_. And the Focus of the incident Rays being given,\nthat of the reflected or refracted ones may be found by finding the\nRefraction of any two Rays, as above; or more readily thus.\n\n_Cas._ 1. Let ACB [in _Fig._ 4.] be a reflecting or refracting Plane,\nand Q the Focus of the incident Rays, and Q_q_C a Perpendicular to that\nPlane. And if this Perpendicular be produced to _q_, so that _q_C be\nequal to QC, the Point _q_ shall be the Focus of the reflected Rays: Or\nif _q_C be taken on the same side of the Plane with QC, and in\nproportion to QC as the Sine of Incidence to the Sine of Refraction, the\nPoint _q_ shall be the Focus of the refracted Rays.\n\n[Illustration: FIG. 4.]\n\n_Cas._ 2. Let ACB [in _Fig._ 5.] be the reflecting Surface of any Sphere\nwhose Centre is E. Bisect any Radius thereof, (suppose EC) in T, and if\nin that Radius on the same side the Point T you take the Points Q and\n_q_, so that TQ, TE, and T_q_, be continual Proportionals, and the Point\nQ be the Focus of the incident Rays, the Point _q_ shall be the Focus of\nthe reflected ones.\n\n[Illustration: FIG. 5.]\n\n_Cas._ 3. Let ACB [in _Fig._ 6.] be the refracting Surface of any Sphere\nwhose Centre is E. In any Radius thereof EC produced both ways take ET\nand C_t_ equal to one another and severally in such Proportion to that\nRadius as the lesser of the Sines of Incidence and Refraction hath to\nthe difference of those Sines. And then if in the same Line you find any\ntwo Points Q and _q_, so that TQ be to ET as E_t_ to _tq_, taking _tq_\nthe contrary way from _t_ which TQ lieth from T, and if the Point Q be\nthe Focus of any incident Rays, the Point _q_ shall be the Focus of the\nrefracted ones.\n\n[Illustration: FIG. 6.]\n\nAnd by the same means the Focus of the Rays after two or more Reflexions\nor Refractions may be found.\n\n[Illustration: FIG. 7.]\n\n_Cas._ 4. Let ACBD [in _Fig._ 7.] be any refracting Lens, spherically\nConvex or Concave or Plane on either side, and let CD be its Axis (that\nis, the Line which cuts both its Surfaces perpendicularly, and passes\nthrough the Centres of the Spheres,) and in this Axis produced let F and\n_f_ be the Foci of the refracted Rays found as above, when the incident\nRays on both sides the Lens are parallel to the same Axis; and upon the\nDiameter F_f_ bisected in E, describe a Circle. Suppose now that any\nPoint Q be the Focus of any incident Rays. Draw QE cutting the said\nCircle in T and _t_, and therein take _tq_ in such proportion to _t_E as\n_t_E or TE hath to TQ. Let _tq_ lie the contrary way from _t_ which TQ\ndoth from T, and _q_ shall be the Focus of the refracted Rays without\nany sensible Error, provided the Point Q be not so remote from the Axis,\nnor the Lens so broad as to make any of the Rays fall too obliquely on\nthe refracting Surfaces.[A]\n\nAnd by the like Operations may the reflecting or refracting Surfaces be\nfound when the two Foci are given, and thereby a Lens be formed, which\nshall make the Rays flow towards or from what Place you please.[B]\n\nSo then the Meaning of this Axiom is, that if Rays fall upon any Plane\nor Spherical Surface or Lens, and before their Incidence flow from or\ntowards any Point Q, they shall after Reflexion or Refraction flow from\nor towards the Point _q_ found by the foregoing Rules. And if the\nincident Rays flow from or towards several points Q, the reflected or\nrefracted Rays shall flow from or towards so many other Points _q_\nfound by the same Rules. Whether the reflected and refracted Rays flow\nfrom or towards the Point _q_ is easily known by the situation of that\nPoint. For if that Point be on the same side of the reflecting or\nrefracting Surface or Lens with the Point Q, and the incident Rays flow\nfrom the Point Q, the reflected flow towards the Point _q_ and the\nrefracted from it; and if the incident Rays flow towards Q, the\nreflected flow from _q_, and the refracted towards it. And the contrary\nhappens when _q_ is on the other side of the Surface.\n\n\nAX. VII.\n\n_Wherever the Rays which come from all the Points of any Object meet\nagain in so many Points after they have been made to converge by\nReflection or Refraction, there they will make a Picture of the Object\nupon any white Body on which they fall._\n\nSo if PR [in _Fig._ 3.] represent any Object without Doors, and AB be a\nLens placed at a hole in the Window-shut of a dark Chamber, whereby the\nRays that come from any Point Q of that Object are made to converge and\nmeet again in the Point _q_; and if a Sheet of white Paper be held at\n_q_ for the Light there to fall upon it, the Picture of that Object PR\nwill appear upon the Paper in its proper shape and Colours. For as the\nLight which comes from the Point Q goes to the Point _q_, so the Light\nwhich comes from other Points P and R of the Object, will go to so many\nother correspondent Points _p_ and _r_ (as is manifest by the sixth\nAxiom;) so that every Point of the Object shall illuminate a\ncorrespondent Point of the Picture, and thereby make a Picture like the\nObject in Shape and Colour, this only excepted, that the Picture shall\nbe inverted. And this is the Reason of that vulgar Experiment of casting\nthe Species of Objects from abroad upon a Wall or Sheet of white Paper\nin a dark Room.\n\nIn like manner, when a Man views any Object PQR, [in _Fig._ 8.] the\nLight which comes from the several Points of the Object is so refracted\nby the transparent skins and humours of the Eye, (that is, by the\noutward coat EFG, called the _Tunica Cornea_, and by the crystalline\nhumour AB which is beyond the Pupil _mk_) as to converge and meet again\nin so many Points in the bottom of the Eye, and there to paint the\nPicture of the Object upon that skin (called the _Tunica Retina_) with\nwhich the bottom of the Eye is covered. For Anatomists, when they have\ntaken off from the bottom of the Eye that outward and most thick Coat\ncalled the _Dura Mater_, can then see through the thinner Coats, the\nPictures of Objects lively painted thereon. And these Pictures,\npropagated by Motion along the Fibres of the Optick Nerves into the\nBrain, are the cause of Vision. For accordingly as these Pictures are\nperfect or imperfect, the Object is seen perfectly or imperfectly. If\nthe Eye be tinged with any colour (as in the Disease of the _Jaundice_)\nso as to tinge the Pictures in the bottom of the Eye with that Colour,\nthen all Objects appear tinged with the same Colour. If the Humours of\nthe Eye by old Age decay, so as by shrinking to make the _Cornea_ and\nCoat of the _Crystalline Humour_ grow flatter than before, the Light\nwill not be refracted enough, and for want of a sufficient Refraction\nwill not converge to the bottom of the Eye but to some place beyond it,\nand by consequence paint in the bottom of the Eye a confused Picture,\nand according to the Indistinctness of this Picture the Object will\nappear confused. This is the reason of the decay of sight in old Men,\nand shews why their Sight is mended by Spectacles. For those Convex\nglasses supply the defect of plumpness in the Eye, and by increasing the\nRefraction make the Rays converge sooner, so as to convene distinctly at\nthe bottom of the Eye if the Glass have a due degree of convexity. And\nthe contrary happens in short-sighted Men whose Eyes are too plump. For\nthe Refraction being now too great, the Rays converge and convene in the\nEyes before they come at the bottom; and therefore the Picture made in\nthe bottom and the Vision caused thereby will not be distinct, unless\nthe Object be brought so near the Eye as that the place where the\nconverging Rays convene may be removed to the bottom, or that the\nplumpness of the Eye be taken off and the Refractions diminished by a\nConcave-glass of a due degree of Concavity, or lastly that by Age the\nEye grow flatter till it come to a due Figure: For short-sighted Men see\nremote Objects best in Old Age, and therefore they are accounted to have\nthe most lasting Eyes.\n\n[Illustration: FIG. 8.]\n\n\nAX. VIII.\n\n_An Object seen by Reflexion or Refraction, appears in that place from\nwhence the Rays after their last Reflexion or Refraction diverge in\nfalling on the Spectator's Eye._\n\n[Illustration: FIG. 9.]\n\nIf the Object A [in FIG. 9.] be seen by Reflexion of a Looking-glass\n_mn_, it shall appear, not in its proper place A, but behind the Glass\nat _a_, from whence any Rays AB, AC, AD, which flow from one and the\nsame Point of the Object, do after their Reflexion made in the Points B,\nC, D, diverge in going from the Glass to E, F, G, where they are\nincident on the Spectator's Eyes. For these Rays do make the same\nPicture in the bottom of the Eyes as if they had come from the Object\nreally placed at _a_ without the Interposition of the Looking-glass; and\nall Vision is made according to the place and shape of that Picture.\n\nIn like manner the Object D [in FIG. 2.] seen through a Prism, appears\nnot in its proper place D, but is thence translated to some other place\n_d_ situated in the last refracted Ray FG drawn backward from F to _d_.\n\n[Illustration: FIG. 10.]\n\nAnd so the Object Q [in FIG. 10.] seen through the Lens AB, appears at\nthe place _q_ from whence the Rays diverge in passing from the Lens to\nthe Eye. Now it is to be noted, that the Image of the Object at _q_ is\nso much bigger or lesser than the Object it self at Q, as the distance\nof the Image at _q_ from the Lens AB is bigger or less than the distance\nof the Object at Q from the same Lens. And if the Object be seen through\ntwo or more such Convex or Concave-glasses, every Glass shall make a new\nImage, and the Object shall appear in the place of the bigness of the\nlast Image. Which consideration unfolds the Theory of Microscopes and\nTelescopes. For that Theory consists in almost nothing else than the\ndescribing such Glasses as shall make the last Image of any Object as\ndistinct and large and luminous as it can conveniently be made.\n\nI have now given in Axioms and their Explications the sum of what hath\nhitherto been treated of in Opticks. For what hath been generally\nagreed on I content my self to assume under the notion of Principles, in\norder to what I have farther to write. And this may suffice for an\nIntroduction to Readers of quick Wit and good Understanding not yet\nversed in Opticks: Although those who are already acquainted with this\nScience, and have handled Glasses, will more readily apprehend what\nfolloweth.\n\nFOOTNOTES:\n\n[A] In our Author's _Lectiones Opticæ_, Part I. Sect. IV. Prop 29, 30,\nthere is an elegant Method of determining these _Foci_; not only in\nspherical Surfaces, but likewise in any other curved Figure whatever:\nAnd in Prop. 32, 33, the same thing is done for any Ray lying out of the\nAxis.\n\n[B] _Ibid._ Prop. 34.\n\n\n\n\n_PROPOSITIONS._\n\n\n\n_PROP._ I. THEOR. I.\n\n_Lights which differ in Colour, differ also in Degrees of\nRefrangibility._\n\nThe PROOF by Experiments.\n\n_Exper._ 1.\n\nI took a black oblong stiff Paper terminated by Parallel Sides, and with\na Perpendicular right Line drawn cross from one Side to the other,\ndistinguished it into two equal Parts. One of these parts I painted with\na red colour and the other with a blue. The Paper was very black, and\nthe Colours intense and thickly laid on, that the Phænomenon might be\nmore conspicuous. This Paper I view'd through a Prism of solid Glass,\nwhose two Sides through which the Light passed to the Eye were plane and\nwell polished, and contained an Angle of about sixty degrees; which\nAngle I call the refracting Angle of the Prism. And whilst I view'd it,\nI held it and the Prism before a Window in such manner that the Sides of\nthe Paper were parallel to the Prism, and both those Sides and the Prism\nwere parallel to the Horizon, and the cross Line was also parallel to\nit: and that the Light which fell from the Window upon the Paper made an\nAngle with the Paper, equal to that Angle which was made with the same\nPaper by the Light reflected from it to the Eye. Beyond the Prism was\nthe Wall of the Chamber under the Window covered over with black Cloth,\nand the Cloth was involved in Darkness that no Light might be reflected\nfrom thence, which in passing by the Edges of the Paper to the Eye,\nmight mingle itself with the Light of the Paper, and obscure the\nPhænomenon thereof. These things being thus ordered, I found that if the\nrefracting Angle of the Prism be turned upwards, so that the Paper may\nseem to be lifted upwards by the Refraction, its blue half will be\nlifted higher by the Refraction than its red half. But if the refracting\nAngle of the Prism be turned downward, so that the Paper may seem to be\ncarried lower by the Refraction, its blue half will be carried something\nlower thereby than its red half. Wherefore in both Cases the Light which\ncomes from the blue half of the Paper through the Prism to the Eye, does\nin like Circumstances suffer a greater Refraction than the Light which\ncomes from the red half, and by consequence is more refrangible.\n\n_Illustration._ In the eleventh Figure, MN represents the Window, and DE\nthe Paper terminated with parallel Sides DJ and HE, and by the\ntransverse Line FG distinguished into two halfs, the one DG of an\nintensely blue Colour, the other FE of an intensely red. And BAC_cab_\nrepresents the Prism whose refracting Planes AB_ba_ and AC_ca_ meet in\nthe Edge of the refracting Angle A_a_. This Edge A_a_ being upward, is\nparallel both to the Horizon, and to the Parallel-Edges of the Paper DJ\nand HE, and the transverse Line FG is perpendicular to the Plane of the\nWindow. And _de_ represents the Image of the Paper seen by Refraction\nupwards in such manner, that the blue half DG is carried higher to _dg_\nthan the red half FE is to _fe_, and therefore suffers a greater\nRefraction. If the Edge of the refracting Angle be turned downward, the\nImage of the Paper will be refracted downward; suppose to [Greek: de],\nand the blue half will be refracted lower to [Greek: dg] than the red\nhalf is to [Greek: pe].\n\n[Illustration: FIG. 11.]\n\n_Exper._ 2. About the aforesaid Paper, whose two halfs were painted over\nwith red and blue, and which was stiff like thin Pasteboard, I lapped\nseveral times a slender Thred of very black Silk, in such manner that\nthe several parts of the Thred might appear upon the Colours like so\nmany black Lines drawn over them, or like long and slender dark Shadows\ncast upon them. I might have drawn black Lines with a Pen, but the\nThreds were smaller and better defined. This Paper thus coloured and\nlined I set against a Wall perpendicularly to the Horizon, so that one\nof the Colours might stand to the Right Hand, and the other to the Left.\nClose before the Paper, at the Confine of the Colours below, I placed a\nCandle to illuminate the Paper strongly: For the Experiment was tried in\nthe Night. The Flame of the Candle reached up to the lower edge of the\nPaper, or a very little higher. Then at the distance of six Feet, and\none or two Inches from the Paper upon the Floor I erected a Glass Lens\nfour Inches and a quarter broad, which might collect the Rays coming\nfrom the several Points of the Paper, and make them converge towards so\nmany other Points at the same distance of six Feet, and one or two\nInches on the other side of the Lens, and so form the Image of the\ncoloured Paper upon a white Paper placed there, after the same manner\nthat a Lens at a Hole in a Window casts the Images of Objects abroad\nupon a Sheet of white Paper in a dark Room. The aforesaid white Paper,\nerected perpendicular to the Horizon, and to the Rays which fell upon it\nfrom the Lens, I moved sometimes towards the Lens, sometimes from it, to\nfind the Places where the Images of the blue and red Parts of the\ncoloured Paper appeared most distinct. Those Places I easily knew by the\nImages of the black Lines which I had made by winding the Silk about the\nPaper. For the Images of those fine and slender Lines (which by reason\nof their Blackness were like Shadows on the Colours) were confused and\nscarce visible, unless when the Colours on either side of each Line were\nterminated most distinctly, Noting therefore, as diligently as I could,\nthe Places where the Images of the red and blue halfs of the coloured\nPaper appeared most distinct, I found that where the red half of the\nPaper appeared distinct, the blue half appeared confused, so that the\nblack Lines drawn upon it could scarce be seen; and on the contrary,\nwhere the blue half appeared most distinct, the red half appeared\nconfused, so that the black Lines upon it were scarce visible. And\nbetween the two Places where these Images appeared distinct there was\nthe distance of an Inch and a half; the distance of the white Paper from\nthe Lens, when the Image of the red half of the coloured Paper appeared\nmost distinct, being greater by an Inch and an half than the distance of\nthe same white Paper from the Lens, when the Image of the blue half\nappeared most distinct. In like Incidences therefore of the blue and red\nupon the Lens, the blue was refracted more by the Lens than the red, so\nas to converge sooner by an Inch and a half, and therefore is more\nrefrangible.\n\n_Illustration._ In the twelfth Figure (p. 27), DE signifies the coloured\nPaper, DG the blue half, FE the red half, MN the Lens, HJ the white\nPaper in that Place where the red half with its black Lines appeared\ndistinct, and _hi_ the same Paper in that Place where the blue half\nappeared distinct. The Place _hi_ was nearer to the Lens MN than the\nPlace HJ by an Inch and an half.\n\n_Scholium._ The same Things succeed, notwithstanding that some of the\nCircumstances be varied; as in the first Experiment when the Prism and\nPaper are any ways inclined to the Horizon, and in both when coloured\nLines are drawn upon very black Paper. But in the Description of these\nExperiments, I have set down such Circumstances, by which either the\nPhænomenon might be render'd more conspicuous, or a Novice might more\neasily try them, or by which I did try them only. The same Thing, I have\noften done in the following Experiments: Concerning all which, this one\nAdmonition may suffice. Now from these Experiments it follows not, that\nall the Light of the blue is more refrangible than all the Light of the\nred: For both Lights are mixed of Rays differently refrangible, so that\nin the red there are some Rays not less refrangible than those of the\nblue, and in the blue there are some Rays not more refrangible than\nthose of the red: But these Rays, in proportion to the whole Light, are\nbut few, and serve to diminish the Event of the Experiment, but are not\nable to destroy it. For, if the red and blue Colours were more dilute\nand weak, the distance of the Images would be less than an Inch and a\nhalf; and if they were more intense and full, that distance would be\ngreater, as will appear hereafter. These Experiments may suffice for the\nColours of Natural Bodies. For in the Colours made by the Refraction of\nPrisms, this Proposition will appear by the Experiments which are now to\nfollow in the next Proposition.\n\n\n_PROP._ II. THEOR. II.\n\n_The Light of the Sun consists of Rays differently Refrangible._\n\nThe PROOF by Experiments.\n\n[Illustration: FIG. 12.]\n\n[Illustration: FIG. 13.]\n\n_Exper._ 3.\n\nIn a very dark Chamber, at a round Hole, about one third Part of an Inch\nbroad, made in the Shut of a Window, I placed a Glass Prism, whereby the\nBeam of the Sun's Light, which came in at that Hole, might be refracted\nupwards toward the opposite Wall of the Chamber, and there form a\ncolour'd Image of the Sun. The Axis of the Prism (that is, the Line\npassing through the middle of the Prism from one end of it to the other\nend parallel to the edge of the Refracting Angle) was in this and the\nfollowing Experiments perpendicular to the incident Rays. About this\nAxis I turned the Prism slowly, and saw the refracted Light on the Wall,\nor coloured Image of the Sun, first to descend, and then to ascend.\nBetween the Descent and Ascent, when the Image seemed Stationary, I\nstopp'd the Prism, and fix'd it in that Posture, that it should be moved\nno more. For in that Posture the Refractions of the Light at the two\nSides of the refracting Angle, that is, at the Entrance of the Rays into\nthe Prism, and at their going out of it, were equal to one another.[C]\nSo also in other Experiments, as often as I would have the Refractions\non both sides the Prism to be equal to one another, I noted the Place\nwhere the Image of the Sun formed by the refracted Light stood still\nbetween its two contrary Motions, in the common Period of its Progress\nand Regress; and when the Image fell upon that Place, I made fast the\nPrism. And in this Posture, as the most convenient, it is to be\nunderstood that all the Prisms are placed in the following Experiments,\nunless where some other Posture is described. The Prism therefore being\nplaced in this Posture, I let the refracted Light fall perpendicularly\nupon a Sheet of white Paper at the opposite Wall of the Chamber, and\nobserved the Figure and Dimensions of the Solar Image formed on the\nPaper by that Light. This Image was Oblong and not Oval, but terminated\nwith two Rectilinear and Parallel Sides, and two Semicircular Ends. On\nits Sides it was bounded pretty distinctly, but on its Ends very\nconfusedly and indistinctly, the Light there decaying and vanishing by\ndegrees. The Breadth of this Image answered to the Sun's Diameter, and\nwas about two Inches and the eighth Part of an Inch, including the\nPenumbra. For the Image was eighteen Feet and an half distant from the\nPrism, and at this distance that Breadth, if diminished by the Diameter\nof the Hole in the Window-shut, that is by a quarter of an Inch,\nsubtended an Angle at the Prism of about half a Degree, which is the\nSun's apparent Diameter. But the Length of the Image was about ten\nInches and a quarter, and the Length of the Rectilinear Sides about\neight Inches; and the refracting Angle of the Prism, whereby so great a\nLength was made, was 64 degrees. With a less Angle the Length of the\nImage was less, the Breadth remaining the same. If the Prism was turned\nabout its Axis that way which made the Rays emerge more obliquely out of\nthe second refracting Surface of the Prism, the Image soon became an\nInch or two longer, or more; and if the Prism was turned about the\ncontrary way, so as to make the Rays fall more obliquely on the first\nrefracting Surface, the Image soon became an Inch or two shorter. And\ntherefore in trying this Experiment, I was as curious as I could be in\nplacing the Prism by the above-mention'd Rule exactly in such a Posture,\nthat the Refractions of the Rays at their Emergence out of the Prism\nmight be equal to that at their Incidence on it. This Prism had some\nVeins running along within the Glass from one end to the other, which\nscattered some of the Sun's Light irregularly, but had no sensible\nEffect in increasing the Length of the coloured Spectrum. For I tried\nthe same Experiment with other Prisms with the same Success. And\nparticularly with a Prism which seemed free from such Veins, and whose\nrefracting Angle was 62-1/2 Degrees, I found the Length of the Image\n9-3/4 or 10 Inches at the distance of 18-1/2 Feet from the Prism, the\nBreadth of the Hole in the Window-shut being 1/4 of an Inch, as before.\nAnd because it is easy to commit a Mistake in placing the Prism in its\ndue Posture, I repeated the Experiment four or five Times, and always\nfound the Length of the Image that which is set down above. With another\nPrism of clearer Glass and better Polish, which seemed free from Veins,\nand whose refracting Angle was 63-1/2 Degrees, the Length of this Image\nat the same distance of 18-1/2 Feet was also about 10 Inches, or 10-1/8.\nBeyond these Measures for about a 1/4 or 1/3 of an Inch at either end of\nthe Spectrum the Light of the Clouds seemed to be a little tinged with\nred and violet, but so very faintly, that I suspected that Tincture\nmight either wholly, or in great Measure arise from some Rays of the\nSpectrum scattered irregularly by some Inequalities in the Substance and\nPolish of the Glass, and therefore I did not include it in these\nMeasures. Now the different Magnitude of the hole in the Window-shut,\nand different thickness of the Prism where the Rays passed through it,\nand different inclinations of the Prism to the Horizon, made no sensible\nchanges in the length of the Image. Neither did the different matter of\nthe Prisms make any: for in a Vessel made of polished Plates of Glass\ncemented together in the shape of a Prism and filled with Water, there\nis the like Success of the Experiment according to the quantity of the\nRefraction. It is farther to be observed, that the Rays went on in right\nLines from the Prism to the Image, and therefore at their very going out\nof the Prism had all that Inclination to one another from which the\nlength of the Image proceeded, that is, the Inclination of more than two\ndegrees and an half. And yet according to the Laws of Opticks vulgarly\nreceived, they could not possibly be so much inclined to one another.[D]\nFor let EG [_Fig._ 13. (p. 27)] represent the Window-shut, F the hole\nmade therein through which a beam of the Sun's Light was transmitted\ninto the darkened Chamber, and ABC a Triangular Imaginary Plane whereby\nthe Prism is feigned to be cut transversely through the middle of the\nLight. Or if you please, let ABC represent the Prism it self, looking\ndirectly towards the Spectator's Eye with its nearer end: And let XY be\nthe Sun, MN the Paper upon which the Solar Image or Spectrum is cast,\nand PT the Image it self whose sides towards _v_ and _w_ are Rectilinear\nand Parallel, and ends towards P and T Semicircular. YKHP and XLJT are\ntwo Rays, the first of which comes from the lower part of the Sun to the\nhigher part of the Image, and is refracted in the Prism at K and H, and\nthe latter comes from the higher part of the Sun to the lower part of\nthe Image, and is refracted at L and J. Since the Refractions on both\nsides the Prism are equal to one another, that is, the Refraction at K\nequal to the Refraction at J, and the Refraction at L equal to the\nRefraction at H, so that the Refractions of the incident Rays at K and L\ntaken together, are equal to the Refractions of the emergent Rays at H\nand J taken together: it follows by adding equal things to equal things,\nthat the Refractions at K and H taken together, are equal to the\nRefractions at J and L taken together, and therefore the two Rays being\nequally refracted, have the same Inclination to one another after\nRefraction which they had before; that is, the Inclination of half a\nDegree answering to the Sun's Diameter. For so great was the inclination\nof the Rays to one another before Refraction. So then, the length of the\nImage PT would by the Rules of Vulgar Opticks subtend an Angle of half a\nDegree at the Prism, and by Consequence be equal to the breadth _vw_;\nand therefore the Image would be round. Thus it would be were the two\nRays XLJT and YKHP, and all the rest which form the Image P_w_T_v_,\nalike refrangible. And therefore seeing by Experience it is found that\nthe Image is not round, but about five times longer than broad, the Rays\nwhich going to the upper end P of the Image suffer the greatest\nRefraction, must be more refrangible than those which go to the lower\nend T, unless the Inequality of Refraction be casual.\n\nThis Image or Spectrum PT was coloured, being red at its least refracted\nend T, and violet at its most refracted end P, and yellow green and\nblue in the intermediate Spaces. Which agrees with the first\nProposition, that Lights which differ in Colour, do also differ in\nRefrangibility. The length of the Image in the foregoing Experiments, I\nmeasured from the faintest and outmost red at one end, to the faintest\nand outmost blue at the other end, excepting only a little Penumbra,\nwhose breadth scarce exceeded a quarter of an Inch, as was said above.\n\n_Exper._ 4. In the Sun's Beam which was propagated into the Room through\nthe hole in the Window-shut, at the distance of some Feet from the hole,\nI held the Prism in such a Posture, that its Axis might be perpendicular\nto that Beam. Then I looked through the Prism upon the hole, and turning\nthe Prism to and fro about its Axis, to make the Image of the Hole\nascend and descend, when between its two contrary Motions it seemed\nStationary, I stopp'd the Prism, that the Refractions of both sides of\nthe refracting Angle might be equal to each other, as in the former\nExperiment. In this situation of the Prism viewing through it the said\nHole, I observed the length of its refracted Image to be many times\ngreater than its breadth, and that the most refracted part thereof\nappeared violet, the least refracted red, the middle parts blue, green\nand yellow in order. The same thing happen'd when I removed the Prism\nout of the Sun's Light, and looked through it upon the hole shining by\nthe Light of the Clouds beyond it. And yet if the Refraction were done\nregularly according to one certain Proportion of the Sines of Incidence\nand Refraction as is vulgarly supposed, the refracted Image ought to\nhave appeared round.\n\nSo then, by these two Experiments it appears, that in Equal Incidences\nthere is a considerable inequality of Refractions. But whence this\ninequality arises, whether it be that some of the incident Rays are\nrefracted more, and others less, constantly, or by chance, or that one\nand the same Ray is by Refraction disturbed, shatter'd, dilated, and as\nit were split and spread into many diverging Rays, as _Grimaldo_\nsupposes, does not yet appear by these Experiments, but will appear by\nthose that follow.\n\n_Exper._ 5. Considering therefore, that if in the third Experiment the\nImage of the Sun should be drawn out into an oblong Form, either by a\nDilatation of every Ray, or by any other casual inequality of the\nRefractions, the same oblong Image would by a second Refraction made\nsideways be drawn out as much in breadth by the like Dilatation of the\nRays, or other casual inequality of the Refractions sideways, I tried\nwhat would be the Effects of such a second Refraction. For this end I\nordered all things as in the third Experiment, and then placed a second\nPrism immediately after the first in a cross Position to it, that it\nmight again refract the beam of the Sun's Light which came to it through\nthe first Prism. In the first Prism this beam was refracted upwards, and\nin the second sideways. And I found that by the Refraction of the second\nPrism, the breadth of the Image was not increased, but its superior\npart, which in the first Prism suffered the greater Refraction, and\nappeared violet and blue, did again in the second Prism suffer a greater\nRefraction than its inferior part, which appeared red and yellow, and\nthis without any Dilatation of the Image in breadth.\n\n[Illustration: FIG. 14]\n\n_Illustration._ Let S [_Fig._ 14, 15.] represent the Sun, F the hole in\nthe Window, ABC the first Prism, DH the second Prism, Y the round Image\nof the Sun made by a direct beam of Light when the Prisms are taken\naway, PT the oblong Image of the Sun made by that beam passing through\nthe first Prism alone, when the second Prism is taken away, and _pt_ the\nImage made by the cross Refractions of both Prisms together. Now if the\nRays which tend towards the several Points of the round Image Y were\ndilated and spread by the Refraction of the first Prism, so that they\nshould not any longer go in single Lines to single Points, but that\nevery Ray being split, shattered, and changed from a Linear Ray to a\nSuperficies of Rays diverging from the Point of Refraction, and lying in\nthe Plane of the Angles of Incidence and Refraction, they should go in\nthose Planes to so many Lines reaching almost from one end of the Image\nPT to the other, and if that Image should thence become oblong: those\nRays and their several parts tending towards the several Points of the\nImage PT ought to be again dilated and spread sideways by the transverse\nRefraction of the second Prism, so as to compose a four square Image,\nsuch as is represented at [Greek: pt]. For the better understanding of\nwhich, let the Image PT be distinguished into five equal parts PQK,\nKQRL, LRSM, MSVN, NVT. And by the same irregularity that the orbicular\nLight Y is by the Refraction of the first Prism dilated and drawn out\ninto a long Image PT, the Light PQK which takes up a space of the same\nlength and breadth with the Light Y ought to be by the Refraction of the\nsecond Prism dilated and drawn out into the long Image _[Greek: p]qkp_,\nand the Light KQRL into the long Image _kqrl_, and the Lights LRSM,\nMSVN, NVT, into so many other long Images _lrsm_, _msvn_, _nvt[Greek:\nt]_; and all these long Images would compose the four square Images\n_[Greek: pt]_. Thus it ought to be were every Ray dilated by Refraction,\nand spread into a triangular Superficies of Rays diverging from the\nPoint of Refraction. For the second Refraction would spread the Rays one\nway as much as the first doth another, and so dilate the Image in\nbreadth as much as the first doth in length. And the same thing ought to\nhappen, were some rays casually refracted more than others. But the\nEvent is otherwise. The Image PT was not made broader by the Refraction\nof the second Prism, but only became oblique, as 'tis represented at\n_pt_, its upper end P being by the Refraction translated to a greater\ndistance than its lower end T. So then the Light which went towards the\nupper end P of the Image, was (at equal Incidences) more refracted in\nthe second Prism, than the Light which tended towards the lower end T,\nthat is the blue and violet, than the red and yellow; and therefore was\nmore refrangible. The same Light was by the Refraction of the first\nPrism translated farther from the place Y to which it tended before\nRefraction; and therefore suffered as well in the first Prism as in the\nsecond a greater Refraction than the rest of the Light, and by\nconsequence was more refrangible than the rest, even before its\nincidence on the first Prism.\n\nSometimes I placed a third Prism after the second, and sometimes also a\nfourth after the third, by all which the Image might be often refracted\nsideways: but the Rays which were more refracted than the rest in the\nfirst Prism were also more refracted in all the rest, and that without\nany Dilatation of the Image sideways: and therefore those Rays for their\nconstancy of a greater Refraction are deservedly reputed more\nrefrangible.\n\n[Illustration: FIG. 15]\n\nBut that the meaning of this Experiment may more clearly appear, it is\nto be considered that the Rays which are equally refrangible do fall\nupon a Circle answering to the Sun's Disque. For this was proved in the\nthird Experiment. By a Circle I understand not here a perfect\ngeometrical Circle, but any orbicular Figure whose length is equal to\nits breadth, and which, as to Sense, may seem circular. Let therefore AG\n[in _Fig._ 15.] represent the Circle which all the most refrangible Rays\npropagated from the whole Disque of the Sun, would illuminate and paint\nupon the opposite Wall if they were alone; EL the Circle which all the\nleast refrangible Rays would in like manner illuminate and paint if they\nwere alone; BH, CJ, DK, the Circles which so many intermediate sorts of\nRays would successively paint upon the Wall, if they were singly\npropagated from the Sun in successive order, the rest being always\nintercepted; and conceive that there are other intermediate Circles\nwithout Number, which innumerable other intermediate sorts of Rays would\nsuccessively paint upon the Wall if the Sun should successively emit\nevery sort apart. And seeing the Sun emits all these sorts at once, they\nmust all together illuminate and paint innumerable equal Circles, of all\nwhich, being according to their degrees of Refrangibility placed in\norder in a continual Series, that oblong Spectrum PT is composed which I\ndescribed in the third Experiment. Now if the Sun's circular Image Y [in\n_Fig._ 15.] which is made by an unrefracted beam of Light was by any\nDilation of the single Rays, or by any other irregularity in the\nRefraction of the first Prism, converted into the oblong Spectrum, PT:\nthen ought every Circle AG, BH, CJ, &c. in that Spectrum, by the cross\nRefraction of the second Prism again dilating or otherwise scattering\nthe Rays as before, to be in like manner drawn out and transformed into\nan oblong Figure, and thereby the breadth of the Image PT would be now\nas much augmented as the length of the Image Y was before by the\nRefraction of the first Prism; and thus by the Refractions of both\nPrisms together would be formed a four square Figure _p[Greek:\np]t[Greek: t]_, as I described above. Wherefore since the breadth of the\nSpectrum PT is not increased by the Refraction sideways, it is certain\nthat the Rays are not split or dilated, or otherways irregularly\nscatter'd by that Refraction, but that every Circle is by a regular and\nuniform Refraction translated entire into another Place, as the Circle\nAG by the greatest Refraction into the place _ag_, the Circle BH by a\nless Refraction into the place _bh_, the Circle CJ by a Refraction still\nless into the place _ci_, and so of the rest; by which means a new\nSpectrum _pt_ inclined to the former PT is in like manner composed of\nCircles lying in a right Line; and these Circles must be of the same\nbigness with the former, because the breadths of all the Spectrums Y, PT\nand _pt_ at equal distances from the Prisms are equal.\n\nI considered farther, that by the breadth of the hole F through which\nthe Light enters into the dark Chamber, there is a Penumbra made in the\nCircuit of the Spectrum Y, and that Penumbra remains in the rectilinear\nSides of the Spectrums PT and _pt_. I placed therefore at that hole a\nLens or Object-glass of a Telescope which might cast the Image of the\nSun distinctly on Y without any Penumbra at all, and found that the\nPenumbra of the rectilinear Sides of the oblong Spectrums PT and _pt_\nwas also thereby taken away, so that those Sides appeared as distinctly\ndefined as did the Circumference of the first Image Y. Thus it happens\nif the Glass of the Prisms be free from Veins, and their sides be\naccurately plane and well polished without those numberless Waves or\nCurles which usually arise from Sand-holes a little smoothed in\npolishing with Putty. If the Glass be only well polished and free from\nVeins, and the Sides not accurately plane, but a little Convex or\nConcave, as it frequently happens; yet may the three Spectrums Y, PT and\n_pt_ want Penumbras, but not in equal distances from the Prisms. Now\nfrom this want of Penumbras, I knew more certainly that every one of the\nCircles was refracted according to some most regular, uniform and\nconstant Law. For if there were any irregularity in the Refraction, the\nright Lines AE and GL, which all the Circles in the Spectrum PT do\ntouch, could not by that Refraction be translated into the Lines _ae_\nand _gl_ as distinct and straight as they were before, but there would\narise in those translated Lines some Penumbra or Crookedness or\nUndulation, or other sensible Perturbation contrary to what is found by\nExperience. Whatsoever Penumbra or Perturbation should be made in the\nCircles by the cross Refraction of the second Prism, all that Penumbra\nor Perturbation would be conspicuous in the right Lines _ae_ and _gl_\nwhich touch those Circles. And therefore since there is no such Penumbra\nor Perturbation in those right Lines, there must be none in the\nCircles. Since the distance between those Tangents or breadth of the\nSpectrum is not increased by the Refractions, the Diameters of the\nCircles are not increased thereby. Since those Tangents continue to be\nright Lines, every Circle which in the first Prism is more or less\nrefracted, is exactly in the same proportion more or less refracted in\nthe second. And seeing all these things continue to succeed after the\nsame manner when the Rays are again in a third Prism, and again in a\nfourth refracted sideways, it is evident that the Rays of one and the\nsame Circle, as to their degree of Refrangibility, continue always\nuniform and homogeneal to one another, and that those of several Circles\ndo differ in degree of Refrangibility, and that in some certain and\nconstant Proportion. Which is the thing I was to prove.\n\nThere is yet another Circumstance or two of this Experiment by which it\nbecomes still more plain and convincing. Let the second Prism DH [in\n_Fig._ 16.] be placed not immediately after the first, but at some\ndistance from it; suppose in the mid-way between it and the Wall on\nwhich the oblong Spectrum PT is cast, so that the Light from the first\nPrism may fall upon it in the form of an oblong Spectrum [Greek: pt]\nparallel to this second Prism, and be refracted sideways to form the\noblong Spectrum _pt_ upon the Wall. And you will find as before, that\nthis Spectrum _pt_ is inclined to that Spectrum PT, which the first\nPrism forms alone without the second; the blue ends P and _p_ being\nfarther distant from one another than the red ones T and _t_, and by\nconsequence that the Rays which go to the blue end [Greek: p] of the\nImage [Greek: pt], and which therefore suffer the greatest Refraction in\nthe first Prism, are again in the second Prism more refracted than the\nrest.\n\n[Illustration: FIG. 16.]\n\n[Illustration: FIG. 17.]\n\nThe same thing I try'd also by letting the Sun's Light into a dark Room\nthrough two little round holes F and [Greek: ph] [in _Fig._ 17.] made in\nthe Window, and with two parallel Prisms ABC and [Greek: abg] placed at\nthose holes (one at each) refracting those two beams of Light to the\nopposite Wall of the Chamber, in such manner that the two colour'd\nImages PT and MN which they there painted were joined end to end and lay\nin one straight Line, the red end T of the one touching the blue end M\nof the other. For if these two refracted Beams were again by a third\nPrism DH placed cross to the two first, refracted sideways, and the\nSpectrums thereby translated to some other part of the Wall of the\nChamber, suppose the Spectrum PT to _pt_ and the Spectrum MN to _mn_,\nthese translated Spectrums _pt_ and _mn_ would not lie in one straight\nLine with their ends contiguous as before, but be broken off from one\nanother and become parallel, the blue end _m_ of the Image _mn_ being by\na greater Refraction translated farther from its former place MT, than\nthe red end _t_ of the other Image _pt_ from the same place MT; which\nputs the Proposition past Dispute. And this happens whether the third\nPrism DH be placed immediately after the two first, or at a great\ndistance from them, so that the Light refracted in the two first Prisms\nbe either white and circular, or coloured and oblong when it falls on\nthe third.\n\n_Exper._ 6. In the middle of two thin Boards I made round holes a third\npart of an Inch in diameter, and in the Window-shut a much broader hole\nbeing made to let into my darkned Chamber a large Beam of the Sun's\nLight; I placed a Prism behind the Shut in that beam to refract it\ntowards the opposite Wall, and close behind the Prism I fixed one of the\nBoards, in such manner that the middle of the refracted Light might pass\nthrough the hole made in it, and the rest be intercepted by the Board.\nThen at the distance of about twelve Feet from the first Board I fixed\nthe other Board in such manner that the middle of the refracted Light\nwhich came through the hole in the first Board, and fell upon the\nopposite Wall, might pass through the hole in this other Board, and the\nrest being intercepted by the Board might paint upon it the coloured\nSpectrum of the Sun. And close behind this Board I fixed another Prism\nto refract the Light which came through the hole. Then I returned\nspeedily to the first Prism, and by turning it slowly to and fro about\nits Axis, I caused the Image which fell upon the second Board to move up\nand down upon that Board, that all its parts might successively pass\nthrough the hole in that Board and fall upon the Prism behind it. And in\nthe mean time, I noted the places on the opposite Wall to which that\nLight after its Refraction in the second Prism did pass; and by the\ndifference of the places I found that the Light which being most\nrefracted in the first Prism did go to the blue end of the Image, was\nagain more refracted in the second Prism than the Light which went to\nthe red end of that Image, which proves as well the first Proposition as\nthe second. And this happened whether the Axis of the two Prisms were\nparallel, or inclined to one another, and to the Horizon in any given\nAngles.\n\n_Illustration._ Let F [in _Fig._ 18.] be the wide hole in the\nWindow-shut, through which the Sun shines upon the first Prism ABC, and\nlet the refracted Light fall upon the middle of the Board DE, and the\nmiddle part of that Light upon the hole G made in the middle part of\nthat Board. Let this trajected part of that Light fall again upon the\nmiddle of the second Board _de_, and there paint such an oblong coloured\nImage of the Sun as was described in the third Experiment. By turning\nthe Prism ABC slowly to and fro about its Axis, this Image will be made\nto move up and down the Board _de_, and by this means all its parts from\none end to the other may be made to pass successively through the hole\n_g_ which is made in the middle of that Board. In the mean while another\nPrism _abc_ is to be fixed next after that hole _g_, to refract the\ntrajected Light a second time. And these things being thus ordered, I\nmarked the places M and N of the opposite Wall upon which the refracted\nLight fell, and found that whilst the two Boards and second Prism\nremained unmoved, those places by turning the first Prism about its Axis\nwere changed perpetually. For when the lower part of the Light which\nfell upon the second Board _de_ was cast through the hole _g_, it went\nto a lower place M on the Wall and when the higher part of that Light\nwas cast through the same hole _g_, it went to a higher place N on the\nWall, and when any intermediate part of the Light was cast through that\nhole, it went to some place on the Wall between M and N. The unchanged\nPosition of the holes in the Boards, made the Incidence of the Rays upon\nthe second Prism to be the same in all cases. And yet in that common\nIncidence some of the Rays were more refracted, and others less. And\nthose were more refracted in this Prism, which by a greater Refraction\nin the first Prism were more turned out of the way, and therefore for\ntheir Constancy of being more refracted are deservedly called more\nrefrangible.\n\n[Illustration: FIG. 18.]\n\n[Illustration: FIG. 20.]\n\n_Exper._ 7. At two holes made near one another in my Window-shut I\nplaced two Prisms, one at each, which might cast upon the opposite Wall\n(after the manner of the third Experiment) two oblong coloured Images of\nthe Sun. And at a little distance from the Wall I placed a long slender\nPaper with straight and parallel edges, and ordered the Prisms and Paper\nso, that the red Colour of one Image might fall directly upon one half\nof the Paper, and the violet Colour of the other Image upon the other\nhalf of the same Paper; so that the Paper appeared of two Colours, red\nand violet, much after the manner of the painted Paper in the first and\nsecond Experiments. Then with a black Cloth I covered the Wall behind\nthe Paper, that no Light might be reflected from it to disturb the\nExperiment, and viewing the Paper through a third Prism held parallel\nto it, I saw that half of it which was illuminated by the violet Light\nto be divided from the other half by a greater Refraction, especially\nwhen I went a good way off from the Paper. For when I viewed it too near\nat hand, the two halfs of the Paper did not appear fully divided from\none another, but seemed contiguous at one of their Angles like the\npainted Paper in the first Experiment. Which also happened when the\nPaper was too broad.\n\n[Illustration: FIG. 19.]\n\nSometimes instead of the Paper I used a white Thred, and this appeared\nthrough the Prism divided into two parallel Threds as is represented in\nthe nineteenth Figure, where DG denotes the Thred illuminated with\nviolet Light from D to E and with red Light from F to G, and _defg_ are\nthe parts of the Thred seen by Refraction. If one half of the Thred be\nconstantly illuminated with red, and the other half be illuminated with\nall the Colours successively, (which may be done by causing one of the\nPrisms to be turned about its Axis whilst the other remains unmoved)\nthis other half in viewing the Thred through the Prism, will appear in\na continual right Line with the first half when illuminated with red,\nand begin to be a little divided from it when illuminated with Orange,\nand remove farther from it when illuminated with yellow, and still\nfarther when with green, and farther when with blue, and go yet farther\noff when illuminated with Indigo, and farthest when with deep violet.\nWhich plainly shews, that the Lights of several Colours are more and\nmore refrangible one than another, in this Order of their Colours, red,\norange, yellow, green, blue, indigo, deep violet; and so proves as well\nthe first Proposition as the second.\n\nI caused also the coloured Spectrums PT [in _Fig._ 17.] and MN made in a\ndark Chamber by the Refractions of two Prisms to lie in a Right Line end\nto end, as was described above in the fifth Experiment, and viewing them\nthrough a third Prism held parallel to their Length, they appeared no\nlonger in a Right Line, but became broken from one another, as they are\nrepresented at _pt_ and _mn_, the violet end _m_ of the Spectrum _mn_\nbeing by a greater Refraction translated farther from its former Place\nMT than the red end _t_ of the other Spectrum _pt_.\n\nI farther caused those two Spectrums PT [in _Fig._ 20.] and MN to become\nco-incident in an inverted Order of their Colours, the red end of each\nfalling on the violet end of the other, as they are represented in the\noblong Figure PTMN; and then viewing them through a Prism DH held\nparallel to their Length, they appeared not co-incident, as when view'd\nwith the naked Eye, but in the form of two distinct Spectrums _pt_ and\n_mn_ crossing one another in the middle after the manner of the Letter\nX. Which shews that the red of the one Spectrum and violet of the other,\nwhich were co-incident at PN and MT, being parted from one another by a\ngreater Refraction of the violet to _p_ and _m_ than of the red to _n_\nand _t_, do differ in degrees of Refrangibility.\n\nI illuminated also a little Circular Piece of white Paper all over with\nthe Lights of both Prisms intermixed, and when it was illuminated with\nthe red of one Spectrum, and deep violet of the other, so as by the\nMixture of those Colours to appear all over purple, I viewed the Paper,\nfirst at a less distance, and then at a greater, through a third Prism;\nand as I went from the Paper, the refracted Image thereof became more\nand more divided by the unequal Refraction of the two mixed Colours, and\nat length parted into two distinct Images, a red one and a violet one,\nwhereof the violet was farthest from the Paper, and therefore suffered\nthe greatest Refraction. And when that Prism at the Window, which cast\nthe violet on the Paper was taken away, the violet Image disappeared;\nbut when the other Prism was taken away the red vanished; which shews,\nthat these two Images were nothing else than the Lights of the two\nPrisms, which had been intermixed on the purple Paper, but were parted\nagain by their unequal Refractions made in the third Prism, through\nwhich the Paper was view'd. This also was observable, that if one of the\nPrisms at the Window, suppose that which cast the violet on the Paper,\nwas turned about its Axis to make all the Colours in this order,\nviolet, indigo, blue, green, yellow, orange, red, fall successively on\nthe Paper from that Prism, the violet Image changed Colour accordingly,\nturning successively to indigo, blue, green, yellow and red, and in\nchanging Colour came nearer and nearer to the red Image made by the\nother Prism, until when it was also red both Images became fully\nco-incident.\n\nI placed also two Paper Circles very near one another, the one in the\nred Light of one Prism, and the other in the violet Light of the other.\nThe Circles were each of them an Inch in diameter, and behind them the\nWall was dark, that the Experiment might not be disturbed by any Light\ncoming from thence. These Circles thus illuminated, I viewed through a\nPrism, so held, that the Refraction might be made towards the red\nCircle, and as I went from them they came nearer and nearer together,\nand at length became co-incident; and afterwards when I went still\nfarther off, they parted again in a contrary Order, the violet by a\ngreater Refraction being carried beyond the red.\n\n_Exper._ 8. In Summer, when the Sun's Light uses to be strongest, I\nplaced a Prism at the Hole of the Window-shut, as in the third\nExperiment, yet so that its Axis might be parallel to the Axis of the\nWorld, and at the opposite Wall in the Sun's refracted Light, I placed\nan open Book. Then going six Feet and two Inches from the Book, I placed\nthere the above-mentioned Lens, by which the Light reflected from the\nBook might be made to converge and meet again at the distance of six\nFeet and two Inches behind the Lens, and there paint the Species of the\nBook upon a Sheet of white Paper much after the manner of the second\nExperiment. The Book and Lens being made fast, I noted the Place where\nthe Paper was, when the Letters of the Book, illuminated by the fullest\nred Light of the Solar Image falling upon it, did cast their Species on\nthat Paper most distinctly: And then I stay'd till by the Motion of the\nSun, and consequent Motion of his Image on the Book, all the Colours\nfrom that red to the middle of the blue pass'd over those Letters; and\nwhen those Letters were illuminated by that blue, I noted again the\nPlace of the Paper when they cast their Species most distinctly upon it:\nAnd I found that this last Place of the Paper was nearer to the Lens\nthan its former Place by about two Inches and an half, or two and three\nquarters. So much sooner therefore did the Light in the violet end of\nthe Image by a greater Refraction converge and meet, than the Light in\nthe red end. But in trying this, the Chamber was as dark as I could make\nit. For, if these Colours be diluted and weakned by the Mixture of any\nadventitious Light, the distance between the Places of the Paper will\nnot be so great. This distance in the second Experiment, where the\nColours of natural Bodies were made use of, was but an Inch and an half,\nby reason of the Imperfection of those Colours. Here in the Colours of\nthe Prism, which are manifestly more full, intense, and lively than\nthose of natural Bodies, the distance is two Inches and three quarters.\nAnd were the Colours still more full, I question not but that the\ndistance would be considerably greater. For the coloured Light of the\nPrism, by the interfering of the Circles described in the second Figure\nof the fifth Experiment, and also by the Light of the very bright Clouds\nnext the Sun's Body intermixing with these Colours, and by the Light\nscattered by the Inequalities in the Polish of the Prism, was so very\nmuch compounded, that the Species which those faint and dark Colours,\nthe indigo and violet, cast upon the Paper were not distinct enough to\nbe well observed.\n\n_Exper._ 9. A Prism, whose two Angles at its Base were equal to one\nanother, and half right ones, and the third a right one, I placed in a\nBeam of the Sun's Light let into a dark Chamber through a Hole in the\nWindow-shut, as in the third Experiment. And turning the Prism slowly\nabout its Axis, until all the Light which went through one of its\nAngles, and was refracted by it began to be reflected by its Base, at\nwhich till then it went out of the Glass, I observed that those Rays\nwhich had suffered the greatest Refraction were sooner reflected than\nthe rest. I conceived therefore, that those Rays of the reflected Light,\nwhich were most refrangible, did first of all by a total Reflexion\nbecome more copious in that Light than the rest, and that afterwards the\nrest also, by a total Reflexion, became as copious as these. To try\nthis, I made the reflected Light pass through another Prism, and being\nrefracted by it to fall afterwards upon a Sheet of white Paper placed\nat some distance behind it, and there by that Refraction to paint the\nusual Colours of the Prism. And then causing the first Prism to be\nturned about its Axis as above, I observed that when those Rays, which\nin this Prism had suffered the greatest Refraction, and appeared of a\nblue and violet Colour began to be totally reflected, the blue and\nviolet Light on the Paper, which was most refracted in the second Prism,\nreceived a sensible Increase above that of the red and yellow, which was\nleast refracted; and afterwards, when the rest of the Light which was\ngreen, yellow, and red, began to be totally reflected in the first\nPrism, the Light of those Colours on the Paper received as great an\nIncrease as the violet and blue had done before. Whence 'tis manifest,\nthat the Beam of Light reflected by the Base of the Prism, being\naugmented first by the more refrangible Rays, and afterwards by the less\nrefrangible ones, is compounded of Rays differently refrangible. And\nthat all such reflected Light is of the same Nature with the Sun's Light\nbefore its Incidence on the Base of the Prism, no Man ever doubted; it\nbeing generally allowed, that Light by such Reflexions suffers no\nAlteration in its Modifications and Properties. I do not here take\nNotice of any Refractions made in the sides of the first Prism, because\nthe Light enters it perpendicularly at the first side, and goes out\nperpendicularly at the second side, and therefore suffers none. So then,\nthe Sun's incident Light being of the same Temper and Constitution with\nhis emergent Light, and the last being compounded of Rays differently\nrefrangible, the first must be in like manner compounded.\n\n[Illustration: FIG. 21.]\n\n_Illustration._ In the twenty-first Figure, ABC is the first Prism, BC\nits Base, B and C its equal Angles at the Base, each of 45 Degrees, A\nits rectangular Vertex, FM a beam of the Sun's Light let into a dark\nRoom through a hole F one third part of an Inch broad, M its Incidence\non the Base of the Prism, MG a less refracted Ray, MH a more refracted\nRay, MN the beam of Light reflected from the Base, VXY the second Prism\nby which this beam in passing through it is refracted, N_t_ the less\nrefracted Light of this beam, and N_p_ the more refracted part thereof.\nWhen the first Prism ABC is turned about its Axis according to the order\nof the Letters ABC, the Rays MH emerge more and more obliquely out of\nthat Prism, and at length after their most oblique Emergence are\nreflected towards N, and going on to _p_ do increase the Number of the\nRays N_p_. Afterwards by continuing the Motion of the first Prism, the\nRays MG are also reflected to N and increase the number of the Rays\nN_t_. And therefore the Light MN admits into its Composition, first the\nmore refrangible Rays, and then the less refrangible Rays, and yet after\nthis Composition is of the same Nature with the Sun's immediate Light\nFM, the Reflexion of the specular Base BC causing no Alteration therein.\n\n_Exper._ 10. Two Prisms, which were alike in Shape, I tied so together,\nthat their Axis and opposite Sides being parallel, they composed a\nParallelopiped. And, the Sun shining into my dark Chamber through a\nlittle hole in the Window-shut, I placed that Parallelopiped in his beam\nat some distance from the hole, in such a Posture, that the Axes of the\nPrisms might be perpendicular to the incident Rays, and that those Rays\nbeing incident upon the first Side of one Prism, might go on through the\ntwo contiguous Sides of both Prisms, and emerge out of the last Side of\nthe second Prism. This Side being parallel to the first Side of the\nfirst Prism, caused the emerging Light to be parallel to the incident.\nThen, beyond these two Prisms I placed a third, which might refract that\nemergent Light, and by that Refraction cast the usual Colours of the\nPrism upon the opposite Wall, or upon a sheet of white Paper held at a\nconvenient Distance behind the Prism for that refracted Light to fall\nupon it. After this I turned the Parallelopiped about its Axis, and\nfound that when the contiguous Sides of the two Prisms became so oblique\nto the incident Rays, that those Rays began all of them to be\nreflected, those Rays which in the third Prism had suffered the greatest\nRefraction, and painted the Paper with violet and blue, were first of\nall by a total Reflexion taken out of the transmitted Light, the rest\nremaining and on the Paper painting their Colours of green, yellow,\norange and red, as before; and afterwards by continuing the Motion of\nthe two Prisms, the rest of the Rays also by a total Reflexion vanished\nin order, according to their degrees of Refrangibility. The Light\ntherefore which emerged out of the two Prisms is compounded of Rays\ndifferently refrangible, seeing the more refrangible Rays may be taken\nout of it, while the less refrangible remain. But this Light being\ntrajected only through the parallel Superficies of the two Prisms, if it\nsuffer'd any change by the Refraction of one Superficies it lost that\nImpression by the contrary Refraction of the other Superficies, and so\nbeing restor'd to its pristine Constitution, became of the same Nature\nand Condition as at first before its Incidence on those Prisms; and\ntherefore, before its Incidence, was as much compounded of Rays\ndifferently refrangible, as afterwards.\n\n[Illustration: FIG. 22.]\n\n_Illustration._ In the twenty second Figure ABC and BCD are the two\nPrisms tied together in the form of a Parallelopiped, their Sides BC and\nCB being contiguous, and their Sides AB and CD parallel. And HJK is the\nthird Prism, by which the Sun's Light propagated through the hole F into\nthe dark Chamber, and there passing through those sides of the Prisms\nAB, BC, CB and CD, is refracted at O to the white Paper PT, falling\nthere partly upon P by a greater Refraction, partly upon T by a less\nRefraction, and partly upon R and other intermediate places by\nintermediate Refractions. By turning the Parallelopiped ACBD about its\nAxis, according to the order of the Letters A, C, D, B, at length when\nthe contiguous Planes BC and CB become sufficiently oblique to the Rays\nFM, which are incident upon them at M, there will vanish totally out of\nthe refracted Light OPT, first of all the most refracted Rays OP, (the\nrest OR and OT remaining as before) then the Rays OR and other\nintermediate ones, and lastly, the least refracted Rays OT. For when\nthe Plane BC becomes sufficiently oblique to the Rays incident upon it,\nthose Rays will begin to be totally reflected by it towards N; and first\nthe most refrangible Rays will be totally reflected (as was explained in\nthe preceding Experiment) and by Consequence must first disappear at P,\nand afterwards the rest as they are in order totally reflected to N,\nthey must disappear in the same order at R and T. So then the Rays which\nat O suffer the greatest Refraction, may be taken out of the Light MO\nwhilst the rest of the Rays remain in it, and therefore that Light MO is\ncompounded of Rays differently refrangible. And because the Planes AB\nand CD are parallel, and therefore by equal and contrary Refractions\ndestroy one anothers Effects, the incident Light FM must be of the same\nKind and Nature with the emergent Light MO, and therefore doth also\nconsist of Rays differently refrangible. These two Lights FM and MO,\nbefore the most refrangible Rays are separated out of the emergent Light\nMO, agree in Colour, and in all other Properties so far as my\nObservation reaches, and therefore are deservedly reputed of the same\nNature and Constitution, and by Consequence the one is compounded as\nwell as the other. But after the most refrangible Rays begin to be\ntotally reflected, and thereby separated out of the emergent Light MO,\nthat Light changes its Colour from white to a dilute and faint yellow, a\npretty good orange, a very full red successively, and then totally\nvanishes. For after the most refrangible Rays which paint the Paper at\nP with a purple Colour, are by a total Reflexion taken out of the beam\nof Light MO, the rest of the Colours which appear on the Paper at R and\nT being mix'd in the Light MO compound there a faint yellow, and after\nthe blue and part of the green which appear on the Paper between P and R\nare taken away, the rest which appear between R and T (that is the\nyellow, orange, red and a little green) being mixed in the beam MO\ncompound there an orange; and when all the Rays are by Reflexion taken\nout of the beam MO, except the least refrangible, which at T appear of a\nfull red, their Colour is the same in that beam MO as afterwards at T,\nthe Refraction of the Prism HJK serving only to separate the differently\nrefrangible Rays, without making any Alteration in their Colours, as\nshall be more fully proved hereafter. All which confirms as well the\nfirst Proposition as the second.\n\n_Scholium._ If this Experiment and the former be conjoined and made one\nby applying a fourth Prism VXY [in _Fig._ 22.] to refract the reflected\nbeam MN towards _tp_, the Conclusion will be clearer. For then the Light\nN_p_ which in the fourth Prism is more refracted, will become fuller and\nstronger when the Light OP, which in the third Prism HJK is more\nrefracted, vanishes at P; and afterwards when the less refracted Light\nOT vanishes at T, the less refracted Light N_t_ will become increased\nwhilst the more refracted Light at _p_ receives no farther increase. And\nas the trajected beam MO in vanishing is always of such a Colour as\nought to result from the mixture of the Colours which fall upon the\nPaper PT, so is the reflected beam MN always of such a Colour as ought\nto result from the mixture of the Colours which fall upon the Paper\n_pt_. For when the most refrangible Rays are by a total Reflexion taken\nout of the beam MO, and leave that beam of an orange Colour, the Excess\nof those Rays in the reflected Light, does not only make the violet,\nindigo and blue at _p_ more full, but also makes the beam MN change from\nthe yellowish Colour of the Sun's Light, to a pale white inclining to\nblue, and afterward recover its yellowish Colour again, so soon as all\nthe rest of the transmitted Light MOT is reflected.\n\nNow seeing that in all this variety of Experiments, whether the Trial be\nmade in Light reflected, and that either from natural Bodies, as in the\nfirst and second Experiment, or specular, as in the ninth; or in Light\nrefracted, and that either before the unequally refracted Rays are by\ndiverging separated from one another, and losing their whiteness which\nthey have altogether, appear severally of several Colours, as in the\nfifth Experiment; or after they are separated from one another, and\nappear colour'd as in the sixth, seventh, and eighth Experiments; or in\nLight trajected through parallel Superficies, destroying each others\nEffects, as in the tenth Experiment; there are always found Rays, which\nat equal Incidences on the same Medium suffer unequal Refractions, and\nthat without any splitting or dilating of single Rays, or contingence in\nthe inequality of the Refractions, as is proved in the fifth and sixth\nExperiments. And seeing the Rays which differ in Refrangibility may be\nparted and sorted from one another, and that either by Refraction as in\nthe third Experiment, or by Reflexion as in the tenth, and then the\nseveral sorts apart at equal Incidences suffer unequal Refractions, and\nthose sorts are more refracted than others after Separation, which were\nmore refracted before it, as in the sixth and following Experiments, and\nif the Sun's Light be trajected through three or more cross Prisms\nsuccessively, those Rays which in the first Prism are refracted more\nthan others, are in all the following Prisms refracted more than others\nin the same Rate and Proportion, as appears by the fifth Experiment;\nit's manifest that the Sun's Light is an heterogeneous Mixture of Rays,\nsome of which are constantly more refrangible than others, as was\nproposed.\n\n\n_PROP._ III. THEOR. III.\n\n_The Sun's Light consists of Rays differing in Reflexibility, and those\nRays are more reflexible than others which are more refrangible._\n\nThis is manifest by the ninth and tenth Experiments: For in the ninth\nExperiment, by turning the Prism about its Axis, until the Rays within\nit which in going out into the Air were refracted by its Base, became so\noblique to that Base, as to begin to be totally reflected thereby; those\nRays became first of all totally reflected, which before at equal\nIncidences with the rest had suffered the greatest Refraction. And the\nsame thing happens in the Reflexion made by the common Base of the two\nPrisms in the tenth Experiment.\n\n\n_PROP._ IV. PROB. I.\n\n_To separate from one another the heterogeneous Rays of compound Light._\n\n[Illustration: FIG. 23.]\n\nThe heterogeneous Rays are in some measure separated from one another by\nthe Refraction of the Prism in the third Experiment, and in the fifth\nExperiment, by taking away the Penumbra from the rectilinear sides of\nthe coloured Image, that Separation in those very rectilinear sides or\nstraight edges of the Image becomes perfect. But in all places between\nthose rectilinear edges, those innumerable Circles there described,\nwhich are severally illuminated by homogeneal Rays, by interfering with\none another, and being every where commix'd, do render the Light\nsufficiently compound. But if these Circles, whilst their Centers keep\ntheir Distances and Positions, could be made less in Diameter, their\ninterfering one with another, and by Consequence the Mixture of the\nheterogeneous Rays would be proportionally diminish'd. In the twenty\nthird Figure let AG, BH, CJ, DK, EL, FM be the Circles which so many\nsorts of Rays flowing from the same disque of the Sun, do in the third\nExperiment illuminate; of all which and innumerable other intermediate\nones lying in a continual Series between the two rectilinear and\nparallel edges of the Sun's oblong Image PT, that Image is compos'd, as\nwas explained in the fifth Experiment. And let _ag_, _bh_, _ci_, _dk_,\n_el_, _fm_ be so many less Circles lying in a like continual Series\nbetween two parallel right Lines _af_ and _gm_ with the same distances\nbetween their Centers, and illuminated by the same sorts of Rays, that\nis the Circle _ag_ with the same sort by which the corresponding Circle\nAG was illuminated, and the Circle _bh_ with the same sort by which the\ncorresponding Circle BH was illuminated, and the rest of the Circles\n_ci_, _dk_, _el_, _fm_ respectively, with the same sorts of Rays by\nwhich the several corresponding Circles CJ, DK, EL, FM were illuminated.\nIn the Figure PT composed of the greater Circles, three of those Circles\nAG, BH, CJ, are so expanded into one another, that the three sorts of\nRays by which those Circles are illuminated, together with other\ninnumerable sorts of intermediate Rays, are mixed at QR in the middle\nof the Circle BH. And the like Mixture happens throughout almost the\nwhole length of the Figure PT. But in the Figure _pt_ composed of the\nless Circles, the three less Circles _ag_, _bh_, _ci_, which answer to\nthose three greater, do not extend into one another; nor are there any\nwhere mingled so much as any two of the three sorts of Rays by which\nthose Circles are illuminated, and which in the Figure PT are all of\nthem intermingled at BH.\n\nNow he that shall thus consider it, will easily understand that the\nMixture is diminished in the same Proportion with the Diameters of the\nCircles. If the Diameters of the Circles whilst their Centers remain the\nsame, be made three times less than before, the Mixture will be also\nthree times less; if ten times less, the Mixture will be ten times less,\nand so of other Proportions. That is, the Mixture of the Rays in the\ngreater Figure PT will be to their Mixture in the less _pt_, as the\nLatitude of the greater Figure is to the Latitude of the less. For the\nLatitudes of these Figures are equal to the Diameters of their Circles.\nAnd hence it easily follows, that the Mixture of the Rays in the\nrefracted Spectrum _pt_ is to the Mixture of the Rays in the direct and\nimmediate Light of the Sun, as the breadth of that Spectrum is to the\ndifference between the length and breadth of the same Spectrum.\n\nSo then, if we would diminish the Mixture of the Rays, we are to\ndiminish the Diameters of the Circles. Now these would be diminished if\nthe Sun's Diameter to which they answer could be made less than it is,\nor (which comes to the same Purpose) if without Doors, at a great\ndistance from the Prism towards the Sun, some opake Body were placed,\nwith a round hole in the middle of it, to intercept all the Sun's Light,\nexcepting so much as coming from the middle of his Body could pass\nthrough that Hole to the Prism. For so the Circles AG, BH, and the rest,\nwould not any longer answer to the whole Disque of the Sun, but only to\nthat Part of it which could be seen from the Prism through that Hole,\nthat it is to the apparent Magnitude of that Hole view'd from the Prism.\nBut that these Circles may answer more distinctly to that Hole, a Lens\nis to be placed by the Prism to cast the Image of the Hole, (that is,\nevery one of the Circles AG, BH, &c.) distinctly upon the Paper at PT,\nafter such a manner, as by a Lens placed at a Window, the Species of\nObjects abroad are cast distinctly upon a Paper within the Room, and the\nrectilinear Sides of the oblong Solar Image in the fifth Experiment\nbecame distinct without any Penumbra. If this be done, it will not be\nnecessary to place that Hole very far off, no not beyond the Window. And\ntherefore instead of that Hole, I used the Hole in the Window-shut, as\nfollows.\n\n_Exper._ 11. In the Sun's Light let into my darken'd Chamber through a\nsmall round Hole in my Window-shut, at about ten or twelve Feet from the\nWindow, I placed a Lens, by which the Image of the Hole might be\ndistinctly cast upon a Sheet of white Paper, placed at the distance of\nsix, eight, ten, or twelve Feet from the Lens. For, according to the\ndifference of the Lenses I used various distances, which I think not\nworth the while to describe. Then immediately after the Lens I placed a\nPrism, by which the trajected Light might be refracted either upwards or\nsideways, and thereby the round Image, which the Lens alone did cast\nupon the Paper might be drawn out into a long one with Parallel Sides,\nas in the third Experiment. This oblong Image I let fall upon another\nPaper at about the same distance from the Prism as before, moving the\nPaper either towards the Prism or from it, until I found the just\ndistance where the Rectilinear Sides of the Image became most distinct.\nFor in this Case, the Circular Images of the Hole, which compose that\nImage after the same manner that the Circles _ag_, _bh_, _ci_, &c. do\nthe Figure _pt_ [in _Fig._ 23.] were terminated most distinctly without\nany Penumbra, and therefore extended into one another the least that\nthey could, and by consequence the Mixture of the heterogeneous Rays was\nnow the least of all. By this means I used to form an oblong Image (such\nas is _pt_) [in _Fig._ 23, and 24.] of Circular Images of the Hole,\n(such as are _ag_, _bh_, _ci_, &c.) and by using a greater or less Hole\nin the Window-shut, I made the Circular Images _ag_, _bh_, _ci_, &c. of\nwhich it was formed, to become greater or less at pleasure, and thereby\nthe Mixture of the Rays in the Image _pt_ to be as much, or as little as\nI desired.\n\n[Illustration: FIG. 24.]\n\n_Illustration._ In the twenty-fourth Figure, F represents the Circular\nHole in the Window-shut, MN the Lens, whereby the Image or Species of\nthat Hole is cast distinctly upon a Paper at J, ABC the Prism, whereby\nthe Rays are at their emerging out of the Lens refracted from J towards\nanother Paper at _pt_, and the round Image at J is turned into an oblong\nImage _pt_ falling on that other Paper. This Image _pt_ consists of\nCircles placed one after another in a Rectilinear Order, as was\nsufficiently explained in the fifth Experiment; and these Circles are\nequal to the Circle J, and consequently answer in magnitude to the Hole\nF; and therefore by diminishing that Hole they may be at pleasure\ndiminished, whilst their Centers remain in their Places. By this means I\nmade the Breadth of the Image _pt_ to be forty times, and sometimes\nsixty or seventy times less than its Length. As for instance, if the\nBreadth of the Hole F be one tenth of an Inch, and MF the distance of\nthe Lens from the Hole be 12 Feet; and if _p_B or _p_M the distance of\nthe Image _pt_ from the Prism or Lens be 10 Feet, and the refracting\nAngle of the Prism be 62 Degrees, the Breadth of the Image _pt_ will be\none twelfth of an Inch, and the Length about six Inches, and therefore\nthe Length to the Breadth as 72 to 1, and by consequence the Light of\nthis Image 71 times less compound than the Sun's direct Light. And Light\nthus far simple and homogeneal, is sufficient for trying all the\nExperiments in this Book about simple Light. For the Composition of\nheterogeneal Rays is in this Light so little, that it is scarce to be\ndiscovered and perceiv'd by Sense, except perhaps in the indigo and\nviolet. For these being dark Colours do easily suffer a sensible Allay\nby that little scattering Light which uses to be refracted irregularly\nby the Inequalities of the Prism.\n\nYet instead of the Circular Hole F, 'tis better to substitute an oblong\nHole shaped like a long Parallelogram with its Length parallel to the\nPrism ABC. For if this Hole be an Inch or two long, and but a tenth or\ntwentieth Part of an Inch broad, or narrower; the Light of the Image\n_pt_ will be as simple as before, or simpler, and the Image will become\nmuch broader, and therefore more fit to have Experiments try'd in its\nLight than before.\n\nInstead of this Parallelogram Hole may be substituted a triangular one\nof equal Sides, whose Base, for instance, is about the tenth Part of an\nInch, and its Height an Inch or more. For by this means, if the Axis of\nthe Prism be parallel to the Perpendicular of the Triangle, the Image\n_pt_ [in _Fig._ 25.] will now be form'd of equicrural Triangles _ag_,\n_bh_, _ci_, _dk_, _el_, _fm_, &c. and innumerable other intermediate\nones answering to the triangular Hole in Shape and Bigness, and lying\none after another in a continual Series between two Parallel Lines _af_\nand _gm_. These Triangles are a little intermingled at their Bases, but\nnot at their Vertices; and therefore the Light on the brighter Side _af_\nof the Image, where the Bases of the Triangles are, is a little\ncompounded, but on the darker Side _gm_ is altogether uncompounded, and\nin all Places between the Sides the Composition is proportional to the\ndistances of the Places from that obscurer Side _gm_. And having a\nSpectrum _pt_ of such a Composition, we may try Experiments either in\nits stronger and less simple Light near the Side _af_, or in its weaker\nand simpler Light near the other Side _gm_, as it shall seem most\nconvenient.\n\n[Illustration: FIG. 25.]\n\nBut in making Experiments of this kind, the Chamber ought to be made as\ndark as can be, lest any Foreign Light mingle it self with the Light of\nthe Spectrum _pt_, and render it compound; especially if we would try\nExperiments in the more simple Light next the Side _gm_ of the Spectrum;\nwhich being fainter, will have a less proportion to the Foreign Light;\nand so by the mixture of that Light be more troubled, and made more\ncompound. The Lens also ought to be good, such as may serve for optical\nUses, and the Prism ought to have a large Angle, suppose of 65 or 70\nDegrees, and to be well wrought, being made of Glass free from Bubbles\nand Veins, with its Sides not a little convex or concave, as usually\nhappens, but truly plane, and its Polish elaborate, as in working\nOptick-glasses, and not such as is usually wrought with Putty, whereby\nthe edges of the Sand-holes being worn away, there are left all over the\nGlass a numberless Company of very little convex polite Risings like\nWaves. The edges also of the Prism and Lens, so far as they may make any\nirregular Refraction, must be covered with a black Paper glewed on. And\nall the Light of the Sun's Beam let into the Chamber, which is useless\nand unprofitable to the Experiment, ought to be intercepted with black\nPaper, or other black Obstacles. For otherwise the useless Light being\nreflected every way in the Chamber, will mix with the oblong Spectrum,\nand help to disturb it. In trying these Things, so much diligence is not\naltogether necessary, but it will promote the Success of the\nExperiments, and by a very scrupulous Examiner of Things deserves to be\napply'd. It's difficult to get Glass Prisms fit for this Purpose, and\ntherefore I used sometimes prismatick Vessels made with pieces of broken\nLooking-glasses, and filled with Rain Water. And to increase the\nRefraction, I sometimes impregnated the Water strongly with _Saccharum\nSaturni_.\n\n\n_PROP._ V. THEOR. IV.\n\n_Homogeneal Light is refracted regularly without any Dilatation\nsplitting or shattering of the Rays, and the confused Vision of Objects\nseen through refracting Bodies by heterogeneal Light arises from the\ndifferent Refrangibility of several sorts of Rays._\n\nThe first Part of this Proposition has been already sufficiently proved\nin the fifth Experiment, and will farther appear by the Experiments\nwhich follow.\n\n_Exper._ 12. In the middle of a black Paper I made a round Hole about a\nfifth or sixth Part of an Inch in diameter. Upon this Paper I caused the\nSpectrum of homogeneal Light described in the former Proposition, so to\nfall, that some part of the Light might pass through the Hole of the\nPaper. This transmitted part of the Light I refracted with a Prism\nplaced behind the Paper, and letting this refracted Light fall\nperpendicularly upon a white Paper two or three Feet distant from the\nPrism, I found that the Spectrum formed on the Paper by this Light was\nnot oblong, as when 'tis made (in the third Experiment) by refracting\nthe Sun's compound Light, but was (so far as I could judge by my Eye)\nperfectly circular, the Length being no greater than the Breadth. Which\nshews, that this Light is refracted regularly without any Dilatation of\nthe Rays.\n\n_Exper._ 13. In the homogeneal Light I placed a Paper Circle of a\nquarter of an Inch in diameter, and in the Sun's unrefracted\nheterogeneal white Light I placed another Paper Circle of the same\nBigness. And going from the Papers to the distance of some Feet, I\nviewed both Circles through a Prism. The Circle illuminated by the Sun's\nheterogeneal Light appeared very oblong, as in the fourth Experiment,\nthe Length being many times greater than the Breadth; but the other\nCircle, illuminated with homogeneal Light, appeared circular and\ndistinctly defined, as when 'tis view'd with the naked Eye. Which proves\nthe whole Proposition.\n\n_Exper._ 14. In the homogeneal Light I placed Flies, and such-like\nminute Objects, and viewing them through a Prism, I saw their Parts as\ndistinctly defined, as if I had viewed them with the naked Eye. The same\nObjects placed in the Sun's unrefracted heterogeneal Light, which was\nwhite, I viewed also through a Prism, and saw them most confusedly\ndefined, so that I could not distinguish their smaller Parts from one\nanother. I placed also the Letters of a small print, one while in the\nhomogeneal Light, and then in the heterogeneal, and viewing them through\na Prism, they appeared in the latter Case so confused and indistinct,\nthat I could not read them; but in the former they appeared so distinct,\nthat I could read readily, and thought I saw them as distinct, as when I\nview'd them with my naked Eye. In both Cases I view'd the same Objects,\nthrough the same Prism at the same distance from me, and in the same\nSituation. There was no difference, but in the Light by which the\nObjects were illuminated, and which in one Case was simple, and in the\nother compound; and therefore, the distinct Vision in the former Case,\nand confused in the latter, could arise from nothing else than from that\ndifference of the Lights. Which proves the whole Proposition.\n\nAnd in these three Experiments it is farther very remarkable, that the\nColour of homogeneal Light was never changed by the Refraction.\n\n\n_PROP._ VI. THEOR. V.\n\n_The Sine of Incidence of every Ray considered apart, is to its Sine of\nRefraction in a given Ratio._\n\nThat every Ray consider'd apart, is constant to it self in some degree\nof Refrangibility, is sufficiently manifest out of what has been said.\nThose Rays, which in the first Refraction, are at equal Incidences most\nrefracted, are also in the following Refractions at equal Incidences\nmost refracted; and so of the least refrangible, and the rest which have\nany mean Degree of Refrangibility, as is manifest by the fifth, sixth,\nseventh, eighth, and ninth Experiments. And those which the first Time\nat like Incidences are equally refracted, are again at like Incidences\nequally and uniformly refracted, and that whether they be refracted\nbefore they be separated from one another, as in the fifth Experiment,\nor whether they be refracted apart, as in the twelfth, thirteenth and\nfourteenth Experiments. The Refraction therefore of every Ray apart is\nregular, and what Rule that Refraction observes we are now to shew.[E]\n\nThe late Writers in Opticks teach, that the Sines of Incidence are in a\ngiven Proportion to the Sines of Refraction, as was explained in the\nfifth Axiom, and some by Instruments fitted for measuring of\nRefractions, or otherwise experimentally examining this Proportion, do\nacquaint us that they have found it accurate. But whilst they, not\nunderstanding the different Refrangibility of several Rays, conceived\nthem all to be refracted according to one and the same Proportion, 'tis\nto be presumed that they adapted their Measures only to the middle of\nthe refracted Light; so that from their Measures we may conclude only\nthat the Rays which have a mean Degree of Refrangibility, that is, those\nwhich when separated from the rest appear green, are refracted according\nto a given Proportion of their Sines. And therefore we are now to shew,\nthat the like given Proportions obtain in all the rest. That it should\nbe so is very reasonable, Nature being ever conformable to her self; but\nan experimental Proof is desired. And such a Proof will be had, if we\ncan shew that the Sines of Refraction of Rays differently refrangible\nare one to another in a given Proportion when their Sines of Incidence\nare equal. For, if the Sines of Refraction of all the Rays are in given\nProportions to the Sine of Refractions of a Ray which has a mean Degree\nof Refrangibility, and this Sine is in a given Proportion to the equal\nSines of Incidence, those other Sines of Refraction will also be in\ngiven Proportions to the equal Sines of Incidence. Now, when the Sines\nof Incidence are equal, it will appear by the following Experiment, that\nthe Sines of Refraction are in a given Proportion to one another.\n\n[Illustration: FIG. 26.]\n\n_Exper._ 15. The Sun shining into a dark Chamber through a little round\nHole in the Window-shut, let S [in _Fig._ 26.] represent his round white\nImage painted on the opposite Wall by his direct Light, PT his oblong\ncoloured Image made by refracting that Light with a Prism placed at the\nWindow; and _pt_, or _2p 2t_, _3p 3t_, his oblong colour'd Image made by\nrefracting again the same Light sideways with a second Prism placed\nimmediately after the first in a cross Position to it, as was explained\nin the fifth Experiment; that is to say, _pt_ when the Refraction of the\nsecond Prism is small, _2p 2t_ when its Refraction is greater, and _3p\n3t_ when it is greatest. For such will be the diversity of the\nRefractions, if the refracting Angle of the second Prism be of various\nMagnitudes; suppose of fifteen or twenty Degrees to make the Image _pt_,\nof thirty or forty to make the Image _2p 2t_, and of sixty to make the\nImage _3p 3t_. But for want of solid Glass Prisms with Angles of\nconvenient Bignesses, there may be Vessels made of polished Plates of\nGlass cemented together in the form of Prisms and filled with Water.\nThese things being thus ordered, I observed that all the solar Images or\ncoloured Spectrums PT, _pt_, _2p 2t_, _3p 3t_ did very nearly converge\nto the place S on which the direct Light of the Sun fell and painted his\nwhite round Image when the Prisms were taken away. The Axis of the\nSpectrum PT, that is the Line drawn through the middle of it parallel to\nits rectilinear Sides, did when produced pass exactly through the middle\nof that white round Image S. And when the Refraction of the second Prism\nwas equal to the Refraction of the first, the refracting Angles of them\nboth being about 60 Degrees, the Axis of the Spectrum _3p 3t_ made by\nthat Refraction, did when produced pass also through the middle of the\nsame white round Image S. But when the Refraction of the second Prism\nwas less than that of the first, the produced Axes of the Spectrums _tp_\nor _2t 2p_ made by that Refraction did cut the produced Axis of the\nSpectrum TP in the points _m_ and _n_, a little beyond the Center of\nthat white round Image S. Whence the proportion of the Line 3_t_T to the\nLine 3_p_P was a little greater than the Proportion of 2_t_T or 2_p_P,\nand this Proportion a little greater than that of _t_T to _p_P. Now when\nthe Light of the Spectrum PT falls perpendicularly upon the Wall, those\nLines 3_t_T, 3_p_P, and 2_t_T, and 2_p_P, and _t_T, _p_P, are the\nTangents of the Refractions, and therefore by this Experiment the\nProportions of the Tangents of the Refractions are obtained, from whence\nthe Proportions of the Sines being derived, they come out equal, so far\nas by viewing the Spectrums, and using some mathematical Reasoning I\ncould estimate. For I did not make an accurate Computation. So then the\nProposition holds true in every Ray apart, so far as appears by\nExperiment. And that it is accurately true, may be demonstrated upon\nthis Supposition. _That Bodies refract Light by acting upon its Rays in\nLines perpendicular to their Surfaces._ But in order to this\nDemonstration, I must distinguish the Motion of every Ray into two\nMotions, the one perpendicular to the refracting Surface, the other\nparallel to it, and concerning the perpendicular Motion lay down the\nfollowing Proposition.\n\nIf any Motion or moving thing whatsoever be incident with any Velocity\non any broad and thin space terminated on both sides by two parallel\nPlanes, and in its Passage through that space be urged perpendicularly\ntowards the farther Plane by any force which at given distances from the\nPlane is of given Quantities; the perpendicular velocity of that Motion\nor Thing, at its emerging out of that space, shall be always equal to\nthe square Root of the sum of the square of the perpendicular velocity\nof that Motion or Thing at its Incidence on that space; and of the\nsquare of the perpendicular velocity which that Motion or Thing would\nhave at its Emergence, if at its Incidence its perpendicular velocity\nwas infinitely little.\n\nAnd the same Proposition holds true of any Motion or Thing\nperpendicularly retarded in its passage through that space, if instead\nof the sum of the two Squares you take their difference. The\nDemonstration Mathematicians will easily find out, and therefore I shall\nnot trouble the Reader with it.\n\nSuppose now that a Ray coming most obliquely in the Line MC [in _Fig._\n1.] be refracted at C by the Plane RS into the Line CN, and if it be\nrequired to find the Line CE, into which any other Ray AC shall be\nrefracted; let MC, AD, be the Sines of Incidence of the two Rays, and\nNG, EF, their Sines of Refraction, and let the equal Motions of the\nincident Rays be represented by the equal Lines MC and AC, and the\nMotion MC being considered as parallel to the refracting Plane, let the\nother Motion AC be distinguished into two Motions AD and DC, one of\nwhich AD is parallel, and the other DC perpendicular to the refracting\nSurface. In like manner, let the Motions of the emerging Rays be\ndistinguish'd into two, whereof the perpendicular ones are MC/NG × CG\nand AD/EF × CF. And if the force of the refracting Plane begins to act\nupon the Rays either in that Plane or at a certain distance from it on\nthe one side, and ends at a certain distance from it on the other side,\nand in all places between those two limits acts upon the Rays in Lines\nperpendicular to that refracting Plane, and the Actions upon the Rays at\nequal distances from the refracting Plane be equal, and at unequal ones\neither equal or unequal according to any rate whatever; that Motion of\nthe Ray which is parallel to the refracting Plane, will suffer no\nAlteration by that Force; and that Motion which is perpendicular to it\nwill be altered according to the rule of the foregoing Proposition. If\ntherefore for the perpendicular velocity of the emerging Ray CN you\nwrite MC/NG × CG as above, then the perpendicular velocity of any other\nemerging Ray CE which was AD/EF × CF, will be equal to the square Root\nof CD_q_ + (_MCq/NGq_ × CG_q_). And by squaring these Equals, and adding\nto them the Equals AD_q_ and MC_q_ - CD_q_, and dividing the Sums by the\nEquals CF_q_ + EF_q_ and CG_q_ + NG_q_, you will have _MCq/NGq_ equal to\n_ADq/EFq_. Whence AD, the Sine of Incidence, is to EF the Sine of\nRefraction, as MC to NG, that is, in a given _ratio_. And this\nDemonstration being general, without determining what Light is, or by\nwhat kind of Force it is refracted, or assuming any thing farther than\nthat the refracting Body acts upon the Rays in Lines perpendicular to\nits Surface; I take it to be a very convincing Argument of the full\ntruth of this Proposition.\n\nSo then, if the _ratio_ of the Sines of Incidence and Refraction of any\nsort of Rays be found in any one case, 'tis given in all cases; and this\nmay be readily found by the Method in the following Proposition.\n\n\n_PROP._ VII. THEOR. VI.\n\n_The Perfection of Telescopes is impeded by the different Refrangibility\nof the Rays of Light._\n\nThe Imperfection of Telescopes is vulgarly attributed to the spherical\nFigures of the Glasses, and therefore Mathematicians have propounded to\nfigure them by the conical Sections. To shew that they are mistaken, I\nhave inserted this Proposition; the truth of which will appear by the\nmeasure of the Refractions of the several sorts of Rays; and these\nmeasures I thus determine.\n\nIn the third Experiment of this first Part, where the refracting Angle\nof the Prism was 62-1/2 Degrees, the half of that Angle 31 deg. 15 min.\nis the Angle of Incidence of the Rays at their going out of the Glass\ninto the Air[F]; and the Sine of this Angle is 5188, the Radius being\n10000. When the Axis of this Prism was parallel to the Horizon, and the\nRefraction of the Rays at their Incidence on this Prism equal to that at\ntheir Emergence out of it, I observed with a Quadrant the Angle which\nthe mean refrangible Rays, (that is those which went to the middle of\nthe Sun's coloured Image) made with the Horizon, and by this Angle and\nthe Sun's altitude observed at the same time, I found the Angle which\nthe emergent Rays contained with the incident to be 44 deg. and 40 min.\nand the half of this Angle added to the Angle of Incidence 31 deg. 15\nmin. makes the Angle of Refraction, which is therefore 53 deg. 35 min.\nand its Sine 8047. These are the Sines of Incidence and Refraction of\nthe mean refrangible Rays, and their Proportion in round Numbers is 20\nto 31. This Glass was of a Colour inclining to green. The last of the\nPrisms mentioned in the third Experiment was of clear white Glass. Its\nrefracting Angle 63-1/2 Degrees. The Angle which the emergent Rays\ncontained, with the incident 45 deg. 50 min. The Sine of half the first\nAngle 5262. The Sine of half the Sum of the Angles 8157. And their\nProportion in round Numbers 20 to 31, as before.\n\nFrom the Length of the Image, which was about 9-3/4 or 10 Inches,\nsubduct its Breadth, which was 2-1/8 Inches, and the Remainder 7-3/4\nInches would be the Length of the Image were the Sun but a Point, and\ntherefore subtends the Angle which the most and least refrangible Rays,\nwhen incident on the Prism in the same Lines, do contain with one\nanother after their Emergence. Whence this Angle is 2 deg. 0´. 7´´. For\nthe distance between the Image and the Prism where this Angle is made,\nwas 18-1/2 Feet, and at that distance the Chord 7-3/4 Inches subtends an\nAngle of 2 deg. 0´. 7´´. Now half this Angle is the Angle which these\nemergent Rays contain with the emergent mean refrangible Rays, and a\nquarter thereof, that is 30´. 2´´. may be accounted the Angle which they\nwould contain with the same emergent mean refrangible Rays, were they\nco-incident to them within the Glass, and suffered no other Refraction\nthan that at their Emergence. For, if two equal Refractions, the one at\nthe Incidence of the Rays on the Prism, the other at their Emergence,\nmake half the Angle 2 deg. 0´. 7´´. then one of those Refractions will\nmake about a quarter of that Angle, and this quarter added to, and\nsubducted from the Angle of Refraction of the mean refrangible Rays,\nwhich was 53 deg. 35´, gives the Angles of Refraction of the most and\nleast refrangible Rays 54 deg. 5´ 2´´, and 53 deg. 4´ 58´´, whose Sines\nare 8099 and 7995, the common Angle of Incidence being 31 deg. 15´, and\nits Sine 5188; and these Sines in the least round Numbers are in\nproportion to one another, as 78 and 77 to 50.\n\nNow, if you subduct the common Sine of Incidence 50 from the Sines of\nRefraction 77 and 78, the Remainders 27 and 28 shew, that in small\nRefractions the Refraction of the least refrangible Rays is to the\nRefraction of the most refrangible ones, as 27 to 28 very nearly, and\nthat the difference of the Refractions of the least refrangible and most\nrefrangible Rays is about the 27-1/2th Part of the whole Refraction of\nthe mean refrangible Rays.\n\nWhence they that are skilled in Opticks will easily understand,[G] that\nthe Breadth of the least circular Space, into which Object-glasses of\nTelescopes can collect all sorts of Parallel Rays, is about the 27-1/2th\nPart of half the Aperture of the Glass, or 55th Part of the whole\nAperture; and that the Focus of the most refrangible Rays is nearer to\nthe Object-glass than the Focus of the least refrangible ones, by about\nthe 27-1/2th Part of the distance between the Object-glass and the Focus\nof the mean refrangible ones.\n\nAnd if Rays of all sorts, flowing from any one lucid Point in the Axis\nof any convex Lens, be made by the Refraction of the Lens to converge to\nPoints not too remote from the Lens, the Focus of the most refrangible\nRays shall be nearer to the Lens than the Focus of the least refrangible\nones, by a distance which is to the 27-1/2th Part of the distance of the\nFocus of the mean refrangible Rays from the Lens, as the distance\nbetween that Focus and the lucid Point, from whence the Rays flow, is to\nthe distance between that lucid Point and the Lens very nearly.\n\nNow to examine whether the Difference between the Refractions, which the\nmost refrangible and the least refrangible Rays flowing from the same\nPoint suffer in the Object-glasses of Telescopes and such-like Glasses,\nbe so great as is here described, I contrived the following Experiment.\n\n_Exper._ 16. The Lens which I used in the second and eighth Experiments,\nbeing placed six Feet and an Inch distant from any Object, collected the\nSpecies of that Object by the mean refrangible Rays at the distance of\nsix Feet and an Inch from the Lens on the other side. And therefore by\nthe foregoing Rule, it ought to collect the Species of that Object by\nthe least refrangible Rays at the distance of six Feet and 3-2/3 Inches\nfrom the Lens, and by the most refrangible ones at the distance of five\nFeet and 10-1/3 Inches from it: So that between the two Places, where\nthese least and most refrangible Rays collect the Species, there may be\nthe distance of about 5-1/3 Inches. For by that Rule, as six Feet and an\nInch (the distance of the Lens from the lucid Object) is to twelve Feet\nand two Inches (the distance of the lucid Object from the Focus of the\nmean refrangible Rays) that is, as One is to Two; so is the 27-1/2th\nPart of six Feet and an Inch (the distance between the Lens and the same\nFocus) to the distance between the Focus of the most refrangible Rays\nand the Focus of the least refrangible ones, which is therefore 5-17/55\nInches, that is very nearly 5-1/3 Inches. Now to know whether this\nMeasure was true, I repeated the second and eighth Experiment with\ncoloured Light, which was less compounded than that I there made use of:\nFor I now separated the heterogeneous Rays from one another by the\nMethod I described in the eleventh Experiment, so as to make a coloured\nSpectrum about twelve or fifteen Times longer than broad. This Spectrum\nI cast on a printed Book, and placing the above-mentioned Lens at the\ndistance of six Feet and an Inch from this Spectrum to collect the\nSpecies of the illuminated Letters at the same distance on the other\nside, I found that the Species of the Letters illuminated with blue were\nnearer to the Lens than those illuminated with deep red by about three\nInches, or three and a quarter; but the Species of the Letters\nilluminated with indigo and violet appeared so confused and indistinct,\nthat I could not read them: Whereupon viewing the Prism, I found it was\nfull of Veins running from one end of the Glass to the other; so that\nthe Refraction could not be regular. I took another Prism therefore\nwhich was free from Veins, and instead of the Letters I used two or\nthree Parallel black Lines a little broader than the Strokes of the\nLetters, and casting the Colours upon these Lines in such manner, that\nthe Lines ran along the Colours from one end of the Spectrum to the\nother, I found that the Focus where the indigo, or confine of this\nColour and violet cast the Species of the black Lines most distinctly,\nto be about four Inches, or 4-1/4 nearer to the Lens than the Focus,\nwhere the deepest red cast the Species of the same black Lines most\ndistinctly. The violet was so faint and dark, that I could not discern\nthe Species of the Lines distinctly by that Colour; and therefore\nconsidering that the Prism was made of a dark coloured Glass inclining\nto green, I took another Prism of clear white Glass; but the Spectrum of\nColours which this Prism made had long white Streams of faint Light\nshooting out from both ends of the Colours, which made me conclude that\nsomething was amiss; and viewing the Prism, I found two or three little\nBubbles in the Glass, which refracted the Light irregularly. Wherefore I\ncovered that Part of the Glass with black Paper, and letting the Light\npass through another Part of it which was free from such Bubbles, the\nSpectrum of Colours became free from those irregular Streams of Light,\nand was now such as I desired. But still I found the violet so dark and\nfaint, that I could scarce see the Species of the Lines by the violet,\nand not at all by the deepest Part of it, which was next the end of the\nSpectrum. I suspected therefore, that this faint and dark Colour might\nbe allayed by that scattering Light which was refracted, and reflected\nirregularly, partly by some very small Bubbles in the Glasses, and\npartly by the Inequalities of their Polish; which Light, tho' it was but\nlittle, yet it being of a white Colour, might suffice to affect the\nSense so strongly as to disturb the Phænomena of that weak and dark\nColour the violet, and therefore I tried, as in the 12th, 13th, and 14th\nExperiments, whether the Light of this Colour did not consist of a\nsensible Mixture of heterogeneous Rays, but found it did not. Nor did\nthe Refractions cause any other sensible Colour than violet to emerge\nout of this Light, as they would have done out of white Light, and by\nconsequence out of this violet Light had it been sensibly compounded\nwith white Light. And therefore I concluded, that the reason why I could\nnot see the Species of the Lines distinctly by this Colour, was only\nthe Darkness of this Colour, and Thinness of its Light, and its distance\nfrom the Axis of the Lens; I divided therefore those Parallel black\nLines into equal Parts, by which I might readily know the distances of\nthe Colours in the Spectrum from one another, and noted the distances of\nthe Lens from the Foci of such Colours, as cast the Species of the Lines\ndistinctly, and then considered whether the difference of those\ndistances bear such proportion to 5-1/3 Inches, the greatest Difference\nof the distances, which the Foci of the deepest red and violet ought to\nhave from the Lens, as the distance of the observed Colours from one\nanother in the Spectrum bear to the greatest distance of the deepest red\nand violet measured in the Rectilinear Sides of the Spectrum, that is,\nto the Length of those Sides, or Excess of the Length of the Spectrum\nabove its Breadth. And my Observations were as follows.\n\nWhen I observed and compared the deepest sensible red, and the Colour in\nthe Confine of green and blue, which at the Rectilinear Sides of the\nSpectrum was distant from it half the Length of those Sides, the Focus\nwhere the Confine of green and blue cast the Species of the Lines\ndistinctly on the Paper, was nearer to the Lens than the Focus, where\nthe red cast those Lines distinctly on it by about 2-1/2 or 2-3/4\nInches. For sometimes the Measures were a little greater, sometimes a\nlittle less, but seldom varied from one another above 1/3 of an Inch.\nFor it was very difficult to define the Places of the Foci, without some\nlittle Errors. Now, if the Colours distant half the Length of the\nImage, (measured at its Rectilinear Sides) give 2-1/2 or 2-3/4\nDifference of the distances of their Foci from the Lens, then the\nColours distant the whole Length ought to give 5 or 5-1/2 Inches\ndifference of those distances.\n\nBut here it's to be noted, that I could not see the red to the full end\nof the Spectrum, but only to the Center of the Semicircle which bounded\nthat end, or a little farther; and therefore I compared this red not\nwith that Colour which was exactly in the middle of the Spectrum, or\nConfine of green and blue, but with that which verged a little more to\nthe blue than to the green: And as I reckoned the whole Length of the\nColours not to be the whole Length of the Spectrum, but the Length of\nits Rectilinear Sides, so compleating the semicircular Ends into\nCircles, when either of the observed Colours fell within those Circles,\nI measured the distance of that Colour from the semicircular End of the\nSpectrum, and subducting half this distance from the measured distance\nof the two Colours, I took the Remainder for their corrected distance;\nand in these Observations set down this corrected distance for the\ndifference of the distances of their Foci from the Lens. For, as the\nLength of the Rectilinear Sides of the Spectrum would be the whole\nLength of all the Colours, were the Circles of which (as we shewed) that\nSpectrum consists contracted and reduced to Physical Points, so in that\nCase this corrected distance would be the real distance of the two\nobserved Colours.\n\nWhen therefore I farther observed the deepest sensible red, and that\nblue whose corrected distance from it was 7/12 Parts of the Length of\nthe Rectilinear Sides of the Spectrum, the difference of the distances\nof their Foci from the Lens was about 3-1/4 Inches, and as 7 to 12, so\nis 3-1/4 to 5-4/7.\n\nWhen I observed the deepest sensible red, and that indigo whose\ncorrected distance was 8/12 or 2/3 of the Length of the Rectilinear\nSides of the Spectrum, the difference of the distances of their Foci\nfrom the Lens, was about 3-2/3 Inches, and as 2 to 3, so is 3-2/3 to\n5-1/2.\n\nWhen I observed the deepest sensible red, and that deep indigo whose\ncorrected distance from one another was 9/12 or 3/4 of the Length of the\nRectilinear Sides of the Spectrum, the difference of the distances of\ntheir Foci from the Lens was about 4 Inches; and as 3 to 4, so is 4 to\n5-1/3.\n\nWhen I observed the deepest sensible red, and that Part of the violet\nnext the indigo, whose corrected distance from the red was 10/12 or 5/6\nof the Length of the Rectilinear Sides of the Spectrum, the difference\nof the distances of their Foci from the Lens was about 4-1/2 Inches, and\nas 5 to 6, so is 4-1/2 to 5-2/5. For sometimes, when the Lens was\nadvantageously placed, so that its Axis respected the blue, and all\nThings else were well ordered, and the Sun shone clear, and I held my\nEye very near to the Paper on which the Lens cast the Species of the\nLines, I could see pretty distinctly the Species of those Lines by that\nPart of the violet which was next the indigo; and sometimes I could see\nthem by above half the violet, For in making these Experiments I had\nobserved, that the Species of those Colours only appear distinct, which\nwere in or near the Axis of the Lens: So that if the blue or indigo were\nin the Axis, I could see their Species distinctly; and then the red\nappeared much less distinct than before. Wherefore I contrived to make\nthe Spectrum of Colours shorter than before, so that both its Ends might\nbe nearer to the Axis of the Lens. And now its Length was about 2-1/2\nInches, and Breadth about 1/5 or 1/6 of an Inch. Also instead of the\nblack Lines on which the Spectrum was cast, I made one black Line\nbroader than those, that I might see its Species more easily; and this\nLine I divided by short cross Lines into equal Parts, for measuring the\ndistances of the observed Colours. And now I could sometimes see the\nSpecies of this Line with its Divisions almost as far as the Center of\nthe semicircular violet End of the Spectrum, and made these farther\nObservations.\n\nWhen I observed the deepest sensible red, and that Part of the violet,\nwhose corrected distance from it was about 8/9 Parts of the Rectilinear\nSides of the Spectrum, the Difference of the distances of the Foci of\nthose Colours from the Lens, was one time 4-2/3, another time 4-3/4,\nanother time 4-7/8 Inches; and as 8 to 9, so are 4-2/3, 4-3/4, 4-7/8, to\n5-1/4, 5-11/32, 5-31/64 respectively.\n\nWhen I observed the deepest sensible red, and deepest sensible violet,\n(the corrected distance of which Colours, when all Things were ordered\nto the best Advantage, and the Sun shone very clear, was about 11/12 or\n15/16 Parts of the Length of the Rectilinear Sides of the coloured\nSpectrum) I found the Difference of the distances of their Foci from the\nLens sometimes 4-3/4 sometimes 5-1/4, and for the most part 5 Inches or\nthereabouts; and as 11 to 12, or 15 to 16, so is five Inches to 5-2/2 or\n5-1/3 Inches.\n\nAnd by this Progression of Experiments I satisfied my self, that had the\nLight at the very Ends of the Spectrum been strong enough to make the\nSpecies of the black Lines appear plainly on the Paper, the Focus of the\ndeepest violet would have been found nearer to the Lens, than the Focus\nof the deepest red, by about 5-1/3 Inches at least. And this is a\nfarther Evidence, that the Sines of Incidence and Refraction of the\nseveral sorts of Rays, hold the same Proportion to one another in the\nsmallest Refractions which they do in the greatest.\n\nMy Progress in making this nice and troublesome Experiment I have set\ndown more at large, that they that shall try it after me may be aware of\nthe Circumspection requisite to make it succeed well. And if they cannot\nmake it succeed so well as I did, they may notwithstanding collect by\nthe Proportion of the distance of the Colours of the Spectrum, to the\nDifference of the distances of their Foci from the Lens, what would be\nthe Success in the more distant Colours by a better trial. And yet, if\nthey use a broader Lens than I did, and fix it to a long strait Staff,\nby means of which it may be readily and truly directed to the Colour\nwhose Focus is desired, I question not but the Experiment will succeed\nbetter with them than it did with me. For I directed the Axis as nearly\nas I could to the middle of the Colours, and then the faint Ends of the\nSpectrum being remote from the Axis, cast their Species less distinctly\non the Paper than they would have done, had the Axis been successively\ndirected to them.\n\nNow by what has been said, it's certain that the Rays which differ in\nRefrangibility do not converge to the same Focus; but if they flow from\na lucid Point, as far from the Lens on one side as their Foci are on the\nother, the Focus of the most refrangible Rays shall be nearer to the\nLens than that of the least refrangible, by above the fourteenth Part of\nthe whole distance; and if they flow from a lucid Point, so very remote\nfrom the Lens, that before their Incidence they may be accounted\nparallel, the Focus of the most refrangible Rays shall be nearer to the\nLens than the Focus of the least refrangible, by about the 27th or 28th\nPart of their whole distance from it. And the Diameter of the Circle in\nthe middle Space between those two Foci which they illuminate, when they\nfall there on any Plane, perpendicular to the Axis (which Circle is the\nleast into which they can all be gathered) is about the 55th Part of the\nDiameter of the Aperture of the Glass. So that 'tis a wonder, that\nTelescopes represent Objects so distinct as they do. But were all the\nRays of Light equally refrangible, the Error arising only from the\nSphericalness of the Figures of Glasses would be many hundred times\nless. For, if the Object-glass of a Telescope be Plano-convex, and the\nPlane side be turned towards the Object, and the Diameter of the\nSphere, whereof this Glass is a Segment, be called D, and the\nSemi-diameter of the Aperture of the Glass be called S, and the Sine of\nIncidence out of Glass into Air, be to the Sine of Refraction as I to R;\nthe Rays which come parallel to the Axis of the Glass, shall in the\nPlace where the Image of the Object is most distinctly made, be\nscattered all over a little Circle, whose Diameter is _(Rq/Iq) × (S\ncub./D quad.)_ very nearly,[H] as I gather by computing the Errors of\nthe Rays by the Method of infinite Series, and rejecting the Terms,\nwhose Quantities are inconsiderable. As for instance, if the Sine of\nIncidence I, be to the Sine of Refraction R, as 20 to 31, and if D the\nDiameter of the Sphere, to which the Convex-side of the Glass is ground,\nbe 100 Feet or 1200 Inches, and S the Semi-diameter of the Aperture be\ntwo Inches, the Diameter of the little Circle, (that is (_Rq × S\ncub.)/(Iq × D quad._)) will be (31 × 31 × 8)/(20 × 20 × 1200 × 1200) (or\n961/72000000) Parts of an Inch. But the Diameter of the little Circle,\nthrough which these Rays are scattered by unequal Refrangibility, will\nbe about the 55th Part of the Aperture of the Object-glass, which here\nis four Inches. And therefore, the Error arising from the Spherical\nFigure of the Glass, is to the Error arising from the different\nRefrangibility of the Rays, as 961/72000000 to 4/55, that is as 1 to\n5449; and therefore being in comparison so very little, deserves not to\nbe considered.\n\n[Illustration: FIG. 27.]\n\nBut you will say, if the Errors caused by the different Refrangibility\nbe so very great, how comes it to pass, that Objects appear through\nTelescopes so distinct as they do? I answer, 'tis because the erring\nRays are not scattered uniformly over all that Circular Space, but\ncollected infinitely more densely in the Center than in any other Part\nof the Circle, and in the Way from the Center to the Circumference, grow\ncontinually rarer and rarer, so as at the Circumference to become\ninfinitely rare; and by reason of their Rarity are not strong enough to\nbe visible, unless in the Center and very near it. Let ADE [in _Fig._\n27.] represent one of those Circles described with the Center C, and\nSemi-diameter AC, and let BFG be a smaller Circle concentrick to the\nformer, cutting with its Circumference the Diameter AC in B, and bisect\nAC in N; and by my reckoning, the Density of the Light in any Place B,\nwill be to its Density in N, as AB to BC; and the whole Light within the\nlesser Circle BFG, will be to the whole Light within the greater AED, as\nthe Excess of the Square of AC above the Square of AB, is to the Square\nof AC. As if BC be the fifth Part of AC, the Light will be four times\ndenser in B than in N, and the whole Light within the less Circle, will\nbe to the whole Light within the greater, as nine to twenty-five. Whence\nit's evident, that the Light within the less Circle, must strike the\nSense much more strongly, than that faint and dilated Light round about\nbetween it and the Circumference of the greater.\n\nBut it's farther to be noted, that the most luminous of the Prismatick\nColours are the yellow and orange. These affect the Senses more strongly\nthan all the rest together, and next to these in strength are the red\nand green. The blue compared with these is a faint and dark Colour, and\nthe indigo and violet are much darker and fainter, so that these\ncompared with the stronger Colours are little to be regarded. The Images\nof Objects are therefore to be placed, not in the Focus of the mean\nrefrangible Rays, which are in the Confine of green and blue, but in the\nFocus of those Rays which are in the middle of the orange and yellow;\nthere where the Colour is most luminous and fulgent, that is in the\nbrightest yellow, that yellow which inclines more to orange than to\ngreen. And by the Refraction of these Rays (whose Sines of Incidence and\nRefraction in Glass are as 17 and 11) the Refraction of Glass and\nCrystal for Optical Uses is to be measured. Let us therefore place the\nImage of the Object in the Focus of these Rays, and all the yellow and\norange will fall within a Circle, whose Diameter is about the 250th\nPart of the Diameter of the Aperture of the Glass. And if you add the\nbrighter half of the red, (that half which is next the orange) and the\nbrighter half of the green, (that half which is next the yellow) about\nthree fifth Parts of the Light of these two Colours will fall within the\nsame Circle, and two fifth Parts will fall without it round about; and\nthat which falls without will be spread through almost as much more\nspace as that which falls within, and so in the gross be almost three\ntimes rarer. Of the other half of the red and green, (that is of the\ndeep dark red and willow green) about one quarter will fall within this\nCircle, and three quarters without, and that which falls without will be\nspread through about four or five times more space than that which falls\nwithin; and so in the gross be rarer, and if compared with the whole\nLight within it, will be about 25 times rarer than all that taken in the\ngross; or rather more than 30 or 40 times rarer, because the deep red in\nthe end of the Spectrum of Colours made by a Prism is very thin and\nrare, and the willow green is something rarer than the orange and\nyellow. The Light of these Colours therefore being so very much rarer\nthan that within the Circle, will scarce affect the Sense, especially\nsince the deep red and willow green of this Light, are much darker\nColours than the rest. And for the same reason the blue and violet being\nmuch darker Colours than these, and much more rarified, may be\nneglected. For the dense and bright Light of the Circle, will obscure\nthe rare and weak Light of these dark Colours round about it, and\nrender them almost insensible. The sensible Image of a lucid Point is\ntherefore scarce broader than a Circle, whose Diameter is the 250th Part\nof the Diameter of the Aperture of the Object-glass of a good Telescope,\nor not much broader, if you except a faint and dark misty Light round\nabout it, which a Spectator will scarce regard. And therefore in a\nTelescope, whose Aperture is four Inches, and Length an hundred Feet, it\nexceeds not 2´´ 45´´´, or 3´´. And in a Telescope whose Aperture is two\nInches, and Length 20 or 30 Feet, it may be 5´´ or 6´´, and scarce\nabove. And this answers well to Experience: For some Astronomers have\nfound the Diameters of the fix'd Stars, in Telescopes of between 20 and\n60 Feet in length, to be about 5´´ or 6´´, or at most 8´´ or 10´´ in\ndiameter. But if the Eye-Glass be tincted faintly with the Smoak of a\nLamp or Torch, to obscure the Light of the Star, the fainter Light in\nthe Circumference of the Star ceases to be visible, and the Star (if the\nGlass be sufficiently soiled with Smoak) appears something more like a\nmathematical Point. And for the same Reason, the enormous Part of the\nLight in the Circumference of every lucid Point ought to be less\ndiscernible in shorter Telescopes than in longer, because the shorter\ntransmit less Light to the Eye.\n\nNow, that the fix'd Stars, by reason of their immense Distance, appear\nlike Points, unless so far as their Light is dilated by Refraction, may\nappear from hence; that when the Moon passes over them and eclipses\nthem, their Light vanishes, not gradually like that of the Planets, but\nall at once; and in the end of the Eclipse it returns into Sight all at\nonce, or certainly in less time than the second of a Minute; the\nRefraction of the Moon's Atmosphere a little protracting the time in\nwhich the Light of the Star first vanishes, and afterwards returns into\nSight.\n\nNow, if we suppose the sensible Image of a lucid Point, to be even 250\ntimes narrower than the Aperture of the Glass; yet this Image would be\nstill much greater than if it were only from the spherical Figure of the\nGlass. For were it not for the different Refrangibility of the Rays, its\nbreadth in an 100 Foot Telescope whose aperture is 4 Inches, would be\nbut 961/72000000 parts of an Inch, as is manifest by the foregoing\nComputation. And therefore in this case the greatest Errors arising from\nthe spherical Figure of the Glass, would be to the greatest sensible\nErrors arising from the different Refrangibility of the Rays as\n961/72000000 to 4/250 at most, that is only as 1 to 1200. And this\nsufficiently shews that it is not the spherical Figures of Glasses, but\nthe different Refrangibility of the Rays which hinders the perfection of\nTelescopes.\n\nThere is another Argument by which it may appear that the different\nRefrangibility of Rays, is the true cause of the imperfection of\nTelescopes. For the Errors of the Rays arising from the spherical\nFigures of Object-glasses, are as the Cubes of the Apertures of the\nObject Glasses; and thence to make Telescopes of various Lengths magnify\nwith equal distinctness, the Apertures of the Object-glasses, and the\nCharges or magnifying Powers ought to be as the Cubes of the square\nRoots of their lengths; which doth not answer to Experience. But the\nErrors of the Rays arising from the different Refrangibility, are as the\nApertures of the Object-glasses; and thence to make Telescopes of\nvarious lengths, magnify with equal distinctness, their Apertures and\nCharges ought to be as the square Roots of their lengths; and this\nanswers to Experience, as is well known. For Instance, a Telescope of 64\nFeet in length, with an Aperture of 2-2/3 Inches, magnifies about 120\ntimes, with as much distinctness as one of a Foot in length, with 1/3 of\nan Inch aperture, magnifies 15 times.\n\n[Illustration: FIG. 28.]\n\nNow were it not for this different Refrangibility of Rays, Telescopes\nmight be brought to a greater perfection than we have yet describ'd, by\ncomposing the Object-glass of two Glasses with Water between them. Let\nADFC [in _Fig._ 28.] represent the Object-glass composed of two Glasses\nABED and BEFC, alike convex on the outsides AGD and CHF, and alike\nconcave on the insides BME, BNE, with Water in the concavity BMEN. Let\nthe Sine of Incidence out of Glass into Air be as I to R, and out of\nWater into Air, as K to R, and by consequence out of Glass into Water,\nas I to K: and let the Diameter of the Sphere to which the convex sides\nAGD and CHF are ground be D, and the Diameter of the Sphere to which the\nconcave sides BME and BNE, are ground be to D, as the Cube Root of\nKK--KI to the Cube Root of RK--RI: and the Refractions on the concave\nsides of the Glasses, will very much correct the Errors of the\nRefractions on the convex sides, so far as they arise from the\nsphericalness of the Figure. And by this means might Telescopes be\nbrought to sufficient perfection, were it not for the different\nRefrangibility of several sorts of Rays. But by reason of this different\nRefrangibility, I do not yet see any other means of improving Telescopes\nby Refractions alone, than that of increasing their lengths, for which\nend the late Contrivance of _Hugenius_ seems well accommodated. For very\nlong Tubes are cumbersome, and scarce to be readily managed, and by\nreason of their length are very apt to bend, and shake by bending, so as\nto cause a continual trembling in the Objects, whereby it becomes\ndifficult to see them distinctly: whereas by his Contrivance the Glasses\nare readily manageable, and the Object-glass being fix'd upon a strong\nupright Pole becomes more steady.\n\nSeeing therefore the Improvement of Telescopes of given lengths by\nRefractions is desperate; I contrived heretofore a Perspective by\nReflexion, using instead of an Object-glass a concave Metal. The\ndiameter of the Sphere to which the Metal was ground concave was about\n25 _English_ Inches, and by consequence the length of the Instrument\nabout six Inches and a quarter. The Eye-glass was Plano-convex, and the\ndiameter of the Sphere to which the convex side was ground was about 1/5\nof an Inch, or a little less, and by consequence it magnified between 30\nand 40 times. By another way of measuring I found that it magnified\nabout 35 times. The concave Metal bore an Aperture of an Inch and a\nthird part; but the Aperture was limited not by an opake Circle,\ncovering the Limb of the Metal round about, but by an opake Circle\nplaced between the Eyeglass and the Eye, and perforated in the middle\nwith a little round hole for the Rays to pass through to the Eye. For\nthis Circle by being placed here, stopp'd much of the erroneous Light,\nwhich otherwise would have disturbed the Vision. By comparing it with a\npretty good Perspective of four Feet in length, made with a concave\nEye-glass, I could read at a greater distance with my own Instrument\nthan with the Glass. Yet Objects appeared much darker in it than in the\nGlass, and that partly because more Light was lost by Reflexion in the\nMetal, than by Refraction in the Glass, and partly because my Instrument\nwas overcharged. Had it magnified but 30 or 25 times, it would have made\nthe Object appear more brisk and pleasant. Two of these I made about 16\nYears ago, and have one of them still by me, by which I can prove the\ntruth of what I write. Yet it is not so good as at the first. For the\nconcave has been divers times tarnished and cleared again, by rubbing\nit with very soft Leather. When I made these an Artist in _London_\nundertook to imitate it; but using another way of polishing them than I\ndid, he fell much short of what I had attained to, as I afterwards\nunderstood by discoursing the Under-workman he had employed. The Polish\nI used was in this manner. I had two round Copper Plates, each six\nInches in Diameter, the one convex, the other concave, ground very true\nto one another. On the convex I ground the Object-Metal or Concave which\nwas to be polish'd, 'till it had taken the Figure of the Convex and was\nready for a Polish. Then I pitched over the convex very thinly, by\ndropping melted Pitch upon it, and warming it to keep the Pitch soft,\nwhilst I ground it with the concave Copper wetted to make it spread\neavenly all over the convex. Thus by working it well I made it as thin\nas a Groat, and after the convex was cold I ground it again to give it\nas true a Figure as I could. Then I took Putty which I had made very\nfine by washing it from all its grosser Particles, and laying a little\nof this upon the Pitch, I ground it upon the Pitch with the concave\nCopper, till it had done making a Noise; and then upon the Pitch I\nground the Object-Metal with a brisk motion, for about two or three\nMinutes of time, leaning hard upon it. Then I put fresh Putty upon the\nPitch, and ground it again till it had done making a noise, and\nafterwards ground the Object-Metal upon it as before. And this Work I\nrepeated till the Metal was polished, grinding it the last time with all\nmy strength for a good while together, and frequently breathing upon\nthe Pitch, to keep it moist without laying on any more fresh Putty. The\nObject-Metal was two Inches broad, and about one third part of an Inch\nthick, to keep it from bending. I had two of these Metals, and when I\nhad polished them both, I tried which was best, and ground the other\nagain, to see if I could make it better than that which I kept. And thus\nby many Trials I learn'd the way of polishing, till I made those two\nreflecting Perspectives I spake of above. For this Art of polishing will\nbe better learn'd by repeated Practice than by my Description. Before I\nground the Object-Metal on the Pitch, I always ground the Putty on it\nwith the concave Copper, till it had done making a noise, because if the\nParticles of the Putty were not by this means made to stick fast in the\nPitch, they would by rolling up and down grate and fret the Object-Metal\nand fill it full of little holes.\n\nBut because Metal is more difficult to polish than Glass, and is\nafterwards very apt to be spoiled by tarnishing, and reflects not so\nmuch Light as Glass quick-silver'd over does: I would propound to use\ninstead of the Metal, a Glass ground concave on the foreside, and as\nmuch convex on the backside, and quick-silver'd over on the convex side.\nThe Glass must be every where of the same thickness exactly. Otherwise\nit will make Objects look colour'd and indistinct. By such a Glass I\ntried about five or six Years ago to make a reflecting Telescope of four\nFeet in length to magnify about 150 times, and I satisfied my self that\nthere wants nothing but a good Artist to bring the Design to\nperfection. For the Glass being wrought by one of our _London_ Artists\nafter such a manner as they grind Glasses for Telescopes, though it\nseemed as well wrought as the Object-glasses use to be, yet when it was\nquick-silver'd, the Reflexion discovered innumerable Inequalities all\nover the Glass. And by reason of these Inequalities, Objects appeared\nindistinct in this Instrument. For the Errors of reflected Rays caused\nby any Inequality of the Glass, are about six times greater than the\nErrors of refracted Rays caused by the like Inequalities. Yet by this\nExperiment I satisfied my self that the Reflexion on the concave side of\nthe Glass, which I feared would disturb the Vision, did no sensible\nprejudice to it, and by consequence that nothing is wanting to perfect\nthese Telescopes, but good Workmen who can grind and polish Glasses\ntruly spherical. An Object-glass of a fourteen Foot Telescope, made by\nan Artificer at _London_, I once mended considerably, by grinding it on\nPitch with Putty, and leaning very easily on it in the grinding, lest\nthe Putty should scratch it. Whether this way may not do well enough for\npolishing these reflecting Glasses, I have not yet tried. But he that\nshall try either this or any other way of polishing which he may think\nbetter, may do well to make his Glasses ready for polishing, by grinding\nthem without that Violence, wherewith our _London_ Workmen press their\nGlasses in grinding. For by such violent pressure, Glasses are apt to\nbend a little in the grinding, and such bending will certainly spoil\ntheir Figure. To recommend therefore the consideration of these\nreflecting Glasses to such Artists as are curious in figuring Glasses, I\nshall describe this optical Instrument in the following Proposition.\n\n\n_PROP._ VIII. PROB. II.\n\n_To shorten Telescopes._\n\nLet ABCD [in _Fig._ 29.] represent a Glass spherically concave on the\nforeside AB, and as much convex on the backside CD, so that it be every\nwhere of an equal thickness. Let it not be thicker on one side than on\nthe other, lest it make Objects appear colour'd and indistinct, and let\nit be very truly wrought and quick-silver'd over on the backside; and\nset in the Tube VXYZ which must be very black within. Let EFG represent\na Prism of Glass or Crystal placed near the other end of the Tube, in\nthe middle of it, by means of a handle of Brass or Iron FGK, to the end\nof which made flat it is cemented. Let this Prism be rectangular at E,\nand let the other two Angles at F and G be accurately equal to each\nother, and by consequence equal to half right ones, and let the plane\nsides FE and GE be square, and by consequence the third side FG a\nrectangular Parallelogram, whose length is to its breadth in a\nsubduplicate proportion of two to one. Let it be so placed in the Tube,\nthat the Axis of the Speculum may pass through the middle of the square\nside EF perpendicularly and by consequence through the middle of the\nside FG at an Angle of 45 Degrees, and let the side EF be turned towards\nthe Speculum, and the distance of this Prism from the Speculum be such\nthat the Rays of the Light PQ, RS, &c. which are incident upon the\nSpeculum in Lines parallel to the Axis thereof, may enter the Prism at\nthe side EF, and be reflected by the side FG, and thence go out of it\nthrough the side GE, to the Point T, which must be the common Focus of\nthe Speculum ABDC, and of a Plano-convex Eye-glass H, through which\nthose Rays must pass to the Eye. And let the Rays at their coming out of\nthe Glass pass through a small round hole, or aperture made in a little\nplate of Lead, Brass, or Silver, wherewith the Glass is to be covered,\nwhich hole must be no bigger than is necessary for Light enough to pass\nthrough. For so it will render the Object distinct, the Plate in which\n'tis made intercepting all the erroneous part of the Light which comes\nfrom the verges of the Speculum AB. Such an Instrument well made, if it\nbe six Foot long, (reckoning the length from the Speculum to the Prism,\nand thence to the Focus T) will bear an aperture of six Inches at the\nSpeculum, and magnify between two and three hundred times. But the hole\nH here limits the aperture with more advantage, than if the aperture was\nplaced at the Speculum. If the Instrument be made longer or shorter, the\naperture must be in proportion as the Cube of the square-square Root of\nthe length, and the magnifying as the aperture. But it's convenient that\nthe Speculum be an Inch or two broader than the aperture at the least,\nand that the Glass of the Speculum be thick, that it bend not in the\nworking. The Prism EFG must be no bigger than is necessary, and its back\nside FG must not be quick-silver'd over. For without quicksilver it will\nreflect all the Light incident on it from the Speculum.\n\n[Illustration: FIG. 29.]\n\nIn this Instrument the Object will be inverted, but may be erected by\nmaking the square sides FF and EG of the Prism EFG not plane but\nspherically convex, that the Rays may cross as well before they come at\nit as afterwards between it and the Eye-glass. If it be desired that the\nInstrument bear a larger aperture, that may be also done by composing\nthe Speculum of two Glasses with Water between them.\n\nIf the Theory of making Telescopes could at length be fully brought into\nPractice, yet there would be certain Bounds beyond which Telescopes\ncould not perform. For the Air through which we look upon the Stars, is\nin a perpetual Tremor; as may be seen by the tremulous Motion of Shadows\ncast from high Towers, and by the twinkling of the fix'd Stars. But\nthese Stars do not twinkle when viewed through Telescopes which have\nlarge apertures. For the Rays of Light which pass through divers parts\nof the aperture, tremble each of them apart, and by means of their\nvarious and sometimes contrary Tremors, fall at one and the same time\nupon different points in the bottom of the Eye, and their trembling\nMotions are too quick and confused to be perceived severally. And all\nthese illuminated Points constitute one broad lucid Point, composed of\nthose many trembling Points confusedly and insensibly mixed with one\nanother by very short and swift Tremors, and thereby cause the Star to\nappear broader than it is, and without any trembling of the whole. Long\nTelescopes may cause Objects to appear brighter and larger than short\nones can do, but they cannot be so formed as to take away that confusion\nof the Rays which arises from the Tremors of the Atmosphere. The only\nRemedy is a most serene and quiet Air, such as may perhaps be found on\nthe tops of the highest Mountains above the grosser Clouds.\n\nFOOTNOTES:\n\n[C] _See our_ Author's Lectiones Opticæ § 10. _Sect. II. § 29. and Sect.\nIII. Prop. 25._\n\n[D] See our Author's _Lectiones Opticæ_, Part. I. Sect. 1. §5.\n\n[E] _This is very fully treated of in our_ Author's Lect. Optic. _Part_\nI. _Sect._ II.\n\n[F] _See our_ Author's Lect. Optic. Part I. Sect. II. § 29.\n\n[G] _This is demonstrated in our_ Author's Lect. Optic. _Part_ I.\n_Sect._ IV. _Prop._ 37.\n\n[H] _How to do this, is shewn in our_ Author's Lect. Optic. _Part_ I.\n_Sect._ IV. _Prop._ 31.\n\n\n\n\nTHE FIRST BOOK OF OPTICKS\n\n\n\n\n_PART II._\n\n\n_PROP._ I. THEOR. I.\n\n_The Phænomena of Colours in refracted or reflected Light are not caused\nby new Modifications of the Light variously impress'd, according to the\nvarious Terminations of the Light and Shadow_.\n\nThe PROOF by Experiments.\n\n_Exper._ 1. For if the Sun shine into a very dark Chamber through an\noblong hole F, [in _Fig._ 1.] whose breadth is the sixth or eighth part\nof an Inch, or something less; and his beam FH do afterwards pass first\nthrough a very large Prism ABC, distant about 20 Feet from the hole, and\nparallel to it, and then (with its white part) through an oblong hole H,\nwhose breadth is about the fortieth or sixtieth part of an Inch, and\nwhich is made in a black opake Body GI, and placed at the distance of\ntwo or three Feet from the Prism, in a parallel Situation both to the\nPrism and to the former hole, and if this white Light thus transmitted\nthrough the hole H, fall afterwards upon a white Paper _pt_, placed\nafter that hole H, at the distance of three or four Feet from it, and\nthere paint the usual Colours of the Prism, suppose red at _t_, yellow\nat _s_, green at _r_, blue at _q_, and violet at _p_; you may with an\nIron Wire, or any such like slender opake Body, whose breadth is about\nthe tenth part of an Inch, by intercepting the Rays at _k_, _l_, _m_,\n_n_ or _o_, take away any one of the Colours at _t_, _s_, _r_, _q_ or\n_p_, whilst the other Colours remain upon the Paper as before; or with\nan Obstacle something bigger you may take away any two, or three, or\nfour Colours together, the rest remaining: So that any one of the\nColours as well as violet may become outmost in the Confine of the\nShadow towards _p_, and any one of them as well as red may become\noutmost in the Confine of the Shadow towards _t_, and any one of them\nmay also border upon the Shadow made within the Colours by the Obstacle\nR intercepting some intermediate part of the Light; and, lastly, any one\nof them by being left alone, may border upon the Shadow on either hand.\nAll the Colours have themselves indifferently to any Confines of Shadow,\nand therefore the differences of these Colours from one another, do not\narise from the different Confines of Shadow, whereby Light is variously\nmodified, as has hitherto been the Opinion of Philosophers. In trying\nthese things 'tis to be observed, that by how much the holes F and H are\nnarrower, and the Intervals between them and the Prism greater, and the\nChamber darker, by so much the better doth the Experiment succeed;\nprovided the Light be not so far diminished, but that the Colours at\n_pt_ be sufficiently visible. To procure a Prism of solid Glass large\nenough for this Experiment will be difficult, and therefore a prismatick\nVessel must be made of polish'd Glass Plates cemented together, and\nfilled with salt Water or clear Oil.\n\n[Illustration: FIG. 1.]\n\n_Exper._ 2. The Sun's Light let into a dark Chamber through the round\nhole F, [in _Fig._ 2.] half an Inch wide, passed first through the Prism\nABC placed at the hole, and then through a Lens PT something more than\nfour Inches broad, and about eight Feet distant from the Prism, and\nthence converged to O the Focus of the Lens distant from it about three\nFeet, and there fell upon a white Paper DE. If that Paper was\nperpendicular to that Light incident upon it, as 'tis represented in the\nposture DE, all the Colours upon it at O appeared white. But if the\nPaper being turned about an Axis parallel to the Prism, became very much\ninclined to the Light, as 'tis represented in the Positions _de_ and\n_[Greek: de]_; the same Light in the one case appeared yellow and red,\nin the other blue. Here one and the same part of the Light in one and\nthe same place, according to the various Inclinations of the Paper,\nappeared in one case white, in another yellow or red, in a third blue,\nwhilst the Confine of Light and shadow, and the Refractions of the Prism\nin all these cases remained the same.\n\n[Illustration: FIG. 2.]\n\n[Illustration: FIG. 3.]\n\n_Exper._ 3. Such another Experiment may be more easily tried as follows.\nLet a broad beam of the Sun's Light coming into a dark Chamber through a\nhole in the Window-shut be refracted by a large Prism ABC, [in _Fig._\n3.] whose refracting Angle C is more than 60 Degrees, and so soon as it\ncomes out of the Prism, let it fall upon the white Paper DE glewed upon\na stiff Plane; and this Light, when the Paper is perpendicular to it, as\n'tis represented in DE, will appear perfectly white upon the Paper; but\nwhen the Paper is very much inclin'd to it in such a manner as to keep\nalways parallel to the Axis of the Prism, the whiteness of the whole\nLight upon the Paper will according to the inclination of the Paper this\nway or that way, change either into yellow and red, as in the posture\n_de_, or into blue and violet, as in the posture [Greek: de]. And if the\nLight before it fall upon the Paper be twice refracted the same way by\ntwo parallel Prisms, these Colours will become the more conspicuous.\nHere all the middle parts of the broad beam of white Light which fell\nupon the Paper, did without any Confine of Shadow to modify it, become\ncolour'd all over with one uniform Colour, the Colour being always the\nsame in the middle of the Paper as at the edges, and this Colour changed\naccording to the various Obliquity of the reflecting Paper, without any\nchange in the Refractions or Shadow, or in the Light which fell upon the\nPaper. And therefore these Colours are to be derived from some other\nCause than the new Modifications of Light by Refractions and Shadows.\n\nIf it be asked, what then is their Cause? I answer, That the Paper in\nthe posture _de_, being more oblique to the more refrangible Rays than\nto the less refrangible ones, is more strongly illuminated by the latter\nthan by the former, and therefore the less refrangible Rays are\npredominant in the reflected Light. And where-ever they are predominant\nin any Light, they tinge it with red or yellow, as may in some measure\nappear by the first Proposition of the first Part of this Book, and will\nmore fully appear hereafter. And the contrary happens in the posture of\nthe Paper [Greek: de], the more refrangible Rays being then predominant\nwhich always tinge Light with blues and violets.\n\n_Exper._ 4. The Colours of Bubbles with which Children play are various,\nand change their Situation variously, without any respect to any Confine\nor Shadow. If such a Bubble be cover'd with a concave Glass, to keep it\nfrom being agitated by any Wind or Motion of the Air, the Colours will\nslowly and regularly change their situation, even whilst the Eye and the\nBubble, and all Bodies which emit any Light, or cast any Shadow, remain\nunmoved. And therefore their Colours arise from some regular Cause which\ndepends not on any Confine of Shadow. What this Cause is will be shewed\nin the next Book.\n\nTo these Experiments may be added the tenth Experiment of the first Part\nof this first Book, where the Sun's Light in a dark Room being\ntrajected through the parallel Superficies of two Prisms tied together\nin the form of a Parallelopipede, became totally of one uniform yellow\nor red Colour, at its emerging out of the Prisms. Here, in the\nproduction of these Colours, the Confine of Shadow can have nothing to\ndo. For the Light changes from white to yellow, orange and red\nsuccessively, without any alteration of the Confine of Shadow: And at\nboth edges of the emerging Light where the contrary Confines of Shadow\nought to produce different Effects, the Colour is one and the same,\nwhether it be white, yellow, orange or red: And in the middle of the\nemerging Light, where there is no Confine of Shadow at all, the Colour\nis the very same as at the edges, the whole Light at its very first\nEmergence being of one uniform Colour, whether white, yellow, orange or\nred, and going on thence perpetually without any change of Colour, such\nas the Confine of Shadow is vulgarly supposed to work in refracted Light\nafter its Emergence. Neither can these Colours arise from any new\nModifications of the Light by Refractions, because they change\nsuccessively from white to yellow, orange and red, while the Refractions\nremain the same, and also because the Refractions are made contrary ways\nby parallel Superficies which destroy one another's Effects. They arise\nnot therefore from any Modifications of Light made by Refractions and\nShadows, but have some other Cause. What that Cause is we shewed above\nin this tenth Experiment, and need not here repeat it.\n\nThere is yet another material Circumstance of this Experiment. For this\nemerging Light being by a third Prism HIK [in _Fig._ 22. _Part_ I.][I]\nrefracted towards the Paper PT, and there painting the usual Colours of\nthe Prism, red, yellow, green, blue, violet: If these Colours arose from\nthe Refractions of that Prism modifying the Light, they would not be in\nthe Light before its Incidence on that Prism. And yet in that Experiment\nwe found, that when by turning the two first Prisms about their common\nAxis all the Colours were made to vanish but the red; the Light which\nmakes that red being left alone, appeared of the very same red Colour\nbefore its Incidence on the third Prism. And in general we find by other\nExperiments, that when the Rays which differ in Refrangibility are\nseparated from one another, and any one Sort of them is considered\napart, the Colour of the Light which they compose cannot be changed by\nany Refraction or Reflexion whatever, as it ought to be were Colours\nnothing else than Modifications of Light caused by Refractions, and\nReflexions, and Shadows. This Unchangeableness of Colour I am now to\ndescribe in the following Proposition.\n\n\n_PROP._ II. THEOR. II.\n\n_All homogeneal Light has its proper Colour answering to its Degree of\nRefrangibility, and that Colour cannot be changed by Reflexions and\nRefractions._\n\nIn the Experiments of the fourth Proposition of the first Part of this\nfirst Book, when I had separated the heterogeneous Rays from one\nanother, the Spectrum _pt_ formed by the separated Rays, did in the\nProgress from its End _p_, on which the most refrangible Rays fell, unto\nits other End _t_, on which the least refrangible Rays fell, appear\ntinged with this Series of Colours, violet, indigo, blue, green, yellow,\norange, red, together with all their intermediate Degrees in a continual\nSuccession perpetually varying. So that there appeared as many Degrees\nof Colours, as there were sorts of Rays differing in Refrangibility.\n\n_Exper._ 5. Now, that these Colours could not be changed by Refraction,\nI knew by refracting with a Prism sometimes one very little Part of this\nLight, sometimes another very little Part, as is described in the\ntwelfth Experiment of the first Part of this Book. For by this\nRefraction the Colour of the Light was never changed in the least. If\nany Part of the red Light was refracted, it remained totally of the same\nred Colour as before. No orange, no yellow, no green or blue, no other\nnew Colour was produced by that Refraction. Neither did the Colour any\nways change by repeated Refractions, but continued always the same red\nentirely as at first. The like Constancy and Immutability I found also\nin the blue, green, and other Colours. So also, if I looked through a\nPrism upon any Body illuminated with any part of this homogeneal Light,\nas in the fourteenth Experiment of the first Part of this Book is\ndescribed; I could not perceive any new Colour generated this way. All\nBodies illuminated with compound Light appear through Prisms confused,\n(as was said above) and tinged with various new Colours, but those\nilluminated with homogeneal Light appeared through Prisms neither less\ndistinct, nor otherwise colour'd, than when viewed with the naked Eyes.\nTheir Colours were not in the least changed by the Refraction of the\ninterposed Prism. I speak here of a sensible Change of Colour: For the\nLight which I here call homogeneal, being not absolutely homogeneal,\nthere ought to arise some little Change of Colour from its\nHeterogeneity. But, if that Heterogeneity was so little as it might be\nmade by the said Experiments of the fourth Proposition, that Change was\nnot sensible, and therefore in Experiments, where Sense is Judge, ought\nto be accounted none at all.\n\n_Exper._ 6. And as these Colours were not changeable by Refractions, so\nneither were they by Reflexions. For all white, grey, red, yellow,\ngreen, blue, violet Bodies, as Paper, Ashes, red Lead, Orpiment, Indico\nBise, Gold, Silver, Copper, Grass, blue Flowers, Violets, Bubbles of\nWater tinged with various Colours, Peacock's Feathers, the Tincture of\n_Lignum Nephriticum_, and such-like, in red homogeneal Light appeared\ntotally red, in blue Light totally blue, in green Light totally green,\nand so of other Colours. In the homogeneal Light of any Colour they all\nappeared totally of that same Colour, with this only Difference, that\nsome of them reflected that Light more strongly, others more faintly. I\nnever yet found any Body, which by reflecting homogeneal Light could\nsensibly change its Colour.\n\nFrom all which it is manifest, that if the Sun's Light consisted of but\none sort of Rays, there would be but one Colour in the whole World, nor\nwould it be possible to produce any new Colour by Reflexions and\nRefractions, and by consequence that the variety of Colours depends upon\nthe Composition of Light.\n\n\n_DEFINITION._\n\nThe homogeneal Light and Rays which appear red, or rather make Objects\nappear so, I call Rubrifick or Red-making; those which make Objects\nappear yellow, green, blue, and violet, I call Yellow-making,\nGreen-making, Blue-making, Violet-making, and so of the rest. And if at\nany time I speak of Light and Rays as coloured or endued with Colours, I\nwould be understood to speak not philosophically and properly, but\ngrossly, and accordingly to such Conceptions as vulgar People in seeing\nall these Experiments would be apt to frame. For the Rays to speak\nproperly are not coloured. In them there is nothing else than a certain\nPower and Disposition to stir up a Sensation of this or that Colour.\nFor as Sound in a Bell or musical String, or other sounding Body, is\nnothing but a trembling Motion, and in the Air nothing but that Motion\npropagated from the Object, and in the Sensorium 'tis a Sense of that\nMotion under the Form of Sound; so Colours in the Object are nothing but\na Disposition to reflect this or that sort of Rays more copiously than\nthe rest; in the Rays they are nothing but their Dispositions to\npropagate this or that Motion into the Sensorium, and in the Sensorium\nthey are Sensations of those Motions under the Forms of Colours.\n\n\n_PROP._ III. PROB. I.\n\n_To define the Refrangibility of the several sorts of homogeneal Light\nanswering to the several Colours._\n\nFor determining this Problem I made the following Experiment.[J]\n\n_Exper._ 7. When I had caused the Rectilinear Sides AF, GM, [in _Fig._\n4.] of the Spectrum of Colours made by the Prism to be distinctly\ndefined, as in the fifth Experiment of the first Part of this Book is\ndescribed, there were found in it all the homogeneal Colours in the same\nOrder and Situation one among another as in the Spectrum of simple\nLight, described in the fourth Proposition of that Part. For the Circles\nof which the Spectrum of compound Light PT is composed, and which in\nthe middle Parts of the Spectrum interfere, and are intermix'd with one\nanother, are not intermix'd in their outmost Parts where they touch\nthose Rectilinear Sides AF and GM. And therefore, in those Rectilinear\nSides when distinctly defined, there is no new Colour generated by\nRefraction. I observed also, that if any where between the two outmost\nCircles TMF and PGA a Right Line, as [Greek: gd], was cross to the\nSpectrum, so as both Ends to fall perpendicularly upon its Rectilinear\nSides, there appeared one and the same Colour, and degree of Colour from\none End of this Line to the other. I delineated therefore in a Paper the\nPerimeter of the Spectrum FAP GMT, and in trying the third Experiment of\nthe first Part of this Book, I held the Paper so that the Spectrum might\nfall upon this delineated Figure, and agree with it exactly, whilst an\nAssistant, whose Eyes for distinguishing Colours were more critical than\nmine, did by Right Lines [Greek: ab, gd, ez,] &c. drawn cross the\nSpectrum, note the Confines of the Colours, that is of the red M[Greek:\nab]F, of the orange [Greek: agdb], of the yellow [Greek: gezd], of the\ngreen [Greek: eêthz], of the blue [Greek: êikth], of the indico [Greek:\nilmk], and of the violet [Greek: l]GA[Greek: m]. And this Operation\nbeing divers times repeated both in the same, and in several Papers, I\nfound that the Observations agreed well enough with one another, and\nthat the Rectilinear Sides MG and FA were by the said cross Lines\ndivided after the manner of a Musical Chord. Let GM be produced to X,\nthat MX may be equal to GM, and conceive GX, [Greek: l]X, [Greek: i]X,\n[Greek: ê]X, [Greek: e]X, [Greek: g]X, [Greek: a]X, MX, to be in\nproportion to one another, as the Numbers, 1, 8/9, 5/6, 3/4, 2/3, 3/5,\n9/16, 1/2, and so to represent the Chords of the Key, and of a Tone, a\nthird Minor, a fourth, a fifth, a sixth Major, a seventh and an eighth\nabove that Key: And the Intervals M[Greek: a], [Greek: ag], [Greek: ge],\n[Greek: eê], [Greek: êi], [Greek: il], and [Greek: l]G, will be the\nSpaces which the several Colours (red, orange, yellow, green, blue,\nindigo, violet) take up.\n\n[Illustration: FIG. 4.]\n\n[Illustration: FIG. 5.]\n\nNow these Intervals or Spaces subtending the Differences of the\nRefractions of the Rays going to the Limits of those Colours, that is,\nto the Points M, [Greek: a], [Greek: g], [Greek: e], [Greek: ê], [Greek:\ni], [Greek: l], G, may without any sensible Error be accounted\nproportional to the Differences of the Sines of Refraction of those Rays\nhaving one common Sine of Incidence, and therefore since the common Sine\nof Incidence of the most and least refrangible Rays out of Glass into\nAir was (by a Method described above) found in proportion to their Sines\nof Refraction, as 50 to 77 and 78, divide the Difference between the\nSines of Refraction 77 and 78, as the Line GM is divided by those\nIntervals, and you will have 77, 77-1/8, 77-1/5, 77-1/3, 77-1/2, 77-2/3,\n77-7/9, 78, the Sines of Refraction of those Rays out of Glass into Air,\ntheir common Sine of Incidence being 50. So then the Sines of the\nIncidences of all the red-making Rays out of Glass into Air, were to the\nSines of their Refractions, not greater than 50 to 77, nor less than 50\nto 77-1/8, but they varied from one another according to all\nintermediate Proportions. And the Sines of the Incidences of the\ngreen-making Rays were to the Sines of their Refractions in all\nProportions from that of 50 to 77-1/3, unto that of 50 to 77-1/2. And\nby the like Limits above-mentioned were the Refractions of the Rays\nbelonging to the rest of the Colours defined, the Sines of the\nred-making Rays extending from 77 to 77-1/8, those of the orange-making\nfrom 77-1/8 to 77-1/5, those of the yellow-making from 77-1/5 to 77-1/3,\nthose of the green-making from 77-1/3 to 77-1/2, those of the\nblue-making from 77-1/2 to 77-2/3, those of the indigo-making from\n77-2/3 to 77-7/9, and those of the violet from 77-7/9, to 78.\n\nThese are the Laws of the Refractions made out of Glass into Air, and\nthence by the third Axiom of the first Part of this Book, the Laws of\nthe Refractions made out of Air into Glass are easily derived.\n\n_Exper._ 8. I found moreover, that when Light goes out of Air through\nseveral contiguous refracting Mediums as through Water and Glass, and\nthence goes out again into Air, whether the refracting Superficies be\nparallel or inclin'd to one another, that Light as often as by contrary\nRefractions 'tis so corrected, that it emergeth in Lines parallel to\nthose in which it was incident, continues ever after to be white. But if\nthe emergent Rays be inclined to the incident, the Whiteness of the\nemerging Light will by degrees in passing on from the Place of\nEmergence, become tinged in its Edges with Colours. This I try'd by\nrefracting Light with Prisms of Glass placed within a Prismatick Vessel\nof Water. Now those Colours argue a diverging and separation of the\nheterogeneous Rays from one another by means of their unequal\nRefractions, as in what follows will more fully appear. And, on the\ncontrary, the permanent whiteness argues, that in like Incidences of the\nRays there is no such separation of the emerging Rays, and by\nconsequence no inequality of their whole Refractions. Whence I seem to\ngather the two following Theorems.\n\n1. The Excesses of the Sines of Refraction of several sorts of Rays\nabove their common Sine of Incidence when the Refractions are made out\nof divers denser Mediums immediately into one and the same rarer Medium,\nsuppose of Air, are to one another in a given Proportion.\n\n2. The Proportion of the Sine of Incidence to the Sine of Refraction of\none and the same sort of Rays out of one Medium into another, is\ncomposed of the Proportion of the Sine of Incidence to the Sine of\nRefraction out of the first Medium into any third Medium, and of the\nProportion of the Sine of Incidence to the Sine of Refraction out of\nthat third Medium into the second Medium.\n\nBy the first Theorem the Refractions of the Rays of every sort made out\nof any Medium into Air are known by having the Refraction of the Rays of\nany one sort. As for instance, if the Refractions of the Rays of every\nsort out of Rain-water into Air be desired, let the common Sine of\nIncidence out of Glass into Air be subducted from the Sines of\nRefraction, and the Excesses will be 27, 27-1/8, 27-1/5, 27-1/3, 27-1/2,\n27-2/3, 27-7/9, 28. Suppose now that the Sine of Incidence of the least\nrefrangible Rays be to their Sine of Refraction out of Rain-water into\nAir as 3 to 4, and say as 1 the difference of those Sines is to 3 the\nSine of Incidence, so is 27 the least of the Excesses above-mentioned to\na fourth Number 81; and 81 will be the common Sine of Incidence out of\nRain-water into Air, to which Sine if you add all the above-mentioned\nExcesses, you will have the desired Sines of the Refractions 108,\n108-1/8, 108-1/5, 108-1/3, 108-1/2, 108-2/3, 108-7/9, 109.\n\nBy the latter Theorem the Refraction out of one Medium into another is\ngathered as often as you have the Refractions out of them both into any\nthird Medium. As if the Sine of Incidence of any Ray out of Glass into\nAir be to its Sine of Refraction, as 20 to 31, and the Sine of Incidence\nof the same Ray out of Air into Water, be to its Sine of Refraction as 4\nto 3; the Sine of Incidence of that Ray out of Glass into Water will be\nto its Sine of Refraction as 20 to 31 and 4 to 3 jointly, that is, as\nthe Factum of 20 and 4 to the Factum of 31 and 3, or as 80 to 93.\n\nAnd these Theorems being admitted into Opticks, there would be scope\nenough of handling that Science voluminously after a new manner,[K] not\nonly by teaching those things which tend to the perfection of Vision,\nbut also by determining mathematically all kinds of Phænomena of Colours\nwhich could be produced by Refractions. For to do this, there is nothing\nelse requisite than to find out the Separations of heterogeneous Rays,\nand their various Mixtures and Proportions in every Mixture. By this\nway of arguing I invented almost all the Phænomena described in these\nBooks, beside some others less necessary to the Argument; and by the\nsuccesses I met with in the Trials, I dare promise, that to him who\nshall argue truly, and then try all things with good Glasses and\nsufficient Circumspection, the expected Event will not be wanting. But\nhe is first to know what Colours will arise from any others mix'd in any\nassigned Proportion.\n\n\n_PROP._ IV. THEOR. III.\n\n_Colours may be produced by Composition which shall be like to the\nColours of homogeneal Light as to the Appearance of Colour, but not as\nto the Immutability of Colour and Constitution of Light. And those\nColours by how much they are more compounded by so much are they less\nfull and intense, and by too much Composition they maybe diluted and\nweaken'd till they cease, and the Mixture becomes white or grey. There\nmay be also Colours produced by Composition, which are not fully like\nany of the Colours of homogeneal Light._\n\nFor a Mixture of homogeneal red and yellow compounds an Orange, like in\nappearance of Colour to that orange which in the series of unmixed\nprismatick Colours lies between them; but the Light of one orange is\nhomogeneal as to Refrangibility, and that of the other is heterogeneal,\nand the Colour of the one, if viewed through a Prism, remains unchanged,\nthat of the other is changed and resolved into its component Colours red\nand yellow. And after the same manner other neighbouring homogeneal\nColours may compound new Colours, like the intermediate homogeneal ones,\nas yellow and green, the Colour between them both, and afterwards, if\nblue be added, there will be made a green the middle Colour of the three\nwhich enter the Composition. For the yellow and blue on either hand, if\nthey are equal in quantity they draw the intermediate green equally\ntowards themselves in Composition, and so keep it as it were in\nÆquilibrion, that it verge not more to the yellow on the one hand, and\nto the blue on the other, but by their mix'd Actions remain still a\nmiddle Colour. To this mix'd green there may be farther added some red\nand violet, and yet the green will not presently cease, but only grow\nless full and vivid, and by increasing the red and violet, it will grow\nmore and more dilute, until by the prevalence of the added Colours it be\novercome and turned into whiteness, or some other Colour. So if to the\nColour of any homogeneal Light, the Sun's white Light composed of all\nsorts of Rays be added, that Colour will not vanish or change its\nSpecies, but be diluted, and by adding more and more white it will be\ndiluted more and more perpetually. Lastly, If red and violet be mingled,\nthere will be generated according to their various Proportions various\nPurples, such as are not like in appearance to the Colour of any\nhomogeneal Light, and of these Purples mix'd with yellow and blue may be\nmade other new Colours.\n\n\n_PROP._ V. THEOR. IV.\n\n_Whiteness and all grey Colours between white and black, may be\ncompounded of Colours, and the whiteness of the Sun's Light is\ncompounded of all the primary Colours mix'd in a due Proportion._\n\nThe PROOF by Experiments.\n\n_Exper._ 9. The Sun shining into a dark Chamber through a little round\nhole in the Window-shut, and his Light being there refracted by a Prism\nto cast his coloured Image PT [in _Fig._ 5.] upon the opposite Wall: I\nheld a white Paper V to that image in such manner that it might be\nilluminated by the colour'd Light reflected from thence, and yet not\nintercept any part of that Light in its passage from the Prism to the\nSpectrum. And I found that when the Paper was held nearer to any Colour\nthan to the rest, it appeared of that Colour to which it approached\nnearest; but when it was equally or almost equally distant from all the\nColours, so that it might be equally illuminated by them all it appeared\nwhite. And in this last situation of the Paper, if some Colours were\nintercepted, the Paper lost its white Colour, and appeared of the Colour\nof the rest of the Light which was not intercepted. So then the Paper\nwas illuminated with Lights of various Colours, namely, red, yellow,\ngreen, blue and violet, and every part of the Light retained its proper\nColour, until it was incident on the Paper, and became reflected thence\nto the Eye; so that if it had been either alone (the rest of the Light\nbeing intercepted) or if it had abounded most, and been predominant in\nthe Light reflected from the Paper, it would have tinged the Paper with\nits own Colour; and yet being mixed with the rest of the Colours in a\ndue proportion, it made the Paper look white, and therefore by a\nComposition with the rest produced that Colour. The several parts of the\ncoloured Light reflected from the Spectrum, whilst they are propagated\nfrom thence through the Air, do perpetually retain their proper Colours,\nbecause wherever they fall upon the Eyes of any Spectator, they make the\nseveral parts of the Spectrum to appear under their proper Colours. They\nretain therefore their proper Colours when they fall upon the Paper V,\nand so by the confusion and perfect mixture of those Colours compound\nthe whiteness of the Light reflected from thence.\n\n_Exper._ 10. Let that Spectrum or solar Image PT [in _Fig._ 6.] fall now\nupon the Lens MN above four Inches broad, and about six Feet distant\nfrom the Prism ABC and so figured that it may cause the coloured Light\nwhich divergeth from the Prism to converge and meet again at its Focus\nG, about six or eight Feet distant from the Lens, and there to fall\nperpendicularly upon a white Paper DE. And if you move this Paper to and\nfro, you will perceive that near the Lens, as at _de_, the whole solar\nImage (suppose at _pt_) will appear upon it intensely coloured after the\nmanner above-explained, and that by receding from the Lens those Colours\nwill perpetually come towards one another, and by mixing more and more\ndilute one another continually, until at length the Paper come to the\nFocus G, where by a perfect mixture they will wholly vanish and be\nconverted into whiteness, the whole Light appearing now upon the Paper\nlike a little white Circle. And afterwards by receding farther from the\nLens, the Rays which before converged will now cross one another in the\nFocus G, and diverge from thence, and thereby make the Colours to appear\nagain, but yet in a contrary order; suppose at [Greek: de], where the\nred _t_ is now above which before was below, and the violet _p_ is below\nwhich before was above.\n\nLet us now stop the Paper at the Focus G, where the Light appears\ntotally white and circular, and let us consider its whiteness. I say,\nthat this is composed of the converging Colours. For if any of those\nColours be intercepted at the Lens, the whiteness will cease and\ndegenerate into that Colour which ariseth from the composition of the\nother Colours which are not intercepted. And then if the intercepted\nColours be let pass and fall upon that compound Colour, they mix with\nit, and by their mixture restore the whiteness. So if the violet, blue\nand green be intercepted, the remaining yellow, orange and red will\ncompound upon the Paper an orange, and then if the intercepted Colours\nbe let pass, they will fall upon this compounded orange, and together\nwith it decompound a white. So also if the red and violet be\nintercepted, the remaining yellow, green and blue, will compound a green\nupon the Paper, and then the red and violet being let pass will fall\nupon this green, and together with it decompound a white. And that in\nthis Composition of white the several Rays do not suffer any Change in\ntheir colorific Qualities by acting upon one another, but are only\nmixed, and by a mixture of their Colours produce white, may farther\nappear by these Arguments.\n\n[Illustration: FIG. 6.]\n\nIf the Paper be placed beyond the Focus G, suppose at [Greek: de], and\nthen the red Colour at the Lens be alternately intercepted, and let pass\nagain, the violet Colour on the Paper will not suffer any Change\nthereby, as it ought to do if the several sorts of Rays acted upon one\nanother in the Focus G, where they cross. Neither will the red upon the\nPaper be changed by any alternate stopping, and letting pass the violet\nwhich crosseth it.\n\nAnd if the Paper be placed at the Focus G, and the white round Image at\nG be viewed through the Prism HIK, and by the Refraction of that Prism\nbe translated to the place _rv_, and there appear tinged with various\nColours, namely, the violet at _v_ and red at _r_, and others between,\nand then the red Colours at the Lens be often stopp'd and let pass by\nturns, the red at _r_ will accordingly disappear, and return as often,\nbut the violet at _v_ will not thereby suffer any Change. And so by\nstopping and letting pass alternately the blue at the Lens, the blue at\n_v_ will accordingly disappear and return, without any Change made in\nthe red at _r_. The red therefore depends on one sort of Rays, and the\nblue on another sort, which in the Focus G where they are commix'd, do\nnot act on one another. And there is the same Reason of the other\nColours.\n\nI considered farther, that when the most refrangible Rays P_p_, and the\nleast refrangible ones T_t_, are by converging inclined to one another,\nthe Paper, if held very oblique to those Rays in the Focus G, might\nreflect one sort of them more copiously than the other sort, and by that\nMeans the reflected Light would be tinged in that Focus with the Colour\nof the predominant Rays, provided those Rays severally retained their\nColours, or colorific Qualities in the Composition of White made by them\nin that Focus. But if they did not retain them in that White, but became\nall of them severally endued there with a Disposition to strike the\nSense with the Perception of White, then they could never lose their\nWhiteness by such Reflexions. I inclined therefore the Paper to the Rays\nvery obliquely, as in the second Experiment of this second Part of the\nfirst Book, that the most refrangible Rays, might be more copiously\nreflected than the rest, and the Whiteness at Length changed\nsuccessively into blue, indigo, and violet. Then I inclined it the\ncontrary Way, that the least refrangible Rays might be more copious in\nthe reflected Light than the rest, and the Whiteness turned successively\nto yellow, orange, and red.\n\nLastly, I made an Instrument XY in fashion of a Comb, whose Teeth being\nin number sixteen, were about an Inch and a half broad, and the\nIntervals of the Teeth about two Inches wide. Then by interposing\nsuccessively the Teeth of this Instrument near the Lens, I intercepted\nPart of the Colours by the interposed Tooth, whilst the rest of them\nwent on through the Interval of the Teeth to the Paper DE, and there\npainted a round Solar Image. But the Paper I had first placed so, that\nthe Image might appear white as often as the Comb was taken away; and\nthen the Comb being as was said interposed, that Whiteness by reason of\nthe intercepted Part of the Colours at the Lens did always change into\nthe Colour compounded of those Colours which were not intercepted, and\nthat Colour was by the Motion of the Comb perpetually varied so, that in\nthe passing of every Tooth over the Lens all these Colours, red, yellow,\ngreen, blue, and purple, did always succeed one another. I caused\ntherefore all the Teeth to pass successively over the Lens, and when the\nMotion was slow, there appeared a perpetual Succession of the Colours\nupon the Paper: But if I so much accelerated the Motion, that the\nColours by reason of their quick Succession could not be distinguished\nfrom one another, the Appearance of the single Colours ceased. There was\nno red, no yellow, no green, no blue, nor purple to be seen any longer,\nbut from a Confusion of them all there arose one uniform white Colour.\nOf the Light which now by the Mixture of all the Colours appeared white,\nthere was no Part really white. One Part was red, another yellow, a\nthird green, a fourth blue, a fifth purple, and every Part retains its\nproper Colour till it strike the Sensorium. If the Impressions follow\none another slowly, so that they may be severally perceived, there is\nmade a distinct Sensation of all the Colours one after another in a\ncontinual Succession. But if the Impressions follow one another so\nquickly, that they cannot be severally perceived, there ariseth out of\nthem all one common Sensation, which is neither of this Colour alone nor\nof that alone, but hath it self indifferently to 'em all, and this is a\nSensation of Whiteness. By the Quickness of the Successions, the\nImpressions of the several Colours are confounded in the Sensorium, and\nout of that Confusion ariseth a mix'd Sensation. If a burning Coal be\nnimbly moved round in a Circle with Gyrations continually repeated, the\nwhole Circle will appear like Fire; the reason of which is, that the\nSensation of the Coal in the several Places of that Circle remains\nimpress'd on the Sensorium, until the Coal return again to the same\nPlace. And so in a quick Consecution of the Colours the Impression of\nevery Colour remains in the Sensorium, until a Revolution of all the\nColours be compleated, and that first Colour return again. The\nImpressions therefore of all the successive Colours are at once in the\nSensorium, and jointly stir up a Sensation of them all; and so it is\nmanifest by this Experiment, that the commix'd Impressions of all the\nColours do stir up and beget a Sensation of white, that is, that\nWhiteness is compounded of all the Colours.\n\nAnd if the Comb be now taken away, that all the Colours may at once pass\nfrom the Lens to the Paper, and be there intermixed, and together\nreflected thence to the Spectator's Eyes; their Impressions on the\nSensorium being now more subtilly and perfectly commixed there, ought\nmuch more to stir up a Sensation of Whiteness.\n\nYou may instead of the Lens use two Prisms HIK and LMN, which by\nrefracting the coloured Light the contrary Way to that of the first\nRefraction, may make the diverging Rays converge and meet again in G, as\nyou see represented in the seventh Figure. For where they meet and mix,\nthey will compose a white Light, as when a Lens is used.\n\n_Exper._ 11. Let the Sun's coloured Image PT [in _Fig._ 8.] fall upon\nthe Wall of a dark Chamber, as in the third Experiment of the first\nBook, and let the same be viewed through a Prism _abc_, held parallel to\nthe Prism ABC, by whose Refraction that Image was made, and let it now\nappear lower than before, suppose in the Place S over-against the red\nColour T. And if you go near to the Image PT, the Spectrum S will appear\noblong and coloured like the Image PT; but if you recede from it, the\nColours of the spectrum S will be contracted more and more, and at\nlength vanish, that Spectrum S becoming perfectly round and white; and\nif you recede yet farther, the Colours will emerge again, but in a\ncontrary Order. Now that Spectrum S appears white in that Case, when the\nRays of several sorts which converge from the several Parts of the Image\nPT, to the Prism _abc_, are so refracted unequally by it, that in their\nPassage from the Prism to the Eye they may diverge from one and the same\nPoint of the Spectrum S, and so fall afterwards upon one and the same\nPoint in the bottom of the Eye, and there be mingled.\n\n[Illustration: FIG. 7.]\n\n[Illustration: FIG. 8.]\n\nAnd farther, if the Comb be here made use of, by whose Teeth the Colours\nat the Image PT may be successively intercepted; the Spectrum S, when\nthe Comb is moved slowly, will be perpetually tinged with successive\nColours: But when by accelerating the Motion of the Comb, the Succession\nof the Colours is so quick that they cannot be severally seen, that\nSpectrum S, by a confused and mix'd Sensation of them all, will appear\nwhite.\n\n_Exper._ 12. The Sun shining through a large Prism ABC [in _Fig._ 9.]\nupon a Comb XY, placed immediately behind the Prism, his Light which\npassed through the Interstices of the Teeth fell upon a white Paper DE.\nThe Breadths of the Teeth were equal to their Interstices, and seven\nTeeth together with their Interstices took up an Inch in Breadth. Now,\nwhen the Paper was about two or three Inches distant from the Comb, the\nLight which passed through its several Interstices painted so many\nRanges of Colours, _kl_, _mn_, _op_, _qr_, &c. which were parallel to\none another, and contiguous, and without any Mixture of white. And these\nRanges of Colours, if the Comb was moved continually up and down with a\nreciprocal Motion, ascended and descended in the Paper, and when the\nMotion of the Comb was so quick, that the Colours could not be\ndistinguished from one another, the whole Paper by their Confusion and\nMixture in the Sensorium appeared white.\n\n[Illustration: FIG. 9.]\n\nLet the Comb now rest, and let the Paper be removed farther from the\nPrism, and the several Ranges of Colours will be dilated and expanded\ninto one another more and more, and by mixing their Colours will dilute\none another, and at length, when the distance of the Paper from the Comb\nis about a Foot, or a little more (suppose in the Place 2D 2E) they will\nso far dilute one another, as to become white.\n\nWith any Obstacle, let all the Light be now stopp'd which passes through\nany one Interval of the Teeth, so that the Range of Colours which comes\nfrom thence may be taken away, and you will see the Light of the rest of\nthe Ranges to be expanded into the Place of the Range taken away, and\nthere to be coloured. Let the intercepted Range pass on as before, and\nits Colours falling upon the Colours of the other Ranges, and mixing\nwith them, will restore the Whiteness.\n\nLet the Paper 2D 2E be now very much inclined to the Rays, so that the\nmost refrangible Rays may be more copiously reflected than the rest, and\nthe white Colour of the Paper through the Excess of those Rays will be\nchanged into blue and violet. Let the Paper be as much inclined the\ncontrary way, that the least refrangible Rays may be now more copiously\nreflected than the rest, and by their Excess the Whiteness will be\nchanged into yellow and red. The several Rays therefore in that white\nLight do retain their colorific Qualities, by which those of any sort,\nwhenever they become more copious than the rest, do by their Excess and\nPredominance cause their proper Colour to appear.\n\nAnd by the same way of arguing, applied to the third Experiment of this\nsecond Part of the first Book, it may be concluded, that the white\nColour of all refracted Light at its very first Emergence, where it\nappears as white as before its Incidence, is compounded of various\nColours.\n\n[Illustration: FIG. 10.]\n\n_Exper._ 13. In the foregoing Experiment the several Intervals of the\nTeeth of the Comb do the Office of so many Prisms, every Interval\nproducing the Phænomenon of one Prism. Whence instead of those Intervals\nusing several Prisms, I try'd to compound Whiteness by mixing their\nColours, and did it by using only three Prisms, as also by using only\ntwo as follows. Let two Prisms ABC and _abc_, [in _Fig._ 10.] whose\nrefracting Angles B and _b_ are equal, be so placed parallel to one\nanother, that the refracting Angle B of the one may touch the Angle _c_\nat the Base of the other, and their Planes CB and _cb_, at which the\nRays emerge, may lie in Directum. Then let the Light trajected through\nthem fall upon the Paper MN, distant about 8 or 12 Inches from the\nPrisms. And the Colours generated by the interior Limits B and _c_ of\nthe two Prisms, will be mingled at PT, and there compound white. For if\neither Prism be taken away, the Colours made by the other will appear in\nthat Place PT, and when the Prism is restored to its Place again, so\nthat its Colours may there fall upon the Colours of the other, the\nMixture of them both will restore the Whiteness.\n\nThis Experiment succeeds also, as I have tried, when the Angle _b_ of\nthe lower Prism, is a little greater than the Angle B of the upper, and\nbetween the interior Angles B and _c_, there intercedes some Space B_c_,\nas is represented in the Figure, and the refracting Planes BC and _bc_,\nare neither in Directum, nor parallel to one another. For there is\nnothing more requisite to the Success of this Experiment, than that the\nRays of all sorts may be uniformly mixed upon the Paper in the Place PT.\nIf the most refrangible Rays coming from the superior Prism take up all\nthe Space from M to P, the Rays of the same sort which come from the\ninferior Prism ought to begin at P, and take up all the rest of the\nSpace from thence towards N. If the least refrangible Rays coming from\nthe superior Prism take up the Space MT, the Rays of the same kind which\ncome from the other Prism ought to begin at T, and take up the\nremaining Space TN. If one sort of the Rays which have intermediate\nDegrees of Refrangibility, and come from the superior Prism be extended\nthrough the Space MQ, and another sort of those Rays through the Space\nMR, and a third sort of them through the Space MS, the same sorts of\nRays coming from the lower Prism, ought to illuminate the remaining\nSpaces QN, RN, SN, respectively. And the same is to be understood of all\nthe other sorts of Rays. For thus the Rays of every sort will be\nscattered uniformly and evenly through the whole Space MN, and so being\nevery where mix'd in the same Proportion, they must every where produce\nthe same Colour. And therefore, since by this Mixture they produce white\nin the Exterior Spaces MP and TN, they must also produce white in the\nInterior Space PT. This is the reason of the Composition by which\nWhiteness was produced in this Experiment, and by what other way soever\nI made the like Composition, the Result was Whiteness.\n\nLastly, If with the Teeth of a Comb of a due Size, the coloured Lights\nof the two Prisms which fall upon the Space PT be alternately\nintercepted, that Space PT, when the Motion of the Comb is slow, will\nalways appear coloured, but by accelerating the Motion of the Comb so\nmuch that the successive Colours cannot be distinguished from one\nanother, it will appear white.\n\n_Exper._ 14. Hitherto I have produced Whiteness by mixing the Colours of\nPrisms. If now the Colours of natural Bodies are to be mingled, let\nWater a little thicken'd with Soap be agitated to raise a Froth, and\nafter that Froth has stood a little, there will appear to one that shall\nview it intently various Colours every where in the Surfaces of the\nseveral Bubbles; but to one that shall go so far off, that he cannot\ndistinguish the Colours from one another, the whole Froth will grow\nwhite with a perfect Whiteness.\n\n_Exper._ 15. Lastly, In attempting to compound a white, by mixing the\ncoloured Powders which Painters use, I consider'd that all colour'd\nPowders do suppress and stop in them a very considerable Part of the\nLight by which they are illuminated. For they become colour'd by\nreflecting the Light of their own Colours more copiously, and that of\nall other Colours more sparingly, and yet they do not reflect the Light\nof their own Colours so copiously as white Bodies do. If red Lead, for\ninstance, and a white Paper, be placed in the red Light of the colour'd\nSpectrum made in a dark Chamber by the Refraction of a Prism, as is\ndescribed in the third Experiment of the first Part of this Book; the\nPaper will appear more lucid than the red Lead, and therefore reflects\nthe red-making Rays more copiously than red Lead doth. And if they be\nheld in the Light of any other Colour, the Light reflected by the Paper\nwill exceed the Light reflected by the red Lead in a much greater\nProportion. And the like happens in Powders of other Colours. And\ntherefore by mixing such Powders, we are not to expect a strong and\nfull White, such as is that of Paper, but some dusky obscure one, such\nas might arise from a Mixture of Light and Darkness, or from white and\nblack, that is, a grey, or dun, or russet brown, such as are the Colours\nof a Man's Nail, of a Mouse, of Ashes, of ordinary Stones, of Mortar, of\nDust and Dirt in High-ways, and the like. And such a dark white I have\noften produced by mixing colour'd Powders. For thus one Part of red\nLead, and five Parts of _Viride Æris_, composed a dun Colour like that\nof a Mouse. For these two Colours were severally so compounded of\nothers, that in both together were a Mixture of all Colours; and there\nwas less red Lead used than _Viride Æris_, because of the Fulness of its\nColour. Again, one Part of red Lead, and four Parts of blue Bise,\ncomposed a dun Colour verging a little to purple, and by adding to this\na certain Mixture of Orpiment and _Viride Æris_ in a due Proportion, the\nMixture lost its purple Tincture, and became perfectly dun. But the\nExperiment succeeded best without Minium thus. To Orpiment I added by\nlittle and little a certain full bright purple, which Painters use,\nuntil the Orpiment ceased to be yellow, and became of a pale red. Then I\ndiluted that red by adding a little _Viride Æris_, and a little more\nblue Bise than _Viride Æris_, until it became of such a grey or pale\nwhite, as verged to no one of the Colours more than to another. For thus\nit became of a Colour equal in Whiteness to that of Ashes, or of Wood\nnewly cut, or of a Man's Skin. The Orpiment reflected more Light than\ndid any other of the Powders, and therefore conduced more to the\nWhiteness of the compounded Colour than they. To assign the Proportions\naccurately may be difficult, by reason of the different Goodness of\nPowders of the same kind. Accordingly, as the Colour of any Powder is\nmore or less full and luminous, it ought to be used in a less or greater\nProportion.\n\nNow, considering that these grey and dun Colours may be also produced by\nmixing Whites and Blacks, and by consequence differ from perfect Whites,\nnot in Species of Colours, but only in degree of Luminousness, it is\nmanifest that there is nothing more requisite to make them perfectly\nwhite than to increase their Light sufficiently; and, on the contrary,\nif by increasing their Light they can be brought to perfect Whiteness,\nit will thence also follow, that they are of the same Species of Colour\nwith the best Whites, and differ from them only in the Quantity of\nLight. And this I tried as follows. I took the third of the\nabove-mention'd grey Mixtures, (that which was compounded of Orpiment,\nPurple, Bise, and _Viride Æris_) and rubbed it thickly upon the Floor of\nmy Chamber, where the Sun shone upon it through the opened Casement; and\nby it, in the shadow, I laid a Piece of white Paper of the same Bigness.\nThen going from them to the distance of 12 or 18 Feet, so that I could\nnot discern the Unevenness of the Surface of the Powder, nor the little\nShadows let fall from the gritty Particles thereof; the Powder appeared\nintensely white, so as to transcend even the Paper it self in Whiteness,\nespecially if the Paper were a little shaded from the Light of the\nClouds, and then the Paper compared with the Powder appeared of such a\ngrey Colour as the Powder had done before. But by laying the Paper where\nthe Sun shines through the Glass of the Window, or by shutting the\nWindow that the Sun might shine through the Glass upon the Powder, and\nby such other fit Means of increasing or decreasing the Lights wherewith\nthe Powder and Paper were illuminated, the Light wherewith the Powder is\nilluminated may be made stronger in such a due Proportion than the Light\nwherewith the Paper is illuminated, that they shall both appear exactly\nalike in Whiteness. For when I was trying this, a Friend coming to visit\nme, I stopp'd him at the Door, and before I told him what the Colours\nwere, or what I was doing; I asked him, Which of the two Whites were the\nbest, and wherein they differed? And after he had at that distance\nviewed them well, he answer'd, that they were both good Whites, and that\nhe could not say which was best, nor wherein their Colours differed.\nNow, if you consider, that this White of the Powder in the Sun-shine was\ncompounded of the Colours which the component Powders (Orpiment, Purple,\nBise, and _Viride Æris_) have in the same Sun-shine, you must\nacknowledge by this Experiment, as well as by the former, that perfect\nWhiteness may be compounded of Colours.\n\nFrom what has been said it is also evident, that the Whiteness of the\nSun's Light is compounded of all the Colours wherewith the several sorts\nof Rays whereof that Light consists, when by their several\nRefrangibilities they are separated from one another, do tinge Paper or\nany other white Body whereon they fall. For those Colours (by _Prop._\nII. _Part_ 2.) are unchangeable, and whenever all those Rays with those\ntheir Colours are mix'd again, they reproduce the same white Light as\nbefore.\n\n\n_PROP._ VI. PROB. II.\n\n_In a mixture of Primary Colours, the Quantity and Quality of each being\ngiven, to know the Colour of the Compound._\n\n[Illustration: FIG. 11.]\n\nWith the Center O [in _Fig._ 11.] and Radius OD describe a Circle ADF,\nand distinguish its Circumference into seven Parts DE, EF, FG, GA, AB,\nBC, CD, proportional to the seven Musical Tones or Intervals of the\neight Sounds, _Sol_, _la_, _fa_, _sol_, _la_, _mi_, _fa_, _sol_,\ncontained in an eight, that is, proportional to the Number 1/9, 1/16,\n1/10, 1/9, 1/16, 1/16, 1/9. Let the first Part DE represent a red\nColour, the second EF orange, the third FG yellow, the fourth CA green,\nthe fifth AB blue, the sixth BC indigo, and the seventh CD violet. And\nconceive that these are all the Colours of uncompounded Light gradually\npassing into one another, as they do when made by Prisms; the\nCircumference DEFGABCD, representing the whole Series of Colours from\none end of the Sun's colour'd Image to the other, so that from D to E be\nall degrees of red, at E the mean Colour between red and orange, from E\nto F all degrees of orange, at F the mean between orange and yellow,\nfrom F to G all degrees of yellow, and so on. Let _p_ be the Center of\nGravity of the Arch DE, and _q_, _r_, _s_, _t_, _u_, _x_, the Centers of\nGravity of the Arches EF, FG, GA, AB, BC, and CD respectively, and about\nthose Centers of Gravity let Circles proportional to the Number of Rays\nof each Colour in the given Mixture be describ'd: that is, the Circle\n_p_ proportional to the Number of the red-making Rays in the Mixture,\nthe Circle _q_ proportional to the Number of the orange-making Rays in\nthe Mixture, and so of the rest. Find the common Center of Gravity of\nall those Circles, _p_, _q_, _r_, _s_, _t_, _u_, _x_. Let that Center be\nZ; and from the Center of the Circle ADF, through Z to the\nCircumference, drawing the Right Line OY, the Place of the Point Y in\nthe Circumference shall shew the Colour arising from the Composition of\nall the Colours in the given Mixture, and the Line OZ shall be\nproportional to the Fulness or Intenseness of the Colour, that is, to\nits distance from Whiteness. As if Y fall in the middle between F and G,\nthe compounded Colour shall be the best yellow; if Y verge from the\nmiddle towards F or G, the compound Colour shall accordingly be a\nyellow, verging towards orange or green. If Z fall upon the\nCircumference, the Colour shall be intense and florid in the highest\nDegree; if it fall in the mid-way between the Circumference and Center,\nit shall be but half so intense, that is, it shall be such a Colour as\nwould be made by diluting the intensest yellow with an equal quantity of\nwhiteness; and if it fall upon the center O, the Colour shall have lost\nall its intenseness, and become a white. But it is to be noted, That if\nthe point Z fall in or near the line OD, the main ingredients being the\nred and violet, the Colour compounded shall not be any of the prismatick\nColours, but a purple, inclining to red or violet, accordingly as the\npoint Z lieth on the side of the line DO towards E or towards C, and in\ngeneral the compounded violet is more bright and more fiery than the\nuncompounded. Also if only two of the primary Colours which in the\ncircle are opposite to one another be mixed in an equal proportion, the\npoint Z shall fall upon the center O, and yet the Colour compounded of\nthose two shall not be perfectly white, but some faint anonymous Colour.\nFor I could never yet by mixing only two primary Colours produce a\nperfect white. Whether it may be compounded of a mixture of three taken\nat equal distances in the circumference I do not know, but of four or\nfive I do not much question but it may. But these are Curiosities of\nlittle or no moment to the understanding the Phænomena of Nature. For in\nall whites produced by Nature, there uses to be a mixture of all sorts\nof Rays, and by consequence a composition of all Colours.\n\nTo give an instance of this Rule; suppose a Colour is compounded of\nthese homogeneal Colours, of violet one part, of indigo one part, of\nblue two parts, of green three parts, of yellow five parts, of orange\nsix parts, and of red ten parts. Proportional to these parts describe\nthe Circles _x_, _v_, _t_, _s_, _r_, _q_, _p_, respectively, that is, so\nthat if the Circle _x_ be one, the Circle _v_ may be one, the Circle _t_\ntwo, the Circle _s_ three, and the Circles _r_, _q_ and _p_, five, six\nand ten. Then I find Z the common center of gravity of these Circles,\nand through Z drawing the Line OY, the Point Y falls upon the\ncircumference between E and F, something nearer to E than to F, and\nthence I conclude, that the Colour compounded of these Ingredients will\nbe an orange, verging a little more to red than to yellow. Also I find\nthat OZ is a little less than one half of OY, and thence I conclude,\nthat this orange hath a little less than half the fulness or intenseness\nof an uncompounded orange; that is to say, that it is such an orange as\nmay be made by mixing an homogeneal orange with a good white in the\nproportion of the Line OZ to the Line ZY, this Proportion being not of\nthe quantities of mixed orange and white Powders, but of the quantities\nof the Lights reflected from them.\n\nThis Rule I conceive accurate enough for practice, though not\nmathematically accurate; and the truth of it may be sufficiently proved\nto Sense, by stopping any of the Colours at the Lens in the tenth\nExperiment of this Book. For the rest of the Colours which are not\nstopp'd, but pass on to the Focus of the Lens, will there compound\neither accurately or very nearly such a Colour, as by this Rule ought to\nresult from their Mixture.\n\n\n_PROP._ VII. THEOR. V.\n\n_All the Colours in the Universe which are made by Light, and depend not\non the Power of Imagination, are either the Colours of homogeneal\nLights, or compounded of these, and that either accurately or very\nnearly, according to the Rule of the foregoing Problem._\n\nFor it has been proved (in _Prop. 1. Part 2._) that the changes of\nColours made by Refractions do not arise from any new Modifications of\nthe Rays impress'd by those Refractions, and by the various Terminations\nof Light and Shadow, as has been the constant and general Opinion of\nPhilosophers. It has also been proved that the several Colours of the\nhomogeneal Rays do constantly answer to their degrees of Refrangibility,\n(_Prop._ 1. _Part_ 1. and _Prop._ 2. _Part_ 2.) and that their degrees\nof Refrangibility cannot be changed by Refractions and Reflexions\n(_Prop._ 2. _Part_ 1.) and by consequence that those their Colours are\nlikewise immutable. It has also been proved directly by refracting and\nreflecting homogeneal Lights apart, that their Colours cannot be\nchanged, (_Prop._ 2. _Part_ 2.) It has been proved also, that when the\nseveral sorts of Rays are mixed, and in crossing pass through the same\nspace, they do not act on one another so as to change each others\ncolorific qualities. (_Exper._ 10. _Part_ 2.) but by mixing their\nActions in the Sensorium beget a Sensation differing from what either\nwould do apart, that is a Sensation of a mean Colour between their\nproper Colours; and particularly when by the concourse and mixtures of\nall sorts of Rays, a white Colour is produced, the white is a mixture of\nall the Colours which the Rays would have apart, (_Prop._ 5. _Part_ 2.)\nThe Rays in that mixture do not lose or alter their several colorific\nqualities, but by all their various kinds of Actions mix'd in the\nSensorium, beget a Sensation of a middling Colour between all their\nColours, which is whiteness. For whiteness is a mean between all\nColours, having it self indifferently to them all, so as with equal\nfacility to be tinged with any of them. A red Powder mixed with a little\nblue, or a blue with a little red, doth not presently lose its Colour,\nbut a white Powder mix'd with any Colour is presently tinged with that\nColour, and is equally capable of being tinged with any Colour whatever.\nIt has been shewed also, that as the Sun's Light is mix'd of all sorts\nof Rays, so its whiteness is a mixture of the Colours of all sorts of\nRays; those Rays having from the beginning their several colorific\nqualities as well as their several Refrangibilities, and retaining them\nperpetually unchanged notwithstanding any Refractions or Reflexions they\nmay at any time suffer, and that whenever any sort of the Sun's Rays is\nby any means (as by Reflexion in _Exper._ 9, and 10. _Part_ 1. or by\nRefraction as happens in all Refractions) separated from the rest, they\nthen manifest their proper Colours. These things have been prov'd, and\nthe sum of all this amounts to the Proposition here to be proved. For if\nthe Sun's Light is mix'd of several sorts of Rays, each of which have\noriginally their several Refrangibilities and colorific Qualities, and\nnotwithstanding their Refractions and Reflexions, and their various\nSeparations or Mixtures, keep those their original Properties\nperpetually the same without alteration; then all the Colours in the\nWorld must be such as constantly ought to arise from the original\ncolorific qualities of the Rays whereof the Lights consist by which\nthose Colours are seen. And therefore if the reason of any Colour\nwhatever be required, we have nothing else to do than to consider how\nthe Rays in the Sun's Light have by Reflexions or Refractions, or other\ncauses, been parted from one another, or mixed together; or otherwise to\nfind out what sorts of Rays are in the Light by which that Colour is\nmade, and in what Proportion; and then by the last Problem to learn the\nColour which ought to arise by mixing those Rays (or their Colours) in\nthat proportion. I speak here of Colours so far as they arise from\nLight. For they appear sometimes by other Causes, as when by the power\nof Phantasy we see Colours in a Dream, or a Mad-man sees things before\nhim which are not there; or when we see Fire by striking the Eye, or see\nColours like the Eye of a Peacock's Feather, by pressing our Eyes in\neither corner whilst we look the other way. Where these and such like\nCauses interpose not, the Colour always answers to the sort or sorts of\nthe Rays whereof the Light consists, as I have constantly found in\nwhatever Phænomena of Colours I have hitherto been able to examine. I\nshall in the following Propositions give instances of this in the\nPhænomena of chiefest note.\n\n\n_PROP._ VIII. PROB. III.\n\n_By the discovered Properties of Light to explain the Colours made by\nPrisms._\n\nLet ABC [in _Fig._ 12.] represent a Prism refracting the Light of the\nSun, which comes into a dark Chamber through a hole F[Greek: ph] almost\nas broad as the Prism, and let MN represent a white Paper on which the\nrefracted Light is cast, and suppose the most refrangible or deepest\nviolet-making Rays fall upon the Space P[Greek: p], the least\nrefrangible or deepest red-making Rays upon the Space T[Greek: t], the\nmiddle sort between the indigo-making and blue-making Rays upon the\nSpace Q[Greek: ch], the middle sort of the green-making Rays upon the\nSpace R, the middle sort between the yellow-making and orange-making\nRays upon the Space S[Greek: s], and other intermediate sorts upon\nintermediate Spaces. For so the Spaces upon which the several sorts\nadequately fall will by reason of the different Refrangibility of those\nsorts be one lower than another. Now if the Paper MN be so near the\nPrism that the Spaces PT and [Greek: pt] do not interfere with one\nanother, the distance between them T[Greek: p] will be illuminated by\nall the sorts of Rays in that proportion to one another which they have\nat their very first coming out of the Prism, and consequently be white.\nBut the Spaces PT and [Greek: pt] on either hand, will not be\nilluminated by them all, and therefore will appear coloured. And\nparticularly at P, where the outmost violet-making Rays fall alone, the\nColour must be the deepest violet. At Q where the violet-making and\nindigo-making Rays are mixed, it must be a violet inclining much to\nindigo. At R where the violet-making, indigo-making, blue-making, and\none half of the green-making Rays are mixed, their Colours must (by the\nconstruction of the second Problem) compound a middle Colour between\nindigo and blue. At S where all the Rays are mixed, except the\nred-making and orange-making, their Colours ought by the same Rule to\ncompound a faint blue, verging more to green than indigo. And in the\nprogress from S to T, this blue will grow more and more faint and\ndilute, till at T, where all the Colours begin to be mixed, it ends in\nwhiteness.\n\n[Illustration: FIG. 12.]\n\nSo again, on the other side of the white at [Greek: t], where the least\nrefrangible or utmost red-making Rays are alone, the Colour must be the\ndeepest red. At [Greek: s] the mixture of red and orange will compound a\nred inclining to orange. At [Greek: r] the mixture of red, orange,\nyellow, and one half of the green must compound a middle Colour between\norange and yellow. At [Greek: ch] the mixture of all Colours but violet\nand indigo will compound a faint yellow, verging more to green than to\norange. And this yellow will grow more faint and dilute continually in\nits progress from [Greek: ch] to [Greek: p], where by a mixture of all\nsorts of Rays it will become white.\n\nThese Colours ought to appear were the Sun's Light perfectly white: But\nbecause it inclines to yellow, the Excess of the yellow-making Rays\nwhereby 'tis tinged with that Colour, being mixed with the faint blue\nbetween S and T, will draw it to a faint green. And so the Colours in\norder from P to [Greek: t] ought to be violet, indigo, blue, very faint\ngreen, white, faint yellow, orange, red. Thus it is by the computation:\nAnd they that please to view the Colours made by a Prism will find it so\nin Nature.\n\nThese are the Colours on both sides the white when the Paper is held\nbetween the Prism and the Point X where the Colours meet, and the\ninterjacent white vanishes. For if the Paper be held still farther off\nfrom the Prism, the most refrangible and least refrangible Rays will be\nwanting in the middle of the Light, and the rest of the Rays which are\nfound there, will by mixture produce a fuller green than before. Also\nthe yellow and blue will now become less compounded, and by consequence\nmore intense than before. And this also agrees with experience.\n\nAnd if one look through a Prism upon a white Object encompassed with\nblackness or darkness, the reason of the Colours arising on the edges is\nmuch the same, as will appear to one that shall a little consider it. If\na black Object be encompassed with a white one, the Colours which appear\nthrough the Prism are to be derived from the Light of the white one,\nspreading into the Regions of the black, and therefore they appear in a\ncontrary order to that, when a white Object is surrounded with black.\nAnd the same is to be understood when an Object is viewed, whose parts\nare some of them less luminous than others. For in the borders of the\nmore and less luminous Parts, Colours ought always by the same\nPrinciples to arise from the Excess of the Light of the more luminous,\nand to be of the same kind as if the darker parts were black, but yet to\nbe more faint and dilute.\n\nWhat is said of Colours made by Prisms may be easily applied to Colours\nmade by the Glasses of Telescopes or Microscopes, or by the Humours of\nthe Eye. For if the Object-glass of a Telescope be thicker on one side\nthan on the other, or if one half of the Glass, or one half of the Pupil\nof the Eye be cover'd with any opake substance; the Object-glass, or\nthat part of it or of the Eye which is not cover'd, may be consider'd as\na Wedge with crooked Sides, and every Wedge of Glass or other pellucid\nSubstance has the effect of a Prism in refracting the Light which passes\nthrough it.[L]\n\nHow the Colours in the ninth and tenth Experiments of the first Part\narise from the different Reflexibility of Light, is evident by what was\nthere said. But it is observable in the ninth Experiment, that whilst\nthe Sun's direct Light is yellow, the Excess of the blue-making Rays in\nthe reflected beam of Light MN, suffices only to bring that yellow to a\npale white inclining to blue, and not to tinge it with a manifestly blue\nColour. To obtain therefore a better blue, I used instead of the yellow\nLight of the Sun the white Light of the Clouds, by varying a little the\nExperiment, as follows.\n\n[Illustration: FIG. 13.]\n\n_Exper._ 16 Let HFG [in _Fig._ 13.] represent a Prism in the open Air,\nand S the Eye of the Spectator, viewing the Clouds by their Light coming\ninto the Prism at the Plane Side FIGK, and reflected in it by its Base\nHEIG, and thence going out through its Plane Side HEFK to the Eye. And\nwhen the Prism and Eye are conveniently placed, so that the Angles of\nIncidence and Reflexion at the Base may be about 40 Degrees, the\nSpectator will see a Bow MN of a blue Colour, running from one End of\nthe Base to the other, with the Concave Side towards him, and the Part\nof the Base IMNG beyond this Bow will be brighter than the other Part\nEMNH on the other Side of it. This blue Colour MN being made by nothing\nelse than by Reflexion of a specular Superficies, seems so odd a\nPhænomenon, and so difficult to be explained by the vulgar Hypothesis of\nPhilosophers, that I could not but think it deserved to be taken Notice\nof. Now for understanding the Reason of it, suppose the Plane ABC to cut\nthe Plane Sides and Base of the Prism perpendicularly. From the Eye to\nthe Line BC, wherein that Plane cuts the Base, draw the Lines S_p_ and\nS_t_, in the Angles S_pc_ 50 degr. 1/9, and S_tc_ 49 degr. 1/28, and the\nPoint _p_ will be the Limit beyond which none of the most refrangible\nRays can pass through the Base of the Prism, and be refracted, whose\nIncidence is such that they may be reflected to the Eye; and the Point\n_t_ will be the like Limit for the least refrangible Rays, that is,\nbeyond which none of them can pass through the Base, whose Incidence is\nsuch that by Reflexion they may come to the Eye. And the Point _r_ taken\nin the middle Way between _p_ and _t_, will be the like Limit for the\nmeanly refrangible Rays. And therefore all the least refrangible Rays\nwhich fall upon the Base beyond _t_, that is, between _t_ and B, and can\ncome from thence to the Eye, will be reflected thither: But on this side\n_t_, that is, between _t_ and _c_, many of these Rays will be\ntransmitted through the Base. And all the most refrangible Rays which\nfall upon the Base beyond _p_, that is, between, _p_ and B, and can by\nReflexion come from thence to the Eye, will be reflected thither, but\nevery where between _p_ and _c_, many of these Rays will get through the\nBase, and be refracted; and the same is to be understood of the meanly\nrefrangible Rays on either side of the Point _r_. Whence it follows,\nthat the Base of the Prism must every where between _t_ and B, by a\ntotal Reflexion of all sorts of Rays to the Eye, look white and bright.\nAnd every where between _p_ and C, by reason of the Transmission of many\nRays of every sort, look more pale, obscure, and dark. But at _r_, and\nin other Places between _p_ and _t_, where all the more refrangible Rays\nare reflected to the Eye, and many of the less refrangible are\ntransmitted, the Excess of the most refrangible in the reflected Light\nwill tinge that Light with their Colour, which is violet and blue. And\nthis happens by taking the Line C _prt_ B any where between the Ends of\nthe Prism HG and EI.\n\n\n_PROP._ IX. PROB. IV.\n\n_By the discovered Properties of Light to explain the Colours of the\nRain-bow._\n\n[Illustration: FIG. 14.]\n\nThis Bow never appears, but where it rains in the Sun-shine, and may be\nmade artificially by spouting up Water which may break aloft, and\nscatter into Drops, and fall down like Rain. For the Sun shining upon\nthese Drops certainly causes the Bow to appear to a Spectator standing\nin a due Position to the Rain and Sun. And hence it is now agreed upon,\nthat this Bow is made by Refraction of the Sun's Light in drops of\nfalling Rain. This was understood by some of the Antients, and of late\nmore fully discover'd and explain'd by the famous _Antonius de Dominis_\nArchbishop of _Spalato_, in his book _De Radiis Visûs & Lucis_,\npublished by his Friend _Bartolus_ at _Venice_, in the Year 1611, and\nwritten above 20 Years before. For he teaches there how the interior Bow\nis made in round Drops of Rain by two Refractions of the Sun's Light,\nand one Reflexion between them, and the exterior by two Refractions, and\ntwo sorts of Reflexions between them in each Drop of Water, and proves\nhis Explications by Experiments made with a Phial full of Water, and\nwith Globes of Glass filled with Water, and placed in the Sun to make\nthe Colours of the two Bows appear in them. The same Explication\n_Des-Cartes_ hath pursued in his Meteors, and mended that of the\nexterior Bow. But whilst they understood not the true Origin of Colours,\nit's necessary to pursue it here a little farther. For understanding\ntherefore how the Bow is made, let a Drop of Rain, or any other\nspherical transparent Body be represented by the Sphere BNFG, [in _Fig._\n14.] described with the Center C, and Semi-diameter CN. And let AN be\none of the Sun's Rays incident upon it at N, and thence refracted to F,\nwhere let it either go out of the Sphere by Refraction towards V, or be\nreflected to G; and at G let it either go out by Refraction to R, or be\nreflected to H; and at H let it go out by Refraction towards S, cutting\nthe incident Ray in Y. Produce AN and RG, till they meet in X, and upon\nAX and NF, let fall the Perpendiculars CD and CE, and produce CD till it\nfall upon the Circumference at L. Parallel to the incident Ray AN draw\nthe Diameter BQ, and let the Sine of Incidence out of Air into Water be\nto the Sine of Refraction as I to R. Now, if you suppose the Point of\nIncidence N to move from the Point B, continually till it come to L, the\nArch QF will first increase and then decrease, and so will the Angle AXR\nwhich the Rays AN and GR contain; and the Arch QF and Angle AXR will be\nbiggest when ND is to CN as sqrt(II - RR) to sqrt(3)RR, in which\ncase NE will be to ND as 2R to I. Also the Angle AYS, which the Rays AN\nand HS contain will first decrease, and then increase and grow least\nwhen ND is to CN as sqrt(II - RR) to sqrt(8)RR, in which case NE\nwill be to ND, as 3R to I. And so the Angle which the next emergent Ray\n(that is, the emergent Ray after three Reflexions) contains with the\nincident Ray AN will come to its Limit when ND is to CN as sqrt(II -\nRR) to sqrt(15)RR, in which case NE will be to ND as 4R to I. And the\nAngle which the Ray next after that Emergent, that is, the Ray emergent\nafter four Reflexions, contains with the Incident, will come to its\nLimit, when ND is to CN as sqrt(II - RR) to sqrt(24)RR, in which\ncase NE will be to ND as 5R to I; and so on infinitely, the Numbers 3,\n8, 15, 24, &c. being gather'd by continual Addition of the Terms of the\narithmetical Progression 3, 5, 7, 9, &c. The Truth of all this\nMathematicians will easily examine.[M]\n\nNow it is to be observed, that as when the Sun comes to his Tropicks,\nDays increase and decrease but a very little for a great while together;\nso when by increasing the distance CD, these Angles come to their\nLimits, they vary their quantity but very little for some time together,\nand therefore a far greater number of the Rays which fall upon all the\nPoints N in the Quadrant BL, shall emerge in the Limits of these Angles,\nthan in any other Inclinations. And farther it is to be observed, that\nthe Rays which differ in Refrangibility will have different Limits of\ntheir Angles of Emergence, and by consequence according to their\ndifferent Degrees of Refrangibility emerge most copiously in different\nAngles, and being separated from one another appear each in their proper\nColours. And what those Angles are may be easily gather'd from the\nforegoing Theorem by Computation.\n\nFor in the least refrangible Rays the Sines I and R (as was found above)\nare 108 and 81, and thence by Computation the greatest Angle AXR will be\nfound 42 Degrees and 2 Minutes, and the least Angle AYS, 50 Degrees and\n57 Minutes. And in the most refrangible Rays the Sines I and R are 109\nand 81, and thence by Computation the greatest Angle AXR will be found\n40 Degrees and 17 Minutes, and the least Angle AYS 54 Degrees and 7\nMinutes.\n\nSuppose now that O [in _Fig._ 15.] is the Spectator's Eye, and OP a Line\ndrawn parallel to the Sun's Rays and let POE, POF, POG, POH, be Angles\nof 40 Degr. 17 Min. 42 Degr. 2 Min. 50 Degr. 57 Min. and 54 Degr. 7 Min.\nrespectively, and these Angles turned about their common Side OP, shall\nwith their other Sides OE, OF; OG, OH, describe the Verges of two\nRain-bows AF, BE and CHDG. For if E, F, G, H, be drops placed any where\nin the conical Superficies described by OE, OF, OG, OH, and be\nilluminated by the Sun's Rays SE, SF, SG, SH; the Angle SEO being equal\nto the Angle POE, or 40 Degr. 17 Min. shall be the greatest Angle in\nwhich the most refrangible Rays can after one Reflexion be refracted to\nthe Eye, and therefore all the Drops in the Line OE shall send the most\nrefrangible Rays most copiously to the Eye, and thereby strike the\nSenses with the deepest violet Colour in that Region. And in like\nmanner the Angle SFO being equal to the Angle POF, or 42 Degr. 2 Min.\nshall be the greatest in which the least refrangible Rays after one\nReflexion can emerge out of the Drops, and therefore those Rays shall\ncome most copiously to the Eye from the Drops in the Line OF, and strike\nthe Senses with the deepest red Colour in that Region. And by the same\nArgument, the Rays which have intermediate Degrees of Refrangibility\nshall come most copiously from Drops between E and F, and strike the\nSenses with the intermediate Colours, in the Order which their Degrees\nof Refrangibility require, that is in the Progress from E to F, or from\nthe inside of the Bow to the outside in this order, violet, indigo,\nblue, green, yellow, orange, red. But the violet, by the mixture of the\nwhite Light of the Clouds, will appear faint and incline to purple.\n\n[Illustration: FIG. 15.]\n\nAgain, the Angle SGO being equal to the Angle POG, or 50 Gr. 51 Min.\nshall be the least Angle in which the least refrangible Rays can after\ntwo Reflexions emerge out of the Drops, and therefore the least\nrefrangible Rays shall come most copiously to the Eye from the Drops in\nthe Line OG, and strike the Sense with the deepest red in that Region.\nAnd the Angle SHO being equal to the Angle POH, or 54 Gr. 7 Min. shall\nbe the least Angle, in which the most refrangible Rays after two\nReflexions can emerge out of the Drops; and therefore those Rays shall\ncome most copiously to the Eye from the Drops in the Line OH, and strike\nthe Senses with the deepest violet in that Region. And by the same\nArgument, the Drops in the Regions between G and H shall strike the\nSense with the intermediate Colours in the Order which their Degrees of\nRefrangibility require, that is, in the Progress from G to H, or from\nthe inside of the Bow to the outside in this order, red, orange, yellow,\ngreen, blue, indigo, violet. And since these four Lines OE, OF, OG, OH,\nmay be situated any where in the above-mention'd conical Superficies;\nwhat is said of the Drops and Colours in these Lines is to be understood\nof the Drops and Colours every where in those Superficies.\n\nThus shall there be made two Bows of Colours, an interior and stronger,\nby one Reflexion in the Drops, and an exterior and fainter by two; for\nthe Light becomes fainter by every Reflexion. And their Colours shall\nlie in a contrary Order to one another, the red of both Bows bordering\nupon the Space GF, which is between the Bows. The Breadth of the\ninterior Bow EOF measured cross the Colours shall be 1 Degr. 45 Min. and\nthe Breadth of the exterior GOH shall be 3 Degr. 10 Min. and the\ndistance between them GOF shall be 8 Gr. 15 Min. the greatest\nSemi-diameter of the innermost, that is, the Angle POF being 42 Gr. 2\nMin. and the least Semi-diameter of the outermost POG, being 50 Gr. 57\nMin. These are the Measures of the Bows, as they would be were the Sun\nbut a Point; for by the Breadth of his Body, the Breadth of the Bows\nwill be increased, and their Distance decreased by half a Degree, and so\nthe breadth of the interior Iris will be 2 Degr. 15 Min. that of the\nexterior 3 Degr. 40 Min. their distance 8 Degr. 25 Min. the greatest\nSemi-diameter of the interior Bow 42 Degr. 17 Min. and the least of the\nexterior 50 Degr. 42 Min. And such are the Dimensions of the Bows in the\nHeavens found to be very nearly, when their Colours appear strong and\nperfect. For once, by such means as I then had, I measured the greatest\nSemi-diameter of the interior Iris about 42 Degrees, and the breadth of\nthe red, yellow and green in that Iris 63 or 64 Minutes, besides the\noutmost faint red obscured by the brightness of the Clouds, for which we\nmay allow 3 or 4 Minutes more. The breadth of the blue was about 40\nMinutes more besides the violet, which was so much obscured by the\nbrightness of the Clouds, that I could not measure its breadth. But\nsupposing the breadth of the blue and violet together to equal that of\nthe red, yellow and green together, the whole breadth of this Iris will\nbe about 2-1/4 Degrees, as above. The least distance between this Iris\nand the exterior Iris was about 8 Degrees and 30 Minutes. The exterior\nIris was broader than the interior, but so faint, especially on the blue\nside, that I could not measure its breadth distinctly. At another time\nwhen both Bows appeared more distinct, I measured the breadth of the\ninterior Iris 2 Gr. 10´, and the breadth of the red, yellow and green in\nthe exterior Iris, was to the breadth of the same Colours in the\ninterior as 3 to 2.\n\nThis Explication of the Rain-bow is yet farther confirmed by the known\nExperiment (made by _Antonius de Dominis_ and _Des-Cartes_) of hanging\nup any where in the Sun-shine a Glass Globe filled with Water, and\nviewing it in such a posture, that the Rays which come from the Globe to\nthe Eye may contain with the Sun's Rays an Angle of either 42 or 50\nDegrees. For if the Angle be about 42 or 43 Degrees, the Spectator\n(suppose at O) shall see a full red Colour in that side of the Globe\nopposed to the Sun as 'tis represented at F, and if that Angle become\nless (suppose by depressing the Globe to E) there will appear other\nColours, yellow, green and blue successive in the same side of the\nGlobe. But if the Angle be made about 50 Degrees (suppose by lifting up\nthe Globe to G) there will appear a red Colour in that side of the Globe\ntowards the Sun, and if the Angle be made greater (suppose by lifting\nup the Globe to H) the red will turn successively to the other Colours,\nyellow, green and blue. The same thing I have tried, by letting a Globe\nrest, and raising or depressing the Eye, or otherwise moving it to make\nthe Angle of a just magnitude.\n\nI have heard it represented, that if the Light of a Candle be refracted\nby a Prism to the Eye; when the blue Colour falls upon the Eye, the\nSpectator shall see red in the Prism, and when the red falls upon the\nEye he shall see blue; and if this were certain, the Colours of the\nGlobe and Rain-bow ought to appear in a contrary order to what we find.\nBut the Colours of the Candle being very faint, the mistake seems to\narise from the difficulty of discerning what Colours fall on the Eye.\nFor, on the contrary, I have sometimes had occasion to observe in the\nSun's Light refracted by a Prism, that the Spectator always sees that\nColour in the Prism which falls upon his Eye. And the same I have found\ntrue also in Candle-light. For when the Prism is moved slowly from the\nLine which is drawn directly from the Candle to the Eye, the red appears\nfirst in the Prism and then the blue, and therefore each of them is seen\nwhen it falls upon the Eye. For the red passes over the Eye first, and\nthen the blue.\n\nThe Light which comes through drops of Rain by two Refractions without\nany Reflexion, ought to appear strongest at the distance of about 26\nDegrees from the Sun, and to decay gradually both ways as the distance\nfrom him increases and decreases. And the same is to be understood of\nLight transmitted through spherical Hail-stones. And if the Hail be a\nlittle flatted, as it often is, the Light transmitted may grow so strong\nat a little less distance than that of 26 Degrees, as to form a Halo\nabout the Sun or Moon; which Halo, as often as the Hail-stones are duly\nfigured may be colour'd, and then it must be red within by the least\nrefrangible Rays, and blue without by the most refrangible ones,\nespecially if the Hail-stones have opake Globules of Snow in their\ncenter to intercept the Light within the Halo (as _Hugenius_ has\nobserv'd) and make the inside thereof more distinctly defined than it\nwould otherwise be. For such Hail-stones, though spherical, by\nterminating the Light by the Snow, may make a Halo red within and\ncolourless without, and darker in the red than without, as Halos used to\nbe. For of those Rays which pass close by the Snow the Rubriform will be\nleast refracted, and so come to the Eye in the directest Lines.\n\nThe Light which passes through a drop of Rain after two Refractions, and\nthree or more Reflexions, is scarce strong enough to cause a sensible\nBow; but in those Cylinders of Ice by which _Hugenius_ explains the\n_Parhelia_, it may perhaps be sensible.\n\n\n_PROP._ X. PROB. V.\n\n_By the discovered Properties of Light to explain the permanent Colours\nof Natural Bodies._\n\nThese Colours arise from hence, that some natural Bodies reflect some\nsorts of Rays, others other sorts more copiously than the rest. Minium\nreflects the least refrangible or red-making Rays most copiously, and\nthence appears red. Violets reflect the most refrangible most copiously,\nand thence have their Colour, and so of other Bodies. Every Body\nreflects the Rays of its own Colour more copiously than the rest, and\nfrom their excess and predominance in the reflected Light has its\nColour.\n\n_Exper._ 17. For if in the homogeneal Lights obtained by the solution of\nthe Problem proposed in the fourth Proposition of the first Part of this\nBook, you place Bodies of several Colours, you will find, as I have\ndone, that every Body looks most splendid and luminous in the Light of\nits own Colour. Cinnaber in the homogeneal red Light is most\nresplendent, in the green Light it is manifestly less resplendent, and\nin the blue Light still less. Indigo in the violet blue Light is most\nresplendent, and its splendor is gradually diminish'd, as it is removed\nthence by degrees through the green and yellow Light to the red. By a\nLeek the green Light, and next that the blue and yellow which compound\ngreen, are more strongly reflected than the other Colours red and\nviolet, and so of the rest. But to make these Experiments the more\nmanifest, such Bodies ought to be chosen as have the fullest and most\nvivid Colours, and two of those Bodies are to be compared together.\nThus, for instance, if Cinnaber and _ultra_-marine blue, or some other\nfull blue be held together in the red homogeneal Light, they will both\nappear red, but the Cinnaber will appear of a strongly luminous and\nresplendent red, and the _ultra_-marine blue of a faint obscure and dark\nred; and if they be held together in the blue homogeneal Light, they\nwill both appear blue, but the _ultra_-marine will appear of a strongly\nluminous and resplendent blue, and the Cinnaber of a faint and dark\nblue. Which puts it out of dispute that the Cinnaber reflects the red\nLight much more copiously than the _ultra_-marine doth, and the\n_ultra_-marine reflects the blue Light much more copiously than the\nCinnaber doth. The same Experiment may be tried successfully with red\nLead and Indigo, or with any other two colour'd Bodies, if due allowance\nbe made for the different strength or weakness of their Colour and\nLight.\n\nAnd as the reason of the Colours of natural Bodies is evident by these\nExperiments, so it is farther confirmed and put past dispute by the two\nfirst Experiments of the first Part, whereby 'twas proved in such Bodies\nthat the reflected Lights which differ in Colours do differ also in\ndegrees of Refrangibility. For thence it's certain, that some Bodies\nreflect the more refrangible, others the less refrangible Rays more\ncopiously.\n\nAnd that this is not only a true reason of these Colours, but even the\nonly reason, may appear farther from this Consideration, that the Colour\nof homogeneal Light cannot be changed by the Reflexion of natural\nBodies.\n\nFor if Bodies by Reflexion cannot in the least change the Colour of any\none sort of Rays, they cannot appear colour'd by any other means than by\nreflecting those which either are of their own Colour, or which by\nmixture must produce it.\n\nBut in trying Experiments of this kind care must be had that the Light\nbe sufficiently homogeneal. For if Bodies be illuminated by the ordinary\nprismatick Colours, they will appear neither of their own Day-light\nColours, nor of the Colour of the Light cast on them, but of some middle\nColour between both, as I have found by Experience. Thus red Lead (for\ninstance) illuminated with the ordinary prismatick green will not appear\neither red or green, but orange or yellow, or between yellow and green,\naccordingly as the green Light by which 'tis illuminated is more or less\ncompounded. For because red Lead appears red when illuminated with white\nLight, wherein all sorts of Rays are equally mix'd, and in the green\nLight all sorts of Rays are not equally mix'd, the Excess of the\nyellow-making, green-making and blue-making Rays in the incident green\nLight, will cause those Rays to abound so much in the reflected Light,\nas to draw the Colour from red towards their Colour. And because the red\nLead reflects the red-making Rays most copiously in proportion to their\nnumber, and next after them the orange-making and yellow-making Rays;\nthese Rays in the reflected Light will be more in proportion to the\nLight than they were in the incident green Light, and thereby will draw\nthe reflected Light from green towards their Colour. And therefore the\nred Lead will appear neither red nor green, but of a Colour between\nboth.\n\nIn transparently colour'd Liquors 'tis observable, that their Colour\nuses to vary with their thickness. Thus, for instance, a red Liquor in a\nconical Glass held between the Light and the Eye, looks of a pale and\ndilute yellow at the bottom where 'tis thin, and a little higher where\n'tis thicker grows orange, and where 'tis still thicker becomes red, and\nwhere 'tis thickest the red is deepest and darkest. For it is to be\nconceiv'd that such a Liquor stops the indigo-making and violet-making\nRays most easily, the blue-making Rays more difficultly, the\ngreen-making Rays still more difficultly, and the red-making most\ndifficultly: And that if the thickness of the Liquor be only so much as\nsuffices to stop a competent number of the violet-making and\nindigo-making Rays, without diminishing much the number of the rest, the\nrest must (by _Prop._ 6. _Part_ 2.) compound a pale yellow. But if the\nLiquor be so much thicker as to stop also a great number of the\nblue-making Rays, and some of the green-making, the rest must compound\nan orange; and where it is so thick as to stop also a great number of\nthe green-making and a considerable number of the yellow-making, the\nrest must begin to compound a red, and this red must grow deeper and\ndarker as the yellow-making and orange-making Rays are more and more\nstopp'd by increasing the thickness of the Liquor, so that few Rays\nbesides the red-making can get through.\n\nOf this kind is an Experiment lately related to me by Mr. _Halley_, who,\nin diving deep into the Sea in a diving Vessel, found in a clear\nSun-shine Day, that when he was sunk many Fathoms deep into the Water\nthe upper part of his Hand on which the Sun shone directly through the\nWater and through a small Glass Window in the Vessel appeared of a red\nColour, like that of a Damask Rose, and the Water below and the under\npart of his Hand illuminated by Light reflected from the Water below\nlook'd green. For thence it may be gather'd, that the Sea-Water reflects\nback the violet and blue-making Rays most easily, and lets the\nred-making Rays pass most freely and copiously to great Depths. For\nthereby the Sun's direct Light at all great Depths, by reason of the\npredominating red-making Rays, must appear red; and the greater the\nDepth is, the fuller and intenser must that red be. And at such Depths\nas the violet-making Rays scarce penetrate unto, the blue-making,\ngreen-making, and yellow-making Rays being reflected from below more\ncopiously than the red-making ones, must compound a green.\n\nNow, if there be two Liquors of full Colours, suppose a red and blue,\nand both of them so thick as suffices to make their Colours sufficiently\nfull; though either Liquor be sufficiently transparent apart, yet will\nyou not be able to see through both together. For, if only the\nred-making Rays pass through one Liquor, and only the blue-making\nthrough the other, no Rays can pass through both. This Mr. _Hook_ tried\ncasually with Glass Wedges filled with red and blue Liquors, and was\nsurprized at the unexpected Event, the reason of it being then unknown;\nwhich makes me trust the more to his Experiment, though I have not tried\nit my self. But he that would repeat it, must take care the Liquors be\nof very good and full Colours.\n\nNow, whilst Bodies become coloured by reflecting or transmitting this or\nthat sort of Rays more copiously than the rest, it is to be conceived\nthat they stop and stifle in themselves the Rays which they do not\nreflect or transmit. For, if Gold be foliated and held between your Eye\nand the Light, the Light looks of a greenish blue, and therefore massy\nGold lets into its Body the blue-making Rays to be reflected to and fro\nwithin it till they be stopp'd and stifled, whilst it reflects the\nyellow-making outwards, and thereby looks yellow. And much after the\nsame manner that Leaf Gold is yellow by reflected, and blue by\ntransmitted Light, and massy Gold is yellow in all Positions of the Eye;\nthere are some Liquors, as the Tincture of _Lignum Nephriticum_, and\nsome sorts of Glass which transmit one sort of Light most copiously, and\nreflect another sort, and thereby look of several Colours, according to\nthe Position of the Eye to the Light. But, if these Liquors or Glasses\nwere so thick and massy that no Light could get through them, I question\nnot but they would like all other opake Bodies appear of one and the\nsame Colour in all Positions of the Eye, though this I cannot yet affirm\nby Experience. For all colour'd Bodies, so far as my Observation\nreaches, may be seen through if made sufficiently thin, and therefore\nare in some measure transparent, and differ only in degrees of\nTransparency from tinged transparent Liquors; these Liquors, as well as\nthose Bodies, by a sufficient Thickness becoming opake. A transparent\nBody which looks of any Colour by transmitted Light, may also look of\nthe same Colour by reflected Light, the Light of that Colour being\nreflected by the farther Surface of the Body, or by the Air beyond it.\nAnd then the reflected Colour will be diminished, and perhaps cease, by\nmaking the Body very thick, and pitching it on the backside to diminish\nthe Reflexion of its farther Surface, so that the Light reflected from\nthe tinging Particles may predominate. In such Cases, the Colour of the\nreflected Light will be apt to vary from that of the Light transmitted.\nBut whence it is that tinged Bodies and Liquors reflect some sort of\nRays, and intromit or transmit other sorts, shall be said in the next\nBook. In this Proposition I content my self to have put it past dispute,\nthat Bodies have such Properties, and thence appear colour'd.\n\n\n_PROP._ XI. PROB. VI.\n\n_By mixing colour'd Lights to compound a beam of Light of the same\nColour and Nature with a beam of the Sun's direct Light, and therein to\nexperience the Truth of the foregoing Propositions._\n\n[Illustration: FIG. 16.]\n\nLet ABC _abc_ [in _Fig._ 16.] represent a Prism, by which the Sun's\nLight let into a dark Chamber through the Hole F, may be refracted\ntowards the Lens MN, and paint upon it at _p_, _q_, _r_, _s_, and _t_,\nthe usual Colours violet, blue, green, yellow, and red, and let the\ndiverging Rays by the Refraction of this Lens converge again towards X,\nand there, by the mixture of all those their Colours, compound a white\naccording to what was shewn above. Then let another Prism DEG _deg_,\nparallel to the former, be placed at X, to refract that white Light\nupwards towards Y. Let the refracting Angles of the Prisms, and their\ndistances from the Lens be equal, so that the Rays which converged from\nthe Lens towards X, and without Refraction, would there have crossed and\ndiverged again, may by the Refraction of the second Prism be reduced\ninto Parallelism and diverge no more. For then those Rays will recompose\na beam of white Light XY. If the refracting Angle of either Prism be the\nbigger, that Prism must be so much the nearer to the Lens. You will know\nwhen the Prisms and the Lens are well set together, by observing if the\nbeam of Light XY, which comes out of the second Prism be perfectly white\nto the very edges of the Light, and at all distances from the Prism\ncontinue perfectly and totally white like a beam of the Sun's Light. For\ntill this happens, the Position of the Prisms and Lens to one another\nmust be corrected; and then if by the help of a long beam of Wood, as is\nrepresented in the Figure, or by a Tube, or some other such Instrument,\nmade for that Purpose, they be made fast in that Situation, you may try\nall the same Experiments in this compounded beam of Light XY, which have\nbeen made in the Sun's direct Light. For this compounded beam of Light\nhas the same appearance, and is endow'd with all the same Properties\nwith a direct beam of the Sun's Light, so far as my Observation reaches.\nAnd in trying Experiments in this beam you may by stopping any of the\nColours, _p_, _q_, _r_, _s_, and _t_, at the Lens, see how the Colours\nproduced in the Experiments are no other than those which the Rays had\nat the Lens before they entered the Composition of this Beam: And by\nconsequence, that they arise not from any new Modifications of the Light\nby Refractions and Reflexions, but from the various Separations and\nMixtures of the Rays originally endow'd with their colour-making\nQualities.\n\nSo, for instance, having with a Lens 4-1/4 Inches broad, and two Prisms\non either hand 6-1/4 Feet distant from the Lens, made such a beam of\ncompounded Light; to examine the reason of the Colours made by Prisms, I\nrefracted this compounded beam of Light XY with another Prism HIK _kh_,\nand thereby cast the usual Prismatick Colours PQRST upon the Paper LV\nplaced behind. And then by stopping any of the Colours _p_, _q_, _r_,\n_s_, _t_, at the Lens, I found that the same Colour would vanish at the\nPaper. So if the Purple _p_ was stopp'd at the Lens, the Purple P upon\nthe Paper would vanish, and the rest of the Colours would remain\nunalter'd, unless perhaps the blue, so far as some purple latent in it\nat the Lens might be separated from it by the following Refractions. And\nso by intercepting the green upon the Lens, the green R upon the Paper\nwould vanish, and so of the rest; which plainly shews, that as the white\nbeam of Light XY was compounded of several Lights variously colour'd at\nthe Lens, so the Colours which afterwards emerge out of it by new\nRefractions are no other than those of which its Whiteness was\ncompounded. The Refraction of the Prism HIK _kh_ generates the Colours\nPQRST upon the Paper, not by changing the colorific Qualities of the\nRays, but by separating the Rays which had the very same colorific\nQualities before they enter'd the Composition of the refracted beam of\nwhite Light XY. For otherwise the Rays which were of one Colour at the\nLens might be of another upon the Paper, contrary to what we find.\n\nSo again, to examine the reason of the Colours of natural Bodies, I\nplaced such Bodies in the Beam of Light XY, and found that they all\nappeared there of those their own Colours which they have in Day-light,\nand that those Colours depend upon the Rays which had the same Colours\nat the Lens before they enter'd the Composition of that beam. Thus, for\ninstance, Cinnaber illuminated by this beam appears of the same red\nColour as in Day-light; and if at the Lens you intercept the\ngreen-making and blue-making Rays, its redness will become more full and\nlively: But if you there intercept the red-making Rays, it will not any\nlonger appear red, but become yellow or green, or of some other Colour,\naccording to the sorts of Rays which you do not intercept. So Gold in\nthis Light XY appears of the same yellow Colour as in Day-light, but by\nintercepting at the Lens a due Quantity of the yellow-making Rays it\nwill appear white like Silver (as I have tried) which shews that its\nyellowness arises from the Excess of the intercepted Rays tinging that\nWhiteness with their Colour when they are let pass. So the Infusion of\n_Lignum Nephriticum_ (as I have also tried) when held in this beam of\nLight XY, looks blue by the reflected Part of the Light, and red by the\ntransmitted Part of it, as when 'tis view'd in Day-light; but if you\nintercept the blue at the Lens the Infusion will lose its reflected blue\nColour, whilst its transmitted red remains perfect, and by the loss of\nsome blue-making Rays, wherewith it was allay'd, becomes more intense\nand full. And, on the contrary, if the red and orange-making Rays be\nintercepted at the Lens, the Infusion will lose its transmitted red,\nwhilst its blue will remain and become more full and perfect. Which\nshews, that the Infusion does not tinge the Rays with blue and red, but\nonly transmits those most copiously which were red-making before, and\nreflects those most copiously which were blue-making before. And after\nthe same manner may the Reasons of other Phænomena be examined, by\ntrying them in this artificial beam of Light XY.\n\nFOOTNOTES:\n\n[I] See p. 59.\n\n[J] _See our_ Author's Lect. Optic. _Part_ II. _Sect._ II. _p._ 239.\n\n[K] _As is done in our_ Author's Lect. Optic. _Part_ I. _Sect._ III.\n_and_ IV. _and Part_ II. _Sect._ II.\n\n[L] _See our_ Author's Lect. Optic. _Part_ II. _Sect._ II. _pag._ 269,\n&c.\n\n[M] _This is demonstrated in our_ Author's Lect. Optic. _Part_ I.\n_Sect._ IV. _Prop._ 35 _and_ 36.\n\n\n\n\nTHE\n\nSECOND BOOK\n\nOF\n\nOPTICKS\n\n\n\n\n_PART I._\n\n_Observations concerning the Reflexions, Refractions, and Colours of\nthin transparent Bodies._\n\n\nIt has been observed by others, that transparent Substances, as Glass,\nWater, Air, &c. when made very thin by being blown into Bubbles, or\notherwise formed into Plates, do exhibit various Colours according to\ntheir various thinness, altho' at a greater thickness they appear very\nclear and colourless. In the former Book I forbore to treat of these\nColours, because they seemed of a more difficult Consideration, and were\nnot necessary for establishing the Properties of Light there discoursed\nof. But because they may conduce to farther Discoveries for compleating\nthe Theory of Light, especially as to the constitution of the parts of\nnatural Bodies, on which their Colours or Transparency depend; I have\nhere set down an account of them. To render this Discourse short and\ndistinct, I have first described the principal of my Observations, and\nthen consider'd and made use of them. The Observations are these.\n\n_Obs._ 1. Compressing two Prisms hard together that their sides (which\nby chance were a very little convex) might somewhere touch one another:\nI found the place in which they touched to become absolutely\ntransparent, as if they had there been one continued piece of Glass. For\nwhen the Light fell so obliquely on the Air, which in other places was\nbetween them, as to be all reflected; it seemed in that place of contact\nto be wholly transmitted, insomuch that when look'd upon, it appeared\nlike a black or dark spot, by reason that little or no sensible Light\nwas reflected from thence, as from other places; and when looked through\nit seemed (as it were) a hole in that Air which was formed into a thin\nPlate, by being compress'd between the Glasses. And through this hole\nObjects that were beyond might be seen distinctly, which could not at\nall be seen through other parts of the Glasses where the Air was\ninterjacent. Although the Glasses were a little convex, yet this\ntransparent spot was of a considerable breadth, which breadth seemed\nprincipally to proceed from the yielding inwards of the parts of the\nGlasses, by reason of their mutual pressure. For by pressing them very\nhard together it would become much broader than otherwise.\n\n_Obs._ 2. When the Plate of Air, by turning the Prisms about their\ncommon Axis, became so little inclined to the incident Rays, that some\nof them began to be transmitted, there arose in it many slender Arcs of\nColours which at first were shaped almost like the Conchoid, as you see\nthem delineated in the first Figure. And by continuing the Motion of the\nPrisms, these Arcs increased and bended more and more about the said\ntransparent spot, till they were compleated into Circles or Rings\nincompassing it, and afterwards continually grew more and more\ncontracted.\n\n[Illustration: FIG. 1.]\n\nThese Arcs at their first appearance were of a violet and blue Colour,\nand between them were white Arcs of Circles, which presently by\ncontinuing the Motion of the Prisms became a little tinged in their\ninward Limbs with red and yellow, and to their outward Limbs the blue\nwas adjacent. So that the order of these Colours from the central dark\nspot, was at that time white, blue, violet; black, red, orange, yellow,\nwhite, blue, violet, &c. But the yellow and red were much fainter than\nthe blue and violet.\n\nThe Motion of the Prisms about their Axis being continued, these Colours\ncontracted more and more, shrinking towards the whiteness on either\nside of it, until they totally vanished into it. And then the Circles in\nthose parts appear'd black and white, without any other Colours\nintermix'd. But by farther moving the Prisms about, the Colours again\nemerged out of the whiteness, the violet and blue at its inward Limb,\nand at its outward Limb the red and yellow. So that now their order from\nthe central Spot was white, yellow, red; black; violet, blue, white,\nyellow, red, &c. contrary to what it was before.\n\n_Obs._ 3. When the Rings or some parts of them appeared only black and\nwhite, they were very distinct and well defined, and the blackness\nseemed as intense as that of the central Spot. Also in the Borders of\nthe Rings, where the Colours began to emerge out of the whiteness, they\nwere pretty distinct, which made them visible to a very great multitude.\nI have sometimes number'd above thirty Successions (reckoning every\nblack and white Ring for one Succession) and seen more of them, which by\nreason of their smalness I could not number. But in other Positions of\nthe Prisms, at which the Rings appeared of many Colours, I could not\ndistinguish above eight or nine of them, and the Exterior of those were\nvery confused and dilute.\n\nIn these two Observations to see the Rings distinct, and without any\nother Colour than Black and white, I found it necessary to hold my Eye\nat a good distance from them. For by approaching nearer, although in the\nsame inclination of my Eye to the Plane of the Rings, there emerged a\nbluish Colour out of the white, which by dilating it self more and more\ninto the black, render'd the Circles less distinct, and left the white a\nlittle tinged with red and yellow. I found also by looking through a\nslit or oblong hole, which was narrower than the pupil of my Eye, and\nheld close to it parallel to the Prisms, I could see the Circles much\ndistincter and visible to a far greater number than otherwise.\n\n_Obs._ 4. To observe more nicely the order of the Colours which arose\nout of the white Circles as the Rays became less and less inclined to\nthe Plate of Air; I took two Object-glasses, the one a Plano-convex for\na fourteen Foot Telescope, and the other a large double Convex for one\nof about fifty Foot; and upon this, laying the other with its plane side\ndownwards, I pressed them slowly together, to make the Colours\nsuccessively emerge in the middle of the Circles, and then slowly lifted\nthe upper Glass from the lower to make them successively vanish again in\nthe same place. The Colour, which by pressing the Glasses together,\nemerged last in the middle of the other Colours, would upon its first\nappearance look like a Circle of a Colour almost uniform from the\ncircumference to the center and by compressing the Glasses still more,\ngrow continually broader until a new Colour emerged in its center, and\nthereby it became a Ring encompassing that new Colour. And by\ncompressing the Glasses still more, the diameter of this Ring would\nincrease, and the breadth of its Orbit or Perimeter decrease until\nanother new Colour emerged in the center of the last: And so on until a\nthird, a fourth, a fifth, and other following new Colours successively\nemerged there, and became Rings encompassing the innermost Colour, the\nlast of which was the black Spot. And, on the contrary, by lifting up\nthe upper Glass from the lower, the diameter of the Rings would\ndecrease, and the breadth of their Orbit increase, until their Colours\nreached successively to the center; and then they being of a\nconsiderable breadth, I could more easily discern and distinguish their\nSpecies than before. And by this means I observ'd their Succession and\nQuantity to be as followeth.\n\nNext to the pellucid central Spot made by the contact of the Glasses\nsucceeded blue, white, yellow, and red. The blue was so little in\nquantity, that I could not discern it in the Circles made by the Prisms,\nnor could I well distinguish any violet in it, but the yellow and red\nwere pretty copious, and seemed about as much in extent as the white,\nand four or five times more than the blue. The next Circuit in order of\nColours immediately encompassing these were violet, blue, green, yellow,\nand red: and these were all of them copious and vivid, excepting the\ngreen, which was very little in quantity, and seemed much more faint and\ndilute than the other Colours. Of the other four, the violet was the\nleast in extent, and the blue less than the yellow or red. The third\nCircuit or Order was purple, blue, green, yellow, and red; in which the\npurple seemed more reddish than the violet in the former Circuit, and\nthe green was much more conspicuous, being as brisk and copious as any\nof the other Colours, except the yellow, but the red began to be a\nlittle faded, inclining very much to purple. After this succeeded the\nfourth Circuit of green and red. The green was very copious and lively,\ninclining on the one side to blue, and on the other side to yellow. But\nin this fourth Circuit there was neither violet, blue, nor yellow, and\nthe red was very imperfect and dirty. Also the succeeding Colours became\nmore and more imperfect and dilute, till after three or four revolutions\nthey ended in perfect whiteness. Their form, when the Glasses were most\ncompress'd so as to make the black Spot appear in the center, is\ndelineated in the second Figure; where _a_, _b_, _c_, _d_, _e_: _f_,\n_g_, _h_, _i_, _k_: _l_, _m_, _n_, _o_, _p_: _q_, _r_: _s_, _t_: _v_,\n_x_: _y_, _z_, denote the Colours reckon'd in order from the center,\nblack, blue, white, yellow, red: violet, blue, green, yellow, red:\npurple, blue, green, yellow, red: green, red: greenish blue, red:\ngreenish blue, pale red: greenish blue, reddish white.\n\n[Illustration: FIG. 2.]\n\n_Obs._ 5. To determine the interval of the Glasses, or thickness of the\ninterjacent Air, by which each Colour was produced, I measured the\nDiameters of the first six Rings at the most lucid part of their Orbits,\nand squaring them, I found their Squares to be in the arithmetical\nProgression of the odd Numbers, 1, 3, 5, 7, 9, 11. And since one of\nthese Glasses was plane, and the other spherical, their Intervals at\nthose Rings must be in the same Progression. I measured also the\nDiameters of the dark or faint Rings between the more lucid Colours, and\nfound their Squares to be in the arithmetical Progression of the even\nNumbers, 2, 4, 6, 8, 10, 12. And it being very nice and difficult to\ntake these measures exactly; I repeated them divers times at divers\nparts of the Glasses, that by their Agreement I might be confirmed in\nthem. And the same method I used in determining some others of the\nfollowing Observations.\n\n_Obs._ 6. The Diameter of the sixth Ring at the most lucid part of its\nOrbit was 58/100 parts of an Inch, and the Diameter of the Sphere on\nwhich the double convex Object-glass was ground was about 102 Feet, and\nhence I gathered the thickness of the Air or Aereal Interval of the\nGlasses at that Ring. But some time after, suspecting that in making\nthis Observation I had not determined the Diameter of the Sphere with\nsufficient accurateness, and being uncertain whether the Plano-convex\nGlass was truly plane, and not something concave or convex on that side\nwhich I accounted plane; and whether I had not pressed the Glasses\ntogether, as I often did, to make them touch; (For by pressing such\nGlasses together their parts easily yield inwards, and the Rings thereby\nbecome sensibly broader than they would be, did the Glasses keep their\nFigures.) I repeated the Experiment, and found the Diameter of the sixth\nlucid Ring about 55/100 parts of an Inch. I repeated the Experiment also\nwith such an Object-glass of another Telescope as I had at hand. This\nwas a double Convex ground on both sides to one and the same Sphere, and\nits Focus was distant from it 83-2/5 Inches. And thence, if the Sines of\nIncidence and Refraction of the bright yellow Light be assumed in\nproportion as 11 to 17, the Diameter of the Sphere to which the Glass\nwas figured will by computation be found 182 Inches. This Glass I laid\nupon a flat one, so that the black Spot appeared in the middle of the\nRings of Colours without any other Pressure than that of the weight of\nthe Glass. And now measuring the Diameter of the fifth dark Circle as\naccurately as I could, I found it the fifth part of an Inch precisely.\nThis Measure was taken with the points of a pair of Compasses on the\nupper Surface on the upper Glass, and my Eye was about eight or nine\nInches distance from the Glass, almost perpendicularly over it, and the\nGlass was 1/6 of an Inch thick, and thence it is easy to collect that\nthe true Diameter of the Ring between the Glasses was greater than its\nmeasur'd Diameter above the Glasses in the Proportion of 80 to 79, or\nthereabouts, and by consequence equal to 16/79 parts of an Inch, and its\ntrue Semi-diameter equal to 8/79 parts. Now as the Diameter of the\nSphere (182 Inches) is to the Semi-diameter of this fifth dark Ring\n(8/79 parts of an Inch) so is this Semi-diameter to the thickness of the\nAir at this fifth dark Ring; which is therefore 32/567931 or\n100/1774784. Parts of an Inch; and the fifth Part thereof, _viz._ the\n1/88739 Part of an Inch, is the Thickness of the Air at the first of\nthese dark Rings.\n\nThe same Experiment I repeated with another double convex Object-glass\nground on both sides to one and the same Sphere. Its Focus was distant\nfrom it 168-1/2 Inches, and therefore the Diameter of that Sphere was\n184 Inches. This Glass being laid upon the same plain Glass, the\nDiameter of the fifth of the dark Rings, when the black Spot in their\nCenter appear'd plainly without pressing the Glasses, was by the measure\nof the Compasses upon the upper Glass 121/600 Parts of an Inch, and by\nconsequence between the Glasses it was 1222/6000: For the upper Glass\nwas 1/8 of an Inch thick, and my Eye was distant from it 8 Inches. And a\nthird proportional to half this from the Diameter of the Sphere is\n5/88850 Parts of an Inch. This is therefore the Thickness of the Air at\nthis Ring, and a fifth Part thereof, _viz._ the 1/88850th Part of an\nInch is the Thickness thereof at the first of the Rings, as above.\n\nI tried the same Thing, by laying these Object-glasses upon flat Pieces\nof a broken Looking-glass, and found the same Measures of the Rings:\nWhich makes me rely upon them till they can be determin'd more\naccurately by Glasses ground to larger Spheres, though in such Glasses\ngreater care must be taken of a true Plane.\n\nThese Dimensions were taken, when my Eye was placed almost\nperpendicularly over the Glasses, being about an Inch, or an Inch and a\nquarter, distant from the incident Rays, and eight Inches distant from\nthe Glass; so that the Rays were inclined to the Glass in an Angle of\nabout four Degrees. Whence by the following Observation you will\nunderstand, that had the Rays been perpendicular to the Glasses, the\nThickness of the Air at these Rings would have been less in the\nProportion of the Radius to the Secant of four Degrees, that is, of\n10000 to 10024. Let the Thicknesses found be therefore diminish'd in\nthis Proportion, and they will become 1/88952 and 1/89063, or (to use\nthe nearest round Number) the 1/89000th Part of an Inch. This is the\nThickness of the Air at the darkest Part of the first dark Ring made by\nperpendicular Rays; and half this Thickness multiplied by the\nProgression, 1, 3, 5, 7, 9, 11, &c. gives the Thicknesses of the Air at\nthe most luminous Parts of all the brightest Rings, _viz._ 1/178000,\n3/178000, 5/178000, 7/178000, &c. their arithmetical Means 2/178000,\n4/178000, 6/178000, &c. being its Thicknesses at the darkest Parts of\nall the dark ones.\n\n_Obs._ 7. The Rings were least, when my Eye was placed perpendicularly\nover the Glasses in the Axis of the Rings: And when I view'd them\nobliquely they became bigger, continually swelling as I removed my Eye\nfarther from the Axis. And partly by measuring the Diameter of the same\nCircle at several Obliquities of my Eye, partly by other Means, as also\nby making use of the two Prisms for very great Obliquities, I found its\nDiameter, and consequently the Thickness of the Air at its Perimeter in\nall those Obliquities to be very nearly in the Proportions express'd in\nthis Table.\n\n-------------------+--------------------+----------+----------\nAngle of Incidence |Angle of Refraction |Diameter  |Thickness\n        on         |         into       |  of the  |   of the\n      the Air.     |       the Air.     |   Ring.  |    Air.\n-------------------+--------------------+----------+----------\n    Deg.    Min.   |                    |          |\n                   |                    |          |\n    00      00     |     00      00     |  10      |  10\n                   |                    |          |\n    06      26     |     10      00     |  10-1/13 |  10-2/13\n                   |                    |          |\n    12      45     |     20      00     |  10-1/3  |  10-2/3\n                   |                    |          |\n    18      49     |     30      00     |  10-3/4  |  11-1/2\n                   |                    |          |\n    24      30     |     40      00     |  11-2/5  |  13\n                   |                    |          |\n    29      37     |     50      00     |  12-1/2  |  15-1/2\n                   |                    |          |\n    33      58     |     60      00     |  14      |  20\n                   |                    |          |\n    35      47     |     65      00     |  15-1/4  |  23-1/4\n                   |                    |          |\n    37      19     |     70      00     |  16-4/5  |  28-1/4\n                   |                    |          |\n    38      33     |     75      00     |  19-1/4  |  37\n                   |                    |          |\n    39      27     |     80      00     |  22-6/7  |  52-1/4\n                   |                    |          |\n    40      00     |     85      00     |  29      |  84-1/12\n                   |                    |          |\n    40      11     |     90      00     |  35      | 122-1/2\n-------------------+--------------------+----------+----------\n\nIn the two first Columns are express'd the Obliquities of the incident\nand emergent Rays to the Plate of the Air, that is, their Angles of\nIncidence and Refraction. In the third Column the Diameter of any\ncolour'd Ring at those Obliquities is expressed in Parts, of which ten\nconstitute that Diameter when the Rays are perpendicular. And in the\nfourth Column the Thickness of the Air at the Circumference of that Ring\nis expressed in Parts, of which also ten constitute its Thickness when\nthe Rays are perpendicular.\n\nAnd from these Measures I seem to gather this Rule: That the Thickness\nof the Air is proportional to the Secant of an Angle, whose Sine is a\ncertain mean Proportional between the Sines of Incidence and Refraction.\nAnd that mean Proportional, so far as by these Measures I can determine\nit, is the first of an hundred and six arithmetical mean Proportionals\nbetween those Sines counted from the bigger Sine, that is, from the Sine\nof Refraction when the Refraction is made out of the Glass into the\nPlate of Air, or from the Sine of Incidence when the Refraction is made\nout of the Plate of Air into the Glass.\n\n_Obs._ 8. The dark Spot in the middle of the Rings increased also by the\nObliquation of the Eye, although almost insensibly. But, if instead of\nthe Object-glasses the Prisms were made use of, its Increase was more\nmanifest when viewed so obliquely that no Colours appear'd about it. It\nwas least when the Rays were incident most obliquely on the interjacent\nAir, and as the obliquity decreased it increased more and more until the\ncolour'd Rings appear'd, and then decreased again, but not so much as it\nincreased before. And hence it is evident, that the Transparency was\nnot only at the absolute Contact of the Glasses, but also where they had\nsome little Interval. I have sometimes observed the Diameter of that\nSpot to be between half and two fifth parts of the Diameter of the\nexterior Circumference of the red in the first Circuit or Revolution of\nColours when view'd almost perpendicularly; whereas when view'd\nobliquely it hath wholly vanish'd and become opake and white like the\nother parts of the Glass; whence it may be collected that the Glasses\ndid then scarcely, or not at all, touch one another, and that their\nInterval at the perimeter of that Spot when view'd perpendicularly was\nabout a fifth or sixth part of their Interval at the circumference of\nthe said red.\n\n_Obs._ 9. By looking through the two contiguous Object-glasses, I found\nthat the interjacent Air exhibited Rings of Colours, as well by\ntransmitting Light as by reflecting it. The central Spot was now white,\nand from it the order of the Colours were yellowish red; black, violet,\nblue, white, yellow, red; violet, blue, green, yellow, red, &c. But\nthese Colours were very faint and dilute, unless when the Light was\ntrajected very obliquely through the Glasses: For by that means they\nbecame pretty vivid. Only the first yellowish red, like the blue in the\nfourth Observation, was so little and faint as scarcely to be discern'd.\nComparing the colour'd Rings made by Reflexion, with these made by\ntransmission of the Light; I found that white was opposite to black, red\nto blue, yellow to violet, and green to a Compound of red and violet.\nThat is, those parts of the Glass were black when looked through, which\nwhen looked upon appeared white, and on the contrary. And so those which\nin one case exhibited blue, did in the other case exhibit red. And the\nlike of the other Colours. The manner you have represented in the third\nFigure, where AB, CD, are the Surfaces of the Glasses contiguous at E,\nand the black Lines between them are their Distances in arithmetical\nProgression, and the Colours written above are seen by reflected Light,\nand those below by Light transmitted (p. 209).\n\n_Obs._ 10. Wetting the Object-glasses a little at their edges, the Water\ncrept in slowly between them, and the Circles thereby became less and\nthe Colours more faint: Insomuch that as the Water crept along, one half\nof them at which it first arrived would appear broken off from the other\nhalf, and contracted into a less Room. By measuring them I found the\nProportions of their Diameters to the Diameters of the like Circles made\nby Air to be about seven to eight, and consequently the Intervals of the\nGlasses at like Circles, caused by those two Mediums Water and Air, are\nas about three to four. Perhaps it may be a general Rule, That if any\nother Medium more or less dense than Water be compress'd between the\nGlasses, their Intervals at the Rings caused thereby will be to their\nIntervals caused by interjacent Air, as the Sines are which measure the\nRefraction made out of that Medium into Air.\n\n_Obs._ 11. When the Water was between the Glasses, if I pressed the\nupper Glass variously at its edges to make the Rings move nimbly from\none place to another, a little white Spot would immediately follow the\ncenter of them, which upon creeping in of the ambient Water into that\nplace would presently vanish. Its appearance was such as interjacent Air\nwould have caused, and it exhibited the same Colours. But it was not\nair, for where any Bubbles of Air were in the Water they would not\nvanish. The Reflexion must have rather been caused by a subtiler Medium,\nwhich could recede through the Glasses at the creeping in of the Water.\n\n_Obs._ 12. These Observations were made in the open Air. But farther to\nexamine the Effects of colour'd Light falling on the Glasses, I darken'd\nthe Room, and view'd them by Reflexion of the Colours of a Prism cast on\na Sheet of white Paper, my Eye being so placed that I could see the\ncolour'd Paper by Reflexion in the Glasses, as in a Looking-glass. And\nby this means the Rings became distincter and visible to a far greater\nnumber than in the open Air. I have sometimes seen more than twenty of\nthem, whereas in the open Air I could not discern above eight or nine.\n\n[Illustration: FIG. 3.]\n\n_Obs._ 13. Appointing an Assistant to move the Prism to and fro about\nits Axis, that all the Colours might successively fall on that part of\nthe Paper which I saw by Reflexion from that part of the Glasses, where\nthe Circles appear'd, so that all the Colours might be successively\nreflected from the Circles to my Eye, whilst I held it immovable, I\nfound the Circles which the red Light made to be manifestly bigger than\nthose which were made by the blue and violet. And it was very pleasant\nto see them gradually swell or contract accordingly as the Colour of the\nLight was changed. The Interval of the Glasses at any of the Rings when\nthey were made by the utmost red Light, was to their Interval at the\nsame Ring when made by the utmost violet, greater than as 3 to 2, and\nless than as 13 to 8. By the most of my Observations it was as 14 to 9.\nAnd this Proportion seem'd very nearly the same in all Obliquities of my\nEye; unless when two Prisms were made use of instead of the\nObject-glasses. For then at a certain great obliquity of my Eye, the\nRings made by the several Colours seem'd equal, and at a greater\nobliquity those made by the violet would be greater than the same Rings\nmade by the red: the Refraction of the Prism in this case causing the\nmost refrangible Rays to fall more obliquely on that plate of the Air\nthan the least refrangible ones. Thus the Experiment succeeded in the\ncolour'd Light, which was sufficiently strong and copious to make the\nRings sensible. And thence it may be gather'd, that if the most\nrefrangible and least refrangible Rays had been copious enough to make\nthe Rings sensible without the mixture of other Rays, the Proportion\nwhich here was 14 to 9 would have been a little greater, suppose 14-1/4\nor 14-1/3 to 9.\n\n_Obs._ 14. Whilst the Prism was turn'd about its Axis with an uniform\nMotion, to make all the several Colours fall successively upon the\nObject-glasses, and thereby to make the Rings contract and dilate: The\nContraction or Dilatation of each Ring thus made by the variation of its\nColour was swiftest in the red, and slowest in the violet, and in the\nintermediate Colours it had intermediate degrees of Celerity. Comparing\nthe quantity of Contraction and Dilatation made by all the degrees of\neach Colour, I found that it was greatest in the red; less in the\nyellow, still less in the blue, and least in the violet. And to make as\njust an Estimation as I could of the Proportions of their Contractions\nor Dilatations, I observ'd that the whole Contraction or Dilatation of\nthe Diameter of any Ring made by all the degrees of red, was to that of\nthe Diameter of the same Ring made by all the degrees of violet, as\nabout four to three, or five to four, and that when the Light was of the\nmiddle Colour between yellow and green, the Diameter of the Ring was\nvery nearly an arithmetical Mean between the greatest Diameter of the\nsame Ring made by the outmost red, and the least Diameter thereof made\nby the outmost violet: Contrary to what happens in the Colours of the\noblong Spectrum made by the Refraction of a Prism, where the red is most\ncontracted, the violet most expanded, and in the midst of all the\nColours is the Confine of green and blue. And hence I seem to collect\nthat the thicknesses of the Air between the Glasses there, where the\nRing is successively made by the limits of the five principal Colours\n(red, yellow, green, blue, violet) in order (that is, by the extreme\nred, by the limit of red and yellow in the middle of the orange, by the\nlimit of yellow and green, by the limit of green and blue, by the limit\nof blue and violet in the middle of the indigo, and by the extreme\nviolet) are to one another very nearly as the sixth lengths of a Chord\nwhich found the Notes in a sixth Major, _sol_, _la_, _mi_, _fa_, _sol_,\n_la_. But it agrees something better with the Observation to say, that\nthe thicknesses of the Air between the Glasses there, where the Rings\nare successively made by the limits of the seven Colours, red, orange,\nyellow, green, blue, indigo, violet in order, are to one another as the\nCube Roots of the Squares of the eight lengths of a Chord, which found\nthe Notes in an eighth, _sol_, _la_, _fa_, _sol_, _la_, _mi_, _fa_,\n_sol_; that is, as the Cube Roots of the Squares of the Numbers, 1, 8/9,\n5/6, 3/4, 2/3, 3/5, 9/16, 1/2.\n\n_Obs._ 15. These Rings were not of various Colours like those made in\nthe open Air, but appeared all over of that prismatick Colour only with\nwhich they were illuminated. And by projecting the prismatick Colours\nimmediately upon the Glasses, I found that the Light which fell on the\ndark Spaces which were between the Colour'd Rings was transmitted\nthrough the Glasses without any variation of Colour. For on a white\nPaper placed behind, it would paint Rings of the same Colour with those\nwhich were reflected, and of the bigness of their immediate Spaces. And\nfrom thence the origin of these Rings is manifest; namely, that the Air\nbetween the Glasses, according to its various thickness, is disposed in\nsome places to reflect, and in others to transmit the Light of any one\nColour (as you may see represented in the fourth Figure) and in the same\nplace to reflect that of one Colour where it transmits that of another.\n\n[Illustration: FIG. 4.]\n\n_Obs._ 16. The Squares of the Diameters of these Rings made by any\nprismatick Colour were in arithmetical Progression, as in the fifth\nObservation. And the Diameter of the sixth Circle, when made by the\ncitrine yellow, and viewed almost perpendicularly was about 58/100 parts\nof an Inch, or a little less, agreeable to the sixth Observation.\n\nThe precedent Observations were made with a rarer thin Medium,\nterminated by a denser, such as was Air or Water compress'd between two\nGlasses. In those that follow are set down the Appearances of a denser\nMedium thin'd within a rarer, such as are Plates of Muscovy Glass,\nBubbles of Water, and some other thin Substances terminated on all sides\nwith air.\n\n_Obs._ 17. If a Bubble be blown with Water first made tenacious by\ndissolving a little Soap in it, 'tis a common Observation, that after a\nwhile it will appear tinged with a great variety of Colours. To defend\nthese Bubbles from being agitated by the external Air (whereby their\nColours are irregularly moved one among another, so that no accurate\nObservation can be made of them,) as soon as I had blown any of them I\ncover'd it with a clear Glass, and by that means its Colours emerged in\na very regular order, like so many concentrick Rings encompassing the\ntop of the Bubble. And as the Bubble grew thinner by the continual\nsubsiding of the Water, these Rings dilated slowly and overspread the\nwhole Bubble, descending in order to the bottom of it, where they\nvanish'd successively. In the mean while, after all the Colours were\nemerged at the top, there grew in the center of the Rings a small round\nblack Spot, like that in the first Observation, which continually\ndilated it self till it became sometimes more than 1/2 or 3/4 of an Inch\nin breadth before the Bubble broke. At first I thought there had been no\nLight reflected from the Water in that place, but observing it more\ncuriously, I saw within it several smaller round Spots, which appeared\nmuch blacker and darker than the rest, whereby I knew that there was\nsome Reflexion at the other places which were not so dark as those\nSpots. And by farther Tryal I found that I could see the Images of some\nthings (as of a Candle or the Sun) very faintly reflected, not only from\nthe great black Spot, but also from the little darker Spots which were\nwithin it.\n\nBesides the aforesaid colour'd Rings there would often appear small\nSpots of Colours, ascending and descending up and down the sides of the\nBubble, by reason of some Inequalities in the subsiding of the Water.\nAnd sometimes small black Spots generated at the sides would ascend up\nto the larger black Spot at the top of the Bubble, and unite with it.\n\n_Obs._ 18. Because the Colours of these Bubbles were more extended and\nlively than those of the Air thinn'd between two Glasses, and so more\neasy to be distinguish'd, I shall here give you a farther description of\ntheir order, as they were observ'd in viewing them by Reflexion of the\nSkies when of a white Colour, whilst a black substance was placed\nbehind the Bubble. And they were these, red, blue; red, blue; red, blue;\nred, green; red, yellow, green, blue, purple; red, yellow, green, blue,\nviolet; red, yellow, white, blue, black.\n\nThe three first Successions of red and blue were very dilute and dirty,\nespecially the first, where the red seem'd in a manner to be white.\nAmong these there was scarce any other Colour sensible besides red and\nblue, only the blues (and principally the second blue) inclined a little\nto green.\n\nThe fourth red was also dilute and dirty, but not so much as the former\nthree; after that succeeded little or no yellow, but a copious green,\nwhich at first inclined a little to yellow, and then became a pretty\nbrisk and good willow green, and afterwards changed to a bluish Colour;\nbut there succeeded neither blue nor violet.\n\nThe fifth red at first inclined very much to purple, and afterwards\nbecame more bright and brisk, but yet not very pure. This was succeeded\nwith a very bright and intense yellow, which was but little in quantity,\nand soon chang'd to green: But that green was copious and something more\npure, deep and lively, than the former green. After that follow'd an\nexcellent blue of a bright Sky-colour, and then a purple, which was less\nin quantity than the blue, and much inclined to red.\n\nThe sixth red was at first of a very fair and lively scarlet, and soon\nafter of a brighter Colour, being very pure and brisk, and the best of\nall the reds. Then after a lively orange follow'd an intense bright and\ncopious yellow, which was also the best of all the yellows, and this\nchanged first to a greenish yellow, and then to a greenish blue; but the\ngreen between the yellow and the blue, was very little and dilute,\nseeming rather a greenish white than a green. The blue which succeeded\nbecame very good, and of a very bright Sky-colour, but yet something\ninferior to the former blue; and the violet was intense and deep with\nlittle or no redness in it. And less in quantity than the blue.\n\nIn the last red appeared a tincture of scarlet next to violet, which\nsoon changed to a brighter Colour, inclining to an orange; and the\nyellow which follow'd was at first pretty good and lively, but\nafterwards it grew more dilute until by degrees it ended in perfect\nwhiteness. And this whiteness, if the Water was very tenacious and\nwell-temper'd, would slowly spread and dilate it self over the greater\npart of the Bubble; continually growing paler at the top, where at\nlength it would crack in many places, and those cracks, as they dilated,\nwould appear of a pretty good, but yet obscure and dark Sky-colour; the\nwhite between the blue Spots diminishing, until it resembled the Threds\nof an irregular Net-work, and soon after vanish'd, and left all the\nupper part of the Bubble of the said dark blue Colour. And this Colour,\nafter the aforesaid manner, dilated it self downwards, until sometimes\nit hath overspread the whole Bubble. In the mean while at the top, which\nwas of a darker blue than the bottom, and appear'd also full of many\nround blue Spots, something darker than the rest, there would emerge\none or more very black Spots, and within those, other Spots of an\nintenser blackness, which I mention'd in the former Observation; and\nthese continually dilated themselves until the Bubble broke.\n\nIf the Water was not very tenacious, the black Spots would break forth\nin the white, without any sensible intervention of the blue. And\nsometimes they would break forth within the precedent yellow, or red, or\nperhaps within the blue of the second order, before the intermediate\nColours had time to display themselves.\n\nBy this description you may perceive how great an affinity these Colours\nhave with those of Air described in the fourth Observation, although set\ndown in a contrary order, by reason that they begin to appear when the\nBubble is thickest, and are most conveniently reckon'd from the lowest\nand thickest part of the Bubble upwards.\n\n_Obs._ 19. Viewing in several oblique Positions of my Eye the Rings of\nColours emerging on the top of the Bubble, I found that they were\nsensibly dilated by increasing the obliquity, but yet not so much by far\nas those made by thinn'd Air in the seventh Observation. For there they\nwere dilated so much as, when view'd most obliquely, to arrive at a part\nof the Plate more than twelve times thicker than that where they\nappear'd when viewed perpendicularly; whereas in this case the thickness\nof the Water, at which they arrived when viewed most obliquely, was to\nthat thickness which exhibited them by perpendicular Rays, something\nless than as 8 to 5. By the best of my Observations it was between 15\nand 15-1/2 to 10; an increase about 24 times less than in the other\ncase.\n\nSometimes the Bubble would become of an uniform thickness all over,\nexcept at the top of it near the black Spot, as I knew, because it would\nexhibit the same appearance of Colours in all Positions of the Eye. And\nthen the Colours which were seen at its apparent circumference by the\nobliquest Rays, would be different from those that were seen in other\nplaces, by Rays less oblique to it. And divers Spectators might see the\nsame part of it of differing Colours, by viewing it at very differing\nObliquities. Now observing how much the Colours at the same places of\nthe Bubble, or at divers places of equal thickness, were varied by the\nseveral Obliquities of the Rays; by the assistance of the 4th, 14th,\n16th and 18th Observations, as they are hereafter explain'd, I collect\nthe thickness of the Water requisite to exhibit any one and the same\nColour, at several Obliquities, to be very nearly in the Proportion\nexpressed in this Table.\n\n-----------------+------------------+----------------\n  Incidence on   | Refraction into  | Thickness of\n   the Water.    |    the Water.    |   the Water.\n-----------------+------------------+----------------\n   Deg.    Min.  |    Deg.    Min.  |\n                 |                  |\n    00     00    |     00     00    |    10\n                 |                  |\n    15     00    |     11     11    |    10-1/4\n                 |                  |\n    30     00    |     22      1    |    10-4/5\n                 |                  |\n    45     00    |     32      2    |    11-4/5\n                 |                  |\n    60     00    |     40     30    |    13\n                 |                  |\n    75     00    |     46     25    |    14-1/2\n                 |                  |\n    90     00    |     48     35    |    15-1/5\n-----------------+------------------+----------------\n\nIn the two first Columns are express'd the Obliquities of the Rays to\nthe Superficies of the Water, that is, their Angles of Incidence and\nRefraction. Where I suppose, that the Sines which measure them are in\nround Numbers, as 3 to 4, though probably the Dissolution of Soap in the\nWater, may a little alter its refractive Virtue. In the third Column,\nthe Thickness of the Bubble, at which any one Colour is exhibited in\nthose several Obliquities, is express'd in Parts, of which ten\nconstitute its Thickness when the Rays are perpendicular. And the Rule\nfound by the seventh Observation agrees well with these Measures, if\nduly apply'd; namely, that the Thickness of a Plate of Water requisite\nto exhibit one and the same Colour at several Obliquities of the Eye, is\nproportional to the Secant of an Angle, whose Sine is the first of an\nhundred and six arithmetical mean Proportionals between the Sines of\nIncidence and Refraction counted from the lesser Sine, that is, from the\nSine of Refraction when the Refraction is made out of Air into Water,\notherwise from the Sine of Incidence.\n\nI have sometimes observ'd, that the Colours which arise on polish'd\nSteel by heating it, or on Bell-metal, and some other metalline\nSubstances, when melted and pour'd on the Ground, where they may cool in\nthe open Air, have, like the Colours of Water-bubbles, been a little\nchanged by viewing them at divers Obliquities, and particularly that a\ndeep blue, or violet, when view'd very obliquely, hath been changed to a\ndeep red. But the Changes of these Colours are not so great and\nsensible as of those made by Water. For the Scoria, or vitrified Part of\nthe Metal, which most Metals when heated or melted do continually\nprotrude, and send out to their Surface, and which by covering the\nMetals in form of a thin glassy Skin, causes these Colours, is much\ndenser than Water; and I find that the Change made by the Obliquation of\nthe Eye is least in Colours of the densest thin Substances.\n\n_Obs._ 20. As in the ninth Observation, so here, the Bubble, by\ntransmitted Light, appear'd of a contrary Colour to that, which it\nexhibited by Reflexion. Thus when the Bubble being look'd on by the\nLight of the Clouds reflected from it, seemed red at its apparent\nCircumference, if the Clouds at the same time, or immediately after,\nwere view'd through it, the Colour at its Circumference would be blue.\nAnd, on the contrary, when by reflected Light it appeared blue, it would\nappear red by transmitted Light.\n\n_Obs._ 21. By wetting very thin Plates of _Muscovy_ Glass, whose\nthinness made the like Colours appear, the Colours became more faint and\nlanguid, especially by wetting the Plates on that side opposite to the\nEye: But I could not perceive any variation of their Species. So then\nthe thickness of a Plate requisite to produce any Colour, depends only\non the density of the Plate, and not on that of the ambient Medium. And\nhence, by the 10th and 16th Observations, may be known the thickness\nwhich Bubbles of Water, or Plates of _Muscovy_ Glass, or other\nSubstances, have at any Colour produced by them.\n\n_Obs._ 22. A thin transparent Body, which is denser than its ambient\nMedium, exhibits more brisk and vivid Colours than that which is so much\nrarer; as I have particularly observed in the Air and Glass. For blowing\nGlass very thin at a Lamp Furnace, those Plates encompassed with Air did\nexhibit Colours much more vivid than those of Air made thin between two\nGlasses.\n\n_Obs._ 23. Comparing the quantity of Light reflected from the several\nRings, I found that it was most copious from the first or inmost, and in\nthe exterior Rings became gradually less and less. Also the whiteness of\nthe first Ring was stronger than that reflected from those parts of the\nthin Medium or Plate which were without the Rings; as I could manifestly\nperceive by viewing at a distance the Rings made by the two\nObject-glasses; or by comparing two Bubbles of Water blown at distant\nTimes, in the first of which the Whiteness appear'd, which succeeded all\nthe Colours, and in the other, the Whiteness which preceded them all.\n\n_Obs._ 24. When the two Object-glasses were lay'd upon one another, so\nas to make the Rings of the Colours appear, though with my naked Eye I\ncould not discern above eight or nine of those Rings, yet by viewing\nthem through a Prism I have seen a far greater Multitude, insomuch that\nI could number more than forty, besides many others, that were so very\nsmall and close together, that I could not keep my Eye steady on them\nseverally so as to number them, but by their Extent I have sometimes\nestimated them to be more than an hundred. And I believe the Experiment\nmay be improved to the Discovery of far greater Numbers. For they seem\nto be really unlimited, though visible only so far as they can be\nseparated by the Refraction of the Prism, as I shall hereafter explain.\n\n[Illustration: FIG. 5.]\n\nBut it was but one side of these Rings, namely, that towards which the\nRefraction was made, which by that Refraction was render'd distinct, and\nthe other side became more confused than when view'd by the naked Eye,\ninsomuch that there I could not discern above one or two, and sometimes\nnone of those Rings, of which I could discern eight or nine with my\nnaked Eye. And their Segments or Arcs, which on the other side appear'd\nso numerous, for the most part exceeded not the third Part of a Circle.\nIf the Refraction was very great, or the Prism very distant from the\nObject-glasses, the middle Part of those Arcs became also confused, so\nas to disappear and constitute an even Whiteness, whilst on either side\ntheir Ends, as also the whole Arcs farthest from the Center, became\ndistincter than before, appearing in the Form as you see them design'd\nin the fifth Figure.\n\nThe Arcs, where they seem'd distinctest, were only white and black\nsuccessively, without any other Colours intermix'd. But in other Places\nthere appeared Colours, whose Order was inverted by the refraction in\nsuch manner, that if I first held the Prism very near the\nObject-glasses, and then gradually removed it farther off towards my\nEye, the Colours of the 2d, 3d, 4th, and following Rings, shrunk towards\nthe white that emerged between them, until they wholly vanish'd into it\nat the middle of the Arcs, and afterwards emerged again in a contrary\nOrder. But at the Ends of the Arcs they retain'd their Order unchanged.\n\nI have sometimes so lay'd one Object-glass upon the other, that to the\nnaked Eye they have all over seem'd uniformly white, without the least\nAppearance of any of the colour'd Rings; and yet by viewing them through\na Prism, great Multitudes of those Rings have discover'd themselves. And\nin like manner Plates of _Muscovy_ Glass, and Bubbles of Glass blown at\na Lamp-Furnace, which were not so thin as to exhibit any Colours to the\nnaked Eye, have through the Prism exhibited a great Variety of them\nranged irregularly up and down in the Form of Waves. And so Bubbles of\nWater, before they began to exhibit their Colours to the naked Eye of a\nBystander, have appeared through a Prism, girded about with many\nparallel and horizontal Rings; to produce which Effect, it was necessary\nto hold the Prism parallel, or very nearly parallel to the Horizon, and\nto dispose it so that the Rays might be refracted upwards.\n\n\n\n\nTHE\n\nSECOND BOOK\n\nOF\n\nOPTICKS\n\n\n_PART II._\n\n_Remarks upon the foregoing Observations._\n\n\nHaving given my Observations of these Colours, before I make use of them\nto unfold the Causes of the Colours of natural Bodies, it is convenient\nthat by the simplest of them, such as are the 2d, 3d, 4th, 9th, 12th,\n18th, 20th, and 24th, I first explain the more compounded. And first to\nshew how the Colours in the fourth and eighteenth Observations are\nproduced, let there be taken in any Right Line from the Point Y, [in\n_Fig._ 6.] the Lengths YA, YB, YC, YD, YE, YF, YG, YH, in proportion to\none another, as the Cube-Roots of the Squares of the Numbers, 1/2, 9/16,\n3/5, 2/3, 3/4, 5/6, 8/9, 1, whereby the Lengths of a Musical Chord to\nsound all the Notes in an eighth are represented; that is, in the\nProportion of the Numbers 6300, 6814, 7114, 7631, 8255, 8855, 9243,\n10000. And at the Points A, B, C, D, E, F, G, H, let Perpendiculars\nA[Greek: a], B[Greek: b], &c. be erected, by whose Intervals the Extent\nof the several Colours set underneath against them, is to be\nrepresented. Then divide the Line _A[Greek: a]_ in such Proportion as\nthe Numbers 1, 2, 3, 5, 6, 7, 9, 10, 11, &c. set at the Points of\nDivision denote. And through those Divisions from Y draw Lines 1I, 2K,\n3L, 5M, 6N, 7O, &c.\n\nNow, if A2 be supposed to represent the Thickness of any thin\ntransparent Body, at which the outmost Violet is most copiously\nreflected in the first Ring, or Series of Colours, then by the 13th\nObservation, HK will represent its Thickness, at which the utmost Red is\nmost copiously reflected in the same Series. Also by the 5th and 16th\nObservations, A6 and HN will denote the Thicknesses at which those\nextreme Colours are most copiously reflected in the second Series, and\nA10 and HQ the Thicknesses at which they are most copiously reflected in\nthe third Series, and so on. And the Thickness at which any of the\nintermediate Colours are reflected most copiously, will, according to\nthe 14th Observation, be defined by the distance of the Line AH from the\nintermediate parts of the Lines 2K, 6N, 10Q, &c. against which the Names\nof those Colours are written below.\n\n[Illustration: FIG. 6.]\n\nBut farther, to define the Latitude of these Colours in each Ring or\nSeries, let A1 design the least thickness, and A3 the greatest\nthickness, at which the extreme violet in the first Series is reflected,\nand let HI, and HL, design the like limits for the extreme red, and let\nthe intermediate Colours be limited by the intermediate parts of the\nLines 1I, and 3L, against which the Names of those Colours are written,\nand so on: But yet with this caution, that the Reflexions be supposed\nstrongest at the intermediate Spaces, 2K, 6N, 10Q, &c. and from thence\nto decrease gradually towards these limits, 1I, 3L, 5M, 7O, &c. on\neither side; where you must not conceive them to be precisely limited,\nbut to decay indefinitely. And whereas I have assign'd the same Latitude\nto every Series, I did it, because although the Colours in the first\nSeries seem to be a little broader than the rest, by reason of a\nstronger Reflexion there, yet that inequality is so insensible as\nscarcely to be determin'd by Observation.\n\nNow according to this Description, conceiving that the Rays originally\nof several Colours are by turns reflected at the Spaces 1I, L3, 5M, O7,\n9PR11, &c. and transmitted at the Spaces AHI1, 3LM5, 7OP9, &c. it is\neasy to know what Colour must in the open Air be exhibited at any\nthickness of a transparent thin Body. For if a Ruler be applied parallel\nto AH, at that distance from it by which the thickness of the Body is\nrepresented, the alternate Spaces 1IL3, 5MO7, &c. which it crosseth will\ndenote the reflected original Colours, of which the Colour exhibited in\nthe open Air is compounded. Thus if the constitution of the green in the\nthird Series of Colours be desired, apply the Ruler as you see at\n[Greek: prsph], and by its passing through some of the blue at [Greek:\np] and yellow at [Greek: s], as well as through the green at [Greek: r],\nyou may conclude that the green exhibited at that thickness of the Body\nis principally constituted of original green, but not without a mixture\nof some blue and yellow.\n\nBy this means you may know how the Colours from the center of the Rings\noutward ought to succeed in order as they were described in the 4th and\n18th Observations. For if you move the Ruler gradually from AH through\nall distances, having pass'd over the first Space which denotes little\nor no Reflexion to be made by thinnest Substances, it will first arrive\nat 1 the violet, and then very quickly at the blue and green, which\ntogether with that violet compound blue, and then at the yellow and red,\nby whose farther addition that blue is converted into whiteness, which\nwhiteness continues during the transit of the edge of the Ruler from I\nto 3, and after that by the successive deficience of its component\nColours, turns first to compound yellow, and then to red, and last of\nall the red ceaseth at L. Then begin the Colours of the second Series,\nwhich succeed in order during the transit of the edge of the Ruler from\n5 to O, and are more lively than before, because more expanded and\nsevered. And for the same reason instead of the former white there\nintercedes between the blue and yellow a mixture of orange, yellow,\ngreen, blue and indigo, all which together ought to exhibit a dilute and\nimperfect green. So the Colours of the third Series all succeed in\norder; first, the violet, which a little interferes with the red of the\nsecond order, and is thereby inclined to a reddish purple; then the blue\nand green, which are less mix'd with other Colours, and consequently\nmore lively than before, especially the green: Then follows the yellow,\nsome of which towards the green is distinct and good, but that part of\nit towards the succeeding red, as also that red is mix'd with the violet\nand blue of the fourth Series, whereby various degrees of red very much\ninclining to purple are compounded. This violet and blue, which should\nsucceed this red, being mixed with, and hidden in it, there succeeds a\ngreen. And this at first is much inclined to blue, but soon becomes a\ngood green, the only unmix'd and lively Colour in this fourth Series.\nFor as it verges towards the yellow, it begins to interfere with the\nColours of the fifth Series, by whose mixture the succeeding yellow and\nred are very much diluted and made dirty, especially the yellow, which\nbeing the weaker Colour is scarce able to shew it self. After this the\nseveral Series interfere more and more, and their Colours become more\nand more intermix'd, till after three or four more revolutions (in which\nthe red and blue predominate by turns) all sorts of Colours are in all\nplaces pretty equally blended, and compound an even whiteness.\n\nAnd since by the 15th Observation the Rays endued with one Colour are\ntransmitted, where those of another Colour are reflected, the reason of\nthe Colours made by the transmitted Light in the 9th and 20th\nObservations is from hence evident.\n\nIf not only the Order and Species of these Colours, but also the precise\nthickness of the Plate, or thin Body at which they are exhibited, be\ndesired in parts of an Inch, that may be also obtained by assistance of\nthe 6th or 16th Observations. For according to those Observations the\nthickness of the thinned Air, which between two Glasses exhibited the\nmost luminous parts of the first six Rings were 1/178000, 3/178000,\n5/178000, 7/178000, 9/178000, 11/178000 parts of an Inch. Suppose the\nLight reflected most copiously at these thicknesses be the bright\ncitrine yellow, or confine of yellow and orange, and these thicknesses\nwill be F[Greek: l], F[Greek: m], F[Greek: u], F[Greek: x], F[Greek: o],\nF[Greek: t]. And this being known, it is easy to determine what\nthickness of Air is represented by G[Greek: ph], or by any other\ndistance of the Ruler from AH.\n\nBut farther, since by the 10th Observation the thickness of Air was to\nthe thickness of Water, which between the same Glasses exhibited the\nsame Colour, as 4 to 3, and by the 21st Observation the Colours of thin\nBodies are not varied by varying the ambient Medium; the thickness of a\nBubble of Water, exhibiting any Colour, will be 3/4 of the thickness of\nAir producing the same Colour. And so according to the same 10th and\n21st Observations, the thickness of a Plate of Glass, whose Refraction\nof the mean refrangible Ray, is measured by the proportion of the Sines\n31 to 20, may be 20/31 of the thickness of Air producing the same\nColours; and the like of other Mediums. I do not affirm, that this\nproportion of 20 to 31, holds in all the Rays; for the Sines of other\nsorts of Rays have other Proportions. But the differences of those\nProportions are so little that I do not here consider them. On these\nGrounds I have composed the following Table, wherein the thickness of\nAir, Water, and Glass, at which each Colour is most intense and\nspecifick, is expressed in parts of an Inch divided into ten hundred\nthousand equal parts.\n\nNow if this Table be compared with the 6th Scheme, you will there see\nthe constitution of each Colour, as to its Ingredients, or the original\nColours of which it is compounded, and thence be enabled to judge of its\nIntenseness or Imperfection; which may suffice in explication of the 4th\nand 18th Observations, unless it be farther desired to delineate the\nmanner how the Colours appear, when the two Object-glasses are laid upon\none another. To do which, let there be described a large Arc of a\nCircle, and a streight Line which may touch that Arc, and parallel to\nthat Tangent several occult Lines, at such distances from it, as the\nNumbers set against the several Colours in the Table denote. For the\nArc, and its Tangent, will represent the Superficies of the Glasses\nterminating the interjacent Air; and the places where the occult Lines\ncut the Arc will show at what distances from the center, or Point of\ncontact, each Colour is reflected.\n\n_The thickness of colour'd Plates and Particles of_\n                                          _____________|_______________\n                                         /                             \\\n                                            Air.      Water.     Glass.\n                                        |---------+----------+----------+\n                       {Very black      |    1/2  |    3/8   |  10/31   |\n                       {Black           |  1      |    3/4   |  20/31   |\n                       {Beginning of    |         |          |          |\n                       {  Black         |  2      |  1-1/2   |  1-2/7   |\nTheir Colours of the   {Blue            |  2-2/5  |  1-4/5   |  1-11/22 |\nfirst Order,           {White           |  5-1/4  |  3-7/8   |  3-2/5   |\n                       {Yellow          |  7-1/9  |  5-1/3   |  4-3/5   |\n                       {Orange          |  8      |  6       |  5-1/6   |\n                       {Red             |  9      |  6-3/4   |  5-4/5   |\n                                        |---------+----------+----------|\n                       {Violet          | 11-1/6  |  8-3/8   |  7-1/5   |\n                       {Indigo          | 12-5/6  |  9-5/8   |  8-2/11  |\n                       {Blue            | 14      |  10-1/2  |  9       |\n                       {Green           | 15-1/8  | 11-2/3   |  9-5/7   |\nOf the second order,   {Yellow          | 16-2/7  | 12-1/5   | 10-2/5   |\n                       {Orange          | 17-2/9  | 13       | 11-1/9   |\n                       {Bright red      | 18-1/3  | 13-3/4   | 11-5/6   |\n                       {Scarlet         | 19-2/3  | 14-3/4   | 12-2/3   |\n                                        |---------+----------+----------|\n                       {Purple          | 21      | 15-3/4   | 13-11/20 |\n                       {Indigo          | 22-1/10 | 16-4/7   | 14-1/4   |\n                       {Blue            | 23-2/5  | 17-11/20 | 15-1/10  |\nOf the third Order,    {Green           | 25-1/5  | 18-9/10  | 16-1/4   |\n                       {Yellow          | 27-1/7  | 20-1/3   | 17-1/2   |\n                       {Red             | 29      | 21-3/4   | 18-5/7   |\n                       {Bluish red      | 32      | 24       | 20-2/3   |\n                                        |---------+----------+----------|\n                       {Bluish green    | 34      | 25-1/2   | 22       |\n                       {Green           | 35-2/7  | 26-1/2   | 22-3/4   |\nOf the fourth Order,   {Yellowish green | 36      | 27       | 23-2/9   |\n                       {Red             | 40-1/3  | 30-1/4   | 26       |\n                                        |---------+----------+----------|\n                       {Greenish blue   | 46      | 34-1/2   | 29-2/3   |\nOf the fifth Order,    {Red             | 52-1/2  | 39-3/8   | 34       |\n                                        |---------+----------+----------|\n                       {Greenish blue   | 58-3/4  | 44       | 38       |\nOf the sixth Order,    {Red             | 65      | 48-3/4   | 42       |\n                                        |---------+----------+----------|\nOf the seventh Order,  {Greenish blue   | 71      | 53-1/4   | 45-4/5   |\n                       {Ruddy White     | 77      | 57-3/4   | 49-2/3   |\n                                        |---------+----------+----------|\n\nThere are also other Uses of this Table: For by its assistance the\nthickness of the Bubble in the 19th Observation was determin'd by the\nColours which it exhibited. And so the bigness of the parts of natural\nBodies may be conjectured by their Colours, as shall be hereafter shewn.\nAlso, if two or more very thin Plates be laid one upon another, so as to\ncompose one Plate equalling them all in thickness, the resulting Colour\nmay be hereby determin'd. For instance, Mr. _Hook_ observed, as is\nmentioned in his _Micrographia_, that a faint yellow Plate of _Muscovy_\nGlass laid upon a blue one, constituted a very deep purple. The yellow\nof the first Order is a faint one, and the thickness of the Plate\nexhibiting it, according to the Table is 4-3/5, to which add 9, the\nthickness exhibiting blue of the second Order, and the Sum will be\n13-3/5, which is the thickness exhibiting the purple of the third Order.\n\nTo explain, in the next place, the circumstances of the 2d and 3d\nObservations; that is, how the Rings of the Colours may (by turning the\nPrisms about their common Axis the contrary way to that expressed in\nthose Observations) be converted into white and black Rings, and\nafterwards into Rings of Colours again, the Colours of each Ring lying\nnow in an inverted order; it must be remember'd, that those Rings of\nColours are dilated by the obliquation of the Rays to the Air which\nintercedes the Glasses, and that according to the Table in the 7th\nObservation, their Dilatation or Increase of their Diameter is most\nmanifest and speedy when they are obliquest. Now the Rays of yellow\nbeing more refracted by the first Superficies of the said Air than those\nof red, are thereby made more oblique to the second Superficies, at\nwhich they are reflected to produce the colour'd Rings, and consequently\nthe yellow Circle in each Ring will be more dilated than the red; and\nthe Excess of its Dilatation will be so much the greater, by how much\nthe greater is the obliquity of the Rays, until at last it become of\nequal extent with the red of the same Ring. And for the same reason the\ngreen, blue and violet, will be also so much dilated by the still\ngreater obliquity of their Rays, as to become all very nearly of equal\nextent with the red, that is, equally distant from the center of the\nRings. And then all the Colours of the same Ring must be co-incident,\nand by their mixture exhibit a white Ring. And these white Rings must\nhave black and dark Rings between them, because they do not spread and\ninterfere with one another, as before. And for that reason also they\nmust become distincter, and visible to far greater numbers. But yet the\nviolet being obliquest will be something more dilated, in proportion to\nits extent, than the other Colours, and so very apt to appear at the\nexterior Verges of the white.\n\nAfterwards, by a greater obliquity of the Rays, the violet and blue\nbecome more sensibly dilated than the red and yellow, and so being\nfarther removed from the center of the Rings, the Colours must emerge\nout of the white in an order contrary to that which they had before; the\nviolet and blue at the exterior Limbs of each Ring, and the red and\nyellow at the interior. And the violet, by reason of the greatest\nobliquity of its Rays, being in proportion most of all expanded, will\nsoonest appear at the exterior Limb of each white Ring, and become more\nconspicuous than the rest. And the several Series of Colours belonging\nto the several Rings, will, by their unfolding and spreading, begin\nagain to interfere, and thereby render the Rings less distinct, and not\nvisible to so great numbers.\n\nIf instead of the Prisms the Object-glasses be made use of, the Rings\nwhich they exhibit become not white and distinct by the obliquity of the\nEye, by reason that the Rays in their passage through that Air which\nintercedes the Glasses are very nearly parallel to those Lines in which\nthey were first incident on the Glasses, and consequently the Rays\nendued with several Colours are not inclined one more than another to\nthat Air, as it happens in the Prisms.\n\nThere is yet another circumstance of these Experiments to be consider'd,\nand that is why the black and white Rings which when view'd at a\ndistance appear distinct, should not only become confused by viewing\nthem near at hand, but also yield a violet Colour at both the edges of\nevery white Ring. And the reason is, that the Rays which enter the Eye\nat several parts of the Pupil, have several Obliquities to the Glasses,\nand those which are most oblique, if consider'd apart, would represent\nthe Rings bigger than those which are the least oblique. Whence the\nbreadth of the Perimeter of every white Ring is expanded outwards by the\nobliquest Rays, and inwards by the least oblique. And this Expansion is\nso much the greater by how much the greater is the difference of the\nObliquity; that is, by how much the Pupil is wider, or the Eye nearer to\nthe Glasses. And the breadth of the violet must be most expanded,\nbecause the Rays apt to excite a Sensation of that Colour are most\noblique to a second or farther Superficies of the thinn'd Air at which\nthey are reflected, and have also the greatest variation of Obliquity,\nwhich makes that Colour soonest emerge out of the edges of the white.\nAnd as the breadth of every Ring is thus augmented, the dark Intervals\nmust be diminish'd, until the neighbouring Rings become continuous, and\nare blended, the exterior first, and then those nearer the center; so\nthat they can no longer be distinguish'd apart, but seem to constitute\nan even and uniform whiteness.\n\nAmong all the Observations there is none accompanied with so odd\ncircumstances as the twenty-fourth. Of those the principal are, that in\nthin Plates, which to the naked Eye seem of an even and uniform\ntransparent whiteness, without any terminations of Shadows, the\nRefraction of a Prism should make Rings of Colours appear, whereas it\nusually makes Objects appear colour'd only there where they are\nterminated with Shadows, or have parts unequally luminous; and that it\nshould make those Rings exceedingly distinct and white, although it\nusually renders Objects confused and coloured. The Cause of these things\nyou will understand by considering, that all the Rings of Colours are\nreally in the Plate, when view'd with the naked Eye, although by reason\nof the great breadth of their Circumferences they so much interfere and\nare blended together, that they seem to constitute an uniform whiteness.\nBut when the Rays pass through the Prism to the Eye, the Orbits of the\nseveral Colours in every Ring are refracted, some more than others,\naccording to their degrees of Refrangibility: By which means the Colours\non one side of the Ring (that is in the circumference on one side of its\ncenter), become more unfolded and dilated, and those on the other side\nmore complicated and contracted. And where by a due Refraction they are\nso much contracted, that the several Rings become narrower than to\ninterfere with one another, they must appear distinct, and also white,\nif the constituent Colours be so much contracted as to be wholly\nco-incident. But on the other side, where the Orbit of every Ring is\nmade broader by the farther unfolding of its Colours, it must interfere\nmore with other Rings than before, and so become less distinct.\n\n[Illustration: FIG. 7.]\n\nTo explain this a little farther, suppose the concentrick Circles AV,\nand BX, [in _Fig._ 7.] represent the red and violet of any Order, which,\ntogether with the intermediate Colours, constitute any one of these\nRings. Now these being view'd through a Prism, the violet Circle BX,\nwill, by a greater Refraction, be farther translated from its place than\nthe red AV, and so approach nearer to it on that side of the Circles,\ntowards which the Refractions are made. For instance, if the red be\ntranslated to _av_, the violet may be translated to _bx_, so as to\napproach nearer to it at _x_ than before; and if the red be farther\ntranslated to av, the violet may be so much farther translated to bx as\nto convene with it at x; and if the red be yet farther translated to\n[Greek: aY], the violet may be still so much farther translated to\n[Greek: bx] as to pass beyond it at [Greek: x], and convene with it at\n_e_ and _f_. And this being understood not only of the red and violet,\nbut of all the other intermediate Colours, and also of every revolution\nof those Colours, you will easily perceive how those of the same\nrevolution or order, by their nearness at _xv_ and [Greek: Yx], and\ntheir coincidence at xv, _e_ and _f_, ought to constitute pretty\ndistinct Arcs of Circles, especially at xv, or at _e_ and _f_; and that\nthey will appear severally at _x_[Greek: u] and at xv exhibit whiteness\nby their coincidence, and again appear severally at [Greek: Yx], but yet\nin a contrary order to that which they had before, and still retain\nbeyond _e_ and _f_. But on the other side, at _ab_, ab, or [Greek: ab],\nthese Colours must become much more confused by being dilated and spread\nso as to interfere with those of other Orders. And the same confusion\nwill happen at [Greek: Ux] between _e_ and _f_, if the Refraction be\nvery great, or the Prism very distant from the Object-glasses: In which\ncase no parts of the Rings will be seen, save only two little Arcs at\n_e_ and _f_, whose distance from one another will be augmented by\nremoving the Prism still farther from the Object-glasses: And these\nlittle Arcs must be distinctest and whitest at their middle, and at\ntheir ends, where they begin to grow confused, they must be colour'd.\nAnd the Colours at one end of every Arc must be in a contrary order to\nthose at the other end, by reason that they cross in the intermediate\nwhite; namely, their ends, which verge towards [Greek: Ux], will be red\nand yellow on that side next the center, and blue and violet on the\nother side. But their other ends which verge from [Greek: Ux], will on\nthe contrary be blue and violet on that side towards the center, and on\nthe other side red and yellow.\n\nNow as all these things follow from the properties of Light by a\nmathematical way of reasoning, so the truth of them may be manifested by\nExperiments. For in a dark Room, by viewing these Rings through a Prism,\nby reflexion of the several prismatick Colours, which an assistant\ncauses to move to and fro upon a Wall or Paper from whence they are\nreflected, whilst the Spectator's Eye, the Prism, and the\nObject-glasses, (as in the 13th Observation,) are placed steady; the\nPosition of the Circles made successively by the several Colours, will\nbe found such, in respect of one another, as I have described in the\nFigures _abxv_, or abxv, or _[Greek: abxU]_. And by the same method the\ntruth of the Explications of other Observations may be examined.\n\nBy what hath been said, the like Phænomena of Water and thin Plates of\nGlass may be understood. But in small fragments of those Plates there is\nthis farther observable, that where they lie flat upon a Table, and are\nturned about their centers whilst they are view'd through a Prism, they\nwill in some postures exhibit Waves of various Colours; and some of them\nexhibit these Waves in one or two Positions only, but the most of them\ndo in all Positions exhibit them, and make them for the most part appear\nalmost all over the Plates. The reason is, that the Superficies of such\nPlates are not even, but have many Cavities and Swellings, which, how\nshallow soever, do a little vary the thickness of the Plate. For at the\nseveral sides of those Cavities, for the Reasons newly described, there\nought to be produced Waves in several postures of the Prism. Now though\nit be but some very small and narrower parts of the Glass, by which\nthese Waves for the most part are caused, yet they may seem to extend\nthemselves over the whole Glass, because from the narrowest of those\nparts there are Colours of several Orders, that is, of several Rings,\nconfusedly reflected, which by Refraction of the Prism are unfolded,\nseparated, and, according to their degrees of Refraction, dispersed to\nseveral places, so as to constitute so many several Waves, as there were\ndivers orders of Colours promiscuously reflected from that part of the\nGlass.\n\nThese are the principal Phænomena of thin Plates or Bubbles, whose\nExplications depend on the properties of Light, which I have heretofore\ndeliver'd. And these you see do necessarily follow from them, and agree\nwith them, even to their very least circumstances; and not only so, but\ndo very much tend to their proof. Thus, by the 24th Observation it\nappears, that the Rays of several Colours, made as well by thin Plates\nor Bubbles, as by Refractions of a Prism, have several degrees of\nRefrangibility; whereby those of each order, which at the reflexion from\nthe Plate or Bubble are intermix'd with those of other orders, are\nseparated from them by Refraction, and associated together so as to\nbecome visible by themselves like Arcs of Circles. For if the Rays were\nall alike refrangible, 'tis impossible that the whiteness, which to the\nnaked Sense appears uniform, should by Refraction have its parts\ntransposed and ranged into those black and white Arcs.\n\nIt appears also that the unequal Refractions of difform Rays proceed not\nfrom any contingent irregularities; such as are Veins, an uneven Polish,\nor fortuitous Position of the Pores of Glass; unequal and casual Motions\nin the Air or Æther, the spreading, breaking, or dividing the same Ray\ninto many diverging parts; or the like. For, admitting any such\nirregularities, it would be impossible for Refractions to render those\nRings so very distinct, and well defined, as they do in the 24th\nObservation. It is necessary therefore that every Ray have its proper\nand constant degree of Refrangibility connate with it, according to\nwhich its refraction is ever justly and regularly perform'd; and that\nseveral Rays have several of those degrees.\n\nAnd what is said of their Refrangibility may be also understood of their\nReflexibility, that is, of their Dispositions to be reflected, some at a\ngreater, and others at a less thickness of thin Plates or Bubbles;\nnamely, that those Dispositions are also connate with the Rays, and\nimmutable; as may appear by the 13th, 14th, and 15th Observations,\ncompared with the fourth and eighteenth.\n\nBy the Precedent Observations it appears also, that whiteness is a\ndissimilar mixture of all Colours, and that Light is a mixture of Rays\nendued with all those Colours. For, considering the multitude of the\nRings of Colours in the 3d, 12th, and 24th Observations, it is manifest,\nthat although in the 4th and 18th Observations there appear no more than\neight or nine of those Rings, yet there are really a far greater number,\nwhich so much interfere and mingle with one another, as after those\neight or nine revolutions to dilute one another wholly, and constitute\nan even and sensibly uniform whiteness. And consequently that whiteness\nmust be allow'd a mixture of all Colours, and the Light which conveys it\nto the Eye must be a mixture of Rays endued with all those Colours.\n\nBut farther; by the 24th Observation it appears, that there is a\nconstant relation between Colours and Refrangibility; the most\nrefrangible Rays being violet, the least refrangible red, and those of\nintermediate Colours having proportionably intermediate degrees of\nRefrangibility. And by the 13th, 14th, and 15th Observations, compared\nwith the 4th or 18th there appears to be the same constant relation\nbetween Colour and Reflexibility; the violet being in like circumstances\nreflected at least thicknesses of any thin Plate or Bubble, the red at\ngreatest thicknesses, and the intermediate Colours at intermediate\nthicknesses. Whence it follows, that the colorifick Dispositions of\nRays are also connate with them, and immutable; and by consequence, that\nall the Productions and Appearances of Colours in the World are derived,\nnot from any physical Change caused in Light by Refraction or Reflexion,\nbut only from the various Mixtures or Separations of Rays, by virtue of\ntheir different Refrangibility or Reflexibility. And in this respect the\nScience of Colours becomes a Speculation as truly mathematical as any\nother part of Opticks. I mean, so far as they depend on the Nature of\nLight, and are not produced or alter'd by the Power of Imagination, or\nby striking or pressing the Eye.\n\n\n\n\nTHE\n\nSECOND BOOK\n\nOF\n\nOPTICKS\n\n\n_PART III._\n\n_Of the permanent Colours of natural Bodies, and the Analogy between\nthem and the Colours of thin transparent Plates._\n\nI am now come to another part of this Design, which is to consider how\nthe Phænomena of thin transparent Plates stand related to those of all\nother natural Bodies. Of these Bodies I have already told you that they\nappear of divers Colours, accordingly as they are disposed to reflect\nmost copiously the Rays originally endued with those Colours. But their\nConstitutions, whereby they reflect some Rays more copiously than\nothers, remain to be discover'd; and these I shall endeavour to manifest\nin the following Propositions.\n\n\nPROP. I.\n\n_Those Superficies of transparent Bodies reflect the greatest quantity\nof Light, which have the greatest refracting Power; that is, which\nintercede Mediums that differ most in their refractive Densities. And in\nthe Confines of equally refracting Mediums there is no Reflexion._\n\nThe Analogy between Reflexion and Refraction will appear by considering,\nthat when Light passeth obliquely out of one Medium into another which\nrefracts from the perpendicular, the greater is the difference of their\nrefractive Density, the less Obliquity of Incidence is requisite to\ncause a total Reflexion. For as the Sines are which measure the\nRefraction, so is the Sine of Incidence at which the total Reflexion\nbegins, to the Radius of the Circle; and consequently that Angle of\nIncidence is least where there is the greatest difference of the Sines.\nThus in the passing of Light out of Water into Air, where the Refraction\nis measured by the Ratio of the Sines 3 to 4, the total Reflexion begins\nwhen the Angle of Incidence is about 48 Degrees 35 Minutes. In passing\nout of Glass into Air, where the Refraction is measured by the Ratio of\nthe Sines 20 to 31, the total Reflexion begins when the Angle of\nIncidence is 40 Degrees 10 Minutes; and so in passing out of Crystal, or\nmore strongly refracting Mediums into Air, there is still a less\nobliquity requisite to cause a total reflexion. Superficies therefore\nwhich refract most do soonest reflect all the Light which is incident on\nthem, and so must be allowed most strongly reflexive.\n\nBut the truth of this Proposition will farther appear by observing, that\nin the Superficies interceding two transparent Mediums, (such as are\nAir, Water, Oil, common Glass, Crystal, metalline Glasses, Island\nGlasses, white transparent Arsenick, Diamonds, &c.) the Reflexion is\nstronger or weaker accordingly, as the Superficies hath a greater or\nless refracting Power. For in the Confine of Air and Sal-gem 'tis\nstronger than in the Confine of Air and Water, and still stronger in the\nConfine of Air and common Glass or Crystal, and stronger in the Confine\nof Air and a Diamond. If any of these, and such like transparent Solids,\nbe immerged in Water, its Reflexion becomes, much weaker than before;\nand still weaker if they be immerged in the more strongly refracting\nLiquors of well rectified Oil of Vitriol or Spirit of Turpentine. If\nWater be distinguish'd into two parts by any imaginary Surface, the\nReflexion in the Confine of those two parts is none at all. In the\nConfine of Water and Ice 'tis very little; in that of Water and Oil 'tis\nsomething greater; in that of Water and Sal-gem still greater; and in\nthat of Water and Glass, or Crystal or other denser Substances still\ngreater, accordingly as those Mediums differ more or less in their\nrefracting Powers. Hence in the Confine of common Glass and Crystal,\nthere ought to be a weak Reflexion, and a stronger Reflexion in the\nConfine of common and metalline Glass; though I have not yet tried\nthis. But in the Confine of two Glasses of equal density, there is not\nany sensible Reflexion; as was shewn in the first Observation. And the\nsame may be understood of the Superficies interceding two Crystals, or\ntwo Liquors, or any other Substances in which no Refraction is caused.\nSo then the reason why uniform pellucid Mediums (such as Water, Glass,\nor Crystal,) have no sensible Reflexion but in their external\nSuperficies, where they are adjacent to other Mediums of a different\ndensity, is because all their contiguous parts have one and the same\ndegree of density.\n\n\nPROP. II.\n\n_The least parts of almost all natural Bodies are in some measure\ntransparent: And the Opacity of those Bodies ariseth from the multitude\nof Reflexions caused in their internal Parts._\n\nThat this is so has been observed by others, and will easily be granted\nby them that have been conversant with Microscopes. And it may be also\ntried by applying any substance to a hole through which some Light is\nimmitted into a dark Room. For how opake soever that Substance may seem\nin the open Air, it will by that means appear very manifestly\ntransparent, if it be of a sufficient thinness. Only white metalline\nBodies must be excepted, which by reason of their excessive density seem\nto reflect almost all the Light incident on their first Superficies;\nunless by solution in Menstruums they be reduced into very small\nParticles, and then they become transparent.\n\n\nPROP. III.\n\n_Between the parts of opake and colour'd Bodies are many Spaces, either\nempty, or replenish'd with Mediums of other Densities; as Water between\nthe tinging Corpuscles wherewith any Liquor is impregnated, Air between\nthe aqueous Globules that constitute Clouds or Mists; and for the most\npart Spaces void of both Air and Water, but yet perhaps not wholly void\nof all Substance, between the parts of hard Bodies._\n\nThe truth of this is evinced by the two precedent Propositions: For by\nthe second Proposition there are many Reflexions made by the internal\nparts of Bodies, which, by the first Proposition, would not happen if\nthe parts of those Bodies were continued without any such Interstices\nbetween them; because Reflexions are caused only in Superficies, which\nintercede Mediums of a differing density, by _Prop._ 1.\n\nBut farther, that this discontinuity of parts is the principal Cause of\nthe opacity of Bodies, will appear by considering, that opake Substances\nbecome transparent by filling their Pores with any Substance of equal or\nalmost equal density with their parts. Thus Paper dipped in Water or\nOil, the _Oculus Mundi_ Stone steep'd in Water, Linnen Cloth oiled or\nvarnish'd, and many other Substances soaked in such Liquors as will\nintimately pervade their little Pores, become by that means more\ntransparent than otherwise; so, on the contrary, the most transparent\nSubstances, may, by evacuating their Pores, or separating their parts,\nbe render'd sufficiently opake; as Salts or wet Paper, or the _Oculus\nMundi_ Stone by being dried, Horn by being scraped, Glass by being\nreduced to Powder, or otherwise flawed; Turpentine by being stirred\nabout with Water till they mix imperfectly, and Water by being form'd\ninto many small Bubbles, either alone in the form of Froth, or by\nshaking it together with Oil of Turpentine, or Oil Olive, or with some\nother convenient Liquor, with which it will not perfectly incorporate.\nAnd to the increase of the opacity of these Bodies, it conduces\nsomething, that by the 23d Observation the Reflexions of very thin\ntransparent Substances are considerably stronger than those made by the\nsame Substances of a greater thickness.\n\n\nPROP. IV.\n\n_The Parts of Bodies and their Interstices must not be less than of some\ndefinite bigness, to render them opake and colour'd._\n\nFor the opakest Bodies, if their parts be subtilly divided, (as Metals,\nby being dissolved in acid Menstruums, &c.) become perfectly\ntransparent. And you may also remember, that in the eighth Observation\nthere was no sensible reflexion at the Superficies of the\nObject-glasses, where they were very near one another, though they did\nnot absolutely touch. And in the 17th Observation the Reflexion of the\nWater-bubble where it became thinnest was almost insensible, so as to\ncause very black Spots to appear on the top of the Bubble, by the want\nof reflected Light.\n\nOn these grounds I perceive it is that Water, Salt, Glass, Stones, and\nsuch like Substances, are transparent. For, upon divers Considerations,\nthey seem to be as full of Pores or Interstices between their parts as\nother Bodies are, but yet their Parts and Interstices to be too small to\ncause Reflexions in their common Surfaces.\n\n\nPROP. V.\n\n_The transparent parts of Bodies, according to their several sizes,\nreflect Rays of one Colour, and transmit those of another, on the same\ngrounds that thin Plates or Bubbles do reflect or transmit those Rays.\nAnd this I take to be the ground of all their Colours._\n\nFor if a thinn'd or plated Body, which being of an even thickness,\nappears all over of one uniform Colour, should be slit into Threads, or\nbroken into Fragments, of the same thickness with the Plate; I see no\nreason why every Thread or Fragment should not keep its Colour, and by\nconsequence why a heap of those Threads or Fragments should not\nconstitute a Mass or Powder of the same Colour, which the Plate\nexhibited before it was broken. And the parts of all natural Bodies\nbeing like so many Fragments of a Plate, must on the same grounds\nexhibit the same Colours.\n\nNow, that they do so will appear by the affinity of their Properties.\nThe finely colour'd Feathers of some Birds, and particularly those of\nPeacocks Tails, do, in the very same part of the Feather, appear of\nseveral Colours in several Positions of the Eye, after the very same\nmanner that thin Plates were found to do in the 7th and 19th\nObservations, and therefore their Colours arise from the thinness of the\ntransparent parts of the Feathers; that is, from the slenderness of the\nvery fine Hairs, or _Capillamenta_, which grow out of the sides of the\ngrosser lateral Branches or Fibres of those Feathers. And to the same\npurpose it is, that the Webs of some Spiders, by being spun very fine,\nhave appeared colour'd, as some have observ'd, and that the colour'd\nFibres of some Silks, by varying the Position of the Eye, do vary their\nColour. Also the Colours of Silks, Cloths, and other Substances, which\nWater or Oil can intimately penetrate, become more faint and obscure by\nbeing immerged in those Liquors, and recover their Vigor again by being\ndried; much after the manner declared of thin Bodies in the 10th and\n21st Observations. Leaf-Gold, some sorts of painted Glass, the Infusion\nof _Lignum Nephriticum_, and some other Substances, reflect one Colour,\nand transmit another; like thin Bodies in the 9th and 20th Observations.\nAnd some of those colour'd Powders which Painters use, may have their\nColours a little changed, by being very elaborately and finely ground.\nWhere I see not what can be justly pretended for those changes, besides\nthe breaking of their parts into less parts by that contrition, after\nthe same manner that the Colour of a thin Plate is changed by varying\nits thickness. For which reason also it is that the colour'd Flowers of\nPlants and Vegetables, by being bruised, usually become more transparent\nthan before, or at least in some degree or other change their Colours.\nNor is it much less to my purpose, that, by mixing divers Liquors, very\nodd and remarkable Productions and Changes of Colours may be effected,\nof which no cause can be more obvious and rational than that the saline\nCorpuscles of one Liquor do variously act upon or unite with the tinging\nCorpuscles of another, so as to make them swell, or shrink, (whereby not\nonly their bulk but their density also may be changed,) or to divide\nthem into smaller Corpuscles, (whereby a colour'd Liquor may become\ntransparent,) or to make many of them associate into one cluster,\nwhereby two transparent Liquors may compose a colour'd one. For we see\nhow apt those saline Menstruums are to penetrate and dissolve Substances\nto which they are applied, and some of them to precipitate what others\ndissolve. In like manner, if we consider the various Phænomena of the\nAtmosphere, we may observe, that when Vapours are first raised, they\nhinder not the transparency of the Air, being divided into parts too\nsmall to cause any Reflexion in their Superficies. But when in order to\ncompose drops of Rain they begin to coalesce and constitute Globules of\nall intermediate sizes, those Globules, when they become of convenient\nsize to reflect some Colours and transmit others, may constitute Clouds\nof various Colours according to their sizes. And I see not what can be\nrationally conceived in so transparent a Substance as Water for the\nproduction of these Colours, besides the various sizes of its fluid and\nglobular Parcels.\n\n\nPROP. VI.\n\n_The parts of Bodies on which their Colours depend, are denser than the\nMedium which pervades their Interstices._\n\nThis will appear by considering, that the Colour of a Body depends not\nonly on the Rays which are incident perpendicularly on its parts, but on\nthose also which are incident at all other Angles. And that according to\nthe 7th Observation, a very little variation of obliquity will change\nthe reflected Colour, where the thin Body or small Particles is rarer\nthan the ambient Medium, insomuch that such a small Particle will at\ndiversly oblique Incidences reflect all sorts of Colours, in so great a\nvariety that the Colour resulting from them all, confusedly reflected\nfrom a heap of such Particles, must rather be a white or grey than any\nother Colour, or at best it must be but a very imperfect and dirty\nColour. Whereas if the thin Body or small Particle be much denser than\nthe ambient Medium, the Colours, according to the 19th Observation, are\nso little changed by the variation of obliquity, that the Rays which\nare reflected least obliquely may predominate over the rest, so much as\nto cause a heap of such Particles to appear very intensely of their\nColour.\n\nIt conduces also something to the confirmation of this Proposition,\nthat, according to the 22d Observation, the Colours exhibited by the\ndenser thin Body within the rarer, are more brisk than those exhibited\nby the rarer within the denser.\n\n\nPROP. VII.\n\n_The bigness of the component parts of natural Bodies may be conjectured\nby their Colours._\n\nFor since the parts of these Bodies, by _Prop._ 5. do most probably\nexhibit the same Colours with a Plate of equal thickness, provided they\nhave the same refractive density; and since their parts seem for the\nmost part to have much the same density with Water or Glass, as by many\ncircumstances is obvious to collect; to determine the sizes of those\nparts, you need only have recourse to the precedent Tables, in which the\nthickness of Water or Glass exhibiting any Colour is expressed. Thus if\nit be desired to know the diameter of a Corpuscle, which being of equal\ndensity with Glass shall reflect green of the third Order; the Number\n16-1/4 shews it to be (16-1/4)/10000 parts of an Inch.\n\nThe greatest difficulty is here to know of what Order the Colour of any\nBody is. And for this end we must have recourse to the 4th and 18th\nObservations; from whence may be collected these particulars.\n\n_Scarlets_, and other _reds_, _oranges_, and _yellows_, if they be pure\nand intense, are most probably of the second order. Those of the first\nand third order also may be pretty good; only the yellow of the first\norder is faint, and the orange and red of the third Order have a great\nMixture of violet and blue.\n\nThere may be good _Greens_ of the fourth Order, but the purest are of\nthe third. And of this Order the green of all Vegetables seems to be,\npartly by reason of the Intenseness of their Colours, and partly because\nwhen they wither some of them turn to a greenish yellow, and others to a\nmore perfect yellow or orange, or perhaps to red, passing first through\nall the aforesaid intermediate Colours. Which Changes seem to be\neffected by the exhaling of the Moisture which may leave the tinging\nCorpuscles more dense, and something augmented by the Accretion of the\noily and earthy Part of that Moisture. Now the green, without doubt, is\nof the same Order with those Colours into which it changeth, because the\nChanges are gradual, and those Colours, though usually not very full,\nyet are often too full and lively to be of the fourth Order.\n\n_Blues_ and _Purples_ may be either of the second or third Order, but\nthe best are of the third. Thus the Colour of Violets seems to be of\nthat Order, because their Syrup by acid Liquors turns red, and by\nurinous and alcalizate turns green. For since it is of the Nature of\nAcids to dissolve or attenuate, and of Alcalies to precipitate or\nincrassate, if the Purple Colour of the Syrup was of the second Order,\nan acid Liquor by attenuating its tinging Corpuscles would change it to\na red of the first Order, and an Alcali by incrassating them would\nchange it to a green of the second Order; which red and green,\nespecially the green, seem too imperfect to be the Colours produced by\nthese Changes. But if the said Purple be supposed of the third Order,\nits Change to red of the second, and green of the third, may without any\nInconvenience be allow'd.\n\nIf there be found any Body of a deeper and less reddish Purple than that\nof the Violets, its Colour most probably is of the second Order. But yet\nthere being no Body commonly known whose Colour is constantly more deep\nthan theirs, I have made use of their Name to denote the deepest and\nleast reddish Purples, such as manifestly transcend their Colour in\npurity.\n\nThe _blue_ of the first Order, though very faint and little, may\npossibly be the Colour of some Substances; and particularly the azure\nColour of the Skies seems to be of this Order. For all Vapours when they\nbegin to condense and coalesce into small Parcels, become first of that\nBigness, whereby such an Azure must be reflected before they can\nconstitute Clouds of other Colours. And so this being the first Colour\nwhich Vapours begin to reflect, it ought to be the Colour of the finest\nand most transparent Skies, in which Vapours are not arrived to that\nGrossness requisite to reflect other Colours, as we find it is by\nExperience.\n\n_Whiteness_, if most intense and luminous, is that of the first Order,\nif less strong and luminous, a Mixture of the Colours of several Orders.\nOf this last kind is the Whiteness of Froth, Paper, Linnen, and most\nwhite Substances; of the former I reckon that of white Metals to be. For\nwhilst the densest of Metals, Gold, if foliated, is transparent, and all\nMetals become transparent if dissolved in Menstruums or vitrified, the\nOpacity of white Metals ariseth not from their Density alone. They being\nless dense than Gold would be more transparent than it, did not some\nother Cause concur with their Density to make them opake. And this Cause\nI take to be such a Bigness of their Particles as fits them to reflect\nthe white of the first order. For, if they be of other Thicknesses they\nmay reflect other Colours, as is manifest by the Colours which appear\nupon hot Steel in tempering it, and sometimes upon the Surface of melted\nMetals in the Skin or Scoria which arises upon them in their cooling.\nAnd as the white of the first order is the strongest which can be made\nby Plates of transparent Substances, so it ought to be stronger in the\ndenser Substances of Metals than in the rarer of Air, Water, and Glass.\nNor do I see but that metallick Substances of such a Thickness as may\nfit them to reflect the white of the first order, may, by reason of\ntheir great Density (according to the Tenor of the first of these\nPropositions) reflect all the Light incident upon them, and so be as\nopake and splendent as it's possible for any Body to be. Gold, or Copper\nmix'd with less than half their Weight of Silver, or Tin, or Regulus of\nAntimony, in fusion, or amalgamed with a very little Mercury, become\nwhite; which shews both that the Particles of white Metals have much\nmore Superficies, and so are smaller, than those of Gold and Copper, and\nalso that they are so opake as not to suffer the Particles of Gold or\nCopper to shine through them. Now it is scarce to be doubted but that\nthe Colours of Gold and Copper are of the second and third order, and\ntherefore the Particles of white Metals cannot be much bigger than is\nrequisite to make them reflect the white of the first order. The\nVolatility of Mercury argues that they are not much bigger, nor may they\nbe much less, lest they lose their Opacity, and become either\ntransparent as they do when attenuated by Vitrification, or by Solution\nin Menstruums, or black as they do when ground smaller, by rubbing\nSilver, or Tin, or Lead, upon other Substances to draw black Lines. The\nfirst and only Colour which white Metals take by grinding their\nParticles smaller, is black, and therefore their white ought to be that\nwhich borders upon the black Spot in the Center of the Rings of Colours,\nthat is, the white of the first order. But, if you would hence gather\nthe Bigness of metallick Particles, you must allow for their Density.\nFor were Mercury transparent, its Density is such that the Sine of\nIncidence upon it (by my Computation) would be to the Sine of its\nRefraction, as 71 to 20, or 7 to 2. And therefore the Thickness of its\nParticles, that they may exhibit the same Colours with those of Bubbles\nof Water, ought to be less than the Thickness of the Skin of those\nBubbles in the Proportion of 2 to 7. Whence it's possible, that the\nParticles of Mercury may be as little as the Particles of some\ntransparent and volatile Fluids, and yet reflect the white of the first\norder.\n\nLastly, for the production of _black_, the Corpuscles must be less than\nany of those which exhibit Colours. For at all greater sizes there is\ntoo much Light reflected to constitute this Colour. But if they be\nsupposed a little less than is requisite to reflect the white and very\nfaint blue of the first order, they will, according to the 4th, 8th,\n17th and 18th Observations, reflect so very little Light as to appear\nintensely black, and yet may perhaps variously refract it to and fro\nwithin themselves so long, until it happen to be stifled and lost, by\nwhich means they will appear black in all positions of the Eye without\nany transparency. And from hence may be understood why Fire, and the\nmore subtile dissolver Putrefaction, by dividing the Particles of\nSubstances, turn them to black, why small quantities of black Substances\nimpart their Colour very freely and intensely to other Substances to\nwhich they are applied; the minute Particles of these, by reason of\ntheir very great number, easily overspreading the gross Particles of\nothers; why Glass ground very elaborately with Sand on a Copper Plate,\n'till it be well polish'd, makes the Sand, together with what is worn\noff from the Glass and Copper, become very black: why black Substances\ndo soonest of all others become hot in the Sun's Light and burn, (which\nEffect may proceed partly from the multitude of Refractions in a little\nroom, and partly from the easy Commotion of so very small Corpuscles;)\nand why blacks are usually a little inclined to a bluish Colour. For\nthat they are so may be seen by illuminating white Paper by Light\nreflected from black Substances. For the Paper will usually appear of a\nbluish white; and the reason is, that black borders in the obscure blue\nof the order described in the 18th Observation, and therefore reflects\nmore Rays of that Colour than of any other.\n\nIn these Descriptions I have been the more particular, because it is not\nimpossible but that Microscopes may at length be improved to the\ndiscovery of the Particles of Bodies on which their Colours depend, if\nthey are not already in some measure arrived to that degree of\nperfection. For if those Instruments are or can be so far improved as\nwith sufficient distinctness to represent Objects five or six hundred\ntimes bigger than at a Foot distance they appear to our naked Eyes, I\nshould hope that we might be able to discover some of the greatest of\nthose Corpuscles. And by one that would magnify three or four thousand\ntimes perhaps they might all be discover'd, but those which produce\nblackness. In the mean while I see nothing material in this Discourse\nthat may rationally be doubted of, excepting this Position: That\ntransparent Corpuscles of the same thickness and density with a Plate,\ndo exhibit the same Colour. And this I would have understood not without\nsome Latitude, as well because those Corpuscles may be of irregular\nFigures, and many Rays must be obliquely incident on them, and so have\na shorter way through them than the length of their Diameters, as\nbecause the straitness of the Medium put in on all sides within such\nCorpuscles may a little alter its Motions or other qualities on which\nthe Reflexion depends. But yet I cannot much suspect the last, because I\nhave observed of some small Plates of Muscovy Glass which were of an\neven thickness, that through a Microscope they have appeared of the same\nColour at their edges and corners where the included Medium was\nterminated, which they appeared of in other places. However it will add\nmuch to our Satisfaction, if those Corpuscles can be discover'd with\nMicroscopes; which if we shall at length attain to, I fear it will be\nthe utmost improvement of this Sense. For it seems impossible to see the\nmore secret and noble Works of Nature within the Corpuscles by reason of\ntheir transparency.\n\n\nPROP. VIII.\n\n_The Cause of Reflexion is not the impinging of Light on the solid or\nimpervious parts of Bodies, as is commonly believed._\n\nThis will appear by the following Considerations. First, That in the\npassage of Light out of Glass into Air there is a Reflexion as strong as\nin its passage out of Air into Glass, or rather a little stronger, and\nby many degrees stronger than in its passage out of Glass into Water.\nAnd it seems not probable that Air should have more strongly reflecting\nparts than Water or Glass. But if that should possibly be supposed, yet\nit will avail nothing; for the Reflexion is as strong or stronger when\nthe Air is drawn away from the Glass, (suppose by the Air-Pump invented\nby _Otto Gueriet_, and improved and made useful by Mr. _Boyle_) as when\nit is adjacent to it. Secondly, If Light in its passage out of Glass\ninto Air be incident more obliquely than at an Angle of 40 or 41 Degrees\nit is wholly reflected, if less obliquely it is in great measure\ntransmitted. Now it is not to be imagined that Light at one degree of\nobliquity should meet with Pores enough in the Air to transmit the\ngreater part of it, and at another degree of obliquity should meet with\nnothing but parts to reflect it wholly, especially considering that in\nits passage out of Air into Glass, how oblique soever be its Incidence,\nit finds Pores enough in the Glass to transmit a great part of it. If\nany Man suppose that it is not reflected by the Air, but by the outmost\nsuperficial parts of the Glass, there is still the same difficulty:\nBesides, that such a Supposition is unintelligible, and will also appear\nto be false by applying Water behind some part of the Glass instead of\nAir. For so in a convenient obliquity of the Rays, suppose of 45 or 46\nDegrees, at which they are all reflected where the Air is adjacent to\nthe Glass, they shall be in great measure transmitted where the Water is\nadjacent to it; which argues, that their Reflexion or Transmission\ndepends on the constitution of the Air and Water behind the Glass, and\nnot on the striking of the Rays upon the parts of the Glass. Thirdly,\nIf the Colours made by a Prism placed at the entrance of a Beam of Light\ninto a darken'd Room be successively cast on a second Prism placed at a\ngreater distance from the former, in such manner that they are all alike\nincident upon it, the second Prism may be so inclined to the incident\nRays, that those which are of a blue Colour shall be all reflected by\nit, and yet those of a red Colour pretty copiously transmitted. Now if\nthe Reflexion be caused by the parts of Air or Glass, I would ask, why\nat the same Obliquity of Incidence the blue should wholly impinge on\nthose parts, so as to be all reflected, and yet the red find Pores\nenough to be in a great measure transmitted. Fourthly, Where two Glasses\ntouch one another, there is no sensible Reflexion, as was declared in\nthe first Observation; and yet I see no reason why the Rays should not\nimpinge on the parts of Glass, as much when contiguous to other Glass as\nwhen contiguous to Air. Fifthly, When the top of a Water-Bubble (in the\n17th Observation,) by the continual subsiding and exhaling of the Water\ngrew very thin, there was such a little and almost insensible quantity\nof Light reflected from it, that it appeared intensely black; whereas\nround about that black Spot, where the Water was thicker, the Reflexion\nwas so strong as to make the Water seem very white. Nor is it only at\nthe least thickness of thin Plates or Bubbles, that there is no manifest\nReflexion, but at many other thicknesses continually greater and\ngreater. For in the 15th Observation the Rays of the same Colour were by\nturns transmitted at one thickness, and reflected at another thickness,\nfor an indeterminate number of Successions. And yet in the Superficies\nof the thinned Body, where it is of any one thickness, there are as many\nparts for the Rays to impinge on, as where it is of any other thickness.\nSixthly, If Reflexion were caused by the parts of reflecting Bodies, it\nwould be impossible for thin Plates or Bubbles, at one and the same\nplace, to reflect the Rays of one Colour, and transmit those of another,\nas they do according to the 13th and 15th Observations. For it is not to\nbe imagined that at one place the Rays which, for instance, exhibit a\nblue Colour, should have the fortune to dash upon the parts, and those\nwhich exhibit a red to hit upon the Pores of the Body; and then at\nanother place, where the Body is either a little thicker or a little\nthinner, that on the contrary the blue should hit upon its pores, and\nthe red upon its parts. Lastly, Were the Rays of Light reflected by\nimpinging on the solid parts of Bodies, their Reflexions from polish'd\nBodies could not be so regular as they are. For in polishing Glass with\nSand, Putty, or Tripoly, it is not to be imagined that those Substances\ncan, by grating and fretting the Glass, bring all its least Particles to\nan accurate Polish; so that all their Surfaces shall be truly plain or\ntruly spherical, and look all the same way, so as together to compose\none even Surface. The smaller the Particles of those Substances are, the\nsmaller will be the Scratches by which they continually fret and wear\naway the Glass until it be polish'd; but be they never so small they can\nwear away the Glass no otherwise than by grating and scratching it, and\nbreaking the Protuberances; and therefore polish it no otherwise than by\nbringing its roughness to a very fine Grain, so that the Scratches and\nFrettings of the Surface become too small to be visible. And therefore\nif Light were reflected by impinging upon the solid parts of the Glass,\nit would be scatter'd as much by the most polish'd Glass as by the\nroughest. So then it remains a Problem, how Glass polish'd by fretting\nSubstances can reflect Light so regularly as it does. And this Problem\nis scarce otherwise to be solved, than by saying, that the Reflexion of\na Ray is effected, not by a single point of the reflecting Body, but by\nsome power of the Body which is evenly diffused all over its Surface,\nand by which it acts upon the Ray without immediate Contact. For that\nthe parts of Bodies do act upon Light at a distance shall be shewn\nhereafter.\n\nNow if Light be reflected, not by impinging on the solid parts of\nBodies, but by some other principle; it's probable that as many of its\nRays as impinge on the solid parts of Bodies are not reflected but\nstifled and lost in the Bodies. For otherwise we must allow two sorts of\nReflexions. Should all the Rays be reflected which impinge on the\ninternal parts of clear Water or Crystal, those Substances would rather\nhave a cloudy Colour than a clear Transparency. To make Bodies look\nblack, it's necessary that many Rays be stopp'd, retained, and lost in\nthem; and it seems not probable that any Rays can be stopp'd and\nstifled in them which do not impinge on their parts.\n\nAnd hence we may understand that Bodies are much more rare and porous\nthan is commonly believed. Water is nineteen times lighter, and by\nconsequence nineteen times rarer than Gold; and Gold is so rare as very\nreadily and without the least opposition to transmit the magnetick\nEffluvia, and easily to admit Quicksilver into its Pores, and to let\nWater pass through it. For a concave Sphere of Gold filled with Water,\nand solder'd up, has, upon pressing the Sphere with great force, let the\nWater squeeze through it, and stand all over its outside in multitudes\nof small Drops, like Dew, without bursting or cracking the Body of the\nGold, as I have been inform'd by an Eye witness. From all which we may\nconclude, that Gold has more Pores than solid parts, and by consequence\nthat Water has above forty times more Pores than Parts. And he that\nshall find out an Hypothesis, by which Water may be so rare, and yet not\nbe capable of compression by force, may doubtless by the same Hypothesis\nmake Gold, and Water, and all other Bodies, as much rarer as he pleases;\nso that Light may find a ready passage through transparent Substances.\n\nThe Magnet acts upon Iron through all dense Bodies not magnetick nor red\nhot, without any diminution of its Virtue; as for instance, through\nGold, Silver, Lead, Glass, Water. The gravitating Power of the Sun is\ntransmitted through the vast Bodies of the Planets without any\ndiminution, so as to act upon all their parts to their very centers\nwith the same Force and according to the same Laws, as if the part upon\nwhich it acts were not surrounded with the Body of the Planet, The Rays\nof Light, whether they be very small Bodies projected, or only Motion or\nForce propagated, are moved in right Lines; and whenever a Ray of Light\nis by any Obstacle turned out of its rectilinear way, it will never\nreturn into the same rectilinear way, unless perhaps by very great\naccident. And yet Light is transmitted through pellucid solid Bodies in\nright Lines to very great distances. How Bodies can have a sufficient\nquantity of Pores for producing these Effects is very difficult to\nconceive, but perhaps not altogether impossible. For the Colours of\nBodies arise from the Magnitudes of the Particles which reflect them, as\nwas explained above. Now if we conceive these Particles of Bodies to be\nso disposed amongst themselves, that the Intervals or empty Spaces\nbetween them may be equal in magnitude to them all; and that these\nParticles may be composed of other Particles much smaller, which have as\nmuch empty Space between them as equals all the Magnitudes of these\nsmaller Particles: And that in like manner these smaller Particles are\nagain composed of others much smaller, all which together are equal to\nall the Pores or empty Spaces between them; and so on perpetually till\nyou come to solid Particles, such as have no Pores or empty Spaces\nwithin them: And if in any gross Body there be, for instance, three such\ndegrees of Particles, the least of which are solid; this Body will have\nseven times more Pores than solid Parts. But if there be four such\ndegrees of Particles, the least of which are solid, the Body will have\nfifteen times more Pores than solid Parts. If there be five degrees, the\nBody will have one and thirty times more Pores than solid Parts. If six\ndegrees, the Body will have sixty and three times more Pores than solid\nParts. And so on perpetually. And there are other ways of conceiving how\nBodies may be exceeding porous. But what is really their inward Frame is\nnot yet known to us.\n\n\nPROP. IX.\n\n_Bodies reflect and refract Light by one and the same power, variously\nexercised in various Circumstances._\n\nThis appears by several Considerations. First, Because when Light goes\nout of Glass into Air, as obliquely as it can possibly do. If its\nIncidence be made still more oblique, it becomes totally reflected. For\nthe power of the Glass after it has refracted the Light as obliquely as\nis possible, if the Incidence be still made more oblique, becomes too\nstrong to let any of its Rays go through, and by consequence causes\ntotal Reflexions. Secondly, Because Light is alternately reflected and\ntransmitted by thin Plates of Glass for many Successions, accordingly as\nthe thickness of the Plate increases in an arithmetical Progression. For\nhere the thickness of the Glass determines whether that Power by which\nGlass acts upon Light shall cause it to be reflected, or suffer it to\nbe transmitted. And, Thirdly, because those Surfaces of transparent\nBodies which have the greatest refracting power, reflect the greatest\nquantity of Light, as was shewn in the first Proposition.\n\n\nPROP. X.\n\n_If Light be swifter in Bodies than in Vacuo, in the proportion of the\nSines which measure the Refraction of the Bodies, the Forces of the\nBodies to reflect and refract Light, are very nearly proportional to the\ndensities of the same Bodies; excepting that unctuous and sulphureous\nBodies refract more than others of this same density._\n\n[Illustration: FIG. 8.]\n\nLet AB represent the refracting plane Surface of any Body, and IC a Ray\nincident very obliquely upon the Body in C, so that the Angle ACI may be\ninfinitely little, and let CR be the refracted Ray. From a given Point B\nperpendicular to the refracting Surface erect BR meeting with the\nrefracting Ray CR in R, and if CR represent the Motion of the refracted\nRay, and this Motion be distinguish'd into two Motions CB and BR,\nwhereof CB is parallel to the refracting Plane, and BR perpendicular to\nit: CB shall represent the Motion of the incident Ray, and BR the\nMotion generated by the Refraction, as Opticians have of late explain'd.\n\nNow if any Body or Thing, in moving through any Space of a given breadth\nterminated on both sides by two parallel Planes, be urged forward in all\nparts of that Space by Forces tending directly forwards towards the last\nPlane, and before its Incidence on the first Plane, had no Motion\ntowards it, or but an infinitely little one; and if the Forces in all\nparts of that Space, between the Planes, be at equal distances from the\nPlanes equal to one another, but at several distances be bigger or less\nin any given Proportion, the Motion generated by the Forces in the whole\npassage of the Body or thing through that Space shall be in a\nsubduplicate Proportion of the Forces, as Mathematicians will easily\nunderstand. And therefore, if the Space of activity of the refracting\nSuperficies of the Body be consider'd as such a Space, the Motion of the\nRay generated by the refracting Force of the Body, during its passage\nthrough that Space, that is, the Motion BR, must be in subduplicate\nProportion of that refracting Force. I say therefore, that the Square of\nthe Line BR, and by consequence the refracting Force of the Body, is\nvery nearly as the density of the same Body. For this will appear by the\nfollowing Table, wherein the Proportion of the Sines which measure the\nRefractions of several Bodies, the Square of BR, supposing CB an unite,\nthe Densities of the Bodies estimated by their Specifick Gravities, and\ntheir Refractive Power in respect of their Densities are set down in\nseveral Columns.\n\n---------------------+----------------+----------------+----------+-----------\n                     |                |                |          |\n                     |                | The Square     | The      | The\n                     |                | of BR, to      | density  | refractive\n                     | The Proportion | which the      | and      | Power of\n                     | of the Sines of| refracting     | specifick| the Body\n                     | Incidence and  | force of the   | gravity  | in respect\n   The refracting    | Refraction of  | Body is        | of the   | of its\n      Bodies.        | yellow Light.  | proportionate. | Body.    | density.\n---------------------+----------------+----------------+----------+-----------\nA Pseudo-Topazius,   |                |                |          |\n  being a natural,   |                |                |          |\n  pellucid, brittle, |   23 to   14   |    1'699       |  4'27    |   3979\n  hairy Stone, of a  |                |                |          |\n  yellow Colour.     |                |                |          |\nAir.                 | 3201 to 3200   |    0'000625    |  0'0012  |   5208\nGlass of Antimony.   |   17 to    9   |    2'568       |  5'28    |   4864\nA Selenitis.         |   61 to   41   |    1'213       |  2'252   |   5386\nGlass vulgar.        |   31 to   20   |    1'4025      |  2'58    |   5436\nCrystal of the Rock. |   25 to   16   |    1'445       |  2'65    |   5450\nIsland Crystal.      |    5 to    3   |    1'778       |  2'72    |   6536\nSal Gemmæ.           |   17 to   11   |    1'388       |  2'143   |   6477\nAlume.               |   35 to   24   |    1'1267      |  1'714   |   6570\nBorax.               |   22 to   15   |    1'1511      |  1'714   |   6716\nNiter.               |   32 to   21   |    1'345       |  1'9     |   7079\nDantzick Vitriol.    |  303 to  200   |    1'295       |  1'715   |   7551\nOil of Vitriol.      |   10 to    7   |    1'041       |  1'7     |   6124\nRain Water.          |  529 to  396   |    0'7845      |  1'      |   7845\nGum Arabick.         |   31 to   21   |    1'179       |  1'375   |   8574\nSpirit of Wine well  |                |                |          |\n  rectified.         |  100 to   73   |    0'8765      |  0'866   |  10121\nCamphire.            |    3 to    2   |    1'25        |  0'996   |  12551\nOil Olive.           |   22 to   15   |    1'1511      |  0'913   |  12607\nLinseed Oil.         |   40 to   27   |    1'1948      |  0'932   |  12819\nSpirit of Turpentine.|   25 to   17   |    1'1626      |  0'874   |  13222\nAmber.               |   14 to    9   |    1'42        |  1'04    |  13654\nA Diamond.           |  100 to   41   |    4'949       |  3'4     |  14556\n---------------------+----------------+----------------+----------+-----------\n\nThe Refraction of the Air in this Table is determin'd by that of the\nAtmosphere observed by Astronomers. For, if Light pass through many\nrefracting Substances or Mediums gradually denser and denser, and\nterminated with parallel Surfaces, the Sum of all the Refractions will\nbe equal to the single Refraction which it would have suffer'd in\npassing immediately out of the first Medium into the last. And this\nholds true, though the Number of the refracting Substances be increased\nto Infinity, and the Distances from one another as much decreased, so\nthat the Light may be refracted in every Point of its Passage, and by\ncontinual Refractions bent into a Curve-Line. And therefore the whole\nRefraction of Light in passing through the Atmosphere from the highest\nand rarest Part thereof down to the lowest and densest Part, must be\nequal to the Refraction which it would suffer in passing at like\nObliquity out of a Vacuum immediately into Air of equal Density with\nthat in the lowest Part of the Atmosphere.\n\nNow, although a Pseudo-Topaz, a Selenitis, Rock Crystal, Island Crystal,\nVulgar Glass (that is, Sand melted together) and Glass of Antimony,\nwhich are terrestrial stony alcalizate Concretes, and Air which probably\narises from such Substances by Fermentation, be Substances very\ndiffering from one another in Density, yet by this Table, they have\ntheir refractive Powers almost in the same Proportion to one another as\ntheir Densities are, excepting that the Refraction of that strange\nSubstance, Island Crystal is a little bigger than the rest. And\nparticularly Air, which is 3500 Times rarer than the Pseudo-Topaz, and\n4400 Times rarer than Glass of Antimony, and 2000 Times rarer than the\nSelenitis, Glass vulgar, or Crystal of the Rock, has notwithstanding its\nrarity the same refractive Power in respect of its Density which those\nvery dense Substances have in respect of theirs, excepting so far as\nthose differ from one another.\n\nAgain, the Refraction of Camphire, Oil Olive, Linseed Oil, Spirit of\nTurpentine and Amber, which are fat sulphureous unctuous Bodies, and a\nDiamond, which probably is an unctuous Substance coagulated, have their\nrefractive Powers in Proportion to one another as their Densities\nwithout any considerable Variation. But the refractive Powers of these\nunctuous Substances are two or three Times greater in respect of their\nDensities than the refractive Powers of the former Substances in respect\nof theirs.\n\nWater has a refractive Power in a middle degree between those two sorts\nof Substances, and probably is of a middle nature. For out of it grow\nall vegetable and animal Substances, which consist as well of\nsulphureous fat and inflamable Parts, as of earthy lean and alcalizate\nones.\n\nSalts and Vitriols have refractive Powers in a middle degree between\nthose of earthy Substances and Water, and accordingly are composed of\nthose two sorts of Substances. For by distillation and rectification of\ntheir Spirits a great Part of them goes into Water, and a great Part\nremains behind in the form of a dry fix'd Earth capable of\nVitrification.\n\nSpirit of Wine has a refractive Power in a middle degree between those\nof Water and oily Substances, and accordingly seems to be composed of\nboth, united by Fermentation; the Water, by means of some saline Spirits\nwith which 'tis impregnated, dissolving the Oil, and volatizing it by\nthe Action. For Spirit of Wine is inflamable by means of its oily Parts,\nand being distilled often from Salt of Tartar, grow by every\ndistillation more and more aqueous and phlegmatick. And Chymists\nobserve, that Vegetables (as Lavender, Rue, Marjoram, &c.) distilled\n_per se_, before fermentation yield Oils without any burning Spirits,\nbut after fermentation yield ardent Spirits without Oils: Which shews,\nthat their Oil is by fermentation converted into Spirit. They find also,\nthat if Oils be poured in a small quantity upon fermentating Vegetables,\nthey distil over after fermentation in the form of Spirits.\n\nSo then, by the foregoing Table, all Bodies seem to have their\nrefractive Powers proportional to their Densities, (or very nearly;)\nexcepting so far as they partake more or less of sulphureous oily\nParticles, and thereby have their refractive Power made greater or less.\nWhence it seems rational to attribute the refractive Power of all Bodies\nchiefly, if not wholly, to the sulphureous Parts with which they abound.\nFor it's probable that all Bodies abound more or less with Sulphurs. And\nas Light congregated by a Burning-glass acts most upon sulphureous\nBodies, to turn them into Fire and Flame; so, since all Action is\nmutual, Sulphurs ought to act most upon Light. For that the action\nbetween Light and Bodies is mutual, may appear from this Consideration;\nThat the densest Bodies which refract and reflect Light most strongly,\ngrow hottest in the Summer Sun, by the action of the refracted or\nreflected Light.\n\nI have hitherto explain'd the power of Bodies to reflect and refract,\nand shew'd, that thin transparent Plates, Fibres, and Particles, do,\naccording to their several thicknesses and densities, reflect several\nsorts of Rays, and thereby appear of several Colours; and by consequence\nthat nothing more is requisite for producing all the Colours of natural\nBodies, than the several sizes and densities of their transparent\nParticles. But whence it is that these Plates, Fibres, and Particles,\ndo, according to their several thicknesses and densities, reflect\nseveral sorts of Rays, I have not yet explain'd. To give some insight\ninto this matter, and make way for understanding the next part of this\nBook, I shall conclude this part with a few more Propositions. Those\nwhich preceded respect the nature of Bodies, these the nature of Light:\nFor both must be understood, before the reason of their Actions upon one\nanother can be known. And because the last Proposition depended upon the\nvelocity of Light, I will begin with a Proposition of that kind.\n\n\nPROP. XI.\n\n_Light is propagated from luminous Bodies in time, and spends about\nseven or eight Minutes of an Hour in passing from the Sun to the Earth._\n\nThis was observed first by _Roemer_, and then by others, by means of the\nEclipses of the Satellites of _Jupiter_. For these Eclipses, when the\nEarth is between the Sun and _Jupiter_, happen about seven or eight\nMinutes sooner than they ought to do by the Tables, and when the Earth\nis beyond the Sun they happen about seven or eight Minutes later than\nthey ought to do; the reason being, that the Light of the Satellites has\nfarther to go in the latter case than in the former by the Diameter of\nthe Earth's Orbit. Some inequalities of time may arise from the\nExcentricities of the Orbs of the Satellites; but those cannot answer in\nall the Satellites, and at all times to the Position and Distance of the\nEarth from the Sun. The mean motions of _Jupiter_'s Satellites is also\nswifter in his descent from his Aphelium to his Perihelium, than in his\nascent in the other half of his Orb. But this inequality has no respect\nto the position of the Earth, and in the three interior Satellites is\ninsensible, as I find by computation from the Theory of their Gravity.\n\n\nPROP. XII.\n\n_Every Ray of Light in its passage through any refracting Surface is put\ninto a certain transient Constitution or State, which in the progress of\nthe Ray returns at equal Intervals, and disposes the Ray at every return\nto be easily transmitted through the next refracting Surface, and\nbetween the returns to be easily reflected by it._\n\nThis is manifest by the 5th, 9th, 12th, and 15th Observations. For by\nthose Observations it appears, that one and the same sort of Rays at\nequal Angles of Incidence on any thin transparent Plate, is alternately\nreflected and transmitted for many Successions accordingly as the\nthickness of the Plate increases in arithmetical Progression of the\nNumbers, 0, 1, 2, 3, 4, 5, 6, 7, 8, &c. so that if the first Reflexion\n(that which makes the first or innermost of the Rings of Colours there\ndescribed) be made at the thickness 1, the Rays shall be transmitted at\nthe thicknesses 0, 2, 4, 6, 8, 10, 12, &c. and thereby make the central\nSpot and Rings of Light, which appear by transmission, and be reflected\nat the thickness 1, 3, 5, 7, 9, 11, &c. and thereby make the Rings which\nappear by Reflexion. And this alternate Reflexion and Transmission, as I\ngather by the 24th Observation, continues for above an hundred\nvicissitudes, and by the Observations in the next part of this Book, for\nmany thousands, being propagated from one Surface of a Glass Plate to\nthe other, though the thickness of the Plate be a quarter of an Inch or\nabove: So that this alternation seems to be propagated from every\nrefracting Surface to all distances without end or limitation.\n\nThis alternate Reflexion and Refraction depends on both the Surfaces of\nevery thin Plate, because it depends on their distance. By the 21st\nObservation, if either Surface of a thin Plate of _Muscovy_ Glass be\nwetted, the Colours caused by the alternate Reflexion and Refraction\ngrow faint, and therefore it depends on them both.\n\nIt is therefore perform'd at the second Surface; for if it were\nperform'd at the first, before the Rays arrive at the second, it would\nnot depend on the second.\n\nIt is also influenced by some action or disposition, propagated from the\nfirst to the second, because otherwise at the second it would not depend\non the first. And this action or disposition, in its propagation,\nintermits and returns by equal Intervals, because in all its progress it\ninclines the Ray at one distance from the first Surface to be reflected\nby the second, at another to be transmitted by it, and that by equal\nIntervals for innumerable vicissitudes. And because the Ray is disposed\nto Reflexion at the distances 1, 3, 5, 7, 9, &c. and to Transmission at\nthe distances 0, 2, 4, 6, 8, 10, &c. (for its transmission through the\nfirst Surface, is at the distance 0, and it is transmitted through both\ntogether, if their distance be infinitely little or much less than 1)\nthe disposition to be transmitted at the distances 2, 4, 6, 8, 10, &c.\nis to be accounted a return of the same disposition which the Ray first\nhad at the distance 0, that is at its transmission through the first\nrefracting Surface. All which is the thing I would prove.\n\nWhat kind of action or disposition this is; Whether it consists in a\ncirculating or a vibrating motion of the Ray, or of the Medium, or\nsomething else, I do not here enquire. Those that are averse from\nassenting to any new Discoveries, but such as they can explain by an\nHypothesis, may for the present suppose, that as Stones by falling upon\nWater put the Water into an undulating Motion, and all Bodies by\npercussion excite vibrations in the Air; so the Rays of Light, by\nimpinging on any refracting or reflecting Surface, excite vibrations in\nthe refracting or reflecting Medium or Substance, and by exciting them\nagitate the solid parts of the refracting or reflecting Body, and by\nagitating them cause the Body to grow warm or hot; that the vibrations\nthus excited are propagated in the refracting or reflecting Medium or\nSubstance, much after the manner that vibrations are propagated in the\nAir for causing Sound, and move faster than the Rays so as to overtake\nthem; and that when any Ray is in that part of the vibration which\nconspires with its Motion, it easily breaks through a refracting\nSurface, but when it is in the contrary part of the vibration which\nimpedes its Motion, it is easily reflected; and, by consequence, that\nevery Ray is successively disposed to be easily reflected, or easily\ntransmitted, by every vibration which overtakes it. But whether this\nHypothesis be true or false I do not here consider. I content my self\nwith the bare Discovery, that the Rays of Light are by some cause or\nother alternately disposed to be reflected or refracted for many\nvicissitudes.\n\n\nDEFINITION.\n\n_The returns of the disposition of any Ray to be reflected I will call\nits_ Fits of easy Reflexion, _and those of its disposition to be\ntransmitted its_ Fits of easy Transmission, _and the space it passes\nbetween every return and the next return, the_ Interval of its Fits.\n\n\nPROP. XIII.\n\n_The reason why the Surfaces of all thick transparent Bodies reflect\npart of the Light incident on them, and refract the rest, is, that some\nRays at their Incidence are in Fits of easy Reflexion, and others in\nFits of easy Transmission._\n\nThis may be gather'd from the 24th Observation, where the Light\nreflected by thin Plates of Air and Glass, which to the naked Eye\nappear'd evenly white all over the Plate, did through a Prism appear\nwaved with many Successions of Light and Darkness made by alternate Fits\nof easy Reflexion and easy Transmission, the Prism severing and\ndistinguishing the Waves of which the white reflected Light was\ncomposed, as was explain'd above.\n\nAnd hence Light is in Fits of easy Reflexion and easy Transmission,\nbefore its Incidence on transparent Bodies. And probably it is put into\nsuch fits at its first emission from luminous Bodies, and continues in\nthem during all its progress. For these Fits are of a lasting nature, as\nwill appear by the next part of this Book.\n\nIn this Proposition I suppose the transparent Bodies to be thick;\nbecause if the thickness of the Body be much less than the Interval of\nthe Fits of easy Reflexion and Transmission of the Rays, the Body loseth\nits reflecting power. For if the Rays, which at their entering into the\nBody are put into Fits of easy Transmission, arrive at the farthest\nSurface of the Body before they be out of those Fits, they must be\ntransmitted. And this is the reason why Bubbles of Water lose their\nreflecting power when they grow very thin; and why all opake Bodies,\nwhen reduced into very small parts, become transparent.\n\n\nPROP. XIV.\n\n_Those Surfaces of transparent Bodies, which if the Ray be in a Fit of\nRefraction do refract it most strongly, if the Ray be in a Fit of\nReflexion do reflect it most easily._\n\nFor we shewed above, in _Prop._ 8. that the cause of Reflexion is not\nthe impinging of Light on the solid impervious parts of Bodies, but some\nother power by which those solid parts act on Light at a distance. We\nshewed also in _Prop._ 9. that Bodies reflect and refract Light by one\nand the same power, variously exercised in various circumstances; and in\n_Prop._ 1. that the most strongly refracting Surfaces reflect the most\nLight: All which compared together evince and rarify both this and the\nlast Proposition.\n\n\nPROP. XV.\n\n_In any one and the same sort of Rays, emerging in any Angle out of any\nrefracting Surface into one and the same Medium, the Interval of the\nfollowing Fits of easy Reflexion and Transmission are either accurately\nor very nearly, as the Rectangle of the Secant of the Angle of\nRefraction, and of the Secant of another Angle, whose Sine is the first\nof 106 arithmetical mean Proportionals, between the Sines of Incidence\nand Refraction, counted from the Sine of Refraction._\n\nThis is manifest by the 7th and 19th Observations.\n\n\nPROP. XVI.\n\n_In several sorts of Rays emerging in equal Angles out of any refracting\nSurface into the same Medium, the Intervals of the following Fits of\neasy Reflexion and easy Transmission are either accurately, or very\nnearly, as the Cube-Roots of the Squares of the lengths of a Chord,\nwhich found the Notes in an Eight_, sol, la, fa, sol, la, mi, fa, sol,\n_with all their intermediate degrees answering to the Colours of those\nRays, according to the Analogy described in the seventh Experiment of\nthe second Part of the first Book._\n\nThis is manifest by the 13th and 14th Observations.\n\n\nPROP. XVII.\n\n_If Rays of any sort pass perpendicularly into several Mediums, the\nIntervals of the Fits of easy Reflexion and Transmission in any one\nMedium, are to those Intervals in any other, as the Sine of Incidence to\nthe Sine of Refraction, when the Rays pass out of the first of those two\nMediums into the second._\n\nThis is manifest by the 10th Observation.\n\n\nPROP. XVIII.\n\n_If the Rays which paint the Colour in the Confine of yellow and orange\npass perpendicularly out of any Medium into Air, the Intervals of their\nFits of easy Reflexion are the 1/89000th part of an Inch. And of the\nsame length are the Intervals of their Fits of easy Transmission._\n\nThis is manifest by the 6th Observation. From these Propositions it is\neasy to collect the Intervals of the Fits of easy Reflexion and easy\nTransmission of any sort of Rays refracted in any angle into any Medium;\nand thence to know, whether the Rays shall be reflected or transmitted\nat their subsequent Incidence upon any other pellucid Medium. Which\nthing, being useful for understanding the next part of this Book, was\nhere to be set down. And for the same reason I add the two following\nPropositions.\n\n\nPROP. XIX.\n\n_If any sort of Rays falling on the polite Surface of any pellucid\nMedium be reflected back, the Fits of easy Reflexion, which they have at\nthe point of Reflexion, shall still continue to return; and the Returns\nshall be at distances from the point of Reflexion in the arithmetical\nprogression of the Numbers 2, 4, 6, 8, 10, 12, &c. and between these\nFits the Rays shall be in Fits of easy Transmission._\n\nFor since the Fits of easy Reflexion and easy Transmission are of a\nreturning nature, there is no reason why these Fits, which continued\ntill the Ray arrived at the reflecting Medium, and there inclined the\nRay to Reflexion, should there cease. And if the Ray at the point of\nReflexion was in a Fit of easy Reflexion, the progression of the\ndistances of these Fits from that point must begin from 0, and so be of\nthe Numbers 0, 2, 4, 6, 8, &c. And therefore the progression of the\ndistances of the intermediate Fits of easy Transmission, reckon'd from\nthe same point, must be in the progression of the odd Numbers 1, 3, 5,\n7, 9, &c. contrary to what happens when the Fits are propagated from\npoints of Refraction.\n\n\nPROP. XX.\n\n_The Intervals of the Fits of easy Reflexion and easy Transmission,\npropagated from points of Reflexion into any Medium, are equal to the\nIntervals of the like Fits, which the same Rays would have, if refracted\ninto the same Medium in Angles of Refraction equal to their Angles of\nReflexion._\n\nFor when Light is reflected by the second Surface of thin Plates, it\ngoes out afterwards freely at the first Surface to make the Rings of\nColours which appear by Reflexion; and, by the freedom of its egress,\nmakes the Colours of these Rings more vivid and strong than those which\nappear on the other side of the Plates by the transmitted Light. The\nreflected Rays are therefore in Fits of easy Transmission at their\negress; which would not always happen, if the Intervals of the Fits\nwithin the Plate after Reflexion were not equal, both in length and\nnumber, to their Intervals before it. And this confirms also the\nproportions set down in the former Proposition. For if the Rays both in\ngoing in and out at the first Surface be in Fits of easy Transmission,\nand the Intervals and Numbers of those Fits between the first and second\nSurface, before and after Reflexion, be equal, the distances of the Fits\nof easy Transmission from either Surface, must be in the same\nprogression after Reflexion as before; that is, from the first Surface\nwhich transmitted them in the progression of the even Numbers 0, 2, 4,\n6, 8, &c. and from the second which reflected them, in that of the odd\nNumbers 1, 3, 5, 7, &c. But these two Propositions will become much more\nevident by the Observations in the following part of this Book.\n\n\n\n\nTHE\n\nSECOND BOOK\n\nOF\n\nOPTICKS\n\n\n_PART IV._\n\n_Observations concerning the Reflexions and Colours of thick transparent\npolish'd Plates._\n\nThere is no Glass or Speculum how well soever polished, but, besides the\nLight which it refracts or reflects regularly, scatters every way\nirregularly a faint Light, by means of which the polish'd Surface, when\nilluminated in a dark room by a beam of the Sun's Light, may be easily\nseen in all positions of the Eye. There are certain Phænomena of this\nscatter'd Light, which when I first observed them, seem'd very strange\nand surprizing to me. My Observations were as follows.\n\n_Obs._ 1. The Sun shining into my darken'd Chamber through a hole one\nthird of an Inch wide, I let the intromitted beam of Light fall\nperpendicularly upon a Glass Speculum ground concave on one side and\nconvex on the other, to a Sphere of five Feet and eleven Inches Radius,\nand Quick-silver'd over on the convex side. And holding a white opake\nChart, or a Quire of Paper at the center of the Spheres to which the\nSpeculum was ground, that is, at the distance of about five Feet and\neleven Inches from the Speculum, in such manner, that the beam of Light\nmight pass through a little hole made in the middle of the Chart to the\nSpeculum, and thence be reflected back to the same hole: I observed upon\nthe Chart four or five concentric Irises or Rings of Colours, like\nRain-bows, encompassing the hole much after the manner that those, which\nin the fourth and following Observations of the first part of this Book\nappear'd between the Object-glasses, encompassed the black Spot, but yet\nlarger and fainter than those. These Rings as they grew larger and\nlarger became diluter and fainter, so that the fifth was scarce visible.\nYet sometimes, when the Sun shone very clear, there appear'd faint\nLineaments of a sixth and seventh. If the distance of the Chart from the\nSpeculum was much greater or much less than that of six Feet, the Rings\nbecame dilute and vanish'd. And if the distance of the Speculum from the\nWindow was much greater than that of six Feet, the reflected beam of\nLight would be so broad at the distance of six Feet from the Speculum\nwhere the Rings appear'd, as to obscure one or two of the innermost\nRings. And therefore I usually placed the Speculum at about six Feet\nfrom the Window; so that its Focus might there fall in with the center\nof its concavity at the Rings upon the Chart. And this Posture is always\nto be understood in the following Observations where no other is\nexpress'd.\n\n_Obs._ 2. The Colours of these Rain-bows succeeded one another from the\ncenter outwards, in the same form and order with those which were made\nin the ninth Observation of the first Part of this Book by Light not\nreflected, but transmitted through the two Object-glasses. For, first,\nthere was in their common center a white round Spot of faint Light,\nsomething broader than the reflected beam of Light, which beam sometimes\nfell upon the middle of the Spot, and sometimes by a little inclination\nof the Speculum receded from the middle, and left the Spot white to the\ncenter.\n\nThis white Spot was immediately encompassed with a dark grey or russet,\nand that dark grey with the Colours of the first Iris; which Colours on\nthe inside next the dark grey were a little violet and indigo, and next\nto that a blue, which on the outside grew pale, and then succeeded a\nlittle greenish yellow, and after that a brighter yellow, and then on\nthe outward edge of the Iris a red which on the outside inclined to\npurple.\n\nThis Iris was immediately encompassed with a second, whose Colours were\nin order from the inside outwards, purple, blue, green, yellow, light\nred, a red mix'd with purple.\n\nThen immediately follow'd the Colours of the third Iris, which were in\norder outwards a green inclining to purple, a good green, and a red more\nbright than that of the former Iris.\n\nThe fourth and fifth Iris seem'd of a bluish green within, and red\nwithout, but so faintly that it was difficult to discern the Colours.\n\n_Obs._ 3. Measuring the Diameters of these Rings upon the Chart as\naccurately as I could, I found them also in the same proportion to one\nanother with the Rings made by Light transmitted through the two\nObject-glasses. For the Diameters of the four first of the bright Rings\nmeasured between the brightest parts of their Orbits, at the distance of\nsix Feet from the Speculum were 1-11/16, 2-3/8, 2-11/12, 3-3/8 Inches,\nwhose Squares are in arithmetical progression of the numbers 1, 2, 3, 4.\nIf the white circular Spot in the middle be reckon'd amongst the Rings,\nand its central Light, where it seems to be most luminous, be put\nequipollent to an infinitely little Ring; the Squares of the Diameters\nof the Rings will be in the progression 0, 1, 2, 3, 4, &c. I measured\nalso the Diameters of the dark Circles between these luminous ones, and\nfound their Squares in the progression of the numbers 1/2, 1-1/2, 2-1/2,\n3-1/2, &c. the Diameters of the first four at the distance of six Feet\nfrom the Speculum, being 1-3/16, 2-1/16, 2-2/3, 3-3/20 Inches. If the\ndistance of the Chart from the Speculum was increased or diminished, the\nDiameters of the Circles were increased or diminished proportionally.\n\n_Obs._ 4. By the analogy between these Rings and those described in the\nObservations of the first Part of this Book, I suspected that there\nwere many more of them which spread into one another, and by interfering\nmix'd their Colours, and diluted one another so that they could not be\nseen apart. I viewed them therefore through a Prism, as I did those in\nthe 24th Observation of the first Part of this Book. And when the Prism\nwas so placed as by refracting the Light of their mix'd Colours to\nseparate them, and distinguish the Rings from one another, as it did\nthose in that Observation, I could then see them distincter than before,\nand easily number eight or nine of them, and sometimes twelve or\nthirteen. And had not their Light been so very faint, I question not but\nthat I might have seen many more.\n\n_Obs._ 5. Placing a Prism at the Window to refract the intromitted beam\nof Light, and cast the oblong Spectrum of Colours on the Speculum: I\ncovered the Speculum with a black Paper which had in the middle of it a\nhole to let any one of the Colours pass through to the Speculum, whilst\nthe rest were intercepted by the Paper. And now I found Rings of that\nColour only which fell upon the Speculum. If the Speculum was\nilluminated with red, the Rings were totally red with dark Intervals, if\nwith blue they were totally blue, and so of the other Colours. And when\nthey were illuminated with any one Colour, the Squares of their\nDiameters measured between their most luminous Parts, were in the\narithmetical Progression of the Numbers, 0, 1, 2, 3, 4 and the Squares\nof the Diameters of their dark Intervals in the Progression of the\nintermediate Numbers 1/2, 1-1/2, 2-1/2, 3-1/2. But if the Colour was\nvaried, they varied their Magnitude. In the red they were largest, in\nthe indigo and violet least, and in the intermediate Colours yellow,\ngreen, and blue, they were of several intermediate Bignesses answering\nto the Colour, that is, greater in yellow than in green, and greater in\ngreen than in blue. And hence I knew, that when the Speculum was\nilluminated with white Light, the red and yellow on the outside of the\nRings were produced by the least refrangible Rays, and the blue and\nviolet by the most refrangible, and that the Colours of each Ring spread\ninto the Colours of the neighbouring Rings on either side, after the\nmanner explain'd in the first and second Part of this Book, and by\nmixing diluted one another so that they could not be distinguish'd,\nunless near the Center where they were least mix'd. For in this\nObservation I could see the Rings more distinctly, and to a greater\nNumber than before, being able in the yellow Light to number eight or\nnine of them, besides a faint shadow of a tenth. To satisfy my self how\nmuch the Colours of the several Rings spread into one another, I\nmeasured the Diameters of the second and third Rings, and found them\nwhen made by the Confine of the red and orange to be to the same\nDiameters when made by the Confine of blue and indigo, as 9 to 8, or\nthereabouts. For it was hard to determine this Proportion accurately.\nAlso the Circles made successively by the red, yellow, and green,\ndiffer'd more from one another than those made successively by the\ngreen, blue, and indigo. For the Circle made by the violet was too dark\nto be seen. To carry on the Computation, let us therefore suppose that\nthe Differences of the Diameters of the Circles made by the outmost red,\nthe Confine of red and orange, the Confine of orange and yellow, the\nConfine of yellow and green, the Confine of green and blue, the Confine\nof blue and indigo, the Confine of indigo and violet, and outmost\nviolet, are in proportion as the Differences of the Lengths of a\nMonochord which sound the Tones in an Eight; _sol_, _la_, _fa_, _sol_,\n_la_, _mi_, _fa_, _sol_, that is, as the Numbers 1/9, 1/18, 1/12, 1/12,\n2/27, 1/27, 1/18. And if the Diameter of the Circle made by the Confine\nof red and orange be 9A, and that of the Circle made by the Confine of\nblue and indigo be 8A as above; their difference 9A-8A will be to the\ndifference of the Diameters of the Circles made by the outmost red, and\nby the Confine of red and orange, as 1/18 + 1/12 + 1/12 + 2/27 to 1/9,\nthat is as 8/27 to 1/9, or 8 to 3, and to the difference of the Circles\nmade by the outmost violet, and by the Confine of blue and indigo, as\n1/18 + 1/12 + 1/12 + 2/27 to 1/27 + 1/18, that is, as 8/27 to 5/54, or\nas 16 to 5. And therefore these differences will be 3/8A and 5/16A. Add\nthe first to 9A and subduct the last from 8A, and you will have the\nDiameters of the Circles made by the least and most refrangible Rays\n75/8A and ((61-1/2)/8)A. These diameters are therefore to one another as\n75 to 61-1/2 or 50 to 41, and their Squares as 2500 to 1681, that is, as\n3 to 2 very nearly. Which proportion differs not much from the\nproportion of the Diameters of the Circles made by the outmost red and\noutmost violet, in the 13th Observation of the first part of this Book.\n\n_Obs._ 6. Placing my Eye where these Rings appear'd plainest, I saw the\nSpeculum tinged all over with Waves of Colours, (red, yellow, green,\nblue;) like those which in the Observations of the first part of this\nBook appeared between the Object-glasses, and upon Bubbles of Water, but\nmuch larger. And after the manner of those, they were of various\nmagnitudes in various Positions of the Eye, swelling and shrinking as I\nmoved my Eye this way and that way. They were formed like Arcs of\nconcentrick Circles, as those were; and when my Eye was over against the\ncenter of the concavity of the Speculum, (that is, 5 Feet and 10 Inches\ndistant from the Speculum,) their common center was in a right Line with\nthat center of concavity, and with the hole in the Window. But in other\npostures of my Eye their center had other positions. They appear'd by\nthe Light of the Clouds propagated to the Speculum through the hole in\nthe Window; and when the Sun shone through that hole upon the Speculum,\nhis Light upon it was of the Colour of the Ring whereon it fell, but by\nits splendor obscured the Rings made by the Light of the Clouds, unless\nwhen the Speculum was removed to a great distance from the Window, so\nthat his Light upon it might be broad and faint. By varying the position\nof my Eye, and moving it nearer to or farther from the direct beam of\nthe Sun's Light, the Colour of the Sun's reflected Light constantly\nvaried upon the Speculum, as it did upon my Eye, the same Colour always\nappearing to a Bystander upon my Eye which to me appear'd upon the\nSpeculum. And thence I knew that the Rings of Colours upon the Chart\nwere made by these reflected Colours, propagated thither from the\nSpeculum in several Angles, and that their production depended not upon\nthe termination of Light and Shadow.\n\n_Obs._ 7. By the Analogy of all these Phænomena with those of the like\nRings of Colours described in the first part of this Book, it seemed to\nme that these Colours were produced by this thick Plate of Glass, much\nafter the manner that those were produced by very thin Plates. For, upon\ntrial, I found that if the Quick-silver were rubb'd off from the\nbackside of the Speculum, the Glass alone would cause the same Rings of\nColours, but much more faint than before; and therefore the Phænomenon\ndepends not upon the Quick-silver, unless so far as the Quick-silver by\nincreasing the Reflexion of the backside of the Glass increases the\nLight of the Rings of Colours. I found also that a Speculum of Metal\nwithout Glass made some Years since for optical uses, and very well\nwrought, produced none of those Rings; and thence I understood that\nthese Rings arise not from one specular Surface alone, but depend upon\nthe two Surfaces of the Plate of Glass whereof the Speculum was made,\nand upon the thickness of the Glass between them. For as in the 7th and\n19th Observations of the first part of this Book a thin Plate of Air,\nWater, or Glass of an even thickness appeared of one Colour when the\nRays were perpendicular to it, of another when they were a little\noblique, of another when more oblique, of another when still more\noblique, and so on; so here, in the sixth Observation, the Light which\nemerged out of the Glass in several Obliquities, made the Glass appear\nof several Colours, and being propagated in those Obliquities to the\nChart, there painted Rings of those Colours. And as the reason why a\nthin Plate appeared of several Colours in several Obliquities of the\nRays, was, that the Rays of one and the same sort are reflected by the\nthin Plate at one obliquity and transmitted at another, and those of\nother sorts transmitted where these are reflected, and reflected where\nthese are transmitted: So the reason why the thick Plate of Glass\nwhereof the Speculum was made did appear of various Colours in various\nObliquities, and in those Obliquities propagated those Colours to the\nChart, was, that the Rays of one and the same sort did at one Obliquity\nemerge out of the Glass, at another did not emerge, but were reflected\nback towards the Quick-silver by the hither Surface of the Glass, and\naccordingly as the Obliquity became greater and greater, emerged and\nwere reflected alternately for many Successions; and that in one and the\nsame Obliquity the Rays of one sort were reflected, and those of another\ntransmitted. This is manifest by the fifth Observation of this part of\nthis Book. For in that Observation, when the Speculum was illuminated by\nany one of the prismatick Colours, that Light made many Rings of the\nsame Colour upon the Chart with dark Intervals, and therefore at its\nemergence out of the Speculum was alternately transmitted and not\ntransmitted from the Speculum to the Chart for many Successions,\naccording to the various Obliquities of its Emergence. And when the\nColour cast on the Speculum by the Prism was varied, the Rings became of\nthe Colour cast on it, and varied their bigness with their Colour, and\ntherefore the Light was now alternately transmitted and not transmitted\nfrom the Speculum to the Chart at other Obliquities than before. It\nseemed to me therefore that these Rings were of one and the same\noriginal with those of thin Plates, but yet with this difference, that\nthose of thin Plates are made by the alternate Reflexions and\nTransmissions of the Rays at the second Surface of the Plate, after one\npassage through it; but here the Rays go twice through the Plate before\nthey are alternately reflected and transmitted. First, they go through\nit from the first Surface to the Quick-silver, and then return through\nit from the Quick-silver to the first Surface, and there are either\ntransmitted to the Chart or reflected back to the Quick-silver,\naccordingly as they are in their Fits of easy Reflexion or Transmission\nwhen they arrive at that Surface. For the Intervals of the Fits of the\nRays which fall perpendicularly on the Speculum, and are reflected back\nin the same perpendicular Lines, by reason of the equality of these\nAngles and Lines, are of the same length and number within the Glass\nafter Reflexion as before, by the 19th Proposition of the third part of\nthis Book. And therefore since all the Rays that enter through the\nfirst Surface are in their Fits of easy Transmission at their entrance,\nand as many of these as are reflected by the second are in their Fits of\neasy Reflexion there, all these must be again in their Fits of easy\nTransmission at their return to the first, and by consequence there go\nout of the Glass to the Chart, and form upon it the white Spot of Light\nin the center of the Rings. For the reason holds good in all sorts of\nRays, and therefore all sorts must go out promiscuously to that Spot,\nand by their mixture cause it to be white. But the Intervals of the Fits\nof those Rays which are reflected more obliquely than they enter, must\nbe greater after Reflexion than before, by the 15th and 20th\nPropositions. And thence it may happen that the Rays at their return to\nthe first Surface, may in certain Obliquities be in Fits of easy\nReflexion, and return back to the Quick-silver, and in other\nintermediate Obliquities be again in Fits of easy Transmission, and so\ngo out to the Chart, and paint on it the Rings of Colours about the\nwhite Spot. And because the Intervals of the Fits at equal obliquities\nare greater and fewer in the less refrangible Rays, and less and more\nnumerous in the more refrangible, therefore the less refrangible at\nequal obliquities shall make fewer Rings than the more refrangible, and\nthe Rings made by those shall be larger than the like number of Rings\nmade by these; that is, the red Rings shall be larger than the yellow,\nthe yellow than the green, the green than the blue, and the blue than\nthe violet, as they were really found to be in the fifth Observation.\nAnd therefore the first Ring of all Colours encompassing the white Spot\nof Light shall be red without any violet within, and yellow, and green,\nand blue in the middle, as it was found in the second Observation; and\nthese Colours in the second Ring, and those that follow, shall be more\nexpanded, till they spread into one another, and blend one another by\ninterfering.\n\nThese seem to be the reasons of these Rings in general; and this put me\nupon observing the thickness of the Glass, and considering whether the\ndimensions and proportions of the Rings may be truly derived from it by\ncomputation.\n\n_Obs._ 8. I measured therefore the thickness of this concavo-convex\nPlate of Glass, and found it every where 1/4 of an Inch precisely. Now,\nby the sixth Observation of the first Part of this Book, a thin Plate of\nAir transmits the brightest Light of the first Ring, that is, the bright\nyellow, when its thickness is the 1/89000th part of an Inch; and by the\ntenth Observation of the same Part, a thin Plate of Glass transmits the\nsame Light of the same Ring, when its thickness is less in proportion of\nthe Sine of Refraction to the Sine of Incidence, that is, when its\nthickness is the 11/1513000th or 1/137545th part of an Inch, supposing\nthe Sines are as 11 to 17. And if this thickness be doubled, it\ntransmits the same bright Light of the second Ring; if tripled, it\ntransmits that of the third, and so on; the bright yellow Light in all\nthese cases being in its Fits of Transmission. And therefore if its\nthickness be multiplied 34386 times, so as to become 1/4 of an Inch, it\ntransmits the same bright Light of the 34386th Ring. Suppose this be the\nbright yellow Light transmitted perpendicularly from the reflecting\nconvex side of the Glass through the concave side to the white Spot in\nthe center of the Rings of Colours on the Chart: And by a Rule in the\n7th and 19th Observations in the first Part of this Book, and by the\n15th and 20th Propositions of the third Part of this Book, if the Rays\nbe made oblique to the Glass, the thickness of the Glass requisite to\ntransmit the same bright Light of the same Ring in any obliquity, is to\nthis thickness of 1/4 of an Inch, as the Secant of a certain Angle to\nthe Radius, the Sine of which Angle is the first of an hundred and six\narithmetical Means between the Sines of Incidence and Refraction,\ncounted from the Sine of Incidence when the Refraction is made out of\nany plated Body into any Medium encompassing it; that is, in this case,\nout of Glass into Air. Now if the thickness of the Glass be increased by\ndegrees, so as to bear to its first thickness, (_viz._ that of a quarter\nof an Inch,) the Proportions which 34386 (the number of Fits of the\nperpendicular Rays in going through the Glass towards the white Spot in\nthe center of the Rings,) hath to 34385, 34384, 34383, and 34382, (the\nnumbers of the Fits of the oblique Rays in going through the Glass\ntowards the first, second, third, and fourth Rings of Colours,) and if\nthe first thickness be divided into 100000000 equal parts, the increased\nthicknesses will be 100002908, 100005816, 100008725, and 100011633, and\nthe Angles of which these thicknesses are Secants will be 26´ 13´´, 37´\n5´´, 45´ 6´´, and 52´ 26´´, the Radius being 100000000; and the Sines of\nthese Angles are 762, 1079, 1321, and 1525, and the proportional Sines\nof Refraction 1172, 1659, 2031, and 2345, the Radius being 100000. For\nsince the Sines of Incidence out of Glass into Air are to the Sines of\nRefraction as 11 to 17, and to the above-mentioned Secants as 11 to the\nfirst of 106 arithmetical Means between 11 and 17, that is, as 11 to\n11-6/106, those Secants will be to the Sines of Refraction as 11-6/106,\nto 17, and by this Analogy will give these Sines. So then, if the\nobliquities of the Rays to the concave Surface of the Glass be such that\nthe Sines of their Refraction in passing out of the Glass through that\nSurface into the Air be 1172, 1659, 2031, 2345, the bright Light of the\n34386th Ring shall emerge at the thicknesses of the Glass, which are to\n1/4 of an Inch as 34386 to 34385, 34384, 34383, 34382, respectively. And\ntherefore, if the thickness in all these Cases be 1/4 of an Inch (as it\nis in the Glass of which the Speculum was made) the bright Light of the\n34385th Ring shall emerge where the Sine of Refraction is 1172, and that\nof the 34384th, 34383th, and 34382th Ring where the Sine is 1659, 2031,\nand 2345 respectively. And in these Angles of Refraction the Light of\nthese Rings shall be propagated from the Speculum to the Chart, and\nthere paint Rings about the white central round Spot of Light which we\nsaid was the Light of the 34386th Ring. And the Semidiameters of these\nRings shall subtend the Angles of Refraction made at the\nConcave-Surface of the Speculum, and by consequence their Diameters\nshall be to the distance of the Chart from the Speculum as those Sines\nof Refraction doubled are to the Radius, that is, as 1172, 1659, 2031,\nand 2345, doubled are to 100000. And therefore, if the distance of the\nChart from the Concave-Surface of the Speculum be six Feet (as it was in\nthe third of these Observations) the Diameters of the Rings of this\nbright yellow Light upon the Chart shall be 1'688, 2'389, 2'925, 3'375\nInches: For these Diameters are to six Feet, as the above-mention'd\nSines doubled are to the Radius. Now, these Diameters of the bright\nyellow Rings, thus found by Computation are the very same with those\nfound in the third of these Observations by measuring them, _viz._ with\n1-11/16, 2-3/8, 2-11/12, and 3-3/8 Inches, and therefore the Theory of\nderiving these Rings from the thickness of the Plate of Glass of which\nthe Speculum was made, and from the Obliquity of the emerging Rays\nagrees with the Observation. In this Computation I have equalled the\nDiameters of the bright Rings made by Light of all Colours, to the\nDiameters of the Rings made by the bright yellow. For this yellow makes\nthe brightest Part of the Rings of all Colours. If you desire the\nDiameters of the Rings made by the Light of any other unmix'd Colour,\nyou may find them readily by putting them to the Diameters of the bright\nyellow ones in a subduplicate Proportion of the Intervals of the Fits of\nthe Rays of those Colours when equally inclined to the refracting or\nreflecting Surface which caused those Fits, that is, by putting the\nDiameters of the Rings made by the Rays in the Extremities and Limits of\nthe seven Colours, red, orange, yellow, green, blue, indigo, violet,\nproportional to the Cube-roots of the Numbers, 1, 8/9, 5/6, 3/4, 2/3,\n3/5, 9/16, 1/2, which express the Lengths of a Monochord sounding the\nNotes in an Eighth: For by this means the Diameters of the Rings of\nthese Colours will be found pretty nearly in the same Proportion to one\nanother, which they ought to have by the fifth of these Observations.\n\nAnd thus I satisfy'd my self, that these Rings were of the same kind and\nOriginal with those of thin Plates, and by consequence that the Fits or\nalternate Dispositions of the Rays to be reflected and transmitted are\npropagated to great distances from every reflecting and refracting\nSurface. But yet to put the matter out of doubt, I added the following\nObservation.\n\n_Obs._ 9. If these Rings thus depend on the thickness of the Plate of\nGlass, their Diameters at equal distances from several Speculums made of\nsuch concavo-convex Plates of Glass as are ground on the same Sphere,\nought to be reciprocally in a subduplicate Proportion of the thicknesses\nof the Plates of Glass. And if this Proportion be found true by\nexperience it will amount to a demonstration that these Rings (like\nthose formed in thin Plates) do depend on the thickness of the Glass. I\nprocured therefore another concavo-convex Plate of Glass ground on both\nsides to the same Sphere with the former Plate. Its thickness was 5/62\nParts of an Inch; and the Diameters of the three first bright Rings\nmeasured between the brightest Parts of their Orbits at the distance of\nsix Feet from the Glass were 3·4-1/6·5-1/8· Inches. Now, the thickness\nof the other Glass being 1/4 of an Inch was to the thickness of this\nGlass as 1/4 to 5/62, that is as 31 to 10, or 310000000 to 100000000,\nand the Roots of these Numbers are 17607 and 10000, and in the\nProportion of the first of these Roots to the second are the Diameters\nof the bright Rings made in this Observation by the thinner Glass,\n3·4-1/6·5-1/8, to the Diameters of the same Rings made in the third of\nthese Observations by the thicker Glass 1-11/16, 2-3/8. 2-11/12, that\nis, the Diameters of the Rings are reciprocally in a subduplicate\nProportion of the thicknesses of the Plates of Glass.\n\nSo then in Plates of Glass which are alike concave on one side, and\nalike convex on the other side, and alike quick-silver'd on the convex\nsides, and differ in nothing but their thickness, the Diameters of the\nRings are reciprocally in a subduplicate Proportion of the thicknesses\nof the Plates. And this shews sufficiently that the Rings depend on both\nthe Surfaces of the Glass. They depend on the convex Surface, because\nthey are more luminous when that Surface is quick-silver'd over than\nwhen it is without Quick-silver. They depend also upon the concave\nSurface, because without that Surface a Speculum makes them not. They\ndepend on both Surfaces, and on the distances between them, because\ntheir bigness is varied by varying only that distance. And this\ndependence is of the same kind with that which the Colours of thin\nPlates have on the distance of the Surfaces of those Plates, because the\nbigness of the Rings, and their Proportion to one another, and the\nvariation of their bigness arising from the variation of the thickness\nof the Glass, and the Orders of their Colours, is such as ought to\nresult from the Propositions in the end of the third Part of this Book,\nderived from the Phænomena of the Colours of thin Plates set down in the\nfirst Part.\n\nThere are yet other Phænomena of these Rings of Colours, but such as\nfollow from the same Propositions, and therefore confirm both the Truth\nof those Propositions, and the Analogy between these Rings and the Rings\nof Colours made by very thin Plates. I shall subjoin some of them.\n\n_Obs._ 10. When the beam of the Sun's Light was reflected back from the\nSpeculum not directly to the hole in the Window, but to a place a little\ndistant from it, the common center of that Spot, and of all the Rings of\nColours fell in the middle way between the beam of the incident Light,\nand the beam of the reflected Light, and by consequence in the center of\nthe spherical concavity of the Speculum, whenever the Chart on which the\nRings of Colours fell was placed at that center. And as the beam of\nreflected Light by inclining the Speculum receded more and more from the\nbeam of incident Light and from the common center of the colour'd Rings\nbetween them, those Rings grew bigger and bigger, and so also did the\nwhite round Spot, and new Rings of Colours emerged successively out of\ntheir common center, and the white Spot became a white Ring\nencompassing them; and the incident and reflected beams of Light always\nfell upon the opposite parts of this white Ring, illuminating its\nPerimeter like two mock Suns in the opposite parts of an Iris. So then\nthe Diameter of this Ring, measured from the middle of its Light on one\nside to the middle of its Light on the other side, was always equal to\nthe distance between the middle of the incident beam of Light, and the\nmiddle of the reflected beam measured at the Chart on which the Rings\nappeared: And the Rays which form'd this Ring were reflected by the\nSpeculum in Angles equal to their Angles of Incidence, and by\nconsequence to their Angles of Refraction at their entrance into the\nGlass, but yet their Angles of Reflexion were not in the same Planes\nwith their Angles of Incidence.\n\n_Obs._ 11. The Colours of the new Rings were in a contrary order to\nthose of the former, and arose after this manner. The white round Spot\nof Light in the middle of the Rings continued white to the center till\nthe distance of the incident and reflected beams at the Chart was about\n7/8 parts of an Inch, and then it began to grow dark in the middle. And\nwhen that distance was about 1-3/16 of an Inch, the white Spot was\nbecome a Ring encompassing a dark round Spot which in the middle\ninclined to violet and indigo. And the luminous Rings encompassing it\nwere grown equal to those dark ones which in the four first Observations\nencompassed them, that is to say, the white Spot was grown a white Ring\nequal to the first of those dark Rings, and the first of those luminous\nRings was now grown equal to the second of those dark ones, and the\nsecond of those luminous ones to the third of those dark ones, and so\non. For the Diameters of the luminous Rings were now 1-3/16, 2-1/16,\n2-2/3, 3-3/20, &c. Inches.\n\nWhen the distance between the incident and reflected beams of Light\nbecame a little bigger, there emerged out of the middle of the dark Spot\nafter the indigo a blue, and then out of that blue a pale green, and\nsoon after a yellow and red. And when the Colour at the center was\nbrightest, being between yellow and red, the bright Rings were grown\nequal to those Rings which in the four first Observations next\nencompassed them; that is to say, the white Spot in the middle of those\nRings was now become a white Ring equal to the first of those bright\nRings, and the first of those bright ones was now become equal to the\nsecond of those, and so on. For the Diameters of the white Ring, and of\nthe other luminous Rings encompassing it, were now 1-11/16, 2-3/8,\n2-11/12, 3-3/8, &c. or thereabouts.\n\nWhen the distance of the two beams of Light at the Chart was a little\nmore increased, there emerged out of the middle in order after the red,\na purple, a blue, a green, a yellow, and a red inclining much to purple,\nand when the Colour was brightest being between yellow and red, the\nformer indigo, blue, green, yellow and red, were become an Iris or Ring\nof Colours equal to the first of those luminous Rings which appeared in\nthe four first Observations, and the white Ring which was now become\nthe second of the luminous Rings was grown equal to the second of those,\nand the first of those which was now become the third Ring was become\nequal to the third of those, and so on. For their Diameters were\n1-11/16, 2-3/8, 2-11/12, 3-3/8 Inches, the distance of the two beams of\nLight, and the Diameter of the white Ring being 2-3/8 Inches.\n\nWhen these two beams became more distant there emerged out of the middle\nof the purplish red, first a darker round Spot, and then out of the\nmiddle of that Spot a brighter. And now the former Colours (purple,\nblue, green, yellow, and purplish red) were become a Ring equal to the\nfirst of the bright Rings mentioned in the four first Observations, and\nthe Rings about this Ring were grown equal to the Rings about that\nrespectively; the distance between the two beams of Light and the\nDiameter of the white Ring (which was now become the third Ring) being\nabout 3 Inches.\n\nThe Colours of the Rings in the middle began now to grow very dilute,\nand if the distance between the two Beams was increased half an Inch, or\nan Inch more, they vanish'd whilst the white Ring, with one or two of\nthe Rings next it on either side, continued still visible. But if the\ndistance of the two beams of Light was still more increased, these also\nvanished: For the Light which coming from several parts of the hole in\nthe Window fell upon the Speculum in several Angles of Incidence, made\nRings of several bignesses, which diluted and blotted out one another,\nas I knew by intercepting some part of that Light. For if I intercepted\nthat part which was nearest to the Axis of the Speculum the Rings would\nbe less, if the other part which was remotest from it they would be\nbigger.\n\n_Obs._ 12. When the Colours of the Prism were cast successively on the\nSpeculum, that Ring which in the two last Observations was white, was of\nthe same bigness in all the Colours, but the Rings without it were\ngreater in the green than in the blue, and still greater in the yellow,\nand greatest in the red. And, on the contrary, the Rings within that\nwhite Circle were less in the green than in the blue, and still less in\nthe yellow, and least in the red. For the Angles of Reflexion of those\nRays which made this Ring, being equal to their Angles of Incidence, the\nFits of every reflected Ray within the Glass after Reflexion are equal\nin length and number to the Fits of the same Ray within the Glass before\nits Incidence on the reflecting Surface. And therefore since all the\nRays of all sorts at their entrance into the Glass were in a Fit of\nTransmission, they were also in a Fit of Transmission at their returning\nto the same Surface after Reflexion; and by consequence were\ntransmitted, and went out to the white Ring on the Chart. This is the\nreason why that Ring was of the same bigness in all the Colours, and why\nin a mixture of all it appears white. But in Rays which are reflected in\nother Angles, the Intervals of the Fits of the least refrangible being\ngreatest, make the Rings of their Colour in their progress from this\nwhite Ring, either outwards or inwards, increase or decrease by the\ngreatest steps; so that the Rings of this Colour without are greatest,\nand within least. And this is the reason why in the last Observation,\nwhen the Speculum was illuminated with white Light, the exterior Rings\nmade by all Colours appeared red without and blue within, and the\ninterior blue without and red within.\n\nThese are the Phænomena of thick convexo-concave Plates of Glass, which\nare every where of the same thickness. There are yet other Phænomena\nwhen these Plates are a little thicker on one side than on the other,\nand others when the Plates are more or less concave than convex, or\nplano-convex, or double-convex. For in all these cases the Plates make\nRings of Colours, but after various manners; all which, so far as I have\nyet observed, follow from the Propositions in the end of the third part\nof this Book, and so conspire to confirm the truth of those\nPropositions. But the Phænomena are too various, and the Calculations\nwhereby they follow from those Propositions too intricate to be here\nprosecuted. I content my self with having prosecuted this kind of\nPhænomena so far as to discover their Cause, and by discovering it to\nratify the Propositions in the third Part of this Book.\n\n_Obs._ 13. As Light reflected by a Lens quick-silver'd on the backside\nmakes the Rings of Colours above described, so it ought to make the like\nRings of Colours in passing through a drop of Water. At the first\nReflexion of the Rays within the drop, some Colours ought to be\ntransmitted, as in the case of a Lens, and others to be reflected back\nto the Eye. For instance, if the Diameter of a small drop or globule of\nWater be about the 500th part of an Inch, so that a red-making Ray in\npassing through the middle of this globule has 250 Fits of easy\nTransmission within the globule, and that all the red-making Rays which\nare at a certain distance from this middle Ray round about it have 249\nFits within the globule, and all the like Rays at a certain farther\ndistance round about it have 248 Fits, and all those at a certain\nfarther distance 247 Fits, and so on; these concentrick Circles of Rays\nafter their transmission, falling on a white Paper, will make\nconcentrick Rings of red upon the Paper, supposing the Light which\npasses through one single globule, strong enough to be sensible. And, in\nlike manner, the Rays of other Colours will make Rings of other Colours.\nSuppose now that in a fair Day the Sun shines through a thin Cloud of\nsuch globules of Water or Hail, and that the globules are all of the\nsame bigness; and the Sun seen through this Cloud shall appear\nencompassed with the like concentrick Rings of Colours, and the Diameter\nof the first Ring of red shall be 7-1/4 Degrees, that of the second\n10-1/4 Degrees, that of the third 12 Degrees 33 Minutes. And accordingly\nas the Globules of Water are bigger or less, the Rings shall be less or\nbigger. This is the Theory, and Experience answers it. For in _June_\n1692, I saw by reflexion in a Vessel of stagnating Water three Halos,\nCrowns, or Rings of Colours about the Sun, like three little Rain-bows,\nconcentrick to his Body. The Colours of the first or innermost Crown\nwere blue next the Sun, red without, and white in the middle between the\nblue and red. Those of the second Crown were purple and blue within, and\npale red without, and green in the middle. And those of the third were\npale blue within, and pale red without; these Crowns enclosed one\nanother immediately, so that their Colours proceeded in this continual\norder from the Sun outward: blue, white, red; purple, blue, green, pale\nyellow and red; pale blue, pale red. The Diameter of the second Crown\nmeasured from the middle of the yellow and red on one side of the Sun,\nto the middle of the same Colour on the other side was 9-1/3 Degrees, or\nthereabouts. The Diameters of the first and third I had not time to\nmeasure, but that of the first seemed to be about five or six Degrees,\nand that of the third about twelve. The like Crowns appear sometimes\nabout the Moon; for in the beginning of the Year 1664, _Febr._ 19th at\nNight, I saw two such Crowns about her. The Diameter of the first or\ninnermost was about three Degrees, and that of the second about five\nDegrees and an half. Next about the Moon was a Circle of white, and next\nabout that the inner Crown, which was of a bluish green within next the\nwhite, and of a yellow and red without, and next about these Colours\nwere blue and green on the inside of the outward Crown, and red on the\noutside of it. At the same time there appear'd a Halo about 22 Degrees\n35´ distant from the center of the Moon. It was elliptical, and its long\nDiameter was perpendicular to the Horizon, verging below farthest from\nthe Moon. I am told that the Moon has sometimes three or more\nconcentrick Crowns of Colours encompassing one another next about her\nBody. The more equal the globules of Water or Ice are to one another,\nthe more Crowns of Colours will appear, and the Colours will be the more\nlively. The Halo at the distance of 22-1/2 Degrees from the Moon is of\nanother sort. By its being oval and remoter from the Moon below than\nabove, I conclude, that it was made by Refraction in some sort of Hail\nor Snow floating in the Air in an horizontal posture, the refracting\nAngle being about 58 or 60 Degrees.\n\n\n\n\nTHE\n\nTHIRD BOOK\n\nOF\n\nOPTICKS\n\n\n_PART I._\n\n_Observations concerning the Inflexions of the Rays of Light, and the\nColours made thereby._\n\nGrimaldo has inform'd us, that if a beam of the Sun's Light be let into\na dark Room through a very small hole, the Shadows of things in this\nLight will be larger than they ought to be if the Rays went on by the\nBodies in straight Lines, and that these Shadows have three parallel\nFringes, Bands or Ranks of colour'd Light adjacent to them. But if the\nHole be enlarged the Fringes grow broad and run into one another, so\nthat they cannot be distinguish'd. These broad Shadows and Fringes have\nbeen reckon'd by some to proceed from the ordinary refraction of the\nAir, but without due examination of the Matter. For the circumstances of\nthe Phænomenon, so far as I have observed them, are as follows.\n\n_Obs._ 1. I made in a piece of Lead a small Hole with a Pin, whose\nbreadth was the 42d part of an Inch. For 21 of those Pins laid together\ntook up the breadth of half an Inch. Through this Hole I let into my\ndarken'd Chamber a beam of the Sun's Light, and found that the Shadows\nof Hairs, Thred, Pins, Straws, and such like slender Substances placed\nin this beam of Light, were considerably broader than they ought to be,\nif the Rays of Light passed on by these Bodies in right Lines. And\nparticularly a Hair of a Man's Head, whose breadth was but the 280th\npart of an Inch, being held in this Light, at the distance of about\ntwelve Feet from the Hole, did cast a Shadow which at the distance of\nfour Inches from the Hair was the sixtieth part of an Inch broad, that\nis, above four times broader than the Hair, and at the distance of two\nFeet from the Hair was about the eight and twentieth part of an Inch\nbroad, that is, ten times broader than the Hair, and at the distance of\nten Feet was the eighth part of an Inch broad, that is 35 times broader.\n\nNor is it material whether the Hair be encompassed with Air, or with any\nother pellucid Substance. For I wetted a polish'd Plate of Glass, and\nlaid the Hair in the Water upon the Glass, and then laying another\npolish'd Plate of Glass upon it, so that the Water might fill up the\nspace between the Glasses, I held them in the aforesaid beam of Light,\nso that the Light might pass through them perpendicularly, and the\nShadow of the Hair was at the same distances as big as before. The\nShadows of Scratches made in polish'd Plates of Glass were also much\nbroader than they ought to be, and the Veins in polish'd Plates of Glass\ndid also cast the like broad Shadows. And therefore the great breadth of\nthese Shadows proceeds from some other cause than the Refraction of the\nAir.\n\nLet the Circle X [in _Fig._ 1.] represent the middle of the Hair; ADG,\nBEH, CFI, three Rays passing by one side of the Hair at several\ndistances; KNQ, LOR, MPS, three other Rays passing by the other side of\nthe Hair at the like distances; D, E, F, and N, O, P, the places where\nthe Rays are bent in their passage by the Hair; G, H, I, and Q, R, S,\nthe places where the Rays fall on a Paper GQ; IS the breadth of the\nShadow of the Hair cast on the Paper, and TI, VS, two Rays passing to\nthe Points I and S without bending when the Hair is taken away. And it's\nmanifest that all the Light between these two Rays TI and VS is bent in\npassing by the Hair, and turned aside from the Shadow IS, because if any\npart of this Light were not bent it would fall on the Paper within the\nShadow, and there illuminate the Paper, contrary to experience. And\nbecause when the Paper is at a great distance from the Hair, the Shadow\nis broad, and therefore the Rays TI and VS are at a great distance from\none another, it follows that the Hair acts upon the Rays of Light at a\ngood distance in their passing by it. But the Action is strongest on the\nRays which pass by at least distances, and grows weaker and weaker\naccordingly as the Rays pass by at distances greater and greater, as is\nrepresented in the Scheme: For thence it comes to pass, that the Shadow\nof the Hair is much broader in proportion to the distance of the Paper\nfrom the Hair, when the Paper is nearer the Hair, than when it is at a\ngreat distance from it.\n\n_Obs._ 2. The Shadows of all Bodies (Metals, Stones, Glass, Wood, Horn,\nIce, &c.) in this Light were border'd with three Parallel Fringes or\nBands of colour'd Light, whereof that which was contiguous to the Shadow\nwas broadest and most luminous, and that which was remotest from it was\nnarrowest, and so faint, as not easily to be visible. It was difficult\nto distinguish the Colours, unless when the Light fell very obliquely\nupon a smooth Paper, or some other smooth white Body, so as to make them\nappear much broader than they would otherwise do. And then the Colours\nwere plainly visible in this Order: The first or innermost Fringe was\nviolet and deep blue next the Shadow, and then light blue, green, and\nyellow in the middle, and red without. The second Fringe was almost\ncontiguous to the first, and the third to the second, and both were blue\nwithin, and yellow and red without, but their Colours were very faint,\nespecially those of the third. The Colours therefore proceeded in this\norder from the Shadow; violet, indigo, pale blue, green, yellow, red;\nblue, yellow, red; pale blue, pale yellow and red. The Shadows made by\nScratches and Bubbles in polish'd Plates of Glass were border'd with the\nlike Fringes of colour'd Light. And if Plates of Looking-glass sloop'd\noff near the edges with a Diamond-cut, be held in the same beam of\nLight, the Light which passes through the parallel Planes of the Glass\nwill be border'd with the like Fringes of Colours where those Planes\nmeet with the Diamond-cut, and by this means there will sometimes appear\nfour or five Fringes of Colours. Let AB, CD [in _Fig._ 2.] represent the\nparallel Planes of a Looking-glass, and BD the Plane of the Diamond-cut,\nmaking at B a very obtuse Angle with the Plane AB. And let all the Light\nbetween the Rays ENI and FBM pass directly through the parallel Planes\nof the Glass, and fall upon the Paper between I and M, and all the Light\nbetween the Rays GO and HD be refracted by the oblique Plane of the\nDiamond-cut BD, and fall upon the Paper between K and L; and the Light\nwhich passes directly through the parallel Planes of the Glass, and\nfalls upon the Paper between I and M, will be border'd with three or\nmore Fringes at M.\n\n[Illustration: FIG. 1.]\n\n[Illustration: FIG. 2.]\n\nSo by looking on the Sun through a Feather or black Ribband held close\nto the Eye, several Rain-bows will appear; the Shadows which the Fibres\nor Threds cast on the _Tunica Retina_, being border'd with the like\nFringes of Colours.\n\n_Obs._ 3. When the Hair was twelve Feet distant from this Hole, and its\nShadow fell obliquely upon a flat white Scale of Inches and Parts of an\nInch placed half a Foot beyond it, and also when the Shadow fell\nperpendicularly upon the same Scale placed nine Feet beyond it; I\nmeasured the breadth of the Shadow and Fringes as accurately as I could,\nand found them in Parts of an Inch as follows.\n\n-------------------------------------------+-----------+--------\n                                           |  half a   | Nine\n                      At the Distance of   |   Foot    |  Feet\n-------------------------------------------+-----------+--------\nThe breadth of the Shadow                  |   1/54    |  1/9\n-------------------------------------------+-----------+--------\nThe breadth between the Middles of the     |   1/38    |\n  brightest Light of the innermost Fringes |    or     |\n  on either side the Shadow                |   1/39    |  7/50\n-------------------------------------------+-----------+--------\nThe breadth between the Middles of the     |           |\n  brightest Light of the middlemost Fringes|           |\n  on either side the Shadow                | 1/23-1/2  |  4/17\n-------------------------------------------+-----------+--------\nThe breadth between the Middles of the     |  1/18     |\n  brightest Light of the outmost Fringes   |   or      |\n  on either side the Shadow                | 1/18-1/2  |  3/10\n-------------------------------------------+-----------+--------\nThe distance between the Middles of the    |           |\n  brightest Light of the first and second  |           |\n  Fringes                                  |  1/120    |  1/21\n-------------------------------------------+-----------+--------\nThe distance between the Middles of the    |           |\n  brightest Light of the second and third  |           |\n  Fringes                                  |  1/170    |  1/31\n-------------------------------------------+-----------+--------\nThe breadth of the luminous Part (green,   |           |\n  white, yellow, and red) of the first     |           |\n  Fringe                                   |  1/170    |  1/32\n-------------------------------------------+-----------+--------\nThe breadth of the darker Space between    |           |\n  the first and second Fringes             |  1/240    |  1/45\n-------------------------------------------+-----------+--------\nThe breadth of the luminous Part of the    |           |\n  second Fringe                            |  1/290    |  1/55\n-------------------------------------------+-----------+--------\nThe breadth of the darker Space between    |           |\n  the second and third Fringes             |  1/340    |  1/63\n-------------------------------------------+-----------+--------\n\nThese Measures I took by letting the Shadow of the Hair, at half a Foot\ndistance, fall so obliquely on the Scale, as to appear twelve times\nbroader than when it fell perpendicularly on it at the same distance,\nand setting down in this Table the twelfth part of the Measures I then\ntook.\n\n_Obs._ 4. When the Shadow and Fringes were cast obliquely upon a smooth\nwhite Body, and that Body was removed farther and farther from the Hair,\nthe first Fringe began to appear and look brighter than the rest of the\nLight at the distance of less than a quarter of an Inch from the Hair,\nand the dark Line or Shadow between that and the second Fringe began to\nappear at a less distance from the Hair than that of the third part of\nan Inch. The second Fringe began to appear at a distance from the Hair\nof less than half an Inch, and the Shadow between that and the third\nFringe at a distance less than an inch, and the third Fringe at a\ndistance less than three Inches. At greater distances they became much\nmore sensible, but kept very nearly the same proportion of their\nbreadths and intervals which they had at their first appearing. For the\ndistance between the middle of the first, and middle of the second\nFringe, was to the distance between the middle of the second and middle\nof the third Fringe, as three to two, or ten to seven. And the last of\nthese two distances was equal to the breadth of the bright Light or\nluminous part of the first Fringe. And this breadth was to the breadth\nof the bright Light of the second Fringe as seven to four, and to the\ndark Interval of the first and second Fringe as three to two, and to\nthe like dark Interval between the second and third as two to one. For\nthe breadths of the Fringes seem'd to be in the progression of the\nNumbers 1, sqrt(1/3), sqrt(1/5), and their Intervals to be in the\nsame progression with them; that is, the Fringes and their Intervals\ntogether to be in the continual progression of the Numbers 1,\nsqrt(1/2), sqrt(1/3), sqrt(1/4), sqrt(1/5), or thereabouts. And\nthese Proportions held the same very nearly at all distances from the\nHair; the dark Intervals of the Fringes being as broad in proportion to\nthe breadth of the Fringes at their first appearance as afterwards at\ngreat distances from the Hair, though not so dark and distinct.\n\n_Obs._ 5. The Sun shining into my darken'd Chamber through a hole a\nquarter of an Inch broad, I placed at the distance of two or three Feet\nfrom the Hole a Sheet of Pasteboard, which was black'd all over on both\nsides, and in the middle of it had a hole about three quarters of an\nInch square for the Light to pass through. And behind the hole I\nfasten'd to the Pasteboard with Pitch the blade of a sharp Knife, to\nintercept some part of the Light which passed through the hole. The\nPlanes of the Pasteboard and blade of the Knife were parallel to one\nanother, and perpendicular to the Rays. And when they were so placed\nthat none of the Sun's Light fell on the Pasteboard, but all of it\npassed through the hole to the Knife, and there part of it fell upon the\nblade of the Knife, and part of it passed by its edge; I let this part\nof the Light which passed by, fall on a white Paper two or three Feet\nbeyond the Knife, and there saw two streams of faint Light shoot out\nboth ways from the beam of Light into the shadow, like the Tails of\nComets. But because the Sun's direct Light by its brightness upon the\nPaper obscured these faint streams, so that I could scarce see them, I\nmade a little hole in the midst of the Paper for that Light to pass\nthrough and fall on a black Cloth behind it; and then I saw the two\nstreams plainly. They were like one another, and pretty nearly equal in\nlength, and breadth, and quantity of Light. Their Light at that end next\nthe Sun's direct Light was pretty strong for the space of about a\nquarter of an Inch, or half an Inch, and in all its progress from that\ndirect Light decreased gradually till it became insensible. The whole\nlength of either of these streams measured upon the paper at the\ndistance of three Feet from the Knife was about six or eight Inches; so\nthat it subtended an Angle at the edge of the Knife of about 10 or 12,\nor at most 14 Degrees. Yet sometimes I thought I saw it shoot three or\nfour Degrees farther, but with a Light so very faint that I could scarce\nperceive it, and suspected it might (in some measure at least) arise\nfrom some other cause than the two streams did. For placing my Eye in\nthat Light beyond the end of that stream which was behind the Knife, and\nlooking towards the Knife, I could see a line of Light upon its edge,\nand that not only when my Eye was in the line of the Streams, but also\nwhen it was without that line either towards the point of the Knife, or\ntowards the handle. This line of Light appear'd contiguous to the edge\nof the Knife, and was narrower than the Light of the innermost Fringe,\nand narrowest when my Eye was farthest from the direct Light, and\ntherefore seem'd to pass between the Light of that Fringe and the edge\nof the Knife, and that which passed nearest the edge to be most bent,\nthough not all of it.\n\n_Obs._ 6. I placed another Knife by this, so that their edges might be\nparallel, and look towards one another, and that the beam of Light might\nfall upon both the Knives, and some part of it pass between their edges.\nAnd when the distance of their edges was about the 400th part of an\nInch, the stream parted in the middle, and left a Shadow between the two\nparts. This Shadow was so black and dark that all the Light which passed\nbetween the Knives seem'd to be bent, and turn'd aside to the one hand\nor to the other. And as the Knives still approach'd one another the\nShadow grew broader, and the streams shorter at their inward ends which\nwere next the Shadow, until upon the contact of the Knives the whole\nLight vanish'd, leaving its place to the Shadow.\n\nAnd hence I gather that the Light which is least bent, and goes to the\ninward ends of the streams, passes by the edges of the Knives at the\ngreatest distance, and this distance when the Shadow begins to appear\nbetween the streams, is about the 800th part of an Inch. And the Light\nwhich passes by the edges of the Knives at distances still less and\nless, is more and more bent, and goes to those parts of the streams\nwhich are farther and farther from the direct Light; because when the\nKnives approach one another till they touch, those parts of the streams\nvanish last which are farthest from the direct Light.\n\n_Obs._ 7. In the fifth Observation the Fringes did not appear, but by\nreason of the breadth of the hole in the Window became so broad as to\nrun into one another, and by joining, to make one continued Light in the\nbeginning of the streams. But in the sixth, as the Knives approached one\nanother, a little before the Shadow appeared between the two streams,\nthe Fringes began to appear on the inner ends of the Streams on either\nside of the direct Light; three on one side made by the edge of one\nKnife, and three on the other side made by the edge of the other Knife.\nThey were distinctest when the Knives were placed at the greatest\ndistance from the hole in the Window, and still became more distinct by\nmaking the hole less, insomuch that I could sometimes see a faint\nlineament of a fourth Fringe beyond the three above mention'd. And as\nthe Knives continually approach'd one another, the Fringes grew\ndistincter and larger, until they vanish'd. The outmost Fringe vanish'd\nfirst, and the middlemost next, and the innermost last. And after they\nwere all vanish'd, and the line of Light which was in the middle between\nthem was grown very broad, enlarging it self on both sides into the\nstreams of Light described in the fifth Observation, the above-mention'd\nShadow began to appear in the middle of this line, and divide it along\nthe middle into two lines of Light, and increased until the whole Light\nvanish'd. This enlargement of the Fringes was so great that the Rays\nwhich go to the innermost Fringe seem'd to be bent above twenty times\nmore when this Fringe was ready to vanish, than when one of the Knives\nwas taken away.\n\nAnd from this and the former Observation compared, I gather, that the\nLight of the first Fringe passed by the edge of the Knife at a distance\ngreater than the 800th part of an Inch, and the Light of the second\nFringe passed by the edge of the Knife at a greater distance than the\nLight of the first Fringe did, and that of the third at a greater\ndistance than that of the second, and that of the streams of Light\ndescribed in the fifth and sixth Observations passed by the edges of the\nKnives at less distances than that of any of the Fringes.\n\n_Obs._ 8. I caused the edges of two Knives to be ground truly strait,\nand pricking their points into a Board so that their edges might look\ntowards one another, and meeting near their points contain a rectilinear\nAngle, I fasten'd their Handles together with Pitch to make this Angle\ninvariable. The distance of the edges of the Knives from one another at\nthe distance of four Inches from the angular Point, where the edges of\nthe Knives met, was the eighth part of an Inch; and therefore the Angle\ncontain'd by the edges was about one Degree 54: The Knives thus fix'd\ntogether I placed in a beam of the Sun's Light, let into my darken'd\nChamber through a Hole the 42d Part of an Inch wide, at the distance of\n10 or 15 Feet from the Hole, and let the Light which passed between\ntheir edges fall very obliquely upon a smooth white Ruler at the\ndistance of half an Inch, or an Inch from the Knives, and there saw the\nFringes by the two edges of the Knives run along the edges of the\nShadows of the Knives in Lines parallel to those edges without growing\nsensibly broader, till they met in Angles equal to the Angle contained\nby the edges of the Knives, and where they met and joined they ended\nwithout crossing one another. But if the Ruler was held at a much\ngreater distance from the Knives, the Fringes where they were farther\nfrom the Place of their Meeting, were a little narrower, and became\nsomething broader and broader as they approach'd nearer and nearer to\none another, and after they met they cross'd one another, and then\nbecame much broader than before.\n\nWhence I gather that the distances at which the Fringes pass by the\nKnives are not increased nor alter'd by the approach of the Knives, but\nthe Angles in which the Rays are there bent are much increased by that\napproach; and that the Knife which is nearest any Ray determines which\nway the Ray shall be bent, and the other Knife increases the bent.\n\n_Obs._ 9. When the Rays fell very obliquely upon the Ruler at the\ndistance of the third Part of an Inch from the Knives, the dark Line\nbetween the first and second Fringe of the Shadow of one Knife, and the\ndark Line between the first and second Fringe of the Shadow of the other\nknife met with one another, at the distance of the fifth Part of an Inch\nfrom the end of the Light which passed between the Knives at the\nconcourse of their edges. And therefore the distance of the edges of the\nKnives at the meeting of these dark Lines was the 160th Part of an Inch.\nFor as four Inches to the eighth Part of an Inch, so is any Length of\nthe edges of the Knives measured from the point of their concourse to\nthe distance of the edges of the Knives at the end of that Length, and\nso is the fifth Part of an Inch to the 160th Part. So then the dark\nLines above-mention'd meet in the middle of the Light which passes\nbetween the Knives where they are distant the 160th Part of an Inch, and\nthe one half of that Light passes by the edge of one Knife at a distance\nnot greater than the 320th Part of an Inch, and falling upon the Paper\nmakes the Fringes of the Shadow of that Knife, and the other half passes\nby the edge of the other Knife, at a distance not greater than the 320th\nPart of an Inch, and falling upon the Paper makes the Fringes of the\nShadow of the other Knife. But if the Paper be held at a distance from\nthe Knives greater than the third Part of an Inch, the dark Lines\nabove-mention'd meet at a greater distance than the fifth Part of an\nInch from the end of the Light which passed between the Knives at the\nconcourse of their edges; and therefore the Light which falls upon the\nPaper where those dark Lines meet passes between the Knives where the\nedges are distant above the 160th part of an Inch.\n\nFor at another time, when the two Knives were distant eight Feet and\nfive Inches from the little hole in the Window, made with a small Pin as\nabove, the Light which fell upon the Paper where the aforesaid dark\nlines met, passed between the Knives, where the distance between their\nedges was as in the following Table, when the distance of the Paper from\nthe Knives was also as follows.\n\n-----------------------------+------------------------------\n                             | Distances between the edges\n Distances of the Paper      |  of the Knives in millesimal\n from the Knives in Inches.  |      parts of an Inch.\n-----------------------------+------------------------------\n          1-1/2.             |             0'012\n          3-1/3.             |             0'020\n          8-3/5.             |             0'034\n         32.                 |             0'057\n         96.                 |             0'081\n        131.                 |             0'087\n_____________________________|______________________________\n\nAnd hence I gather, that the Light which makes the Fringes upon the\nPaper is not the same Light at all distances of the Paper from the\nKnives, but when the Paper is held near the Knives, the Fringes are made\nby Light which passes by the edges of the Knives at a less distance, and\nis more bent than when the Paper is held at a greater distance from the\nKnives.\n\n[Illustration: FIG. 3.]\n\n_Obs._ 10. When the Fringes of the Shadows of the Knives fell\nperpendicularly upon a Paper at a great distance from the Knives, they\nwere in the form of Hyperbola's, and their Dimensions were as follows.\nLet CA, CB [in _Fig._ 3.] represent Lines drawn upon the Paper parallel\nto the edges of the Knives, and between which all the Light would fall,\nif it passed between the edges of the Knives without inflexion; DE a\nRight Line drawn through C making the Angles ACD, BCE, equal to one\nanother, and terminating all the Light which falls upon the Paper from\nthe point where the edges of the Knives meet; _eis_, _fkt_, and _glv_,\nthree hyperbolical Lines representing the Terminus of the Shadow of one\nof the Knives, the dark Line between the first and second Fringes of\nthat Shadow, and the dark Line between the second and third Fringes of\nthe same Shadow; _xip_, _ykq_, and _zlr_, three other hyperbolical Lines\nrepresenting the Terminus of the Shadow of the other Knife, the dark\nLine between the first and second Fringes of that Shadow, and the dark\nline between the second and third Fringes of the same Shadow. And\nconceive that these three Hyperbola's are like and equal to the former\nthree, and cross them in the points _i_, _k_, and _l_, and that the\nShadows of the Knives are terminated and distinguish'd from the first\nluminous Fringes by the lines _eis_ and _xip_, until the meeting and\ncrossing of the Fringes, and then those lines cross the Fringes in the\nform of dark lines, terminating the first luminous Fringes within side,\nand distinguishing them from another Light which begins to appear at\n_i_, and illuminates all the triangular space _ip_DE_s_ comprehended by\nthese dark lines, and the right line DE. Of these Hyperbola's one\nAsymptote is the line DE, and their other Asymptotes are parallel to the\nlines CA and CB. Let _rv_ represent a line drawn any where upon the\nPaper parallel to the Asymptote DE, and let this line cross the right\nlines AC in _m_, and BC in _n_, and the six dark hyperbolical lines in\n_p_, _q_, _r_; _s_, _t_, _v_; and by measuring the distances _ps_, _qt_,\n_rv_, and thence collecting the lengths of the Ordinates _np_, _nq_,\n_nr_ or _ms_, _mt_, _mv_, and doing this at several distances of the\nline _rv_ from the Asymptote DD, you may find as many points of these\nHyperbola's as you please, and thereby know that these curve lines are\nHyperbola's differing little from the conical Hyperbola. And by\nmeasuring the lines C_i_, C_k_, C_l_, you may find other points of these\nCurves.\n\nFor instance; when the Knives were distant from the hole in the Window\nten Feet, and the Paper from the Knives nine Feet, and the Angle\ncontained by the edges of the Knives to which the Angle ACB is equal,\nwas subtended by a Chord which was to the Radius as 1 to 32, and the\ndistance of the line _rv_ from the Asymptote DE was half an Inch: I\nmeasured the lines _ps_, _qt_, _rv_, and found them 0'35, 0'65, 0'98\nInches respectively; and by adding to their halfs the line 1/2 _mn_,\n(which here was the 128th part of an Inch, or 0'0078 Inches,) the Sums\n_np_, _nq_, _nr_, were 0'1828, 0'3328, 0'4978 Inches. I measured also\nthe distances of the brightest parts of the Fringes which run between\n_pq_ and _st_, _qr_ and _tv_, and next beyond _r_ and _v_, and found\nthem 0'5, 0'8, and 1'17 Inches.\n\n_Obs._ 11. The Sun shining into my darken'd Room through a small round\nhole made in a Plate of Lead with a slender Pin, as above; I placed at\nthe hole a Prism to refract the Light, and form on the opposite Wall the\nSpectrum of Colours, described in the third Experiment of the first\nBook. And then I found that the Shadows of all Bodies held in the\ncolour'd Light between the Prism and the Wall, were border'd with\nFringes of the Colour of that Light in which they were held. In the full\nred Light they were totally red without any sensible blue or violet, and\nin the deep blue Light they were totally blue without any sensible red\nor yellow; and so in the green Light they were totally green, excepting\na little yellow and blue, which were mixed in the green Light of the\nPrism. And comparing the Fringes made in the several colour'd Lights, I\nfound that those made in the red Light were largest, those made in the\nviolet were least, and those made in the green were of a middle bigness.\nFor the Fringes with which the Shadow of a Man's Hair were bordered,\nbeing measured cross the Shadow at the distance of six Inches from the\nHair, the distance between the middle and most luminous part of the\nfirst or innermost Fringe on one side of the Shadow, and that of the\nlike Fringe on the other side of the Shadow, was in the full red Light\n1/37-1/4 of an Inch, and in the full violet 7/46. And the like distance\nbetween the middle and most luminous parts of the second Fringes on\neither side the Shadow was in the full red Light 1/22, and in the violet\n1/27 of an Inch. And these distances of the Fringes held the same\nproportion at all distances from the Hair without any sensible\nvariation.\n\nSo then the Rays which made these Fringes in the red Light passed by the\nHair at a greater distance than those did which made the like Fringes in\nthe violet; and therefore the Hair in causing these Fringes acted alike\nupon the red Light or least refrangible Rays at a greater distance, and\nupon the violet or most refrangible Rays at a less distance, and by\nthose actions disposed the red Light into Larger Fringes, and the violet\ninto smaller, and the Lights of intermediate Colours into Fringes of\nintermediate bignesses without changing the Colour of any sort of Light.\n\nWhen therefore the Hair in the first and second of these Observations\nwas held in the white beam of the Sun's Light, and cast a Shadow which\nwas border'd with three Fringes of coloured Light, those Colours arose\nnot from any new modifications impress'd upon the Rays of Light by the\nHair, but only from the various inflexions whereby the several Sorts of\nRays were separated from one another, which before separation, by the\nmixture of all their Colours, composed the white beam of the Sun's\nLight, but whenever separated compose Lights of the several Colours\nwhich they are originally disposed to exhibit. In this 11th Observation,\nwhere the Colours are separated before the Light passes by the Hair, the\nleast refrangible Rays, which when separated from the rest make red,\nwere inflected at a greater distance from the Hair, so as to make three\nred Fringes at a greater distance from the middle of the Shadow of the\nHair; and the most refrangible Rays which when separated make violet,\nwere inflected at a less distance from the Hair, so as to make three\nviolet Fringes at a less distance from the middle of the Shadow of the\nHair. And other Rays of intermediate degrees of Refrangibility were\ninflected at intermediate distances from the Hair, so as to make Fringes\nof intermediate Colours at intermediate distances from the middle of the\nShadow of the Hair. And in the second Observation, where all the Colours\nare mix'd in the white Light which passes by the Hair, these Colours are\nseparated by the various inflexions of the Rays, and the Fringes which\nthey make appear all together, and the innermost Fringes being\ncontiguous make one broad Fringe composed of all the Colours in due\norder, the violet lying on the inside of the Fringe next the Shadow, the\nred on the outside farthest from the Shadow, and the blue, green, and\nyellow, in the middle. And, in like manner, the middlemost Fringes of\nall the Colours lying in order, and being contiguous, make another broad\nFringe composed of all the Colours; and the outmost Fringes of all the\nColours lying in order, and being contiguous, make a third broad Fringe\ncomposed of all the Colours. These are the three Fringes of colour'd\nLight with which the Shadows of all Bodies are border'd in the second\nObservation.\n\nWhen I made the foregoing Observations, I design'd to repeat most of\nthem with more care and exactness, and to make some new ones for\ndetermining the manner how the Rays of Light are bent in their passage\nby Bodies, for making the Fringes of Colours with the dark lines between\nthem. But I was then interrupted, and cannot now think of taking these\nthings into farther Consideration. And since I have not finish'd this\npart of my Design, I shall conclude with proposing only some Queries, in\norder to a farther search to be made by others.\n\n_Query_ 1. Do not Bodies act upon Light at a distance, and by their\naction bend its Rays; and is not this action (_cæteris paribus_)\nstrongest at the least distance?\n\n_Qu._ 2. Do not the Rays which differ in Refrangibility differ also in\nFlexibity; and are they not by their different Inflexions separated from\none another, so as after separation to make the Colours in the three\nFringes above described? And after what manner are they inflected to\nmake those Fringes?\n\n_Qu._ 3. Are not the Rays of Light in passing by the edges and sides of\nBodies, bent several times backwards and forwards, with a motion like\nthat of an Eel? And do not the three Fringes of colour'd Light\nabove-mention'd arise from three such bendings?\n\n_Qu._ 4. Do not the Rays of Light which fall upon Bodies, and are\nreflected or refracted, begin to bend before they arrive at the Bodies;\nand are they not reflected, refracted, and inflected, by one and the\nsame Principle, acting variously in various Circumstances?\n\n_Qu._ 5. Do not Bodies and Light act mutually upon one another; that is\nto say, Bodies upon Light in emitting, reflecting, refracting and\ninflecting it, and Light upon Bodies for heating them, and putting their\nparts into a vibrating motion wherein heat consists?\n\n_Qu._ 6. Do not black Bodies conceive heat more easily from Light than\nthose of other Colours do, by reason that the Light falling on them is\nnot reflected outwards, but enters the Bodies, and is often reflected\nand refracted within them, until it be stifled and lost?\n\n_Qu._ 7. Is not the strength and vigor of the action between Light and\nsulphureous Bodies observed above, one reason why sulphureous Bodies\ntake fire more readily, and burn more vehemently than other Bodies do?\n\n_Qu._ 8. Do not all fix'd Bodies, when heated beyond a certain degree,\nemit Light and shine; and is not this Emission perform'd by the\nvibrating motions of their parts? And do not all Bodies which abound\nwith terrestrial parts, and especially with sulphureous ones, emit Light\nas often as those parts are sufficiently agitated; whether that\nagitation be made by Heat, or by Friction, or Percussion, or\nPutrefaction, or by any vital Motion, or any other Cause? As for\ninstance; Sea-Water in a raging Storm; Quick-silver agitated in _vacuo_;\nthe Back of a Cat, or Neck of a Horse, obliquely struck or rubbed in a\ndark place; Wood, Flesh and Fish while they putrefy; Vapours arising\nfrom putrefy'd Waters, usually call'd _Ignes Fatui_; Stacks of moist Hay\nor Corn growing hot by fermentation; Glow-worms and the Eyes of some\nAnimals by vital Motions; the vulgar _Phosphorus_ agitated by the\nattrition of any Body, or by the acid Particles of the Air; Amber and\nsome Diamonds by striking, pressing or rubbing them; Scrapings of Steel\nstruck off with a Flint; Iron hammer'd very nimbly till it become so hot\nas to kindle Sulphur thrown upon it; the Axletrees of Chariots taking\nfire by the rapid rotation of the Wheels; and some Liquors mix'd with\none another whose Particles come together with an Impetus, as Oil of\nVitriol distilled from its weight of Nitre, and then mix'd with twice\nits weight of Oil of Anniseeds. So also a Globe of Glass about 8 or 10\nInches in diameter, being put into a Frame where it may be swiftly\nturn'd round its Axis, will in turning shine where it rubs against the\npalm of ones Hand apply'd to it: And if at the same time a piece of\nwhite Paper or white Cloth, or the end of ones Finger be held at the\ndistance of about a quarter of an Inch or half an Inch from that part of\nthe Glass where it is most in motion, the electrick Vapour which is\nexcited by the friction of the Glass against the Hand, will by dashing\nagainst the white Paper, Cloth or Finger, be put into such an agitation\nas to emit Light, and make the white Paper, Cloth or Finger, appear\nlucid like a Glowworm; and in rushing out of the Glass will sometimes\npush against the finger so as to be felt. And the same things have been\nfound by rubbing a long and large Cylinder or Glass or Amber with a\nPaper held in ones hand, and continuing the friction till the Glass grew\nwarm.\n\n_Qu._ 9. Is not Fire a Body heated so hot as to emit Light copiously?\nFor what else is a red hot Iron than Fire? And what else is a burning\nCoal than red hot Wood?\n\n_Qu._ 10. Is not Flame a Vapour, Fume or Exhalation heated red hot, that\nis, so hot as to shine? For Bodies do not flame without emitting a\ncopious Fume, and this Fume burns in the Flame. The _Ignis Fatuus_ is a\nVapour shining without heat, and is there not the same difference\nbetween this Vapour and Flame, as between rotten Wood shining without\nheat and burning Coals of Fire? In distilling hot Spirits, if the Head\nof the Still be taken off, the Vapour which ascends out of the Still\nwill take fire at the Flame of a Candle, and turn into Flame, and the\nFlame will run along the Vapour from the Candle to the Still. Some\nBodies heated by Motion, or Fermentation, if the heat grow intense, fume\ncopiously, and if the heat be great enough the Fumes will shine and\nbecome Flame. Metals in fusion do not flame for want of a copious Fume,\nexcept Spelter, which fumes copiously, and thereby flames. All flaming\nBodies, as Oil, Tallow, Wax, Wood, fossil Coals, Pitch, Sulphur, by\nflaming waste and vanish into burning Smoke, which Smoke, if the Flame\nbe put out, is very thick and visible, and sometimes smells strongly,\nbut in the Flame loses its smell by burning, and according to the nature\nof the Smoke the Flame is of several Colours, as that of Sulphur blue,\nthat of Copper open'd with sublimate green, that of Tallow yellow, that\nof Camphire white. Smoke passing through Flame cannot but grow red hot,\nand red hot Smoke can have no other appearance than that of Flame. When\nGun-powder takes fire, it goes away into Flaming Smoke. For the Charcoal\nand Sulphur easily take fire, and set fire to the Nitre, and the Spirit\nof the Nitre being thereby rarified into Vapour, rushes out with\nExplosion much after the manner that the Vapour of Water rushes out of\nan Æolipile; the Sulphur also being volatile is converted into Vapour,\nand augments the Explosion. And the acid Vapour of the Sulphur (namely\nthat which distils under a Bell into Oil of Sulphur,) entring violently\ninto the fix'd Body of the Nitre, sets loose the Spirit of the Nitre,\nand excites a great Fermentation, whereby the Heat is farther augmented,\nand the fix'd Body of the Nitre is also rarified into Fume, and the\nExplosion is thereby made more vehement and quick. For if Salt of Tartar\nbe mix'd with Gun-powder, and that Mixture be warm'd till it takes fire,\nthe Explosion will be more violent and quick than that of Gun-powder\nalone; which cannot proceed from any other cause than the action of the\nVapour of the Gun-powder upon the Salt of Tartar, whereby that Salt is\nrarified. The Explosion of Gun-powder arises therefore from the violent\naction whereby all the Mixture being quickly and vehemently heated, is\nrarified and converted into Fume and Vapour: which Vapour, by the\nviolence of that action, becoming so hot as to shine, appears in the\nform of Flame.\n\n_Qu._ 11. Do not great Bodies conserve their heat the longest, their\nparts heating one another, and may not great dense and fix'd Bodies,\nwhen heated beyond a certain degree, emit Light so copiously, as by the\nEmission and Re-action of its Light, and the Reflexions and Refractions\nof its Rays within its Pores to grow still hotter, till it comes to a\ncertain period of heat, such as is that of the Sun? And are not the Sun\nand fix'd Stars great Earths vehemently hot, whose heat is conserved by\nthe greatness of the Bodies, and the mutual Action and Reaction between\nthem, and the Light which they emit, and whose parts are kept from\nfuming away, not only by their fixity, but also by the vast weight and\ndensity of the Atmospheres incumbent upon them; and very strongly\ncompressing them, and condensing the Vapours and Exhalations which arise\nfrom them? For if Water be made warm in any pellucid Vessel emptied of\nAir, that Water in the _Vacuum_ will bubble and boil as vehemently as it\nwould in the open Air in a Vessel set upon the Fire till it conceives a\nmuch greater heat. For the weight of the incumbent Atmosphere keeps down\nthe Vapours, and hinders the Water from boiling, until it grow much\nhotter than is requisite to make it boil _in vacuo_. Also a mixture of\nTin and Lead being put upon a red hot Iron _in vacuo_ emits a Fume and\nFlame, but the same Mixture in the open Air, by reason of the incumbent\nAtmosphere, does not so much as emit any Fume which can be perceived by\nSight. In like manner the great weight of the Atmosphere which lies upon\nthe Globe of the Sun may hinder Bodies there from rising up and going\naway from the Sun in the form of Vapours and Fumes, unless by means of a\nfar greater heat than that which on the Surface of our Earth would very\neasily turn them into Vapours and Fumes. And the same great weight may\ncondense those Vapours and Exhalations as soon as they shall at any time\nbegin to ascend from the Sun, and make them presently fall back again\ninto him, and by that action increase his Heat much after the manner\nthat in our Earth the Air increases the Heat of a culinary Fire. And the\nsame weight may hinder the Globe of the Sun from being diminish'd,\nunless by the Emission of Light, and a very small quantity of Vapours\nand Exhalations.\n\n_Qu._ 12. Do not the Rays of Light in falling upon the bottom of the Eye\nexcite Vibrations in the _Tunica Retina_? Which Vibrations, being\npropagated along the solid Fibres of the optick Nerves into the Brain,\ncause the Sense of seeing. For because dense Bodies conserve their Heat\na long time, and the densest Bodies conserve their Heat the longest, the\nVibrations of their parts are of a lasting nature, and therefore may be\npropagated along solid Fibres of uniform dense Matter to a great\ndistance, for conveying into the Brain the impressions made upon all the\nOrgans of Sense. For that Motion which can continue long in one and the\nsame part of a Body, can be propagated a long way from one part to\nanother, supposing the Body homogeneal, so that the Motion may not be\nreflected, refracted, interrupted or disorder'd by any unevenness of the\nBody.\n\n_Qu._ 13. Do not several sorts of Rays make Vibrations of several\nbignesses, which according to their bignesses excite Sensations of\nseveral Colours, much after the manner that the Vibrations of the Air,\naccording to their several bignesses excite Sensations of several\nSounds? And particularly do not the most refrangible Rays excite the\nshortest Vibrations for making a Sensation of deep violet, the least\nrefrangible the largest for making a Sensation of deep red, and the\nseveral intermediate sorts of Rays, Vibrations of several intermediate\nbignesses to make Sensations of the several intermediate Colours?\n\n_Qu._ 14. May not the harmony and discord of Colours arise from the\nproportions of the Vibrations propagated through the Fibres of the\noptick Nerves into the Brain, as the harmony and discord of Sounds arise\nfrom the proportions of the Vibrations of the Air? For some Colours, if\nthey be view'd together, are agreeable to one another, as those of Gold\nand Indigo, and others disagree.\n\n_Qu._ 15. Are not the Species of Objects seen with both Eyes united\nwhere the optick Nerves meet before they come into the Brain, the Fibres\non the right side of both Nerves uniting there, and after union going\nthence into the Brain in the Nerve which is on the right side of the\nHead, and the Fibres on the left side of both Nerves uniting in the same\nplace, and after union going into the Brain in the Nerve which is on the\nleft side of the Head, and these two Nerves meeting in the Brain in such\na manner that their Fibres make but one entire Species or Picture, half\nof which on the right side of the Sensorium comes from the right side of\nboth Eyes through the right side of both optick Nerves to the place\nwhere the Nerves meet, and from thence on the right side of the Head\ninto the Brain, and the other half on the left side of the Sensorium\ncomes in like manner from the left side of both Eyes. For the optick\nNerves of such Animals as look the same way with both Eyes (as of Men,\nDogs, Sheep, Oxen, &c.) meet before they come into the Brain, but the\noptick Nerves of such Animals as do not look the same way with both Eyes\n(as of Fishes, and of the Chameleon,) do not meet, if I am rightly\ninform'd.\n\n_Qu._ 16. When a Man in the dark presses either corner of his Eye with\nhis Finger, and turns his Eye away from his Finger, he will see a Circle\nof Colours like those in the Feather of a Peacock's Tail. If the Eye and\nthe Finger remain quiet these Colours vanish in a second Minute of Time,\nbut if the Finger be moved with a quavering Motion they appear again. Do\nnot these Colours arise from such Motions excited in the bottom of the\nEye by the Pressure and Motion of the Finger, as, at other times are\nexcited there by Light for causing Vision? And do not the Motions once\nexcited continue about a Second of Time before they cease? And when a\nMan by a stroke upon his Eye sees a flash of Light, are not the like\nMotions excited in the _Retina_ by the stroke? And when a Coal of Fire\nmoved nimbly in the circumference of a Circle, makes the whole\ncircumference appear like a Circle of Fire; is it not because the\nMotions excited in the bottom of the Eye by the Rays of Light are of a\nlasting nature, and continue till the Coal of Fire in going round\nreturns to its former place? And considering the lastingness of the\nMotions excited in the bottom of the Eye by Light, are they not of a\nvibrating nature?\n\n_Qu._ 17. If a stone be thrown into stagnating Water, the Waves excited\nthereby continue some time to arise in the place where the Stone fell\ninto the Water, and are propagated from thence in concentrick Circles\nupon the Surface of the Water to great distances. And the Vibrations or\nTremors excited in the Air by percussion, continue a little time to move\nfrom the place of percussion in concentrick Spheres to great distances.\nAnd in like manner, when a Ray of Light falls upon the Surface of any\npellucid Body, and is there refracted or reflected, may not Waves of\nVibrations, or Tremors, be thereby excited in the refracting or\nreflecting Medium at the point of Incidence, and continue to arise\nthere, and to be propagated from thence as long as they continue to\narise and be propagated, when they are excited in the bottom of the Eye\nby the Pressure or Motion of the Finger, or by the Light which comes\nfrom the Coal of Fire in the Experiments above-mention'd? and are not\nthese Vibrations propagated from the point of Incidence to great\ndistances? And do they not overtake the Rays of Light, and by overtaking\nthem successively, do they not put them into the Fits of easy Reflexion\nand easy Transmission described above? For if the Rays endeavour to\nrecede from the densest part of the Vibration, they may be alternately\naccelerated and retarded by the Vibrations overtaking them.\n\n_Qu._ 18. If in two large tall cylindrical Vessels of Glass inverted,\ntwo little Thermometers be suspended so as not to touch the Vessels, and\nthe Air be drawn out of one of these Vessels, and these Vessels thus\nprepared be carried out of a cold place into a warm one; the Thermometer\n_in vacuo_ will grow warm as much, and almost as soon as the Thermometer\nwhich is not _in vacuo_. And when the Vessels are carried back into the\ncold place, the Thermometer _in vacuo_ will grow cold almost as soon as\nthe other Thermometer. Is not the Heat of the warm Room convey'd through\nthe _Vacuum_ by the Vibrations of a much subtiler Medium than Air, which\nafter the Air was drawn out remained in the _Vacuum_? And is not this\nMedium the same with that Medium by which Light is refracted and\nreflected, and by whose Vibrations Light communicates Heat to Bodies,\nand is put into Fits of easy Reflexion and easy Transmission? And do not\nthe Vibrations of this Medium in hot Bodies contribute to the\nintenseness and duration of their Heat? And do not hot Bodies\ncommunicate their Heat to contiguous cold ones, by the Vibrations of\nthis Medium propagated from them into the cold ones? And is not this\nMedium exceedingly more rare and subtile than the Air, and exceedingly\nmore elastick and active? And doth it not readily pervade all Bodies?\nAnd is it not (by its elastick force) expanded through all the Heavens?\n\n_Qu._ 19. Doth not the Refraction of Light proceed from the different\ndensity of this Æthereal Medium in different places, the Light receding\nalways from the denser parts of the Medium? And is not the density\nthereof greater in free and open Spaces void of Air and other grosser\nBodies, than within the Pores of Water, Glass, Crystal, Gems, and other\ncompact Bodies? For when Light passes through Glass or Crystal, and\nfalling very obliquely upon the farther Surface thereof is totally\nreflected, the total Reflexion ought to proceed rather from the density\nand vigour of the Medium without and beyond the Glass, than from the\nrarity and weakness thereof.\n\n_Qu._ 20. Doth not this Æthereal Medium in passing out of Water, Glass,\nCrystal, and other compact and dense Bodies into empty Spaces, grow\ndenser and denser by degrees, and by that means refract the Rays of\nLight not in a point, but by bending them gradually in curve Lines? And\ndoth not the gradual condensation of this Medium extend to some distance\nfrom the Bodies, and thereby cause the Inflexions of the Rays of Light,\nwhich pass by the edges of dense Bodies, at some distance from the\nBodies?\n\n_Qu._ 21. Is not this Medium much rarer within the dense Bodies of the\nSun, Stars, Planets and Comets, than in the empty celestial Spaces\nbetween them? And in passing from them to great distances, doth it not\ngrow denser and denser perpetually, and thereby cause the gravity of\nthose great Bodies towards one another, and of their parts towards the\nBodies; every Body endeavouring to go from the denser parts of the\nMedium towards the rarer? For if this Medium be rarer within the Sun's\nBody than at its Surface, and rarer there than at the hundredth part of\nan Inch from its Body, and rarer there than at the fiftieth part of an\nInch from its Body, and rarer there than at the Orb of _Saturn_; I see\nno reason why the Increase of density should stop any where, and not\nrather be continued through all distances from the Sun to _Saturn_, and\nbeyond. And though this Increase of density may at great distances be\nexceeding slow, yet if the elastick force of this Medium be exceeding\ngreat, it may suffice to impel Bodies from the denser parts of the\nMedium towards the rarer, with all that power which we call Gravity. And\nthat the elastick force of this Medium is exceeding great, may be\ngather'd from the swiftness of its Vibrations. Sounds move about 1140\n_English_ Feet in a second Minute of Time, and in seven or eight Minutes\nof Time they move about one hundred _English_ Miles. Light moves from\nthe Sun to us in about seven or eight Minutes of Time, which distance is\nabout 70,000,000 _English_ Miles, supposing the horizontal Parallax of\nthe Sun to be about 12´´. And the Vibrations or Pulses of this Medium,\nthat they may cause the alternate Fits of easy Transmission and easy\nReflexion, must be swifter than Light, and by consequence above 700,000\ntimes swifter than Sounds. And therefore the elastick force of this\nMedium, in proportion to its density, must be above 700000 x 700000\n(that is, above 490,000,000,000) times greater than the elastick force\nof the Air is in proportion to its density. For the Velocities of the\nPulses of elastick Mediums are in a subduplicate _Ratio_ of the\nElasticities and the Rarities of the Mediums taken together.\n\nAs Attraction is stronger in small Magnets than in great ones in\nproportion to their Bulk, and Gravity is greater in the Surfaces of\nsmall Planets than in those of great ones in proportion to their bulk,\nand small Bodies are agitated much more by electric attraction than\ngreat ones; so the smallness of the Rays of Light may contribute very\nmuch to the power of the Agent by which they are refracted. And so if\nany one should suppose that _Æther_ (like our Air) may contain Particles\nwhich endeavour to recede from one another (for I do not know what this\n_Æther_ is) and that its Particles are exceedingly smaller than those of\nAir, or even than those of Light: The exceeding smallness of its\nParticles may contribute to the greatness of the force by which those\nParticles may recede from one another, and thereby make that Medium\nexceedingly more rare and elastick than Air, and by consequence\nexceedingly less able to resist the motions of Projectiles, and\nexceedingly more able to press upon gross Bodies, by endeavouring to\nexpand it self.\n\n_Qu._ 22. May not Planets and Comets, and all gross Bodies, perform\ntheir Motions more freely, and with less resistance in this Æthereal\nMedium than in any Fluid, which fills all Space adequately without\nleaving any Pores, and by consequence is much denser than Quick-silver\nor Gold? And may not its resistance be so small, as to be\ninconsiderable? For instance; If this _Æther_ (for so I will call it)\nshould be supposed 700000 times more elastick than our Air, and above\n700000 times more rare; its resistance would be above 600,000,000 times\nless than that of Water. And so small a resistance would scarce make any\nsensible alteration in the Motions of the Planets in ten thousand\nYears. If any one would ask how a Medium can be so rare, let him tell me\nhow the Air, in the upper parts of the Atmosphere, can be above an\nhundred thousand thousand times rarer than Gold. Let him also tell me,\nhow an electrick Body can by Friction emit an Exhalation so rare and\nsubtile, and yet so potent, as by its Emission to cause no sensible\nDiminution of the weight of the electrick Body, and to be expanded\nthrough a Sphere, whose Diameter is above two Feet, and yet to be able\nto agitate and carry up Leaf Copper, or Leaf Gold, at the distance of\nabove a Foot from the electrick Body? And how the Effluvia of a Magnet\ncan be so rare and subtile, as to pass through a Plate of Glass without\nany Resistance or Diminution of their Force, and yet so potent as to\nturn a magnetick Needle beyond the Glass?\n\n_Qu._ 23. Is not Vision perform'd chiefly by the Vibrations of this\nMedium, excited in the bottom of the Eye by the Rays of Light, and\npropagated through the solid, pellucid and uniform Capillamenta of the\noptick Nerves into the place of Sensation? And is not Hearing perform'd\nby the Vibrations either of this or some other Medium, excited in the\nauditory Nerves by the Tremors of the Air, and propagated through the\nsolid, pellucid and uniform Capillamenta of those Nerves into the place\nof Sensation? And so of the other Senses.\n\n_Qu._ 24. Is not Animal Motion perform'd by the Vibrations of this\nMedium, excited in the Brain by the power of the Will, and propagated\nfrom thence through the solid, pellucid and uniform Capillamenta of the\nNerves into the Muscles, for contracting and dilating them? I suppose\nthat the Capillamenta of the Nerves are each of them solid and uniform,\nthat the vibrating Motion of the Æthereal Medium may be propagated along\nthem from one end to the other uniformly, and without interruption: For\nObstructions in the Nerves create Palsies. And that they may be\nsufficiently uniform, I suppose them to be pellucid when view'd singly,\ntho' the Reflexions in their cylindrical Surfaces may make the whole\nNerve (composed of many Capillamenta) appear opake and white. For\nopacity arises from reflecting Surfaces, such as may disturb and\ninterrupt the Motions of this Medium.\n\n[Sidenote: _See the following Scheme, p. 356._]\n\n_Qu._ 25. Are there not other original Properties of the Rays of Light,\nbesides those already described? An instance of another original\nProperty we have in the Refraction of Island Crystal, described first by\n_Erasmus Bartholine_, and afterwards more exactly by _Hugenius_, in his\nBook _De la Lumiere_. This Crystal is a pellucid fissile Stone, clear as\nWater or Crystal of the Rock, and without Colour; enduring a red Heat\nwithout losing its transparency, and in a very strong Heat calcining\nwithout Fusion. Steep'd a Day or two in Water, it loses its natural\nPolish. Being rubb'd on Cloth, it attracts pieces of Straws and other\nlight things, like Ambar or Glass; and with _Aqua fortis_ it makes an\nEbullition. It seems to be a sort of Talk, and is found in form of an\noblique Parallelopiped, with six parallelogram Sides and eight solid\nAngles. The obtuse Angles of the Parallelograms are each of them 101\nDegrees and 52 Minutes; the acute ones 78 Degrees and 8 Minutes. Two of\nthe solid Angles opposite to one another, as C and E, are compassed each\nof them with three of these obtuse Angles, and each of the other six\nwith one obtuse and two acute ones. It cleaves easily in planes parallel\nto any of its Sides, and not in any other Planes. It cleaves with a\nglossy polite Surface not perfectly plane, but with some little\nunevenness. It is easily scratch'd, and by reason of its softness it\ntakes a Polish very difficultly. It polishes better upon polish'd\nLooking-glass than upon Metal, and perhaps better upon Pitch, Leather or\nParchment. Afterwards it must be rubb'd with a little Oil or white of an\nEgg, to fill up its Scratches; whereby it will become very transparent\nand polite. But for several Experiments, it is not necessary to polish\nit. If a piece of this crystalline Stone be laid upon a Book, every\nLetter of the Book seen through it will appear double, by means of a\ndouble Refraction. And if any beam of Light falls either\nperpendicularly, or in any oblique Angle upon any Surface of this\nCrystal, it becomes divided into two beams by means of the same double\nRefraction. Which beams are of the same Colour with the incident beam of\nLight, and seem equal to one another in the quantity of their Light, or\nvery nearly equal. One of these Refractions is perform'd by the usual\nRule of Opticks, the Sine of Incidence out of Air into this Crystal\nbeing to the Sine of Refraction, as five to three. The other\nRefraction, which may be called the unusual Refraction, is perform'd by\nthe following Rule.\n\n[Illustration: FIG. 4.]\n\nLet ADBC represent the refracting Surface of the Crystal, C the biggest\nsolid Angle at that Surface, GEHF the opposite Surface, and CK a\nperpendicular on that Surface. This perpendicular makes with the edge of\nthe Crystal CF, an Angle of 19 Degr. 3'. Join KF, and in it take KL, so\nthat the Angle KCL be 6 Degr. 40'. and the Angle LCF 12 Degr. 23'. And\nif ST represent any beam of Light incident at T in any Angle upon the\nrefracting Surface ADBC, let TV be the refracted beam determin'd by the\ngiven Portion of the Sines 5 to 3, according to the usual Rule of\nOpticks. Draw VX parallel and equal to KL. Draw it the same way from V\nin which L lieth from K; and joining TX, this line TX shall be the other\nrefracted beam carried from T to X, by the unusual Refraction.\n\nIf therefore the incident beam ST be perpendicular to the refracting\nSurface, the two beams TV and TX, into which it shall become divided,\nshall be parallel to the lines CK and CL; one of those beams going\nthrough the Crystal perpendicularly, as it ought to do by the usual Laws\nof Opticks, and the other TX by an unusual Refraction diverging from the\nperpendicular, and making with it an Angle VTX of about 6-2/3 Degrees,\nas is found by Experience. And hence, the Plane VTX, and such like\nPlanes which are parallel to the Plane CFK, may be called the Planes of\nperpendicular Refraction. And the Coast towards which the lines KL and\nVX are drawn, may be call'd the Coast of unusual Refraction.\n\nIn like manner Crystal of the Rock has a double Refraction: But the\ndifference of the two Refractions is not so great and manifest as in\nIsland Crystal.\n\nWhen the beam ST incident on Island Crystal is divided into two beams TV\nand TX, and these two beams arrive at the farther Surface of the Glass;\nthe beam TV, which was refracted at the first Surface after the usual\nmanner, shall be again refracted entirely after the usual manner at the\nsecond Surface; and the beam TX, which was refracted after the unusual\nmanner in the first Surface, shall be again refracted entirely after the\nunusual manner in the second Surface; so that both these beams shall\nemerge out of the second Surface in lines parallel to the first incident\nbeam ST.\n\nAnd if two pieces of Island Crystal be placed one after another, in such\nmanner that all the Surfaces of the latter be parallel to all the\ncorresponding Surfaces of the former: The Rays which are refracted after\nthe usual manner in the first Surface of the first Crystal, shall be\nrefracted after the usual manner in all the following Surfaces; and the\nRays which are refracted after the unusual manner in the first Surface,\nshall be refracted after the unusual manner in all the following\nSurfaces. And the same thing happens, though the Surfaces of the\nCrystals be any ways inclined to one another, provided that their Planes\nof perpendicular Refraction be parallel to one another.\n\nAnd therefore there is an original difference in the Rays of Light, by\nmeans of which some Rays are in this Experiment constantly refracted\nafter the usual manner, and others constantly after the unusual manner:\nFor if the difference be not original, but arises from new Modifications\nimpress'd on the Rays at their first Refraction, it would be alter'd by\nnew Modifications in the three following Refractions; whereas it suffers\nno alteration, but is constant, and has the same effect upon the Rays in\nall the Refractions. The unusual Refraction is therefore perform'd by an\noriginal property of the Rays. And it remains to be enquired, whether\nthe Rays have not more original Properties than are yet discover'd.\n\n_Qu._ 26. Have not the Rays of Light several sides, endued with several\noriginal Properties? For if the Planes of perpendicular Refraction of\nthe second Crystal be at right Angles with the Planes of perpendicular\nRefraction of the first Crystal, the Rays which are refracted after the\nusual manner in passing through the first Crystal, will be all of them\nrefracted after the unusual manner in passing through the second\nCrystal; and the Rays which are refracted after the unusual manner in\npassing through the first Crystal, will be all of them refracted after\nthe usual manner in passing through the second Crystal. And therefore\nthere are not two sorts of Rays differing in their nature from one\nanother, one of which is constantly and in all Positions refracted after\nthe usual manner, and the other constantly and in all Positions after\nthe unusual manner. The difference between the two sorts of Rays in the\nExperiment mention'd in the 25th Question, was only in the Positions of\nthe Sides of the Rays to the Planes of perpendicular Refraction. For one\nand the same Ray is here refracted sometimes after the usual, and\nsometimes after the unusual manner, according to the Position which its\nSides have to the Crystals. If the Sides of the Ray are posited the same\nway to both Crystals, it is refracted after the same manner in them\nboth: But if that side of the Ray which looks towards the Coast of the\nunusual Refraction of the first Crystal, be 90 Degrees from that side of\nthe same Ray which looks toward the Coast of the unusual Refraction of\nthe second Crystal, (which may be effected by varying the Position of\nthe second Crystal to the first, and by consequence to the Rays of\nLight,) the Ray shall be refracted after several manners in the several\nCrystals. There is nothing more required to determine whether the Rays\nof Light which fall upon the second Crystal shall be refracted after\nthe usual or after the unusual manner, but to turn about this Crystal,\nso that the Coast of this Crystal's unusual Refraction may be on this or\non that side of the Ray. And therefore every Ray may be consider'd as\nhaving four Sides or Quarters, two of which opposite to one another\nincline the Ray to be refracted after the unusual manner, as often as\neither of them are turn'd towards the Coast of unusual Refraction; and\nthe other two, whenever either of them are turn'd towards the Coast of\nunusual Refraction, do not incline it to be otherwise refracted than\nafter the usual manner. The two first may therefore be call'd the Sides\nof unusual Refraction. And since these Dispositions were in the Rays\nbefore their Incidence on the second, third, and fourth Surfaces of the\ntwo Crystals, and suffered no alteration (so far as appears,) by the\nRefraction of the Rays in their passage through those Surfaces, and the\nRays were refracted by the same Laws in all the four Surfaces; it\nappears that those Dispositions were in the Rays originally, and\nsuffer'd no alteration by the first Refraction, and that by means of\nthose Dispositions the Rays were refracted at their Incidence on the\nfirst Surface of the first Crystal, some of them after the usual, and\nsome of them after the unusual manner, accordingly as their Sides of\nunusual Refraction were then turn'd towards the Coast of the unusual\nRefraction of that Crystal, or sideways from it.\n\nEvery Ray of Light has therefore two opposite Sides, originally endued\nwith a Property on which the unusual Refraction depends, and the other\ntwo opposite Sides not endued with that Property. And it remains to be\nenquired, whether there are not more Properties of Light by which the\nSides of the Rays differ, and are distinguished from one another.\n\nIn explaining the difference of the Sides of the Rays above mention'd, I\nhave supposed that the Rays fall perpendicularly on the first Crystal.\nBut if they fall obliquely on it, the Success is the same. Those Rays\nwhich are refracted after the usual manner in the first Crystal, will be\nrefracted after the unusual manner in the second Crystal, supposing the\nPlanes of perpendicular Refraction to be at right Angles with one\nanother, as above; and on the contrary.\n\nIf the Planes of the perpendicular Refraction of the two Crystals be\nneither parallel nor perpendicular to one another, but contain an acute\nAngle: The two beams of Light which emerge out of the first Crystal,\nwill be each of them divided into two more at their Incidence on the\nsecond Crystal. For in this case the Rays in each of the two beams will\nsome of them have their Sides of unusual Refraction, and some of them\ntheir other Sides turn'd towards the Coast of the unusual Refraction of\nthe second Crystal.\n\n_Qu._ 27. Are not all Hypotheses erroneous which have hitherto been\ninvented for explaining the Phænomena of Light, by new Modifications of\nthe Rays? For those Phænomena depend not upon new Modifications, as has\nbeen supposed, but upon the original and unchangeable Properties of the\nRays.\n\n_Qu._ 28. Are not all Hypotheses erroneous, in which Light is supposed\nto consist in Pression or Motion, propagated through a fluid Medium? For\nin all these Hypotheses the Phænomena of Light have been hitherto\nexplain'd by supposing that they arise from new Modifications of the\nRays; which is an erroneous Supposition.\n\nIf Light consisted only in Pression propagated without actual Motion, it\nwould not be able to agitate and heat the Bodies which refract and\nreflect it. If it consisted in Motion propagated to all distances in an\ninstant, it would require an infinite force every moment, in every\nshining Particle, to generate that Motion. And if it consisted in\nPression or Motion, propagated either in an instant or in time, it would\nbend into the Shadow. For Pression or Motion cannot be propagated in a\nFluid in right Lines, beyond an Obstacle which stops part of the Motion,\nbut will bend and spread every way into the quiescent Medium which lies\nbeyond the Obstacle. Gravity tends downwards, but the Pressure of Water\narising from Gravity tends every way with equal Force, and is propagated\nas readily, and with as much force sideways as downwards, and through\ncrooked passages as through strait ones. The Waves on the Surface of\nstagnating Water, passing by the sides of a broad Obstacle which stops\npart of them, bend afterwards and dilate themselves gradually into the\nquiet Water behind the Obstacle. The Waves, Pulses or Vibrations of the\nAir, wherein Sounds consist, bend manifestly, though not so much as the\nWaves of Water. For a Bell or a Cannon may be heard beyond a Hill which\nintercepts the sight of the sounding Body, and Sounds are propagated as\nreadily through crooked Pipes as through streight ones. But Light is\nnever known to follow crooked Passages nor to bend into the Shadow. For\nthe fix'd Stars by the Interposition of any of the Planets cease to be\nseen. And so do the Parts of the Sun by the Interposition of the Moon,\n_Mercury_ or _Venus_. The Rays which pass very near to the edges of any\nBody, are bent a little by the action of the Body, as we shew'd above;\nbut this bending is not towards but from the Shadow, and is perform'd\nonly in the passage of the Ray by the Body, and at a very small distance\nfrom it. So soon as the Ray is past the Body, it goes right on.\n\n[Sidenote: _Mais pour dire comment cela se fait, je n'ay rien trove\njusqu' ici qui me satisfasse._ C. H. de la lumiere, c. 5, p. 91.]\n\nTo explain the unusual Refraction of Island Crystal by Pression or\nMotion propagated, has not hitherto been attempted (to my knowledge)\nexcept by _Huygens_, who for that end supposed two several vibrating\nMediums within that Crystal. But when he tried the Refractions in two\nsuccessive pieces of that Crystal, and found them such as is mention'd\nabove; he confessed himself at a loss for explaining them. For Pressions\nor Motions, propagated from a shining Body through an uniform Medium,\nmust be on all sides alike; whereas by those Experiments it appears,\nthat the Rays of Light have different Properties in their different\nSides. He suspected that the Pulses of _Æther_ in passing through the\nfirst Crystal might receive certain new Modifications, which might\ndetermine them to be propagated in this or that Medium within the\nsecond Crystal, according to the Position of that Crystal. But what\nModifications those might be he could not say, nor think of any thing\nsatisfactory in that Point. And if he had known that the unusual\nRefraction depends not on new Modifications, but on the original and\nunchangeable Dispositions of the Rays, he would have found it as\ndifficult to explain how those Dispositions which he supposed to be\nimpress'd on the Rays by the first Crystal, could be in them before\ntheir Incidence on that Crystal, and in general, how all Rays emitted by\nshining Bodies, can have those Dispositions in them from the beginning.\nTo me, at least, this seems inexplicable, if Light be nothing else than\nPression or Motion propagated through _Æther_.\n\nAnd it is as difficult to explain by these Hypotheses, how Rays can be\nalternately in Fits of easy Reflexion and easy Transmission; unless\nperhaps one might suppose that there are in all Space two Æthereal\nvibrating Mediums, and that the Vibrations of one of them constitute\nLight, and the Vibrations of the other are swifter, and as often as they\novertake the Vibrations of the first, put them into those Fits. But how\ntwo _Æthers_ can be diffused through all Space, one of which acts upon\nthe other, and by consequence is re-acted upon, without retarding,\nshattering, dispersing and confounding one anothers Motions, is\ninconceivable. And against filling the Heavens with fluid Mediums,\nunless they be exceeding rare, a great Objection arises from the regular\nand very lasting Motions of the Planets and Comets in all manner of\nCourses through the Heavens. For thence it is manifest, that the Heavens\nare void of all sensible Resistance, and by consequence of all sensible\nMatter.\n\nFor the resisting Power of fluid Mediums arises partly from the\nAttrition of the Parts of the Medium, and partly from the _Vis inertiæ_\nof the Matter. That part of the Resistance of a spherical Body which\narises from the Attrition of the Parts of the Medium is very nearly as\nthe Diameter, or, at the most, as the _Factum_ of the Diameter, and the\nVelocity of the spherical Body together. And that part of the Resistance\nwhich arises from the _Vis inertiæ_ of the Matter, is as the Square of\nthat _Factum_. And by this difference the two sorts of Resistance may be\ndistinguish'd from one another in any Medium; and these being\ndistinguish'd, it will be found that almost all the Resistance of Bodies\nof a competent Magnitude moving in Air, Water, Quick-silver, and such\nlike Fluids with a competent Velocity, arises from the _Vis inertiæ_ of\nthe Parts of the Fluid.\n\nNow that part of the resisting Power of any Medium which arises from the\nTenacity, Friction or Attrition of the Parts of the Medium, may be\ndiminish'd by dividing the Matter into smaller Parts, and making the\nParts more smooth and slippery: But that part of the Resistance which\narises from the _Vis inertiæ_, is proportional to the Density of the\nMatter, and cannot be diminish'd by dividing the Matter into smaller\nParts, nor by any other means than by decreasing the Density of the\nMedium. And for these Reasons the Density of fluid Mediums is very\nnearly proportional to their Resistance. Liquors which differ not much\nin Density, as Water, Spirit of Wine, Spirit of Turpentine, hot Oil,\ndiffer not much in Resistance. Water is thirteen or fourteen times\nlighter than Quick-silver and by consequence thirteen or fourteen times\nrarer, and its Resistance is less than that of Quick-silver in the same\nProportion, or thereabouts, as I have found by Experiments made with\nPendulums. The open Air in which we breathe is eight or nine hundred\ntimes lighter than Water, and by consequence eight or nine hundred times\nrarer, and accordingly its Resistance is less than that of Water in the\nsame Proportion, or thereabouts; as I have also found by Experiments\nmade with Pendulums. And in thinner Air the Resistance is still less,\nand at length, by ratifying the Air, becomes insensible. For small\nFeathers falling in the open Air meet with great Resistance, but in a\ntall Glass well emptied of Air, they fall as fast as Lead or Gold, as I\nhave seen tried several times. Whence the Resistance seems still to\ndecrease in proportion to the Density of the Fluid. For I do not find by\nany Experiments, that Bodies moving in Quick-silver, Water or Air, meet\nwith any other sensible Resistance than what arises from the Density and\nTenacity of those sensible Fluids, as they would do if the Pores of\nthose Fluids, and all other Spaces, were filled with a dense and\nsubtile Fluid. Now if the Resistance in a Vessel well emptied of Air,\nwas but an hundred times less than in the open Air, it would be about a\nmillion of times less than in Quick-silver. But it seems to be much less\nin such a Vessel, and still much less in the Heavens, at the height of\nthree or four hundred Miles from the Earth, or above. For Mr. _Boyle_\nhas shew'd that Air may be rarified above ten thousand times in Vessels\nof Glass; and the Heavens are much emptier of Air than any _Vacuum_ we\ncan make below. For since the Air is compress'd by the Weight of the\nincumbent Atmosphere, and the Density of Air is proportional to the\nForce compressing it, it follows by Computation, that at the height of\nabout seven and a half _English_ Miles from the Earth, the Air is four\ntimes rarer than at the Surface of the Earth; and at the height of 15\nMiles it is sixteen times rarer than that at the Surface of the Earth;\nand at the height of 22-1/2, 30, or 38 Miles, it is respectively 64,\n256, or 1024 times rarer, or thereabouts; and at the height of 76, 152,\n228 Miles, it is about 1000000, 1000000000000, or 1000000000000000000\ntimes rarer; and so on.\n\nHeat promotes Fluidity very much by diminishing the Tenacity of Bodies.\nIt makes many Bodies fluid which are not fluid in cold, and increases\nthe Fluidity of tenacious Liquids, as of Oil, Balsam, and Honey, and\nthereby decreases their Resistance. But it decreases not the Resistance\nof Water considerably, as it would do if any considerable part of the\nResistance of Water arose from the Attrition or Tenacity of its Parts.\nAnd therefore the Resistance of Water arises principally and almost\nentirely from the _Vis inertiæ_ of its Matter; and by consequence, if\nthe Heavens were as dense as Water, they would not have much less\nResistance than Water; if as dense as Quick-silver, they would not have\nmuch less Resistance than Quick-silver; if absolutely dense, or full of\nMatter without any _Vacuum_, let the Matter be never so subtil and\nfluid, they would have a greater Resistance than Quick-silver. A solid\nGlobe in such a Medium would lose above half its Motion in moving three\ntimes the length of its Diameter, and a Globe not solid (such as are the\nPlanets,) would be retarded sooner. And therefore to make way for the\nregular and lasting Motions of the Planets and Comets, it's necessary to\nempty the Heavens of all Matter, except perhaps some very thin Vapours,\nSteams, or Effluvia, arising from the Atmospheres of the Earth, Planets,\nand Comets, and from such an exceedingly rare Æthereal Medium as we\ndescribed above. A dense Fluid can be of no use for explaining the\nPhænomena of Nature, the Motions of the Planets and Comets being better\nexplain'd without it. It serves only to disturb and retard the Motions\nof those great Bodies, and make the Frame of Nature languish: And in the\nPores of Bodies, it serves only to stop the vibrating Motions of their\nParts, wherein their Heat and Activity consists. And as it is of no use,\nand hinders the Operations of Nature, and makes her languish, so there\nis no evidence for its Existence, and therefore it ought to be rejected.\nAnd if it be rejected, the Hypotheses that Light consists in Pression\nor Motion, propagated through such a Medium, are rejected with it.\n\nAnd for rejecting such a Medium, we have the Authority of those the\noldest and most celebrated Philosophers of _Greece_ and _Phoenicia_,\nwho made a _Vacuum_, and Atoms, and the Gravity of Atoms, the first\nPrinciples of their Philosophy; tacitly attributing Gravity to some\nother Cause than dense Matter. Later Philosophers banish the\nConsideration of such a Cause out of natural Philosophy, feigning\nHypotheses for explaining all things mechanically, and referring other\nCauses to Metaphysicks: Whereas the main Business of natural Philosophy\nis to argue from Phænomena without feigning Hypotheses, and to deduce\nCauses from Effects, till we come to the very first Cause, which\ncertainly is not mechanical; and not only to unfold the Mechanism of the\nWorld, but chiefly to resolve these and such like Questions. What is\nthere in places almost empty of Matter, and whence is it that the Sun\nand Planets gravitate towards one another, without dense Matter between\nthem? Whence is it that Nature doth nothing in vain; and whence arises\nall that Order and Beauty which we see in the World? To what end are\nComets, and whence is it that Planets move all one and the same way in\nOrbs concentrick, while Comets move all manner of ways in Orbs very\nexcentrick; and what hinders the fix'd Stars from falling upon one\nanother? How came the Bodies of Animals to be contrived with so much\nArt, and for what ends were their several Parts? Was the Eye contrived\nwithout Skill in Opticks, and the Ear without Knowledge of Sounds? How\ndo the Motions of the Body follow from the Will, and whence is the\nInstinct in Animals? Is not the Sensory of Animals that place to which\nthe sensitive Substance is present, and into which the sensible Species\nof Things are carried through the Nerves and Brain, that there they may\nbe perceived by their immediate presence to that Substance? And these\nthings being rightly dispatch'd, does it not appear from Phænomena that\nthere is a Being incorporeal, living, intelligent, omnipresent, who in\ninfinite Space, as it were in his Sensory, sees the things themselves\nintimately, and throughly perceives them, and comprehends them wholly by\ntheir immediate presence to himself: Of which things the Images only\ncarried through the Organs of Sense into our little Sensoriums, are\nthere seen and beheld by that which in us perceives and thinks. And\nthough every true Step made in this Philosophy brings us not immediately\nto the Knowledge of the first Cause, yet it brings us nearer to it, and\non that account is to be highly valued.\n\n_Qu._ 29. Are not the Rays of Light very small Bodies emitted from\nshining Substances? For such Bodies will pass through uniform Mediums in\nright Lines without bending into the Shadow, which is the Nature of the\nRays of Light. They will also be capable of several Properties, and be\nable to conserve their Properties unchanged in passing through several\nMediums, which is another Condition of the Rays of Light. Pellucid\nSubstances act upon the Rays of Light at a distance in refracting,\nreflecting, and inflecting them, and the Rays mutually agitate the Parts\nof those Substances at a distance for heating them; and this Action and\nRe-action at a distance very much resembles an attractive Force between\nBodies. If Refraction be perform'd by Attraction of the Rays, the Sines\nof Incidence must be to the Sines of Refraction in a given Proportion,\nas we shew'd in our Principles of Philosophy: And this Rule is true by\nExperience. The Rays of Light in going out of Glass into a _Vacuum_, are\nbent towards the Glass; and if they fall too obliquely on the _Vacuum_,\nthey are bent backwards into the Glass, and totally reflected; and this\nReflexion cannot be ascribed to the Resistance of an absolute _Vacuum_,\nbut must be caused by the Power of the Glass attracting the Rays at\ntheir going out of it into the _Vacuum_, and bringing them back. For if\nthe farther Surface of the Glass be moisten'd with Water or clear Oil,\nor liquid and clear Honey, the Rays which would otherwise be reflected\nwill go into the Water, Oil, or Honey; and therefore are not reflected\nbefore they arrive at the farther Surface of the Glass, and begin to go\nout of it. If they go out of it into the Water, Oil, or Honey, they go\non, because the Attraction of the Glass is almost balanced and rendered\nineffectual by the contrary Attraction of the Liquor. But if they go out\nof it into a _Vacuum_ which has no Attraction to balance that of the\nGlass, the Attraction of the Glass either bends and refracts them, or\nbrings them back and reflects them. And this is still more evident by\nlaying together two Prisms of Glass, or two Object-glasses of very long\nTelescopes, the one plane, the other a little convex, and so compressing\nthem that they do not fully touch, nor are too far asunder. For the\nLight which falls upon the farther Surface of the first Glass where the\nInterval between the Glasses is not above the ten hundred thousandth\nPart of an Inch, will go through that Surface, and through the Air or\n_Vacuum_ between the Glasses, and enter into the second Glass, as was\nexplain'd in the first, fourth, and eighth Observations of the first\nPart of the second Book. But, if the second Glass be taken away, the\nLight which goes out of the second Surface of the first Glass into the\nAir or _Vacuum_, will not go on forwards, but turns back into the first\nGlass, and is reflected; and therefore it is drawn back by the Power of\nthe first Glass, there being nothing else to turn it back. Nothing more\nis requisite for producing all the variety of Colours, and degrees of\nRefrangibility, than that the Rays of Light be Bodies of different\nSizes, the least of which may take violet the weakest and darkest of the\nColours, and be more easily diverted by refracting Surfaces from the\nright Course; and the rest as they are bigger and bigger, may make the\nstronger and more lucid Colours, blue, green, yellow, and red, and be\nmore and more difficultly diverted. Nothing more is requisite for\nputting the Rays of Light into Fits of easy Reflexion and easy\nTransmission, than that they be small Bodies which by their attractive\nPowers, or some other Force, stir up Vibrations in what they act upon,\nwhich Vibrations being swifter than the Rays, overtake them\nsuccessively, and agitate them so as by turns to increase and decrease\ntheir Velocities, and thereby put them into those Fits. And lastly, the\nunusual Refraction of Island-Crystal looks very much as if it were\nperform'd by some kind of attractive virtue lodged in certain Sides both\nof the Rays, and of the Particles of the Crystal. For were it not for\nsome kind of Disposition or Virtue lodged in some Sides of the Particles\nof the Crystal, and not in their other Sides, and which inclines and\nbends the Rays towards the Coast of unusual Refraction, the Rays which\nfall perpendicularly on the Crystal, would not be refracted towards that\nCoast rather than towards any other Coast, both at their Incidence and\nat their Emergence, so as to emerge perpendicularly by a contrary\nSituation of the Coast of unusual Refraction at the second Surface; the\nCrystal acting upon the Rays after they have pass'd through it, and are\nemerging into the Air; or, if you please, into a _Vacuum_. And since the\nCrystal by this Disposition or Virtue does not act upon the Rays, unless\nwhen one of their Sides of unusual Refraction looks towards that Coast,\nthis argues a Virtue or Disposition in those Sides of the Rays, which\nanswers to, and sympathizes with that Virtue or Disposition of the\nCrystal, as the Poles of two Magnets answer to one another. And as\nMagnetism may be intended and remitted, and is found only in the Magnet\nand in Iron: So this Virtue of refracting the perpendicular Rays is\ngreater in Island-Crystal, less in Crystal of the Rock, and is not yet\nfound in other Bodies. I do not say that this Virtue is magnetical: It\nseems to be of another kind. I only say, that whatever it be, it's\ndifficult to conceive how the Rays of Light, unless they be Bodies, can\nhave a permanent Virtue in two of their Sides which is not in their\nother Sides, and this without any regard to their Position to the Space\nor Medium through which they pass.\n\nWhat I mean in this Question by a _Vacuum_, and by the Attractions of\nthe Rays of Light towards Glass or Crystal, may be understood by what\nwas said in the 18th, 19th, and 20th Questions.\n\n_Quest._ 30. Are not gross Bodies and Light convertible into one\nanother, and may not Bodies receive much of their Activity from the\nParticles of Light which enter their Composition? For all fix'd Bodies\nbeing heated emit Light so long as they continue sufficiently hot, and\nLight mutually stops in Bodies as often as its Rays strike upon their\nParts, as we shew'd above. I know no Body less apt to shine than Water;\nand yet Water by frequent Distillations changes into fix'd Earth, as Mr.\n_Boyle_ has try'd; and then this Earth being enabled to endure a\nsufficient Heat, shines by Heat like other Bodies.\n\nThe changing of Bodies into Light, and Light into Bodies, is very\nconformable to the Course of Nature, which seems delighted with\nTransmutations. Water, which is a very fluid tasteless Salt, she changes\nby Heat into Vapour, which is a sort of Air, and by Cold into Ice, which\nis a hard, pellucid, brittle, fusible Stone; and this Stone returns into\nWater by Heat, and Vapour returns into Water by Cold. Earth by Heat\nbecomes Fire, and by Cold returns into Earth. Dense Bodies by\nFermentation rarify into several sorts of Air, and this Air by\nFermentation, and sometimes without it, returns into dense Bodies.\nMercury appears sometimes in the form of a fluid Metal, sometimes in the\nform of a hard brittle Metal, sometimes in the form of a corrosive\npellucid Salt call'd Sublimate, sometimes in the form of a tasteless,\npellucid, volatile white Earth, call'd _Mercurius Dulcis_; or in that of\na red opake volatile Earth, call'd Cinnaber; or in that of a red or\nwhite Precipitate, or in that of a fluid Salt; and in Distillation it\nturns into Vapour, and being agitated _in Vacuo_, it shines like Fire.\nAnd after all these Changes it returns again into its first form of\nMercury. Eggs grow from insensible Magnitudes, and change into Animals;\nTadpoles into Frogs; and Worms into Flies. All Birds, Beasts and Fishes,\nInsects, Trees, and other Vegetables, with their several Parts, grow out\nof Water and watry Tinctures and Salts, and by Putrefaction return again\ninto watry Substances. And Water standing a few Days in the open Air,\nyields a Tincture, which (like that of Malt) by standing longer yields a\nSediment and a Spirit, but before Putrefaction is fit Nourishment for\nAnimals and Vegetables. And among such various and strange\nTransmutations, why may not Nature change Bodies into Light, and Light\ninto Bodies?\n\n_Quest._ 31. Have not the small Particles of Bodies certain Powers,\nVirtues, or Forces, by which they act at a distance, not only upon the\nRays of Light for reflecting, refracting, and inflecting them, but also\nupon one another for producing a great Part of the Phænomena of Nature?\nFor it's well known, that Bodies act one upon another by the Attractions\nof Gravity, Magnetism, and Electricity; and these Instances shew the\nTenor and Course of Nature, and make it not improbable but that there\nmay be more attractive Powers than these. For Nature is very consonant\nand conformable to her self. How these Attractions may be perform'd, I\ndo not here consider. What I call Attraction may be perform'd by\nimpulse, or by some other means unknown to me. I use that Word here to\nsignify only in general any Force by which Bodies tend towards one\nanother, whatsoever be the Cause. For we must learn from the Phænomena\nof Nature what Bodies attract one another, and what are the Laws and\nProperties of the Attraction, before we enquire the Cause by which the\nAttraction is perform'd. The Attractions of Gravity, Magnetism, and\nElectricity, reach to very sensible distances, and so have been observed\nby vulgar Eyes, and there may be others which reach to so small\ndistances as hitherto escape Observation; and perhaps electrical\nAttraction may reach to such small distances, even without being excited\nby Friction.\n\nFor when Salt of Tartar runs _per Deliquium_, is not this done by an\nAttraction between the Particles of the Salt of Tartar, and the\nParticles of the Water which float in the Air in the form of Vapours?\nAnd why does not common Salt, or Salt-petre, or Vitriol, run _per\nDeliquium_, but for want of such an Attraction? Or why does not Salt of\nTartar draw more Water out of the Air than in a certain Proportion to\nits quantity, but for want of an attractive Force after it is satiated\nwith Water? And whence is it but from this attractive Power that Water\nwhich alone distils with a gentle luke-warm Heat, will not distil from\nSalt of Tartar without a great Heat? And is it not from the like\nattractive Power between the Particles of Oil of Vitriol and the\nParticles of Water, that Oil of Vitriol draws to it a good quantity of\nWater out of the Air, and after it is satiated draws no more, and in\nDistillation lets go the Water very difficultly? And when Water and Oil\nof Vitriol poured successively into the same Vessel grow very hot in the\nmixing, does not this Heat argue a great Motion in the Parts of the\nLiquors? And does not this Motion argue, that the Parts of the two\nLiquors in mixing coalesce with Violence, and by consequence rush\ntowards one another with an accelerated Motion? And when _Aqua fortis_,\nor Spirit of Vitriol poured upon Filings of Iron dissolves the Filings\nwith a great Heat and Ebullition, is not this Heat and Ebullition\neffected by a violent Motion of the Parts, and does not that Motion\nargue that the acid Parts of the Liquor rush towards the Parts of the\nMetal with violence, and run forcibly into its Pores till they get\nbetween its outmost Particles, and the main Mass of the Metal, and\nsurrounding those Particles loosen them from the main Mass, and set them\nat liberty to float off into the Water? And when the acid Particles,\nwhich alone would distil with an easy Heat, will not separate from the\nParticles of the Metal without a very violent Heat, does not this\nconfirm the Attraction between them?\n\nWhen Spirit of Vitriol poured upon common Salt or Salt-petre makes an\nEbullition with the Salt, and unites with it, and in Distillation the\nSpirit of the common Salt or Salt-petre comes over much easier than it\nwould do before, and the acid part of the Spirit of Vitriol stays\nbehind; does not this argue that the fix'd Alcaly of the Salt attracts\nthe acid Spirit of the Vitriol more strongly than its own Spirit, and\nnot being able to hold them both, lets go its own? And when Oil of\nVitriol is drawn off from its weight of Nitre, and from both the\nIngredients a compound Spirit of Nitre is distilled, and two parts of\nthis Spirit are poured on one part of Oil of Cloves or Carraway Seeds,\nor of any ponderous Oil of vegetable or animal Substances, or Oil of\nTurpentine thicken'd with a little Balsam of Sulphur, and the Liquors\ngrow so very hot in mixing, as presently to send up a burning Flame;\ndoes not this very great and sudden Heat argue that the two Liquors mix\nwith violence, and that their Parts in mixing run towards one another\nwith an accelerated Motion, and clash with the greatest Force? And is it\nnot for the same reason that well rectified Spirit of Wine poured on the\nsame compound Spirit flashes; and that the _Pulvis fulminans_, composed\nof Sulphur, Nitre, and Salt of Tartar, goes off with a more sudden and\nviolent Explosion than Gun-powder, the acid Spirits of the Sulphur and\nNitre rushing towards one another, and towards the Salt of Tartar, with\nso great a violence, as by the shock to turn the whole at once into\nVapour and Flame? Where the Dissolution is slow, it makes a slow\nEbullition and a gentle Heat; and where it is quicker, it makes a\ngreater Ebullition with more heat; and where it is done at once, the\nEbullition is contracted into a sudden Blast or violent Explosion, with\na heat equal to that of Fire and Flame. So when a Drachm of the\nabove-mention'd compound Spirit of Nitre was poured upon half a Drachm\nof Oil of Carraway Seeds _in vacuo_, the Mixture immediately made a\nflash like Gun-powder, and burst the exhausted Receiver, which was a\nGlass six Inches wide, and eight Inches deep. And even the gross Body of\nSulphur powder'd, and with an equal weight of Iron Filings and a little\nWater made into Paste, acts upon the Iron, and in five or six hours\ngrows too hot to be touch'd, and emits a Flame. And by these Experiments\ncompared with the great quantity of Sulphur with which the Earth\nabounds, and the warmth of the interior Parts of the Earth, and hot\nSprings, and burning Mountains, and with Damps, mineral Coruscations,\nEarthquakes, hot suffocating Exhalations, Hurricanes, and Spouts; we may\nlearn that sulphureous Steams abound in the Bowels of the Earth and\nferment with Minerals, and sometimes take fire with a sudden Coruscation\nand Explosion; and if pent up in subterraneous Caverns, burst the\nCaverns with a great shaking of the Earth, as in springing of a Mine.\nAnd then the Vapour generated by the Explosion, expiring through the\nPores of the Earth, feels hot and suffocates, and makes Tempests and\nHurricanes, and sometimes causes the Land to slide, or the Sea to boil,\nand carries up the Water thereof in Drops, which by their weight fall\ndown again in Spouts. Also some sulphureous Steams, at all times when\nthe Earth is dry, ascending into the Air, ferment there with nitrous\nAcids, and sometimes taking fire cause Lightning and Thunder, and fiery\nMeteors. For the Air abounds with acid Vapours fit to promote\nFermentations, as appears by the rusting of Iron and Copper in it, the\nkindling of Fire by blowing, and the beating of the Heart by means of\nRespiration. Now the above-mention'd Motions are so great and violent as\nto shew that in Fermentations the Particles of Bodies which almost rest,\nare put into new Motions by a very potent Principle, which acts upon\nthem only when they approach one another, and causes them to meet and\nclash with great violence, and grow hot with the motion, and dash one\nanother into pieces, and vanish into Air, and Vapour, and Flame.\n\nWhen Salt of Tartar _per deliquium_, being poured into the Solution of\nany Metal, precipitates the Metal and makes it fall down to the bottom\nof the Liquor in the form of Mud: Does not this argue that the acid\nParticles are attracted more strongly by the Salt of Tartar than by the\nMetal, and by the stronger Attraction go from the Metal to the Salt of\nTartar? And so when a Solution of Iron in _Aqua fortis_ dissolves the\n_Lapis Calaminaris_, and lets go the Iron, or a Solution of Copper\ndissolves Iron immersed in it and lets go the Copper, or a Solution of\nSilver dissolves Copper and lets go the Silver, or a Solution of Mercury\nin _Aqua fortis_ being poured upon Iron, Copper, Tin, or Lead, dissolves\nthe Metal and lets go the Mercury; does not this argue that the acid\nParticles of the _Aqua fortis_ are attracted more strongly by the _Lapis\nCalaminaris_ than by Iron, and more strongly by Iron than by Copper, and\nmore strongly by Copper than by Silver, and more strongly by Iron,\nCopper, Tin, and Lead, than by Mercury? And is it not for the same\nreason that Iron requires more _Aqua fortis_ to dissolve it than Copper,\nand Copper more than the other Metals; and that of all Metals, Iron is\ndissolved most easily, and is most apt to rust; and next after Iron,\nCopper?\n\nWhen Oil of Vitriol is mix'd with a little Water, or is run _per\ndeliquium_, and in Distillation the Water ascends difficultly, and\nbrings over with it some part of the Oil of Vitriol in the form of\nSpirit of Vitriol, and this Spirit being poured upon Iron, Copper, or\nSalt of Tartar, unites with the Body and lets go the Water; doth not\nthis shew that the acid Spirit is attracted by the Water, and more\nattracted by the fix'd Body than by the Water, and therefore lets go the\nWater to close with the fix'd Body? And is it not for the same reason\nthat the Water and acid Spirits which are mix'd together in Vinegar,\n_Aqua fortis_, and Spirit of Salt, cohere and rise together in\nDistillation; but if the _Menstruum_ be poured on Salt of Tartar, or on\nLead, or Iron, or any fix'd Body which it can dissolve, the Acid by a\nstronger Attraction adheres to the Body, and lets go the Water? And is\nit not also from a mutual Attraction that the Spirits of Soot and\nSea-Salt unite and compose the Particles of Sal-armoniac, which are less\nvolatile than before, because grosser and freer from Water; and that the\nParticles of Sal-armoniac in Sublimation carry up the Particles of\nAntimony, which will not sublime alone; and that the Particles of\nMercury uniting with the acid Particles of Spirit of Salt compose\nMercury sublimate, and with the Particles of Sulphur, compose Cinnaber;\nand that the Particles of Spirit of Wine and Spirit of Urine well\nrectified unite, and letting go the Water which dissolved them, compose\na consistent Body; and that in subliming Cinnaber from Salt of Tartar,\nor from quick Lime, the Sulphur by a stronger Attraction of the Salt or\nLime lets go the Mercury, and stays with the fix'd Body; and that when\nMercury sublimate is sublimed from Antimony, or from Regulus of\nAntimony, the Spirit of Salt lets go the Mercury, and unites with the\nantimonial metal which attracts it more strongly, and stays with it till\nthe Heat be great enough to make them both ascend together, and then\ncarries up the Metal with it in the form of a very fusible Salt, called\nButter of Antimony, although the Spirit of Salt alone be almost as\nvolatile as Water, and the Antimony alone as fix'd as Lead?\n\nWhen _Aqua fortis_ dissolves Silver and not Gold, and _Aqua regia_\ndissolves Gold and not Silver, may it not be said that _Aqua fortis_ is\nsubtil enough to penetrate Gold as well as Silver, but wants the\nattractive Force to give it Entrance; and that _Aqua regia_ is subtil\nenough to penetrate Silver as well as Gold, but wants the attractive\nForce to give it Entrance? For _Aqua regia_ is nothing else than _Aqua\nfortis_ mix'd with some Spirit of Salt, or with Sal-armoniac; and even\ncommon Salt dissolved in _Aqua fortis_, enables the _Menstruum_ to\ndissolve Gold, though the Salt be a gross Body. When therefore Spirit of\nSalt precipitates Silver out of _Aqua fortis_, is it not done by\nattracting and mixing with the _Aqua fortis_, and not attracting, or\nperhaps repelling Silver? And when Water precipitates Antimony out of\nthe Sublimate of Antimony and Sal-armoniac, or out of Butter of\nAntimony, is it not done by its dissolving, mixing with, and weakening\nthe Sal-armoniac or Spirit of Salt, and its not attracting, or perhaps\nrepelling the Antimony? And is it not for want of an attractive virtue\nbetween the Parts of Water and Oil, of Quick-silver and Antimony, of\nLead and Iron, that these Substances do not mix; and by a weak\nAttraction, that Quick-silver and Copper mix difficultly; and from a\nstrong one, that Quick-silver and Tin, Antimony and Iron, Water and\nSalts, mix readily? And in general, is it not from the same Principle\nthat Heat congregates homogeneal Bodies, and separates heterogeneal\nones?\n\nWhen Arsenick with Soap gives a Regulus, and with Mercury sublimate a\nvolatile fusible Salt, like Butter of Antimony, doth not this shew that\nArsenick, which is a Substance totally volatile, is compounded of fix'd\nand volatile Parts, strongly cohering by a mutual Attraction, so that\nthe volatile will not ascend without carrying up the fixed? And so, when\nan equal weight of Spirit of Wine and Oil of Vitriol are digested\ntogether, and in Distillation yield two fragrant and volatile Spirits\nwhich will not mix with one another, and a fix'd black Earth remains\nbehind; doth not this shew that Oil of Vitriol is composed of volatile\nand fix'd Parts strongly united by Attraction, so as to ascend together\nin form of a volatile, acid, fluid Salt, until the Spirit of Wine\nattracts and separates the volatile Parts from the fixed? And therefore,\nsince Oil of Sulphur _per Campanam_ is of the same Nature with Oil of\nVitriol, may it not be inferred, that Sulphur is also a mixture of\nvolatile and fix'd Parts so strongly cohering by Attraction, as to\nascend together in Sublimation. By dissolving Flowers of Sulphur in Oil\nof Turpentine, and distilling the Solution, it is found that Sulphur is\ncomposed of an inflamable thick Oil or fat Bitumen, an acid Salt, a very\nfix'd Earth, and a little Metal. The three first were found not much\nunequal to one another, the fourth in so small a quantity as scarce to\nbe worth considering. The acid Salt dissolved in Water, is the same with\nOil of Sulphur _per Campanam_, and abounding much in the Bowels of the\nEarth, and particularly in Markasites, unites it self to the other\nIngredients of the Markasite, which are, Bitumen, Iron, Copper, and\nEarth, and with them compounds Allum, Vitriol, and Sulphur. With the\nEarth alone it compounds Allum; with the Metal alone, or Metal and\nEarth together, it compounds Vitriol; and with the Bitumen and Earth it\ncompounds Sulphur. Whence it comes to pass that Markasites abound with\nthose three Minerals. And is it not from the mutual Attraction of the\nIngredients that they stick together for compounding these Minerals, and\nthat the Bitumen carries up the other Ingredients of the Sulphur, which\nwithout it would not sublime? And the same Question may be put\nconcerning all, or almost all the gross Bodies in Nature. For all the\nParts of Animals and Vegetables are composed of Substances volatile and\nfix'd, fluid and solid, as appears by their Analysis; and so are Salts\nand Minerals, so far as Chymists have been hitherto able to examine\ntheir Composition.\n\nWhen Mercury sublimate is re-sublimed with fresh Mercury, and becomes\n_Mercurius Dulcis_, which is a white tasteless Earth scarce dissolvable\nin Water, and _Mercurius Dulcis_ re-sublimed with Spirit of Salt returns\ninto Mercury sublimate; and when Metals corroded with a little acid turn\ninto rust, which is an Earth tasteless and indissolvable in Water, and\nthis Earth imbibed with more acid becomes a metallick Salt; and when\nsome Stones, as Spar of Lead, dissolved in proper _Menstruums_ become\nSalts; do not these things shew that Salts are dry Earth and watry Acid\nunited by Attraction, and that the Earth will not become a Salt without\nso much acid as makes it dissolvable in Water? Do not the sharp and\npungent Tastes of Acids arise from the strong Attraction whereby the\nacid Particles rush upon and agitate the Particles of the Tongue? And\nwhen Metals are dissolved in acid _Menstruums_, and the Acids in\nconjunction with the Metal act after a different manner, so that the\nCompound has a different Taste much milder than before, and sometimes a\nsweet one; is it not because the Acids adhere to the metallick\nParticles, and thereby lose much of their Activity? And if the Acid be\nin too small a Proportion to make the Compound dissolvable in Water,\nwill it not by adhering strongly to the Metal become unactive and lose\nits Taste, and the Compound be a tasteless Earth? For such things as are\nnot dissolvable by the Moisture of the Tongue, act not upon the Taste.\n\nAs Gravity makes the Sea flow round the denser and weightier Parts of\nthe Globe of the Earth, so the Attraction may make the watry Acid flow\nround the denser and compacter Particles of Earth for composing the\nParticles of Salt. For otherwise the Acid would not do the Office of a\nMedium between the Earth and common Water, for making Salts dissolvable\nin the Water; nor would Salt of Tartar readily draw off the Acid from\ndissolved Metals, nor Metals the Acid from Mercury. Now, as in the great\nGlobe of the Earth and Sea, the densest Bodies by their Gravity sink\ndown in Water, and always endeavour to go towards the Center of the\nGlobe; so in Particles of Salt, the densest Matter may always endeavour\nto approach the Center of the Particle: So that a Particle of Salt may\nbe compared to a Chaos; being dense, hard, dry, and earthy in the\nCenter; and rare, soft, moist, and watry in the Circumference. And\nhence it seems to be that Salts are of a lasting Nature, being scarce\ndestroy'd, unless by drawing away their watry Parts by violence, or by\nletting them soak into the Pores of the central Earth by a gentle Heat\nin Putrefaction, until the Earth be dissolved by the Water, and\nseparated into smaller Particles, which by reason of their Smallness\nmake the rotten Compound appear of a black Colour. Hence also it may be,\nthat the Parts of Animals and Vegetables preserve their several Forms,\nand assimilate their Nourishment; the soft and moist Nourishment easily\nchanging its Texture by a gentle Heat and Motion, till it becomes like\nthe dense, hard, dry, and durable Earth in the Center of each Particle.\nBut when the Nourishment grows unfit to be assimilated, or the central\nEarth grows too feeble to assimilate it, the Motion ends in Confusion,\nPutrefaction, and Death.\n\nIf a very small quantity of any Salt or Vitriol be dissolved in a great\nquantity of Water, the Particles of the Salt or Vitriol will not sink to\nthe bottom, though they be heavier in Specie than the Water, but will\nevenly diffuse themselves into all the Water, so as to make it as saline\nat the top as at the bottom. And does not this imply that the Parts of\nthe Salt or Vitriol recede from one another, and endeavour to expand\nthemselves, and get as far asunder as the quantity of Water in which\nthey float, will allow? And does not this Endeavour imply that they have\na repulsive Force by which they fly from one another, or at least, that\nthey attract the Water more strongly than they do one another? For as\nall things ascend in Water which are less attracted than Water, by the\ngravitating Power of the Earth; so all the Particles of Salt which float\nin Water, and are less attracted than Water by any one Particle of Salt,\nmust recede from that Particle, and give way to the more attracted\nWater.\n\nWhen any saline Liquor is evaporated to a Cuticle and let cool, the Salt\nconcretes in regular Figures; which argues, that the Particles of the\nSalt before they concreted, floated in the Liquor at equal distances in\nrank and file, and by consequence that they acted upon one another by\nsome Power which at equal distances is equal, at unequal distances\nunequal. For by such a Power they will range themselves uniformly, and\nwithout it they will float irregularly, and come together as\nirregularly. And since the Particles of Island-Crystal act all the same\nway upon the Rays of Light for causing the unusual Refraction, may it\nnot be supposed that in the Formation of this Crystal, the Particles not\nonly ranged themselves in rank and file for concreting in regular\nFigures, but also by some kind of polar Virtue turned their homogeneal\nSides the same way.\n\nThe Parts of all homogeneal hard Bodies which fully touch one another,\nstick together very strongly. And for explaining how this may be, some\nhave invented hooked Atoms, which is begging the Question; and others\ntell us that Bodies are glued together by rest, that is, by an occult\nQuality, or rather by nothing; and others, that they stick together by\nconspiring Motions, that is, by relative rest amongst themselves. I had\nrather infer from their Cohesion, that their Particles attract one\nanother by some Force, which in immediate Contact is exceeding strong,\nat small distances performs the chymical Operations above-mention'd, and\nreaches not far from the Particles with any sensible Effect.\n\nAll Bodies seem to be composed of hard Particles: For otherwise Fluids\nwould not congeal; as Water, Oils, Vinegar, and Spirit or Oil of Vitriol\ndo by freezing; Mercury by Fumes of Lead; Spirit of Nitre and Mercury,\nby dissolving the Mercury and evaporating the Flegm; Spirit of Wine and\nSpirit of Urine, by deflegming and mixing them; and Spirit of Urine and\nSpirit of Salt, by subliming them together to make Sal-armoniac. Even\nthe Rays of Light seem to be hard Bodies; for otherwise they would not\nretain different Properties in their different Sides. And therefore\nHardness may be reckon'd the Property of all uncompounded Matter. At\nleast, this seems to be as evident as the universal Impenetrability of\nMatter. For all Bodies, so far as Experience reaches, are either hard,\nor may be harden'd; and we have no other Evidence of universal\nImpenetrability, besides a large Experience without an experimental\nException. Now if compound Bodies are so very hard as we find some of\nthem to be, and yet are very porous, and consist of Parts which are only\nlaid together; the simple Particles which are void of Pores, and were\nnever yet divided, must be much harder. For such hard Particles being\nheaped up together, can scarce touch one another in more than a few\nPoints, and therefore must be separable by much less Force than is\nrequisite to break a solid Particle, whose Parts touch in all the Space\nbetween them, without any Pores or Interstices to weaken their Cohesion.\nAnd how such very hard Particles which are only laid together and touch\nonly in a few Points, can stick together, and that so firmly as they do,\nwithout the assistance of something which causes them to be attracted or\npress'd towards one another, is very difficult to conceive.\n\nThe same thing I infer also from the cohering of two polish'd Marbles\n_in vacuo_, and from the standing of Quick-silver in the Barometer at\nthe height of 50, 60 or 70 Inches, or above, when ever it is well-purged\nof Air and carefully poured in, so that its Parts be every where\ncontiguous both to one another and to the Glass. The Atmosphere by its\nweight presses the Quick-silver into the Glass, to the height of 29 or\n30 Inches. And some other Agent raises it higher, not by pressing it\ninto the Glass, but by making its Parts stick to the Glass, and to one\nanother. For upon any discontinuation of Parts, made either by Bubbles\nor by shaking the Glass, the whole Mercury falls down to the height of\n29 or 30 Inches.\n\nAnd of the same kind with these Experiments are those that follow. If\ntwo plane polish'd Plates of Glass (suppose two pieces of a polish'd\nLooking-glass) be laid together, so that their sides be parallel and at\na very small distance from one another, and then their lower edges be\ndipped into Water, the Water will rise up between them. And the less\nthe distance of the Glasses is, the greater will be the height to which\nthe Water will rise. If the distance be about the hundredth part of an\nInch, the Water will rise to the height of about an Inch; and if the\ndistance be greater or less in any Proportion, the height will be\nreciprocally proportional to the distance very nearly. For the\nattractive Force of the Glasses is the same, whether the distance\nbetween them be greater or less; and the weight of the Water drawn up is\nthe same, if the height of it be reciprocally proportional to the\ndistance of the Glasses. And in like manner, Water ascends between two\nMarbles polish'd plane, when their polish'd sides are parallel, and at a\nvery little distance from one another, And if slender Pipes of Glass be\ndipped at one end into stagnating Water, the Water will rise up within\nthe Pipe, and the height to which it rises will be reciprocally\nproportional to the Diameter of the Cavity of the Pipe, and will equal\nthe height to which it rises between two Planes of Glass, if the\nSemi-diameter of the Cavity of the Pipe be equal to the distance between\nthe Planes, or thereabouts. And these Experiments succeed after the same\nmanner _in vacuo_ as in the open Air, (as hath been tried before the\nRoyal Society,) and therefore are not influenced by the Weight or\nPressure of the Atmosphere.\n\nAnd if a large Pipe of Glass be filled with sifted Ashes well pressed\ntogether in the Glass, and one end of the Pipe be dipped into stagnating\nWater, the Water will rise up slowly in the Ashes, so as in the space\nof a Week or Fortnight to reach up within the Glass, to the height of 30\nor 40 Inches above the stagnating Water. And the Water rises up to this\nheight by the Action only of those Particles of the Ashes which are upon\nthe Surface of the elevated Water; the Particles which are within the\nWater, attracting or repelling it as much downwards as upwards. And\ntherefore the Action of the Particles is very strong. But the Particles\nof the Ashes being not so dense and close together as those of Glass,\ntheir Action is not so strong as that of Glass, which keeps Quick-silver\nsuspended to the height of 60 or 70 Inches, and therefore acts with a\nForce which would keep Water suspended to the height of above 60 Feet.\n\nBy the same Principle, a Sponge sucks in Water, and the Glands in the\nBodies of Animals, according to their several Natures and Dispositions,\nsuck in various Juices from the Blood.\n\nIf two plane polish'd Plates of Glass three or four Inches broad, and\ntwenty or twenty five long, be laid one of them parallel to the Horizon,\nthe other upon the first, so as at one of their ends to touch one\nanother, and contain an Angle of about 10 or 15 Minutes, and the same be\nfirst moisten'd on their inward sides with a clean Cloth dipp'd into Oil\nof Oranges or Spirit of Turpentine, and a Drop or two of the Oil or\nSpirit be let fall upon the lower Glass at the other; so soon as the\nupper Glass is laid down upon the lower, so as to touch it at one end as\nabove, and to touch the Drop at the other end, making with the lower\nGlass an Angle of about 10 or 15 Minutes; the Drop will begin to move\ntowards the Concourse of the Glasses, and will continue to move with an\naccelerated Motion, till it arrives at that Concourse of the Glasses.\nFor the two Glasses attract the Drop, and make it run that way towards\nwhich the Attractions incline. And if when the Drop is in motion you\nlift up that end of the Glasses where they meet, and towards which the\nDrop moves, the Drop will ascend between the Glasses, and therefore is\nattracted. And as you lift up the Glasses more and more, the Drop will\nascend slower and slower, and at length rest, being then carried\ndownward by its Weight, as much as upwards by the Attraction. And by\nthis means you may know the Force by which the Drop is attracted at all\ndistances from the Concourse of the Glasses.\n\nNow by some Experiments of this kind, (made by Mr. _Hauksbee_) it has\nbeen found that the Attraction is almost reciprocally in a duplicate\nProportion of the distance of the middle of the Drop from the Concourse\nof the Glasses, _viz._ reciprocally in a simple Proportion, by reason of\nthe spreading of the Drop, and its touching each Glass in a larger\nSurface; and again reciprocally in a simple Proportion, by reason of the\nAttractions growing stronger within the same quantity of attracting\nSurface. The Attraction therefore within the same quantity of attracting\nSurface, is reciprocally as the distance between the Glasses. And\ntherefore where the distance is exceeding small, the Attraction must be\nexceeding great. By the Table in the second Part of the second Book,\nwherein the thicknesses of colour'd Plates of Water between two Glasses\nare set down, the thickness of the Plate where it appears very black, is\nthree eighths of the ten hundred thousandth part of an Inch. And where\nthe Oil of Oranges between the Glasses is of this thickness, the\nAttraction collected by the foregoing Rule, seems to be so strong, as\nwithin a Circle of an Inch in diameter, to suffice to hold up a Weight\nequal to that of a Cylinder of Water of an Inch in diameter, and two or\nthree Furlongs in length. And where it is of a less thickness the\nAttraction may be proportionally greater, and continue to increase,\nuntil the thickness do not exceed that of a single Particle of the Oil.\nThere are therefore Agents in Nature able to make the Particles of\nBodies stick together by very strong Attractions. And it is the Business\nof experimental Philosophy to find them out.\n\nNow the smallest Particles of Matter may cohere by the strongest\nAttractions, and compose bigger Particles of weaker Virtue; and many of\nthese may cohere and compose bigger Particles whose Virtue is still\nweaker, and so on for divers Successions, until the Progression end in\nthe biggest Particles on which the Operations in Chymistry, and the\nColours of natural Bodies depend, and which by cohering compose Bodies\nof a sensible Magnitude. If the Body is compact, and bends or yields\ninward to Pression without any sliding of its Parts, it is hard and\nelastick, returning to its Figure with a Force rising from the mutual\nAttraction of its Parts. If the Parts slide upon one another, the Body\nis malleable or soft. If they slip easily, and are of a fit Size to be\nagitated by Heat, and the Heat is big enough to keep them in Agitation,\nthe Body is fluid; and if it be apt to stick to things, it is humid; and\nthe Drops of every fluid affect a round Figure by the mutual Attraction\nof their Parts, as the Globe of the Earth and Sea affects a round Figure\nby the mutual Attraction of its Parts by Gravity.\n\nSince Metals dissolved in Acids attract but a small quantity of the\nAcid, their attractive Force can reach but to a small distance from\nthem. And as in Algebra, where affirmative Quantities vanish and cease,\nthere negative ones begin; so in Mechanicks, where Attraction ceases,\nthere a repulsive Virtue ought to succeed. And that there is such a\nVirtue, seems to follow from the Reflexions and Inflexions of the Rays\nof Light. For the Rays are repelled by Bodies in both these Cases,\nwithout the immediate Contact of the reflecting or inflecting Body. It\nseems also to follow from the Emission of Light; the Ray so soon as it\nis shaken off from a shining Body by the vibrating Motion of the Parts\nof the Body, and gets beyond the reach of Attraction, being driven away\nwith exceeding great Velocity. For that Force which is sufficient to\nturn it back in Reflexion, may be sufficient to emit it. It seems also\nto follow from the Production of Air and Vapour. The Particles when they\nare shaken off from Bodies by Heat or Fermentation, so soon as they are\nbeyond the reach of the Attraction of the Body, receding from it, and\nalso from one another with great Strength, and keeping at a distance,\nso as sometimes to take up above a Million of Times more space than they\ndid before in the form of a dense Body. Which vast Contraction and\nExpansion seems unintelligible, by feigning the Particles of Air to be\nspringy and ramous, or rolled up like Hoops, or by any other means than\na repulsive Power. The Particles of Fluids which do not cohere too\nstrongly, and are of such a Smallness as renders them most susceptible\nof those Agitations which keep Liquors in a Fluor, are most easily\nseparated and rarified into Vapour, and in the Language of the Chymists,\nthey are volatile, rarifying with an easy Heat, and condensing with\nCold. But those which are grosser, and so less susceptible of Agitation,\nor cohere by a stronger Attraction, are not separated without a stronger\nHeat, or perhaps not without Fermentation. And these last are the Bodies\nwhich Chymists call fix'd, and being rarified by Fermentation, become\ntrue permanent Air; those Particles receding from one another with the\ngreatest Force, and being most difficultly brought together, which upon\nContact cohere most strongly. And because the Particles of permanent Air\nare grosser, and arise from denser Substances than those of Vapours,\nthence it is that true Air is more ponderous than Vapour, and that a\nmoist Atmosphere is lighter than a dry one, quantity for quantity. From\nthe same repelling Power it seems to be that Flies walk upon the Water\nwithout wetting their Feet; and that the Object-glasses of long\nTelescopes lie upon one another without touching; and that dry Powders\nare difficultly made to touch one another so as to stick together,\nunless by melting them, or wetting them with Water, which by exhaling\nmay bring them together; and that two polish'd Marbles, which by\nimmediate Contact stick together, are difficultly brought so close\ntogether as to stick.\n\nAnd thus Nature will be very conformable to her self and very simple,\nperforming all the great Motions of the heavenly Bodies by the\nAttraction of Gravity which intercedes those Bodies, and almost all the\nsmall ones of their Particles by some other attractive and repelling\nPowers which intercede the Particles. The _Vis inertiæ_ is a passive\nPrinciple by which Bodies persist in their Motion or Rest, receive\nMotion in proportion to the Force impressing it, and resist as much as\nthey are resisted. By this Principle alone there never could have been\nany Motion in the World. Some other Principle was necessary for putting\nBodies into Motion; and now they are in Motion, some other Principle is\nnecessary for conserving the Motion. For from the various Composition of\ntwo Motions, 'tis very certain that there is not always the same\nquantity of Motion in the World. For if two Globes joined by a slender\nRod, revolve about their common Center of Gravity with an uniform\nMotion, while that Center moves on uniformly in a right Line drawn in\nthe Plane of their circular Motion; the Sum of the Motions of the two\nGlobes, as often as the Globes are in the right Line described by their\ncommon Center of Gravity, will be bigger than the Sum of their Motions,\nwhen they are in a Line perpendicular to that right Line. By this\nInstance it appears that Motion may be got or lost. But by reason of the\nTenacity of Fluids, and Attrition of their Parts, and the Weakness of\nElasticity in Solids, Motion is much more apt to be lost than got, and\nis always upon the Decay. For Bodies which are either absolutely hard,\nor so soft as to be void of Elasticity, will not rebound from one\nanother. Impenetrability makes them only stop. If two equal Bodies meet\ndirectly _in vacuo_, they will by the Laws of Motion stop where they\nmeet, and lose all their Motion, and remain in rest, unless they be\nelastick, and receive new Motion from their Spring. If they have so much\nElasticity as suffices to make them re-bound with a quarter, or half, or\nthree quarters of the Force with which they come together, they will\nlose three quarters, or half, or a quarter of their Motion. And this may\nbe try'd, by letting two equal Pendulums fall against one another from\nequal heights. If the Pendulums be of Lead or soft Clay, they will lose\nall or almost all their Motions: If of elastick Bodies they will lose\nall but what they recover from their Elasticity. If it be said, that\nthey can lose no Motion but what they communicate to other Bodies, the\nconsequence is, that _in vacuo_ they can lose no Motion, but when they\nmeet they must go on and penetrate one another's Dimensions. If three\nequal round Vessels be filled, the one with Water, the other with Oil,\nthe third with molten Pitch, and the Liquors be stirred about alike to\ngive them a vortical Motion; the Pitch by its Tenacity will lose its\nMotion quickly, the Oil being less tenacious will keep it longer, and\nthe Water being less tenacious will keep it longest, but yet will lose\nit in a short time. Whence it is easy to understand, that if many\ncontiguous Vortices of molten Pitch were each of them as large as those\nwhich some suppose to revolve about the Sun and fix'd Stars, yet these\nand all their Parts would, by their Tenacity and Stiffness, communicate\ntheir Motion to one another till they all rested among themselves.\nVortices of Oil or Water, or some fluider Matter, might continue longer\nin Motion; but unless the Matter were void of all Tenacity and Attrition\nof Parts, and Communication of Motion, (which is not to be supposed,)\nthe Motion would constantly decay. Seeing therefore the variety of\nMotion which we find in the World is always decreasing, there is a\nnecessity of conserving and recruiting it by active Principles, such as\nare the cause of Gravity, by which Planets and Comets keep their Motions\nin their Orbs, and Bodies acquire great Motion in falling; and the cause\nof Fermentation, by which the Heart and Blood of Animals are kept in\nperpetual Motion and Heat; the inward Parts of the Earth are constantly\nwarm'd, and in some places grow very hot; Bodies burn and shine,\nMountains take fire, the Caverns of the Earth are blown up, and the Sun\ncontinues violently hot and lucid, and warms all things by his Light.\nFor we meet with very little Motion in the World, besides what is owing\nto these active Principles. And if it were not for these Principles, the\nBodies of the Earth, Planets, Comets, Sun, and all things in them,\nwould grow cold and freeze, and become inactive Masses; and all\nPutrefaction, Generation, Vegetation and Life would cease, and the\nPlanets and Comets would not remain in their Orbs.\n\nAll these things being consider'd, it seems probable to me, that God in\nthe Beginning form'd Matter in solid, massy, hard, impenetrable,\nmoveable Particles, of such Sizes and Figures, and with such other\nProperties, and in such Proportion to Space, as most conduced to the End\nfor which he form'd them; and that these primitive Particles being\nSolids, are incomparably harder than any porous Bodies compounded of\nthem; even so very hard, as never to wear or break in pieces; no\nordinary Power being able to divide what God himself made one in the\nfirst Creation. While the Particles continue entire, they may compose\nBodies of one and the same Nature and Texture in all Ages: But should\nthey wear away, or break in pieces, the Nature of Things depending on\nthem, would be changed. Water and Earth, composed of old worn Particles\nand Fragments of Particles, would not be of the same Nature and Texture\nnow, with Water and Earth composed of entire Particles in the Beginning.\nAnd therefore, that Nature may be lasting, the Changes of corporeal\nThings are to be placed only in the various Separations and new\nAssociations and Motions of these permanent Particles; compound Bodies\nbeing apt to break, not in the midst of solid Particles, but where those\nParticles are laid together, and only touch in a few Points.\n\nIt seems to me farther, that these Particles have not only a _Vis\ninertiæ_, accompanied with such passive Laws of Motion as naturally\nresult from that Force, but also that they are moved by certain active\nPrinciples, such as is that of Gravity, and that which causes\nFermentation, and the Cohesion of Bodies. These Principles I consider,\nnot as occult Qualities, supposed to result from the specifick Forms of\nThings, but as general Laws of Nature, by which the Things themselves\nare form'd; their Truth appearing to us by Phænomena, though their\nCauses be not yet discover'd. For these are manifest Qualities, and\ntheir Causes only are occult. And the _Aristotelians_ gave the Name of\noccult Qualities, not to manifest Qualities, but to such Qualities only\nas they supposed to lie hid in Bodies, and to be the unknown Causes of\nmanifest Effects: Such as would be the Causes of Gravity, and of\nmagnetick and electrick Attractions, and of Fermentations, if we should\nsuppose that these Forces or Actions arose from Qualities unknown to us,\nand uncapable of being discovered and made manifest. Such occult\nQualities put a stop to the Improvement of natural Philosophy, and\ntherefore of late Years have been rejected. To tell us that every\nSpecies of Things is endow'd with an occult specifick Quality by which\nit acts and produces manifest Effects, is to tell us nothing: But to\nderive two or three general Principles of Motion from Phænomena, and\nafterwards to tell us how the Properties and Actions of all corporeal\nThings follow from those manifest Principles, would be a very great step\nin Philosophy, though the Causes of those Principles were not yet\ndiscover'd: And therefore I scruple not to propose the Principles of\nMotion above-mention'd, they being of very general Extent, and leave\ntheir Causes to be found out.\n\nNow by the help of these Principles, all material Things seem to have\nbeen composed of the hard and solid Particles above-mention'd, variously\nassociated in the first Creation by the Counsel of an intelligent Agent.\nFor it became him who created them to set them in order. And if he did\nso, it's unphilosophical to seek for any other Origin of the World, or\nto pretend that it might arise out of a Chaos by the mere Laws of\nNature; though being once form'd, it may continue by those Laws for many\nAges. For while Comets move in very excentrick Orbs in all manner of\nPositions, blind Fate could never make all the Planets move one and the\nsame way in Orbs concentrick, some inconsiderable Irregularities\nexcepted, which may have risen from the mutual Actions of Comets and\nPlanets upon one another, and which will be apt to increase, till this\nSystem wants a Reformation. Such a wonderful Uniformity in the Planetary\nSystem must be allowed the Effect of Choice. And so must the Uniformity\nin the Bodies of Animals, they having generally a right and a left side\nshaped alike, and on either side of their Bodies two Legs behind, and\neither two Arms, or two Legs, or two Wings before upon their Shoulders,\nand between their Shoulders a Neck running down into a Back-bone, and a\nHead upon it; and in the Head two Ears, two Eyes, a Nose, a Mouth, and\na Tongue, alike situated. Also the first Contrivance of those very\nartificial Parts of Animals, the Eyes, Ears, Brain, Muscles, Heart,\nLungs, Midriff, Glands, Larynx, Hands, Wings, swimming Bladders, natural\nSpectacles, and other Organs of Sense and Motion; and the Instinct of\nBrutes and Insects, can be the effect of nothing else than the Wisdom\nand Skill of a powerful ever-living Agent, who being in all Places, is\nmore able by his Will to move the Bodies within his boundless uniform\nSensorium, and thereby to form and reform the Parts of the Universe,\nthan we are by our Will to move the Parts of our own Bodies. And yet we\nare not to consider the World as the Body of God, or the several Parts\nthereof, as the Parts of God. He is an uniform Being, void of Organs,\nMembers or Parts, and they are his Creatures subordinate to him, and\nsubservient to his Will; and he is no more the Soul of them, than the\nSoul of Man is the Soul of the Species of Things carried through the\nOrgans of Sense into the place of its Sensation, where it perceives them\nby means of its immediate Presence, without the Intervention of any\nthird thing. The Organs of Sense are not for enabling the Soul to\nperceive the Species of Things in its Sensorium, but only for conveying\nthem thither; and God has no need of such Organs, he being every where\npresent to the Things themselves. And since Space is divisible _in\ninfinitum_, and Matter is not necessarily in all places, it may be also\nallow'd that God is able to create Particles of Matter of several Sizes\nand Figures, and in several Proportions to Space, and perhaps of\ndifferent Densities and Forces, and thereby to vary the Laws of Nature,\nand make Worlds of several sorts in several Parts of the Universe. At\nleast, I see nothing of Contradiction in all this.\n\nAs in Mathematicks, so in Natural Philosophy, the Investigation of\ndifficult Things by the Method of Analysis, ought ever to precede the\nMethod of Composition. This Analysis consists in making Experiments and\nObservations, and in drawing general Conclusions from them by Induction,\nand admitting of no Objections against the Conclusions, but such as are\ntaken from Experiments, or other certain Truths. For Hypotheses are not\nto be regarded in experimental Philosophy. And although the arguing from\nExperiments and Observations by Induction be no Demonstration of general\nConclusions; yet it is the best way of arguing which the Nature of\nThings admits of, and may be looked upon as so much the stronger, by how\nmuch the Induction is more general. And if no Exception occur from\nPhænomena, the Conclusion may be pronounced generally. But if at any\ntime afterwards any Exception shall occur from Experiments, it may then\nbegin to be pronounced with such Exceptions as occur. By this way of\nAnalysis we may proceed from Compounds to Ingredients, and from Motions\nto the Forces producing them; and in general, from Effects to their\nCauses, and from particular Causes to more general ones, till the\nArgument end in the most general. This is the Method of Analysis: And\nthe Synthesis consists in assuming the Causes discover'd, and\nestablish'd as Principles, and by them explaining the Phænomena\nproceeding from them, and proving the Explanations.\n\nIn the two first Books of these Opticks, I proceeded by this Analysis to\ndiscover and prove the original Differences of the Rays of Light in\nrespect of Refrangibility, Reflexibility, and Colour, and their\nalternate Fits of easy Reflexion and easy Transmission, and the\nProperties of Bodies, both opake and pellucid, on which their Reflexions\nand Colours depend. And these Discoveries being proved, may be assumed\nin the Method of Composition for explaining the Phænomena arising from\nthem: An Instance of which Method I gave in the End of the first Book.\nIn this third Book I have only begun the Analysis of what remains to be\ndiscover'd about Light and its Effects upon the Frame of Nature, hinting\nseveral things about it, and leaving the Hints to be examin'd and\nimprov'd by the farther Experiments and Observations of such as are\ninquisitive. And if natural Philosophy in all its Parts, by pursuing\nthis Method, shall at length be perfected, the Bounds of Moral\nPhilosophy will be also enlarged. For so far as we can know by natural\nPhilosophy what is the first Cause, what Power he has over us, and what\nBenefits we receive from him, so far our Duty towards him, as well as\nthat towards one another, will appear to us by the Light of Nature. And\nno doubt, if the Worship of false Gods had not blinded the Heathen,\ntheir moral Philosophy would have gone farther than to the four\nCardinal Virtues; and instead of teaching the Transmigration of Souls,\nand to worship the Sun and Moon, and dead Heroes, they would have taught\nus to worship our true Author and Benefactor, as their Ancestors did\nunder the Government of _Noah_ and his Sons before they corrupted\nthemselves."
  },
  {
    "path": "src/vendor/libbacktrace/LICENSE",
    "content": "# Copyright (C) 2012-2016 Free Software Foundation, Inc.\n\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions are\n# met:\n\n#     (1) Redistributions of source code must retain the above copyright\n#     notice, this list of conditions and the following disclaimer. \n\n#     (2) Redistributions in binary form must reproduce the above copyright\n#     notice, this list of conditions and the following disclaimer in\n#     the documentation and/or other materials provided with the\n#     distribution.  \n    \n#     (3) The name of the author may not be used to\n#     endorse or promote products derived from this software without\n#     specific prior written permission.\n\n# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n# DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,\n# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\n# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n# POSSIBILITY OF SUCH DAMAGE.\n"
  },
  {
    "path": "src/vendor/libbacktrace/Makefile.am",
    "content": "# Makefile.am -- Backtrace Makefile.\n# Copyright (C) 2012-2024 Free Software Foundation, Inc.\n\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions are\n# met:\n\n#     (1) Redistributions of source code must retain the above copyright\n#     notice, this list of conditions and the following disclaimer.\n\n#     (2) Redistributions in binary form must reproduce the above copyright\n#     notice, this list of conditions and the following disclaimer in\n#     the documentation and/or other materials provided with the\n#     distribution.\n\n#     (3) The name of the author may not be used to\n#     endorse or promote products derived from this software without\n#     specific prior written permission.\n\n# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n# DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,\n# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\n# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n# POSSIBILITY OF SUCH DAMAGE.\n\nACLOCAL_AMFLAGS = -I config\n\nAM_CPPFLAGS =\n\nAM_CFLAGS = $(EXTRA_FLAGS) $(WARN_FLAGS) $(PIC_FLAG)\n\ninclude_HEADERS = backtrace.h backtrace-supported.h internal.h debuginfod_support.h\n\nlib_LTLIBRARIES = libbacktrace.la\n\nlibbacktrace_la_SOURCES = \\\n\tbacktrace.h \\\n\tatomic.c \\\n\tdwarf.c \\\n\tfileline.c \\\n\tinternal.h \\\n\tdebuginfod_support.h \\\n\tposix.c \\\n\tprint.c \\\n\tsort.c \\\n\tstate.c\n\nBACKTRACE_FILES = \\\n\tbacktrace.c \\\n\tsimple.c \\\n\tnounwind.c\n\nFORMAT_FILES = \\\n\telf.c \\\n\tmacho.c \\\n\tpecoff.c \\\n\tunknown.c \\\n\txcoff.c\n\nVIEW_FILES = \\\n\tread.c \\\n\tmmapio.c\n\nALLOC_FILES = \\\n\talloc.c \\\n\tmmap.c\n\nEXTRA_libbacktrace_la_SOURCES = \\\n\t$(BACKTRACE_FILES) \\\n\t$(FORMAT_FILES) \\\n\t$(VIEW_FILES) \\\n\t$(ALLOC_FILES)\n\nlibbacktrace_la_LIBADD = \\\n\t$(BACKTRACE_FILE) \\\n\t$(FORMAT_FILE) \\\n\t$(VIEW_FILE) \\\n\t$(ALLOC_FILE)\n\nlibbacktrace_la_DEPENDENCIES = $(libbacktrace_la_LIBADD)\n\n# Testsuite.\n\n# Add a test to this variable if you want it to be built as a program,\n# with SOURCES, etc.\ncheck_PROGRAMS =\n\n# Add a test to this variable if you want it to be run.\nTESTS =\n\n# Add a test to this variable if you want it to be built as a Makefile\n# target and run.\nMAKETESTS =\n\n# Add a test to this variable if you want it to be built as a program,\n# with SOURCES, etc., and run.\nBUILDTESTS =\n\n# Add a file to this variable if you want it to be built for testing.\ncheck_DATA =\n\n# Flags to use when compiling test programs.\nlibbacktrace_TEST_CFLAGS = $(EXTRA_FLAGS) $(WARN_FLAGS) -g\n\n# Flags to use when linking test programs.\n# This avoids generating a shell script when configured with --enable-shared.\nlibbacktrace_testing_ldflags = -no-install\n\nif USE_DSYMUTIL\n\n%.dSYM: %\n\t$(DSYMUTIL) $<\n\nendif USE_DSYMUTIL\n\nif NATIVE\ncheck_LTLIBRARIES = libbacktrace_alloc.la\n\nlibbacktrace_alloc_la_SOURCES = $(libbacktrace_la_SOURCES)\nlibbacktrace_alloc_la_LIBADD = $(BACKTRACE_FILE) $(FORMAT_FILE) read.lo alloc.lo\n\nlibbacktrace_alloc_la_DEPENDENCIES = $(libbacktrace_alloc_la_LIBADD)\n\ncheck_LTLIBRARIES += libbacktrace_noformat.la\n\nlibbacktrace_noformat_la_SOURCES = $(libbacktrace_la_SOURCES)\nlibbacktrace_noformat_la_LIBADD = $(BACKTRACE_FILE) $(VIEW_FILE) $(ALLOC_FILE)\n\nlibbacktrace_noformat_la_DEPENDENCIES = $(libbacktrace_noformat_la_LIBADD)\n\nif HAVE_ELF\nif HAVE_OBJCOPY_DEBUGLINK\n\nTEST_BUILD_ID_DIR=$(abs_builddir)/usr/lib/debug/.build-id/\n\ncheck_LTLIBRARIES += libbacktrace_elf_for_test.la\n\nlibbacktrace_elf_for_test_la_SOURCES = $(libbacktrace_la_SOURCES)\nlibbacktrace_elf_for_test_la_LIBADD = $(BACKTRACE_FILE) elf_for_test.lo \\\n\t$(VIEW_FILE) $(ALLOC_FILE)\n\nelf_for_test.c: elf.c\n\tSEARCH='^#define SYSTEM_BUILD_ID_DIR.*$$'; \\\n\tREPLACE=\"#define SYSTEM_BUILD_ID_DIR \\\"$(TEST_BUILD_ID_DIR)\\\"\"; \\\n\t$(SED) \"s%$$SEARCH%$$REPLACE%\" \\\n\t\t$< \\\n\t\t> $@.tmp\n\tmv $@.tmp $@\n\nendif HAVE_OBJCOPY_DEBUGLINK\nendif HAVE_ELF\n\nelf_%.c: elf.c\n\tnlinit=`echo 'nl=\"'; echo '\"'`; eval \"$$nlinit\"; \\\n\tSEARCH='#error \"Unknown BACKTRACE_ELF_SIZE\"'; \\\n\tREPLACE=\"#undef BACKTRACE_ELF_SIZE\\\\$${nl}#define BACKTRACE_ELF_SIZE\"; \\\n\t$(SED) \"s/^$$SEARCH\\$$/$$REPLACE $*/\" \\\n\t\t$< \\\n\t\t> $@.tmp\n\tmv $@.tmp $@\n\nxcoff_%.c: xcoff.c\n\tnlinit=`echo 'nl=\"'; echo '\"'`; eval \"$$nlinit\"; \\\n\tSEARCH='#error \"Unknown BACKTRACE_XCOFF_SIZE\"'; \\\n\tREPLACE=\"#undef BACKTRACE_XCOFF_SIZE\\\\$${nl}#define BACKTRACE_XCOFF_SIZE\"; \\\n\t$(SED) \"s/^$$SEARCH\\$$/$$REPLACE $*/\" \\\n\t\t$< \\\n\t\t> $@.tmp\n\tmv $@.tmp $@\n\ntest_elf_32_SOURCES = test_format.c testlib.c\ntest_elf_32_CFLAGS = $(libbacktrace_TEST_CFLAGS)\ntest_elf_32_LDFLAGS = $(libbacktrace_testing_ldflags)\ntest_elf_32_LDADD = libbacktrace_noformat.la elf_32.lo\n\nBUILDTESTS += test_elf_32\n\ntest_elf_64_SOURCES = test_format.c testlib.c\ntest_elf_64_CFLAGS = $(libbacktrace_TEST_CFLAGS)\ntest_elf_64_LDFLAGS = $(libbacktrace_testing_ldflags)\ntest_elf_64_LDADD = libbacktrace_noformat.la elf_64.lo\n\nBUILDTESTS += test_elf_64\n\ntest_macho_SOURCES = test_format.c testlib.c\ntest_macho_CFLAGS = $(libbacktrace_TEST_CFLAGS)\ntest_macho_LDFLAGS = $(libbacktrace_testing_ldflags)\ntest_macho_LDADD = libbacktrace_noformat.la macho.lo\n\nBUILDTESTS += test_macho\n\ntest_xcoff_32_SOURCES = test_format.c testlib.c\ntest_xcoff_32_CFLAGS = $(libbacktrace_TEST_CFLAGS)\ntest_xcoff_32_LDFLAGS = $(libbacktrace_testing_ldflags)\ntest_xcoff_32_LDADD = libbacktrace_noformat.la xcoff_32.lo\n\nBUILDTESTS += test_xcoff_32\n\ntest_xcoff_64_SOURCES = test_format.c testlib.c\ntest_xcoff_64_CFLAGS = $(libbacktrace_TEST_CFLAGS)\ntest_xcoff_64_LDFLAGS = $(libbacktrace_testing_ldflags)\ntest_xcoff_64_LDADD = libbacktrace_noformat.la xcoff_64.lo\n\nBUILDTESTS += test_xcoff_64\n\ntest_pecoff_SOURCES = test_format.c testlib.c\ntest_pecoff_CFLAGS = $(libbacktrace_TEST_CFLAGS)\ntest_pecoff_LDFLAGS = $(libbacktrace_testing_ldflags)\ntest_pecoff_LDADD = libbacktrace_noformat.la pecoff.lo\n\nBUILDTESTS += test_pecoff\n\ntest_unknown_SOURCES = test_format.c testlib.c\ntest_unknown_CFLAGS = $(libbacktrace_TEST_CFLAGS)\ntest_unknown_LDFLAGS = $(libbacktrace_testing_ldflags)\ntest_unknown_LDADD = libbacktrace_noformat.la unknown.lo\n\nBUILDTESTS += test_unknown\n\nunittest_SOURCES = unittest.c testlib.c\nunittest_CFLAGS = $(libbacktrace_TEST_CFLAGS)\nunittest_LDFLAGS = $(libbacktrace_testing_ldflags)\nunittest_LDADD = libbacktrace.la\n\nBUILDTESTS += unittest\n\nunittest_alloc_SOURCES = $(unittest_SOURCES)\nunittest_alloc_CFLAGS = $(libbacktrace_TEST_CFLAGS)\nunittest_alloc_LDFLAGS = $(libbacktrace_testing_ldflags)\nunittest_alloc_LDADD = libbacktrace_alloc.la\n\nBUILDTESTS += unittest_alloc\n\ncheck_LTLIBRARIES += libbacktrace_instrumented_alloc.la\n\nlibbacktrace_instrumented_alloc_la_SOURCES = $(libbacktrace_la_SOURCES)\nlibbacktrace_instrumented_alloc_la_LIBADD = $(BACKTRACE_FILE) $(FORMAT_FILE) \\\n\tread.lo instrumented_alloc.lo\n\nlibbacktrace_instrumented_alloc_la_DEPENDENCIES = \\\n\t$(libbacktrace_instrumented_alloc_la_LIBADD)\n\ninstrumented_alloc.lo: alloc.c\n\nallocfail_SOURCES = allocfail.c testlib.c\nallocfail_CFLAGS = $(libbacktrace_TEST_CFLAGS)\nallocfail_LDADD = libbacktrace_instrumented_alloc.la\n\ncheck_PROGRAMS += allocfail\n\nallocfail.sh: allocfail\n\nTESTS += allocfail.sh\n\nif USE_DSYMUTIL\ncheck_DATA += allocfail.dSYM\nendif USE_DSYMUTIL\n\nif HAVE_ELF\nif HAVE_BUILDID\nif HAVE_OBJCOPY_DEBUGLINK\n\nb2test_SOURCES = $(btest_SOURCES)\nb2test_CFLAGS = $(libbacktrace_TEST_CFLAGS)\nb2test_LDFLAGS = -Wl,--build-id $(libbacktrace_testing_ldflags)\nb2test_LDADD = libbacktrace_elf_for_test.la\n\ncheck_PROGRAMS += b2test\nMAKETESTS += b2test_buildid b2test_buildidfull\n\nif HAVE_DWZ\n\nb3test_SOURCES = $(btest_SOURCES)\nb3test_CFLAGS = $(libbacktrace_TEST_CFLAGS)\nb3test_LDFLAGS = -Wl,--build-id $(libbacktrace_testing_ldflags)\nb3test_LDADD = libbacktrace_elf_for_test.la\n\ncheck_PROGRAMS += b3test\nMAKETESTS += b3test_dwz_buildid b3test_dwz_buildidfull\n\nendif HAVE_DWZ\n\nendif HAVE_OBJCOPY_DEBUGLINK\nendif HAVE_BUILDID\nendif HAVE_ELF\n\nbtest_SOURCES = btest.c testlib.c\nbtest_CFLAGS = $(libbacktrace_TEST_CFLAGS) -O\nbtest_LDFLAGS = $(libbacktrace_testing_ldflags)\nbtest_LDADD = libbacktrace.la\n\nBUILDTESTS += btest\n\nif USE_DSYMUTIL\ncheck_DATA += btest.dSYM\nendif USE_DSYMUTIL\n\nif HAVE_ELF\n\nbtest_lto_SOURCES = btest.c testlib.c\nbtest_lto_CFLAGS = $(libbacktrace_TEST_CFLAGS) -O -flto\nbtest_lto_LDFLAGS = $(libbacktrace_testing_ldflags)\nbtest_lto_LDADD = libbacktrace.la\n\nBUILDTESTS += btest_lto\n\nendif HAVE_ELF\n\nbtest_alloc_SOURCES = $(btest_SOURCES)\nbtest_alloc_CFLAGS = $(libbacktrace_TEST_CFLAGS)\nbtest_alloc_LDFLAGS = $(libbacktrace_testing_ldflags)\nbtest_alloc_LDADD = libbacktrace_alloc.la\n\nBUILDTESTS += btest_alloc\n\nif USE_DSYMUTIL\ncheck_DATA += btest_alloc.dSYM\nendif USE_DSYMUTIL\n\nif HAVE_DWZ\n\n%_dwz: %\n\trm -f $@ $@_common.debug\n\tcp $< $@_1\n\tcp $< $@_2\n\tif $(DWZ) -m $@_common.debug $@_1 $@_2; then \\\n\t  rm -f $@_2; \\\n\t  mv $@_1 $@; \\\n\telse \\\n\t  echo \"Ignoring dwz errors, assuming that test passes\"; \\\n\t  cp $< $@; \\\n\tfi\n\nMAKETESTS += btest_dwz\n\nif HAVE_OBJCOPY_DEBUGLINK\n\nMAKETESTS += btest_dwz_gnudebuglink\n\nendif HAVE_OBJCOPY_DEBUGLINK\n\nendif HAVE_DWZ\n\nstest_SOURCES = stest.c\nstest_CFLAGS = $(libbacktrace_TEST_CFLAGS)\nstest_LDFLAGS = $(libbacktrace_testing_ldflags)\nstest_LDADD = libbacktrace.la\n\nBUILDTESTS += stest\n\nif USE_DSYMUTIL\ncheck_DATA += stest.dSYM\nendif USE_DSYMUTIL\n\nstest_alloc_SOURCES = $(stest_SOURCES)\nstest_alloc_CFLAGS = $(libbacktrace_TEST_CFLAGS)\nstest_alloc_LDFLAGS = $(libbacktrace_testing_ldflags)\nstest_alloc_LDADD = libbacktrace_alloc.la\n\nBUILDTESTS += stest_alloc\n\nif USE_DSYMUTIL\ncheck_DATA += stest_alloc.dSYM\nendif USE_DSYMUTIL\n\nif HAVE_ELF\n\nztest_SOURCES = ztest.c testlib.c\nztest_CFLAGS = $(libbacktrace_TEST_CFLAGS) -DSRCDIR=\\\"$(srcdir)\\\"\nztest_LDFLAGS = $(libbacktrace_testing_ldflags)\nztest_LDADD = libbacktrace.la\nztest_alloc_LDADD = libbacktrace_alloc.la\n\nif HAVE_ZLIB\nztest_LDADD += -lz\nztest_alloc_LDADD += -lz\nendif\nztest_LDADD += $(CLOCK_GETTIME_LINK)\nztest_alloc_LDADD += $(CLOCK_GETTIME_LINK)\n\nBUILDTESTS += ztest\n\nztest_alloc_SOURCES = $(ztest_SOURCES)\nztest_alloc_CFLAGS = $(ztest_CFLAGS)\nztest_alloc_LDFLAGS = $(libbacktrace_testing_ldflags)\n\nBUILDTESTS += ztest_alloc\n\nzstdtest_SOURCES = zstdtest.c testlib.c\nzstdtest_CFLAGS = $(libbacktrace_TEST_CFLAGS) -DSRCDIR=\\\"$(srcdir)\\\"\nzstdtest_LDFLAGS = $(libbacktrace_testing_ldflags)\nzstdtest_LDADD = libbacktrace.la\nzstdtest_alloc_LDADD = libbacktrace_alloc.la\n\nif HAVE_ZSTD\nzstdtest_LDADD += -lzstd\nzstdtest_alloc_LDADD += -lzstd\nendif\nzstdtest_LDADD += $(CLOCK_GETTIME_LINK)\nzstdtest_alloc_LDADD += $(CLOCK_GETTIME_LINK)\n\nBUILDTESTS += zstdtest\n\nzstdtest_alloc_SOURCES = $(zstdtest_SOURCES)\nzstdtest_alloc_CFLAGS = $(zstdtest_CFLAGS)\nzstdtest_alloc_LDFLAGS = $(libbacktrace_testing_ldflags)\n\nBUILDTESTS += zstdtest_alloc\n\nendif HAVE_ELF\n\nedtest_SOURCES = edtest.c edtest2_build.c testlib.c\nedtest_CFLAGS = $(libbacktrace_TEST_CFLAGS)\nedtest_LDFLAGS = $(libbacktrace_testing_ldflags)\nedtest_LDADD = libbacktrace.la\n\nBUILDTESTS += edtest\n\nif USE_DSYMUTIL\ncheck_DATA += edtest.dSYM\nendif USE_DSYMUTIL\n\nedtest_alloc_SOURCES = $(edtest_SOURCES)\nedtest_alloc_CFLAGS = $(libbacktrace_TEST_CFLAGS)\nedtest_alloc_LDFLAGS = $(libbacktrace_testing_ldflags)\nedtest_alloc_LDADD = libbacktrace_alloc.la\n\nif USE_DSYMUTIL\ncheck_DATA += edtest_alloc.dSYM\nendif USE_DSYMUTIL\n\nBUILDTESTS += edtest_alloc\n\nedtest2_build.c: gen_edtest2_build; @true\ngen_edtest2_build: $(srcdir)/edtest2.c\n\tcat $(srcdir)/edtest2.c > tmp-edtest2_build.c\n\t$(SHELL) $(srcdir)/move-if-change tmp-edtest2_build.c edtest2_build.c\n\techo timestamp > $@\n\nif HAVE_PTHREAD\n\nBUILDTESTS += ttest\n\nttest_SOURCES = ttest.c testlib.c\nttest_CFLAGS = $(libbacktrace_TEST_CFLAGS) -pthread\nttest_LDFLAGS = $(libbacktrace_testing_ldflags)\nttest_LDADD = libbacktrace.la\n\nif USE_DSYMUTIL\ncheck_DATA += ttest.dSYM\nendif USE_DSYMUTIL\n\nBUILDTESTS += ttest_alloc\n\nttest_alloc_SOURCES = $(ttest_SOURCES)\nttest_alloc_CFLAGS = $(ttest_CFLAGS)\nttest_alloc_LDFLAGS = $(libbacktrace_testing_ldflags)\nttest_alloc_LDADD = libbacktrace_alloc.la\n\nif USE_DSYMUTIL\ncheck_DATA += ttest_alloc.dSYM\nendif USE_DSYMUTIL\n\nendif HAVE_PTHREAD\n\nif HAVE_OBJCOPY_DEBUGLINK\n\nMAKETESTS += btest_gnudebuglink btest_gnudebuglinkfull\n\n%_gnudebuglink: %\n\t$(OBJCOPY) --only-keep-debug $< $@.debug\n\t$(OBJCOPY) --strip-debug --add-gnu-debuglink=$@.debug $< $@\n\n%_gnudebuglinkfull: %\n\t$(OBJCOPY) --only-keep-debug $< $@.debug\n\t$(OBJCOPY) --strip-all --add-gnu-debuglink=$@.debug $< $@\n\nendif HAVE_OBJCOPY_DEBUGLINK\n\n%_buildid: %\n\t./install-debuginfo-for-buildid.sh \\\n\t  \"$(TEST_BUILD_ID_DIR)\" \\\n\t  $<\n\t$(OBJCOPY) --strip-debug $< $@\n\n%_buildidfull: %\n\t./install-debuginfo-for-buildid.sh \\\n\t  \"$(TEST_BUILD_ID_DIR)\" \\\n\t  $<\n\t$(OBJCOPY) --strip-all $< $@\n\nif HAVE_COMPRESSED_DEBUG_ZLIB_GNU\n\nctestg_SOURCES = btest.c testlib.c\nctestg_CFLAGS = $(libbacktrace_TEST_CFLAGS)\nctestg_LDFLAGS = -Wl,--compress-debug-sections=zlib-gnu $(libbacktrace_testing_ldflags)\nctestg_LDADD = libbacktrace.la\n\nctestg_alloc_SOURCES = $(ctestg_SOURCES)\nctestg_alloc_CFLAGS = $(ctestg_CFLAGS)\nctestg_alloc_LDFLAGS = $(ctestg_LDFLAGS) $(libbacktrace_testing_ldflags)\nctestg_alloc_LDADD = libbacktrace_alloc.la\n\nBUILDTESTS += ctestg ctestg_alloc\n\nendif\n\nif HAVE_COMPRESSED_DEBUG_ZLIB_GABI\n\nctesta_SOURCES = btest.c testlib.c\nctesta_CFLAGS = $(libbacktrace_TEST_CFLAGS)\nctesta_LDFLAGS = -Wl,--compress-debug-sections=zlib-gabi $(libbacktrace_testing_ldflags)\nctesta_LDADD = libbacktrace.la\n\nctesta_alloc_SOURCES = $(ctesta_SOURCES)\nctesta_alloc_CFLAGS = $(ctesta_CFLAGS)\nctesta_alloc_LDFLAGS = $(ctesta_LDFLAGS) $(libbacktrace_testing_ldflags)\nctesta_alloc_LDADD = libbacktrace_alloc.la\n\nBUILDTESTS += ctesta ctesta_alloc\n\nendif\n\nif HAVE_COMPRESSED_DEBUG_ZSTD\n\nctestzstd_SOURCES = btest.c testlib.c\nctestzstd_CFLAGS = $(libbacktrace_TEST_CFLAGS)\nctestzstd_LDFLAGS = -Wl,--compress-debug-sections=zstd $(libbacktrace_testing_ldflags)\nctestzstd_LDADD = libbacktrace.la\n\nctestzstd_alloc_SOURCES = $(ctestzstd_SOURCES)\nctestzstd_alloc_CFLAGS = $(ctestzstd_CFLAGS)\nctestzstd_alloc_LDFLAGS = $(ctestzstd_LDFLAGS) $(libbacktrace_testing_ldflags)\nctestzstd_alloc_LDADD = libbacktrace_alloc.la\n\nBUILDTESTS += ctestzstd ctestzstd_alloc\n\nendif\n\nif HAVE_DWARF5\n\ndwarf5_SOURCES = btest.c testlib.c\ndwarf5_CFLAGS = $(libbacktrace_TEST_CFLAGS) -gdwarf-5\ndwarf5_LDFLAGS = $(libbacktrace_testing_ldflags)\ndwarf5_LDADD = libbacktrace.la\n\nBUILDTESTS += dwarf5\n\nif USE_DSYMUTIL\ncheck_DATA += dwarf5.dSYM\nendif USE_DSYMUTIL\n\ndwarf5_alloc_SOURCES = $(dwarf5_SOURCES)\ndwarf5_alloc_CFLAGS = $(dwarf5_CFLAGS)\ndwarf5_alloc_LDFLAGS = $(libbacktrace_testing_ldflags)\ndwarf5_alloc_LDADD = libbacktrace_alloc.la\n\nBUILDTESTS += dwarf5_alloc\n\nif USE_DSYMUTIL\ncheck_DATA += dwarf5_alloc.dSYM\nendif USE_DSYMUTIL\n\nendif\n\nmtest_SOURCES = mtest.c testlib.c\nmtest_CFLAGS = $(libbacktrace_TEST_CFLAGS) -O\nmtest_LDFLAGS = $(libbacktrace_testing_ldflags)\nmtest_LDADD = libbacktrace.la\n\nBUILDTESTS += mtest\n\nif USE_DSYMUTIL\ncheck_DATA += mtest.dSYM\nendif USE_DSYMUTIL\n\nif HAVE_MINIDEBUG\n\nMAKETESTS += mtest_minidebug\n\n%_minidebug: %\n\t$(NM) -D $< -P --defined-only | $(AWK) '{ print $$1 }' | sort > $<.dsyms\n\t$(NM) $< -P --defined-only | $(AWK) '{ if ($$2 == \"T\" || $$2 == \"t\" || $$2 == \"D\") print $$1 }' | sort > $<.fsyms\n\t$(COMM) -13 $<.dsyms $<.fsyms > $<.keepsyms\n\t$(OBJCOPY) --only-keep-debug $< $<.dbg\n\t$(OBJCOPY) -S --remove-section .gdb_index --remove-section .comment --keep-symbols=$<.keepsyms $<.dbg $<.mdbg\n\t$(OBJCOPY) --strip-all --remove-section ..comment $< $<.strip\n\trm -f $<.mdbg.xz\n\t$(XZ) $<.mdbg\n\t$(OBJCOPY) --add-section .gnu_debugdata=$<.mdbg.xz $<.strip\n\tmv $<.strip $@\n\nif HAVE_ELF\nif HAVE_BUILDID\nif HAVE_OBJCOPY_DEBUGLINK\n\nm2test_SOURCES = $(mtest_SOURCES)\nm2test_CFLAGS = $(libbacktrace_TEST_CFLAGS) -O\nm2test_LDFLAGS = -Wl,--build-id $(libbacktrace_testing_ldflags)\nm2test_LDADD = libbacktrace_elf_for_test.la\n\ncheck_PROGRAMS += m2test\nMAKETESTS += m2test_minidebug2\n\n# minidebug2 is like minidebug but also adds the gnu_debugdata section\n# to the debug file, and uses a build ID file.  There is no reason to do\n# this but it was causing an infinite recursion.\n%_minidebug2: %\n\t$(NM) -D $< -P --defined-only | $(AWK) '{ print $$1 }' | sort > $<.dsyms2\n\t$(NM) $< -P --defined-only | $(AWK) '{ if ($$2 == \"T\" || $$2 == \"t\" || $$2 == \"D\") print $$1 }' | sort > $<.fsyms2\n\t$(COMM) -13 $<.dsyms2 $<.fsyms2 > $<.keepsyms2\n\t$(OBJCOPY) --only-keep-debug $< $<.dbg2\n\t$(OBJCOPY) -S --remove-section .gdb_index --remove-section .comment --keep-symbols=$<.keepsyms2 $<.dbg2 $<.mdbg2\n\t$(OBJCOPY) --strip-all --remove-section ..comment $< $<.strip2\n\trm -f $<.mdbg2.xz\n\t$(XZ) $<.mdbg2\n\t$(OBJCOPY) --add-section .gnu_debugdata=$<.mdbg2.xz $<.dbg2\n\t$(OBJCOPY) --add-section .gnu_debugdata=$<.mdbg2.xz $<.strip2\n\t$(SHELL) ./install-debuginfo-for-buildid.sh $(TEST_BUILD_ID_DIR) $<.dbg2\n\tmv $<.strip2 $@\n\nendif HAVE_OBJCOPY_DEBUGLINK\nendif HAVE_BUILDID\nendif HAVE_ELF\n\nendif HAVE_MINIDEBUG\n\nendif NATIVE\n\nif HAVE_ELF\n\nxztest_SOURCES = xztest.c testlib.c\nxztest_CFLAGS = $(libbacktrace_TEST_CFLAGS) -DSRCDIR=\\\"$(srcdir)\\\"\nxztest_LDFLAGS = $(libbacktrace_testing_ldflags)\nxztest_LDADD = libbacktrace.la\n\nxztest_alloc_SOURCES = $(xztest_SOURCES)\nxztest_alloc_CFLAGS = $(xztest_CFLAGS)\nxztest_alloc_LDFLAGS = $(libbacktrace_testing_ldflags)\nxztest_alloc_LDADD = libbacktrace_alloc.la\n\nif HAVE_LIBLZMA\nxztest_LDADD += -llzma\nxztest_alloc_LDADD += -llzma\nendif\n\nxztest_LDADD += $(CLOCK_GETTIME_LINK)\nxztest_alloc_LDADD += $(CLOCK_GETTIME_LINK)\n\nBUILDTESTS += xztest xztest_alloc\n\nendif HAVE_ELF\n\ncheck_PROGRAMS += $(BUILDTESTS)\n\nTESTS += $(MAKETESTS) $(BUILDTESTS)\n\nCLEANFILES = \\\n\t$(MAKETESTS) $(BUILDTESTS) *.debug elf_for_test.c edtest2_build.c \\\n\tgen_edtest2_build \\\n\t*.dsyms *.fsyms *.keepsyms *.dbg *.mdbg *.mdbg.xz *.strip \\\n\t*.dsyms2 *.fsyms2 *.keepsyms2 *.dbg2 *.mdbg2 *.mdbg2.xz *.strip2\n\nclean-local:\n\t-rm -rf usr\n\n# We can't use automake's automatic dependency tracking, because it\n# breaks when using bootstrap-lean.  Automatic dependency tracking\n# with GCC bootstrap will cause some of the objects to depend on\n# header files in prev-gcc/include, e.g., stddef.h and stdarg.h.  When\n# using bootstrap-lean, prev-gcc is removed after each stage.  When\n# running \"make install\", those header files will be gone, causing the\n# library to be rebuilt at install time.  That may not succeed.\n\n# These manual dependencies do not include dependencies on unwind.h,\n# even though that is part of GCC, because where to find it depends on\n# whether we are being built as a host library or a target library.\n\nalloc.lo: config.h backtrace.h internal.h\nbacktrace.lo: config.h backtrace.h internal.h\nbtest.lo: filenames.h backtrace.h backtrace-supported.h\ndwarf.lo: config.h filenames.h backtrace.h internal.h\nelf.lo: config.h backtrace.h internal.h debuginfod_support.h\nfileline.lo: config.h backtrace.h internal.h\nmacho.lo: config.h backtrace.h internal.h\nmmap.lo: config.h backtrace.h internal.h\nmmapio.lo: config.h backtrace.h internal.h\nmtest.lo: backtrace.h backtrace-supported.h\nnounwind.lo: config.h internal.h\npecoff.lo: config.h backtrace.h internal.h\nposix.lo: config.h backtrace.h internal.h\nprint.lo: config.h backtrace.h internal.h\nread.lo: config.h backtrace.h internal.h\nsimple.lo: config.h backtrace.h internal.h\nsort.lo: config.h backtrace.h internal.h\nstest.lo: config.h backtrace.h internal.h\nstate.lo: config.h backtrace.h backtrace-supported.h internal.h\nunknown.lo: config.h backtrace.h internal.h\nxcoff.lo: config.h backtrace.h internal.h\nxztest.lo: config.h backtrace.h backtrace-supported.h internal.h testlib.h\nztest.lo: config.h backtrace.h backtrace-supported.h internal.h testlib.h\n\n"
  },
  {
    "path": "src/vendor/libbacktrace/Makefile.in",
    "content": "# Makefile.in generated by automake 1.15.1 from Makefile.am.\n# @configure_input@\n\n# Copyright (C) 1994-2017 Free Software Foundation, Inc.\n\n# This Makefile.in is free software; the Free Software Foundation\n# gives unlimited permission to copy and/or distribute it,\n# with or without modifications, as long as this notice is preserved.\n\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY, to the extent permitted by law; without\n# even the implied warranty of MERCHANTABILITY or FITNESS FOR A\n# PARTICULAR PURPOSE.\n\n@SET_MAKE@\n\n# Makefile.am -- Backtrace Makefile.\n# Copyright (C) 2012-2024 Free Software Foundation, Inc.\n\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions are\n# met:\n\n#     (1) Redistributions of source code must retain the above copyright\n#     notice, this list of conditions and the following disclaimer.\n\n#     (2) Redistributions in binary form must reproduce the above copyright\n#     notice, this list of conditions and the following disclaimer in\n#     the documentation and/or other materials provided with the\n#     distribution.\n\n#     (3) The name of the author may not be used to\n#     endorse or promote products derived from this software without\n#     specific prior written permission.\n\n# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n# DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,\n# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\n# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n# POSSIBILITY OF SUCH DAMAGE.\n\n\nVPATH = @srcdir@\nam__is_gnu_make = { \\\n  if test -z '$(MAKELEVEL)'; then \\\n    false; \\\n  elif test -n '$(MAKE_HOST)'; then \\\n    true; \\\n  elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \\\n    true; \\\n  else \\\n    false; \\\n  fi; \\\n}\nam__make_running_with_option = \\\n  case $${target_option-} in \\\n      ?) ;; \\\n      *) echo \"am__make_running_with_option: internal error: invalid\" \\\n              \"target option '$${target_option-}' specified\" >&2; \\\n         exit 1;; \\\n  esac; \\\n  has_opt=no; \\\n  sane_makeflags=$$MAKEFLAGS; \\\n  if $(am__is_gnu_make); then \\\n    sane_makeflags=$$MFLAGS; \\\n  else \\\n    case $$MAKEFLAGS in \\\n      *\\\\[\\ \\\t]*) \\\n        bs=\\\\; \\\n        sane_makeflags=`printf '%s\\n' \"$$MAKEFLAGS\" \\\n          | sed \"s/$$bs$$bs[$$bs $$bs\t]*//g\"`;; \\\n    esac; \\\n  fi; \\\n  skip_next=no; \\\n  strip_trailopt () \\\n  { \\\n    flg=`printf '%s\\n' \"$$flg\" | sed \"s/$$1.*$$//\"`; \\\n  }; \\\n  for flg in $$sane_makeflags; do \\\n    test $$skip_next = yes && { skip_next=no; continue; }; \\\n    case $$flg in \\\n      *=*|--*) continue;; \\\n        -*I) strip_trailopt 'I'; skip_next=yes;; \\\n      -*I?*) strip_trailopt 'I';; \\\n        -*O) strip_trailopt 'O'; skip_next=yes;; \\\n      -*O?*) strip_trailopt 'O';; \\\n        -*l) strip_trailopt 'l'; skip_next=yes;; \\\n      -*l?*) strip_trailopt 'l';; \\\n      -[dEDm]) skip_next=yes;; \\\n      -[JT]) skip_next=yes;; \\\n    esac; \\\n    case $$flg in \\\n      *$$target_option*) has_opt=yes; break;; \\\n    esac; \\\n  done; \\\n  test $$has_opt = yes\nam__make_dryrun = (target_option=n; $(am__make_running_with_option))\nam__make_keepgoing = (target_option=k; $(am__make_running_with_option))\npkgdatadir = $(datadir)/@PACKAGE@\npkgincludedir = $(includedir)/@PACKAGE@\npkglibdir = $(libdir)/@PACKAGE@\npkglibexecdir = $(libexecdir)/@PACKAGE@\nam__cd = CDPATH=\"$${ZSH_VERSION+.}$(PATH_SEPARATOR)\" && cd\ninstall_sh_DATA = $(install_sh) -c -m 644\ninstall_sh_PROGRAM = $(install_sh) -c\ninstall_sh_SCRIPT = $(install_sh) -c\nINSTALL_HEADER = $(INSTALL_DATA)\ntransform = $(program_transform_name)\nNORMAL_INSTALL = :\nPRE_INSTALL = :\nPOST_INSTALL = :\nNORMAL_UNINSTALL = :\nPRE_UNINSTALL = :\nPOST_UNINSTALL = :\nbuild_triplet = @build@\nhost_triplet = @host@\ntarget_triplet = @target@\ncheck_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \\\n\t$(am__EXEEXT_4) $(am__EXEEXT_17)\nTESTS = $(am__append_4) $(MAKETESTS) $(am__EXEEXT_17)\n@HAVE_ELF_TRUE@@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@am__append_1 = libbacktrace_elf_for_test.la\n@NATIVE_TRUE@am__append_2 = test_elf_32 test_elf_64 test_macho \\\n@NATIVE_TRUE@\ttest_xcoff_32 test_xcoff_64 test_pecoff \\\n@NATIVE_TRUE@\ttest_unknown unittest unittest_alloc btest\n@NATIVE_TRUE@am__append_3 = allocfail\n@NATIVE_TRUE@am__append_4 = allocfail.sh\n@NATIVE_TRUE@@USE_DSYMUTIL_TRUE@am__append_5 = allocfail.dSYM \\\n@NATIVE_TRUE@@USE_DSYMUTIL_TRUE@\tbtest.dSYM btest_alloc.dSYM \\\n@NATIVE_TRUE@@USE_DSYMUTIL_TRUE@\tstest.dSYM stest_alloc.dSYM \\\n@NATIVE_TRUE@@USE_DSYMUTIL_TRUE@\tedtest.dSYM edtest_alloc.dSYM\n@HAVE_BUILDID_TRUE@@HAVE_ELF_TRUE@@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@am__append_6 = b2test\n@HAVE_BUILDID_TRUE@@HAVE_ELF_TRUE@@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@am__append_7 = b2test_buildid b2test_buildidfull\n@HAVE_BUILDID_TRUE@@HAVE_DWZ_TRUE@@HAVE_ELF_TRUE@@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@am__append_8 = b3test\n@HAVE_BUILDID_TRUE@@HAVE_DWZ_TRUE@@HAVE_ELF_TRUE@@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@am__append_9 = b3test_dwz_buildid b3test_dwz_buildidfull\n@HAVE_ELF_TRUE@@NATIVE_TRUE@am__append_10 = btest_lto\n@NATIVE_TRUE@am__append_11 = btest_alloc stest stest_alloc\n@HAVE_DWZ_TRUE@@NATIVE_TRUE@am__append_12 = btest_dwz\n@HAVE_DWZ_TRUE@@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@am__append_13 = btest_dwz_gnudebuglink\n@HAVE_ELF_TRUE@@HAVE_ZLIB_TRUE@@NATIVE_TRUE@am__append_14 = -lz\n@HAVE_ELF_TRUE@@HAVE_ZLIB_TRUE@@NATIVE_TRUE@am__append_15 = -lz\n@HAVE_ELF_TRUE@@NATIVE_TRUE@am__append_16 = ztest ztest_alloc zstdtest \\\n@HAVE_ELF_TRUE@@NATIVE_TRUE@\tzstdtest_alloc\n@HAVE_ELF_TRUE@@HAVE_ZSTD_TRUE@@NATIVE_TRUE@am__append_17 = -lzstd\n@HAVE_ELF_TRUE@@HAVE_ZSTD_TRUE@@NATIVE_TRUE@am__append_18 = -lzstd\n@NATIVE_TRUE@am__append_19 = edtest edtest_alloc\n@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@am__append_20 = ttest ttest_alloc\n@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@@USE_DSYMUTIL_TRUE@am__append_21 =  \\\n@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@@USE_DSYMUTIL_TRUE@\tttest.dSYM \\\n@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@@USE_DSYMUTIL_TRUE@\tttest_alloc.dSYM\n@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@am__append_22 = btest_gnudebuglink btest_gnudebuglinkfull\n@HAVE_COMPRESSED_DEBUG_ZLIB_GNU_TRUE@@NATIVE_TRUE@am__append_23 = ctestg ctestg_alloc\n@HAVE_COMPRESSED_DEBUG_ZLIB_GABI_TRUE@@NATIVE_TRUE@am__append_24 = ctesta ctesta_alloc\n@HAVE_COMPRESSED_DEBUG_ZSTD_TRUE@@NATIVE_TRUE@am__append_25 = ctestzstd ctestzstd_alloc\n@HAVE_DWARF5_TRUE@@NATIVE_TRUE@am__append_26 = dwarf5 dwarf5_alloc\n@HAVE_DWARF5_TRUE@@NATIVE_TRUE@@USE_DSYMUTIL_TRUE@am__append_27 =  \\\n@HAVE_DWARF5_TRUE@@NATIVE_TRUE@@USE_DSYMUTIL_TRUE@\tdwarf5.dSYM \\\n@HAVE_DWARF5_TRUE@@NATIVE_TRUE@@USE_DSYMUTIL_TRUE@\tdwarf5_alloc.dSYM\n@NATIVE_TRUE@am__append_28 = mtest\n@NATIVE_TRUE@@USE_DSYMUTIL_TRUE@am__append_29 = mtest.dSYM\n@HAVE_MINIDEBUG_TRUE@@NATIVE_TRUE@am__append_30 = mtest_minidebug\n@HAVE_BUILDID_TRUE@@HAVE_ELF_TRUE@@HAVE_MINIDEBUG_TRUE@@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@am__append_31 = m2test\n@HAVE_BUILDID_TRUE@@HAVE_ELF_TRUE@@HAVE_MINIDEBUG_TRUE@@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@am__append_32 = m2test_minidebug2\n@HAVE_ELF_TRUE@@HAVE_LIBLZMA_TRUE@am__append_33 = -llzma\n@HAVE_ELF_TRUE@@HAVE_LIBLZMA_TRUE@am__append_34 = -llzma\n@HAVE_ELF_TRUE@am__append_35 = xztest xztest_alloc\nsubdir = .\nACLOCAL_M4 = $(top_srcdir)/aclocal.m4\nam__aclocal_m4_deps = $(top_srcdir)/config/lead-dot.m4 \\\n\t$(top_srcdir)/config/libtool.m4 \\\n\t$(top_srcdir)/config/ltoptions.m4 \\\n\t$(top_srcdir)/config/ltsugar.m4 \\\n\t$(top_srcdir)/config/ltversion.m4 \\\n\t$(top_srcdir)/config/lt~obsolete.m4 \\\n\t$(top_srcdir)/config/multi.m4 $(top_srcdir)/config/override.m4 \\\n\t$(top_srcdir)/config/unwind_ipinfo.m4 \\\n\t$(top_srcdir)/config/warnings.m4 $(top_srcdir)/configure.ac\nam__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \\\n\t$(ACLOCAL_M4)\nDIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \\\n\t$(am__configure_deps) $(include_HEADERS)\nam__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \\\n configure.lineno config.status.lineno\nmkinstalldirs = $(install_sh) -d\nCONFIG_HEADER = config.h\nCONFIG_CLEAN_FILES = backtrace-supported.h \\\n\tinstall-debuginfo-for-buildid.sh\nCONFIG_CLEAN_VPATH_FILES =\nam__vpath_adj_setup = srcdirstrip=`echo \"$(srcdir)\" | sed 's|.|.|g'`;\nam__vpath_adj = case $$p in \\\n    $(srcdir)/*) f=`echo \"$$p\" | sed \"s|^$$srcdirstrip/||\"`;; \\\n    *) f=$$p;; \\\n  esac;\nam__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;\nam__install_max = 40\nam__nobase_strip_setup = \\\n  srcdirstrip=`echo \"$(srcdir)\" | sed 's/[].[^$$\\\\*|]/\\\\\\\\&/g'`\nam__nobase_strip = \\\n  for p in $$list; do echo \"$$p\"; done | sed -e \"s|$$srcdirstrip/||\"\nam__nobase_list = $(am__nobase_strip_setup); \\\n  for p in $$list; do echo \"$$p $$p\"; done | \\\n  sed \"s| $$srcdirstrip/| |;\"' / .*\\//!s/ .*/ ./; s,\\( .*\\)/[^/]*$$,\\1,' | \\\n  $(AWK) 'BEGIN { files[\".\"] = \"\" } { files[$$2] = files[$$2] \" \" $$1; \\\n    if (++n[$$2] == $(am__install_max)) \\\n      { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = \"\" } } \\\n    END { for (dir in files) print dir, files[dir] }'\nam__base_list = \\\n  sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\\n/ /g' | \\\n  sed '$$!N;$$!N;$$!N;$$!N;s/\\n/ /g'\nam__uninstall_files_from_dir = { \\\n  test -z \"$$files\" \\\n    || { test ! -d \"$$dir\" && test ! -f \"$$dir\" && test ! -r \"$$dir\"; } \\\n    || { echo \" ( cd '$$dir' && rm -f\" $$files \")\"; \\\n         $(am__cd) \"$$dir\" && rm -f $$files; }; \\\n  }\nam__installdirs = \"$(DESTDIR)$(libdir)\" \"$(DESTDIR)$(includedir)\"\nLTLIBRARIES = $(lib_LTLIBRARIES)\nam__DEPENDENCIES_1 =\nam_libbacktrace_la_OBJECTS = atomic.lo dwarf.lo fileline.lo posix.lo \\\n\tprint.lo sort.lo state.lo\nlibbacktrace_la_OBJECTS = $(am_libbacktrace_la_OBJECTS)\nAM_V_lt = $(am__v_lt_@AM_V@)\nam__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)\nam__v_lt_0 = --silent\nam__v_lt_1 = \nam__objects_1 = atomic.lo dwarf.lo fileline.lo posix.lo print.lo \\\n\tsort.lo state.lo\n@NATIVE_TRUE@am_libbacktrace_alloc_la_OBJECTS = $(am__objects_1)\nlibbacktrace_alloc_la_OBJECTS = $(am_libbacktrace_alloc_la_OBJECTS)\n@NATIVE_TRUE@am_libbacktrace_alloc_la_rpath =\n@HAVE_ELF_TRUE@@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@libbacktrace_elf_for_test_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \\\n@HAVE_ELF_TRUE@@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@\telf_for_test.lo \\\n@HAVE_ELF_TRUE@@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@\t$(am__DEPENDENCIES_1) \\\n@HAVE_ELF_TRUE@@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@\t$(am__DEPENDENCIES_1)\n@HAVE_ELF_TRUE@@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@am_libbacktrace_elf_for_test_la_OBJECTS = $(am__objects_1)\nlibbacktrace_elf_for_test_la_OBJECTS =  \\\n\t$(am_libbacktrace_elf_for_test_la_OBJECTS)\n@HAVE_ELF_TRUE@@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@am_libbacktrace_elf_for_test_la_rpath =\n@NATIVE_TRUE@am_libbacktrace_instrumented_alloc_la_OBJECTS =  \\\n@NATIVE_TRUE@\t$(am__objects_1)\nlibbacktrace_instrumented_alloc_la_OBJECTS =  \\\n\t$(am_libbacktrace_instrumented_alloc_la_OBJECTS)\n@NATIVE_TRUE@am_libbacktrace_instrumented_alloc_la_rpath =\n@NATIVE_TRUE@am_libbacktrace_noformat_la_OBJECTS = $(am__objects_1)\nlibbacktrace_noformat_la_OBJECTS =  \\\n\t$(am_libbacktrace_noformat_la_OBJECTS)\n@NATIVE_TRUE@am_libbacktrace_noformat_la_rpath =\n@NATIVE_TRUE@am__EXEEXT_1 = allocfail$(EXEEXT)\n@HAVE_BUILDID_TRUE@@HAVE_ELF_TRUE@@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@am__EXEEXT_2 = b2test$(EXEEXT)\n@HAVE_BUILDID_TRUE@@HAVE_DWZ_TRUE@@HAVE_ELF_TRUE@@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@am__EXEEXT_3 = b3test$(EXEEXT)\n@HAVE_BUILDID_TRUE@@HAVE_ELF_TRUE@@HAVE_MINIDEBUG_TRUE@@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@am__EXEEXT_4 = m2test$(EXEEXT)\n@NATIVE_TRUE@am__EXEEXT_5 = test_elf_32$(EXEEXT) test_elf_64$(EXEEXT) \\\n@NATIVE_TRUE@\ttest_macho$(EXEEXT) test_xcoff_32$(EXEEXT) \\\n@NATIVE_TRUE@\ttest_xcoff_64$(EXEEXT) test_pecoff$(EXEEXT) \\\n@NATIVE_TRUE@\ttest_unknown$(EXEEXT) unittest$(EXEEXT) \\\n@NATIVE_TRUE@\tunittest_alloc$(EXEEXT) btest$(EXEEXT)\n@HAVE_ELF_TRUE@@NATIVE_TRUE@am__EXEEXT_6 = btest_lto$(EXEEXT)\n@NATIVE_TRUE@am__EXEEXT_7 = btest_alloc$(EXEEXT) stest$(EXEEXT) \\\n@NATIVE_TRUE@\tstest_alloc$(EXEEXT)\n@HAVE_ELF_TRUE@@NATIVE_TRUE@am__EXEEXT_8 = ztest$(EXEEXT) \\\n@HAVE_ELF_TRUE@@NATIVE_TRUE@\tztest_alloc$(EXEEXT) \\\n@HAVE_ELF_TRUE@@NATIVE_TRUE@\tzstdtest$(EXEEXT) \\\n@HAVE_ELF_TRUE@@NATIVE_TRUE@\tzstdtest_alloc$(EXEEXT)\n@NATIVE_TRUE@am__EXEEXT_9 = edtest$(EXEEXT) edtest_alloc$(EXEEXT)\n@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@am__EXEEXT_10 = ttest$(EXEEXT) \\\n@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@\tttest_alloc$(EXEEXT)\n@HAVE_COMPRESSED_DEBUG_ZLIB_GNU_TRUE@@NATIVE_TRUE@am__EXEEXT_11 = ctestg$(EXEEXT) \\\n@HAVE_COMPRESSED_DEBUG_ZLIB_GNU_TRUE@@NATIVE_TRUE@\tctestg_alloc$(EXEEXT)\n@HAVE_COMPRESSED_DEBUG_ZLIB_GABI_TRUE@@NATIVE_TRUE@am__EXEEXT_12 = ctesta$(EXEEXT) \\\n@HAVE_COMPRESSED_DEBUG_ZLIB_GABI_TRUE@@NATIVE_TRUE@\tctesta_alloc$(EXEEXT)\n@HAVE_COMPRESSED_DEBUG_ZSTD_TRUE@@NATIVE_TRUE@am__EXEEXT_13 = ctestzstd$(EXEEXT) \\\n@HAVE_COMPRESSED_DEBUG_ZSTD_TRUE@@NATIVE_TRUE@\tctestzstd_alloc$(EXEEXT)\n@HAVE_DWARF5_TRUE@@NATIVE_TRUE@am__EXEEXT_14 = dwarf5$(EXEEXT) \\\n@HAVE_DWARF5_TRUE@@NATIVE_TRUE@\tdwarf5_alloc$(EXEEXT)\n@NATIVE_TRUE@am__EXEEXT_15 = mtest$(EXEEXT)\n@HAVE_ELF_TRUE@am__EXEEXT_16 = xztest$(EXEEXT) xztest_alloc$(EXEEXT)\nam__EXEEXT_17 = $(am__EXEEXT_5) $(am__EXEEXT_6) $(am__EXEEXT_7) \\\n\t$(am__EXEEXT_8) $(am__EXEEXT_9) $(am__EXEEXT_10) \\\n\t$(am__EXEEXT_11) $(am__EXEEXT_12) $(am__EXEEXT_13) \\\n\t$(am__EXEEXT_14) $(am__EXEEXT_15) $(am__EXEEXT_16)\n@NATIVE_TRUE@am_allocfail_OBJECTS = allocfail-allocfail.$(OBJEXT) \\\n@NATIVE_TRUE@\tallocfail-testlib.$(OBJEXT)\nallocfail_OBJECTS = $(am_allocfail_OBJECTS)\n@NATIVE_TRUE@allocfail_DEPENDENCIES =  \\\n@NATIVE_TRUE@\tlibbacktrace_instrumented_alloc.la\nallocfail_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \\\n\t$(LIBTOOLFLAGS) --mode=link $(CCLD) $(allocfail_CFLAGS) \\\n\t$(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@\n@NATIVE_TRUE@am__objects_2 = b2test-btest.$(OBJEXT) \\\n@NATIVE_TRUE@\tb2test-testlib.$(OBJEXT)\n@HAVE_BUILDID_TRUE@@HAVE_ELF_TRUE@@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@am_b2test_OBJECTS = $(am__objects_2)\nb2test_OBJECTS = $(am_b2test_OBJECTS)\n@HAVE_BUILDID_TRUE@@HAVE_ELF_TRUE@@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@b2test_DEPENDENCIES = libbacktrace_elf_for_test.la\nb2test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \\\n\t$(LIBTOOLFLAGS) --mode=link $(CCLD) $(b2test_CFLAGS) $(CFLAGS) \\\n\t$(b2test_LDFLAGS) $(LDFLAGS) -o $@\n@NATIVE_TRUE@am__objects_3 = b3test-btest.$(OBJEXT) \\\n@NATIVE_TRUE@\tb3test-testlib.$(OBJEXT)\n@HAVE_BUILDID_TRUE@@HAVE_DWZ_TRUE@@HAVE_ELF_TRUE@@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@am_b3test_OBJECTS = $(am__objects_3)\nb3test_OBJECTS = $(am_b3test_OBJECTS)\n@HAVE_BUILDID_TRUE@@HAVE_DWZ_TRUE@@HAVE_ELF_TRUE@@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@b3test_DEPENDENCIES = libbacktrace_elf_for_test.la\nb3test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \\\n\t$(LIBTOOLFLAGS) --mode=link $(CCLD) $(b3test_CFLAGS) $(CFLAGS) \\\n\t$(b3test_LDFLAGS) $(LDFLAGS) -o $@\n@NATIVE_TRUE@am_btest_OBJECTS = btest-btest.$(OBJEXT) \\\n@NATIVE_TRUE@\tbtest-testlib.$(OBJEXT)\nbtest_OBJECTS = $(am_btest_OBJECTS)\n@NATIVE_TRUE@btest_DEPENDENCIES = libbacktrace.la\nbtest_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \\\n\t$(LIBTOOLFLAGS) --mode=link $(CCLD) $(btest_CFLAGS) $(CFLAGS) \\\n\t$(btest_LDFLAGS) $(LDFLAGS) -o $@\n@NATIVE_TRUE@am__objects_4 = btest_alloc-btest.$(OBJEXT) \\\n@NATIVE_TRUE@\tbtest_alloc-testlib.$(OBJEXT)\n@NATIVE_TRUE@am_btest_alloc_OBJECTS = $(am__objects_4)\nbtest_alloc_OBJECTS = $(am_btest_alloc_OBJECTS)\n@NATIVE_TRUE@btest_alloc_DEPENDENCIES = libbacktrace_alloc.la\nbtest_alloc_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \\\n\t$(LIBTOOLFLAGS) --mode=link $(CCLD) $(btest_alloc_CFLAGS) \\\n\t$(CFLAGS) $(btest_alloc_LDFLAGS) $(LDFLAGS) -o $@\n@HAVE_ELF_TRUE@@NATIVE_TRUE@am_btest_lto_OBJECTS =  \\\n@HAVE_ELF_TRUE@@NATIVE_TRUE@\tbtest_lto-btest.$(OBJEXT) \\\n@HAVE_ELF_TRUE@@NATIVE_TRUE@\tbtest_lto-testlib.$(OBJEXT)\nbtest_lto_OBJECTS = $(am_btest_lto_OBJECTS)\n@HAVE_ELF_TRUE@@NATIVE_TRUE@btest_lto_DEPENDENCIES = libbacktrace.la\nbtest_lto_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \\\n\t$(LIBTOOLFLAGS) --mode=link $(CCLD) $(btest_lto_CFLAGS) \\\n\t$(CFLAGS) $(btest_lto_LDFLAGS) $(LDFLAGS) -o $@\n@HAVE_COMPRESSED_DEBUG_ZLIB_GABI_TRUE@@NATIVE_TRUE@am_ctesta_OBJECTS = ctesta-btest.$(OBJEXT) \\\n@HAVE_COMPRESSED_DEBUG_ZLIB_GABI_TRUE@@NATIVE_TRUE@\tctesta-testlib.$(OBJEXT)\nctesta_OBJECTS = $(am_ctesta_OBJECTS)\n@HAVE_COMPRESSED_DEBUG_ZLIB_GABI_TRUE@@NATIVE_TRUE@ctesta_DEPENDENCIES = libbacktrace.la\nctesta_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \\\n\t$(LIBTOOLFLAGS) --mode=link $(CCLD) $(ctesta_CFLAGS) $(CFLAGS) \\\n\t$(ctesta_LDFLAGS) $(LDFLAGS) -o $@\n@HAVE_COMPRESSED_DEBUG_ZLIB_GABI_TRUE@@NATIVE_TRUE@am__objects_5 = ctesta_alloc-btest.$(OBJEXT) \\\n@HAVE_COMPRESSED_DEBUG_ZLIB_GABI_TRUE@@NATIVE_TRUE@\tctesta_alloc-testlib.$(OBJEXT)\n@HAVE_COMPRESSED_DEBUG_ZLIB_GABI_TRUE@@NATIVE_TRUE@am_ctesta_alloc_OBJECTS = $(am__objects_5)\nctesta_alloc_OBJECTS = $(am_ctesta_alloc_OBJECTS)\n@HAVE_COMPRESSED_DEBUG_ZLIB_GABI_TRUE@@NATIVE_TRUE@ctesta_alloc_DEPENDENCIES = libbacktrace_alloc.la\nctesta_alloc_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \\\n\t$(LIBTOOLFLAGS) --mode=link $(CCLD) $(ctesta_alloc_CFLAGS) \\\n\t$(CFLAGS) $(ctesta_alloc_LDFLAGS) $(LDFLAGS) -o $@\n@HAVE_COMPRESSED_DEBUG_ZLIB_GNU_TRUE@@NATIVE_TRUE@am_ctestg_OBJECTS = ctestg-btest.$(OBJEXT) \\\n@HAVE_COMPRESSED_DEBUG_ZLIB_GNU_TRUE@@NATIVE_TRUE@\tctestg-testlib.$(OBJEXT)\nctestg_OBJECTS = $(am_ctestg_OBJECTS)\n@HAVE_COMPRESSED_DEBUG_ZLIB_GNU_TRUE@@NATIVE_TRUE@ctestg_DEPENDENCIES = libbacktrace.la\nctestg_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \\\n\t$(LIBTOOLFLAGS) --mode=link $(CCLD) $(ctestg_CFLAGS) $(CFLAGS) \\\n\t$(ctestg_LDFLAGS) $(LDFLAGS) -o $@\n@HAVE_COMPRESSED_DEBUG_ZLIB_GNU_TRUE@@NATIVE_TRUE@am__objects_6 = ctestg_alloc-btest.$(OBJEXT) \\\n@HAVE_COMPRESSED_DEBUG_ZLIB_GNU_TRUE@@NATIVE_TRUE@\tctestg_alloc-testlib.$(OBJEXT)\n@HAVE_COMPRESSED_DEBUG_ZLIB_GNU_TRUE@@NATIVE_TRUE@am_ctestg_alloc_OBJECTS = $(am__objects_6)\nctestg_alloc_OBJECTS = $(am_ctestg_alloc_OBJECTS)\n@HAVE_COMPRESSED_DEBUG_ZLIB_GNU_TRUE@@NATIVE_TRUE@ctestg_alloc_DEPENDENCIES = libbacktrace_alloc.la\nctestg_alloc_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \\\n\t$(LIBTOOLFLAGS) --mode=link $(CCLD) $(ctestg_alloc_CFLAGS) \\\n\t$(CFLAGS) $(ctestg_alloc_LDFLAGS) $(LDFLAGS) -o $@\n@HAVE_COMPRESSED_DEBUG_ZSTD_TRUE@@NATIVE_TRUE@am_ctestzstd_OBJECTS = ctestzstd-btest.$(OBJEXT) \\\n@HAVE_COMPRESSED_DEBUG_ZSTD_TRUE@@NATIVE_TRUE@\tctestzstd-testlib.$(OBJEXT)\nctestzstd_OBJECTS = $(am_ctestzstd_OBJECTS)\n@HAVE_COMPRESSED_DEBUG_ZSTD_TRUE@@NATIVE_TRUE@ctestzstd_DEPENDENCIES =  \\\n@HAVE_COMPRESSED_DEBUG_ZSTD_TRUE@@NATIVE_TRUE@\tlibbacktrace.la\nctestzstd_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \\\n\t$(LIBTOOLFLAGS) --mode=link $(CCLD) $(ctestzstd_CFLAGS) \\\n\t$(CFLAGS) $(ctestzstd_LDFLAGS) $(LDFLAGS) -o $@\n@HAVE_COMPRESSED_DEBUG_ZSTD_TRUE@@NATIVE_TRUE@am__objects_7 = ctestzstd_alloc-btest.$(OBJEXT) \\\n@HAVE_COMPRESSED_DEBUG_ZSTD_TRUE@@NATIVE_TRUE@\tctestzstd_alloc-testlib.$(OBJEXT)\n@HAVE_COMPRESSED_DEBUG_ZSTD_TRUE@@NATIVE_TRUE@am_ctestzstd_alloc_OBJECTS = $(am__objects_7)\nctestzstd_alloc_OBJECTS = $(am_ctestzstd_alloc_OBJECTS)\n@HAVE_COMPRESSED_DEBUG_ZSTD_TRUE@@NATIVE_TRUE@ctestzstd_alloc_DEPENDENCIES = libbacktrace_alloc.la\nctestzstd_alloc_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \\\n\t$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \\\n\t$(ctestzstd_alloc_CFLAGS) $(CFLAGS) $(ctestzstd_alloc_LDFLAGS) \\\n\t$(LDFLAGS) -o $@\n@HAVE_DWARF5_TRUE@@NATIVE_TRUE@am_dwarf5_OBJECTS =  \\\n@HAVE_DWARF5_TRUE@@NATIVE_TRUE@\tdwarf5-btest.$(OBJEXT) \\\n@HAVE_DWARF5_TRUE@@NATIVE_TRUE@\tdwarf5-testlib.$(OBJEXT)\ndwarf5_OBJECTS = $(am_dwarf5_OBJECTS)\n@HAVE_DWARF5_TRUE@@NATIVE_TRUE@dwarf5_DEPENDENCIES = libbacktrace.la\ndwarf5_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \\\n\t$(LIBTOOLFLAGS) --mode=link $(CCLD) $(dwarf5_CFLAGS) $(CFLAGS) \\\n\t$(dwarf5_LDFLAGS) $(LDFLAGS) -o $@\n@HAVE_DWARF5_TRUE@@NATIVE_TRUE@am__objects_8 =  \\\n@HAVE_DWARF5_TRUE@@NATIVE_TRUE@\tdwarf5_alloc-btest.$(OBJEXT) \\\n@HAVE_DWARF5_TRUE@@NATIVE_TRUE@\tdwarf5_alloc-testlib.$(OBJEXT)\n@HAVE_DWARF5_TRUE@@NATIVE_TRUE@am_dwarf5_alloc_OBJECTS =  \\\n@HAVE_DWARF5_TRUE@@NATIVE_TRUE@\t$(am__objects_8)\ndwarf5_alloc_OBJECTS = $(am_dwarf5_alloc_OBJECTS)\n@HAVE_DWARF5_TRUE@@NATIVE_TRUE@dwarf5_alloc_DEPENDENCIES =  \\\n@HAVE_DWARF5_TRUE@@NATIVE_TRUE@\tlibbacktrace_alloc.la\ndwarf5_alloc_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \\\n\t$(LIBTOOLFLAGS) --mode=link $(CCLD) $(dwarf5_alloc_CFLAGS) \\\n\t$(CFLAGS) $(dwarf5_alloc_LDFLAGS) $(LDFLAGS) -o $@\n@NATIVE_TRUE@am_edtest_OBJECTS = edtest-edtest.$(OBJEXT) \\\n@NATIVE_TRUE@\tedtest-edtest2_build.$(OBJEXT) \\\n@NATIVE_TRUE@\tedtest-testlib.$(OBJEXT)\nedtest_OBJECTS = $(am_edtest_OBJECTS)\n@NATIVE_TRUE@edtest_DEPENDENCIES = libbacktrace.la\nedtest_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \\\n\t$(LIBTOOLFLAGS) --mode=link $(CCLD) $(edtest_CFLAGS) $(CFLAGS) \\\n\t$(edtest_LDFLAGS) $(LDFLAGS) -o $@\n@NATIVE_TRUE@am__objects_9 = edtest_alloc-edtest.$(OBJEXT) \\\n@NATIVE_TRUE@\tedtest_alloc-edtest2_build.$(OBJEXT) \\\n@NATIVE_TRUE@\tedtest_alloc-testlib.$(OBJEXT)\n@NATIVE_TRUE@am_edtest_alloc_OBJECTS = $(am__objects_9)\nedtest_alloc_OBJECTS = $(am_edtest_alloc_OBJECTS)\n@NATIVE_TRUE@edtest_alloc_DEPENDENCIES = libbacktrace_alloc.la\nedtest_alloc_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \\\n\t$(LIBTOOLFLAGS) --mode=link $(CCLD) $(edtest_alloc_CFLAGS) \\\n\t$(CFLAGS) $(edtest_alloc_LDFLAGS) $(LDFLAGS) -o $@\n@NATIVE_TRUE@am__objects_10 = m2test-mtest.$(OBJEXT) \\\n@NATIVE_TRUE@\tm2test-testlib.$(OBJEXT)\n@HAVE_BUILDID_TRUE@@HAVE_ELF_TRUE@@HAVE_MINIDEBUG_TRUE@@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@am_m2test_OBJECTS = $(am__objects_10)\nm2test_OBJECTS = $(am_m2test_OBJECTS)\n@HAVE_BUILDID_TRUE@@HAVE_ELF_TRUE@@HAVE_MINIDEBUG_TRUE@@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@m2test_DEPENDENCIES = libbacktrace_elf_for_test.la\nm2test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \\\n\t$(LIBTOOLFLAGS) --mode=link $(CCLD) $(m2test_CFLAGS) $(CFLAGS) \\\n\t$(m2test_LDFLAGS) $(LDFLAGS) -o $@\n@NATIVE_TRUE@am_mtest_OBJECTS = mtest-mtest.$(OBJEXT) \\\n@NATIVE_TRUE@\tmtest-testlib.$(OBJEXT)\nmtest_OBJECTS = $(am_mtest_OBJECTS)\n@NATIVE_TRUE@mtest_DEPENDENCIES = libbacktrace.la\nmtest_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \\\n\t$(LIBTOOLFLAGS) --mode=link $(CCLD) $(mtest_CFLAGS) $(CFLAGS) \\\n\t$(mtest_LDFLAGS) $(LDFLAGS) -o $@\n@NATIVE_TRUE@am_stest_OBJECTS = stest-stest.$(OBJEXT)\nstest_OBJECTS = $(am_stest_OBJECTS)\n@NATIVE_TRUE@stest_DEPENDENCIES = libbacktrace.la\nstest_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \\\n\t$(LIBTOOLFLAGS) --mode=link $(CCLD) $(stest_CFLAGS) $(CFLAGS) \\\n\t$(stest_LDFLAGS) $(LDFLAGS) -o $@\n@NATIVE_TRUE@am__objects_11 = stest_alloc-stest.$(OBJEXT)\n@NATIVE_TRUE@am_stest_alloc_OBJECTS = $(am__objects_11)\nstest_alloc_OBJECTS = $(am_stest_alloc_OBJECTS)\n@NATIVE_TRUE@stest_alloc_DEPENDENCIES = libbacktrace_alloc.la\nstest_alloc_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \\\n\t$(LIBTOOLFLAGS) --mode=link $(CCLD) $(stest_alloc_CFLAGS) \\\n\t$(CFLAGS) $(stest_alloc_LDFLAGS) $(LDFLAGS) -o $@\n@NATIVE_TRUE@am_test_elf_32_OBJECTS =  \\\n@NATIVE_TRUE@\ttest_elf_32-test_format.$(OBJEXT) \\\n@NATIVE_TRUE@\ttest_elf_32-testlib.$(OBJEXT)\ntest_elf_32_OBJECTS = $(am_test_elf_32_OBJECTS)\n@NATIVE_TRUE@test_elf_32_DEPENDENCIES = libbacktrace_noformat.la \\\n@NATIVE_TRUE@\telf_32.lo\ntest_elf_32_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \\\n\t$(LIBTOOLFLAGS) --mode=link $(CCLD) $(test_elf_32_CFLAGS) \\\n\t$(CFLAGS) $(test_elf_32_LDFLAGS) $(LDFLAGS) -o $@\n@NATIVE_TRUE@am_test_elf_64_OBJECTS =  \\\n@NATIVE_TRUE@\ttest_elf_64-test_format.$(OBJEXT) \\\n@NATIVE_TRUE@\ttest_elf_64-testlib.$(OBJEXT)\ntest_elf_64_OBJECTS = $(am_test_elf_64_OBJECTS)\n@NATIVE_TRUE@test_elf_64_DEPENDENCIES = libbacktrace_noformat.la \\\n@NATIVE_TRUE@\telf_64.lo\ntest_elf_64_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \\\n\t$(LIBTOOLFLAGS) --mode=link $(CCLD) $(test_elf_64_CFLAGS) \\\n\t$(CFLAGS) $(test_elf_64_LDFLAGS) $(LDFLAGS) -o $@\n@NATIVE_TRUE@am_test_macho_OBJECTS = test_macho-test_format.$(OBJEXT) \\\n@NATIVE_TRUE@\ttest_macho-testlib.$(OBJEXT)\ntest_macho_OBJECTS = $(am_test_macho_OBJECTS)\n@NATIVE_TRUE@test_macho_DEPENDENCIES = libbacktrace_noformat.la \\\n@NATIVE_TRUE@\tmacho.lo\ntest_macho_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \\\n\t$(LIBTOOLFLAGS) --mode=link $(CCLD) $(test_macho_CFLAGS) \\\n\t$(CFLAGS) $(test_macho_LDFLAGS) $(LDFLAGS) -o $@\n@NATIVE_TRUE@am_test_pecoff_OBJECTS =  \\\n@NATIVE_TRUE@\ttest_pecoff-test_format.$(OBJEXT) \\\n@NATIVE_TRUE@\ttest_pecoff-testlib.$(OBJEXT)\ntest_pecoff_OBJECTS = $(am_test_pecoff_OBJECTS)\n@NATIVE_TRUE@test_pecoff_DEPENDENCIES = libbacktrace_noformat.la \\\n@NATIVE_TRUE@\tpecoff.lo\ntest_pecoff_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \\\n\t$(LIBTOOLFLAGS) --mode=link $(CCLD) $(test_pecoff_CFLAGS) \\\n\t$(CFLAGS) $(test_pecoff_LDFLAGS) $(LDFLAGS) -o $@\n@NATIVE_TRUE@am_test_unknown_OBJECTS =  \\\n@NATIVE_TRUE@\ttest_unknown-test_format.$(OBJEXT) \\\n@NATIVE_TRUE@\ttest_unknown-testlib.$(OBJEXT)\ntest_unknown_OBJECTS = $(am_test_unknown_OBJECTS)\n@NATIVE_TRUE@test_unknown_DEPENDENCIES = libbacktrace_noformat.la \\\n@NATIVE_TRUE@\tunknown.lo\ntest_unknown_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \\\n\t$(LIBTOOLFLAGS) --mode=link $(CCLD) $(test_unknown_CFLAGS) \\\n\t$(CFLAGS) $(test_unknown_LDFLAGS) $(LDFLAGS) -o $@\n@NATIVE_TRUE@am_test_xcoff_32_OBJECTS =  \\\n@NATIVE_TRUE@\ttest_xcoff_32-test_format.$(OBJEXT) \\\n@NATIVE_TRUE@\ttest_xcoff_32-testlib.$(OBJEXT)\ntest_xcoff_32_OBJECTS = $(am_test_xcoff_32_OBJECTS)\n@NATIVE_TRUE@test_xcoff_32_DEPENDENCIES = libbacktrace_noformat.la \\\n@NATIVE_TRUE@\txcoff_32.lo\ntest_xcoff_32_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \\\n\t$(LIBTOOLFLAGS) --mode=link $(CCLD) $(test_xcoff_32_CFLAGS) \\\n\t$(CFLAGS) $(test_xcoff_32_LDFLAGS) $(LDFLAGS) -o $@\n@NATIVE_TRUE@am_test_xcoff_64_OBJECTS =  \\\n@NATIVE_TRUE@\ttest_xcoff_64-test_format.$(OBJEXT) \\\n@NATIVE_TRUE@\ttest_xcoff_64-testlib.$(OBJEXT)\ntest_xcoff_64_OBJECTS = $(am_test_xcoff_64_OBJECTS)\n@NATIVE_TRUE@test_xcoff_64_DEPENDENCIES = libbacktrace_noformat.la \\\n@NATIVE_TRUE@\txcoff_64.lo\ntest_xcoff_64_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \\\n\t$(LIBTOOLFLAGS) --mode=link $(CCLD) $(test_xcoff_64_CFLAGS) \\\n\t$(CFLAGS) $(test_xcoff_64_LDFLAGS) $(LDFLAGS) -o $@\n@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@am_ttest_OBJECTS =  \\\n@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@\tttest-ttest.$(OBJEXT) \\\n@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@\tttest-testlib.$(OBJEXT)\nttest_OBJECTS = $(am_ttest_OBJECTS)\n@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@ttest_DEPENDENCIES = libbacktrace.la\nttest_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \\\n\t$(LIBTOOLFLAGS) --mode=link $(CCLD) $(ttest_CFLAGS) $(CFLAGS) \\\n\t$(ttest_LDFLAGS) $(LDFLAGS) -o $@\n@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@am__objects_12 =  \\\n@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@\tttest_alloc-ttest.$(OBJEXT) \\\n@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@\tttest_alloc-testlib.$(OBJEXT)\n@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@am_ttest_alloc_OBJECTS =  \\\n@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@\t$(am__objects_12)\nttest_alloc_OBJECTS = $(am_ttest_alloc_OBJECTS)\n@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@ttest_alloc_DEPENDENCIES =  \\\n@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@\tlibbacktrace_alloc.la\nttest_alloc_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \\\n\t$(LIBTOOLFLAGS) --mode=link $(CCLD) $(ttest_alloc_CFLAGS) \\\n\t$(CFLAGS) $(ttest_alloc_LDFLAGS) $(LDFLAGS) -o $@\n@NATIVE_TRUE@am_unittest_OBJECTS = unittest-unittest.$(OBJEXT) \\\n@NATIVE_TRUE@\tunittest-testlib.$(OBJEXT)\nunittest_OBJECTS = $(am_unittest_OBJECTS)\n@NATIVE_TRUE@unittest_DEPENDENCIES = libbacktrace.la\nunittest_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \\\n\t$(LIBTOOLFLAGS) --mode=link $(CCLD) $(unittest_CFLAGS) \\\n\t$(CFLAGS) $(unittest_LDFLAGS) $(LDFLAGS) -o $@\n@NATIVE_TRUE@am__objects_13 = unittest_alloc-unittest.$(OBJEXT) \\\n@NATIVE_TRUE@\tunittest_alloc-testlib.$(OBJEXT)\n@NATIVE_TRUE@am_unittest_alloc_OBJECTS = $(am__objects_13)\nunittest_alloc_OBJECTS = $(am_unittest_alloc_OBJECTS)\n@NATIVE_TRUE@unittest_alloc_DEPENDENCIES = libbacktrace_alloc.la\nunittest_alloc_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \\\n\t$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \\\n\t$(unittest_alloc_CFLAGS) $(CFLAGS) $(unittest_alloc_LDFLAGS) \\\n\t$(LDFLAGS) -o $@\n@HAVE_ELF_TRUE@am_xztest_OBJECTS = xztest-xztest.$(OBJEXT) \\\n@HAVE_ELF_TRUE@\txztest-testlib.$(OBJEXT)\nxztest_OBJECTS = $(am_xztest_OBJECTS)\n@HAVE_ELF_TRUE@xztest_DEPENDENCIES = libbacktrace.la \\\n@HAVE_ELF_TRUE@\t$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)\nxztest_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \\\n\t$(LIBTOOLFLAGS) --mode=link $(CCLD) $(xztest_CFLAGS) $(CFLAGS) \\\n\t$(xztest_LDFLAGS) $(LDFLAGS) -o $@\n@HAVE_ELF_TRUE@am__objects_14 = xztest_alloc-xztest.$(OBJEXT) \\\n@HAVE_ELF_TRUE@\txztest_alloc-testlib.$(OBJEXT)\n@HAVE_ELF_TRUE@am_xztest_alloc_OBJECTS = $(am__objects_14)\nxztest_alloc_OBJECTS = $(am_xztest_alloc_OBJECTS)\n@HAVE_ELF_TRUE@xztest_alloc_DEPENDENCIES = libbacktrace_alloc.la \\\n@HAVE_ELF_TRUE@\t$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)\nxztest_alloc_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \\\n\t$(LIBTOOLFLAGS) --mode=link $(CCLD) $(xztest_alloc_CFLAGS) \\\n\t$(CFLAGS) $(xztest_alloc_LDFLAGS) $(LDFLAGS) -o $@\n@HAVE_ELF_TRUE@@NATIVE_TRUE@am_zstdtest_OBJECTS =  \\\n@HAVE_ELF_TRUE@@NATIVE_TRUE@\tzstdtest-zstdtest.$(OBJEXT) \\\n@HAVE_ELF_TRUE@@NATIVE_TRUE@\tzstdtest-testlib.$(OBJEXT)\nzstdtest_OBJECTS = $(am_zstdtest_OBJECTS)\n@HAVE_ELF_TRUE@@NATIVE_TRUE@zstdtest_DEPENDENCIES = libbacktrace.la \\\n@HAVE_ELF_TRUE@@NATIVE_TRUE@\t$(am__DEPENDENCIES_1) \\\n@HAVE_ELF_TRUE@@NATIVE_TRUE@\t$(am__DEPENDENCIES_1)\nzstdtest_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \\\n\t$(LIBTOOLFLAGS) --mode=link $(CCLD) $(zstdtest_CFLAGS) \\\n\t$(CFLAGS) $(zstdtest_LDFLAGS) $(LDFLAGS) -o $@\n@HAVE_ELF_TRUE@@NATIVE_TRUE@am__objects_15 =  \\\n@HAVE_ELF_TRUE@@NATIVE_TRUE@\tzstdtest_alloc-zstdtest.$(OBJEXT) \\\n@HAVE_ELF_TRUE@@NATIVE_TRUE@\tzstdtest_alloc-testlib.$(OBJEXT)\n@HAVE_ELF_TRUE@@NATIVE_TRUE@am_zstdtest_alloc_OBJECTS =  \\\n@HAVE_ELF_TRUE@@NATIVE_TRUE@\t$(am__objects_15)\nzstdtest_alloc_OBJECTS = $(am_zstdtest_alloc_OBJECTS)\n@HAVE_ELF_TRUE@@NATIVE_TRUE@zstdtest_alloc_DEPENDENCIES =  \\\n@HAVE_ELF_TRUE@@NATIVE_TRUE@\tlibbacktrace_alloc.la \\\n@HAVE_ELF_TRUE@@NATIVE_TRUE@\t$(am__DEPENDENCIES_1) \\\n@HAVE_ELF_TRUE@@NATIVE_TRUE@\t$(am__DEPENDENCIES_1)\nzstdtest_alloc_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \\\n\t$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \\\n\t$(zstdtest_alloc_CFLAGS) $(CFLAGS) $(zstdtest_alloc_LDFLAGS) \\\n\t$(LDFLAGS) -o $@\n@HAVE_ELF_TRUE@@NATIVE_TRUE@am_ztest_OBJECTS = ztest-ztest.$(OBJEXT) \\\n@HAVE_ELF_TRUE@@NATIVE_TRUE@\tztest-testlib.$(OBJEXT)\nztest_OBJECTS = $(am_ztest_OBJECTS)\n@HAVE_ELF_TRUE@@NATIVE_TRUE@ztest_DEPENDENCIES = libbacktrace.la \\\n@HAVE_ELF_TRUE@@NATIVE_TRUE@\t$(am__DEPENDENCIES_1) \\\n@HAVE_ELF_TRUE@@NATIVE_TRUE@\t$(am__DEPENDENCIES_1)\nztest_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \\\n\t$(LIBTOOLFLAGS) --mode=link $(CCLD) $(ztest_CFLAGS) $(CFLAGS) \\\n\t$(ztest_LDFLAGS) $(LDFLAGS) -o $@\n@HAVE_ELF_TRUE@@NATIVE_TRUE@am__objects_16 =  \\\n@HAVE_ELF_TRUE@@NATIVE_TRUE@\tztest_alloc-ztest.$(OBJEXT) \\\n@HAVE_ELF_TRUE@@NATIVE_TRUE@\tztest_alloc-testlib.$(OBJEXT)\n@HAVE_ELF_TRUE@@NATIVE_TRUE@am_ztest_alloc_OBJECTS =  \\\n@HAVE_ELF_TRUE@@NATIVE_TRUE@\t$(am__objects_16)\nztest_alloc_OBJECTS = $(am_ztest_alloc_OBJECTS)\n@HAVE_ELF_TRUE@@NATIVE_TRUE@ztest_alloc_DEPENDENCIES =  \\\n@HAVE_ELF_TRUE@@NATIVE_TRUE@\tlibbacktrace_alloc.la \\\n@HAVE_ELF_TRUE@@NATIVE_TRUE@\t$(am__DEPENDENCIES_1) \\\n@HAVE_ELF_TRUE@@NATIVE_TRUE@\t$(am__DEPENDENCIES_1)\nztest_alloc_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \\\n\t$(LIBTOOLFLAGS) --mode=link $(CCLD) $(ztest_alloc_CFLAGS) \\\n\t$(CFLAGS) $(ztest_alloc_LDFLAGS) $(LDFLAGS) -o $@\nAM_V_P = $(am__v_P_@AM_V@)\nam__v_P_ = $(am__v_P_@AM_DEFAULT_V@)\nam__v_P_0 = false\nam__v_P_1 = :\nAM_V_GEN = $(am__v_GEN_@AM_V@)\nam__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)\nam__v_GEN_0 = @echo \"  GEN     \" $@;\nam__v_GEN_1 = \nAM_V_at = $(am__v_at_@AM_V@)\nam__v_at_ = $(am__v_at_@AM_DEFAULT_V@)\nam__v_at_0 = @\nam__v_at_1 = \nDEFAULT_INCLUDES = -I.@am__isrc@\ndepcomp =\nam__depfiles_maybe =\nCOMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \\\n\t$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)\nLTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \\\n\t$(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \\\n\t$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \\\n\t$(AM_CFLAGS) $(CFLAGS)\nAM_V_CC = $(am__v_CC_@AM_V@)\nam__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)\nam__v_CC_0 = @echo \"  CC      \" $@;\nam__v_CC_1 = \nCCLD = $(CC)\nLINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \\\n\t$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \\\n\t$(AM_LDFLAGS) $(LDFLAGS) -o $@\nAM_V_CCLD = $(am__v_CCLD_@AM_V@)\nam__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)\nam__v_CCLD_0 = @echo \"  CCLD    \" $@;\nam__v_CCLD_1 = \nSOURCES = $(libbacktrace_la_SOURCES) $(EXTRA_libbacktrace_la_SOURCES) \\\n\t$(libbacktrace_alloc_la_SOURCES) \\\n\t$(libbacktrace_elf_for_test_la_SOURCES) \\\n\t$(libbacktrace_instrumented_alloc_la_SOURCES) \\\n\t$(libbacktrace_noformat_la_SOURCES) $(allocfail_SOURCES) \\\n\t$(b2test_SOURCES) $(b3test_SOURCES) $(btest_SOURCES) \\\n\t$(btest_alloc_SOURCES) $(btest_lto_SOURCES) $(ctesta_SOURCES) \\\n\t$(ctesta_alloc_SOURCES) $(ctestg_SOURCES) \\\n\t$(ctestg_alloc_SOURCES) $(ctestzstd_SOURCES) \\\n\t$(ctestzstd_alloc_SOURCES) $(dwarf5_SOURCES) \\\n\t$(dwarf5_alloc_SOURCES) $(edtest_SOURCES) \\\n\t$(edtest_alloc_SOURCES) $(m2test_SOURCES) $(mtest_SOURCES) \\\n\t$(stest_SOURCES) $(stest_alloc_SOURCES) $(test_elf_32_SOURCES) \\\n\t$(test_elf_64_SOURCES) $(test_macho_SOURCES) \\\n\t$(test_pecoff_SOURCES) $(test_unknown_SOURCES) \\\n\t$(test_xcoff_32_SOURCES) $(test_xcoff_64_SOURCES) \\\n\t$(ttest_SOURCES) $(ttest_alloc_SOURCES) $(unittest_SOURCES) \\\n\t$(unittest_alloc_SOURCES) $(xztest_SOURCES) \\\n\t$(xztest_alloc_SOURCES) $(zstdtest_SOURCES) \\\n\t$(zstdtest_alloc_SOURCES) $(ztest_SOURCES) \\\n\t$(ztest_alloc_SOURCES)\nam__can_run_installinfo = \\\n  case $$AM_UPDATE_INFO_DIR in \\\n    n|no|NO) false;; \\\n    *) (install-info --version) >/dev/null 2>&1;; \\\n  esac\nHEADERS = $(include_HEADERS)\nam__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \\\n\t$(LISP)config.h.in\n# Read a list of newline-separated strings from the standard input,\n# and print each of them once, without duplicates.  Input order is\n# *not* preserved.\nam__uniquify_input = $(AWK) '\\\n  BEGIN { nonempty = 0; } \\\n  { items[$$0] = 1; nonempty = 1; } \\\n  END { if (nonempty) { for (i in items) print i; }; } \\\n'\n# Make sure the list of sources is unique.  This is necessary because,\n# e.g., the same source file might be shared among _SOURCES variables\n# for different programs/libraries.\nam__define_uniq_tagged_files = \\\n  list='$(am__tagged_files)'; \\\n  unique=`for i in $$list; do \\\n    if test -f \"$$i\"; then echo $$i; else echo $(srcdir)/$$i; fi; \\\n  done | $(am__uniquify_input)`\nETAGS = etags\nCTAGS = ctags\nCSCOPE = cscope\nAM_RECURSIVE_TARGETS = cscope check recheck\nam__tty_colors_dummy = \\\n  mgn= red= grn= lgn= blu= brg= std=; \\\n  am__color_tests=no\nam__tty_colors = { \\\n  $(am__tty_colors_dummy); \\\n  if test \"X$(AM_COLOR_TESTS)\" = Xno; then \\\n    am__color_tests=no; \\\n  elif test \"X$(AM_COLOR_TESTS)\" = Xalways; then \\\n    am__color_tests=yes; \\\n  elif test \"X$$TERM\" != Xdumb && { test -t 1; } 2>/dev/null; then \\\n    am__color_tests=yes; \\\n  fi; \\\n  if test $$am__color_tests = yes; then \\\n    red='\u001b[0;31m'; \\\n    grn='\u001b[0;32m'; \\\n    lgn='\u001b[1;32m'; \\\n    blu='\u001b[1;34m'; \\\n    mgn='\u001b[0;35m'; \\\n    brg='\u001b[1m'; \\\n    std='\u001b[m'; \\\n  fi; \\\n}\nam__recheck_rx = ^[ \t]*:recheck:[ \t]*\nam__global_test_result_rx = ^[ \t]*:global-test-result:[ \t]*\nam__copy_in_global_log_rx = ^[ \t]*:copy-in-global-log:[ \t]*\n# A command that, given a newline-separated list of test names on the\n# standard input, print the name of the tests that are to be re-run\n# upon \"make recheck\".\nam__list_recheck_tests = $(AWK) '{ \\\n  recheck = 1; \\\n  while ((rc = (getline line < ($$0 \".trs\"))) != 0) \\\n    { \\\n      if (rc < 0) \\\n        { \\\n          if ((getline line2 < ($$0 \".log\")) < 0) \\\n\t    recheck = 0; \\\n          break; \\\n        } \\\n      else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \\\n        { \\\n          recheck = 0; \\\n          break; \\\n        } \\\n      else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \\\n        { \\\n          break; \\\n        } \\\n    }; \\\n  if (recheck) \\\n    print $$0; \\\n  close ($$0 \".trs\"); \\\n  close ($$0 \".log\"); \\\n}'\n# A command that, given a newline-separated list of test names on the\n# standard input, create the global log from their .trs and .log files.\nam__create_global_log = $(AWK) ' \\\nfunction fatal(msg) \\\n{ \\\n  print \"fatal: making $@: \" msg | \"cat >&2\"; \\\n  exit 1; \\\n} \\\nfunction rst_section(header) \\\n{ \\\n  print header; \\\n  len = length(header); \\\n  for (i = 1; i <= len; i = i + 1) \\\n    printf \"=\"; \\\n  printf \"\\n\\n\"; \\\n} \\\n{ \\\n  copy_in_global_log = 1; \\\n  global_test_result = \"RUN\"; \\\n  while ((rc = (getline line < ($$0 \".trs\"))) != 0) \\\n    { \\\n      if (rc < 0) \\\n         fatal(\"failed to read from \" $$0 \".trs\"); \\\n      if (line ~ /$(am__global_test_result_rx)/) \\\n        { \\\n          sub(\"$(am__global_test_result_rx)\", \"\", line); \\\n          sub(\"[ \t]*$$\", \"\", line); \\\n          global_test_result = line; \\\n        } \\\n      else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \\\n        copy_in_global_log = 0; \\\n    }; \\\n  if (copy_in_global_log) \\\n    { \\\n      rst_section(global_test_result \": \" $$0); \\\n      while ((rc = (getline line < ($$0 \".log\"))) != 0) \\\n      { \\\n        if (rc < 0) \\\n          fatal(\"failed to read from \" $$0 \".log\"); \\\n        print line; \\\n      }; \\\n      printf \"\\n\"; \\\n    }; \\\n  close ($$0 \".trs\"); \\\n  close ($$0 \".log\"); \\\n}'\n# Restructured Text title.\nam__rst_title = { sed 's/.*/   &   /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; }\n# Solaris 10 'make', and several other traditional 'make' implementations,\n# pass \"-e\" to $(SHELL), and POSIX 2008 even requires this.  Work around it\n# by disabling -e (using the XSI extension \"set +e\") if it's set.\nam__sh_e_setup = case $$- in *e*) set +e;; esac\n# Default flags passed to test drivers.\nam__common_driver_flags = \\\n  --color-tests \"$$am__color_tests\" \\\n  --enable-hard-errors \"$$am__enable_hard_errors\" \\\n  --expect-failure \"$$am__expect_failure\"\n# To be inserted before the command running the test.  Creates the\n# directory for the log if needed.  Stores in $dir the directory\n# containing $f, in $tst the test, in $log the log.  Executes the\n# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and\n# passes TESTS_ENVIRONMENT.  Set up options for the wrapper that\n# will run the test scripts (or their associated LOG_COMPILER, if\n# thy have one).\nam__check_pre = \\\n$(am__sh_e_setup);\t\t\t\t\t\\\n$(am__vpath_adj_setup) $(am__vpath_adj)\t\t\t\\\n$(am__tty_colors);\t\t\t\t\t\\\nsrcdir=$(srcdir); export srcdir;\t\t\t\\\ncase \"$@\" in\t\t\t\t\t\t\\\n  */*) am__odir=`echo \"./$@\" | sed 's|/[^/]*$$||'`;;\t\\\n    *) am__odir=.;; \t\t\t\t\t\\\nesac;\t\t\t\t\t\t\t\\\ntest \"x$$am__odir\" = x\".\" || test -d \"$$am__odir\" \t\\\n  || $(MKDIR_P) \"$$am__odir\" || exit $$?;\t\t\\\nif test -f \"./$$f\"; then dir=./;\t\t\t\\\nelif test -f \"$$f\"; then dir=;\t\t\t\t\\\nelse dir=\"$(srcdir)/\"; fi;\t\t\t\t\\\ntst=$$dir$$f; log='$@'; \t\t\t\t\\\nif test -n '$(DISABLE_HARD_ERRORS)'; then\t\t\\\n  am__enable_hard_errors=no; \t\t\t\t\\\nelse\t\t\t\t\t\t\t\\\n  am__enable_hard_errors=yes; \t\t\t\t\\\nfi; \t\t\t\t\t\t\t\\\ncase \" $(XFAIL_TESTS) \" in\t\t\t\t\\\n  *[\\ \\\t]$$f[\\ \\\t]* | *[\\ \\\t]$$dir$$f[\\ \\\t]*) \\\n    am__expect_failure=yes;;\t\t\t\t\\\n  *)\t\t\t\t\t\t\t\\\n    am__expect_failure=no;;\t\t\t\t\\\nesac; \t\t\t\t\t\t\t\\\n$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT)\n# A shell command to get the names of the tests scripts with any registered\n# extension removed (i.e., equivalently, the names of the test logs, with\n# the '.log' extension removed).  The result is saved in the shell variable\n# '$bases'.  This honors runtime overriding of TESTS and TEST_LOGS.  Sadly,\n# we cannot use something simpler, involving e.g., \"$(TEST_LOGS:.log=)\",\n# since that might cause problem with VPATH rewrites for suffix-less tests.\n# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'.\nam__set_TESTS_bases = \\\n  bases='$(TEST_LOGS)'; \\\n  bases=`for i in $$bases; do echo $$i; done | sed 's/\\.log$$//'`; \\\n  bases=`echo $$bases`\nRECHECK_LOGS = $(TEST_LOGS)\nTEST_SUITE_LOG = test-suite.log\nTEST_EXTENSIONS = @EXEEXT@ .test\nLOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver\nLOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS)\nam__set_b = \\\n  case '$@' in \\\n    */*) \\\n      case '$*' in \\\n        */*) b='$*';; \\\n          *) b=`echo '$@' | sed 's/\\.log$$//'`; \\\n       esac;; \\\n    *) \\\n      b='$*';; \\\n  esac\nam__test_logs1 = $(TESTS:=.log)\nam__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log)\nTEST_LOGS = $(am__test_logs2:.test.log=.log)\nTEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver\nTEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \\\n\t$(TEST_LOG_FLAGS)\nACLOCAL = @ACLOCAL@\nALLOC_FILE = @ALLOC_FILE@\nAMTAR = @AMTAR@\nAM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@\nAR = @AR@\nAUTOCONF = @AUTOCONF@\nAUTOHEADER = @AUTOHEADER@\nAUTOMAKE = @AUTOMAKE@\nAWK = @AWK@\nBACKTRACE_FILE = @BACKTRACE_FILE@\nBACKTRACE_SUPPORTED = @BACKTRACE_SUPPORTED@\nBACKTRACE_SUPPORTS_DATA = @BACKTRACE_SUPPORTS_DATA@\nBACKTRACE_SUPPORTS_THREADS = @BACKTRACE_SUPPORTS_THREADS@\nBACKTRACE_USES_MALLOC = @BACKTRACE_USES_MALLOC@\nCC = @CC@\nCFLAGS = @CFLAGS@\nCLOCK_GETTIME_LINK = @CLOCK_GETTIME_LINK@\nCOMM = @COMM@\nCPP = @CPP@\nCPPFLAGS = @CPPFLAGS@\nCYGPATH_W = @CYGPATH_W@\nDEFS = @DEFS@\nDSYMUTIL = @DSYMUTIL@\nDUMPBIN = @DUMPBIN@\nDWZ = @DWZ@\nECHO_C = @ECHO_C@\nECHO_N = @ECHO_N@\nECHO_T = @ECHO_T@\nEGREP = @EGREP@\nEXEEXT = @EXEEXT@\nEXTRA_FLAGS = @EXTRA_FLAGS@\nFGREP = @FGREP@\nFORMAT_FILE = @FORMAT_FILE@\nGREP = @GREP@\nINSTALL = @INSTALL@\nINSTALL_DATA = @INSTALL_DATA@\nINSTALL_PROGRAM = @INSTALL_PROGRAM@\nINSTALL_SCRIPT = @INSTALL_SCRIPT@\nINSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@\nLD = @LD@\nLDFLAGS = @LDFLAGS@\nLIBOBJS = @LIBOBJS@\nLIBS = @LIBS@\nLIBTOOL = @LIBTOOL@\nLIPO = @LIPO@\nLN_S = @LN_S@\nLTLIBOBJS = @LTLIBOBJS@\nMAINT = @MAINT@\nMAKEINFO = @MAKEINFO@\nMKDIR_P = @MKDIR_P@\nNM = @NM@\nNMEDIT = @NMEDIT@\nOBJCOPY = @OBJCOPY@\nOBJDUMP = @OBJDUMP@\nOBJEXT = @OBJEXT@\nOTOOL = @OTOOL@\nOTOOL64 = @OTOOL64@\nPACKAGE = @PACKAGE@\nPACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@\nPACKAGE_NAME = @PACKAGE_NAME@\nPACKAGE_STRING = @PACKAGE_STRING@\nPACKAGE_TARNAME = @PACKAGE_TARNAME@\nPACKAGE_URL = @PACKAGE_URL@\nPACKAGE_VERSION = @PACKAGE_VERSION@\nPATH_SEPARATOR = @PATH_SEPARATOR@\nPIC_FLAG = @PIC_FLAG@\nPTHREAD_CFLAGS = @PTHREAD_CFLAGS@\nRANLIB = @RANLIB@\nREADELF = @READELF@\nSED = @SED@\nSET_MAKE = @SET_MAKE@\nSHELL = @SHELL@\nSTRIP = @STRIP@\nVERSION = @VERSION@\nVIEW_FILE = @VIEW_FILE@\nWARN_FLAGS = @WARN_FLAGS@\nXZ = @XZ@\nabs_builddir = @abs_builddir@\nabs_srcdir = @abs_srcdir@\nabs_top_builddir = @abs_top_builddir@\nabs_top_srcdir = @abs_top_srcdir@\nac_ct_CC = @ac_ct_CC@\nac_ct_DUMPBIN = @ac_ct_DUMPBIN@\nam__leading_dot = @am__leading_dot@\nam__tar = @am__tar@\nam__untar = @am__untar@\nbindir = @bindir@\nbuild = @build@\nbuild_alias = @build_alias@\nbuild_cpu = @build_cpu@\nbuild_os = @build_os@\nbuild_vendor = @build_vendor@\nbuilddir = @builddir@\ndatadir = @datadir@\ndatarootdir = @datarootdir@\ndocdir = @docdir@\ndvidir = @dvidir@\nexec_prefix = @exec_prefix@\nhost = @host@\nhost_alias = @host_alias@\nhost_cpu = @host_cpu@\nhost_os = @host_os@\nhost_vendor = @host_vendor@\nhtmldir = @htmldir@\nincludedir = @includedir@\ninfodir = @infodir@\ninstall_sh = @install_sh@\nlibdir = @libdir@\nlibexecdir = @libexecdir@\nlibtool_VERSION = @libtool_VERSION@\nlocaledir = @localedir@\nlocalstatedir = @localstatedir@\nmandir = @mandir@\nmkdir_p = @mkdir_p@\nmulti_basedir = @multi_basedir@\noldincludedir = @oldincludedir@\npdfdir = @pdfdir@\nprefix = @prefix@\nprogram_transform_name = @program_transform_name@\npsdir = @psdir@\nsbindir = @sbindir@\nsharedstatedir = @sharedstatedir@\nsrcdir = @srcdir@\nsysconfdir = @sysconfdir@\ntarget = @target@\ntarget_alias = @target_alias@\ntarget_cpu = @target_cpu@\ntarget_os = @target_os@\ntarget_vendor = @target_vendor@\ntop_build_prefix = @top_build_prefix@\ntop_builddir = @top_builddir@\ntop_srcdir = @top_srcdir@\nACLOCAL_AMFLAGS = -I config\nAM_CPPFLAGS = \nAM_CFLAGS = $(EXTRA_FLAGS) $(WARN_FLAGS) $(PIC_FLAG)\ninclude_HEADERS = backtrace.h backtrace-supported.h internal.h debuginfod_support.h\nlib_LTLIBRARIES = libbacktrace.la\nlibbacktrace_la_SOURCES = \\\n\tbacktrace.h \\\n\tatomic.c \\\n\tdwarf.c \\\n\tfileline.c \\\n\tinternal.h \\\n\tdebuginfod_support.h \\\n\tposix.c \\\n\tprint.c \\\n\tsort.c \\\n\tstate.c\n\nBACKTRACE_FILES = \\\n\tbacktrace.c \\\n\tsimple.c \\\n\tnounwind.c\n\nFORMAT_FILES = \\\n\telf.c \\\n\tmacho.c \\\n\tpecoff.c \\\n\tunknown.c \\\n\txcoff.c\n\nVIEW_FILES = \\\n\tread.c \\\n\tmmapio.c\n\nALLOC_FILES = \\\n\talloc.c \\\n\tmmap.c\n\nEXTRA_libbacktrace_la_SOURCES = \\\n\t$(BACKTRACE_FILES) \\\n\t$(FORMAT_FILES) \\\n\t$(VIEW_FILES) \\\n\t$(ALLOC_FILES)\n\nlibbacktrace_la_LIBADD = \\\n\t$(BACKTRACE_FILE) \\\n\t$(FORMAT_FILE) \\\n\t$(VIEW_FILE) \\\n\t$(ALLOC_FILE)\n\nlibbacktrace_la_DEPENDENCIES = $(libbacktrace_la_LIBADD)\n\n# Add a test to this variable if you want it to be built as a Makefile\n# target and run.\nMAKETESTS = $(am__append_7) $(am__append_9) $(am__append_12) \\\n\t$(am__append_13) $(am__append_22) $(am__append_30) \\\n\t$(am__append_32)\n\n# Add a test to this variable if you want it to be built as a program,\n# with SOURCES, etc., and run.\nBUILDTESTS = $(am__append_2) $(am__append_10) $(am__append_11) \\\n\t$(am__append_16) $(am__append_19) $(am__append_20) \\\n\t$(am__append_23) $(am__append_24) $(am__append_25) \\\n\t$(am__append_26) $(am__append_28) $(am__append_35)\n\n# Add a file to this variable if you want it to be built for testing.\ncheck_DATA = $(am__append_5) $(am__append_21) $(am__append_27) \\\n\t$(am__append_29)\n\n# Flags to use when compiling test programs.\nlibbacktrace_TEST_CFLAGS = $(EXTRA_FLAGS) $(WARN_FLAGS) -g\n\n# Flags to use when linking test programs.\n# This avoids generating a shell script when configured with --enable-shared.\nlibbacktrace_testing_ldflags = -no-install\n@NATIVE_TRUE@check_LTLIBRARIES = libbacktrace_alloc.la \\\n@NATIVE_TRUE@\tlibbacktrace_noformat.la $(am__append_1) \\\n@NATIVE_TRUE@\tlibbacktrace_instrumented_alloc.la\n@NATIVE_TRUE@libbacktrace_alloc_la_SOURCES = $(libbacktrace_la_SOURCES)\n@NATIVE_TRUE@libbacktrace_alloc_la_LIBADD = $(BACKTRACE_FILE) $(FORMAT_FILE) read.lo alloc.lo\n@NATIVE_TRUE@libbacktrace_alloc_la_DEPENDENCIES = $(libbacktrace_alloc_la_LIBADD)\n@NATIVE_TRUE@libbacktrace_noformat_la_SOURCES = $(libbacktrace_la_SOURCES)\n@NATIVE_TRUE@libbacktrace_noformat_la_LIBADD = $(BACKTRACE_FILE) $(VIEW_FILE) $(ALLOC_FILE)\n@NATIVE_TRUE@libbacktrace_noformat_la_DEPENDENCIES = $(libbacktrace_noformat_la_LIBADD)\n@HAVE_ELF_TRUE@@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@TEST_BUILD_ID_DIR = $(abs_builddir)/usr/lib/debug/.build-id/\n@HAVE_ELF_TRUE@@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@libbacktrace_elf_for_test_la_SOURCES = $(libbacktrace_la_SOURCES)\n@HAVE_ELF_TRUE@@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@libbacktrace_elf_for_test_la_LIBADD = $(BACKTRACE_FILE) elf_for_test.lo \\\n@HAVE_ELF_TRUE@@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@\t$(VIEW_FILE) $(ALLOC_FILE)\n\n@NATIVE_TRUE@test_elf_32_SOURCES = test_format.c testlib.c\n@NATIVE_TRUE@test_elf_32_CFLAGS = $(libbacktrace_TEST_CFLAGS)\n@NATIVE_TRUE@test_elf_32_LDFLAGS = $(libbacktrace_testing_ldflags)\n@NATIVE_TRUE@test_elf_32_LDADD = libbacktrace_noformat.la elf_32.lo\n@NATIVE_TRUE@test_elf_64_SOURCES = test_format.c testlib.c\n@NATIVE_TRUE@test_elf_64_CFLAGS = $(libbacktrace_TEST_CFLAGS)\n@NATIVE_TRUE@test_elf_64_LDFLAGS = $(libbacktrace_testing_ldflags)\n@NATIVE_TRUE@test_elf_64_LDADD = libbacktrace_noformat.la elf_64.lo\n@NATIVE_TRUE@test_macho_SOURCES = test_format.c testlib.c\n@NATIVE_TRUE@test_macho_CFLAGS = $(libbacktrace_TEST_CFLAGS)\n@NATIVE_TRUE@test_macho_LDFLAGS = $(libbacktrace_testing_ldflags)\n@NATIVE_TRUE@test_macho_LDADD = libbacktrace_noformat.la macho.lo\n@NATIVE_TRUE@test_xcoff_32_SOURCES = test_format.c testlib.c\n@NATIVE_TRUE@test_xcoff_32_CFLAGS = $(libbacktrace_TEST_CFLAGS)\n@NATIVE_TRUE@test_xcoff_32_LDFLAGS = $(libbacktrace_testing_ldflags)\n@NATIVE_TRUE@test_xcoff_32_LDADD = libbacktrace_noformat.la xcoff_32.lo\n@NATIVE_TRUE@test_xcoff_64_SOURCES = test_format.c testlib.c\n@NATIVE_TRUE@test_xcoff_64_CFLAGS = $(libbacktrace_TEST_CFLAGS)\n@NATIVE_TRUE@test_xcoff_64_LDFLAGS = $(libbacktrace_testing_ldflags)\n@NATIVE_TRUE@test_xcoff_64_LDADD = libbacktrace_noformat.la xcoff_64.lo\n@NATIVE_TRUE@test_pecoff_SOURCES = test_format.c testlib.c\n@NATIVE_TRUE@test_pecoff_CFLAGS = $(libbacktrace_TEST_CFLAGS)\n@NATIVE_TRUE@test_pecoff_LDFLAGS = $(libbacktrace_testing_ldflags)\n@NATIVE_TRUE@test_pecoff_LDADD = libbacktrace_noformat.la pecoff.lo\n@NATIVE_TRUE@test_unknown_SOURCES = test_format.c testlib.c\n@NATIVE_TRUE@test_unknown_CFLAGS = $(libbacktrace_TEST_CFLAGS)\n@NATIVE_TRUE@test_unknown_LDFLAGS = $(libbacktrace_testing_ldflags)\n@NATIVE_TRUE@test_unknown_LDADD = libbacktrace_noformat.la unknown.lo\n@NATIVE_TRUE@unittest_SOURCES = unittest.c testlib.c\n@NATIVE_TRUE@unittest_CFLAGS = $(libbacktrace_TEST_CFLAGS)\n@NATIVE_TRUE@unittest_LDFLAGS = $(libbacktrace_testing_ldflags)\n@NATIVE_TRUE@unittest_LDADD = libbacktrace.la\n@NATIVE_TRUE@unittest_alloc_SOURCES = $(unittest_SOURCES)\n@NATIVE_TRUE@unittest_alloc_CFLAGS = $(libbacktrace_TEST_CFLAGS)\n@NATIVE_TRUE@unittest_alloc_LDFLAGS = $(libbacktrace_testing_ldflags)\n@NATIVE_TRUE@unittest_alloc_LDADD = libbacktrace_alloc.la\n@NATIVE_TRUE@libbacktrace_instrumented_alloc_la_SOURCES = $(libbacktrace_la_SOURCES)\n@NATIVE_TRUE@libbacktrace_instrumented_alloc_la_LIBADD = $(BACKTRACE_FILE) $(FORMAT_FILE) \\\n@NATIVE_TRUE@\tread.lo instrumented_alloc.lo\n\n@NATIVE_TRUE@libbacktrace_instrumented_alloc_la_DEPENDENCIES = \\\n@NATIVE_TRUE@\t$(libbacktrace_instrumented_alloc_la_LIBADD)\n\n@NATIVE_TRUE@allocfail_SOURCES = allocfail.c testlib.c\n@NATIVE_TRUE@allocfail_CFLAGS = $(libbacktrace_TEST_CFLAGS)\n@NATIVE_TRUE@allocfail_LDADD = libbacktrace_instrumented_alloc.la\n@HAVE_BUILDID_TRUE@@HAVE_ELF_TRUE@@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@b2test_SOURCES = $(btest_SOURCES)\n@HAVE_BUILDID_TRUE@@HAVE_ELF_TRUE@@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@b2test_CFLAGS = $(libbacktrace_TEST_CFLAGS)\n@HAVE_BUILDID_TRUE@@HAVE_ELF_TRUE@@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@b2test_LDFLAGS = -Wl,--build-id $(libbacktrace_testing_ldflags)\n@HAVE_BUILDID_TRUE@@HAVE_ELF_TRUE@@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@b2test_LDADD = libbacktrace_elf_for_test.la\n@HAVE_BUILDID_TRUE@@HAVE_DWZ_TRUE@@HAVE_ELF_TRUE@@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@b3test_SOURCES = $(btest_SOURCES)\n@HAVE_BUILDID_TRUE@@HAVE_DWZ_TRUE@@HAVE_ELF_TRUE@@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@b3test_CFLAGS = $(libbacktrace_TEST_CFLAGS)\n@HAVE_BUILDID_TRUE@@HAVE_DWZ_TRUE@@HAVE_ELF_TRUE@@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@b3test_LDFLAGS = -Wl,--build-id $(libbacktrace_testing_ldflags)\n@HAVE_BUILDID_TRUE@@HAVE_DWZ_TRUE@@HAVE_ELF_TRUE@@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@b3test_LDADD = libbacktrace_elf_for_test.la\n@NATIVE_TRUE@btest_SOURCES = btest.c testlib.c\n@NATIVE_TRUE@btest_CFLAGS = $(libbacktrace_TEST_CFLAGS) -O\n@NATIVE_TRUE@btest_LDFLAGS = $(libbacktrace_testing_ldflags)\n@NATIVE_TRUE@btest_LDADD = libbacktrace.la\n@HAVE_ELF_TRUE@@NATIVE_TRUE@btest_lto_SOURCES = btest.c testlib.c\n@HAVE_ELF_TRUE@@NATIVE_TRUE@btest_lto_CFLAGS = $(libbacktrace_TEST_CFLAGS) -O -flto\n@HAVE_ELF_TRUE@@NATIVE_TRUE@btest_lto_LDFLAGS = $(libbacktrace_testing_ldflags)\n@HAVE_ELF_TRUE@@NATIVE_TRUE@btest_lto_LDADD = libbacktrace.la\n@NATIVE_TRUE@btest_alloc_SOURCES = $(btest_SOURCES)\n@NATIVE_TRUE@btest_alloc_CFLAGS = $(libbacktrace_TEST_CFLAGS)\n@NATIVE_TRUE@btest_alloc_LDFLAGS = $(libbacktrace_testing_ldflags)\n@NATIVE_TRUE@btest_alloc_LDADD = libbacktrace_alloc.la\n@NATIVE_TRUE@stest_SOURCES = stest.c\n@NATIVE_TRUE@stest_CFLAGS = $(libbacktrace_TEST_CFLAGS)\n@NATIVE_TRUE@stest_LDFLAGS = $(libbacktrace_testing_ldflags)\n@NATIVE_TRUE@stest_LDADD = libbacktrace.la\n@NATIVE_TRUE@stest_alloc_SOURCES = $(stest_SOURCES)\n@NATIVE_TRUE@stest_alloc_CFLAGS = $(libbacktrace_TEST_CFLAGS)\n@NATIVE_TRUE@stest_alloc_LDFLAGS = $(libbacktrace_testing_ldflags)\n@NATIVE_TRUE@stest_alloc_LDADD = libbacktrace_alloc.la\n@HAVE_ELF_TRUE@@NATIVE_TRUE@ztest_SOURCES = ztest.c testlib.c\n@HAVE_ELF_TRUE@@NATIVE_TRUE@ztest_CFLAGS = $(libbacktrace_TEST_CFLAGS) -DSRCDIR=\\\"$(srcdir)\\\"\n@HAVE_ELF_TRUE@@NATIVE_TRUE@ztest_LDFLAGS = $(libbacktrace_testing_ldflags)\n@HAVE_ELF_TRUE@@NATIVE_TRUE@ztest_LDADD = libbacktrace.la \\\n@HAVE_ELF_TRUE@@NATIVE_TRUE@\t$(am__append_14) \\\n@HAVE_ELF_TRUE@@NATIVE_TRUE@\t$(CLOCK_GETTIME_LINK)\n@HAVE_ELF_TRUE@@NATIVE_TRUE@ztest_alloc_LDADD = libbacktrace_alloc.la \\\n@HAVE_ELF_TRUE@@NATIVE_TRUE@\t$(am__append_15) \\\n@HAVE_ELF_TRUE@@NATIVE_TRUE@\t$(CLOCK_GETTIME_LINK)\n@HAVE_ELF_TRUE@@NATIVE_TRUE@ztest_alloc_SOURCES = $(ztest_SOURCES)\n@HAVE_ELF_TRUE@@NATIVE_TRUE@ztest_alloc_CFLAGS = $(ztest_CFLAGS)\n@HAVE_ELF_TRUE@@NATIVE_TRUE@ztest_alloc_LDFLAGS = $(libbacktrace_testing_ldflags)\n@HAVE_ELF_TRUE@@NATIVE_TRUE@zstdtest_SOURCES = zstdtest.c testlib.c\n@HAVE_ELF_TRUE@@NATIVE_TRUE@zstdtest_CFLAGS = $(libbacktrace_TEST_CFLAGS) -DSRCDIR=\\\"$(srcdir)\\\"\n@HAVE_ELF_TRUE@@NATIVE_TRUE@zstdtest_LDFLAGS = $(libbacktrace_testing_ldflags)\n@HAVE_ELF_TRUE@@NATIVE_TRUE@zstdtest_LDADD = libbacktrace.la \\\n@HAVE_ELF_TRUE@@NATIVE_TRUE@\t$(am__append_17) \\\n@HAVE_ELF_TRUE@@NATIVE_TRUE@\t$(CLOCK_GETTIME_LINK)\n@HAVE_ELF_TRUE@@NATIVE_TRUE@zstdtest_alloc_LDADD =  \\\n@HAVE_ELF_TRUE@@NATIVE_TRUE@\tlibbacktrace_alloc.la \\\n@HAVE_ELF_TRUE@@NATIVE_TRUE@\t$(am__append_18) \\\n@HAVE_ELF_TRUE@@NATIVE_TRUE@\t$(CLOCK_GETTIME_LINK)\n@HAVE_ELF_TRUE@@NATIVE_TRUE@zstdtest_alloc_SOURCES = $(zstdtest_SOURCES)\n@HAVE_ELF_TRUE@@NATIVE_TRUE@zstdtest_alloc_CFLAGS = $(zstdtest_CFLAGS)\n@HAVE_ELF_TRUE@@NATIVE_TRUE@zstdtest_alloc_LDFLAGS = $(libbacktrace_testing_ldflags)\n@NATIVE_TRUE@edtest_SOURCES = edtest.c edtest2_build.c testlib.c\n@NATIVE_TRUE@edtest_CFLAGS = $(libbacktrace_TEST_CFLAGS)\n@NATIVE_TRUE@edtest_LDFLAGS = $(libbacktrace_testing_ldflags)\n@NATIVE_TRUE@edtest_LDADD = libbacktrace.la\n@NATIVE_TRUE@edtest_alloc_SOURCES = $(edtest_SOURCES)\n@NATIVE_TRUE@edtest_alloc_CFLAGS = $(libbacktrace_TEST_CFLAGS)\n@NATIVE_TRUE@edtest_alloc_LDFLAGS = $(libbacktrace_testing_ldflags)\n@NATIVE_TRUE@edtest_alloc_LDADD = libbacktrace_alloc.la\n@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@ttest_SOURCES = ttest.c testlib.c\n@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@ttest_CFLAGS = $(libbacktrace_TEST_CFLAGS) -pthread\n@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@ttest_LDFLAGS = $(libbacktrace_testing_ldflags)\n@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@ttest_LDADD = libbacktrace.la\n@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@ttest_alloc_SOURCES = $(ttest_SOURCES)\n@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@ttest_alloc_CFLAGS = $(ttest_CFLAGS)\n@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@ttest_alloc_LDFLAGS = $(libbacktrace_testing_ldflags)\n@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@ttest_alloc_LDADD = libbacktrace_alloc.la\n@HAVE_COMPRESSED_DEBUG_ZLIB_GNU_TRUE@@NATIVE_TRUE@ctestg_SOURCES = btest.c testlib.c\n@HAVE_COMPRESSED_DEBUG_ZLIB_GNU_TRUE@@NATIVE_TRUE@ctestg_CFLAGS = $(libbacktrace_TEST_CFLAGS)\n@HAVE_COMPRESSED_DEBUG_ZLIB_GNU_TRUE@@NATIVE_TRUE@ctestg_LDFLAGS = -Wl,--compress-debug-sections=zlib-gnu $(libbacktrace_testing_ldflags)\n@HAVE_COMPRESSED_DEBUG_ZLIB_GNU_TRUE@@NATIVE_TRUE@ctestg_LDADD = libbacktrace.la\n@HAVE_COMPRESSED_DEBUG_ZLIB_GNU_TRUE@@NATIVE_TRUE@ctestg_alloc_SOURCES = $(ctestg_SOURCES)\n@HAVE_COMPRESSED_DEBUG_ZLIB_GNU_TRUE@@NATIVE_TRUE@ctestg_alloc_CFLAGS = $(ctestg_CFLAGS)\n@HAVE_COMPRESSED_DEBUG_ZLIB_GNU_TRUE@@NATIVE_TRUE@ctestg_alloc_LDFLAGS = $(ctestg_LDFLAGS) $(libbacktrace_testing_ldflags)\n@HAVE_COMPRESSED_DEBUG_ZLIB_GNU_TRUE@@NATIVE_TRUE@ctestg_alloc_LDADD = libbacktrace_alloc.la\n@HAVE_COMPRESSED_DEBUG_ZLIB_GABI_TRUE@@NATIVE_TRUE@ctesta_SOURCES = btest.c testlib.c\n@HAVE_COMPRESSED_DEBUG_ZLIB_GABI_TRUE@@NATIVE_TRUE@ctesta_CFLAGS = $(libbacktrace_TEST_CFLAGS)\n@HAVE_COMPRESSED_DEBUG_ZLIB_GABI_TRUE@@NATIVE_TRUE@ctesta_LDFLAGS = -Wl,--compress-debug-sections=zlib-gabi $(libbacktrace_testing_ldflags)\n@HAVE_COMPRESSED_DEBUG_ZLIB_GABI_TRUE@@NATIVE_TRUE@ctesta_LDADD = libbacktrace.la\n@HAVE_COMPRESSED_DEBUG_ZLIB_GABI_TRUE@@NATIVE_TRUE@ctesta_alloc_SOURCES = $(ctesta_SOURCES)\n@HAVE_COMPRESSED_DEBUG_ZLIB_GABI_TRUE@@NATIVE_TRUE@ctesta_alloc_CFLAGS = $(ctesta_CFLAGS)\n@HAVE_COMPRESSED_DEBUG_ZLIB_GABI_TRUE@@NATIVE_TRUE@ctesta_alloc_LDFLAGS = $(ctesta_LDFLAGS) $(libbacktrace_testing_ldflags)\n@HAVE_COMPRESSED_DEBUG_ZLIB_GABI_TRUE@@NATIVE_TRUE@ctesta_alloc_LDADD = libbacktrace_alloc.la\n@HAVE_COMPRESSED_DEBUG_ZSTD_TRUE@@NATIVE_TRUE@ctestzstd_SOURCES = btest.c testlib.c\n@HAVE_COMPRESSED_DEBUG_ZSTD_TRUE@@NATIVE_TRUE@ctestzstd_CFLAGS = $(libbacktrace_TEST_CFLAGS)\n@HAVE_COMPRESSED_DEBUG_ZSTD_TRUE@@NATIVE_TRUE@ctestzstd_LDFLAGS = -Wl,--compress-debug-sections=zstd $(libbacktrace_testing_ldflags)\n@HAVE_COMPRESSED_DEBUG_ZSTD_TRUE@@NATIVE_TRUE@ctestzstd_LDADD = libbacktrace.la\n@HAVE_COMPRESSED_DEBUG_ZSTD_TRUE@@NATIVE_TRUE@ctestzstd_alloc_SOURCES = $(ctestzstd_SOURCES)\n@HAVE_COMPRESSED_DEBUG_ZSTD_TRUE@@NATIVE_TRUE@ctestzstd_alloc_CFLAGS = $(ctestzstd_CFLAGS)\n@HAVE_COMPRESSED_DEBUG_ZSTD_TRUE@@NATIVE_TRUE@ctestzstd_alloc_LDFLAGS = $(ctestzstd_LDFLAGS) $(libbacktrace_testing_ldflags)\n@HAVE_COMPRESSED_DEBUG_ZSTD_TRUE@@NATIVE_TRUE@ctestzstd_alloc_LDADD = libbacktrace_alloc.la\n@HAVE_DWARF5_TRUE@@NATIVE_TRUE@dwarf5_SOURCES = btest.c testlib.c\n@HAVE_DWARF5_TRUE@@NATIVE_TRUE@dwarf5_CFLAGS = $(libbacktrace_TEST_CFLAGS) -gdwarf-5\n@HAVE_DWARF5_TRUE@@NATIVE_TRUE@dwarf5_LDFLAGS = $(libbacktrace_testing_ldflags)\n@HAVE_DWARF5_TRUE@@NATIVE_TRUE@dwarf5_LDADD = libbacktrace.la\n@HAVE_DWARF5_TRUE@@NATIVE_TRUE@dwarf5_alloc_SOURCES = $(dwarf5_SOURCES)\n@HAVE_DWARF5_TRUE@@NATIVE_TRUE@dwarf5_alloc_CFLAGS = $(dwarf5_CFLAGS)\n@HAVE_DWARF5_TRUE@@NATIVE_TRUE@dwarf5_alloc_LDFLAGS = $(libbacktrace_testing_ldflags)\n@HAVE_DWARF5_TRUE@@NATIVE_TRUE@dwarf5_alloc_LDADD = libbacktrace_alloc.la\n@NATIVE_TRUE@mtest_SOURCES = mtest.c testlib.c\n@NATIVE_TRUE@mtest_CFLAGS = $(libbacktrace_TEST_CFLAGS) -O\n@NATIVE_TRUE@mtest_LDFLAGS = $(libbacktrace_testing_ldflags)\n@NATIVE_TRUE@mtest_LDADD = libbacktrace.la\n@HAVE_BUILDID_TRUE@@HAVE_ELF_TRUE@@HAVE_MINIDEBUG_TRUE@@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@m2test_SOURCES = $(mtest_SOURCES)\n@HAVE_BUILDID_TRUE@@HAVE_ELF_TRUE@@HAVE_MINIDEBUG_TRUE@@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@m2test_CFLAGS = $(libbacktrace_TEST_CFLAGS) -O\n@HAVE_BUILDID_TRUE@@HAVE_ELF_TRUE@@HAVE_MINIDEBUG_TRUE@@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@m2test_LDFLAGS = -Wl,--build-id $(libbacktrace_testing_ldflags)\n@HAVE_BUILDID_TRUE@@HAVE_ELF_TRUE@@HAVE_MINIDEBUG_TRUE@@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@m2test_LDADD = libbacktrace_elf_for_test.la\n@HAVE_ELF_TRUE@xztest_SOURCES = xztest.c testlib.c\n@HAVE_ELF_TRUE@xztest_CFLAGS = $(libbacktrace_TEST_CFLAGS) -DSRCDIR=\\\"$(srcdir)\\\"\n@HAVE_ELF_TRUE@xztest_LDFLAGS = $(libbacktrace_testing_ldflags)\n@HAVE_ELF_TRUE@xztest_LDADD = libbacktrace.la $(am__append_33) \\\n@HAVE_ELF_TRUE@\t$(CLOCK_GETTIME_LINK)\n@HAVE_ELF_TRUE@xztest_alloc_SOURCES = $(xztest_SOURCES)\n@HAVE_ELF_TRUE@xztest_alloc_CFLAGS = $(xztest_CFLAGS)\n@HAVE_ELF_TRUE@xztest_alloc_LDFLAGS = $(libbacktrace_testing_ldflags)\n@HAVE_ELF_TRUE@xztest_alloc_LDADD = libbacktrace_alloc.la \\\n@HAVE_ELF_TRUE@\t$(am__append_34) $(CLOCK_GETTIME_LINK)\nCLEANFILES = \\\n\t$(MAKETESTS) $(BUILDTESTS) *.debug elf_for_test.c edtest2_build.c \\\n\tgen_edtest2_build \\\n\t*.dsyms *.fsyms *.keepsyms *.dbg *.mdbg *.mdbg.xz *.strip \\\n\t*.dsyms2 *.fsyms2 *.keepsyms2 *.dbg2 *.mdbg2 *.mdbg2.xz *.strip2\n\nall: config.h\n\t$(MAKE) $(AM_MAKEFLAGS) all-am\n\n.SUFFIXES:\n.SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs\nam--refresh: Makefile\n\t@:\n$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)\n\t@for dep in $?; do \\\n\t  case '$(am__configure_deps)' in \\\n\t    *$$dep*) \\\n\t      echo ' cd $(srcdir) && $(AUTOMAKE) --foreign --ignore-deps'; \\\n\t      $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign --ignore-deps \\\n\t\t&& exit 0; \\\n\t      exit 1;; \\\n\t  esac; \\\n\tdone; \\\n\techo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign --ignore-deps Makefile'; \\\n\t$(am__cd) $(top_srcdir) && \\\n\t  $(AUTOMAKE) --foreign --ignore-deps Makefile\nMakefile: $(srcdir)/Makefile.in $(top_builddir)/config.status\n\t@case '$?' in \\\n\t  *config.status*) \\\n\t    echo ' $(SHELL) ./config.status'; \\\n\t    $(SHELL) ./config.status;; \\\n\t  *) \\\n\t    echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \\\n\t    cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \\\n\tesac;\n\n$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)\n\t$(SHELL) ./config.status --recheck\n\n$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)\n\t$(am__cd) $(srcdir) && $(AUTOCONF)\n$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)\n\t$(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)\n$(am__aclocal_m4_deps):\n\nconfig.h: stamp-h1\n\t@test -f $@ || rm -f stamp-h1\n\t@test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1\n\nstamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status\n\t@rm -f stamp-h1\n\tcd $(top_builddir) && $(SHELL) ./config.status config.h\n$(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) \n\t($(am__cd) $(top_srcdir) && $(AUTOHEADER))\n\trm -f stamp-h1\n\ttouch $@\n\ndistclean-hdr:\n\t-rm -f config.h stamp-h1\nbacktrace-supported.h: $(top_builddir)/config.status $(srcdir)/backtrace-supported.h.in\n\tcd $(top_builddir) && $(SHELL) ./config.status $@\ninstall-debuginfo-for-buildid.sh: $(top_builddir)/config.status $(srcdir)/install-debuginfo-for-buildid.sh.in\n\tcd $(top_builddir) && $(SHELL) ./config.status $@\n\nclean-checkLTLIBRARIES:\n\t-test -z \"$(check_LTLIBRARIES)\" || rm -f $(check_LTLIBRARIES)\n\t@list='$(check_LTLIBRARIES)'; \\\n\tlocs=`for p in $$list; do echo $$p; done | \\\n\t      sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \\\n\t      sort -u`; \\\n\ttest -z \"$$locs\" || { \\\n\t  echo rm -f $${locs}; \\\n\t  rm -f $${locs}; \\\n\t}\n\ninstall-libLTLIBRARIES: $(lib_LTLIBRARIES)\n\t@$(NORMAL_INSTALL)\n\t@list='$(lib_LTLIBRARIES)'; test -n \"$(libdir)\" || list=; \\\n\tlist2=; for p in $$list; do \\\n\t  if test -f $$p; then \\\n\t    list2=\"$$list2 $$p\"; \\\n\t  else :; fi; \\\n\tdone; \\\n\ttest -z \"$$list2\" || { \\\n\t  echo \" $(MKDIR_P) '$(DESTDIR)$(libdir)'\"; \\\n\t  $(MKDIR_P) \"$(DESTDIR)$(libdir)\" || exit 1; \\\n\t  echo \" $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'\"; \\\n\t  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 \"$(DESTDIR)$(libdir)\"; \\\n\t}\n\nuninstall-libLTLIBRARIES:\n\t@$(NORMAL_UNINSTALL)\n\t@list='$(lib_LTLIBRARIES)'; test -n \"$(libdir)\" || list=; \\\n\tfor p in $$list; do \\\n\t  $(am__strip_dir) \\\n\t  echo \" $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'\"; \\\n\t  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f \"$(DESTDIR)$(libdir)/$$f\"; \\\n\tdone\n\nclean-libLTLIBRARIES:\n\t-test -z \"$(lib_LTLIBRARIES)\" || rm -f $(lib_LTLIBRARIES)\n\t@list='$(lib_LTLIBRARIES)'; \\\n\tlocs=`for p in $$list; do echo $$p; done | \\\n\t      sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \\\n\t      sort -u`; \\\n\ttest -z \"$$locs\" || { \\\n\t  echo rm -f $${locs}; \\\n\t  rm -f $${locs}; \\\n\t}\n\nlibbacktrace.la: $(libbacktrace_la_OBJECTS) $(libbacktrace_la_DEPENDENCIES) $(EXTRA_libbacktrace_la_DEPENDENCIES) \n\t$(AM_V_CCLD)$(LINK) -rpath $(libdir) $(libbacktrace_la_OBJECTS) $(libbacktrace_la_LIBADD) $(LIBS)\n\nlibbacktrace_alloc.la: $(libbacktrace_alloc_la_OBJECTS) $(libbacktrace_alloc_la_DEPENDENCIES) $(EXTRA_libbacktrace_alloc_la_DEPENDENCIES) \n\t$(AM_V_CCLD)$(LINK) $(am_libbacktrace_alloc_la_rpath) $(libbacktrace_alloc_la_OBJECTS) $(libbacktrace_alloc_la_LIBADD) $(LIBS)\n\nlibbacktrace_elf_for_test.la: $(libbacktrace_elf_for_test_la_OBJECTS) $(libbacktrace_elf_for_test_la_DEPENDENCIES) $(EXTRA_libbacktrace_elf_for_test_la_DEPENDENCIES) \n\t$(AM_V_CCLD)$(LINK) $(am_libbacktrace_elf_for_test_la_rpath) $(libbacktrace_elf_for_test_la_OBJECTS) $(libbacktrace_elf_for_test_la_LIBADD) $(LIBS)\n\nlibbacktrace_instrumented_alloc.la: $(libbacktrace_instrumented_alloc_la_OBJECTS) $(libbacktrace_instrumented_alloc_la_DEPENDENCIES) $(EXTRA_libbacktrace_instrumented_alloc_la_DEPENDENCIES) \n\t$(AM_V_CCLD)$(LINK) $(am_libbacktrace_instrumented_alloc_la_rpath) $(libbacktrace_instrumented_alloc_la_OBJECTS) $(libbacktrace_instrumented_alloc_la_LIBADD) $(LIBS)\n\nlibbacktrace_noformat.la: $(libbacktrace_noformat_la_OBJECTS) $(libbacktrace_noformat_la_DEPENDENCIES) $(EXTRA_libbacktrace_noformat_la_DEPENDENCIES) \n\t$(AM_V_CCLD)$(LINK) $(am_libbacktrace_noformat_la_rpath) $(libbacktrace_noformat_la_OBJECTS) $(libbacktrace_noformat_la_LIBADD) $(LIBS)\n\nclean-checkPROGRAMS:\n\t@list='$(check_PROGRAMS)'; test -n \"$$list\" || exit 0; \\\n\techo \" rm -f\" $$list; \\\n\trm -f $$list || exit $$?; \\\n\ttest -n \"$(EXEEXT)\" || exit 0; \\\n\tlist=`for p in $$list; do echo \"$$p\"; done | sed 's/$(EXEEXT)$$//'`; \\\n\techo \" rm -f\" $$list; \\\n\trm -f $$list\n\nallocfail$(EXEEXT): $(allocfail_OBJECTS) $(allocfail_DEPENDENCIES) $(EXTRA_allocfail_DEPENDENCIES) \n\t@rm -f allocfail$(EXEEXT)\n\t$(AM_V_CCLD)$(allocfail_LINK) $(allocfail_OBJECTS) $(allocfail_LDADD) $(LIBS)\n\nb2test$(EXEEXT): $(b2test_OBJECTS) $(b2test_DEPENDENCIES) $(EXTRA_b2test_DEPENDENCIES) \n\t@rm -f b2test$(EXEEXT)\n\t$(AM_V_CCLD)$(b2test_LINK) $(b2test_OBJECTS) $(b2test_LDADD) $(LIBS)\n\nb3test$(EXEEXT): $(b3test_OBJECTS) $(b3test_DEPENDENCIES) $(EXTRA_b3test_DEPENDENCIES) \n\t@rm -f b3test$(EXEEXT)\n\t$(AM_V_CCLD)$(b3test_LINK) $(b3test_OBJECTS) $(b3test_LDADD) $(LIBS)\n\nbtest$(EXEEXT): $(btest_OBJECTS) $(btest_DEPENDENCIES) $(EXTRA_btest_DEPENDENCIES) \n\t@rm -f btest$(EXEEXT)\n\t$(AM_V_CCLD)$(btest_LINK) $(btest_OBJECTS) $(btest_LDADD) $(LIBS)\n\nbtest_alloc$(EXEEXT): $(btest_alloc_OBJECTS) $(btest_alloc_DEPENDENCIES) $(EXTRA_btest_alloc_DEPENDENCIES) \n\t@rm -f btest_alloc$(EXEEXT)\n\t$(AM_V_CCLD)$(btest_alloc_LINK) $(btest_alloc_OBJECTS) $(btest_alloc_LDADD) $(LIBS)\n\nbtest_lto$(EXEEXT): $(btest_lto_OBJECTS) $(btest_lto_DEPENDENCIES) $(EXTRA_btest_lto_DEPENDENCIES) \n\t@rm -f btest_lto$(EXEEXT)\n\t$(AM_V_CCLD)$(btest_lto_LINK) $(btest_lto_OBJECTS) $(btest_lto_LDADD) $(LIBS)\n\nctesta$(EXEEXT): $(ctesta_OBJECTS) $(ctesta_DEPENDENCIES) $(EXTRA_ctesta_DEPENDENCIES) \n\t@rm -f ctesta$(EXEEXT)\n\t$(AM_V_CCLD)$(ctesta_LINK) $(ctesta_OBJECTS) $(ctesta_LDADD) $(LIBS)\n\nctesta_alloc$(EXEEXT): $(ctesta_alloc_OBJECTS) $(ctesta_alloc_DEPENDENCIES) $(EXTRA_ctesta_alloc_DEPENDENCIES) \n\t@rm -f ctesta_alloc$(EXEEXT)\n\t$(AM_V_CCLD)$(ctesta_alloc_LINK) $(ctesta_alloc_OBJECTS) $(ctesta_alloc_LDADD) $(LIBS)\n\nctestg$(EXEEXT): $(ctestg_OBJECTS) $(ctestg_DEPENDENCIES) $(EXTRA_ctestg_DEPENDENCIES) \n\t@rm -f ctestg$(EXEEXT)\n\t$(AM_V_CCLD)$(ctestg_LINK) $(ctestg_OBJECTS) $(ctestg_LDADD) $(LIBS)\n\nctestg_alloc$(EXEEXT): $(ctestg_alloc_OBJECTS) $(ctestg_alloc_DEPENDENCIES) $(EXTRA_ctestg_alloc_DEPENDENCIES) \n\t@rm -f ctestg_alloc$(EXEEXT)\n\t$(AM_V_CCLD)$(ctestg_alloc_LINK) $(ctestg_alloc_OBJECTS) $(ctestg_alloc_LDADD) $(LIBS)\n\nctestzstd$(EXEEXT): $(ctestzstd_OBJECTS) $(ctestzstd_DEPENDENCIES) $(EXTRA_ctestzstd_DEPENDENCIES) \n\t@rm -f ctestzstd$(EXEEXT)\n\t$(AM_V_CCLD)$(ctestzstd_LINK) $(ctestzstd_OBJECTS) $(ctestzstd_LDADD) $(LIBS)\n\nctestzstd_alloc$(EXEEXT): $(ctestzstd_alloc_OBJECTS) $(ctestzstd_alloc_DEPENDENCIES) $(EXTRA_ctestzstd_alloc_DEPENDENCIES) \n\t@rm -f ctestzstd_alloc$(EXEEXT)\n\t$(AM_V_CCLD)$(ctestzstd_alloc_LINK) $(ctestzstd_alloc_OBJECTS) $(ctestzstd_alloc_LDADD) $(LIBS)\n\ndwarf5$(EXEEXT): $(dwarf5_OBJECTS) $(dwarf5_DEPENDENCIES) $(EXTRA_dwarf5_DEPENDENCIES) \n\t@rm -f dwarf5$(EXEEXT)\n\t$(AM_V_CCLD)$(dwarf5_LINK) $(dwarf5_OBJECTS) $(dwarf5_LDADD) $(LIBS)\n\ndwarf5_alloc$(EXEEXT): $(dwarf5_alloc_OBJECTS) $(dwarf5_alloc_DEPENDENCIES) $(EXTRA_dwarf5_alloc_DEPENDENCIES) \n\t@rm -f dwarf5_alloc$(EXEEXT)\n\t$(AM_V_CCLD)$(dwarf5_alloc_LINK) $(dwarf5_alloc_OBJECTS) $(dwarf5_alloc_LDADD) $(LIBS)\n\nedtest$(EXEEXT): $(edtest_OBJECTS) $(edtest_DEPENDENCIES) $(EXTRA_edtest_DEPENDENCIES) \n\t@rm -f edtest$(EXEEXT)\n\t$(AM_V_CCLD)$(edtest_LINK) $(edtest_OBJECTS) $(edtest_LDADD) $(LIBS)\n\nedtest_alloc$(EXEEXT): $(edtest_alloc_OBJECTS) $(edtest_alloc_DEPENDENCIES) $(EXTRA_edtest_alloc_DEPENDENCIES) \n\t@rm -f edtest_alloc$(EXEEXT)\n\t$(AM_V_CCLD)$(edtest_alloc_LINK) $(edtest_alloc_OBJECTS) $(edtest_alloc_LDADD) $(LIBS)\n\nm2test$(EXEEXT): $(m2test_OBJECTS) $(m2test_DEPENDENCIES) $(EXTRA_m2test_DEPENDENCIES) \n\t@rm -f m2test$(EXEEXT)\n\t$(AM_V_CCLD)$(m2test_LINK) $(m2test_OBJECTS) $(m2test_LDADD) $(LIBS)\n\nmtest$(EXEEXT): $(mtest_OBJECTS) $(mtest_DEPENDENCIES) $(EXTRA_mtest_DEPENDENCIES) \n\t@rm -f mtest$(EXEEXT)\n\t$(AM_V_CCLD)$(mtest_LINK) $(mtest_OBJECTS) $(mtest_LDADD) $(LIBS)\n\nstest$(EXEEXT): $(stest_OBJECTS) $(stest_DEPENDENCIES) $(EXTRA_stest_DEPENDENCIES) \n\t@rm -f stest$(EXEEXT)\n\t$(AM_V_CCLD)$(stest_LINK) $(stest_OBJECTS) $(stest_LDADD) $(LIBS)\n\nstest_alloc$(EXEEXT): $(stest_alloc_OBJECTS) $(stest_alloc_DEPENDENCIES) $(EXTRA_stest_alloc_DEPENDENCIES) \n\t@rm -f stest_alloc$(EXEEXT)\n\t$(AM_V_CCLD)$(stest_alloc_LINK) $(stest_alloc_OBJECTS) $(stest_alloc_LDADD) $(LIBS)\n\ntest_elf_32$(EXEEXT): $(test_elf_32_OBJECTS) $(test_elf_32_DEPENDENCIES) $(EXTRA_test_elf_32_DEPENDENCIES) \n\t@rm -f test_elf_32$(EXEEXT)\n\t$(AM_V_CCLD)$(test_elf_32_LINK) $(test_elf_32_OBJECTS) $(test_elf_32_LDADD) $(LIBS)\n\ntest_elf_64$(EXEEXT): $(test_elf_64_OBJECTS) $(test_elf_64_DEPENDENCIES) $(EXTRA_test_elf_64_DEPENDENCIES) \n\t@rm -f test_elf_64$(EXEEXT)\n\t$(AM_V_CCLD)$(test_elf_64_LINK) $(test_elf_64_OBJECTS) $(test_elf_64_LDADD) $(LIBS)\n\ntest_macho$(EXEEXT): $(test_macho_OBJECTS) $(test_macho_DEPENDENCIES) $(EXTRA_test_macho_DEPENDENCIES) \n\t@rm -f test_macho$(EXEEXT)\n\t$(AM_V_CCLD)$(test_macho_LINK) $(test_macho_OBJECTS) $(test_macho_LDADD) $(LIBS)\n\ntest_pecoff$(EXEEXT): $(test_pecoff_OBJECTS) $(test_pecoff_DEPENDENCIES) $(EXTRA_test_pecoff_DEPENDENCIES) \n\t@rm -f test_pecoff$(EXEEXT)\n\t$(AM_V_CCLD)$(test_pecoff_LINK) $(test_pecoff_OBJECTS) $(test_pecoff_LDADD) $(LIBS)\n\ntest_unknown$(EXEEXT): $(test_unknown_OBJECTS) $(test_unknown_DEPENDENCIES) $(EXTRA_test_unknown_DEPENDENCIES) \n\t@rm -f test_unknown$(EXEEXT)\n\t$(AM_V_CCLD)$(test_unknown_LINK) $(test_unknown_OBJECTS) $(test_unknown_LDADD) $(LIBS)\n\ntest_xcoff_32$(EXEEXT): $(test_xcoff_32_OBJECTS) $(test_xcoff_32_DEPENDENCIES) $(EXTRA_test_xcoff_32_DEPENDENCIES) \n\t@rm -f test_xcoff_32$(EXEEXT)\n\t$(AM_V_CCLD)$(test_xcoff_32_LINK) $(test_xcoff_32_OBJECTS) $(test_xcoff_32_LDADD) $(LIBS)\n\ntest_xcoff_64$(EXEEXT): $(test_xcoff_64_OBJECTS) $(test_xcoff_64_DEPENDENCIES) $(EXTRA_test_xcoff_64_DEPENDENCIES) \n\t@rm -f test_xcoff_64$(EXEEXT)\n\t$(AM_V_CCLD)$(test_xcoff_64_LINK) $(test_xcoff_64_OBJECTS) $(test_xcoff_64_LDADD) $(LIBS)\n\nttest$(EXEEXT): $(ttest_OBJECTS) $(ttest_DEPENDENCIES) $(EXTRA_ttest_DEPENDENCIES) \n\t@rm -f ttest$(EXEEXT)\n\t$(AM_V_CCLD)$(ttest_LINK) $(ttest_OBJECTS) $(ttest_LDADD) $(LIBS)\n\nttest_alloc$(EXEEXT): $(ttest_alloc_OBJECTS) $(ttest_alloc_DEPENDENCIES) $(EXTRA_ttest_alloc_DEPENDENCIES) \n\t@rm -f ttest_alloc$(EXEEXT)\n\t$(AM_V_CCLD)$(ttest_alloc_LINK) $(ttest_alloc_OBJECTS) $(ttest_alloc_LDADD) $(LIBS)\n\nunittest$(EXEEXT): $(unittest_OBJECTS) $(unittest_DEPENDENCIES) $(EXTRA_unittest_DEPENDENCIES) \n\t@rm -f unittest$(EXEEXT)\n\t$(AM_V_CCLD)$(unittest_LINK) $(unittest_OBJECTS) $(unittest_LDADD) $(LIBS)\n\nunittest_alloc$(EXEEXT): $(unittest_alloc_OBJECTS) $(unittest_alloc_DEPENDENCIES) $(EXTRA_unittest_alloc_DEPENDENCIES) \n\t@rm -f unittest_alloc$(EXEEXT)\n\t$(AM_V_CCLD)$(unittest_alloc_LINK) $(unittest_alloc_OBJECTS) $(unittest_alloc_LDADD) $(LIBS)\n\nxztest$(EXEEXT): $(xztest_OBJECTS) $(xztest_DEPENDENCIES) $(EXTRA_xztest_DEPENDENCIES) \n\t@rm -f xztest$(EXEEXT)\n\t$(AM_V_CCLD)$(xztest_LINK) $(xztest_OBJECTS) $(xztest_LDADD) $(LIBS)\n\nxztest_alloc$(EXEEXT): $(xztest_alloc_OBJECTS) $(xztest_alloc_DEPENDENCIES) $(EXTRA_xztest_alloc_DEPENDENCIES) \n\t@rm -f xztest_alloc$(EXEEXT)\n\t$(AM_V_CCLD)$(xztest_alloc_LINK) $(xztest_alloc_OBJECTS) $(xztest_alloc_LDADD) $(LIBS)\n\nzstdtest$(EXEEXT): $(zstdtest_OBJECTS) $(zstdtest_DEPENDENCIES) $(EXTRA_zstdtest_DEPENDENCIES) \n\t@rm -f zstdtest$(EXEEXT)\n\t$(AM_V_CCLD)$(zstdtest_LINK) $(zstdtest_OBJECTS) $(zstdtest_LDADD) $(LIBS)\n\nzstdtest_alloc$(EXEEXT): $(zstdtest_alloc_OBJECTS) $(zstdtest_alloc_DEPENDENCIES) $(EXTRA_zstdtest_alloc_DEPENDENCIES) \n\t@rm -f zstdtest_alloc$(EXEEXT)\n\t$(AM_V_CCLD)$(zstdtest_alloc_LINK) $(zstdtest_alloc_OBJECTS) $(zstdtest_alloc_LDADD) $(LIBS)\n\nztest$(EXEEXT): $(ztest_OBJECTS) $(ztest_DEPENDENCIES) $(EXTRA_ztest_DEPENDENCIES) \n\t@rm -f ztest$(EXEEXT)\n\t$(AM_V_CCLD)$(ztest_LINK) $(ztest_OBJECTS) $(ztest_LDADD) $(LIBS)\n\nztest_alloc$(EXEEXT): $(ztest_alloc_OBJECTS) $(ztest_alloc_DEPENDENCIES) $(EXTRA_ztest_alloc_DEPENDENCIES) \n\t@rm -f ztest_alloc$(EXEEXT)\n\t$(AM_V_CCLD)$(ztest_alloc_LINK) $(ztest_alloc_OBJECTS) $(ztest_alloc_LDADD) $(LIBS)\n\nmostlyclean-compile:\n\t-rm -f *.$(OBJEXT)\n\ndistclean-compile:\n\t-rm -f *.tab.c\n\n.c.o:\n\t$(AM_V_CC)$(COMPILE) -c -o $@ $<\n\n.c.obj:\n\t$(AM_V_CC)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`\n\n.c.lo:\n\t$(AM_V_CC)$(LTCOMPILE) -c -o $@ $<\n\nallocfail-allocfail.o: allocfail.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(allocfail_CFLAGS) $(CFLAGS) -c -o allocfail-allocfail.o `test -f 'allocfail.c' || echo '$(srcdir)/'`allocfail.c\n\nallocfail-allocfail.obj: allocfail.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(allocfail_CFLAGS) $(CFLAGS) -c -o allocfail-allocfail.obj `if test -f 'allocfail.c'; then $(CYGPATH_W) 'allocfail.c'; else $(CYGPATH_W) '$(srcdir)/allocfail.c'; fi`\n\nallocfail-testlib.o: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(allocfail_CFLAGS) $(CFLAGS) -c -o allocfail-testlib.o `test -f 'testlib.c' || echo '$(srcdir)/'`testlib.c\n\nallocfail-testlib.obj: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(allocfail_CFLAGS) $(CFLAGS) -c -o allocfail-testlib.obj `if test -f 'testlib.c'; then $(CYGPATH_W) 'testlib.c'; else $(CYGPATH_W) '$(srcdir)/testlib.c'; fi`\n\nb2test-btest.o: btest.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(b2test_CFLAGS) $(CFLAGS) -c -o b2test-btest.o `test -f 'btest.c' || echo '$(srcdir)/'`btest.c\n\nb2test-btest.obj: btest.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(b2test_CFLAGS) $(CFLAGS) -c -o b2test-btest.obj `if test -f 'btest.c'; then $(CYGPATH_W) 'btest.c'; else $(CYGPATH_W) '$(srcdir)/btest.c'; fi`\n\nb2test-testlib.o: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(b2test_CFLAGS) $(CFLAGS) -c -o b2test-testlib.o `test -f 'testlib.c' || echo '$(srcdir)/'`testlib.c\n\nb2test-testlib.obj: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(b2test_CFLAGS) $(CFLAGS) -c -o b2test-testlib.obj `if test -f 'testlib.c'; then $(CYGPATH_W) 'testlib.c'; else $(CYGPATH_W) '$(srcdir)/testlib.c'; fi`\n\nb3test-btest.o: btest.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(b3test_CFLAGS) $(CFLAGS) -c -o b3test-btest.o `test -f 'btest.c' || echo '$(srcdir)/'`btest.c\n\nb3test-btest.obj: btest.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(b3test_CFLAGS) $(CFLAGS) -c -o b3test-btest.obj `if test -f 'btest.c'; then $(CYGPATH_W) 'btest.c'; else $(CYGPATH_W) '$(srcdir)/btest.c'; fi`\n\nb3test-testlib.o: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(b3test_CFLAGS) $(CFLAGS) -c -o b3test-testlib.o `test -f 'testlib.c' || echo '$(srcdir)/'`testlib.c\n\nb3test-testlib.obj: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(b3test_CFLAGS) $(CFLAGS) -c -o b3test-testlib.obj `if test -f 'testlib.c'; then $(CYGPATH_W) 'testlib.c'; else $(CYGPATH_W) '$(srcdir)/testlib.c'; fi`\n\nbtest-btest.o: btest.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(btest_CFLAGS) $(CFLAGS) -c -o btest-btest.o `test -f 'btest.c' || echo '$(srcdir)/'`btest.c\n\nbtest-btest.obj: btest.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(btest_CFLAGS) $(CFLAGS) -c -o btest-btest.obj `if test -f 'btest.c'; then $(CYGPATH_W) 'btest.c'; else $(CYGPATH_W) '$(srcdir)/btest.c'; fi`\n\nbtest-testlib.o: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(btest_CFLAGS) $(CFLAGS) -c -o btest-testlib.o `test -f 'testlib.c' || echo '$(srcdir)/'`testlib.c\n\nbtest-testlib.obj: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(btest_CFLAGS) $(CFLAGS) -c -o btest-testlib.obj `if test -f 'testlib.c'; then $(CYGPATH_W) 'testlib.c'; else $(CYGPATH_W) '$(srcdir)/testlib.c'; fi`\n\nbtest_alloc-btest.o: btest.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(btest_alloc_CFLAGS) $(CFLAGS) -c -o btest_alloc-btest.o `test -f 'btest.c' || echo '$(srcdir)/'`btest.c\n\nbtest_alloc-btest.obj: btest.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(btest_alloc_CFLAGS) $(CFLAGS) -c -o btest_alloc-btest.obj `if test -f 'btest.c'; then $(CYGPATH_W) 'btest.c'; else $(CYGPATH_W) '$(srcdir)/btest.c'; fi`\n\nbtest_alloc-testlib.o: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(btest_alloc_CFLAGS) $(CFLAGS) -c -o btest_alloc-testlib.o `test -f 'testlib.c' || echo '$(srcdir)/'`testlib.c\n\nbtest_alloc-testlib.obj: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(btest_alloc_CFLAGS) $(CFLAGS) -c -o btest_alloc-testlib.obj `if test -f 'testlib.c'; then $(CYGPATH_W) 'testlib.c'; else $(CYGPATH_W) '$(srcdir)/testlib.c'; fi`\n\nbtest_lto-btest.o: btest.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(btest_lto_CFLAGS) $(CFLAGS) -c -o btest_lto-btest.o `test -f 'btest.c' || echo '$(srcdir)/'`btest.c\n\nbtest_lto-btest.obj: btest.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(btest_lto_CFLAGS) $(CFLAGS) -c -o btest_lto-btest.obj `if test -f 'btest.c'; then $(CYGPATH_W) 'btest.c'; else $(CYGPATH_W) '$(srcdir)/btest.c'; fi`\n\nbtest_lto-testlib.o: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(btest_lto_CFLAGS) $(CFLAGS) -c -o btest_lto-testlib.o `test -f 'testlib.c' || echo '$(srcdir)/'`testlib.c\n\nbtest_lto-testlib.obj: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(btest_lto_CFLAGS) $(CFLAGS) -c -o btest_lto-testlib.obj `if test -f 'testlib.c'; then $(CYGPATH_W) 'testlib.c'; else $(CYGPATH_W) '$(srcdir)/testlib.c'; fi`\n\nctesta-btest.o: btest.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ctesta_CFLAGS) $(CFLAGS) -c -o ctesta-btest.o `test -f 'btest.c' || echo '$(srcdir)/'`btest.c\n\nctesta-btest.obj: btest.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ctesta_CFLAGS) $(CFLAGS) -c -o ctesta-btest.obj `if test -f 'btest.c'; then $(CYGPATH_W) 'btest.c'; else $(CYGPATH_W) '$(srcdir)/btest.c'; fi`\n\nctesta-testlib.o: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ctesta_CFLAGS) $(CFLAGS) -c -o ctesta-testlib.o `test -f 'testlib.c' || echo '$(srcdir)/'`testlib.c\n\nctesta-testlib.obj: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ctesta_CFLAGS) $(CFLAGS) -c -o ctesta-testlib.obj `if test -f 'testlib.c'; then $(CYGPATH_W) 'testlib.c'; else $(CYGPATH_W) '$(srcdir)/testlib.c'; fi`\n\nctesta_alloc-btest.o: btest.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ctesta_alloc_CFLAGS) $(CFLAGS) -c -o ctesta_alloc-btest.o `test -f 'btest.c' || echo '$(srcdir)/'`btest.c\n\nctesta_alloc-btest.obj: btest.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ctesta_alloc_CFLAGS) $(CFLAGS) -c -o ctesta_alloc-btest.obj `if test -f 'btest.c'; then $(CYGPATH_W) 'btest.c'; else $(CYGPATH_W) '$(srcdir)/btest.c'; fi`\n\nctesta_alloc-testlib.o: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ctesta_alloc_CFLAGS) $(CFLAGS) -c -o ctesta_alloc-testlib.o `test -f 'testlib.c' || echo '$(srcdir)/'`testlib.c\n\nctesta_alloc-testlib.obj: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ctesta_alloc_CFLAGS) $(CFLAGS) -c -o ctesta_alloc-testlib.obj `if test -f 'testlib.c'; then $(CYGPATH_W) 'testlib.c'; else $(CYGPATH_W) '$(srcdir)/testlib.c'; fi`\n\nctestg-btest.o: btest.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ctestg_CFLAGS) $(CFLAGS) -c -o ctestg-btest.o `test -f 'btest.c' || echo '$(srcdir)/'`btest.c\n\nctestg-btest.obj: btest.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ctestg_CFLAGS) $(CFLAGS) -c -o ctestg-btest.obj `if test -f 'btest.c'; then $(CYGPATH_W) 'btest.c'; else $(CYGPATH_W) '$(srcdir)/btest.c'; fi`\n\nctestg-testlib.o: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ctestg_CFLAGS) $(CFLAGS) -c -o ctestg-testlib.o `test -f 'testlib.c' || echo '$(srcdir)/'`testlib.c\n\nctestg-testlib.obj: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ctestg_CFLAGS) $(CFLAGS) -c -o ctestg-testlib.obj `if test -f 'testlib.c'; then $(CYGPATH_W) 'testlib.c'; else $(CYGPATH_W) '$(srcdir)/testlib.c'; fi`\n\nctestg_alloc-btest.o: btest.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ctestg_alloc_CFLAGS) $(CFLAGS) -c -o ctestg_alloc-btest.o `test -f 'btest.c' || echo '$(srcdir)/'`btest.c\n\nctestg_alloc-btest.obj: btest.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ctestg_alloc_CFLAGS) $(CFLAGS) -c -o ctestg_alloc-btest.obj `if test -f 'btest.c'; then $(CYGPATH_W) 'btest.c'; else $(CYGPATH_W) '$(srcdir)/btest.c'; fi`\n\nctestg_alloc-testlib.o: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ctestg_alloc_CFLAGS) $(CFLAGS) -c -o ctestg_alloc-testlib.o `test -f 'testlib.c' || echo '$(srcdir)/'`testlib.c\n\nctestg_alloc-testlib.obj: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ctestg_alloc_CFLAGS) $(CFLAGS) -c -o ctestg_alloc-testlib.obj `if test -f 'testlib.c'; then $(CYGPATH_W) 'testlib.c'; else $(CYGPATH_W) '$(srcdir)/testlib.c'; fi`\n\nctestzstd-btest.o: btest.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ctestzstd_CFLAGS) $(CFLAGS) -c -o ctestzstd-btest.o `test -f 'btest.c' || echo '$(srcdir)/'`btest.c\n\nctestzstd-btest.obj: btest.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ctestzstd_CFLAGS) $(CFLAGS) -c -o ctestzstd-btest.obj `if test -f 'btest.c'; then $(CYGPATH_W) 'btest.c'; else $(CYGPATH_W) '$(srcdir)/btest.c'; fi`\n\nctestzstd-testlib.o: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ctestzstd_CFLAGS) $(CFLAGS) -c -o ctestzstd-testlib.o `test -f 'testlib.c' || echo '$(srcdir)/'`testlib.c\n\nctestzstd-testlib.obj: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ctestzstd_CFLAGS) $(CFLAGS) -c -o ctestzstd-testlib.obj `if test -f 'testlib.c'; then $(CYGPATH_W) 'testlib.c'; else $(CYGPATH_W) '$(srcdir)/testlib.c'; fi`\n\nctestzstd_alloc-btest.o: btest.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ctestzstd_alloc_CFLAGS) $(CFLAGS) -c -o ctestzstd_alloc-btest.o `test -f 'btest.c' || echo '$(srcdir)/'`btest.c\n\nctestzstd_alloc-btest.obj: btest.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ctestzstd_alloc_CFLAGS) $(CFLAGS) -c -o ctestzstd_alloc-btest.obj `if test -f 'btest.c'; then $(CYGPATH_W) 'btest.c'; else $(CYGPATH_W) '$(srcdir)/btest.c'; fi`\n\nctestzstd_alloc-testlib.o: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ctestzstd_alloc_CFLAGS) $(CFLAGS) -c -o ctestzstd_alloc-testlib.o `test -f 'testlib.c' || echo '$(srcdir)/'`testlib.c\n\nctestzstd_alloc-testlib.obj: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ctestzstd_alloc_CFLAGS) $(CFLAGS) -c -o ctestzstd_alloc-testlib.obj `if test -f 'testlib.c'; then $(CYGPATH_W) 'testlib.c'; else $(CYGPATH_W) '$(srcdir)/testlib.c'; fi`\n\ndwarf5-btest.o: btest.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dwarf5_CFLAGS) $(CFLAGS) -c -o dwarf5-btest.o `test -f 'btest.c' || echo '$(srcdir)/'`btest.c\n\ndwarf5-btest.obj: btest.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dwarf5_CFLAGS) $(CFLAGS) -c -o dwarf5-btest.obj `if test -f 'btest.c'; then $(CYGPATH_W) 'btest.c'; else $(CYGPATH_W) '$(srcdir)/btest.c'; fi`\n\ndwarf5-testlib.o: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dwarf5_CFLAGS) $(CFLAGS) -c -o dwarf5-testlib.o `test -f 'testlib.c' || echo '$(srcdir)/'`testlib.c\n\ndwarf5-testlib.obj: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dwarf5_CFLAGS) $(CFLAGS) -c -o dwarf5-testlib.obj `if test -f 'testlib.c'; then $(CYGPATH_W) 'testlib.c'; else $(CYGPATH_W) '$(srcdir)/testlib.c'; fi`\n\ndwarf5_alloc-btest.o: btest.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dwarf5_alloc_CFLAGS) $(CFLAGS) -c -o dwarf5_alloc-btest.o `test -f 'btest.c' || echo '$(srcdir)/'`btest.c\n\ndwarf5_alloc-btest.obj: btest.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dwarf5_alloc_CFLAGS) $(CFLAGS) -c -o dwarf5_alloc-btest.obj `if test -f 'btest.c'; then $(CYGPATH_W) 'btest.c'; else $(CYGPATH_W) '$(srcdir)/btest.c'; fi`\n\ndwarf5_alloc-testlib.o: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dwarf5_alloc_CFLAGS) $(CFLAGS) -c -o dwarf5_alloc-testlib.o `test -f 'testlib.c' || echo '$(srcdir)/'`testlib.c\n\ndwarf5_alloc-testlib.obj: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dwarf5_alloc_CFLAGS) $(CFLAGS) -c -o dwarf5_alloc-testlib.obj `if test -f 'testlib.c'; then $(CYGPATH_W) 'testlib.c'; else $(CYGPATH_W) '$(srcdir)/testlib.c'; fi`\n\nedtest-edtest.o: edtest.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(edtest_CFLAGS) $(CFLAGS) -c -o edtest-edtest.o `test -f 'edtest.c' || echo '$(srcdir)/'`edtest.c\n\nedtest-edtest.obj: edtest.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(edtest_CFLAGS) $(CFLAGS) -c -o edtest-edtest.obj `if test -f 'edtest.c'; then $(CYGPATH_W) 'edtest.c'; else $(CYGPATH_W) '$(srcdir)/edtest.c'; fi`\n\nedtest-edtest2_build.o: edtest2_build.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(edtest_CFLAGS) $(CFLAGS) -c -o edtest-edtest2_build.o `test -f 'edtest2_build.c' || echo '$(srcdir)/'`edtest2_build.c\n\nedtest-edtest2_build.obj: edtest2_build.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(edtest_CFLAGS) $(CFLAGS) -c -o edtest-edtest2_build.obj `if test -f 'edtest2_build.c'; then $(CYGPATH_W) 'edtest2_build.c'; else $(CYGPATH_W) '$(srcdir)/edtest2_build.c'; fi`\n\nedtest-testlib.o: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(edtest_CFLAGS) $(CFLAGS) -c -o edtest-testlib.o `test -f 'testlib.c' || echo '$(srcdir)/'`testlib.c\n\nedtest-testlib.obj: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(edtest_CFLAGS) $(CFLAGS) -c -o edtest-testlib.obj `if test -f 'testlib.c'; then $(CYGPATH_W) 'testlib.c'; else $(CYGPATH_W) '$(srcdir)/testlib.c'; fi`\n\nedtest_alloc-edtest.o: edtest.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(edtest_alloc_CFLAGS) $(CFLAGS) -c -o edtest_alloc-edtest.o `test -f 'edtest.c' || echo '$(srcdir)/'`edtest.c\n\nedtest_alloc-edtest.obj: edtest.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(edtest_alloc_CFLAGS) $(CFLAGS) -c -o edtest_alloc-edtest.obj `if test -f 'edtest.c'; then $(CYGPATH_W) 'edtest.c'; else $(CYGPATH_W) '$(srcdir)/edtest.c'; fi`\n\nedtest_alloc-edtest2_build.o: edtest2_build.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(edtest_alloc_CFLAGS) $(CFLAGS) -c -o edtest_alloc-edtest2_build.o `test -f 'edtest2_build.c' || echo '$(srcdir)/'`edtest2_build.c\n\nedtest_alloc-edtest2_build.obj: edtest2_build.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(edtest_alloc_CFLAGS) $(CFLAGS) -c -o edtest_alloc-edtest2_build.obj `if test -f 'edtest2_build.c'; then $(CYGPATH_W) 'edtest2_build.c'; else $(CYGPATH_W) '$(srcdir)/edtest2_build.c'; fi`\n\nedtest_alloc-testlib.o: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(edtest_alloc_CFLAGS) $(CFLAGS) -c -o edtest_alloc-testlib.o `test -f 'testlib.c' || echo '$(srcdir)/'`testlib.c\n\nedtest_alloc-testlib.obj: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(edtest_alloc_CFLAGS) $(CFLAGS) -c -o edtest_alloc-testlib.obj `if test -f 'testlib.c'; then $(CYGPATH_W) 'testlib.c'; else $(CYGPATH_W) '$(srcdir)/testlib.c'; fi`\n\nm2test-mtest.o: mtest.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(m2test_CFLAGS) $(CFLAGS) -c -o m2test-mtest.o `test -f 'mtest.c' || echo '$(srcdir)/'`mtest.c\n\nm2test-mtest.obj: mtest.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(m2test_CFLAGS) $(CFLAGS) -c -o m2test-mtest.obj `if test -f 'mtest.c'; then $(CYGPATH_W) 'mtest.c'; else $(CYGPATH_W) '$(srcdir)/mtest.c'; fi`\n\nm2test-testlib.o: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(m2test_CFLAGS) $(CFLAGS) -c -o m2test-testlib.o `test -f 'testlib.c' || echo '$(srcdir)/'`testlib.c\n\nm2test-testlib.obj: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(m2test_CFLAGS) $(CFLAGS) -c -o m2test-testlib.obj `if test -f 'testlib.c'; then $(CYGPATH_W) 'testlib.c'; else $(CYGPATH_W) '$(srcdir)/testlib.c'; fi`\n\nmtest-mtest.o: mtest.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mtest_CFLAGS) $(CFLAGS) -c -o mtest-mtest.o `test -f 'mtest.c' || echo '$(srcdir)/'`mtest.c\n\nmtest-mtest.obj: mtest.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mtest_CFLAGS) $(CFLAGS) -c -o mtest-mtest.obj `if test -f 'mtest.c'; then $(CYGPATH_W) 'mtest.c'; else $(CYGPATH_W) '$(srcdir)/mtest.c'; fi`\n\nmtest-testlib.o: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mtest_CFLAGS) $(CFLAGS) -c -o mtest-testlib.o `test -f 'testlib.c' || echo '$(srcdir)/'`testlib.c\n\nmtest-testlib.obj: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mtest_CFLAGS) $(CFLAGS) -c -o mtest-testlib.obj `if test -f 'testlib.c'; then $(CYGPATH_W) 'testlib.c'; else $(CYGPATH_W) '$(srcdir)/testlib.c'; fi`\n\nstest-stest.o: stest.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stest_CFLAGS) $(CFLAGS) -c -o stest-stest.o `test -f 'stest.c' || echo '$(srcdir)/'`stest.c\n\nstest-stest.obj: stest.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stest_CFLAGS) $(CFLAGS) -c -o stest-stest.obj `if test -f 'stest.c'; then $(CYGPATH_W) 'stest.c'; else $(CYGPATH_W) '$(srcdir)/stest.c'; fi`\n\nstest_alloc-stest.o: stest.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stest_alloc_CFLAGS) $(CFLAGS) -c -o stest_alloc-stest.o `test -f 'stest.c' || echo '$(srcdir)/'`stest.c\n\nstest_alloc-stest.obj: stest.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stest_alloc_CFLAGS) $(CFLAGS) -c -o stest_alloc-stest.obj `if test -f 'stest.c'; then $(CYGPATH_W) 'stest.c'; else $(CYGPATH_W) '$(srcdir)/stest.c'; fi`\n\ntest_elf_32-test_format.o: test_format.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_elf_32_CFLAGS) $(CFLAGS) -c -o test_elf_32-test_format.o `test -f 'test_format.c' || echo '$(srcdir)/'`test_format.c\n\ntest_elf_32-test_format.obj: test_format.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_elf_32_CFLAGS) $(CFLAGS) -c -o test_elf_32-test_format.obj `if test -f 'test_format.c'; then $(CYGPATH_W) 'test_format.c'; else $(CYGPATH_W) '$(srcdir)/test_format.c'; fi`\n\ntest_elf_32-testlib.o: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_elf_32_CFLAGS) $(CFLAGS) -c -o test_elf_32-testlib.o `test -f 'testlib.c' || echo '$(srcdir)/'`testlib.c\n\ntest_elf_32-testlib.obj: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_elf_32_CFLAGS) $(CFLAGS) -c -o test_elf_32-testlib.obj `if test -f 'testlib.c'; then $(CYGPATH_W) 'testlib.c'; else $(CYGPATH_W) '$(srcdir)/testlib.c'; fi`\n\ntest_elf_64-test_format.o: test_format.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_elf_64_CFLAGS) $(CFLAGS) -c -o test_elf_64-test_format.o `test -f 'test_format.c' || echo '$(srcdir)/'`test_format.c\n\ntest_elf_64-test_format.obj: test_format.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_elf_64_CFLAGS) $(CFLAGS) -c -o test_elf_64-test_format.obj `if test -f 'test_format.c'; then $(CYGPATH_W) 'test_format.c'; else $(CYGPATH_W) '$(srcdir)/test_format.c'; fi`\n\ntest_elf_64-testlib.o: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_elf_64_CFLAGS) $(CFLAGS) -c -o test_elf_64-testlib.o `test -f 'testlib.c' || echo '$(srcdir)/'`testlib.c\n\ntest_elf_64-testlib.obj: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_elf_64_CFLAGS) $(CFLAGS) -c -o test_elf_64-testlib.obj `if test -f 'testlib.c'; then $(CYGPATH_W) 'testlib.c'; else $(CYGPATH_W) '$(srcdir)/testlib.c'; fi`\n\ntest_macho-test_format.o: test_format.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_macho_CFLAGS) $(CFLAGS) -c -o test_macho-test_format.o `test -f 'test_format.c' || echo '$(srcdir)/'`test_format.c\n\ntest_macho-test_format.obj: test_format.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_macho_CFLAGS) $(CFLAGS) -c -o test_macho-test_format.obj `if test -f 'test_format.c'; then $(CYGPATH_W) 'test_format.c'; else $(CYGPATH_W) '$(srcdir)/test_format.c'; fi`\n\ntest_macho-testlib.o: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_macho_CFLAGS) $(CFLAGS) -c -o test_macho-testlib.o `test -f 'testlib.c' || echo '$(srcdir)/'`testlib.c\n\ntest_macho-testlib.obj: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_macho_CFLAGS) $(CFLAGS) -c -o test_macho-testlib.obj `if test -f 'testlib.c'; then $(CYGPATH_W) 'testlib.c'; else $(CYGPATH_W) '$(srcdir)/testlib.c'; fi`\n\ntest_pecoff-test_format.o: test_format.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_pecoff_CFLAGS) $(CFLAGS) -c -o test_pecoff-test_format.o `test -f 'test_format.c' || echo '$(srcdir)/'`test_format.c\n\ntest_pecoff-test_format.obj: test_format.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_pecoff_CFLAGS) $(CFLAGS) -c -o test_pecoff-test_format.obj `if test -f 'test_format.c'; then $(CYGPATH_W) 'test_format.c'; else $(CYGPATH_W) '$(srcdir)/test_format.c'; fi`\n\ntest_pecoff-testlib.o: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_pecoff_CFLAGS) $(CFLAGS) -c -o test_pecoff-testlib.o `test -f 'testlib.c' || echo '$(srcdir)/'`testlib.c\n\ntest_pecoff-testlib.obj: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_pecoff_CFLAGS) $(CFLAGS) -c -o test_pecoff-testlib.obj `if test -f 'testlib.c'; then $(CYGPATH_W) 'testlib.c'; else $(CYGPATH_W) '$(srcdir)/testlib.c'; fi`\n\ntest_unknown-test_format.o: test_format.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_unknown_CFLAGS) $(CFLAGS) -c -o test_unknown-test_format.o `test -f 'test_format.c' || echo '$(srcdir)/'`test_format.c\n\ntest_unknown-test_format.obj: test_format.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_unknown_CFLAGS) $(CFLAGS) -c -o test_unknown-test_format.obj `if test -f 'test_format.c'; then $(CYGPATH_W) 'test_format.c'; else $(CYGPATH_W) '$(srcdir)/test_format.c'; fi`\n\ntest_unknown-testlib.o: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_unknown_CFLAGS) $(CFLAGS) -c -o test_unknown-testlib.o `test -f 'testlib.c' || echo '$(srcdir)/'`testlib.c\n\ntest_unknown-testlib.obj: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_unknown_CFLAGS) $(CFLAGS) -c -o test_unknown-testlib.obj `if test -f 'testlib.c'; then $(CYGPATH_W) 'testlib.c'; else $(CYGPATH_W) '$(srcdir)/testlib.c'; fi`\n\ntest_xcoff_32-test_format.o: test_format.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_xcoff_32_CFLAGS) $(CFLAGS) -c -o test_xcoff_32-test_format.o `test -f 'test_format.c' || echo '$(srcdir)/'`test_format.c\n\ntest_xcoff_32-test_format.obj: test_format.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_xcoff_32_CFLAGS) $(CFLAGS) -c -o test_xcoff_32-test_format.obj `if test -f 'test_format.c'; then $(CYGPATH_W) 'test_format.c'; else $(CYGPATH_W) '$(srcdir)/test_format.c'; fi`\n\ntest_xcoff_32-testlib.o: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_xcoff_32_CFLAGS) $(CFLAGS) -c -o test_xcoff_32-testlib.o `test -f 'testlib.c' || echo '$(srcdir)/'`testlib.c\n\ntest_xcoff_32-testlib.obj: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_xcoff_32_CFLAGS) $(CFLAGS) -c -o test_xcoff_32-testlib.obj `if test -f 'testlib.c'; then $(CYGPATH_W) 'testlib.c'; else $(CYGPATH_W) '$(srcdir)/testlib.c'; fi`\n\ntest_xcoff_64-test_format.o: test_format.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_xcoff_64_CFLAGS) $(CFLAGS) -c -o test_xcoff_64-test_format.o `test -f 'test_format.c' || echo '$(srcdir)/'`test_format.c\n\ntest_xcoff_64-test_format.obj: test_format.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_xcoff_64_CFLAGS) $(CFLAGS) -c -o test_xcoff_64-test_format.obj `if test -f 'test_format.c'; then $(CYGPATH_W) 'test_format.c'; else $(CYGPATH_W) '$(srcdir)/test_format.c'; fi`\n\ntest_xcoff_64-testlib.o: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_xcoff_64_CFLAGS) $(CFLAGS) -c -o test_xcoff_64-testlib.o `test -f 'testlib.c' || echo '$(srcdir)/'`testlib.c\n\ntest_xcoff_64-testlib.obj: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_xcoff_64_CFLAGS) $(CFLAGS) -c -o test_xcoff_64-testlib.obj `if test -f 'testlib.c'; then $(CYGPATH_W) 'testlib.c'; else $(CYGPATH_W) '$(srcdir)/testlib.c'; fi`\n\nttest-ttest.o: ttest.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ttest_CFLAGS) $(CFLAGS) -c -o ttest-ttest.o `test -f 'ttest.c' || echo '$(srcdir)/'`ttest.c\n\nttest-ttest.obj: ttest.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ttest_CFLAGS) $(CFLAGS) -c -o ttest-ttest.obj `if test -f 'ttest.c'; then $(CYGPATH_W) 'ttest.c'; else $(CYGPATH_W) '$(srcdir)/ttest.c'; fi`\n\nttest-testlib.o: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ttest_CFLAGS) $(CFLAGS) -c -o ttest-testlib.o `test -f 'testlib.c' || echo '$(srcdir)/'`testlib.c\n\nttest-testlib.obj: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ttest_CFLAGS) $(CFLAGS) -c -o ttest-testlib.obj `if test -f 'testlib.c'; then $(CYGPATH_W) 'testlib.c'; else $(CYGPATH_W) '$(srcdir)/testlib.c'; fi`\n\nttest_alloc-ttest.o: ttest.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ttest_alloc_CFLAGS) $(CFLAGS) -c -o ttest_alloc-ttest.o `test -f 'ttest.c' || echo '$(srcdir)/'`ttest.c\n\nttest_alloc-ttest.obj: ttest.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ttest_alloc_CFLAGS) $(CFLAGS) -c -o ttest_alloc-ttest.obj `if test -f 'ttest.c'; then $(CYGPATH_W) 'ttest.c'; else $(CYGPATH_W) '$(srcdir)/ttest.c'; fi`\n\nttest_alloc-testlib.o: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ttest_alloc_CFLAGS) $(CFLAGS) -c -o ttest_alloc-testlib.o `test -f 'testlib.c' || echo '$(srcdir)/'`testlib.c\n\nttest_alloc-testlib.obj: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ttest_alloc_CFLAGS) $(CFLAGS) -c -o ttest_alloc-testlib.obj `if test -f 'testlib.c'; then $(CYGPATH_W) 'testlib.c'; else $(CYGPATH_W) '$(srcdir)/testlib.c'; fi`\n\nunittest-unittest.o: unittest.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_CFLAGS) $(CFLAGS) -c -o unittest-unittest.o `test -f 'unittest.c' || echo '$(srcdir)/'`unittest.c\n\nunittest-unittest.obj: unittest.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_CFLAGS) $(CFLAGS) -c -o unittest-unittest.obj `if test -f 'unittest.c'; then $(CYGPATH_W) 'unittest.c'; else $(CYGPATH_W) '$(srcdir)/unittest.c'; fi`\n\nunittest-testlib.o: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_CFLAGS) $(CFLAGS) -c -o unittest-testlib.o `test -f 'testlib.c' || echo '$(srcdir)/'`testlib.c\n\nunittest-testlib.obj: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_CFLAGS) $(CFLAGS) -c -o unittest-testlib.obj `if test -f 'testlib.c'; then $(CYGPATH_W) 'testlib.c'; else $(CYGPATH_W) '$(srcdir)/testlib.c'; fi`\n\nunittest_alloc-unittest.o: unittest.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_alloc_CFLAGS) $(CFLAGS) -c -o unittest_alloc-unittest.o `test -f 'unittest.c' || echo '$(srcdir)/'`unittest.c\n\nunittest_alloc-unittest.obj: unittest.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_alloc_CFLAGS) $(CFLAGS) -c -o unittest_alloc-unittest.obj `if test -f 'unittest.c'; then $(CYGPATH_W) 'unittest.c'; else $(CYGPATH_W) '$(srcdir)/unittest.c'; fi`\n\nunittest_alloc-testlib.o: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_alloc_CFLAGS) $(CFLAGS) -c -o unittest_alloc-testlib.o `test -f 'testlib.c' || echo '$(srcdir)/'`testlib.c\n\nunittest_alloc-testlib.obj: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_alloc_CFLAGS) $(CFLAGS) -c -o unittest_alloc-testlib.obj `if test -f 'testlib.c'; then $(CYGPATH_W) 'testlib.c'; else $(CYGPATH_W) '$(srcdir)/testlib.c'; fi`\n\nxztest-xztest.o: xztest.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xztest_CFLAGS) $(CFLAGS) -c -o xztest-xztest.o `test -f 'xztest.c' || echo '$(srcdir)/'`xztest.c\n\nxztest-xztest.obj: xztest.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xztest_CFLAGS) $(CFLAGS) -c -o xztest-xztest.obj `if test -f 'xztest.c'; then $(CYGPATH_W) 'xztest.c'; else $(CYGPATH_W) '$(srcdir)/xztest.c'; fi`\n\nxztest-testlib.o: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xztest_CFLAGS) $(CFLAGS) -c -o xztest-testlib.o `test -f 'testlib.c' || echo '$(srcdir)/'`testlib.c\n\nxztest-testlib.obj: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xztest_CFLAGS) $(CFLAGS) -c -o xztest-testlib.obj `if test -f 'testlib.c'; then $(CYGPATH_W) 'testlib.c'; else $(CYGPATH_W) '$(srcdir)/testlib.c'; fi`\n\nxztest_alloc-xztest.o: xztest.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xztest_alloc_CFLAGS) $(CFLAGS) -c -o xztest_alloc-xztest.o `test -f 'xztest.c' || echo '$(srcdir)/'`xztest.c\n\nxztest_alloc-xztest.obj: xztest.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xztest_alloc_CFLAGS) $(CFLAGS) -c -o xztest_alloc-xztest.obj `if test -f 'xztest.c'; then $(CYGPATH_W) 'xztest.c'; else $(CYGPATH_W) '$(srcdir)/xztest.c'; fi`\n\nxztest_alloc-testlib.o: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xztest_alloc_CFLAGS) $(CFLAGS) -c -o xztest_alloc-testlib.o `test -f 'testlib.c' || echo '$(srcdir)/'`testlib.c\n\nxztest_alloc-testlib.obj: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xztest_alloc_CFLAGS) $(CFLAGS) -c -o xztest_alloc-testlib.obj `if test -f 'testlib.c'; then $(CYGPATH_W) 'testlib.c'; else $(CYGPATH_W) '$(srcdir)/testlib.c'; fi`\n\nzstdtest-zstdtest.o: zstdtest.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(zstdtest_CFLAGS) $(CFLAGS) -c -o zstdtest-zstdtest.o `test -f 'zstdtest.c' || echo '$(srcdir)/'`zstdtest.c\n\nzstdtest-zstdtest.obj: zstdtest.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(zstdtest_CFLAGS) $(CFLAGS) -c -o zstdtest-zstdtest.obj `if test -f 'zstdtest.c'; then $(CYGPATH_W) 'zstdtest.c'; else $(CYGPATH_W) '$(srcdir)/zstdtest.c'; fi`\n\nzstdtest-testlib.o: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(zstdtest_CFLAGS) $(CFLAGS) -c -o zstdtest-testlib.o `test -f 'testlib.c' || echo '$(srcdir)/'`testlib.c\n\nzstdtest-testlib.obj: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(zstdtest_CFLAGS) $(CFLAGS) -c -o zstdtest-testlib.obj `if test -f 'testlib.c'; then $(CYGPATH_W) 'testlib.c'; else $(CYGPATH_W) '$(srcdir)/testlib.c'; fi`\n\nzstdtest_alloc-zstdtest.o: zstdtest.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(zstdtest_alloc_CFLAGS) $(CFLAGS) -c -o zstdtest_alloc-zstdtest.o `test -f 'zstdtest.c' || echo '$(srcdir)/'`zstdtest.c\n\nzstdtest_alloc-zstdtest.obj: zstdtest.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(zstdtest_alloc_CFLAGS) $(CFLAGS) -c -o zstdtest_alloc-zstdtest.obj `if test -f 'zstdtest.c'; then $(CYGPATH_W) 'zstdtest.c'; else $(CYGPATH_W) '$(srcdir)/zstdtest.c'; fi`\n\nzstdtest_alloc-testlib.o: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(zstdtest_alloc_CFLAGS) $(CFLAGS) -c -o zstdtest_alloc-testlib.o `test -f 'testlib.c' || echo '$(srcdir)/'`testlib.c\n\nzstdtest_alloc-testlib.obj: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(zstdtest_alloc_CFLAGS) $(CFLAGS) -c -o zstdtest_alloc-testlib.obj `if test -f 'testlib.c'; then $(CYGPATH_W) 'testlib.c'; else $(CYGPATH_W) '$(srcdir)/testlib.c'; fi`\n\nztest-ztest.o: ztest.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ztest_CFLAGS) $(CFLAGS) -c -o ztest-ztest.o `test -f 'ztest.c' || echo '$(srcdir)/'`ztest.c\n\nztest-ztest.obj: ztest.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ztest_CFLAGS) $(CFLAGS) -c -o ztest-ztest.obj `if test -f 'ztest.c'; then $(CYGPATH_W) 'ztest.c'; else $(CYGPATH_W) '$(srcdir)/ztest.c'; fi`\n\nztest-testlib.o: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ztest_CFLAGS) $(CFLAGS) -c -o ztest-testlib.o `test -f 'testlib.c' || echo '$(srcdir)/'`testlib.c\n\nztest-testlib.obj: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ztest_CFLAGS) $(CFLAGS) -c -o ztest-testlib.obj `if test -f 'testlib.c'; then $(CYGPATH_W) 'testlib.c'; else $(CYGPATH_W) '$(srcdir)/testlib.c'; fi`\n\nztest_alloc-ztest.o: ztest.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ztest_alloc_CFLAGS) $(CFLAGS) -c -o ztest_alloc-ztest.o `test -f 'ztest.c' || echo '$(srcdir)/'`ztest.c\n\nztest_alloc-ztest.obj: ztest.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ztest_alloc_CFLAGS) $(CFLAGS) -c -o ztest_alloc-ztest.obj `if test -f 'ztest.c'; then $(CYGPATH_W) 'ztest.c'; else $(CYGPATH_W) '$(srcdir)/ztest.c'; fi`\n\nztest_alloc-testlib.o: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ztest_alloc_CFLAGS) $(CFLAGS) -c -o ztest_alloc-testlib.o `test -f 'testlib.c' || echo '$(srcdir)/'`testlib.c\n\nztest_alloc-testlib.obj: testlib.c\n\t$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ztest_alloc_CFLAGS) $(CFLAGS) -c -o ztest_alloc-testlib.obj `if test -f 'testlib.c'; then $(CYGPATH_W) 'testlib.c'; else $(CYGPATH_W) '$(srcdir)/testlib.c'; fi`\n\nmostlyclean-libtool:\n\t-rm -f *.lo\n\nclean-libtool:\n\t-rm -rf .libs _libs\n\ndistclean-libtool:\n\t-rm -f libtool config.lt\ninstall-includeHEADERS: $(include_HEADERS)\n\t@$(NORMAL_INSTALL)\n\t@list='$(include_HEADERS)'; test -n \"$(includedir)\" || list=; \\\n\tif test -n \"$$list\"; then \\\n\t  echo \" $(MKDIR_P) '$(DESTDIR)$(includedir)'\"; \\\n\t  $(MKDIR_P) \"$(DESTDIR)$(includedir)\" || exit 1; \\\n\tfi; \\\n\tfor p in $$list; do \\\n\t  if test -f \"$$p\"; then d=; else d=\"$(srcdir)/\"; fi; \\\n\t  echo \"$$d$$p\"; \\\n\tdone | $(am__base_list) | \\\n\twhile read files; do \\\n\t  echo \" $(INSTALL_HEADER) $$files '$(DESTDIR)$(includedir)'\"; \\\n\t  $(INSTALL_HEADER) $$files \"$(DESTDIR)$(includedir)\" || exit $$?; \\\n\tdone\n\nuninstall-includeHEADERS:\n\t@$(NORMAL_UNINSTALL)\n\t@list='$(include_HEADERS)'; test -n \"$(includedir)\" || list=; \\\n\tfiles=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \\\n\tdir='$(DESTDIR)$(includedir)'; $(am__uninstall_files_from_dir)\n\nID: $(am__tagged_files)\n\t$(am__define_uniq_tagged_files); mkid -fID $$unique\ntags: tags-am\nTAGS: tags\n\ntags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)\n\tset x; \\\n\there=`pwd`; \\\n\t$(am__define_uniq_tagged_files); \\\n\tshift; \\\n\tif test -z \"$(ETAGS_ARGS)$$*$$unique\"; then :; else \\\n\t  test -n \"$$unique\" || unique=$$empty_fix; \\\n\t  if test $$# -gt 0; then \\\n\t    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \\\n\t      \"$$@\" $$unique; \\\n\t  else \\\n\t    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \\\n\t      $$unique; \\\n\t  fi; \\\n\tfi\nctags: ctags-am\n\nCTAGS: ctags\nctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)\n\t$(am__define_uniq_tagged_files); \\\n\ttest -z \"$(CTAGS_ARGS)$$unique\" \\\n\t  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \\\n\t     $$unique\n\nGTAGS:\n\there=`$(am__cd) $(top_builddir) && pwd` \\\n\t  && $(am__cd) $(top_srcdir) \\\n\t  && gtags -i $(GTAGS_ARGS) \"$$here\"\ncscope: cscope.files\n\ttest ! -s cscope.files \\\n\t  || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS)\nclean-cscope:\n\t-rm -f cscope.files\ncscope.files: clean-cscope cscopelist\ncscopelist: cscopelist-am\n\ncscopelist-am: $(am__tagged_files)\n\tlist='$(am__tagged_files)'; \\\n\tcase \"$(srcdir)\" in \\\n\t  [\\\\/]* | ?:[\\\\/]*) sdir=\"$(srcdir)\" ;; \\\n\t  *) sdir=$(subdir)/$(srcdir) ;; \\\n\tesac; \\\n\tfor i in $$list; do \\\n\t  if test -f \"$$i\"; then \\\n\t    echo \"$(subdir)/$$i\"; \\\n\t  else \\\n\t    echo \"$$sdir/$$i\"; \\\n\t  fi; \\\n\tdone >> $(top_builddir)/cscope.files\n\ndistclean-tags:\n\t-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags\n\t-rm -f cscope.out cscope.in.out cscope.po.out cscope.files\n\n# Recover from deleted '.trs' file; this should ensure that\n# \"rm -f foo.log; make foo.trs\" re-run 'foo.test', and re-create\n# both 'foo.log' and 'foo.trs'.  Break the recipe in two subshells\n# to avoid problems with \"make -n\".\n.log.trs:\n\trm -f $< $@\n\t$(MAKE) $(AM_MAKEFLAGS) $<\n\n# Leading 'am--fnord' is there to ensure the list of targets does not\n# expand to empty, as could happen e.g. with make check TESTS=''.\nam--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck)\nam--force-recheck:\n\t@:\n\n$(TEST_SUITE_LOG): $(TEST_LOGS)\n\t@$(am__set_TESTS_bases); \\\n\tam__f_ok () { test -f \"$$1\" && test -r \"$$1\"; }; \\\n\tredo_bases=`for i in $$bases; do \\\n\t              am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \\\n\t            done`; \\\n\tif test -n \"$$redo_bases\"; then \\\n\t  redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \\\n\t  redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \\\n\t  if $(am__make_dryrun); then :; else \\\n\t    rm -f $$redo_logs && rm -f $$redo_results || exit 1; \\\n\t  fi; \\\n\tfi; \\\n\tif test -n \"$$am__remaking_logs\"; then \\\n\t  echo \"fatal: making $(TEST_SUITE_LOG): possible infinite\" \\\n\t       \"recursion detected\" >&2; \\\n\telif test -n \"$$redo_logs\"; then \\\n\t  am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \\\n\tfi; \\\n\tif $(am__make_dryrun); then :; else \\\n\t  st=0;  \\\n\t  errmsg=\"fatal: making $(TEST_SUITE_LOG): failed to create\"; \\\n\t  for i in $$redo_bases; do \\\n\t    test -f $$i.trs && test -r $$i.trs \\\n\t      || { echo \"$$errmsg $$i.trs\" >&2; st=1; }; \\\n\t    test -f $$i.log && test -r $$i.log \\\n\t      || { echo \"$$errmsg $$i.log\" >&2; st=1; }; \\\n\t  done; \\\n\t  test $$st -eq 0 || exit 1; \\\n\tfi\n\t@$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \\\n\tws='[ \t]'; \\\n\tresults=`for b in $$bases; do echo $$b.trs; done`; \\\n\ttest -n \"$$results\" || results=/dev/null; \\\n\tall=`  grep \"^$$ws*:test-result:\"           $$results | wc -l`; \\\n\tpass=` grep \"^$$ws*:test-result:$$ws*PASS\"  $$results | wc -l`; \\\n\tfail=` grep \"^$$ws*:test-result:$$ws*FAIL\"  $$results | wc -l`; \\\n\tskip=` grep \"^$$ws*:test-result:$$ws*SKIP\"  $$results | wc -l`; \\\n\txfail=`grep \"^$$ws*:test-result:$$ws*XFAIL\" $$results | wc -l`; \\\n\txpass=`grep \"^$$ws*:test-result:$$ws*XPASS\" $$results | wc -l`; \\\n\terror=`grep \"^$$ws*:test-result:$$ws*ERROR\" $$results | wc -l`; \\\n\tif test `expr $$fail + $$xpass + $$error` -eq 0; then \\\n\t  success=true; \\\n\telse \\\n\t  success=false; \\\n\tfi; \\\n\tbr='==================='; br=$$br$$br$$br$$br; \\\n\tresult_count () \\\n\t{ \\\n\t    if test x\"$$1\" = x\"--maybe-color\"; then \\\n\t      maybe_colorize=yes; \\\n\t    elif test x\"$$1\" = x\"--no-color\"; then \\\n\t      maybe_colorize=no; \\\n\t    else \\\n\t      echo \"$@: invalid 'result_count' usage\" >&2; exit 4; \\\n\t    fi; \\\n\t    shift; \\\n\t    desc=$$1 count=$$2; \\\n\t    if test $$maybe_colorize = yes && test $$count -gt 0; then \\\n\t      color_start=$$3 color_end=$$std; \\\n\t    else \\\n\t      color_start= color_end=; \\\n\t    fi; \\\n\t    echo \"$${color_start}# $$desc $$count$${color_end}\"; \\\n\t}; \\\n\tcreate_testsuite_report () \\\n\t{ \\\n\t  result_count $$1 \"TOTAL:\" $$all   \"$$brg\"; \\\n\t  result_count $$1 \"PASS: \" $$pass  \"$$grn\"; \\\n\t  result_count $$1 \"SKIP: \" $$skip  \"$$blu\"; \\\n\t  result_count $$1 \"XFAIL:\" $$xfail \"$$lgn\"; \\\n\t  result_count $$1 \"FAIL: \" $$fail  \"$$red\"; \\\n\t  result_count $$1 \"XPASS:\" $$xpass \"$$red\"; \\\n\t  result_count $$1 \"ERROR:\" $$error \"$$mgn\"; \\\n\t}; \\\n\t{\t\t\t\t\t\t\t\t\\\n\t  echo \"$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)\" |\t\\\n\t    $(am__rst_title);\t\t\t\t\t\t\\\n\t  create_testsuite_report --no-color;\t\t\t\t\\\n\t  echo;\t\t\t\t\t\t\t\t\\\n\t  echo \".. contents:: :depth: 2\";\t\t\t\t\\\n\t  echo;\t\t\t\t\t\t\t\t\\\n\t  for b in $$bases; do echo $$b; done\t\t\t\t\\\n\t    | $(am__create_global_log);\t\t\t\t\t\\\n\t} >$(TEST_SUITE_LOG).tmp || exit 1;\t\t\t\t\\\n\tmv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG);\t\t\t\\\n\tif $$success; then\t\t\t\t\t\t\\\n\t  col=\"$$grn\";\t\t\t\t\t\t\t\\\n\t else\t\t\t\t\t\t\t\t\\\n\t  col=\"$$red\";\t\t\t\t\t\t\t\\\n\t  test x\"$$VERBOSE\" = x || cat $(TEST_SUITE_LOG);\t\t\\\n\tfi;\t\t\t\t\t\t\t\t\\\n\techo \"$${col}$$br$${std}\"; \t\t\t\t\t\\\n\techo \"$${col}Testsuite summary for $(PACKAGE_STRING)$${std}\";\t\\\n\techo \"$${col}$$br$${std}\"; \t\t\t\t\t\\\n\tcreate_testsuite_report --maybe-color;\t\t\t\t\\\n\techo \"$$col$$br$$std\";\t\t\t\t\t\t\\\n\tif $$success; then :; else\t\t\t\t\t\\\n\t  echo \"$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}\";\t\t\\\n\t  if test -n \"$(PACKAGE_BUGREPORT)\"; then\t\t\t\\\n\t    echo \"$${col}Please report to $(PACKAGE_BUGREPORT)$${std}\";\t\\\n\t  fi;\t\t\t\t\t\t\t\t\\\n\t  echo \"$$col$$br$$std\";\t\t\t\t\t\\\n\tfi;\t\t\t\t\t\t\t\t\\\n\t$$success || exit 1\n\ncheck-TESTS:\n\t@list='$(RECHECK_LOGS)';           test -z \"$$list\" || rm -f $$list\n\t@list='$(RECHECK_LOGS:.log=.trs)'; test -z \"$$list\" || rm -f $$list\n\t@test -z \"$(TEST_SUITE_LOG)\" || rm -f $(TEST_SUITE_LOG)\n\t@set +e; $(am__set_TESTS_bases); \\\n\tlog_list=`for i in $$bases; do echo $$i.log; done`; \\\n\ttrs_list=`for i in $$bases; do echo $$i.trs; done`; \\\n\tlog_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \\\n\t$(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS=\"$$log_list\"; \\\n\texit $$?;\nrecheck: all $(check_LTLIBRARIES) $(check_PROGRAMS) $(check_DATA)\n\t@test -z \"$(TEST_SUITE_LOG)\" || rm -f $(TEST_SUITE_LOG)\n\t@set +e; $(am__set_TESTS_bases); \\\n\tbases=`for i in $$bases; do echo $$i; done \\\n\t         | $(am__list_recheck_tests)` || exit 1; \\\n\tlog_list=`for i in $$bases; do echo $$i.log; done`; \\\n\tlog_list=`echo $$log_list`; \\\n\t$(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \\\n\t        am__force_recheck=am--force-recheck \\\n\t        TEST_LOGS=\"$$log_list\"; \\\n\texit $$?\nallocfail.sh.log: allocfail.sh\n\t@p='allocfail.sh'; \\\n\tb='allocfail.sh'; \\\n\t$(am__check_pre) $(LOG_DRIVER) --test-name \"$$f\" \\\n\t--log-file $$b.log --trs-file $$b.trs \\\n\t$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \\\n\t\"$$tst\" $(AM_TESTS_FD_REDIRECT)\nb2test_buildid.log: b2test_buildid\n\t@p='b2test_buildid'; \\\n\tb='b2test_buildid'; \\\n\t$(am__check_pre) $(LOG_DRIVER) --test-name \"$$f\" \\\n\t--log-file $$b.log --trs-file $$b.trs \\\n\t$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \\\n\t\"$$tst\" $(AM_TESTS_FD_REDIRECT)\nb2test_buildidfull.log: b2test_buildidfull\n\t@p='b2test_buildidfull'; \\\n\tb='b2test_buildidfull'; \\\n\t$(am__check_pre) $(LOG_DRIVER) --test-name \"$$f\" \\\n\t--log-file $$b.log --trs-file $$b.trs \\\n\t$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \\\n\t\"$$tst\" $(AM_TESTS_FD_REDIRECT)\nb3test_dwz_buildid.log: b3test_dwz_buildid\n\t@p='b3test_dwz_buildid'; \\\n\tb='b3test_dwz_buildid'; \\\n\t$(am__check_pre) $(LOG_DRIVER) --test-name \"$$f\" \\\n\t--log-file $$b.log --trs-file $$b.trs \\\n\t$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \\\n\t\"$$tst\" $(AM_TESTS_FD_REDIRECT)\nb3test_dwz_buildidfull.log: b3test_dwz_buildidfull\n\t@p='b3test_dwz_buildidfull'; \\\n\tb='b3test_dwz_buildidfull'; \\\n\t$(am__check_pre) $(LOG_DRIVER) --test-name \"$$f\" \\\n\t--log-file $$b.log --trs-file $$b.trs \\\n\t$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \\\n\t\"$$tst\" $(AM_TESTS_FD_REDIRECT)\nbtest_dwz.log: btest_dwz\n\t@p='btest_dwz'; \\\n\tb='btest_dwz'; \\\n\t$(am__check_pre) $(LOG_DRIVER) --test-name \"$$f\" \\\n\t--log-file $$b.log --trs-file $$b.trs \\\n\t$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \\\n\t\"$$tst\" $(AM_TESTS_FD_REDIRECT)\nbtest_dwz_gnudebuglink.log: btest_dwz_gnudebuglink\n\t@p='btest_dwz_gnudebuglink'; \\\n\tb='btest_dwz_gnudebuglink'; \\\n\t$(am__check_pre) $(LOG_DRIVER) --test-name \"$$f\" \\\n\t--log-file $$b.log --trs-file $$b.trs \\\n\t$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \\\n\t\"$$tst\" $(AM_TESTS_FD_REDIRECT)\nbtest_gnudebuglink.log: btest_gnudebuglink\n\t@p='btest_gnudebuglink'; \\\n\tb='btest_gnudebuglink'; \\\n\t$(am__check_pre) $(LOG_DRIVER) --test-name \"$$f\" \\\n\t--log-file $$b.log --trs-file $$b.trs \\\n\t$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \\\n\t\"$$tst\" $(AM_TESTS_FD_REDIRECT)\nbtest_gnudebuglinkfull.log: btest_gnudebuglinkfull\n\t@p='btest_gnudebuglinkfull'; \\\n\tb='btest_gnudebuglinkfull'; \\\n\t$(am__check_pre) $(LOG_DRIVER) --test-name \"$$f\" \\\n\t--log-file $$b.log --trs-file $$b.trs \\\n\t$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \\\n\t\"$$tst\" $(AM_TESTS_FD_REDIRECT)\nmtest_minidebug.log: mtest_minidebug\n\t@p='mtest_minidebug'; \\\n\tb='mtest_minidebug'; \\\n\t$(am__check_pre) $(LOG_DRIVER) --test-name \"$$f\" \\\n\t--log-file $$b.log --trs-file $$b.trs \\\n\t$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \\\n\t\"$$tst\" $(AM_TESTS_FD_REDIRECT)\nm2test_minidebug2.log: m2test_minidebug2\n\t@p='m2test_minidebug2'; \\\n\tb='m2test_minidebug2'; \\\n\t$(am__check_pre) $(LOG_DRIVER) --test-name \"$$f\" \\\n\t--log-file $$b.log --trs-file $$b.trs \\\n\t$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \\\n\t\"$$tst\" $(AM_TESTS_FD_REDIRECT)\ntest_elf_32.log: test_elf_32$(EXEEXT)\n\t@p='test_elf_32$(EXEEXT)'; \\\n\tb='test_elf_32'; \\\n\t$(am__check_pre) $(LOG_DRIVER) --test-name \"$$f\" \\\n\t--log-file $$b.log --trs-file $$b.trs \\\n\t$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \\\n\t\"$$tst\" $(AM_TESTS_FD_REDIRECT)\ntest_elf_64.log: test_elf_64$(EXEEXT)\n\t@p='test_elf_64$(EXEEXT)'; \\\n\tb='test_elf_64'; \\\n\t$(am__check_pre) $(LOG_DRIVER) --test-name \"$$f\" \\\n\t--log-file $$b.log --trs-file $$b.trs \\\n\t$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \\\n\t\"$$tst\" $(AM_TESTS_FD_REDIRECT)\ntest_macho.log: test_macho$(EXEEXT)\n\t@p='test_macho$(EXEEXT)'; \\\n\tb='test_macho'; \\\n\t$(am__check_pre) $(LOG_DRIVER) --test-name \"$$f\" \\\n\t--log-file $$b.log --trs-file $$b.trs \\\n\t$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \\\n\t\"$$tst\" $(AM_TESTS_FD_REDIRECT)\ntest_xcoff_32.log: test_xcoff_32$(EXEEXT)\n\t@p='test_xcoff_32$(EXEEXT)'; \\\n\tb='test_xcoff_32'; \\\n\t$(am__check_pre) $(LOG_DRIVER) --test-name \"$$f\" \\\n\t--log-file $$b.log --trs-file $$b.trs \\\n\t$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \\\n\t\"$$tst\" $(AM_TESTS_FD_REDIRECT)\ntest_xcoff_64.log: test_xcoff_64$(EXEEXT)\n\t@p='test_xcoff_64$(EXEEXT)'; \\\n\tb='test_xcoff_64'; \\\n\t$(am__check_pre) $(LOG_DRIVER) --test-name \"$$f\" \\\n\t--log-file $$b.log --trs-file $$b.trs \\\n\t$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \\\n\t\"$$tst\" $(AM_TESTS_FD_REDIRECT)\ntest_pecoff.log: test_pecoff$(EXEEXT)\n\t@p='test_pecoff$(EXEEXT)'; \\\n\tb='test_pecoff'; \\\n\t$(am__check_pre) $(LOG_DRIVER) --test-name \"$$f\" \\\n\t--log-file $$b.log --trs-file $$b.trs \\\n\t$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \\\n\t\"$$tst\" $(AM_TESTS_FD_REDIRECT)\ntest_unknown.log: test_unknown$(EXEEXT)\n\t@p='test_unknown$(EXEEXT)'; \\\n\tb='test_unknown'; \\\n\t$(am__check_pre) $(LOG_DRIVER) --test-name \"$$f\" \\\n\t--log-file $$b.log --trs-file $$b.trs \\\n\t$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \\\n\t\"$$tst\" $(AM_TESTS_FD_REDIRECT)\nunittest.log: unittest$(EXEEXT)\n\t@p='unittest$(EXEEXT)'; \\\n\tb='unittest'; \\\n\t$(am__check_pre) $(LOG_DRIVER) --test-name \"$$f\" \\\n\t--log-file $$b.log --trs-file $$b.trs \\\n\t$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \\\n\t\"$$tst\" $(AM_TESTS_FD_REDIRECT)\nunittest_alloc.log: unittest_alloc$(EXEEXT)\n\t@p='unittest_alloc$(EXEEXT)'; \\\n\tb='unittest_alloc'; \\\n\t$(am__check_pre) $(LOG_DRIVER) --test-name \"$$f\" \\\n\t--log-file $$b.log --trs-file $$b.trs \\\n\t$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \\\n\t\"$$tst\" $(AM_TESTS_FD_REDIRECT)\nbtest.log: btest$(EXEEXT)\n\t@p='btest$(EXEEXT)'; \\\n\tb='btest'; \\\n\t$(am__check_pre) $(LOG_DRIVER) --test-name \"$$f\" \\\n\t--log-file $$b.log --trs-file $$b.trs \\\n\t$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \\\n\t\"$$tst\" $(AM_TESTS_FD_REDIRECT)\nbtest_lto.log: btest_lto$(EXEEXT)\n\t@p='btest_lto$(EXEEXT)'; \\\n\tb='btest_lto'; \\\n\t$(am__check_pre) $(LOG_DRIVER) --test-name \"$$f\" \\\n\t--log-file $$b.log --trs-file $$b.trs \\\n\t$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \\\n\t\"$$tst\" $(AM_TESTS_FD_REDIRECT)\nbtest_alloc.log: btest_alloc$(EXEEXT)\n\t@p='btest_alloc$(EXEEXT)'; \\\n\tb='btest_alloc'; \\\n\t$(am__check_pre) $(LOG_DRIVER) --test-name \"$$f\" \\\n\t--log-file $$b.log --trs-file $$b.trs \\\n\t$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \\\n\t\"$$tst\" $(AM_TESTS_FD_REDIRECT)\nstest.log: stest$(EXEEXT)\n\t@p='stest$(EXEEXT)'; \\\n\tb='stest'; \\\n\t$(am__check_pre) $(LOG_DRIVER) --test-name \"$$f\" \\\n\t--log-file $$b.log --trs-file $$b.trs \\\n\t$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \\\n\t\"$$tst\" $(AM_TESTS_FD_REDIRECT)\nstest_alloc.log: stest_alloc$(EXEEXT)\n\t@p='stest_alloc$(EXEEXT)'; \\\n\tb='stest_alloc'; \\\n\t$(am__check_pre) $(LOG_DRIVER) --test-name \"$$f\" \\\n\t--log-file $$b.log --trs-file $$b.trs \\\n\t$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \\\n\t\"$$tst\" $(AM_TESTS_FD_REDIRECT)\nztest.log: ztest$(EXEEXT)\n\t@p='ztest$(EXEEXT)'; \\\n\tb='ztest'; \\\n\t$(am__check_pre) $(LOG_DRIVER) --test-name \"$$f\" \\\n\t--log-file $$b.log --trs-file $$b.trs \\\n\t$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \\\n\t\"$$tst\" $(AM_TESTS_FD_REDIRECT)\nztest_alloc.log: ztest_alloc$(EXEEXT)\n\t@p='ztest_alloc$(EXEEXT)'; \\\n\tb='ztest_alloc'; \\\n\t$(am__check_pre) $(LOG_DRIVER) --test-name \"$$f\" \\\n\t--log-file $$b.log --trs-file $$b.trs \\\n\t$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \\\n\t\"$$tst\" $(AM_TESTS_FD_REDIRECT)\nzstdtest.log: zstdtest$(EXEEXT)\n\t@p='zstdtest$(EXEEXT)'; \\\n\tb='zstdtest'; \\\n\t$(am__check_pre) $(LOG_DRIVER) --test-name \"$$f\" \\\n\t--log-file $$b.log --trs-file $$b.trs \\\n\t$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \\\n\t\"$$tst\" $(AM_TESTS_FD_REDIRECT)\nzstdtest_alloc.log: zstdtest_alloc$(EXEEXT)\n\t@p='zstdtest_alloc$(EXEEXT)'; \\\n\tb='zstdtest_alloc'; \\\n\t$(am__check_pre) $(LOG_DRIVER) --test-name \"$$f\" \\\n\t--log-file $$b.log --trs-file $$b.trs \\\n\t$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \\\n\t\"$$tst\" $(AM_TESTS_FD_REDIRECT)\nedtest.log: edtest$(EXEEXT)\n\t@p='edtest$(EXEEXT)'; \\\n\tb='edtest'; \\\n\t$(am__check_pre) $(LOG_DRIVER) --test-name \"$$f\" \\\n\t--log-file $$b.log --trs-file $$b.trs \\\n\t$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \\\n\t\"$$tst\" $(AM_TESTS_FD_REDIRECT)\nedtest_alloc.log: edtest_alloc$(EXEEXT)\n\t@p='edtest_alloc$(EXEEXT)'; \\\n\tb='edtest_alloc'; \\\n\t$(am__check_pre) $(LOG_DRIVER) --test-name \"$$f\" \\\n\t--log-file $$b.log --trs-file $$b.trs \\\n\t$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \\\n\t\"$$tst\" $(AM_TESTS_FD_REDIRECT)\nttest.log: ttest$(EXEEXT)\n\t@p='ttest$(EXEEXT)'; \\\n\tb='ttest'; \\\n\t$(am__check_pre) $(LOG_DRIVER) --test-name \"$$f\" \\\n\t--log-file $$b.log --trs-file $$b.trs \\\n\t$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \\\n\t\"$$tst\" $(AM_TESTS_FD_REDIRECT)\nttest_alloc.log: ttest_alloc$(EXEEXT)\n\t@p='ttest_alloc$(EXEEXT)'; \\\n\tb='ttest_alloc'; \\\n\t$(am__check_pre) $(LOG_DRIVER) --test-name \"$$f\" \\\n\t--log-file $$b.log --trs-file $$b.trs \\\n\t$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \\\n\t\"$$tst\" $(AM_TESTS_FD_REDIRECT)\nctestg.log: ctestg$(EXEEXT)\n\t@p='ctestg$(EXEEXT)'; \\\n\tb='ctestg'; \\\n\t$(am__check_pre) $(LOG_DRIVER) --test-name \"$$f\" \\\n\t--log-file $$b.log --trs-file $$b.trs \\\n\t$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \\\n\t\"$$tst\" $(AM_TESTS_FD_REDIRECT)\nctestg_alloc.log: ctestg_alloc$(EXEEXT)\n\t@p='ctestg_alloc$(EXEEXT)'; \\\n\tb='ctestg_alloc'; \\\n\t$(am__check_pre) $(LOG_DRIVER) --test-name \"$$f\" \\\n\t--log-file $$b.log --trs-file $$b.trs \\\n\t$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \\\n\t\"$$tst\" $(AM_TESTS_FD_REDIRECT)\nctesta.log: ctesta$(EXEEXT)\n\t@p='ctesta$(EXEEXT)'; \\\n\tb='ctesta'; \\\n\t$(am__check_pre) $(LOG_DRIVER) --test-name \"$$f\" \\\n\t--log-file $$b.log --trs-file $$b.trs \\\n\t$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \\\n\t\"$$tst\" $(AM_TESTS_FD_REDIRECT)\nctesta_alloc.log: ctesta_alloc$(EXEEXT)\n\t@p='ctesta_alloc$(EXEEXT)'; \\\n\tb='ctesta_alloc'; \\\n\t$(am__check_pre) $(LOG_DRIVER) --test-name \"$$f\" \\\n\t--log-file $$b.log --trs-file $$b.trs \\\n\t$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \\\n\t\"$$tst\" $(AM_TESTS_FD_REDIRECT)\nctestzstd.log: ctestzstd$(EXEEXT)\n\t@p='ctestzstd$(EXEEXT)'; \\\n\tb='ctestzstd'; \\\n\t$(am__check_pre) $(LOG_DRIVER) --test-name \"$$f\" \\\n\t--log-file $$b.log --trs-file $$b.trs \\\n\t$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \\\n\t\"$$tst\" $(AM_TESTS_FD_REDIRECT)\nctestzstd_alloc.log: ctestzstd_alloc$(EXEEXT)\n\t@p='ctestzstd_alloc$(EXEEXT)'; \\\n\tb='ctestzstd_alloc'; \\\n\t$(am__check_pre) $(LOG_DRIVER) --test-name \"$$f\" \\\n\t--log-file $$b.log --trs-file $$b.trs \\\n\t$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \\\n\t\"$$tst\" $(AM_TESTS_FD_REDIRECT)\ndwarf5.log: dwarf5$(EXEEXT)\n\t@p='dwarf5$(EXEEXT)'; \\\n\tb='dwarf5'; \\\n\t$(am__check_pre) $(LOG_DRIVER) --test-name \"$$f\" \\\n\t--log-file $$b.log --trs-file $$b.trs \\\n\t$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \\\n\t\"$$tst\" $(AM_TESTS_FD_REDIRECT)\ndwarf5_alloc.log: dwarf5_alloc$(EXEEXT)\n\t@p='dwarf5_alloc$(EXEEXT)'; \\\n\tb='dwarf5_alloc'; \\\n\t$(am__check_pre) $(LOG_DRIVER) --test-name \"$$f\" \\\n\t--log-file $$b.log --trs-file $$b.trs \\\n\t$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \\\n\t\"$$tst\" $(AM_TESTS_FD_REDIRECT)\nmtest.log: mtest$(EXEEXT)\n\t@p='mtest$(EXEEXT)'; \\\n\tb='mtest'; \\\n\t$(am__check_pre) $(LOG_DRIVER) --test-name \"$$f\" \\\n\t--log-file $$b.log --trs-file $$b.trs \\\n\t$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \\\n\t\"$$tst\" $(AM_TESTS_FD_REDIRECT)\nxztest.log: xztest$(EXEEXT)\n\t@p='xztest$(EXEEXT)'; \\\n\tb='xztest'; \\\n\t$(am__check_pre) $(LOG_DRIVER) --test-name \"$$f\" \\\n\t--log-file $$b.log --trs-file $$b.trs \\\n\t$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \\\n\t\"$$tst\" $(AM_TESTS_FD_REDIRECT)\nxztest_alloc.log: xztest_alloc$(EXEEXT)\n\t@p='xztest_alloc$(EXEEXT)'; \\\n\tb='xztest_alloc'; \\\n\t$(am__check_pre) $(LOG_DRIVER) --test-name \"$$f\" \\\n\t--log-file $$b.log --trs-file $$b.trs \\\n\t$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \\\n\t\"$$tst\" $(AM_TESTS_FD_REDIRECT)\n.test.log:\n\t@p='$<'; \\\n\t$(am__set_b); \\\n\t$(am__check_pre) $(TEST_LOG_DRIVER) --test-name \"$$f\" \\\n\t--log-file $$b.log --trs-file $$b.trs \\\n\t$(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \\\n\t\"$$tst\" $(AM_TESTS_FD_REDIRECT)\n@am__EXEEXT_TRUE@.test$(EXEEXT).log:\n@am__EXEEXT_TRUE@\t@p='$<'; \\\n@am__EXEEXT_TRUE@\t$(am__set_b); \\\n@am__EXEEXT_TRUE@\t$(am__check_pre) $(TEST_LOG_DRIVER) --test-name \"$$f\" \\\n@am__EXEEXT_TRUE@\t--log-file $$b.log --trs-file $$b.trs \\\n@am__EXEEXT_TRUE@\t$(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \\\n@am__EXEEXT_TRUE@\t\"$$tst\" $(AM_TESTS_FD_REDIRECT)\ncheck-am: all-am\n\t$(MAKE) $(AM_MAKEFLAGS) $(check_LTLIBRARIES) $(check_PROGRAMS) \\\n\t  $(check_DATA)\n\t$(MAKE) $(AM_MAKEFLAGS) check-TESTS\ncheck: check-am\nall-am: Makefile $(LTLIBRARIES) $(HEADERS) config.h\ninstalldirs:\n\tfor dir in \"$(DESTDIR)$(libdir)\" \"$(DESTDIR)$(includedir)\"; do \\\n\t  test -z \"$$dir\" || $(MKDIR_P) \"$$dir\"; \\\n\tdone\ninstall: install-am\ninstall-exec: install-exec-am\ninstall-data: install-data-am\nuninstall: uninstall-am\n\ninstall-am: all-am\n\t@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am\n\ninstallcheck: installcheck-am\ninstall-strip:\n\tif test -z '$(STRIP)'; then \\\n\t  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM=\"$(INSTALL_STRIP_PROGRAM)\" \\\n\t    install_sh_PROGRAM=\"$(INSTALL_STRIP_PROGRAM)\" INSTALL_STRIP_FLAG=-s \\\n\t      install; \\\n\telse \\\n\t  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM=\"$(INSTALL_STRIP_PROGRAM)\" \\\n\t    install_sh_PROGRAM=\"$(INSTALL_STRIP_PROGRAM)\" INSTALL_STRIP_FLAG=-s \\\n\t    \"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'\" install; \\\n\tfi\nmostlyclean-generic:\n\t-test -z \"$(TEST_LOGS)\" || rm -f $(TEST_LOGS)\n\t-test -z \"$(TEST_LOGS:.log=.trs)\" || rm -f $(TEST_LOGS:.log=.trs)\n\t-test -z \"$(TEST_SUITE_LOG)\" || rm -f $(TEST_SUITE_LOG)\n\nclean-generic:\n\t-test -z \"$(CLEANFILES)\" || rm -f $(CLEANFILES)\n\ndistclean-generic:\n\t-test -z \"$(CONFIG_CLEAN_FILES)\" || rm -f $(CONFIG_CLEAN_FILES)\n\t-test . = \"$(srcdir)\" || test -z \"$(CONFIG_CLEAN_VPATH_FILES)\" || rm -f $(CONFIG_CLEAN_VPATH_FILES)\n\nmaintainer-clean-generic:\n\t@echo \"This command is intended for maintainers to use\"\n\t@echo \"it deletes files that may require special tools to rebuild.\"\nclean: clean-am\n\nclean-am: clean-checkLTLIBRARIES clean-checkPROGRAMS clean-generic \\\n\tclean-libLTLIBRARIES clean-libtool clean-local mostlyclean-am\n\ndistclean: distclean-am\n\t-rm -f $(am__CONFIG_DISTCLEAN_FILES)\n\t-rm -f Makefile\ndistclean-am: clean-am distclean-compile distclean-generic \\\n\tdistclean-hdr distclean-libtool distclean-tags\n\ndvi: dvi-am\n\ndvi-am:\n\nhtml: html-am\n\nhtml-am:\n\ninfo: info-am\n\ninfo-am:\n\ninstall-data-am: install-includeHEADERS\n\ninstall-dvi: install-dvi-am\n\ninstall-dvi-am:\n\ninstall-exec-am: install-libLTLIBRARIES\n\ninstall-html: install-html-am\n\ninstall-html-am:\n\ninstall-info: install-info-am\n\ninstall-info-am:\n\ninstall-man:\n\ninstall-pdf: install-pdf-am\n\ninstall-pdf-am:\n\ninstall-ps: install-ps-am\n\ninstall-ps-am:\n\ninstallcheck-am:\n\nmaintainer-clean: maintainer-clean-am\n\t-rm -f $(am__CONFIG_DISTCLEAN_FILES)\n\t-rm -rf $(top_srcdir)/autom4te.cache\n\t-rm -f Makefile\nmaintainer-clean-am: distclean-am maintainer-clean-generic\n\nmostlyclean: mostlyclean-am\n\nmostlyclean-am: mostlyclean-compile mostlyclean-generic \\\n\tmostlyclean-libtool\n\npdf: pdf-am\n\npdf-am:\n\nps: ps-am\n\nps-am:\n\nuninstall-am: uninstall-includeHEADERS uninstall-libLTLIBRARIES\n\n.MAKE: all check-am install-am install-strip\n\n.PHONY: CTAGS GTAGS TAGS all all-am am--refresh check check-TESTS \\\n\tcheck-am clean clean-checkLTLIBRARIES clean-checkPROGRAMS \\\n\tclean-cscope clean-generic clean-libLTLIBRARIES clean-libtool \\\n\tclean-local cscope cscopelist-am ctags ctags-am distclean \\\n\tdistclean-compile distclean-generic distclean-hdr \\\n\tdistclean-libtool distclean-tags dvi dvi-am html html-am info \\\n\tinfo-am install install-am install-data install-data-am \\\n\tinstall-dvi install-dvi-am install-exec install-exec-am \\\n\tinstall-html install-html-am install-includeHEADERS \\\n\tinstall-info install-info-am install-libLTLIBRARIES \\\n\tinstall-man install-pdf install-pdf-am install-ps \\\n\tinstall-ps-am install-strip installcheck installcheck-am \\\n\tinstalldirs maintainer-clean maintainer-clean-generic \\\n\tmostlyclean mostlyclean-compile mostlyclean-generic \\\n\tmostlyclean-libtool pdf pdf-am ps ps-am recheck tags tags-am \\\n\tuninstall uninstall-am uninstall-includeHEADERS \\\n\tuninstall-libLTLIBRARIES\n\n.PRECIOUS: Makefile\n\n\n@USE_DSYMUTIL_TRUE@%.dSYM: %\n@USE_DSYMUTIL_TRUE@\t$(DSYMUTIL) $<\n\n@HAVE_ELF_TRUE@@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@elf_for_test.c: elf.c\n@HAVE_ELF_TRUE@@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@\tSEARCH='^#define SYSTEM_BUILD_ID_DIR.*$$'; \\\n@HAVE_ELF_TRUE@@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@\tREPLACE=\"#define SYSTEM_BUILD_ID_DIR \\\"$(TEST_BUILD_ID_DIR)\\\"\"; \\\n@HAVE_ELF_TRUE@@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@\t$(SED) \"s%$$SEARCH%$$REPLACE%\" \\\n@HAVE_ELF_TRUE@@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@\t\t$< \\\n@HAVE_ELF_TRUE@@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@\t\t> $@.tmp\n@HAVE_ELF_TRUE@@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@\tmv $@.tmp $@\n\n@NATIVE_TRUE@elf_%.c: elf.c\n@NATIVE_TRUE@\tnlinit=`echo 'nl=\"'; echo '\"'`; eval \"$$nlinit\"; \\\n@NATIVE_TRUE@\tSEARCH='#error \"Unknown BACKTRACE_ELF_SIZE\"'; \\\n@NATIVE_TRUE@\tREPLACE=\"#undef BACKTRACE_ELF_SIZE\\\\$${nl}#define BACKTRACE_ELF_SIZE\"; \\\n@NATIVE_TRUE@\t$(SED) \"s/^$$SEARCH\\$$/$$REPLACE $*/\" \\\n@NATIVE_TRUE@\t\t$< \\\n@NATIVE_TRUE@\t\t> $@.tmp\n@NATIVE_TRUE@\tmv $@.tmp $@\n\n@NATIVE_TRUE@xcoff_%.c: xcoff.c\n@NATIVE_TRUE@\tnlinit=`echo 'nl=\"'; echo '\"'`; eval \"$$nlinit\"; \\\n@NATIVE_TRUE@\tSEARCH='#error \"Unknown BACKTRACE_XCOFF_SIZE\"'; \\\n@NATIVE_TRUE@\tREPLACE=\"#undef BACKTRACE_XCOFF_SIZE\\\\$${nl}#define BACKTRACE_XCOFF_SIZE\"; \\\n@NATIVE_TRUE@\t$(SED) \"s/^$$SEARCH\\$$/$$REPLACE $*/\" \\\n@NATIVE_TRUE@\t\t$< \\\n@NATIVE_TRUE@\t\t> $@.tmp\n@NATIVE_TRUE@\tmv $@.tmp $@\n\n@NATIVE_TRUE@instrumented_alloc.lo: alloc.c\n\n@NATIVE_TRUE@allocfail.sh: allocfail\n\n@HAVE_DWZ_TRUE@@NATIVE_TRUE@%_dwz: %\n@HAVE_DWZ_TRUE@@NATIVE_TRUE@\trm -f $@ $@_common.debug\n@HAVE_DWZ_TRUE@@NATIVE_TRUE@\tcp $< $@_1\n@HAVE_DWZ_TRUE@@NATIVE_TRUE@\tcp $< $@_2\n@HAVE_DWZ_TRUE@@NATIVE_TRUE@\tif $(DWZ) -m $@_common.debug $@_1 $@_2; then \\\n@HAVE_DWZ_TRUE@@NATIVE_TRUE@\t  rm -f $@_2; \\\n@HAVE_DWZ_TRUE@@NATIVE_TRUE@\t  mv $@_1 $@; \\\n@HAVE_DWZ_TRUE@@NATIVE_TRUE@\telse \\\n@HAVE_DWZ_TRUE@@NATIVE_TRUE@\t  echo \"Ignoring dwz errors, assuming that test passes\"; \\\n@HAVE_DWZ_TRUE@@NATIVE_TRUE@\t  cp $< $@; \\\n@HAVE_DWZ_TRUE@@NATIVE_TRUE@\tfi\n\n@NATIVE_TRUE@edtest2_build.c: gen_edtest2_build; @true\n@NATIVE_TRUE@gen_edtest2_build: $(srcdir)/edtest2.c\n@NATIVE_TRUE@\tcat $(srcdir)/edtest2.c > tmp-edtest2_build.c\n@NATIVE_TRUE@\t$(SHELL) $(srcdir)/move-if-change tmp-edtest2_build.c edtest2_build.c\n@NATIVE_TRUE@\techo timestamp > $@\n\n@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@%_gnudebuglink: %\n@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@\t$(OBJCOPY) --only-keep-debug $< $@.debug\n@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@\t$(OBJCOPY) --strip-debug --add-gnu-debuglink=$@.debug $< $@\n\n@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@%_gnudebuglinkfull: %\n@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@\t$(OBJCOPY) --only-keep-debug $< $@.debug\n@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@\t$(OBJCOPY) --strip-all --add-gnu-debuglink=$@.debug $< $@\n\n@NATIVE_TRUE@%_buildid: %\n@NATIVE_TRUE@\t./install-debuginfo-for-buildid.sh \\\n@NATIVE_TRUE@\t  \"$(TEST_BUILD_ID_DIR)\" \\\n@NATIVE_TRUE@\t  $<\n@NATIVE_TRUE@\t$(OBJCOPY) --strip-debug $< $@\n\n@NATIVE_TRUE@%_buildidfull: %\n@NATIVE_TRUE@\t./install-debuginfo-for-buildid.sh \\\n@NATIVE_TRUE@\t  \"$(TEST_BUILD_ID_DIR)\" \\\n@NATIVE_TRUE@\t  $<\n@NATIVE_TRUE@\t$(OBJCOPY) --strip-all $< $@\n\n@HAVE_MINIDEBUG_TRUE@@NATIVE_TRUE@%_minidebug: %\n@HAVE_MINIDEBUG_TRUE@@NATIVE_TRUE@\t$(NM) -D $< -P --defined-only | $(AWK) '{ print $$1 }' | sort > $<.dsyms\n@HAVE_MINIDEBUG_TRUE@@NATIVE_TRUE@\t$(NM) $< -P --defined-only | $(AWK) '{ if ($$2 == \"T\" || $$2 == \"t\" || $$2 == \"D\") print $$1 }' | sort > $<.fsyms\n@HAVE_MINIDEBUG_TRUE@@NATIVE_TRUE@\t$(COMM) -13 $<.dsyms $<.fsyms > $<.keepsyms\n@HAVE_MINIDEBUG_TRUE@@NATIVE_TRUE@\t$(OBJCOPY) --only-keep-debug $< $<.dbg\n@HAVE_MINIDEBUG_TRUE@@NATIVE_TRUE@\t$(OBJCOPY) -S --remove-section .gdb_index --remove-section .comment --keep-symbols=$<.keepsyms $<.dbg $<.mdbg\n@HAVE_MINIDEBUG_TRUE@@NATIVE_TRUE@\t$(OBJCOPY) --strip-all --remove-section ..comment $< $<.strip\n@HAVE_MINIDEBUG_TRUE@@NATIVE_TRUE@\trm -f $<.mdbg.xz\n@HAVE_MINIDEBUG_TRUE@@NATIVE_TRUE@\t$(XZ) $<.mdbg\n@HAVE_MINIDEBUG_TRUE@@NATIVE_TRUE@\t$(OBJCOPY) --add-section .gnu_debugdata=$<.mdbg.xz $<.strip\n@HAVE_MINIDEBUG_TRUE@@NATIVE_TRUE@\tmv $<.strip $@\n\n# minidebug2 is like minidebug but also adds the gnu_debugdata section\n# to the debug file, and uses a build ID file.  There is no reason to do\n# this but it was causing an infinite recursion.\n@HAVE_BUILDID_TRUE@@HAVE_ELF_TRUE@@HAVE_MINIDEBUG_TRUE@@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@%_minidebug2: %\n@HAVE_BUILDID_TRUE@@HAVE_ELF_TRUE@@HAVE_MINIDEBUG_TRUE@@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@\t$(NM) -D $< -P --defined-only | $(AWK) '{ print $$1 }' | sort > $<.dsyms2\n@HAVE_BUILDID_TRUE@@HAVE_ELF_TRUE@@HAVE_MINIDEBUG_TRUE@@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@\t$(NM) $< -P --defined-only | $(AWK) '{ if ($$2 == \"T\" || $$2 == \"t\" || $$2 == \"D\") print $$1 }' | sort > $<.fsyms2\n@HAVE_BUILDID_TRUE@@HAVE_ELF_TRUE@@HAVE_MINIDEBUG_TRUE@@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@\t$(COMM) -13 $<.dsyms2 $<.fsyms2 > $<.keepsyms2\n@HAVE_BUILDID_TRUE@@HAVE_ELF_TRUE@@HAVE_MINIDEBUG_TRUE@@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@\t$(OBJCOPY) --only-keep-debug $< $<.dbg2\n@HAVE_BUILDID_TRUE@@HAVE_ELF_TRUE@@HAVE_MINIDEBUG_TRUE@@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@\t$(OBJCOPY) -S --remove-section .gdb_index --remove-section .comment --keep-symbols=$<.keepsyms2 $<.dbg2 $<.mdbg2\n@HAVE_BUILDID_TRUE@@HAVE_ELF_TRUE@@HAVE_MINIDEBUG_TRUE@@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@\t$(OBJCOPY) --strip-all --remove-section ..comment $< $<.strip2\n@HAVE_BUILDID_TRUE@@HAVE_ELF_TRUE@@HAVE_MINIDEBUG_TRUE@@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@\trm -f $<.mdbg2.xz\n@HAVE_BUILDID_TRUE@@HAVE_ELF_TRUE@@HAVE_MINIDEBUG_TRUE@@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@\t$(XZ) $<.mdbg2\n@HAVE_BUILDID_TRUE@@HAVE_ELF_TRUE@@HAVE_MINIDEBUG_TRUE@@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@\t$(OBJCOPY) --add-section .gnu_debugdata=$<.mdbg2.xz $<.dbg2\n@HAVE_BUILDID_TRUE@@HAVE_ELF_TRUE@@HAVE_MINIDEBUG_TRUE@@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@\t$(OBJCOPY) --add-section .gnu_debugdata=$<.mdbg2.xz $<.strip2\n@HAVE_BUILDID_TRUE@@HAVE_ELF_TRUE@@HAVE_MINIDEBUG_TRUE@@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@\t$(SHELL) ./install-debuginfo-for-buildid.sh $(TEST_BUILD_ID_DIR) $<.dbg2\n@HAVE_BUILDID_TRUE@@HAVE_ELF_TRUE@@HAVE_MINIDEBUG_TRUE@@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@\tmv $<.strip2 $@\n\nclean-local:\n\t-rm -rf usr\n\n# We can't use automake's automatic dependency tracking, because it\n# breaks when using bootstrap-lean.  Automatic dependency tracking\n# with GCC bootstrap will cause some of the objects to depend on\n# header files in prev-gcc/include, e.g., stddef.h and stdarg.h.  When\n# using bootstrap-lean, prev-gcc is removed after each stage.  When\n# running \"make install\", those header files will be gone, causing the\n# library to be rebuilt at install time.  That may not succeed.\n\n# These manual dependencies do not include dependencies on unwind.h,\n# even though that is part of GCC, because where to find it depends on\n# whether we are being built as a host library or a target library.\n\nalloc.lo: config.h backtrace.h internal.h\nbacktrace.lo: config.h backtrace.h internal.h\nbtest.lo: filenames.h backtrace.h backtrace-supported.h\ndwarf.lo: config.h filenames.h backtrace.h internal.h\nelf.lo: config.h backtrace.h internal.h debuginfod_support.h\nfileline.lo: config.h backtrace.h internal.h\nmacho.lo: config.h backtrace.h internal.h\nmmap.lo: config.h backtrace.h internal.h\nmmapio.lo: config.h backtrace.h internal.h\nmtest.lo: backtrace.h backtrace-supported.h\nnounwind.lo: config.h internal.h\npecoff.lo: config.h backtrace.h internal.h\nposix.lo: config.h backtrace.h internal.h\nprint.lo: config.h backtrace.h internal.h\nread.lo: config.h backtrace.h internal.h\nsimple.lo: config.h backtrace.h internal.h\nsort.lo: config.h backtrace.h internal.h\nstest.lo: config.h backtrace.h internal.h\nstate.lo: config.h backtrace.h backtrace-supported.h internal.h\nunknown.lo: config.h backtrace.h internal.h\nxcoff.lo: config.h backtrace.h internal.h\nxztest.lo: config.h backtrace.h backtrace-supported.h internal.h testlib.h\nztest.lo: config.h backtrace.h backtrace-supported.h internal.h testlib.h\n\n# Tell versions [3.59,3.63) of GNU make to not export all variables.\n# Otherwise a system limit (for SysV at least) may be exceeded.\n.NOEXPORT:\n"
  },
  {
    "path": "src/vendor/libbacktrace/README.md",
    "content": "# libbacktrace\nA C library that may be linked into a C/C++ program to produce symbolic backtraces\n\nInitially written by Ian Lance Taylor <iant@golang.org>.\n\nThis is version 1.0.\nIt is likely that this will always be version 1.0.\n\nThe libbacktrace library may be linked into a program or library and\nused to produce symbolic backtraces.\nSample uses would be to print a detailed backtrace when an error\noccurs or to gather detailed profiling information.\n\nIn general the functions provided by this library are async-signal-safe,\nmeaning that they may be safely called from a signal handler.\nThat said, on systems that use `dl_iterate_phdr`, such as GNU/Linux,\ngitthe first call to a libbacktrace function will call `dl_iterate_phdr`,\nwhich is not in general async-signal-safe.  Therefore, programs\nthat call libbacktrace from a signal handler should ensure that they\nmake an initial call from outside of a signal handler.\nSimilar considerations apply when arranging to call libbacktrace\nfrom within malloc; `dl_iterate_phdr` can also call malloc,\nso make an initial call to a libbacktrace function outside of\nmalloc before trying to call libbacktrace functions within malloc.\n\nThe libbacktrace library is provided under a BSD license.\nSee the source files for the exact license text.\n\nThe public functions are declared and documented in the header file\nbacktrace.h, which should be #include'd by a user of the library.\n\nBuilding libbacktrace will generate a file backtrace-supported.h,\nwhich a user of the library may use to determine whether backtraces\nwill work.\nSee the source file backtrace-supported.h.in for the macros that it\ndefines.\n\nAs of July 2024, libbacktrace supports ELF, PE/COFF, Mach-O, and\nXCOFF executables with DWARF debugging information.\nIn other words, it supports GNU/Linux, *BSD, macOS, Windows, and AIX.\nThe library is written to make it straightforward to add support for\nother object file and debugging formats.\n\nThe library relies on the C++ unwind API defined at\nhttps://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html\nThis API is provided by GCC and clang.\n"
  },
  {
    "path": "src/vendor/libbacktrace/aclocal.m4",
    "content": "# generated automatically by aclocal 1.15.1 -*- Autoconf -*-\n\n# Copyright (C) 1996-2017 Free Software Foundation, Inc.\n\n# This file is free software; the Free Software Foundation\n# gives unlimited permission to copy and/or distribute it,\n# with or without modifications, as long as this notice is preserved.\n\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY, to the extent permitted by law; without\n# even the implied warranty of MERCHANTABILITY or FITNESS FOR A\n# PARTICULAR PURPOSE.\n\nm4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])])\nm4_ifndef([AC_AUTOCONF_VERSION],\n  [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl\nm4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],,\n[m4_warning([this file was generated for autoconf 2.69.\nYou have another version of autoconf.  It may work, but is not guaranteed to.\nIf you have problems, you may need to regenerate the build system entirely.\nTo do so, use the procedure documented by the package, typically 'autoreconf'.])])\n\n# Copyright (C) 2002-2017 Free Software Foundation, Inc.\n#\n# This file is free software; the Free Software Foundation\n# gives unlimited permission to copy and/or distribute it,\n# with or without modifications, as long as this notice is preserved.\n\n# AM_AUTOMAKE_VERSION(VERSION)\n# ----------------------------\n# Automake X.Y traces this macro to ensure aclocal.m4 has been\n# generated from the m4 files accompanying Automake X.Y.\n# (This private macro should not be called outside this file.)\nAC_DEFUN([AM_AUTOMAKE_VERSION],\n[am__api_version='1.15'\ndnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to\ndnl require some minimum version.  Point them to the right macro.\nm4_if([$1], [1.15.1], [],\n      [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl\n])\n\n# _AM_AUTOCONF_VERSION(VERSION)\n# -----------------------------\n# aclocal traces this macro to find the Autoconf version.\n# This is a private macro too.  Using m4_define simplifies\n# the logic in aclocal, which can simply ignore this definition.\nm4_define([_AM_AUTOCONF_VERSION], [])\n\n# AM_SET_CURRENT_AUTOMAKE_VERSION\n# -------------------------------\n# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.\n# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.\nAC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],\n[AM_AUTOMAKE_VERSION([1.15.1])dnl\nm4_ifndef([AC_AUTOCONF_VERSION],\n  [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl\n_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])\n\n# AM_AUX_DIR_EXPAND                                         -*- Autoconf -*-\n\n# Copyright (C) 2001-2017 Free Software Foundation, Inc.\n#\n# This file is free software; the Free Software Foundation\n# gives unlimited permission to copy and/or distribute it,\n# with or without modifications, as long as this notice is preserved.\n\n# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets\n# $ac_aux_dir to '$srcdir/foo'.  In other projects, it is set to\n# '$srcdir', '$srcdir/..', or '$srcdir/../..'.\n#\n# Of course, Automake must honor this variable whenever it calls a\n# tool from the auxiliary directory.  The problem is that $srcdir (and\n# therefore $ac_aux_dir as well) can be either absolute or relative,\n# depending on how configure is run.  This is pretty annoying, since\n# it makes $ac_aux_dir quite unusable in subdirectories: in the top\n# source directory, any form will work fine, but in subdirectories a\n# relative path needs to be adjusted first.\n#\n# $ac_aux_dir/missing\n#    fails when called from a subdirectory if $ac_aux_dir is relative\n# $top_srcdir/$ac_aux_dir/missing\n#    fails if $ac_aux_dir is absolute,\n#    fails when called from a subdirectory in a VPATH build with\n#          a relative $ac_aux_dir\n#\n# The reason of the latter failure is that $top_srcdir and $ac_aux_dir\n# are both prefixed by $srcdir.  In an in-source build this is usually\n# harmless because $srcdir is '.', but things will broke when you\n# start a VPATH build or use an absolute $srcdir.\n#\n# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,\n# iff we strip the leading $srcdir from $ac_aux_dir.  That would be:\n#   am_aux_dir='\\$(top_srcdir)/'`expr \"$ac_aux_dir\" : \"$srcdir//*\\(.*\\)\"`\n# and then we would define $MISSING as\n#   MISSING=\"\\${SHELL} $am_aux_dir/missing\"\n# This will work as long as MISSING is not called from configure, because\n# unfortunately $(top_srcdir) has no meaning in configure.\n# However there are other variables, like CC, which are often used in\n# configure, and could therefore not use this \"fixed\" $ac_aux_dir.\n#\n# Another solution, used here, is to always expand $ac_aux_dir to an\n# absolute PATH.  The drawback is that using absolute paths prevent a\n# configured tree to be moved without reconfiguration.\n\nAC_DEFUN([AM_AUX_DIR_EXPAND],\n[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl\n# Expand $ac_aux_dir to an absolute path.\nam_aux_dir=`cd \"$ac_aux_dir\" && pwd`\n])\n\n# AM_CONDITIONAL                                            -*- Autoconf -*-\n\n# Copyright (C) 1997-2017 Free Software Foundation, Inc.\n#\n# This file is free software; the Free Software Foundation\n# gives unlimited permission to copy and/or distribute it,\n# with or without modifications, as long as this notice is preserved.\n\n# AM_CONDITIONAL(NAME, SHELL-CONDITION)\n# -------------------------------------\n# Define a conditional.\nAC_DEFUN([AM_CONDITIONAL],\n[AC_PREREQ([2.52])dnl\n m4_if([$1], [TRUE],  [AC_FATAL([$0: invalid condition: $1])],\n       [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl\nAC_SUBST([$1_TRUE])dnl\nAC_SUBST([$1_FALSE])dnl\n_AM_SUBST_NOTMAKE([$1_TRUE])dnl\n_AM_SUBST_NOTMAKE([$1_FALSE])dnl\nm4_define([_AM_COND_VALUE_$1], [$2])dnl\nif $2; then\n  $1_TRUE=\n  $1_FALSE='#'\nelse\n  $1_TRUE='#'\n  $1_FALSE=\nfi\nAC_CONFIG_COMMANDS_PRE(\n[if test -z \"${$1_TRUE}\" && test -z \"${$1_FALSE}\"; then\n  AC_MSG_ERROR([[conditional \"$1\" was never defined.\nUsually this means the macro was only invoked conditionally.]])\nfi])])\n\n# Do all the work for Automake.                             -*- Autoconf -*-\n\n# Copyright (C) 1996-2017 Free Software Foundation, Inc.\n#\n# This file is free software; the Free Software Foundation\n# gives unlimited permission to copy and/or distribute it,\n# with or without modifications, as long as this notice is preserved.\n\n# This macro actually does too much.  Some checks are only needed if\n# your package does certain things.  But this isn't really a big deal.\n\ndnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O.\nm4_define([AC_PROG_CC],\nm4_defn([AC_PROG_CC])\n[_AM_PROG_CC_C_O\n])\n\n# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])\n# AM_INIT_AUTOMAKE([OPTIONS])\n# -----------------------------------------------\n# The call with PACKAGE and VERSION arguments is the old style\n# call (pre autoconf-2.50), which is being phased out.  PACKAGE\n# and VERSION should now be passed to AC_INIT and removed from\n# the call to AM_INIT_AUTOMAKE.\n# We support both call styles for the transition.  After\n# the next Automake release, Autoconf can make the AC_INIT\n# arguments mandatory, and then we can depend on a new Autoconf\n# release and drop the old call support.\nAC_DEFUN([AM_INIT_AUTOMAKE],\n[AC_PREREQ([2.65])dnl\ndnl Autoconf wants to disallow AM_ names.  We explicitly allow\ndnl the ones we care about.\nm4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl\nAC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl\nAC_REQUIRE([AC_PROG_INSTALL])dnl\nif test \"`cd $srcdir && pwd`\" != \"`pwd`\"; then\n  # Use -I$(srcdir) only when $(srcdir) != ., so that make's output\n  # is not polluted with repeated \"-I.\"\n  AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl\n  # test to see if srcdir already configured\n  if test -f $srcdir/config.status; then\n    AC_MSG_ERROR([source directory already configured; run \"make distclean\" there first])\n  fi\nfi\n\n# test whether we have cygpath\nif test -z \"$CYGPATH_W\"; then\n  if (cygpath --version) >/dev/null 2>/dev/null; then\n    CYGPATH_W='cygpath -w'\n  else\n    CYGPATH_W=echo\n  fi\nfi\nAC_SUBST([CYGPATH_W])\n\n# Define the identity of the package.\ndnl Distinguish between old-style and new-style calls.\nm4_ifval([$2],\n[AC_DIAGNOSE([obsolete],\n             [$0: two- and three-arguments forms are deprecated.])\nm4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl\n AC_SUBST([PACKAGE], [$1])dnl\n AC_SUBST([VERSION], [$2])],\n[_AM_SET_OPTIONS([$1])dnl\ndnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT.\nm4_if(\n  m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]),\n  [ok:ok],,\n  [m4_fatal([AC_INIT should be called with package and version arguments])])dnl\n AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl\n AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl\n\n_AM_IF_OPTION([no-define],,\n[AC_DEFINE_UNQUOTED([PACKAGE], [\"$PACKAGE\"], [Name of package])\n AC_DEFINE_UNQUOTED([VERSION], [\"$VERSION\"], [Version number of package])])dnl\n\n# Some tools Automake needs.\nAC_REQUIRE([AM_SANITY_CHECK])dnl\nAC_REQUIRE([AC_ARG_PROGRAM])dnl\nAM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}])\nAM_MISSING_PROG([AUTOCONF], [autoconf])\nAM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}])\nAM_MISSING_PROG([AUTOHEADER], [autoheader])\nAM_MISSING_PROG([MAKEINFO], [makeinfo])\nAC_REQUIRE([AM_PROG_INSTALL_SH])dnl\nAC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl\nAC_REQUIRE([AC_PROG_MKDIR_P])dnl\n# For better backward compatibility.  To be removed once Automake 1.9.x\n# dies out for good.  For more background, see:\n# <http://lists.gnu.org/archive/html/automake/2012-07/msg00001.html>\n# <http://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>\nAC_SUBST([mkdir_p], ['$(MKDIR_P)'])\n# We need awk for the \"check\" target (and possibly the TAP driver).  The\n# system \"awk\" is bad on some platforms.\nAC_REQUIRE([AC_PROG_AWK])dnl\nAC_REQUIRE([AC_PROG_MAKE_SET])dnl\nAC_REQUIRE([AM_SET_LEADING_DOT])dnl\n_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])],\n\t      [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])],\n\t\t\t     [_AM_PROG_TAR([v7])])])\n_AM_IF_OPTION([no-dependencies],,\n[AC_PROVIDE_IFELSE([AC_PROG_CC],\n\t\t  [_AM_DEPENDENCIES([CC])],\n\t\t  [m4_define([AC_PROG_CC],\n\t\t\t     m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl\nAC_PROVIDE_IFELSE([AC_PROG_CXX],\n\t\t  [_AM_DEPENDENCIES([CXX])],\n\t\t  [m4_define([AC_PROG_CXX],\n\t\t\t     m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl\nAC_PROVIDE_IFELSE([AC_PROG_OBJC],\n\t\t  [_AM_DEPENDENCIES([OBJC])],\n\t\t  [m4_define([AC_PROG_OBJC],\n\t\t\t     m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl\nAC_PROVIDE_IFELSE([AC_PROG_OBJCXX],\n\t\t  [_AM_DEPENDENCIES([OBJCXX])],\n\t\t  [m4_define([AC_PROG_OBJCXX],\n\t\t\t     m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl\n])\nAC_REQUIRE([AM_SILENT_RULES])dnl\ndnl The testsuite driver may need to know about EXEEXT, so add the\ndnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen.  This\ndnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below.\nAC_CONFIG_COMMANDS_PRE(dnl\n[m4_provide_if([_AM_COMPILER_EXEEXT],\n  [AM_CONDITIONAL([am__EXEEXT], [test -n \"$EXEEXT\"])])])dnl\n\n# POSIX will say in a future version that running \"rm -f\" with no argument\n# is OK; and we want to be able to make that assumption in our Makefile\n# recipes.  So use an aggressive probe to check that the usage we want is\n# actually supported \"in the wild\" to an acceptable degree.\n# See automake bug#10828.\n# To make any issue more visible, cause the running configure to be aborted\n# by default if the 'rm' program in use doesn't match our expectations; the\n# user can still override this though.\nif rm -f && rm -fr && rm -rf; then : OK; else\n  cat >&2 <<'END'\nOops!\n\nYour 'rm' program seems unable to run without file operands specified\non the command line, even when the '-f' option is present.  This is contrary\nto the behaviour of most rm programs out there, and not conforming with\nthe upcoming POSIX standard: <http://austingroupbugs.net/view.php?id=542>\n\nPlease tell bug-automake@gnu.org about your system, including the value\nof your $PATH and any error possibly output before this message.  This\ncan help us improve future automake versions.\n\nEND\n  if test x\"$ACCEPT_INFERIOR_RM_PROGRAM\" = x\"yes\"; then\n    echo 'Configuration will proceed anyway, since you have set the' >&2\n    echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to \"yes\"' >&2\n    echo >&2\n  else\n    cat >&2 <<'END'\nAborting the configuration process, to ensure you take notice of the issue.\n\nYou can download and install GNU coreutils to get an 'rm' implementation\nthat behaves properly: <http://www.gnu.org/software/coreutils/>.\n\nIf you want to complete the configuration process using your problematic\n'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM\nto \"yes\", and re-run configure.\n\nEND\n    AC_MSG_ERROR([Your 'rm' program is bad, sorry.])\n  fi\nfi\ndnl The trailing newline in this macro's definition is deliberate, for\ndnl backward compatibility and to allow trailing 'dnl'-style comments\ndnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841.\n])\n\ndnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion.  Do not\ndnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further\ndnl mangled by Autoconf and run in a shell conditional statement.\nm4_define([_AC_COMPILER_EXEEXT],\nm4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])])\n\n# When config.status generates a header, we must update the stamp-h file.\n# This file resides in the same directory as the config header\n# that is generated.  The stamp files are numbered to have different names.\n\n# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the\n# loop where config.status creates the headers, so we can generate\n# our stamp files there.\nAC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK],\n[# Compute $1's index in $config_headers.\n_am_arg=$1\n_am_stamp_count=1\nfor _am_header in $config_headers :; do\n  case $_am_header in\n    $_am_arg | $_am_arg:* )\n      break ;;\n    * )\n      _am_stamp_count=`expr $_am_stamp_count + 1` ;;\n  esac\ndone\necho \"timestamp for $_am_arg\" >`AS_DIRNAME([\"$_am_arg\"])`/stamp-h[]$_am_stamp_count])\n\n# Copyright (C) 2001-2017 Free Software Foundation, Inc.\n#\n# This file is free software; the Free Software Foundation\n# gives unlimited permission to copy and/or distribute it,\n# with or without modifications, as long as this notice is preserved.\n\n# AM_PROG_INSTALL_SH\n# ------------------\n# Define $install_sh.\nAC_DEFUN([AM_PROG_INSTALL_SH],\n[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl\nif test x\"${install_sh+set}\" != xset; then\n  case $am_aux_dir in\n  *\\ * | *\\\t*)\n    install_sh=\"\\${SHELL} '$am_aux_dir/install-sh'\" ;;\n  *)\n    install_sh=\"\\${SHELL} $am_aux_dir/install-sh\"\n  esac\nfi\nAC_SUBST([install_sh])])\n\n# Add --enable-maintainer-mode option to configure.         -*- Autoconf -*-\n# From Jim Meyering\n\n# Copyright (C) 1996-2017 Free Software Foundation, Inc.\n#\n# This file is free software; the Free Software Foundation\n# gives unlimited permission to copy and/or distribute it,\n# with or without modifications, as long as this notice is preserved.\n\n# AM_MAINTAINER_MODE([DEFAULT-MODE])\n# ----------------------------------\n# Control maintainer-specific portions of Makefiles.\n# Default is to disable them, unless 'enable' is passed literally.\n# For symmetry, 'disable' may be passed as well.  Anyway, the user\n# can override the default with the --enable/--disable switch.\nAC_DEFUN([AM_MAINTAINER_MODE],\n[m4_case(m4_default([$1], [disable]),\n       [enable], [m4_define([am_maintainer_other], [disable])],\n       [disable], [m4_define([am_maintainer_other], [enable])],\n       [m4_define([am_maintainer_other], [enable])\n        m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])])\nAC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles])\n  dnl maintainer-mode's default is 'disable' unless 'enable' is passed\n  AC_ARG_ENABLE([maintainer-mode],\n    [AS_HELP_STRING([--]am_maintainer_other[-maintainer-mode],\n      am_maintainer_other[ make rules and dependencies not useful\n      (and sometimes confusing) to the casual installer])],\n    [USE_MAINTAINER_MODE=$enableval],\n    [USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes]))\n  AC_MSG_RESULT([$USE_MAINTAINER_MODE])\n  AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes])\n  MAINT=$MAINTAINER_MODE_TRUE\n  AC_SUBST([MAINT])dnl\n]\n)\n\n# Fake the existence of programs that GNU maintainers use.  -*- Autoconf -*-\n\n# Copyright (C) 1997-2017 Free Software Foundation, Inc.\n#\n# This file is free software; the Free Software Foundation\n# gives unlimited permission to copy and/or distribute it,\n# with or without modifications, as long as this notice is preserved.\n\n# AM_MISSING_PROG(NAME, PROGRAM)\n# ------------------------------\nAC_DEFUN([AM_MISSING_PROG],\n[AC_REQUIRE([AM_MISSING_HAS_RUN])\n$1=${$1-\"${am_missing_run}$2\"}\nAC_SUBST($1)])\n\n# AM_MISSING_HAS_RUN\n# ------------------\n# Define MISSING if not defined so far and test if it is modern enough.\n# If it is, set am_missing_run to use it, otherwise, to nothing.\nAC_DEFUN([AM_MISSING_HAS_RUN],\n[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl\nAC_REQUIRE_AUX_FILE([missing])dnl\nif test x\"${MISSING+set}\" != xset; then\n  case $am_aux_dir in\n  *\\ * | *\\\t*)\n    MISSING=\"\\${SHELL} \\\"$am_aux_dir/missing\\\"\" ;;\n  *)\n    MISSING=\"\\${SHELL} $am_aux_dir/missing\" ;;\n  esac\nfi\n# Use eval to expand $SHELL\nif eval \"$MISSING --is-lightweight\"; then\n  am_missing_run=\"$MISSING \"\nelse\n  am_missing_run=\n  AC_MSG_WARN(['missing' script is too old or missing])\nfi\n])\n\n# Helper functions for option handling.                     -*- Autoconf -*-\n\n# Copyright (C) 2001-2017 Free Software Foundation, Inc.\n#\n# This file is free software; the Free Software Foundation\n# gives unlimited permission to copy and/or distribute it,\n# with or without modifications, as long as this notice is preserved.\n\n# _AM_MANGLE_OPTION(NAME)\n# -----------------------\nAC_DEFUN([_AM_MANGLE_OPTION],\n[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])])\n\n# _AM_SET_OPTION(NAME)\n# --------------------\n# Set option NAME.  Presently that only means defining a flag for this option.\nAC_DEFUN([_AM_SET_OPTION],\n[m4_define(_AM_MANGLE_OPTION([$1]), [1])])\n\n# _AM_SET_OPTIONS(OPTIONS)\n# ------------------------\n# OPTIONS is a space-separated list of Automake options.\nAC_DEFUN([_AM_SET_OPTIONS],\n[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])])\n\n# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET])\n# -------------------------------------------\n# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.\nAC_DEFUN([_AM_IF_OPTION],\n[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])\n\n# Copyright (C) 1999-2017 Free Software Foundation, Inc.\n#\n# This file is free software; the Free Software Foundation\n# gives unlimited permission to copy and/or distribute it,\n# with or without modifications, as long as this notice is preserved.\n\n# _AM_PROG_CC_C_O\n# ---------------\n# Like AC_PROG_CC_C_O, but changed for automake.  We rewrite AC_PROG_CC\n# to automatically call this.\nAC_DEFUN([_AM_PROG_CC_C_O],\n[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl\nAC_REQUIRE_AUX_FILE([compile])dnl\nAC_LANG_PUSH([C])dnl\nAC_CACHE_CHECK(\n  [whether $CC understands -c and -o together],\n  [am_cv_prog_cc_c_o],\n  [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])])\n  # Make sure it works both with $CC and with simple cc.\n  # Following AC_PROG_CC_C_O, we do the test twice because some\n  # compilers refuse to overwrite an existing .o file with -o,\n  # though they will create one.\n  am_cv_prog_cc_c_o=yes\n  for am_i in 1 2; do\n    if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \\\n         && test -f conftest2.$ac_objext; then\n      : OK\n    else\n      am_cv_prog_cc_c_o=no\n      break\n    fi\n  done\n  rm -f core conftest*\n  unset am_i])\nif test \"$am_cv_prog_cc_c_o\" != yes; then\n   # Losing compiler, so override with the script.\n   # FIXME: It is wrong to rewrite CC.\n   # But if we don't then we get into trouble of one sort or another.\n   # A longer-term fix would be to have automake use am__CC in this case,\n   # and then we could set am__CC=\"\\$(top_srcdir)/compile \\$(CC)\"\n   CC=\"$am_aux_dir/compile $CC\"\nfi\nAC_LANG_POP([C])])\n\n# For backward compatibility.\nAC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])])\n\n# Copyright (C) 2001-2017 Free Software Foundation, Inc.\n#\n# This file is free software; the Free Software Foundation\n# gives unlimited permission to copy and/or distribute it,\n# with or without modifications, as long as this notice is preserved.\n\n# AM_RUN_LOG(COMMAND)\n# -------------------\n# Run COMMAND, save the exit status in ac_status, and log it.\n# (This has been adapted from Autoconf's _AC_RUN_LOG macro.)\nAC_DEFUN([AM_RUN_LOG],\n[{ echo \"$as_me:$LINENO: $1\" >&AS_MESSAGE_LOG_FD\n   ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD\n   ac_status=$?\n   echo \"$as_me:$LINENO: \\$? = $ac_status\" >&AS_MESSAGE_LOG_FD\n   (exit $ac_status); }])\n\n# Check to make sure that the build environment is sane.    -*- Autoconf -*-\n\n# Copyright (C) 1996-2017 Free Software Foundation, Inc.\n#\n# This file is free software; the Free Software Foundation\n# gives unlimited permission to copy and/or distribute it,\n# with or without modifications, as long as this notice is preserved.\n\n# AM_SANITY_CHECK\n# ---------------\nAC_DEFUN([AM_SANITY_CHECK],\n[AC_MSG_CHECKING([whether build environment is sane])\n# Reject unsafe characters in $srcdir or the absolute working directory\n# name.  Accept space and tab only in the latter.\nam_lf='\n'\ncase `pwd` in\n  *[[\\\\\\\"\\#\\$\\&\\'\\`$am_lf]]*)\n    AC_MSG_ERROR([unsafe absolute working directory name]);;\nesac\ncase $srcdir in\n  *[[\\\\\\\"\\#\\$\\&\\'\\`$am_lf\\ \\\t]]*)\n    AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);;\nesac\n\n# Do 'set' in a subshell so we don't clobber the current shell's\n# arguments.  Must try -L first in case configure is actually a\n# symlink; some systems play weird games with the mod time of symlinks\n# (eg FreeBSD returns the mod time of the symlink's containing\n# directory).\nif (\n   am_has_slept=no\n   for am_try in 1 2; do\n     echo \"timestamp, slept: $am_has_slept\" > conftest.file\n     set X `ls -Lt \"$srcdir/configure\" conftest.file 2> /dev/null`\n     if test \"$[*]\" = \"X\"; then\n\t# -L didn't work.\n\tset X `ls -t \"$srcdir/configure\" conftest.file`\n     fi\n     if test \"$[*]\" != \"X $srcdir/configure conftest.file\" \\\n\t&& test \"$[*]\" != \"X conftest.file $srcdir/configure\"; then\n\n\t# If neither matched, then we have a broken ls.  This can happen\n\t# if, for instance, CONFIG_SHELL is bash and it inherits a\n\t# broken ls alias from the environment.  This has actually\n\t# happened.  Such a system could not be considered \"sane\".\n\tAC_MSG_ERROR([ls -t appears to fail.  Make sure there is not a broken\n  alias in your environment])\n     fi\n     if test \"$[2]\" = conftest.file || test $am_try -eq 2; then\n       break\n     fi\n     # Just in case.\n     sleep 1\n     am_has_slept=yes\n   done\n   test \"$[2]\" = conftest.file\n   )\nthen\n   # Ok.\n   :\nelse\n   AC_MSG_ERROR([newly created file is older than distributed files!\nCheck your system clock])\nfi\nAC_MSG_RESULT([yes])\n# If we didn't sleep, we still need to ensure time stamps of config.status and\n# generated files are strictly newer.\nam_sleep_pid=\nif grep 'slept: no' conftest.file >/dev/null 2>&1; then\n  ( sleep 1 ) &\n  am_sleep_pid=$!\nfi\nAC_CONFIG_COMMANDS_PRE(\n  [AC_MSG_CHECKING([that generated files are newer than configure])\n   if test -n \"$am_sleep_pid\"; then\n     # Hide warnings about reused PIDs.\n     wait $am_sleep_pid 2>/dev/null\n   fi\n   AC_MSG_RESULT([done])])\nrm -f conftest.file\n])\n\n# Copyright (C) 2009-2017 Free Software Foundation, Inc.\n#\n# This file is free software; the Free Software Foundation\n# gives unlimited permission to copy and/or distribute it,\n# with or without modifications, as long as this notice is preserved.\n\n# AM_SILENT_RULES([DEFAULT])\n# --------------------------\n# Enable less verbose build rules; with the default set to DEFAULT\n# (\"yes\" being less verbose, \"no\" or empty being verbose).\nAC_DEFUN([AM_SILENT_RULES],\n[AC_ARG_ENABLE([silent-rules], [dnl\nAS_HELP_STRING(\n  [--enable-silent-rules],\n  [less verbose build output (undo: \"make V=1\")])\nAS_HELP_STRING(\n  [--disable-silent-rules],\n  [verbose build output (undo: \"make V=0\")])dnl\n])\ncase $enable_silent_rules in @%:@ (((\n  yes) AM_DEFAULT_VERBOSITY=0;;\n   no) AM_DEFAULT_VERBOSITY=1;;\n    *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);;\nesac\ndnl\ndnl A few 'make' implementations (e.g., NonStop OS and NextStep)\ndnl do not support nested variable expansions.\ndnl See automake bug#9928 and bug#10237.\nam_make=${MAKE-make}\nAC_CACHE_CHECK([whether $am_make supports nested variables],\n   [am_cv_make_support_nested_variables],\n   [if AS_ECHO([['TRUE=$(BAR$(V))\nBAR0=false\nBAR1=true\nV=1\nam__doit:\n\t@$(TRUE)\n.PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then\n  am_cv_make_support_nested_variables=yes\nelse\n  am_cv_make_support_nested_variables=no\nfi])\nif test $am_cv_make_support_nested_variables = yes; then\n  dnl Using '$V' instead of '$(V)' breaks IRIX make.\n  AM_V='$(V)'\n  AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'\nelse\n  AM_V=$AM_DEFAULT_VERBOSITY\n  AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY\nfi\nAC_SUBST([AM_V])dnl\nAM_SUBST_NOTMAKE([AM_V])dnl\nAC_SUBST([AM_DEFAULT_V])dnl\nAM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl\nAC_SUBST([AM_DEFAULT_VERBOSITY])dnl\nAM_BACKSLASH='\\'\nAC_SUBST([AM_BACKSLASH])dnl\n_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl\n])\n\n# Copyright (C) 2001-2017 Free Software Foundation, Inc.\n#\n# This file is free software; the Free Software Foundation\n# gives unlimited permission to copy and/or distribute it,\n# with or without modifications, as long as this notice is preserved.\n\n# AM_PROG_INSTALL_STRIP\n# ---------------------\n# One issue with vendor 'install' (even GNU) is that you can't\n# specify the program used to strip binaries.  This is especially\n# annoying in cross-compiling environments, where the build's strip\n# is unlikely to handle the host's binaries.\n# Fortunately install-sh will honor a STRIPPROG variable, so we\n# always use install-sh in \"make install-strip\", and initialize\n# STRIPPROG with the value of the STRIP variable (set by the user).\nAC_DEFUN([AM_PROG_INSTALL_STRIP],\n[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl\n# Installed binaries are usually stripped using 'strip' when the user\n# run \"make install-strip\".  However 'strip' might not be the right\n# tool to use in cross-compilation environments, therefore Automake\n# will honor the 'STRIP' environment variable to overrule this program.\ndnl Don't test for $cross_compiling = yes, because it might be 'maybe'.\nif test \"$cross_compiling\" != no; then\n  AC_CHECK_TOOL([STRIP], [strip], :)\nfi\nINSTALL_STRIP_PROGRAM=\"\\$(install_sh) -c -s\"\nAC_SUBST([INSTALL_STRIP_PROGRAM])])\n\n# Copyright (C) 2006-2017 Free Software Foundation, Inc.\n#\n# This file is free software; the Free Software Foundation\n# gives unlimited permission to copy and/or distribute it,\n# with or without modifications, as long as this notice is preserved.\n\n# _AM_SUBST_NOTMAKE(VARIABLE)\n# ---------------------------\n# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in.\n# This macro is traced by Automake.\nAC_DEFUN([_AM_SUBST_NOTMAKE])\n\n# AM_SUBST_NOTMAKE(VARIABLE)\n# --------------------------\n# Public sister of _AM_SUBST_NOTMAKE.\nAC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])\n\n# Check how to create a tarball.                            -*- Autoconf -*-\n\n# Copyright (C) 2004-2017 Free Software Foundation, Inc.\n#\n# This file is free software; the Free Software Foundation\n# gives unlimited permission to copy and/or distribute it,\n# with or without modifications, as long as this notice is preserved.\n\n# _AM_PROG_TAR(FORMAT)\n# --------------------\n# Check how to create a tarball in format FORMAT.\n# FORMAT should be one of 'v7', 'ustar', or 'pax'.\n#\n# Substitute a variable $(am__tar) that is a command\n# writing to stdout a FORMAT-tarball containing the directory\n# $tardir.\n#     tardir=directory && $(am__tar) > result.tar\n#\n# Substitute a variable $(am__untar) that extract such\n# a tarball read from stdin.\n#     $(am__untar) < result.tar\n#\nAC_DEFUN([_AM_PROG_TAR],\n[# Always define AMTAR for backward compatibility.  Yes, it's still used\n# in the wild :-(  We should find a proper way to deprecate it ...\nAC_SUBST([AMTAR], ['$${TAR-tar}'])\n\n# We'll loop over all known methods to create a tar archive until one works.\n_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'\n\nm4_if([$1], [v7],\n  [am__tar='$${TAR-tar} chof - \"$$tardir\"' am__untar='$${TAR-tar} xf -'],\n\n  [m4_case([$1],\n    [ustar],\n     [# The POSIX 1988 'ustar' format is defined with fixed-size fields.\n      # There is notably a 21 bits limit for the UID and the GID.  In fact,\n      # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343\n      # and bug#13588).\n      am_max_uid=2097151 # 2^21 - 1\n      am_max_gid=$am_max_uid\n      # The $UID and $GID variables are not portable, so we need to resort\n      # to the POSIX-mandated id(1) utility.  Errors in the 'id' calls\n      # below are definitely unexpected, so allow the users to see them\n      # (that is, avoid stderr redirection).\n      am_uid=`id -u || echo unknown`\n      am_gid=`id -g || echo unknown`\n      AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format])\n      if test $am_uid -le $am_max_uid; then\n         AC_MSG_RESULT([yes])\n      else\n         AC_MSG_RESULT([no])\n         _am_tools=none\n      fi\n      AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format])\n      if test $am_gid -le $am_max_gid; then\n         AC_MSG_RESULT([yes])\n      else\n        AC_MSG_RESULT([no])\n        _am_tools=none\n      fi],\n\n  [pax],\n    [],\n\n  [m4_fatal([Unknown tar format])])\n\n  AC_MSG_CHECKING([how to create a $1 tar archive])\n\n  # Go ahead even if we have the value already cached.  We do so because we\n  # need to set the values for the 'am__tar' and 'am__untar' variables.\n  _am_tools=${am_cv_prog_tar_$1-$_am_tools}\n\n  for _am_tool in $_am_tools; do\n    case $_am_tool in\n    gnutar)\n      for _am_tar in tar gnutar gtar; do\n        AM_RUN_LOG([$_am_tar --version]) && break\n      done\n      am__tar=\"$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - \"'\"$$tardir\"'\n      am__tar_=\"$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - \"'\"$tardir\"'\n      am__untar=\"$_am_tar -xf -\"\n      ;;\n    plaintar)\n      # Must skip GNU tar: if it does not support --format= it doesn't create\n      # ustar tarball either.\n      (tar --version) >/dev/null 2>&1 && continue\n      am__tar='tar chf - \"$$tardir\"'\n      am__tar_='tar chf - \"$tardir\"'\n      am__untar='tar xf -'\n      ;;\n    pax)\n      am__tar='pax -L -x $1 -w \"$$tardir\"'\n      am__tar_='pax -L -x $1 -w \"$tardir\"'\n      am__untar='pax -r'\n      ;;\n    cpio)\n      am__tar='find \"$$tardir\" -print | cpio -o -H $1 -L'\n      am__tar_='find \"$tardir\" -print | cpio -o -H $1 -L'\n      am__untar='cpio -i -H $1 -d'\n      ;;\n    none)\n      am__tar=false\n      am__tar_=false\n      am__untar=false\n      ;;\n    esac\n\n    # If the value was cached, stop now.  We just wanted to have am__tar\n    # and am__untar set.\n    test -n \"${am_cv_prog_tar_$1}\" && break\n\n    # tar/untar a dummy directory, and stop if the command works.\n    rm -rf conftest.dir\n    mkdir conftest.dir\n    echo GrepMe > conftest.dir/file\n    AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])\n    rm -rf conftest.dir\n    if test -s conftest.tar; then\n      AM_RUN_LOG([$am__untar <conftest.tar])\n      AM_RUN_LOG([cat conftest.dir/file])\n      grep GrepMe conftest.dir/file >/dev/null 2>&1 && break\n    fi\n  done\n  rm -rf conftest.dir\n\n  AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])\n  AC_MSG_RESULT([$am_cv_prog_tar_$1])])\n\nAC_SUBST([am__tar])\nAC_SUBST([am__untar])\n]) # _AM_PROG_TAR\n\nm4_include([config/lead-dot.m4])\nm4_include([config/libtool.m4])\nm4_include([config/ltoptions.m4])\nm4_include([config/ltsugar.m4])\nm4_include([config/ltversion.m4])\nm4_include([config/lt~obsolete.m4])\nm4_include([config/multi.m4])\nm4_include([config/override.m4])\nm4_include([config/unwind_ipinfo.m4])\nm4_include([config/warnings.m4])\n"
  },
  {
    "path": "src/vendor/libbacktrace/alloc.c",
    "content": "/* alloc.c -- Memory allocation without mmap.\n   Copyright (C) 2012-2024 Free Software Foundation, Inc.\n   Written by Ian Lance Taylor, Google.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n    (1) Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n\n    (2) Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in\n    the documentation and/or other materials provided with the\n    distribution.\n\n    (3) The name of the author may not be used to\n    endorse or promote products derived from this software without\n    specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\nIMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,\nINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\nHOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\nIN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGE.  */\n\n#include \"config.h\"\n\n#include <errno.h>\n#include <stdlib.h>\n#include <sys/types.h>\n\n#include \"backtrace.h\"\n#include \"internal.h\"\n\n/* Allocation routines to use on systems that do not support anonymous\n   mmap.  This implementation just uses malloc, which means that the\n   backtrace functions may not be safely invoked from a signal\n   handler.  */\n\n/* Allocate memory like malloc.  If ERROR_CALLBACK is NULL, don't\n   report an error.  */\n\nvoid *\nbacktrace_alloc (struct backtrace_state *state ATTRIBUTE_UNUSED,\n\t\t size_t size, backtrace_error_callback error_callback,\n\t\t void *data)\n{\n  void *ret;\n\n  ret = malloc (size);\n  if (ret == NULL)\n    {\n      if (error_callback)\n\terror_callback (data, \"malloc\", errno);\n    }\n  return ret;\n}\n\n/* Free memory.  */\n\nvoid\nbacktrace_free (struct backtrace_state *state ATTRIBUTE_UNUSED,\n\t\tvoid *p, size_t size ATTRIBUTE_UNUSED,\n\t\tbacktrace_error_callback error_callback ATTRIBUTE_UNUSED,\n\t\tvoid *data ATTRIBUTE_UNUSED)\n{\n  free (p);\n}\n\n/* Grow VEC by SIZE bytes.  */\n\nvoid *\nbacktrace_vector_grow (struct backtrace_state *state ATTRIBUTE_UNUSED,\n\t\t       size_t size, backtrace_error_callback error_callback,\n\t\t       void *data, struct backtrace_vector *vec)\n{\n  void *ret;\n\n  if (size > vec->alc)\n    {\n      size_t alc;\n      void *base;\n\n      if (vec->size == 0)\n\talc = 32 * size;\n      else if (vec->size >= 4096)\n\talc = vec->size + 4096;\n      else\n\talc = 2 * vec->size;\n\n      if (alc < vec->size + size)\n\talc = vec->size + size;\n\n      base = realloc (vec->base, alc);\n      if (base == NULL)\n\t{\n\t  error_callback (data, \"realloc\", errno);\n\t  return NULL;\n\t}\n\n      vec->base = base;\n      vec->alc = alc - vec->size;\n    }\n\n  ret = (char *) vec->base + vec->size;\n  vec->size += size;\n  vec->alc -= size;\n  return ret;\n}\n\n/* Finish the current allocation on VEC.  */\n\nvoid *\nbacktrace_vector_finish (struct backtrace_state *state,\n\t\t\t struct backtrace_vector *vec,\n\t\t\t backtrace_error_callback error_callback,\n\t\t\t void *data)\n{\n  void *ret;\n\n  /* With this allocator we call realloc in backtrace_vector_grow,\n     which means we can't easily reuse the memory here.  So just\n     release it.  */\n  if (!backtrace_vector_release (state, vec, error_callback, data))\n    return NULL;\n  ret = vec->base;\n  vec->base = NULL;\n  vec->size = 0;\n  vec->alc = 0;\n  return ret;\n}\n\n/* Release any extra space allocated for VEC.  */\n\nint\nbacktrace_vector_release (struct backtrace_state *state ATTRIBUTE_UNUSED,\n\t\t\t  struct backtrace_vector *vec,\n\t\t\t  backtrace_error_callback error_callback,\n\t\t\t  void *data)\n{\n  vec->alc = 0;\n\n  if (vec->size == 0)\n    {\n      /* As of C17, realloc with size 0 is marked as an obsolescent feature, use\n\t free instead.  */\n      free (vec->base);\n      vec->base = NULL;\n      return 1;\n    }\n\n  vec->base = realloc (vec->base, vec->size);\n  if (vec->base == NULL)\n    {\n      error_callback (data, \"realloc\", errno);\n      return 0;\n    }\n\n  return 1;\n}\n"
  },
  {
    "path": "src/vendor/libbacktrace/allocfail.c",
    "content": "/* allocfail.c -- Test for libbacktrace library\n   Copyright (C) 2018-2024 Free Software Foundation, Inc.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n    (1) Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n\n    (2) Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in\n    the documentation and/or other materials provided with the\n    distribution.\n\n    (3) The name of the author may not be used to\n    endorse or promote products derived from this software without\n    specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\nIMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,\nINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\nHOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\nIN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGE.  */\n\n#include <assert.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <unistd.h>\n\n#include \"filenames.h\"\n\n#include \"backtrace.h\"\n#include \"backtrace-supported.h\"\n\n#include \"testlib.h\"\n\nextern uint64_t get_nr_allocs (void);\nextern void set_fail_at_alloc (uint64_t);\nextern int at_fail_alloc_p (void);\n\nstatic int test1 (void) __attribute__ ((noinline, unused));\nstatic int f2 (int) __attribute__ ((noinline));\nstatic int f3 (int, int) __attribute__ ((noinline));\n\nstatic unsigned callback_errors = 0;\n\nstatic void\nerror_callback_full (void *vdata ATTRIBUTE_UNUSED,\n\t\t     const char *msg ATTRIBUTE_UNUSED,\n\t\t     int errnum ATTRIBUTE_UNUSED)\n{\n  if (at_fail_alloc_p ())\n    {\n      set_fail_at_alloc (0);\n      return;\n    }\n\n  callback_errors++;\n}\n\nstatic int\ncallback_full (void *vdata ATTRIBUTE_UNUSED, uintptr_t pc ATTRIBUTE_UNUSED,\n\t      const char *filename ATTRIBUTE_UNUSED,\n\t      int lineno ATTRIBUTE_UNUSED,\n\t      const char *function ATTRIBUTE_UNUSED)\n{\n\n  return 0;\n}\n\nstatic int\ntest1 (void)\n{\n  return f2 (__LINE__) + 1;\n}\n\nstatic int\nf2 (int f1line)\n{\n  return f3 (f1line, __LINE__) + 2;\n}\n\nstatic int\nf3 (int f1line ATTRIBUTE_UNUSED, int f2line ATTRIBUTE_UNUSED)\n{\n  int i;\n\n  i = backtrace_full (state, 0, callback_full, error_callback_full, NULL);\n\n  if (i != 0)\n    {\n      fprintf (stderr, \"test1: unexpected return value %d\\n\", i);\n      ++failures;\n    }\n\n  if (callback_errors)\n      ++failures;\n\n  return failures;\n}\n\n/* Run all the tests.  */\n\nint\nmain (int argc, char **argv)\n{\n  uint64_t fail_at = 0;\n\n  if (argc == 2)\n    {\n      fail_at = atoi (argv[1]);\n      set_fail_at_alloc (fail_at);\n    }\n\n  state = backtrace_create_state (argv[0], BACKTRACE_SUPPORTS_THREADS,\n\t\t\t\t  error_callback_full, NULL);\n  if (state == NULL)\n    exit (failures ? EXIT_FAILURE : EXIT_SUCCESS);\n\n#if BACKTRACE_SUPPORTED\n  test1 ();\n#endif\n\n  if (argc == 1)\n    fprintf (stderr, \"%llu\\n\", (long long unsigned) get_nr_allocs ());\n\n  exit (failures ? EXIT_FAILURE : EXIT_SUCCESS);\n}\n"
  },
  {
    "path": "src/vendor/libbacktrace/allocfail.sh",
    "content": "#!/bin/sh\n\n# allocfail.sh -- Test for libbacktrace library.\n# Copyright (C) 2018-2024 Free Software Foundation, Inc.\n\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions are\n# met:\n\n#     (1) Redistributions of source code must retain the above copyright\n#     notice, this list of conditions and the following disclaimer.\n\n#     (2) Redistributions in binary form must reproduce the above copyright\n#     notice, this list of conditions and the following disclaimer in\n#     the documentation and/or other materials provided with the\n#     distribution.\n\n#     (3) The name of the author may not be used to\n#     endorse or promote products derived from this software without\n#     specific prior written permission.\n\n# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n# DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,\n# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\n# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n# POSSIBILITY OF SUCH DAMAGE.\n\nset -e\n\nif [ ! -f ./allocfail ]; then\n    # Hard failure.\n    exit 99\nfi\n\nallocs=$(./allocfail 2>&1)\nif [ \"$allocs\" = \"\" ]; then\n    # Hard failure.\n    exit 99\nfi\n\n# This generates the following output:\n# ...\n# $ allocfail.sh\n# allocs: 80495\n# Status changed to 0 at 1\n# Status changed to 1 at 3\n# Status changed to 0 at 11\n# Status changed to 1 at 12\n# Status changed to 0 at 845\n# ...\n#\n# We have status 0 for an allocation failure at:\n# - 1 because backtrace_create_state handles failure robustly\n# - 2 because the fail switches backtrace_full to !can_alloc mode.\n# - 11 because failure of elf_open_debugfile_by_buildid does not generate an\n#   error callback beyond the one for the allocation failure itself.\n\necho \"allocs: $allocs\"\n\nstep=1\ni=1\npasses=0\nprev_status=-1\nwhile [ $i -le $allocs ]; do\n    if ./allocfail $i >/dev/null 2>&1; status=$?; then\n\ttrue\n    fi\n    if [ $status -gt 1 ]; then\n\techo \"Unallowed fail found: $i\"\n\t# Failure.\n\texit 1\n    fi\n\n    # The test-case would run too long if we would excercise all allocs.\n    # So, run with step 1 initially, and increase the step once we have 10\n    # subsequent passes, and drop back to step 1 once we encounter another\n    # failure.  This takes ~2.6 seconds on an i7-6600U CPU @ 2.60GHz.\n    if [ $status -eq 0 ]; then\n\tpasses=$(($passes + 1))\n\tif [ $passes -ge 10 ]; then\n\t    step=$((step * 10))\n\t    passes=0\n\tfi\n    elif [ $status -eq 1 ]; then\n\tpasses=0\n\tstep=1\n    fi\n\n    if [ $status -ne $prev_status ]; then\n\techo \"Status changed to $status at $i\"\n    fi\n    prev_status=$status\n\n    i=$(($i + $step))\ndone\n\n# Success.\nexit 0\n"
  },
  {
    "path": "src/vendor/libbacktrace/atomic.c",
    "content": "/* atomic.c -- Support for atomic functions if not present.\n   Copyright (C) 2013-2024 Free Software Foundation, Inc.\n   Written by Ian Lance Taylor, Google.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n    (1) Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n\n    (2) Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in\n    the documentation and/or other materials provided with the\n    distribution.\n\n    (3) The name of the author may not be used to\n    endorse or promote products derived from this software without\n    specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\nIMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,\nINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\nHOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\nIN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGE.  */\n\n#include \"config.h\"\n\n#include <sys/types.h>\n\n#include \"backtrace.h\"\n#include \"backtrace-supported.h\"\n#include \"internal.h\"\n\n/* This file holds implementations of the atomic functions that are\n   used if the host compiler has the sync functions but not the atomic\n   functions, as is true of versions of GCC before 4.7.  */\n\n#if !defined (HAVE_ATOMIC_FUNCTIONS) && defined (HAVE_SYNC_FUNCTIONS)\n\n/* Do an atomic load of a pointer.  */\n\nvoid *\nbacktrace_atomic_load_pointer (void *arg)\n{\n  void **pp;\n  void *p;\n\n  pp = (void **) arg;\n  p = *pp;\n  while (!__sync_bool_compare_and_swap (pp, p, p))\n    p = *pp;\n  return p;\n}\n\n/* Do an atomic load of an int.  */\n\nint\nbacktrace_atomic_load_int (int *p)\n{\n  int i;\n\n  i = *p;\n  while (!__sync_bool_compare_and_swap (p, i, i))\n    i = *p;\n  return i;\n}\n\n/* Do an atomic store of a pointer.  */\n\nvoid\nbacktrace_atomic_store_pointer (void *arg, void *p)\n{\n  void **pp;\n  void *old;\n\n  pp = (void **) arg;\n  old = *pp;\n  while (!__sync_bool_compare_and_swap (pp, old, p))\n    old = *pp;\n}\n\n/* Do an atomic store of a size_t value.  */\n\nvoid\nbacktrace_atomic_store_size_t (size_t *p, size_t v)\n{\n  size_t old;\n\n  old = *p;\n  while (!__sync_bool_compare_and_swap (p, old, v))\n    old = *p;\n}\n\n/* Do an atomic store of a int value.  */\n\nvoid\nbacktrace_atomic_store_int (int *p, int v)\n{\n  size_t old;\n\n  old = *p;\n  while (!__sync_bool_compare_and_swap (p, old, v))\n    old = *p;\n}\n\n#endif\n"
  },
  {
    "path": "src/vendor/libbacktrace/backtrace-supported.h.in",
    "content": "/* backtrace-supported.h.in -- Whether stack backtrace is supported.\n   Copyright (C) 2012-2024 Free Software Foundation, Inc.\n   Written by Ian Lance Taylor, Google.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n    (1) Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n\n    (2) Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in\n    the documentation and/or other materials provided with the\n    distribution.\n\n    (3) The name of the author may not be used to\n    endorse or promote products derived from this software without\n    specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\nIMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,\nINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\nHOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\nIN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGE.  */\n\n/* The file backtrace-supported.h.in is used by configure to generate\n   the file backtrace-supported.h.  The file backtrace-supported.h may\n   be #include'd to see whether the backtrace library will be able to\n   get a backtrace and produce symbolic information.  */\n\n\n/* BACKTRACE_SUPPORTED will be #define'd as 1 if the backtrace library\n   should work, 0 if it will not.  Libraries may #include this to make\n   other arrangements.  */\n\n#define BACKTRACE_SUPPORTED @BACKTRACE_SUPPORTED@\n\n/* BACKTRACE_USES_MALLOC will be #define'd as 1 if the backtrace\n   library will call malloc as it works, 0 if it will call mmap\n   instead.  This may be used to determine whether it is safe to call\n   the backtrace functions from a signal handler.  In general this\n   only applies to calls like backtrace and backtrace_pcinfo.  It does\n   not apply to backtrace_simple, which never calls malloc.  It does\n   not apply to backtrace_print, which always calls fprintf and\n   therefore malloc.  */\n\n#define BACKTRACE_USES_MALLOC @BACKTRACE_USES_MALLOC@\n\n/* BACKTRACE_SUPPORTS_THREADS will be #define'd as 1 if the backtrace\n   library is configured with threading support, 0 if not.  If this is\n   0, the threaded parameter to backtrace_create_state must be passed\n   as 0.  */\n\n#define BACKTRACE_SUPPORTS_THREADS @BACKTRACE_SUPPORTS_THREADS@\n\n/* BACKTRACE_SUPPORTS_DATA will be #defined'd as 1 if the backtrace_syminfo\n   will work for variables.  It will always work for functions.  */\n\n#define BACKTRACE_SUPPORTS_DATA @BACKTRACE_SUPPORTS_DATA@\n"
  },
  {
    "path": "src/vendor/libbacktrace/backtrace.c",
    "content": "/* backtrace.c -- Entry point for stack backtrace library.\n   Copyright (C) 2012-2024 Free Software Foundation, Inc.\n   Written by Ian Lance Taylor, Google.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n    (1) Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n\n    (2) Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in\n    the documentation and/or other materials provided with the\n    distribution.\n\n    (3) The name of the author may not be used to\n    endorse or promote products derived from this software without\n    specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\nIMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,\nINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\nHOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\nIN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGE.  */\n\n#include \"config.h\"\n\n#include <sys/types.h>\n\n#include \"unwind.h\"\n#include \"backtrace.h\"\n#include \"internal.h\"\n\n/* The main backtrace_full routine.  */\n\n/* Data passed through _Unwind_Backtrace.  */\n\nstruct backtrace_data\n{\n  /* Number of frames to skip.  */\n  int skip;\n  /* Library state.  */\n  struct backtrace_state *state;\n  /* Callback routine.  */\n  backtrace_full_callback callback;\n  /* Error callback routine.  */\n  backtrace_error_callback error_callback;\n  /* Data to pass to callback routines.  */\n  void *data;\n  /* Value to return from backtrace_full.  */\n  int ret;\n  /* Whether there is any memory available.  */\n  int can_alloc;\n};\n\n/* Unwind library callback routine.  This is passed to\n   _Unwind_Backtrace.  */\n\nstatic _Unwind_Reason_Code\nunwind (struct _Unwind_Context *context, void *vdata)\n{\n  struct backtrace_data *bdata = (struct backtrace_data *) vdata;\n  uintptr_t pc;\n  int ip_before_insn = 0;\n\n#ifdef HAVE_GETIPINFO\n  pc = _Unwind_GetIPInfo (context, &ip_before_insn);\n#else\n  pc = _Unwind_GetIP (context);\n#endif\n\n  if (bdata->skip > 0)\n    {\n      --bdata->skip;\n      return _URC_NO_REASON;\n    }\n\n  if (!ip_before_insn)\n    --pc;\n\n  if (!bdata->can_alloc)\n    bdata->ret = bdata->callback (bdata->data, pc, NULL, 0, NULL);\n  else\n    bdata->ret = backtrace_pcinfo (bdata->state, pc, bdata->callback,\n\t\t\t\t   bdata->error_callback, bdata->data);\n  if (bdata->ret != 0)\n    return _URC_END_OF_STACK;\n\n  return _URC_NO_REASON;\n}\n\n/* Get a stack backtrace.  */\n\nint __attribute__((noinline))\nbacktrace_full (struct backtrace_state *state, int skip,\n\t\tbacktrace_full_callback callback,\n\t\tbacktrace_error_callback error_callback, void *data)\n{\n  struct backtrace_data bdata;\n  void *p;\n\n  bdata.skip = skip + 1;\n  bdata.state = state;\n  bdata.callback = callback;\n  bdata.error_callback = error_callback;\n  bdata.data = data;\n  bdata.ret = 0;\n\n  /* If we can't allocate any memory at all, don't try to produce\n     file/line information.  */\n  p = backtrace_alloc (state, 4096, NULL, NULL);\n  if (p == NULL)\n    bdata.can_alloc = 0;\n  else\n    {\n      backtrace_free (state, p, 4096, NULL, NULL);\n      bdata.can_alloc = 1;\n    }\n\n  _Unwind_Backtrace (unwind, &bdata);\n  return bdata.ret;\n}\n"
  },
  {
    "path": "src/vendor/libbacktrace/backtrace.h",
    "content": "/* backtrace.h -- Public header file for stack backtrace library.\n   Copyright (C) 2012-2024 Free Software Foundation, Inc.\n   Written by Ian Lance Taylor, Google.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n    (1) Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n\n    (2) Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in\n    the documentation and/or other materials provided with the\n    distribution.\n\n    (3) The name of the author may not be used to\n    endorse or promote products derived from this software without\n    specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\nIMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,\nINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\nHOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\nIN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGE.  */\n\n#ifndef BACKTRACE_H\n#define BACKTRACE_H\n\n#include <stddef.h>\n#include <stdint.h>\n#include <stdio.h>\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* The backtrace state.  This struct is intentionally not defined in\n   the public interface.  */\n\nstruct backtrace_state;\n\n/* The type of the error callback argument to backtrace functions.\n   This function, if not NULL, will be called for certain error cases.\n   The DATA argument is passed to the function that calls this one.\n   The MSG argument is an error message.  The ERRNUM argument, if\n   greater than 0, holds an errno value.  The MSG buffer may become\n   invalid after this function returns.\n\n   As a special case, the ERRNUM argument will be passed as -1 if no\n   debug info can be found for the executable, or if the debug info\n   exists but has an unsupported version, but the function requires\n   debug info (e.g., backtrace_full, backtrace_pcinfo).  The MSG in\n   this case will be something along the lines of \"no debug info\".\n   Similarly, ERRNUM will be passed as -1 if there is no symbol table,\n   but the function requires a symbol table (e.g., backtrace_syminfo).\n   This may be used as a signal that some other approach should be\n   tried.  */\n\ntypedef void (*backtrace_error_callback) (void *data, const char *msg,\n\t\t\t\t\t  int errnum);\n\n/* Create state information for the backtrace routines.  This must be\n   called before any of the other routines, and its return value must\n   be passed to all of the other routines.  FILENAME is the path name\n   of the executable file; if it is NULL the library will try\n   system-specific path names.  If not NULL, FILENAME must point to a\n   permanent buffer.  If THREADED is non-zero the state may be\n   accessed by multiple threads simultaneously, and the library will\n   use appropriate atomic operations.  If THREADED is zero the state\n   may only be accessed by one thread at a time.  This returns a state\n   pointer on success, NULL on error.  If an error occurs, this will\n   call the ERROR_CALLBACK routine.\n\n   Calling this function allocates resources that cannot be freed.\n   There is no backtrace_free_state function.  The state is used to\n   cache information that is expensive to recompute.  Programs are\n   expected to call this function at most once and to save the return\n   value for all later calls to backtrace functions.  */\n\nextern struct backtrace_state *backtrace_create_state (\n    const char *filename, int threaded,\n    backtrace_error_callback error_callback, void *data);\n\n/* The type of the callback argument to the backtrace_full function.\n   DATA is the argument passed to backtrace_full.  PC is the program\n   counter.  FILENAME is the name of the file containing PC, or NULL\n   if not available.  LINENO is the line number in FILENAME containing\n   PC, or 0 if not available.  FUNCTION is the name of the function\n   containing PC, or NULL if not available.  This should return 0 to\n   continuing tracing.  The FILENAME and FUNCTION buffers may become\n   invalid after this function returns.  */\n\ntypedef int (*backtrace_full_callback) (void *data, uintptr_t pc,\n\t\t\t\t\tconst char *filename, int lineno,\n\t\t\t\t\tconst char *function);\n\n/* Get a full stack backtrace.  SKIP is the number of frames to skip;\n   passing 0 will start the trace with the function calling\n   backtrace_full.  DATA is passed to the callback routine.  If any\n   call to CALLBACK returns a non-zero value, the stack backtrace\n   stops, and backtrace returns that value; this may be used to limit\n   the number of stack frames desired.  If all calls to CALLBACK\n   return 0, backtrace returns 0.  The backtrace_full function will\n   make at least one call to either CALLBACK or ERROR_CALLBACK.  This\n   function requires debug info for the executable.  */\n\nextern int backtrace_full (struct backtrace_state *state, int skip,\n\t\t\t   backtrace_full_callback callback,\n\t\t\t   backtrace_error_callback error_callback,\n\t\t\t   void *data);\n\n/* The type of the callback argument to the backtrace_simple function.\n   DATA is the argument passed to simple_backtrace.  PC is the program\n   counter.  This should return 0 to continue tracing.  */\n\ntypedef int (*backtrace_simple_callback) (void *data, uintptr_t pc);\n\n/* Get a simple backtrace.  SKIP is the number of frames to skip, as\n   in backtrace.  DATA is passed to the callback routine.  If any call\n   to CALLBACK returns a non-zero value, the stack backtrace stops,\n   and backtrace_simple returns that value.  Otherwise\n   backtrace_simple returns 0.  The backtrace_simple function will\n   make at least one call to either CALLBACK or ERROR_CALLBACK.  This\n   function does not require any debug info for the executable.  */\n\nextern int backtrace_simple (struct backtrace_state *state, int skip,\n\t\t\t     backtrace_simple_callback callback,\n\t\t\t     backtrace_error_callback error_callback,\n\t\t\t     void *data);\n\n/* Print the current backtrace in a user readable format to a FILE.\n   SKIP is the number of frames to skip, as in backtrace_full.  Any\n   error messages are printed to stderr.  This function requires debug\n   info for the executable.  */\n\nextern void backtrace_print (struct backtrace_state *state, int skip, FILE *);\n\n/* Given PC, a program counter in the current program, call the\n   callback function with filename, line number, and function name\n   information.  This will normally call the callback function exactly\n   once.  However, if the PC happens to describe an inlined call, and\n   the debugging information contains the necessary information, then\n   this may call the callback function multiple times.  This will make\n   at least one call to either CALLBACK or ERROR_CALLBACK.  This\n   returns the first non-zero value returned by CALLBACK, or 0.  */\n\nextern int backtrace_pcinfo (struct backtrace_state *state, uintptr_t pc,\n\t\t\t     backtrace_full_callback callback,\n\t\t\t     backtrace_error_callback error_callback,\n\t\t\t     void *data);\n\n/* The type of the callback argument to backtrace_syminfo.  DATA and\n   PC are the arguments passed to backtrace_syminfo.  SYMNAME is the\n   name of the symbol for the corresponding code.  SYMVAL is the\n   value and SYMSIZE is the size of the symbol.  SYMNAME will be NULL\n   if no error occurred but the symbol could not be found.  */\n\ntypedef void (*backtrace_syminfo_callback) (void *data, uintptr_t pc,\n\t\t\t\t\t    const char *symname,\n\t\t\t\t\t    uintptr_t symval,\n\t\t\t\t\t    uintptr_t symsize);\n\n/* Given ADDR, an address or program counter in the current program,\n   call the callback information with the symbol name and value\n   describing the function or variable in which ADDR may be found.\n   This will call either CALLBACK or ERROR_CALLBACK exactly once.\n   This returns 1 on success, 0 on failure.  This function requires\n   the symbol table but does not require the debug info.  Note that if\n   the symbol table is present but ADDR could not be found in the\n   table, CALLBACK will be called with a NULL SYMNAME argument.\n   Returns 1 on success, 0 on error.  */\n\nextern int backtrace_syminfo (struct backtrace_state *state, uintptr_t addr,\n\t\t\t      backtrace_syminfo_callback callback,\n\t\t\t      backtrace_error_callback error_callback,\n\t\t\t      void *data);\n\n#ifdef __cplusplus\n} /* End extern \"C\".  */\n#endif\n\n#endif\n"
  },
  {
    "path": "src/vendor/libbacktrace/btest.c",
    "content": "/* btest.c -- Test for libbacktrace library\n   Copyright (C) 2012-2024 Free Software Foundation, Inc.\n   Written by Ian Lance Taylor, Google.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n    (1) Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n\n    (2) Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in\n    the documentation and/or other materials provided with the\n    distribution.\n\n    (3) The name of the author may not be used to\n    endorse or promote products derived from this software without\n    specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\nIMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,\nINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\nHOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\nIN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGE.  */\n\n/* This program tests the externally visible interfaces of the\n   libbacktrace library.  */\n\n#include <assert.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <unistd.h>\n#include <sys/stat.h>\n\n#include \"filenames.h\"\n\n#include \"backtrace.h\"\n#include \"backtrace-supported.h\"\n\n#include \"testlib.h\"\n\n/* Test the backtrace function with non-inlined functions.  */\n\nstatic int test1 (void) __attribute__ ((noinline, noclone, optnone, unused));\nstatic int f2 (int) __attribute__ ((noinline, noclone));\nstatic int f3 (int, int) __attribute__ ((noinline, noclone));\n\nstatic int\ntest1 (void)\n{\n  /* Returning a value here and elsewhere avoids a tailcall which\n     would mess up the backtrace.  */\n  return f2 (__LINE__) + 1;\n}\n\nstatic int\nf2 (int f1line)\n{\n  return f3 (f1line, __LINE__) + 2;\n}\n\nstatic int\nf3 (int f1line, int f2line)\n{\n  struct info all[20];\n  struct bdata data;\n  int f3line;\n  int i;\n\n  data.all = &all[0];\n  data.index = 0;\n  data.max = 20;\n  data.failed = 0;\n\n  f3line = __LINE__ + 1;\n  i = backtrace_full (state, 0, callback_one, error_callback_one, &data);\n\n  if (i != 0)\n    {\n      fprintf (stderr, \"test1: unexpected return value %d\\n\", i);\n      data.failed = 1;\n    }\n\n  if (data.index < 3)\n    {\n      fprintf (stderr,\n\t       \"test1: not enough frames; got %zu, expected at least 3\\n\",\n\t       data.index);\n      data.failed = 1;\n    }\n\n  check (\"test1\", 0, all, f3line, \"f3\", \"btest.c\", &data.failed);\n  check (\"test1\", 1, all, f2line, \"f2\", \"btest.c\", &data.failed);\n  check (\"test1\", 2, all, f1line, \"test1\", \"btest.c\", &data.failed);\n\n  printf (\"%s: backtrace_full noinline\\n\", data.failed ? \"FAIL\" : \"PASS\");\n\n  if (data.failed)\n    ++failures;\n\n  return failures;\n}\n\n/* Test the backtrace function with inlined functions.  */\n\nstatic inline int test2 (void) __attribute__ ((always_inline, unused));\nstatic inline int f12 (int) __attribute__ ((always_inline));\nstatic inline int f13 (int, int) __attribute__ ((always_inline));\n\nstatic inline int\ntest2 (void)\n{\n  return f12 (__LINE__) + 1;\n}\n\nstatic inline int\nf12 (int f1line)\n{\n  return f13 (f1line, __LINE__) + 2;\n}\n\nstatic inline int\nf13 (int f1line, int f2line)\n{\n  struct info all[20];\n  struct bdata data;\n  int f3line;\n  int i;\n\n  data.all = &all[0];\n  data.index = 0;\n  data.max = 20;\n  data.failed = 0;\n\n  f3line = __LINE__ + 1;\n  i = backtrace_full (state, 0, callback_one, error_callback_one, &data);\n\n  if (i != 0)\n    {\n      fprintf (stderr, \"test2: unexpected return value %d\\n\", i);\n      data.failed = 1;\n    }\n\n  check (\"test2\", 0, all, f3line, \"f13\", \"btest.c\", &data.failed);\n  check (\"test2\", 1, all, f2line, \"f12\", \"btest.c\", &data.failed);\n  check (\"test2\", 2, all, f1line, \"test2\", \"btest.c\", &data.failed);\n\n  printf (\"%s: backtrace_full inline\\n\", data.failed ? \"FAIL\" : \"PASS\");\n\n  if (data.failed)\n    ++failures;\n\n  return failures;\n}\n\n/* Test the backtrace_simple function with non-inlined functions.  */\n\nstatic int test3 (void) __attribute__ ((noinline, noclone, optnone, unused));\nstatic int f22 (int) __attribute__ ((noinline, noclone));\nstatic int f23 (int, int) __attribute__ ((noinline, noclone));\n\nstatic int\ntest3 (void)\n{\n  return f22 (__LINE__) + 1;\n}\n\nstatic int\nf22 (int f1line)\n{\n  return f23 (f1line, __LINE__) + 2;\n}\n\nstatic int\nf23 (int f1line, int f2line)\n{\n  uintptr_t addrs[20];\n  struct sdata data;\n  int f3line;\n  int i;\n\n  data.addrs = &addrs[0];\n  data.index = 0;\n  data.max = 20;\n  data.failed = 0;\n\n  f3line = __LINE__ + 1;\n  i = backtrace_simple (state, 0, callback_two, error_callback_two, &data);\n\n  if (i != 0)\n    {\n      fprintf (stderr, \"test3: unexpected return value %d\\n\", i);\n      data.failed = 1;\n    }\n\n  if (!data.failed)\n    {\n      struct info all[20];\n      struct bdata bdata;\n      int j;\n\n      bdata.all = &all[0];\n      bdata.index = 0;\n      bdata.max = 20;\n      bdata.failed = 0;\n\n      for (j = 0; j < 3; ++j)\n\t{\n\t  i = backtrace_pcinfo (state, addrs[j], callback_one,\n\t\t\t\terror_callback_one, &bdata);\n\t  if (i != 0)\n\t    {\n\t      fprintf (stderr,\n\t\t       (\"test3: unexpected return value \"\n\t\t\t\"from backtrace_pcinfo %d\\n\"),\n\t\t       i);\n\t      bdata.failed = 1;\n\t    }\n\t  if (!bdata.failed && bdata.index != (size_t) (j + 1))\n\t    {\n\t      fprintf (stderr,\n\t\t       (\"wrong number of calls from backtrace_pcinfo \"\n\t\t\t\"got %u expected %d\\n\"),\n\t\t       (unsigned int) bdata.index, j + 1);\n\t      bdata.failed = 1;\n\t    }\n\t}\n\n      check (\"test3\", 0, all, f3line, \"f23\", \"btest.c\", &bdata.failed);\n      check (\"test3\", 1, all, f2line, \"f22\", \"btest.c\", &bdata.failed);\n      check (\"test3\", 2, all, f1line, \"test3\", \"btest.c\", &bdata.failed);\n\n      if (bdata.failed)\n\tdata.failed = 1;\n\n      for (j = 0; j < 3; ++j)\n\t{\n\t  struct symdata symdata;\n\n\t  symdata.name = NULL;\n\t  symdata.val = 0;\n\t  symdata.size = 0;\n\t  symdata.failed = 0;\n\n\t  i = backtrace_syminfo (state, addrs[j], callback_three,\n\t\t\t\t error_callback_three, &symdata);\n\t  if (i == 0)\n\t    {\n\t      fprintf (stderr,\n\t\t       (\"test3: [%d]: unexpected return value \"\n\t\t\t\"from backtrace_syminfo %d\\n\"),\n\t\t       j, i);\n\t      symdata.failed = 1;\n\t    }\n\n\t  if (!symdata.failed)\n\t    {\n\t      const char *expected;\n\n\t      switch (j)\n\t\t{\n\t\tcase 0:\n\t\t  expected = \"f23\";\n\t\t  break;\n\t\tcase 1:\n\t\t  expected = \"f22\";\n\t\t  break;\n\t\tcase 2:\n\t\t  expected = \"test3\";\n\t\t  break;\n\t\tdefault:\n\t\t  assert (0);\n\t\t}\n\n\t      if (symdata.name == NULL)\n\t\t{\n\t\t  fprintf (stderr, \"test3: [%d]: NULL syminfo name\\n\", j);\n\t\t  symdata.failed = 1;\n\t\t}\n\t      /* Use strncmp, not strcmp, because GCC might create a\n\t\t clone.  */\n\t      else if (strncmp (symdata.name, expected, strlen (expected))\n\t\t       != 0)\n\t\t{\n\t\t  fprintf (stderr,\n\t\t\t   (\"test3: [%d]: unexpected syminfo name \"\n\t\t\t    \"got %s expected %s\\n\"),\n\t\t\t   j, symdata.name, expected);\n\t\t  symdata.failed = 1;\n\t\t}\n\t    }\n\n\t  if (symdata.failed)\n\t    data.failed = 1;\n\t}\n    }\n\n  printf (\"%s: backtrace_simple noinline\\n\", data.failed ? \"FAIL\" : \"PASS\");\n\n  if (data.failed)\n    ++failures;\n\n  return failures;\n}\n\n/* Test the backtrace_simple function with inlined functions.  */\n\nstatic inline int test4 (void) __attribute__ ((always_inline, unused));\nstatic inline int f32 (int) __attribute__ ((always_inline));\nstatic inline int f33 (int, int) __attribute__ ((always_inline));\n\nstatic inline int\ntest4 (void)\n{\n  return f32 (__LINE__) + 1;\n}\n\nstatic inline int\nf32 (int f1line)\n{\n  return f33 (f1line, __LINE__) + 2;\n}\n\nstatic inline int\nf33 (int f1line, int f2line)\n{\n  uintptr_t addrs[20];\n  struct sdata data;\n  int f3line;\n  int i;\n\n  data.addrs = &addrs[0];\n  data.index = 0;\n  data.max = 20;\n  data.failed = 0;\n\n  f3line = __LINE__ + 1;\n  i = backtrace_simple (state, 0, callback_two, error_callback_two, &data);\n\n  if (i != 0)\n    {\n      fprintf (stderr, \"test3: unexpected return value %d\\n\", i);\n      data.failed = 1;\n    }\n\n  if (!data.failed)\n    {\n      struct info all[20];\n      struct bdata bdata;\n\n      bdata.all = &all[0];\n      bdata.index = 0;\n      bdata.max = 20;\n      bdata.failed = 0;\n\n      i = backtrace_pcinfo (state, addrs[0], callback_one, error_callback_one,\n\t\t\t    &bdata);\n      if (i != 0)\n\t{\n\t  fprintf (stderr,\n\t\t   (\"test4: unexpected return value \"\n\t\t    \"from backtrace_pcinfo %d\\n\"),\n\t\t   i);\n\t  bdata.failed = 1;\n\t}\n\n      check (\"test4\", 0, all, f3line, \"f33\", \"btest.c\", &bdata.failed);\n      check (\"test4\", 1, all, f2line, \"f32\", \"btest.c\", &bdata.failed);\n      check (\"test4\", 2, all, f1line, \"test4\", \"btest.c\", &bdata.failed);\n\n      if (bdata.failed)\n\tdata.failed = 1;\n    }\n\n  printf (\"%s: backtrace_simple inline\\n\", data.failed ? \"FAIL\" : \"PASS\");\n\n  if (data.failed)\n    ++failures;\n\n  return failures;\n}\n\nstatic int test5 (void) __attribute__ ((unused));\n\nint global = 1;\n\nstatic int\ntest5 (void)\n{\n  struct symdata symdata;\n  int i;\n  uintptr_t addr = (uintptr_t) &global;\n\n  if (sizeof (global) > 1)\n    addr += 1;\n\n  symdata.name = NULL;\n  symdata.val = 0;\n  symdata.size = 0;\n  symdata.failed = 0;\n\n  i = backtrace_syminfo (state, addr, callback_three,\n\t\t\t error_callback_three, &symdata);\n  if (i == 0)\n    {\n      fprintf (stderr,\n\t       \"test5: unexpected return value from backtrace_syminfo %d\\n\",\n\t       i);\n      symdata.failed = 1;\n    }\n\n  if (!symdata.failed)\n    {\n      if (symdata.name == NULL)\n\t{\n\t  fprintf (stderr, \"test5: NULL syminfo name\\n\");\n\t  symdata.failed = 1;\n\t}\n      else if (!(strncmp (symdata.name, \"global\", 6) == 0\n\t\t && (symdata.name[6] == '\\0'|| symdata.name[6] == '.')))\n\t{\n\t  fprintf (stderr,\n\t\t   \"test5: unexpected syminfo name got %s expected %s\\n\",\n\t\t   symdata.name, \"global\");\n\t  symdata.failed = 1;\n\t}\n      else if (symdata.val != (uintptr_t) &global)\n\t{\n\t  fprintf (stderr,\n\t\t   \"test5: unexpected syminfo value got %lx expected %lx\\n\",\n\t\t   (unsigned long) symdata.val,\n\t\t   (unsigned long) (uintptr_t) &global);\n\t  symdata.failed = 1;\n\t}\n      else if (symdata.size != sizeof (global) && symdata.size != 0)\n\t{\n\t  fprintf (stderr,\n\t\t   \"test5: unexpected syminfo size got %lx expected %lx\\n\",\n\t\t   (unsigned long) symdata.size,\n\t\t   (unsigned long) sizeof (global));\n\t  symdata.failed = 1;\n\t}\n    }\n\n  printf (\"%s: backtrace_syminfo variable\\n\",\n\t  symdata.failed ? \"FAIL\" : \"PASS\");\n\n  if (symdata.failed)\n    ++failures;\n\n  return failures;\n}\n\n#define MIN_DESCRIPTOR 3\n#define MAX_DESCRIPTOR 10\n\nstatic int fstat_status[MAX_DESCRIPTOR];\n\n/* Check files that are available.  */\n\nstatic void\ncheck_available_files (void)\n{\n  struct stat s;\n  for (unsigned i = MIN_DESCRIPTOR; i < MAX_DESCRIPTOR; i++)\n    fstat_status[i] = fstat (i, &s);\n}\n\n/* Check that are no files left open.  */\n\nstatic void\ncheck_open_files (void)\n{\n  for (unsigned i = MIN_DESCRIPTOR; i < MAX_DESCRIPTOR; i++)\n    {\n      if (fstat_status[i] != 0 && close (i) == 0)\n\t{\n\t  fprintf (stderr,\n\t\t   \"ERROR: descriptor %d still open after tests complete\\n\",\n\t\t   i);\n\t  ++failures;\n\t}\n    }\n}\n\n/* Run all the tests.  */\n\nint\nmain (int argc ATTRIBUTE_UNUSED, char **argv)\n{\n  check_available_files ();\n\n  state = backtrace_create_state (argv[0], BACKTRACE_SUPPORTS_THREADS,\n\t\t\t\t  error_callback_create, NULL);\n\n#if BACKTRACE_SUPPORTED\n  test1 ();\n  test2 ();\n  test3 ();\n  test4 ();\n#if BACKTRACE_SUPPORTS_DATA\n  test5 ();\n#endif\n#endif\n\n  check_open_files ();\n\n  exit (failures ? EXIT_FAILURE : EXIT_SUCCESS);\n}\n"
  },
  {
    "path": "src/vendor/libbacktrace/compile",
    "content": "#! /bin/sh\n# Wrapper for compilers which do not understand '-c -o'.\n\nscriptversion=2016-01-11.22; # UTC\n\n# Copyright (C) 1999-2017 Free Software Foundation, Inc.\n# Written by Tom Tromey <tromey@cygnus.com>.\n#\n# This program is free software; you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation; either version 2, or (at your option)\n# any later version.\n#\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\n# As a special exception to the GNU General Public License, if you\n# distribute this file as part of a program that contains a\n# configuration script generated by Autoconf, you may include it under\n# the same distribution terms that you use for the rest of that program.\n\n# This file is maintained in Automake, please report\n# bugs to <bug-automake@gnu.org> or send patches to\n# <automake-patches@gnu.org>.\n\nnl='\n'\n\n# We need space, tab and new line, in precisely that order.  Quoting is\n# there to prevent tools from complaining about whitespace usage.\nIFS=\" \"\"\t$nl\"\n\nfile_conv=\n\n# func_file_conv build_file lazy\n# Convert a $build file to $host form and store it in $file\n# Currently only supports Windows hosts. If the determined conversion\n# type is listed in (the comma separated) LAZY, no conversion will\n# take place.\nfunc_file_conv ()\n{\n  file=$1\n  case $file in\n    / | /[!/]*) # absolute file, and not a UNC file\n      if test -z \"$file_conv\"; then\n\t# lazily determine how to convert abs files\n\tcase `uname -s` in\n\t  MINGW*)\n\t    file_conv=mingw\n\t    ;;\n\t  CYGWIN*)\n\t    file_conv=cygwin\n\t    ;;\n\t  *)\n\t    file_conv=wine\n\t    ;;\n\tesac\n      fi\n      case $file_conv/,$2, in\n\t*,$file_conv,*)\n\t  ;;\n\tmingw/*)\n\t  file=`cmd //C echo \"$file \" | sed -e 's/\"\\(.*\\) \" *$/\\1/'`\n\t  ;;\n\tcygwin/*)\n\t  file=`cygpath -m \"$file\" || echo \"$file\"`\n\t  ;;\n\twine/*)\n\t  file=`winepath -w \"$file\" || echo \"$file\"`\n\t  ;;\n      esac\n      ;;\n  esac\n}\n\n# func_cl_dashL linkdir\n# Make cl look for libraries in LINKDIR\nfunc_cl_dashL ()\n{\n  func_file_conv \"$1\"\n  if test -z \"$lib_path\"; then\n    lib_path=$file\n  else\n    lib_path=\"$lib_path;$file\"\n  fi\n  linker_opts=\"$linker_opts -LIBPATH:$file\"\n}\n\n# func_cl_dashl library\n# Do a library search-path lookup for cl\nfunc_cl_dashl ()\n{\n  lib=$1\n  found=no\n  save_IFS=$IFS\n  IFS=';'\n  for dir in $lib_path $LIB\n  do\n    IFS=$save_IFS\n    if $shared && test -f \"$dir/$lib.dll.lib\"; then\n      found=yes\n      lib=$dir/$lib.dll.lib\n      break\n    fi\n    if test -f \"$dir/$lib.lib\"; then\n      found=yes\n      lib=$dir/$lib.lib\n      break\n    fi\n    if test -f \"$dir/lib$lib.a\"; then\n      found=yes\n      lib=$dir/lib$lib.a\n      break\n    fi\n  done\n  IFS=$save_IFS\n\n  if test \"$found\" != yes; then\n    lib=$lib.lib\n  fi\n}\n\n# func_cl_wrapper cl arg...\n# Adjust compile command to suit cl\nfunc_cl_wrapper ()\n{\n  # Assume a capable shell\n  lib_path=\n  shared=:\n  linker_opts=\n  for arg\n  do\n    if test -n \"$eat\"; then\n      eat=\n    else\n      case $1 in\n\t-o)\n\t  # configure might choose to run compile as 'compile cc -o foo foo.c'.\n\t  eat=1\n\t  case $2 in\n\t    *.o | *.[oO][bB][jJ])\n\t      func_file_conv \"$2\"\n\t      set x \"$@\" -Fo\"$file\"\n\t      shift\n\t      ;;\n\t    *)\n\t      func_file_conv \"$2\"\n\t      set x \"$@\" -Fe\"$file\"\n\t      shift\n\t      ;;\n\t  esac\n\t  ;;\n\t-I)\n\t  eat=1\n\t  func_file_conv \"$2\" mingw\n\t  set x \"$@\" -I\"$file\"\n\t  shift\n\t  ;;\n\t-I*)\n\t  func_file_conv \"${1#-I}\" mingw\n\t  set x \"$@\" -I\"$file\"\n\t  shift\n\t  ;;\n\t-l)\n\t  eat=1\n\t  func_cl_dashl \"$2\"\n\t  set x \"$@\" \"$lib\"\n\t  shift\n\t  ;;\n\t-l*)\n\t  func_cl_dashl \"${1#-l}\"\n\t  set x \"$@\" \"$lib\"\n\t  shift\n\t  ;;\n\t-L)\n\t  eat=1\n\t  func_cl_dashL \"$2\"\n\t  ;;\n\t-L*)\n\t  func_cl_dashL \"${1#-L}\"\n\t  ;;\n\t-static)\n\t  shared=false\n\t  ;;\n\t-Wl,*)\n\t  arg=${1#-Wl,}\n\t  save_ifs=\"$IFS\"; IFS=','\n\t  for flag in $arg; do\n\t    IFS=\"$save_ifs\"\n\t    linker_opts=\"$linker_opts $flag\"\n\t  done\n\t  IFS=\"$save_ifs\"\n\t  ;;\n\t-Xlinker)\n\t  eat=1\n\t  linker_opts=\"$linker_opts $2\"\n\t  ;;\n\t-*)\n\t  set x \"$@\" \"$1\"\n\t  shift\n\t  ;;\n\t*.cc | *.CC | *.cxx | *.CXX | *.[cC]++)\n\t  func_file_conv \"$1\"\n\t  set x \"$@\" -Tp\"$file\"\n\t  shift\n\t  ;;\n\t*.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO])\n\t  func_file_conv \"$1\" mingw\n\t  set x \"$@\" \"$file\"\n\t  shift\n\t  ;;\n\t*)\n\t  set x \"$@\" \"$1\"\n\t  shift\n\t  ;;\n      esac\n    fi\n    shift\n  done\n  if test -n \"$linker_opts\"; then\n    linker_opts=\"-link$linker_opts\"\n  fi\n  exec \"$@\" $linker_opts\n  exit 1\n}\n\neat=\n\ncase $1 in\n  '')\n     echo \"$0: No command.  Try '$0 --help' for more information.\" 1>&2\n     exit 1;\n     ;;\n  -h | --h*)\n    cat <<\\EOF\nUsage: compile [--help] [--version] PROGRAM [ARGS]\n\nWrapper for compilers which do not understand '-c -o'.\nRemove '-o dest.o' from ARGS, run PROGRAM with the remaining\narguments, and rename the output as expected.\n\nIf you are trying to build a whole package this is not the\nright script to run: please start by reading the file 'INSTALL'.\n\nReport bugs to <bug-automake@gnu.org>.\nEOF\n    exit $?\n    ;;\n  -v | --v*)\n    echo \"compile $scriptversion\"\n    exit $?\n    ;;\n  cl | *[/\\\\]cl | cl.exe | *[/\\\\]cl.exe | \\\n  icl | *[/\\\\]icl | icl.exe | *[/\\\\]icl.exe )\n    func_cl_wrapper \"$@\"      # Doesn't return...\n    ;;\nesac\n\nofile=\ncfile=\n\nfor arg\ndo\n  if test -n \"$eat\"; then\n    eat=\n  else\n    case $1 in\n      -o)\n\t# configure might choose to run compile as 'compile cc -o foo foo.c'.\n\t# So we strip '-o arg' only if arg is an object.\n\teat=1\n\tcase $2 in\n\t  *.o | *.obj)\n\t    ofile=$2\n\t    ;;\n\t  *)\n\t    set x \"$@\" -o \"$2\"\n\t    shift\n\t    ;;\n\tesac\n\t;;\n      *.c)\n\tcfile=$1\n\tset x \"$@\" \"$1\"\n\tshift\n\t;;\n      *)\n\tset x \"$@\" \"$1\"\n\tshift\n\t;;\n    esac\n  fi\n  shift\ndone\n\nif test -z \"$ofile\" || test -z \"$cfile\"; then\n  # If no '-o' option was seen then we might have been invoked from a\n  # pattern rule where we don't need one.  That is ok -- this is a\n  # normal compilation that the losing compiler can handle.  If no\n  # '.c' file was seen then we are probably linking.  That is also\n  # ok.\n  exec \"$@\"\nfi\n\n# Name of file we expect compiler to create.\ncofile=`echo \"$cfile\" | sed 's|^.*[\\\\/]||; s|^[a-zA-Z]:||; s/\\.c$/.o/'`\n\n# Create the lock directory.\n# Note: use '[/\\\\:.-]' here to ensure that we don't use the same name\n# that we are using for the .o file.  Also, base the name on the expected\n# object file name, since that is what matters with a parallel build.\nlockdir=`echo \"$cofile\" | sed -e 's|[/\\\\:.-]|_|g'`.d\nwhile true; do\n  if mkdir \"$lockdir\" >/dev/null 2>&1; then\n    break\n  fi\n  sleep 1\ndone\n# FIXME: race condition here if user kills between mkdir and trap.\ntrap \"rmdir '$lockdir'; exit 1\" 1 2 15\n\n# Run the compile.\n\"$@\"\nret=$?\n\nif test -f \"$cofile\"; then\n  test \"$cofile\" = \"$ofile\" || mv \"$cofile\" \"$ofile\"\nelif test -f \"${cofile}bj\"; then\n  test \"${cofile}bj\" = \"$ofile\" || mv \"${cofile}bj\" \"$ofile\"\nfi\n\nrmdir \"$lockdir\"\nexit $ret\n\n# Local Variables:\n# mode: shell-script\n# sh-indentation: 2\n# eval: (add-hook 'write-file-hooks 'time-stamp)\n# time-stamp-start: \"scriptversion=\"\n# time-stamp-format: \"%:y-%02m-%02d.%02H\"\n# time-stamp-time-zone: \"UTC0\"\n# time-stamp-end: \"; # UTC\"\n# End:\n"
  },
  {
    "path": "src/vendor/libbacktrace/config/enable.m4",
    "content": "dnl ----------------------------------------------------------------------\ndnl This whole bit snagged from libstdc++-v3.\n\ndnl\ndnl GCC_ENABLE\ndnl    (FEATURE, DEFAULT, HELP-ARG, HELP-STRING)\ndnl    (FEATURE, DEFAULT, HELP-ARG, HELP-STRING, permit a|b|c)\ndnl    (FEATURE, DEFAULT, HELP-ARG, HELP-STRING, SHELL-CODE-HANDLER)\ndnl\ndnl See docs/html/17_intro/configury.html#enable for documentation.\ndnl\nAC_DEFUN([GCC_ENABLE],[dnl\nm4_define([_g_switch],[--enable-$1])dnl\nm4_define([_g_help],[AC_HELP_STRING(_g_switch$3,[$4 @<:@default=$2@:>@])])dnl\n AC_ARG_ENABLE($1,_g_help,\n  m4_bmatch([$5],\n   [^permit ],\n     [[\n      case \"$enableval\" in\n       m4_bpatsubst([$5],[permit ])) ;;\n       *) AC_MSG_ERROR(Unknown argument to enable/disable $1) ;;\n          dnl Idea for future:  generate a URL pointing to\n          dnl \"onlinedocs/configopts.html#whatever\"\n      esac\n     ]],\n   [^$],\n     [[\n      case \"$enableval\" in\n       yes|no) ;;\n       *) AC_MSG_ERROR(Argument to enable/disable $1 must be yes or no) ;;\n      esac\n     ]],\n   [[$5]]),\n  [enable_]m4_bpatsubst([$1],-,_)[=][$2])\nm4_undefine([_g_switch])dnl\nm4_undefine([_g_help])dnl\n])\n\n"
  },
  {
    "path": "src/vendor/libbacktrace/config/lead-dot.m4",
    "content": "#                                                          -*- Autoconf -*-\n# Copyright (C) 2003, 2009  Free Software Foundation, Inc.\n\n# This program is free software; you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation; either version 3, or (at your option)\n# any later version.\n\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n\n# You should have received a copy of the GNU General Public License\n# along with this program; see the file COPYING3.  If not see\n# <http://www.gnu.org/licenses/>.\n\n# serial 1\n\n# Check whether the underlying file-system supports filenames\n# with a leading dot.  For instance MS-DOS doesn't.\nAC_DEFUN([AM_SET_LEADING_DOT],\n[rm -rf .tst 2>/dev/null\nmkdir .tst 2>/dev/null\nif test -d .tst; then\n  am__leading_dot=.\nelse\n  am__leading_dot=_\nfi\nrmdir .tst 2>/dev/null\nAC_SUBST([am__leading_dot])])\n"
  },
  {
    "path": "src/vendor/libbacktrace/config/libtool.m4",
    "content": "# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*-\n#\n#   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,\n#                 2006, 2007, 2008, 2009 Free Software Foundation, Inc.\n#   Written by Gordon Matzigkeit, 1996\n#\n# This file is free software; the Free Software Foundation gives\n# unlimited permission to copy and/or distribute it, with or without\n# modifications, as long as this notice is preserved.\n\nm4_define([_LT_COPYING], [dnl\n#   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,\n#                 2006, 2007, 2008, 2009 Free Software Foundation, Inc.\n#   Written by Gordon Matzigkeit, 1996\n#\n#   This file is part of GNU Libtool.\n#\n# GNU Libtool is free software; you can redistribute it and/or\n# modify it under the terms of the GNU General Public License as\n# published by the Free Software Foundation; either version 2 of\n# the License, or (at your option) any later version.\n#\n# As a special exception to the GNU General Public License,\n# if you distribute this file as part of a program or library that\n# is built using GNU Libtool, you may include this file under the\n# same distribution terms that you use for the rest of that program.\n#\n# GNU Libtool is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with GNU Libtool; see the file COPYING.  If not, a copy\n# can be downloaded from http://www.gnu.org/licenses/gpl.html, or\n# obtained by writing to the Free Software Foundation, Inc.,\n# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n])\n\n# serial 56 LT_INIT\n\n\n# LT_PREREQ(VERSION)\n# ------------------\n# Complain and exit if this libtool version is less that VERSION.\nm4_defun([LT_PREREQ],\n[m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1,\n       [m4_default([$3],\n\t\t   [m4_fatal([Libtool version $1 or higher is required],\n\t\t             63)])],\n       [$2])])\n\n\n# _LT_CHECK_BUILDDIR\n# ------------------\n# Complain if the absolute build directory name contains unusual characters\nm4_defun([_LT_CHECK_BUILDDIR],\n[case `pwd` in\n  *\\ * | *\\\t*)\n    AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;;\nesac\n])\n\n\n# LT_INIT([OPTIONS])\n# ------------------\nAC_DEFUN([LT_INIT],\n[AC_PREREQ([2.58])dnl We use AC_INCLUDES_DEFAULT\nAC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl\nAC_BEFORE([$0], [LT_LANG])dnl\nAC_BEFORE([$0], [LT_OUTPUT])dnl\nAC_BEFORE([$0], [LTDL_INIT])dnl\nm4_require([_LT_CHECK_BUILDDIR])dnl\n\ndnl Autoconf doesn't catch unexpanded LT_ macros by default:\nm4_pattern_forbid([^_?LT_[A-Z_]+$])dnl\nm4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl\ndnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4\ndnl unless we require an AC_DEFUNed macro:\nAC_REQUIRE([LTOPTIONS_VERSION])dnl\nAC_REQUIRE([LTSUGAR_VERSION])dnl\nAC_REQUIRE([LTVERSION_VERSION])dnl\nAC_REQUIRE([LTOBSOLETE_VERSION])dnl\nm4_require([_LT_PROG_LTMAIN])dnl\n\n_LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}])\n\ndnl Parse OPTIONS\n_LT_SET_OPTIONS([$0], [$1])\n\n# This can be used to rebuild libtool when needed\nLIBTOOL_DEPS=\"$ltmain\"\n\n# Always use our own libtool.\nLIBTOOL='$(SHELL) $(top_builddir)/libtool'\nAC_SUBST(LIBTOOL)dnl\n\n_LT_SETUP\n\n# Only expand once:\nm4_define([LT_INIT])\n])# LT_INIT\n\n# Old names:\nAU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT])\nAU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT])\ndnl aclocal-1.4 backwards compatibility:\ndnl AC_DEFUN([AC_PROG_LIBTOOL], [])\ndnl AC_DEFUN([AM_PROG_LIBTOOL], [])\n\n\n# _LT_CC_BASENAME(CC)\n# -------------------\n# Calculate cc_basename.  Skip known compiler wrappers and cross-prefix.\nm4_defun([_LT_CC_BASENAME],\n[for cc_temp in $1\"\"; do\n  case $cc_temp in\n    compile | *[[\\\\/]]compile | ccache | *[[\\\\/]]ccache ) ;;\n    distcc | *[[\\\\/]]distcc | purify | *[[\\\\/]]purify ) ;;\n    \\-*) ;;\n    *) break;;\n  esac\ndone\ncc_basename=`$ECHO \"$cc_temp\" | $SED \"s%.*/%%; s%^$host_alias-%%\"`\n])\n\n\n# _LT_FILEUTILS_DEFAULTS\n# ----------------------\n# It is okay to use these file commands and assume they have been set\n# sensibly after `m4_require([_LT_FILEUTILS_DEFAULTS])'.\nm4_defun([_LT_FILEUTILS_DEFAULTS],\n[: ${CP=\"cp -f\"}\n: ${MV=\"mv -f\"}\n: ${RM=\"rm -f\"}\n])# _LT_FILEUTILS_DEFAULTS\n\n\n# _LT_SETUP\n# ---------\nm4_defun([_LT_SETUP],\n[AC_REQUIRE([AC_CANONICAL_HOST])dnl\nAC_REQUIRE([AC_CANONICAL_BUILD])dnl\nAC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl\nAC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl\n\n_LT_DECL([], [host_alias], [0], [The host system])dnl\n_LT_DECL([], [host], [0])dnl\n_LT_DECL([], [host_os], [0])dnl\ndnl\n_LT_DECL([], [build_alias], [0], [The build system])dnl\n_LT_DECL([], [build], [0])dnl\n_LT_DECL([], [build_os], [0])dnl\ndnl\nAC_REQUIRE([AC_PROG_CC])dnl\nAC_REQUIRE([LT_PATH_LD])dnl\nAC_REQUIRE([LT_PATH_NM])dnl\ndnl\nAC_REQUIRE([AC_PROG_LN_S])dnl\ntest -z \"$LN_S\" && LN_S=\"ln -s\"\n_LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl\ndnl\nAC_REQUIRE([LT_CMD_MAX_LEN])dnl\n_LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally \"o\")])dnl\n_LT_DECL([], [exeext], [0], [Executable file suffix (normally \"\")])dnl\ndnl\nm4_require([_LT_FILEUTILS_DEFAULTS])dnl\nm4_require([_LT_CHECK_SHELL_FEATURES])dnl\nm4_require([_LT_CMD_RELOAD])dnl\nm4_require([_LT_CHECK_MAGIC_METHOD])dnl\nm4_require([_LT_CMD_OLD_ARCHIVE])dnl\nm4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl\n\n_LT_CONFIG_LIBTOOL_INIT([\n# See if we are running on zsh, and set the options which allow our\n# commands through without removal of \\ escapes INIT.\nif test -n \"\\${ZSH_VERSION+set}\" ; then\n   setopt NO_GLOB_SUBST\nfi\n])\nif test -n \"${ZSH_VERSION+set}\" ; then\n   setopt NO_GLOB_SUBST\nfi\n\n_LT_CHECK_OBJDIR\n\nm4_require([_LT_TAG_COMPILER])dnl\n\ncase $host_os in\naix3*)\n  # AIX sometimes has problems with the GCC collect2 program.  For some\n  # reason, if we set the COLLECT_NAMES environment variable, the problems\n  # vanish in a puff of smoke.\n  if test \"X${COLLECT_NAMES+set}\" != Xset; then\n    COLLECT_NAMES=\n    export COLLECT_NAMES\n  fi\n  ;;\nesac\n\n# Global variables:\nofile=libtool\ncan_build_shared=yes\n\n# All known linkers require a `.a' archive for static linking (except MSVC,\n# which needs '.lib').\nlibext=a\n\nwith_gnu_ld=\"$lt_cv_prog_gnu_ld\"\n\nold_CC=\"$CC\"\nold_CFLAGS=\"$CFLAGS\"\n\n# Set sane defaults for various variables\ntest -z \"$CC\" && CC=cc\ntest -z \"$LTCC\" && LTCC=$CC\ntest -z \"$LTCFLAGS\" && LTCFLAGS=$CFLAGS\ntest -z \"$LD\" && LD=ld\ntest -z \"$ac_objext\" && ac_objext=o\n\n_LT_CC_BASENAME([$compiler])\n\n# Only perform the check for file, if the check method requires it\ntest -z \"$MAGIC_CMD\" && MAGIC_CMD=file\ncase $deplibs_check_method in\nfile_magic*)\n  if test \"$file_magic_cmd\" = '$MAGIC_CMD'; then\n    _LT_PATH_MAGIC\n  fi\n  ;;\nesac\n\n# Use C for the default configuration in the libtool script\nLT_SUPPORTED_TAG([CC])\n_LT_LANG_C_CONFIG\n_LT_LANG_DEFAULT_CONFIG\n_LT_CONFIG_COMMANDS\n])# _LT_SETUP\n\n\n# _LT_PREPARE_SED_QUOTE_VARS\n# --------------------------\n# Define a few sed substitution that help us do robust quoting.\nm4_defun([_LT_PREPARE_SED_QUOTE_VARS],\n[# Backslashify metacharacters that are still active within\n# double-quoted strings.\nsed_quote_subst='s/\\([[\"`$\\\\]]\\)/\\\\\\1/g'\n\n# Same as above, but do not quote variable references.\ndouble_quote_subst='s/\\([[\"`\\\\]]\\)/\\\\\\1/g'\n\n# Sed substitution to delay expansion of an escaped shell variable in a\n# double_quote_subst'ed string.\ndelay_variable_subst='s/\\\\\\\\\\\\\\\\\\\\\\$/\\\\\\\\\\\\$/g'\n\n# Sed substitution to delay expansion of an escaped single quote.\ndelay_single_quote_subst='s/'\\''/'\\'\\\\\\\\\\\\\\'\\''/g'\n\n# Sed substitution to avoid accidental globbing in evaled expressions\nno_glob_subst='s/\\*/\\\\\\*/g'\n])\n\n# _LT_PROG_LTMAIN\n# ---------------\n# Note that this code is called both from `configure', and `config.status'\n# now that we use AC_CONFIG_COMMANDS to generate libtool.  Notably,\n# `config.status' has no value for ac_aux_dir unless we are using Automake,\n# so we pass a copy along to make sure it has a sensible value anyway.\nm4_defun([_LT_PROG_LTMAIN],\n[m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl\n_LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir'])\nltmain=\"$ac_aux_dir/ltmain.sh\"\n])# _LT_PROG_LTMAIN\n\n\n## ------------------------------------- ##\n## Accumulate code for creating libtool. ##\n## ------------------------------------- ##\n\n# So that we can recreate a full libtool script including additional\n# tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS\n# in macros and then make a single call at the end using the `libtool'\n# label.\n\n\n# _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS])\n# ----------------------------------------\n# Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later.\nm4_define([_LT_CONFIG_LIBTOOL_INIT],\n[m4_ifval([$1],\n          [m4_append([_LT_OUTPUT_LIBTOOL_INIT],\n                     [$1\n])])])\n\n# Initialize.\nm4_define([_LT_OUTPUT_LIBTOOL_INIT])\n\n\n# _LT_CONFIG_LIBTOOL([COMMANDS])\n# ------------------------------\n# Register COMMANDS to be passed to AC_CONFIG_COMMANDS later.\nm4_define([_LT_CONFIG_LIBTOOL],\n[m4_ifval([$1],\n          [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS],\n                     [$1\n])])])\n\n# Initialize.\nm4_define([_LT_OUTPUT_LIBTOOL_COMMANDS])\n\n\n# _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS])\n# -----------------------------------------------------\nm4_defun([_LT_CONFIG_SAVE_COMMANDS],\n[_LT_CONFIG_LIBTOOL([$1])\n_LT_CONFIG_LIBTOOL_INIT([$2])\n])\n\n\n# _LT_FORMAT_COMMENT([COMMENT])\n# -----------------------------\n# Add leading comment marks to the start of each line, and a trailing\n# full-stop to the whole comment if one is not present already.\nm4_define([_LT_FORMAT_COMMENT],\n[m4_ifval([$1], [\nm4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])],\n              [['`$\\]], [\\\\\\&])]m4_bmatch([$1], [[!?.]$], [], [.])\n)])\n\n\n\n## ------------------------ ##\n## FIXME: Eliminate VARNAME ##\n## ------------------------ ##\n\n\n# _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?])\n# -------------------------------------------------------------------\n# CONFIGNAME is the name given to the value in the libtool script.\n# VARNAME is the (base) name used in the configure script.\n# VALUE may be 0, 1 or 2 for a computed quote escaped value based on\n# VARNAME.  Any other value will be used directly.\nm4_define([_LT_DECL],\n[lt_if_append_uniq([lt_decl_varnames], [$2], [, ],\n    [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name],\n\t[m4_ifval([$1], [$1], [$2])])\n    lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3])\n    m4_ifval([$4],\n\t[lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])])\n    lt_dict_add_subkey([lt_decl_dict], [$2],\n\t[tagged?], [m4_ifval([$5], [yes], [no])])])\n])\n\n\n# _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION])\n# --------------------------------------------------------\nm4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])])\n\n\n# lt_decl_tag_varnames([SEPARATOR], [VARNAME1...])\n# ------------------------------------------------\nm4_define([lt_decl_tag_varnames],\n[_lt_decl_filter([tagged?], [yes], $@)])\n\n\n# _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..])\n# ---------------------------------------------------------\nm4_define([_lt_decl_filter],\n[m4_case([$#],\n  [0], [m4_fatal([$0: too few arguments: $#])],\n  [1], [m4_fatal([$0: too few arguments: $#: $1])],\n  [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)],\n  [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)],\n  [lt_dict_filter([lt_decl_dict], $@)])[]dnl\n])\n\n\n# lt_decl_quote_varnames([SEPARATOR], [VARNAME1...])\n# --------------------------------------------------\nm4_define([lt_decl_quote_varnames],\n[_lt_decl_filter([value], [1], $@)])\n\n\n# lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...])\n# ---------------------------------------------------\nm4_define([lt_decl_dquote_varnames],\n[_lt_decl_filter([value], [2], $@)])\n\n\n# lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...])\n# ---------------------------------------------------\nm4_define([lt_decl_varnames_tagged],\n[m4_assert([$# <= 2])dnl\n_$0(m4_quote(m4_default([$1], [[, ]])),\n    m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]),\n    m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))])\nm4_define([_lt_decl_varnames_tagged],\n[m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])])\n\n\n# lt_decl_all_varnames([SEPARATOR], [VARNAME1...])\n# ------------------------------------------------\nm4_define([lt_decl_all_varnames],\n[_$0(m4_quote(m4_default([$1], [[, ]])),\n     m4_if([$2], [],\n\t   m4_quote(lt_decl_varnames),\n\tm4_quote(m4_shift($@))))[]dnl\n])\nm4_define([_lt_decl_all_varnames],\n[lt_join($@, lt_decl_varnames_tagged([$1],\n\t\t\tlt_decl_tag_varnames([[, ]], m4_shift($@))))dnl\n])\n\n\n# _LT_CONFIG_STATUS_DECLARE([VARNAME])\n# ------------------------------------\n# Quote a variable value, and forward it to `config.status' so that its\n# declaration there will have the same value as in `configure'.  VARNAME\n# must have a single quote delimited value for this to work.\nm4_define([_LT_CONFIG_STATUS_DECLARE],\n[$1='`$ECHO \"$][$1\" | $SED \"$delay_single_quote_subst\"`'])\n\n\n# _LT_CONFIG_STATUS_DECLARATIONS\n# ------------------------------\n# We delimit libtool config variables with single quotes, so when\n# we write them to config.status, we have to be sure to quote all\n# embedded single quotes properly.  In configure, this macro expands\n# each variable declared with _LT_DECL (and _LT_TAGDECL) into:\n#\n#    <var>='`$ECHO \"$<var>\" | $SED \"$delay_single_quote_subst\"`'\nm4_defun([_LT_CONFIG_STATUS_DECLARATIONS],\n[m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames),\n    [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])])\n\n\n# _LT_LIBTOOL_TAGS\n# ----------------\n# Output comment and list of tags supported by the script\nm4_defun([_LT_LIBTOOL_TAGS],\n[_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl\navailable_tags=\"_LT_TAGS\"dnl\n])\n\n\n# _LT_LIBTOOL_DECLARE(VARNAME, [TAG])\n# -----------------------------------\n# Extract the dictionary values for VARNAME (optionally with TAG) and\n# expand to a commented shell variable setting:\n#\n#    # Some comment about what VAR is for.\n#    visible_name=$lt_internal_name\nm4_define([_LT_LIBTOOL_DECLARE],\n[_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1],\n\t\t\t\t\t   [description])))[]dnl\nm4_pushdef([_libtool_name],\n    m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl\nm4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])),\n    [0], [_libtool_name=[$]$1],\n    [1], [_libtool_name=$lt_[]$1],\n    [2], [_libtool_name=$lt_[]$1],\n    [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl\nm4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl\n])\n\n\n# _LT_LIBTOOL_CONFIG_VARS\n# -----------------------\n# Produce commented declarations of non-tagged libtool config variables\n# suitable for insertion in the LIBTOOL CONFIG section of the `libtool'\n# script.  Tagged libtool config variables (even for the LIBTOOL CONFIG\n# section) are produced by _LT_LIBTOOL_TAG_VARS.\nm4_defun([_LT_LIBTOOL_CONFIG_VARS],\n[m4_foreach([_lt_var],\n    m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)),\n    [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])])\n\n\n# _LT_LIBTOOL_TAG_VARS(TAG)\n# -------------------------\nm4_define([_LT_LIBTOOL_TAG_VARS],\n[m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames),\n    [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])])\n\n\n# _LT_TAGVAR(VARNAME, [TAGNAME])\n# ------------------------------\nm4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])])\n\n\n# _LT_CONFIG_COMMANDS\n# -------------------\n# Send accumulated output to $CONFIG_STATUS.  Thanks to the lists of\n# variables for single and double quote escaping we saved from calls\n# to _LT_DECL, we can put quote escaped variables declarations\n# into `config.status', and then the shell code to quote escape them in\n# for loops in `config.status'.  Finally, any additional code accumulated\n# from calls to _LT_CONFIG_LIBTOOL_INIT is expanded.\nm4_defun([_LT_CONFIG_COMMANDS],\n[AC_PROVIDE_IFELSE([LT_OUTPUT],\n\tdnl If the libtool generation code has been placed in $CONFIG_LT,\n\tdnl instead of duplicating it all over again into config.status,\n\tdnl then we will have config.status run $CONFIG_LT later, so it\n\tdnl needs to know what name is stored there:\n        [AC_CONFIG_COMMANDS([libtool],\n            [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])],\n    dnl If the libtool generation code is destined for config.status,\n    dnl expand the accumulated commands and init code now:\n    [AC_CONFIG_COMMANDS([libtool],\n        [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])])\n])#_LT_CONFIG_COMMANDS\n\n\n# Initialize.\nm4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT],\n[\n\n# The HP-UX ksh and POSIX shell print the target directory to stdout\n# if CDPATH is set.\n(unset CDPATH) >/dev/null 2>&1 && unset CDPATH\n\nsed_quote_subst='$sed_quote_subst'\ndouble_quote_subst='$double_quote_subst'\ndelay_variable_subst='$delay_variable_subst'\n_LT_CONFIG_STATUS_DECLARATIONS\nLTCC='$LTCC'\nLTCFLAGS='$LTCFLAGS'\ncompiler='$compiler_DEFAULT'\n\n# A function that is used when there is no print builtin or printf.\nfunc_fallback_echo ()\n{\n  eval 'cat <<_LTECHO_EOF\n\\$[]1\n_LTECHO_EOF'\n}\n\n# Quote evaled strings.\nfor var in lt_decl_all_varnames([[ \\\n]], lt_decl_quote_varnames); do\n    case \\`eval \\\\\\\\\\$ECHO \\\\\\\\\"\"\\\\\\\\\\$\\$var\"\\\\\\\\\"\\` in\n    *[[\\\\\\\\\\\\\\`\\\\\"\\\\\\$]]*)\n      eval \"lt_\\$var=\\\\\\\\\\\\\"\\\\\\`\\\\\\$ECHO \\\\\"\\\\\\$\\$var\\\\\" | \\\\\\$SED \\\\\"\\\\\\$sed_quote_subst\\\\\"\\\\\\`\\\\\\\\\\\\\"\"\n      ;;\n    *)\n      eval \"lt_\\$var=\\\\\\\\\\\\\"\\\\\\$\\$var\\\\\\\\\\\\\"\"\n      ;;\n    esac\ndone\n\n# Double-quote double-evaled strings.\nfor var in lt_decl_all_varnames([[ \\\n]], lt_decl_dquote_varnames); do\n    case \\`eval \\\\\\\\\\$ECHO \\\\\\\\\"\"\\\\\\\\\\$\\$var\"\\\\\\\\\"\\` in\n    *[[\\\\\\\\\\\\\\`\\\\\"\\\\\\$]]*)\n      eval \"lt_\\$var=\\\\\\\\\\\\\"\\\\\\`\\\\\\$ECHO \\\\\"\\\\\\$\\$var\\\\\" | \\\\\\$SED -e \\\\\"\\\\\\$double_quote_subst\\\\\" -e \\\\\"\\\\\\$sed_quote_subst\\\\\" -e \\\\\"\\\\\\$delay_variable_subst\\\\\"\\\\\\`\\\\\\\\\\\\\"\"\n      ;;\n    *)\n      eval \"lt_\\$var=\\\\\\\\\\\\\"\\\\\\$\\$var\\\\\\\\\\\\\"\"\n      ;;\n    esac\ndone\n\n_LT_OUTPUT_LIBTOOL_INIT\n])\n\n# _LT_GENERATED_FILE_INIT(FILE, [COMMENT])\n# ------------------------------------\n# Generate a child script FILE with all initialization necessary to\n# reuse the environment learned by the parent script, and make the\n# file executable.  If COMMENT is supplied, it is inserted after the\n# `#!' sequence but before initialization text begins.  After this\n# macro, additional text can be appended to FILE to form the body of\n# the child script.  The macro ends with non-zero status if the\n# file could not be fully written (such as if the disk is full).\nm4_ifdef([AS_INIT_GENERATED],\n[m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])],\n[m4_defun([_LT_GENERATED_FILE_INIT],\n[m4_require([AS_PREPARE])]dnl\n[m4_pushdef([AS_MESSAGE_LOG_FD])]dnl\n[lt_write_fail=0\ncat >$1 <<_ASEOF || lt_write_fail=1\n#! $SHELL\n# Generated by $as_me.\n$2\nSHELL=\\${CONFIG_SHELL-$SHELL}\nexport SHELL\n_ASEOF\ncat >>$1 <<\\_ASEOF || lt_write_fail=1\nAS_SHELL_SANITIZE\n_AS_PREPARE\nexec AS_MESSAGE_FD>&1\n_ASEOF\ntest $lt_write_fail = 0 && chmod +x $1[]dnl\nm4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT\n\n# LT_OUTPUT\n# ---------\n# This macro allows early generation of the libtool script (before\n# AC_OUTPUT is called), incase it is used in configure for compilation\n# tests.\nAC_DEFUN([LT_OUTPUT],\n[: ${CONFIG_LT=./config.lt}\nAC_MSG_NOTICE([creating $CONFIG_LT])\n_LT_GENERATED_FILE_INIT([\"$CONFIG_LT\"],\n[# Run this file to recreate a libtool stub with the current configuration.])\n\ncat >>\"$CONFIG_LT\" <<\\_LTEOF\nlt_cl_silent=false\nexec AS_MESSAGE_LOG_FD>>config.log\n{\n  echo\n  AS_BOX([Running $as_me.])\n} >&AS_MESSAGE_LOG_FD\n\nlt_cl_help=\"\\\n\\`$as_me' creates a local libtool stub from the current configuration,\nfor use in further configure time tests before the real libtool is\ngenerated.\n\nUsage: $[0] [[OPTIONS]]\n\n  -h, --help      print this help, then exit\n  -V, --version   print version number, then exit\n  -q, --quiet     do not print progress messages\n  -d, --debug     don't remove temporary files\n\nReport bugs to <bug-libtool@gnu.org>.\"\n\nlt_cl_version=\"\\\nm4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl\nm4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION])\nconfigured by $[0], generated by m4_PACKAGE_STRING.\n\nCopyright (C) 2009 Free Software Foundation, Inc.\nThis config.lt script is free software; the Free Software Foundation\ngives unlimited permision to copy, distribute and modify it.\"\n\nwhile test $[#] != 0\ndo\n  case $[1] in\n    --version | --v* | -V )\n      echo \"$lt_cl_version\"; exit 0 ;;\n    --help | --h* | -h )\n      echo \"$lt_cl_help\"; exit 0 ;;\n    --debug | --d* | -d )\n      debug=: ;;\n    --quiet | --q* | --silent | --s* | -q )\n      lt_cl_silent=: ;;\n\n    -*) AC_MSG_ERROR([unrecognized option: $[1]\nTry \\`$[0] --help' for more information.]) ;;\n\n    *) AC_MSG_ERROR([unrecognized argument: $[1]\nTry \\`$[0] --help' for more information.]) ;;\n  esac\n  shift\ndone\n\nif $lt_cl_silent; then\n  exec AS_MESSAGE_FD>/dev/null\nfi\n_LTEOF\n\ncat >>\"$CONFIG_LT\" <<_LTEOF\n_LT_OUTPUT_LIBTOOL_COMMANDS_INIT\n_LTEOF\n\ncat >>\"$CONFIG_LT\" <<\\_LTEOF\nAC_MSG_NOTICE([creating $ofile])\n_LT_OUTPUT_LIBTOOL_COMMANDS\nAS_EXIT(0)\n_LTEOF\nchmod +x \"$CONFIG_LT\"\n\n# configure is writing to config.log, but config.lt does its own redirection,\n# appending to config.log, which fails on DOS, as config.log is still kept\n# open by configure.  Here we exec the FD to /dev/null, effectively closing\n# config.log, so it can be properly (re)opened and appended to by config.lt.\nlt_cl_success=:\ntest \"$silent\" = yes &&\n  lt_config_lt_args=\"$lt_config_lt_args --quiet\"\nexec AS_MESSAGE_LOG_FD>/dev/null\n$SHELL \"$CONFIG_LT\" $lt_config_lt_args || lt_cl_success=false\nexec AS_MESSAGE_LOG_FD>>config.log\n$lt_cl_success || AS_EXIT(1)\n])# LT_OUTPUT\n\n\n# _LT_CONFIG(TAG)\n# ---------------\n# If TAG is the built-in tag, create an initial libtool script with a\n# default configuration from the untagged config vars.  Otherwise add code\n# to config.status for appending the configuration named by TAG from the\n# matching tagged config vars.\nm4_defun([_LT_CONFIG],\n[m4_require([_LT_FILEUTILS_DEFAULTS])dnl\n_LT_CONFIG_SAVE_COMMANDS([\n  m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl\n  m4_if(_LT_TAG, [C], [\n    # See if we are running on zsh, and set the options which allow our\n    # commands through without removal of \\ escapes.\n    if test -n \"${ZSH_VERSION+set}\" ; then\n      setopt NO_GLOB_SUBST\n    fi\n\n    cfgfile=\"${ofile}T\"\n    trap \"$RM \\\"$cfgfile\\\"; exit 1\" 1 2 15\n    $RM \"$cfgfile\"\n\n    cat <<_LT_EOF >> \"$cfgfile\"\n#! $SHELL\n\n# `$ECHO \"$ofile\" | sed 's%^.*/%%'` - Provide generalized library-building support services.\n# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION\n# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:\n# NOTE: Changes made to this file will be lost: look at ltmain.sh.\n#\n_LT_COPYING\n_LT_LIBTOOL_TAGS\n\n# ### BEGIN LIBTOOL CONFIG\n_LT_LIBTOOL_CONFIG_VARS\n_LT_LIBTOOL_TAG_VARS\n# ### END LIBTOOL CONFIG\n\n_LT_EOF\n\n  case $host_os in\n  aix3*)\n    cat <<\\_LT_EOF >> \"$cfgfile\"\n# AIX sometimes has problems with the GCC collect2 program.  For some\n# reason, if we set the COLLECT_NAMES environment variable, the problems\n# vanish in a puff of smoke.\nif test \"X${COLLECT_NAMES+set}\" != Xset; then\n  COLLECT_NAMES=\n  export COLLECT_NAMES\nfi\n_LT_EOF\n    ;;\n  esac\n\n  _LT_PROG_LTMAIN\n\n  # We use sed instead of cat because bash on DJGPP gets confused if\n  # if finds mixed CR/LF and LF-only lines.  Since sed operates in\n  # text mode, it properly converts lines to CR/LF.  This bash problem\n  # is reportedly fixed, but why not run on old versions too?\n  sed '/^# Generated shell functions inserted here/q' \"$ltmain\" >> \"$cfgfile\" \\\n    || (rm -f \"$cfgfile\"; exit 1)\n\n  _LT_PROG_XSI_SHELLFNS\n\n  sed -n '/^# Generated shell functions inserted here/,$p' \"$ltmain\" >> \"$cfgfile\" \\\n    || (rm -f \"$cfgfile\"; exit 1)\n\n  mv -f \"$cfgfile\" \"$ofile\" ||\n    (rm -f \"$ofile\" && cp \"$cfgfile\" \"$ofile\" && rm -f \"$cfgfile\")\n  chmod +x \"$ofile\"\n],\n[cat <<_LT_EOF >> \"$ofile\"\n\ndnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded\ndnl in a comment (ie after a #).\n# ### BEGIN LIBTOOL TAG CONFIG: $1\n_LT_LIBTOOL_TAG_VARS(_LT_TAG)\n# ### END LIBTOOL TAG CONFIG: $1\n_LT_EOF\n])dnl /m4_if\n],\n[m4_if([$1], [], [\n    PACKAGE='$PACKAGE'\n    VERSION='$VERSION'\n    TIMESTAMP='$TIMESTAMP'\n    RM='$RM'\n    ofile='$ofile'], [])\n])dnl /_LT_CONFIG_SAVE_COMMANDS\n])# _LT_CONFIG\n\n\n# LT_SUPPORTED_TAG(TAG)\n# ---------------------\n# Trace this macro to discover what tags are supported by the libtool\n# --tag option, using:\n#    autoconf --trace 'LT_SUPPORTED_TAG:$1'\nAC_DEFUN([LT_SUPPORTED_TAG], [])\n\n\n# C support is built-in for now\nm4_define([_LT_LANG_C_enabled], [])\nm4_define([_LT_TAGS], [])\n\n\n# LT_LANG(LANG)\n# -------------\n# Enable libtool support for the given language if not already enabled.\nAC_DEFUN([LT_LANG],\n[AC_BEFORE([$0], [LT_OUTPUT])dnl\nm4_case([$1],\n  [C],\t\t\t[_LT_LANG(C)],\n  [C++],\t\t[_LT_LANG(CXX)],\n  [Java],\t\t[_LT_LANG(GCJ)],\n  [Fortran 77],\t\t[_LT_LANG(F77)],\n  [Fortran],\t\t[_LT_LANG(FC)],\n  [Windows Resource],\t[_LT_LANG(RC)],\n  [m4_ifdef([_LT_LANG_]$1[_CONFIG],\n    [_LT_LANG($1)],\n    [m4_fatal([$0: unsupported language: \"$1\"])])])dnl\n])# LT_LANG\n\n\n# _LT_LANG(LANGNAME)\n# ------------------\nm4_defun([_LT_LANG],\n[m4_ifdef([_LT_LANG_]$1[_enabled], [],\n  [LT_SUPPORTED_TAG([$1])dnl\n  m4_append([_LT_TAGS], [$1 ])dnl\n  m4_define([_LT_LANG_]$1[_enabled], [])dnl\n  _LT_LANG_$1_CONFIG($1)])dnl\n])# _LT_LANG\n\n\n# _LT_LANG_DEFAULT_CONFIG\n# -----------------------\nm4_defun([_LT_LANG_DEFAULT_CONFIG],\n[AC_PROVIDE_IFELSE([AC_PROG_CXX],\n  [LT_LANG(CXX)],\n  [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])])\n\nAC_PROVIDE_IFELSE([AC_PROG_F77],\n  [LT_LANG(F77)],\n  [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])])\n\nAC_PROVIDE_IFELSE([AC_PROG_FC],\n  [LT_LANG(FC)],\n  [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])])\n\ndnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal\ndnl pulling things in needlessly.\nAC_PROVIDE_IFELSE([AC_PROG_GCJ],\n  [LT_LANG(GCJ)],\n  [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],\n    [LT_LANG(GCJ)],\n    [AC_PROVIDE_IFELSE([LT_PROG_GCJ],\n      [LT_LANG(GCJ)],\n      [m4_ifdef([AC_PROG_GCJ],\n\t[m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])])\n       m4_ifdef([A][M_PROG_GCJ],\n\t[m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])])\n       m4_ifdef([LT_PROG_GCJ],\n\t[m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])])\n\nAC_PROVIDE_IFELSE([LT_PROG_RC],\n  [LT_LANG(RC)],\n  [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])])\n])# _LT_LANG_DEFAULT_CONFIG\n\n# Obsolete macros:\nAU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)])\nAU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)])\nAU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)])\nAU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)])\nAU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)])\ndnl aclocal-1.4 backwards compatibility:\ndnl AC_DEFUN([AC_LIBTOOL_CXX], [])\ndnl AC_DEFUN([AC_LIBTOOL_F77], [])\ndnl AC_DEFUN([AC_LIBTOOL_FC], [])\ndnl AC_DEFUN([AC_LIBTOOL_GCJ], [])\ndnl AC_DEFUN([AC_LIBTOOL_RC], [])\n\n\n# _LT_TAG_COMPILER\n# ----------------\nm4_defun([_LT_TAG_COMPILER],\n[AC_REQUIRE([AC_PROG_CC])dnl\n\n_LT_DECL([LTCC], [CC], [1], [A C compiler])dnl\n_LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl\n_LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl\n_LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl\n\n# If no C compiler was specified, use CC.\nLTCC=${LTCC-\"$CC\"}\n\n# If no C compiler flags were specified, use CFLAGS.\nLTCFLAGS=${LTCFLAGS-\"$CFLAGS\"}\n\n# Allow CC to be a program name with arguments.\ncompiler=$CC\n])# _LT_TAG_COMPILER\n\n\n# _LT_COMPILER_BOILERPLATE\n# ------------------------\n# Check for compiler boilerplate output or warnings with\n# the simple compiler test code.\nm4_defun([_LT_COMPILER_BOILERPLATE],\n[m4_require([_LT_DECL_SED])dnl\nac_outfile=conftest.$ac_objext\necho \"$lt_simple_compile_test_code\" >conftest.$ac_ext\neval \"$ac_compile\" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err\n_lt_compiler_boilerplate=`cat conftest.err`\n$RM conftest*\n])# _LT_COMPILER_BOILERPLATE\n\n\n# _LT_LINKER_BOILERPLATE\n# ----------------------\n# Check for linker boilerplate output or warnings with\n# the simple link test code.\nm4_defun([_LT_LINKER_BOILERPLATE],\n[m4_require([_LT_DECL_SED])dnl\nac_outfile=conftest.$ac_objext\necho \"$lt_simple_link_test_code\" >conftest.$ac_ext\neval \"$ac_link\" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err\n_lt_linker_boilerplate=`cat conftest.err`\n$RM -r conftest*\n])# _LT_LINKER_BOILERPLATE\n\n# _LT_REQUIRED_DARWIN_CHECKS\n# -------------------------\nm4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[\n  case $host_os in\n    rhapsody* | darwin*)\n    AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:])\n    AC_CHECK_TOOL([NMEDIT], [nmedit], [:])\n    AC_CHECK_TOOL([LIPO], [lipo], [:])\n    AC_CHECK_TOOL([OTOOL], [otool], [:])\n    AC_CHECK_TOOL([OTOOL64], [otool64], [:])\n    _LT_DECL([], [DSYMUTIL], [1],\n      [Tool to manipulate archived DWARF debug symbol files on Mac OS X])\n    _LT_DECL([], [NMEDIT], [1],\n      [Tool to change global to local symbols on Mac OS X])\n    _LT_DECL([], [LIPO], [1],\n      [Tool to manipulate fat objects and archives on Mac OS X])\n    _LT_DECL([], [OTOOL], [1],\n      [ldd/readelf like tool for Mach-O binaries on Mac OS X])\n    _LT_DECL([], [OTOOL64], [1],\n      [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4])\n\n    AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod],\n      [lt_cv_apple_cc_single_mod=no\n      if test -z \"${LT_MULTI_MODULE}\"; then\n\t# By default we will add the -single_module flag. You can override\n\t# by either setting the environment variable LT_MULTI_MODULE\n\t# non-empty at configure time, or by adding -multi_module to the\n\t# link flags.\n\trm -rf libconftest.dylib*\n\techo \"int foo(void){return 1;}\" > conftest.c\n\techo \"$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \\\n-dynamiclib -Wl,-single_module conftest.c\" >&AS_MESSAGE_LOG_FD\n\t$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \\\n\t  -dynamiclib -Wl,-single_module conftest.c 2>conftest.err\n        _lt_result=$?\n\tif test -f libconftest.dylib && test ! -s conftest.err && test $_lt_result = 0; then\n\t  lt_cv_apple_cc_single_mod=yes\n\telse\n\t  cat conftest.err >&AS_MESSAGE_LOG_FD\n\tfi\n\trm -rf libconftest.dylib*\n\trm -f conftest.*\n      fi])\n    AC_CACHE_CHECK([for -exported_symbols_list linker flag],\n      [lt_cv_ld_exported_symbols_list],\n      [lt_cv_ld_exported_symbols_list=no\n      save_LDFLAGS=$LDFLAGS\n      echo \"_main\" > conftest.sym\n      LDFLAGS=\"$LDFLAGS -Wl,-exported_symbols_list,conftest.sym\"\n      AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])],\n\t[lt_cv_ld_exported_symbols_list=yes],\n\t[lt_cv_ld_exported_symbols_list=no])\n\tLDFLAGS=\"$save_LDFLAGS\"\n    ])\n    AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load],\n      [lt_cv_ld_force_load=no\n      cat > conftest.c << _LT_EOF\nint forced_loaded() { return 2;}\n_LT_EOF\n      echo \"$LTCC $LTCFLAGS -c -o conftest.o conftest.c\" >&AS_MESSAGE_LOG_FD\n      $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD\n      echo \"$AR cru libconftest.a conftest.o\" >&AS_MESSAGE_LOG_FD\n      $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD\n      cat > conftest.c << _LT_EOF\nint main() { return 0;}\n_LT_EOF\n      echo \"$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a\" >&AS_MESSAGE_LOG_FD\n      $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err\n      _lt_result=$?\n      if test -f conftest && test ! -s conftest.err && test $_lt_result = 0 && $GREP forced_load conftest 2>&1 >/dev/null; then\n\tlt_cv_ld_force_load=yes\n      else\n\tcat conftest.err >&AS_MESSAGE_LOG_FD\n      fi\n        rm -f conftest.err libconftest.a conftest conftest.c\n        rm -rf conftest.dSYM\n    ])\n    # Allow for Darwin 4-7 (macOS 10.0-10.3) although these are not expect to\n    # build without first building modern cctools / linker.\n    case $host_cpu-$host_os in\n    *-rhapsody* | *-darwin1.[[012]])\n      _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;;\n    *-darwin1.*)\n      _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;\n    *-darwin*)\n      # darwin 5.x (macOS 10.1) onwards we only need to adjust when the\n      # deployment target is forced to an earlier version.\n      case ${MACOSX_DEPLOYMENT_TARGET-UNSET},$host in\n\tUNSET,*-darwin[[89]]*|UNSET,*-darwin[[12]][[0-9]]*)\n\t  ;;\n\t10.[[012]][[,.]]*)\n\t  _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'\n\t  ;;\n\t*)\n\t  ;;\n     esac\n    ;;\n  esac\n    if test \"$lt_cv_apple_cc_single_mod\" = \"yes\"; then\n      _lt_dar_single_mod='$single_module'\n    fi\n    if test \"$lt_cv_ld_exported_symbols_list\" = \"yes\"; then\n      _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym'\n    else\n      _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}'\n    fi\n    if test \"$DSYMUTIL\" != \":\" && test \"$lt_cv_ld_force_load\" = \"no\"; then\n      _lt_dsymutil='~$DSYMUTIL $lib || :'\n    else\n      _lt_dsymutil=\n    fi\n    ;;\n  esac\n])\n\n\n# _LT_DARWIN_LINKER_FEATURES\n# --------------------------\n# Checks for linker and compiler features on Darwin / macOS / iOS\nm4_defun([_LT_DARWIN_LINKER_FEATURES],\n[\n  m4_require([_LT_REQUIRED_DARWIN_CHECKS])\n\n  # Publish an arg to allow the user to select that Darwin host (and target)\n  # libraries should be given install-names like @rpath/libfoo.dylib.  This\n  # requires that the user of the library then adds an 'rpath' to the DSO that\n  # needs access.\n  # NOTE: there are defaults below, for systems that support rpaths.  The person\n  # configuring can override the defaults for any system version that supports\n  # them - they are, however, forced off for system versions without support.\n  AC_ARG_ENABLE([darwin-at-rpath],\n    AS_HELP_STRING([--enable-darwin-at-rpath],\n      [install libraries with @rpath/library-name, requires rpaths to be added to executables]),\n  [if test \"x$enable_darwin_at_rpath\" = \"xyes\"; then\n    # This is not supported before macOS 10.5 / Darwin9.\n    case ${MACOSX_DEPLOYMENT_TARGET-UNSET},$host_os in\n      UNSET,darwin[[4-8]]*|UNSET,rhapsody*|10.[[0-4]][[,.]]*)\n\tAC_MSG_WARN([Darwin @rpath library names are incompatible with OSX versions earlier than 10.5 (rpaths disabled)])\n\tenable_darwin_at_rpath=no\n      ;;\n    esac\n   fi],\n  [case ${MACOSX_DEPLOYMENT_TARGET-UNSET},$host_os in\n    # As above, before 10.5 / Darwin9 this does not work.\n     UNSET,darwin[[4-8]]*|UNSET,rhapsody*|10.[[0-4]][[,.]]*)\n       enable_darwin_at_rpath=no\n       ;;\n\n    # We cannot build and test reliably on macOS 10.11+ (Darwin15+) without use\n    # of rpaths, since runpaths set via DYLD_LIBRARY_PATH are elided by key\n    # system executables (e.g. /bin/sh).  Force rpaths on for these systems.\n      UNSET,darwin1[[5-9]]*|UNSET,darwin2*|10.1[[1-9]][[,.]]*|1[[1-9]].*[[,.]]* )\n      AC_MSG_NOTICE([@rpath library names are needed on macOS versions later than 10.11 (rpaths have been enabled)])\n      enable_darwin_at_rpath=yes\n      ;;\n    # NOTE: we are not (yet) doing anything for 10.5 .. 10.10, since they can\n    # work with either DYLD_LIBRARY_PATH or embedded rpaths.\n\n    esac\n  ])\n\n  _LT_TAGVAR(archive_cmds_need_lc, $1)=no\n  _LT_TAGVAR(hardcode_direct, $1)=no\n  _LT_TAGVAR(hardcode_automatic, $1)=yes\n  _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported\n  if test \"$lt_cv_ld_force_load\" = \"yes\"; then\n    _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\\\"\\\"; do test  -n \\\"$conv\\\" && new_convenience=\\\"$new_convenience ${wl}-force_load,$conv\\\"; done; func_echo_all \\\"$new_convenience\\\"`'\n  else\n    _LT_TAGVAR(whole_archive_flag_spec, $1)=''\n  fi\n  _LT_TAGVAR(link_all_deplibs, $1)=yes\n  _LT_TAGVAR(allow_undefined_flag, $1)=\"$_lt_dar_allow_undefined\"\n  case $cc_basename in\n     ifort*) _lt_dar_can_shared=yes ;;\n     *) _lt_dar_can_shared=$GCC ;;\n  esac\n  if test \"$_lt_dar_can_shared\" = \"yes\"; then\n    output_verbose_link_cmd=func_echo_all\n    _lt_install_name='\\$rpath/\\$soname'\n    if test \"x$enable_darwin_at_rpath\" = \"xyes\"; then\n      _lt_install_name='@rpath/\\$soname'\n    fi\n    _LT_TAGVAR(archive_cmds, $1)=\"\\$CC -dynamiclib \\$allow_undefined_flag -o \\$lib \\$libobjs \\$deplibs \\$compiler_flags -install_name ${_lt_install_name} \\$verstring ${_lt_dsymutil}\"\n    _LT_TAGVAR(module_cmds, $1)=\"\\$CC \\$allow_undefined_flag -o \\$lib -bundle \\$libobjs \\$deplibs \\$compiler_flags${_lt_dsymutil}\"\n    _LT_TAGVAR(archive_expsym_cmds, $1)=\"sed 's,^,_,' < \\$export_symbols > \\$output_objdir/\\${libname}-symbols.expsym~\\$CC -dynamiclib \\$allow_undefined_flag -o \\$lib \\$libobjs \\$deplibs \\$compiler_flags -install_name ${_lt_install_name} \\$verstring ${_lt_dar_export_syms}${_lt_dsymutil}\"\n    _LT_TAGVAR(module_expsym_cmds, $1)=\"sed -e 's,^,_,' < \\$export_symbols > \\$output_objdir/\\${libname}-symbols.expsym~\\$CC \\$allow_undefined_flag -o \\$lib -bundle \\$libobjs \\$deplibs \\$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}\"\n    m4_if([$1], [CXX],\n[   if test \"$lt_cv_apple_cc_single_mod\" != \"yes\"; then\n      _lt_install_name='\\$rpath/\\$soname'\n      if test \"x$enable_darwin_at_rpath\" = \"xyes\"; then\n        _lt_install_name='@rpath/\\$soname'\n      fi\n      _LT_TAGVAR(archive_cmds, $1)=\"\\$CC -r -keep_private_externs -nostdlib -o \\${lib}-master.o \\$libobjs~\\$CC -dynamiclib \\$allow_undefined_flag -o \\$lib \\${lib}-master.o \\$deplibs \\$compiler_flags -install_name ${_lt_install_name} \\$verstring${_lt_dsymutil}\"\n      _LT_TAGVAR(archive_expsym_cmds, $1)=\"sed 's,^,_,' < \\$export_symbols > \\$output_objdir/\\${libname}-symbols.expsym~\\$CC -r -keep_private_externs -nostdlib -o \\${lib}-master.o \\$libobjs~\\$CC -dynamiclib \\$allow_undefined_flag -o \\$lib \\${lib}-master.o \\$deplibs \\$compiler_flags -install_name \\$rpath/\\$soname \\$verstring${_lt_dar_export_syms}${_lt_dsymutil}\"\n    fi\n],[])\n  else\n  _LT_TAGVAR(ld_shlibs, $1)=no\n  fi\n])\n\n# _LT_SYS_MODULE_PATH_AIX\n# -----------------------\n# Links a minimal program and checks the executable\n# for the system default hardcoded library path. In most cases,\n# this is /usr/lib:/lib, but when the MPI compilers are used\n# the location of the communication and MPI libs are included too.\n# If we don't find anything, use the default library path according\n# to the aix ld manual.\nm4_defun([_LT_SYS_MODULE_PATH_AIX],\n[m4_require([_LT_DECL_SED])dnl\nAC_LINK_IFELSE([AC_LANG_SOURCE([AC_LANG_PROGRAM])],[\nlt_aix_libpath_sed='\n    /Import File Strings/,/^$/ {\n\t/^0/ {\n\t    s/^0  *\\(.*\\)$/\\1/\n\t    p\n\t}\n    }'\naix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e \"$lt_aix_libpath_sed\"`\n# Check for a 64-bit object if we didn't find anything.\nif test -z \"$aix_libpath\"; then\n  aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e \"$lt_aix_libpath_sed\"`\nfi],[])\nif test -z \"$aix_libpath\"; then aix_libpath=\"/usr/lib:/lib\"; fi\n])# _LT_SYS_MODULE_PATH_AIX\n\n\n# _LT_SHELL_INIT(ARG)\n# -------------------\nm4_define([_LT_SHELL_INIT],\n[m4_divert_text([M4SH-INIT], [$1\n])])# _LT_SHELL_INIT\n\n\n\n# _LT_PROG_ECHO_BACKSLASH\n# -----------------------\n# Find how we can fake an echo command that does not interpret backslash.\n# In particular, with Autoconf 2.60 or later we add some code to the start\n# of the generated configure script which will find a shell with a builtin\n# printf (which we can use as an echo command).\nm4_defun([_LT_PROG_ECHO_BACKSLASH],\n[ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'\nECHO=$ECHO$ECHO$ECHO$ECHO$ECHO\nECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO\n\nAC_MSG_CHECKING([how to print strings])\n# Test print first, because it will be a builtin if present.\nif test \"X`print -r -- -n 2>/dev/null`\" = X-n && \\\n   test \"X`print -r -- $ECHO 2>/dev/null`\" = \"X$ECHO\"; then\n  ECHO='print -r --'\nelif test \"X`printf %s $ECHO 2>/dev/null`\" = \"X$ECHO\"; then\n  ECHO='printf %s\\n'\nelse\n  # Use this function as a fallback that always works.\n  func_fallback_echo ()\n  {\n    eval 'cat <<_LTECHO_EOF\n$[]1\n_LTECHO_EOF'\n  }\n  ECHO='func_fallback_echo'\nfi\n\n# func_echo_all arg...\n# Invoke $ECHO with all args, space-separated.\nfunc_echo_all ()\n{\n    $ECHO \"$*\" \n}\n\ncase \"$ECHO\" in\n  printf*) AC_MSG_RESULT([printf]) ;;\n  print*) AC_MSG_RESULT([print -r]) ;;\n  *) AC_MSG_RESULT([cat]) ;;\nesac\n\nm4_ifdef([_AS_DETECT_SUGGESTED],\n[_AS_DETECT_SUGGESTED([\n  test -n \"${ZSH_VERSION+set}${BASH_VERSION+set}\" || (\n    ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'\n    ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO\n    ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO\n    PATH=/empty FPATH=/empty; export PATH FPATH\n    test \"X`printf %s $ECHO`\" = \"X$ECHO\" \\\n      || test \"X`print -r -- $ECHO`\" = \"X$ECHO\" )])])\n\n_LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts])\n_LT_DECL([], [ECHO], [1], [An echo program that protects backslashes])\n])# _LT_PROG_ECHO_BACKSLASH\n\n\n# _LT_ENABLE_LOCK\n# ---------------\nm4_defun([_LT_ENABLE_LOCK],\n[AC_ARG_ENABLE([libtool-lock],\n  [AS_HELP_STRING([--disable-libtool-lock],\n    [avoid locking (might break parallel builds)])])\ntest \"x$enable_libtool_lock\" != xno && enable_libtool_lock=yes\n\n# Some flags need to be propagated to the compiler or linker for good\n# libtool support.\ncase $host in\nia64-*-hpux*)\n  # Find out which ABI we are using.\n  echo 'int i;' > conftest.$ac_ext\n  if AC_TRY_EVAL(ac_compile); then\n    case `/usr/bin/file conftest.$ac_objext` in\n      *ELF-32*)\n\tHPUX_IA64_MODE=\"32\"\n\t;;\n      *ELF-64*)\n\tHPUX_IA64_MODE=\"64\"\n\t;;\n    esac\n  fi\n  rm -rf conftest*\n  ;;\n*-*-irix6*)\n  # Find out which ABI we are using.\n  echo '[#]line '$LINENO' \"configure\"' > conftest.$ac_ext\n  if AC_TRY_EVAL(ac_compile); then\n    if test \"$lt_cv_prog_gnu_ld\" = yes; then\n      case `/usr/bin/file conftest.$ac_objext` in\n\t*32-bit*)\n\t  LD=\"${LD-ld} -melf32bsmip\"\n\t  ;;\n\t*N32*)\n\t  LD=\"${LD-ld} -melf32bmipn32\"\n\t  ;;\n\t*64-bit*)\n\t  LD=\"${LD-ld} -melf64bmip\"\n\t;;\n      esac\n    else\n      case `/usr/bin/file conftest.$ac_objext` in\n\t*32-bit*)\n\t  LD=\"${LD-ld} -32\"\n\t  ;;\n\t*N32*)\n\t  LD=\"${LD-ld} -n32\"\n\t  ;;\n\t*64-bit*)\n\t  LD=\"${LD-ld} -64\"\n\t  ;;\n      esac\n    fi\n  fi\n  rm -rf conftest*\n  ;;\n\nx86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \\\ns390*-*linux*|s390*-*tpf*|sparc*-*linux*)\n  # Find out which ABI we are using.\n  echo 'int i;' > conftest.$ac_ext\n  if AC_TRY_EVAL(ac_compile); then\n    case `/usr/bin/file conftest.o` in\n      *32-bit*)\n\tcase $host in\n\t  x86_64-*kfreebsd*-gnu)\n\t    LD=\"${LD-ld} -m elf_i386_fbsd\"\n\t    ;;\n\t  x86_64-*linux*)\n\t    case `/usr/bin/file conftest.o` in\n\t      *x86-64*)\n\t\tLD=\"${LD-ld} -m elf32_x86_64\"\n\t\t;;\n\t      *)\n\t\tLD=\"${LD-ld} -m elf_i386\"\n\t\t;;\n\t    esac\n\t    ;;\n\t  powerpc64le-*linux*)\n\t    LD=\"${LD-ld} -m elf32lppclinux\"\n\t    ;;\n\t  powerpc64-*linux*)\n\t    LD=\"${LD-ld} -m elf32ppclinux\"\n\t    ;;\n\t  s390x-*linux*)\n\t    LD=\"${LD-ld} -m elf_s390\"\n\t    ;;\n\t  sparc64-*linux*)\n\t    LD=\"${LD-ld} -m elf32_sparc\"\n\t    ;;\n\tesac\n\t;;\n      *64-bit*)\n\tcase $host in\n\t  x86_64-*kfreebsd*-gnu)\n\t    LD=\"${LD-ld} -m elf_x86_64_fbsd\"\n\t    ;;\n\t  x86_64-*linux*)\n\t    LD=\"${LD-ld} -m elf_x86_64\"\n\t    ;;\n\t  powerpcle-*linux*)\n\t    LD=\"${LD-ld} -m elf64lppc\"\n\t    ;;\n\t  powerpc-*linux*)\n\t    LD=\"${LD-ld} -m elf64ppc\"\n\t    ;;\n\t  s390*-*linux*|s390*-*tpf*)\n\t    LD=\"${LD-ld} -m elf64_s390\"\n\t    ;;\n\t  sparc*-*linux*)\n\t    LD=\"${LD-ld} -m elf64_sparc\"\n\t    ;;\n\tesac\n\t;;\n    esac\n  fi\n  rm -rf conftest*\n  ;;\n\n*-*-sco3.2v5*)\n  # On SCO OpenServer 5, we need -belf to get full-featured binaries.\n  SAVE_CFLAGS=\"$CFLAGS\"\n  CFLAGS=\"$CFLAGS -belf\"\n  AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf,\n    [AC_LANG_PUSH(C)\n     AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no])\n     AC_LANG_POP])\n  if test x\"$lt_cv_cc_needs_belf\" != x\"yes\"; then\n    # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf\n    CFLAGS=\"$SAVE_CFLAGS\"\n  fi\n  ;;\nsparc*-*solaris*)\n  # Find out which ABI we are using.\n  echo 'int i;' > conftest.$ac_ext\n  if AC_TRY_EVAL(ac_compile); then\n    case `/usr/bin/file conftest.o` in\n    *64-bit*)\n      case $lt_cv_prog_gnu_ld in\n      yes*) LD=\"${LD-ld} -m elf64_sparc\" ;;\n      *)\n\tif ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then\n\t  LD=\"${LD-ld} -64\"\n\tfi\n\t;;\n      esac\n      ;;\n    esac\n  fi\n  rm -rf conftest*\n  ;;\nesac\n\nneed_locks=\"$enable_libtool_lock\"\n])# _LT_ENABLE_LOCK\n\n\n# _LT_CMD_OLD_ARCHIVE\n# -------------------\nm4_defun([_LT_CMD_OLD_ARCHIVE],\n[plugin_option=\nplugin_names=\"liblto_plugin.so liblto_plugin-0.dll cyglto_plugin-0.dll\"\nfor plugin in $plugin_names; do\n  plugin_so=`${CC} ${CFLAGS} --print-prog-name $plugin`\n  if test x$plugin_so = x$plugin; then\n    plugin_so=`${CC} ${CFLAGS} --print-file-name $plugin`\n  fi\n  if test x$plugin_so != x$plugin; then\n    plugin_option=\"--plugin $plugin_so\"\n    break\n  fi\ndone\n\nAC_CHECK_TOOL(AR, ar, false)\ntest -z \"$AR\" && AR=ar\nif test -n \"$plugin_option\"; then\n  if $AR --help 2>&1 | grep -q \"\\--plugin\"; then\n    touch conftest.c\n    $AR $plugin_option rc conftest.a conftest.c\n    if test \"$?\" != 0; then\n      AC_MSG_WARN([Failed: $AR $plugin_option rc])\n    else\n      AR=\"$AR $plugin_option\"\n    fi\n    rm -f conftest.*\n  fi\nfi\ntest -z \"$AR_FLAGS\" && AR_FLAGS=cru\n_LT_DECL([], [AR], [1], [The archiver])\n_LT_DECL([], [AR_FLAGS], [1])\n\nAC_CHECK_TOOL(STRIP, strip, :)\ntest -z \"$STRIP\" && STRIP=:\n_LT_DECL([], [STRIP], [1], [A symbol stripping program])\n\nAC_CHECK_TOOL(RANLIB, ranlib, :)\ntest -z \"$RANLIB\" && RANLIB=:\nif test -n \"$plugin_option\" && test \"$RANLIB\" != \":\"; then\n  if $RANLIB --help 2>&1 | grep -q \"\\--plugin\"; then\n    RANLIB=\"$RANLIB $plugin_option\"\n  fi\nfi\n_LT_DECL([], [RANLIB], [1],\n    [Commands used to install an old-style archive])\n\n# Determine commands to create old-style static archives.\nold_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs'\nold_postinstall_cmds='chmod 644 $oldlib'\nold_postuninstall_cmds=\n\nif test -n \"$RANLIB\"; then\n  case $host_os in\n  openbsd*)\n    old_postinstall_cmds=\"$old_postinstall_cmds~\\$RANLIB -t \\$oldlib\"\n    ;;\n  *)\n    old_postinstall_cmds=\"$old_postinstall_cmds~\\$RANLIB \\$oldlib\"\n    ;;\n  esac\n  old_archive_cmds=\"$old_archive_cmds~\\$RANLIB \\$oldlib\"\nfi\n\ncase $host_os in\n  darwin*)\n    lock_old_archive_extraction=yes ;;\n  *)\n    lock_old_archive_extraction=no ;;\nesac\n_LT_DECL([], [old_postinstall_cmds], [2])\n_LT_DECL([], [old_postuninstall_cmds], [2])\n_LT_TAGDECL([], [old_archive_cmds], [2],\n    [Commands used to build an old-style archive])\n_LT_DECL([], [lock_old_archive_extraction], [0],\n    [Whether to use a lock for old archive extraction])\n])# _LT_CMD_OLD_ARCHIVE\n\n\n# _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,\n#\t\t[OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE])\n# ----------------------------------------------------------------\n# Check whether the given compiler option works\nAC_DEFUN([_LT_COMPILER_OPTION],\n[m4_require([_LT_FILEUTILS_DEFAULTS])dnl\nm4_require([_LT_DECL_SED])dnl\nAC_CACHE_CHECK([$1], [$2],\n  [$2=no\n   m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4])\n   echo \"$lt_simple_compile_test_code\" > conftest.$ac_ext\n   lt_compiler_flag=\"$3\"\n   # Insert the option either (1) after the last *FLAGS variable, or\n   # (2) before a word containing \"conftest.\", or (3) at the end.\n   # Note that $ac_compile itself does not contain backslashes and begins\n   # with a dollar sign (not a hyphen), so the echo should work correctly.\n   # The option is referenced via a variable to avoid confusing sed.\n   lt_compile=`echo \"$ac_compile\" | $SED \\\n   -e 's:.*FLAGS}\\{0,1\\} :&$lt_compiler_flag :; t' \\\n   -e 's: [[^ ]]*conftest\\.: $lt_compiler_flag&:; t' \\\n   -e 's:$: $lt_compiler_flag:'`\n   (eval echo \"\\\"\\$as_me:$LINENO: $lt_compile\\\"\" >&AS_MESSAGE_LOG_FD)\n   (eval \"$lt_compile\" 2>conftest.err)\n   ac_status=$?\n   cat conftest.err >&AS_MESSAGE_LOG_FD\n   echo \"$as_me:$LINENO: \\$? = $ac_status\" >&AS_MESSAGE_LOG_FD\n   if (exit $ac_status) && test -s \"$ac_outfile\"; then\n     # The compiler can only warn and ignore the option if not recognized\n     # So say no if there are warnings other than the usual output.\n     $ECHO \"$_lt_compiler_boilerplate\" | $SED '/^$/d' >conftest.exp\n     $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2\n     if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then\n       $2=yes\n     fi\n   fi\n   $RM conftest*\n])\n\nif test x\"[$]$2\" = xyes; then\n    m4_if([$5], , :, [$5])\nelse\n    m4_if([$6], , :, [$6])\nfi\n])# _LT_COMPILER_OPTION\n\n# Old name:\nAU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION])\ndnl aclocal-1.4 backwards compatibility:\ndnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], [])\n\n\n# _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,\n#                  [ACTION-SUCCESS], [ACTION-FAILURE])\n# ----------------------------------------------------\n# Check whether the given linker option works\nAC_DEFUN([_LT_LINKER_OPTION],\n[m4_require([_LT_FILEUTILS_DEFAULTS])dnl\nm4_require([_LT_DECL_SED])dnl\nAC_CACHE_CHECK([$1], [$2],\n  [$2=no\n   save_LDFLAGS=\"$LDFLAGS\"\n   LDFLAGS=\"$LDFLAGS $3\"\n   echo \"$lt_simple_link_test_code\" > conftest.$ac_ext\n   if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then\n     # The linker can only warn and ignore the option if not recognized\n     # So say no if there are warnings\n     if test -s conftest.err; then\n       # Append any errors to the config.log.\n       cat conftest.err 1>&AS_MESSAGE_LOG_FD\n       $ECHO \"$_lt_linker_boilerplate\" | $SED '/^$/d' > conftest.exp\n       $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2\n       if diff conftest.exp conftest.er2 >/dev/null; then\n         $2=yes\n       fi\n     else\n       $2=yes\n     fi\n   fi\n   $RM -r conftest*\n   LDFLAGS=\"$save_LDFLAGS\"\n])\n\nif test x\"[$]$2\" = xyes; then\n    m4_if([$4], , :, [$4])\nelse\n    m4_if([$5], , :, [$5])\nfi\n])# _LT_LINKER_OPTION\n\n# Old name:\nAU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION])\ndnl aclocal-1.4 backwards compatibility:\ndnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], [])\n\n\n# LT_CMD_MAX_LEN\n#---------------\nAC_DEFUN([LT_CMD_MAX_LEN],\n[AC_REQUIRE([AC_CANONICAL_HOST])dnl\n# find the maximum length of command line arguments\nAC_MSG_CHECKING([the maximum length of command line arguments])\nAC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl\n  i=0\n  teststring=\"ABCD\"\n\n  case $build_os in\n  msdosdjgpp*)\n    # On DJGPP, this test can blow up pretty badly due to problems in libc\n    # (any single argument exceeding 2000 bytes causes a buffer overrun\n    # during glob expansion).  Even if it were fixed, the result of this\n    # check would be larger than it should be.\n    lt_cv_sys_max_cmd_len=12288;    # 12K is about right\n    ;;\n\n  gnu*)\n    # Under GNU Hurd, this test is not required because there is\n    # no limit to the length of command line arguments.\n    # Libtool will interpret -1 as no limit whatsoever\n    lt_cv_sys_max_cmd_len=-1;\n    ;;\n\n  cygwin* | mingw* | cegcc*)\n    # On Win9x/ME, this test blows up -- it succeeds, but takes\n    # about 5 minutes as the teststring grows exponentially.\n    # Worse, since 9x/ME are not pre-emptively multitasking,\n    # you end up with a \"frozen\" computer, even though with patience\n    # the test eventually succeeds (with a max line length of 256k).\n    # Instead, let's just punt: use the minimum linelength reported by\n    # all of the supported platforms: 8192 (on NT/2K/XP).\n    lt_cv_sys_max_cmd_len=8192;\n    ;;\n\n  mint*)\n    # On MiNT this can take a long time and run out of memory.\n    lt_cv_sys_max_cmd_len=8192;\n    ;;\n\n  amigaos*)\n    # On AmigaOS with pdksh, this test takes hours, literally.\n    # So we just punt and use a minimum line length of 8192.\n    lt_cv_sys_max_cmd_len=8192;\n    ;;\n\n  netbsd* | freebsd* | openbsd* | darwin* | dragonfly*)\n    # This has been around since 386BSD, at least.  Likely further.\n    if test -x /sbin/sysctl; then\n      lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`\n    elif test -x /usr/sbin/sysctl; then\n      lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`\n    else\n      lt_cv_sys_max_cmd_len=65536\t# usable default for all BSDs\n    fi\n    # And add a safety zone\n    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \\/ 4`\n    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \\* 3`\n    ;;\n\n  interix*)\n    # We know the value 262144 and hardcode it with a safety zone (like BSD)\n    lt_cv_sys_max_cmd_len=196608\n    ;;\n\n  osf*)\n    # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure\n    # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not\n    # nice to cause kernel panics so lets avoid the loop below.\n    # First set a reasonable default.\n    lt_cv_sys_max_cmd_len=16384\n    #\n    if test -x /sbin/sysconfig; then\n      case `/sbin/sysconfig -q proc exec_disable_arg_limit` in\n        *1*) lt_cv_sys_max_cmd_len=-1 ;;\n      esac\n    fi\n    ;;\n  sco3.2v5*)\n    lt_cv_sys_max_cmd_len=102400\n    ;;\n  sysv5* | sco5v6* | sysv4.2uw2*)\n    kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`\n    if test -n \"$kargmax\"; then\n      lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[\t ]]//'`\n    else\n      lt_cv_sys_max_cmd_len=32768\n    fi\n    ;;\n  *)\n    lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null`\n    if test -n \"$lt_cv_sys_max_cmd_len\"; then\n      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \\/ 4`\n      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \\* 3`\n    else\n      # Make teststring a little bigger before we do anything with it.\n      # a 1K string should be a reasonable start.\n      for i in 1 2 3 4 5 6 7 8 ; do\n        teststring=$teststring$teststring\n      done\n      SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}\n      # If test is not a shell built-in, we'll probably end up computing a\n      # maximum length that is only half of the actual maximum length, but\n      # we can't tell.\n      while { test \"X\"`func_fallback_echo \"$teststring$teststring\" 2>/dev/null` \\\n\t         = \"X$teststring$teststring\"; } >/dev/null 2>&1 &&\n\t      test $i != 17 # 1/2 MB should be enough\n      do\n        i=`expr $i + 1`\n        teststring=$teststring$teststring\n      done\n      # Only check the string length outside the loop.\n      lt_cv_sys_max_cmd_len=`expr \"X$teststring\" : \".*\" 2>&1`\n      teststring=\n      # Add a significant safety factor because C++ compilers can tack on\n      # massive amounts of additional arguments before passing them to the\n      # linker.  It appears as though 1/2 is a usable value.\n      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \\/ 2`\n    fi\n    ;;\n  esac\n])\nif test -n $lt_cv_sys_max_cmd_len ; then\n  AC_MSG_RESULT($lt_cv_sys_max_cmd_len)\nelse\n  AC_MSG_RESULT(none)\nfi\nmax_cmd_len=$lt_cv_sys_max_cmd_len\n_LT_DECL([], [max_cmd_len], [0],\n    [What is the maximum length of a command?])\n])# LT_CMD_MAX_LEN\n\n# Old name:\nAU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN])\ndnl aclocal-1.4 backwards compatibility:\ndnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], [])\n\n\n# _LT_HEADER_DLFCN\n# ----------------\nm4_defun([_LT_HEADER_DLFCN],\n[AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl\n])# _LT_HEADER_DLFCN\n\n\n# _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE,\n#                      ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING)\n# ----------------------------------------------------------------\nm4_defun([_LT_TRY_DLOPEN_SELF],\n[m4_require([_LT_HEADER_DLFCN])dnl\nif test \"$cross_compiling\" = yes; then :\n  [$4]\nelse\n  lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2\n  lt_status=$lt_dlunknown\n  cat > conftest.$ac_ext <<_LT_EOF\n[#line __oline__ \"configure\"\n#include \"confdefs.h\"\n\n#if HAVE_DLFCN_H\n#include <dlfcn.h>\n#endif\n\n#include <stdio.h>\n\n#ifdef RTLD_GLOBAL\n#  define LT_DLGLOBAL\t\tRTLD_GLOBAL\n#else\n#  ifdef DL_GLOBAL\n#    define LT_DLGLOBAL\t\tDL_GLOBAL\n#  else\n#    define LT_DLGLOBAL\t\t0\n#  endif\n#endif\n\n/* We may have to define LT_DLLAZY_OR_NOW in the command line if we\n   find out it does not work in some platform. */\n#ifndef LT_DLLAZY_OR_NOW\n#  ifdef RTLD_LAZY\n#    define LT_DLLAZY_OR_NOW\t\tRTLD_LAZY\n#  else\n#    ifdef DL_LAZY\n#      define LT_DLLAZY_OR_NOW\t\tDL_LAZY\n#    else\n#      ifdef RTLD_NOW\n#        define LT_DLLAZY_OR_NOW\tRTLD_NOW\n#      else\n#        ifdef DL_NOW\n#          define LT_DLLAZY_OR_NOW\tDL_NOW\n#        else\n#          define LT_DLLAZY_OR_NOW\t0\n#        endif\n#      endif\n#    endif\n#  endif\n#endif\n\n/* When -fvisbility=hidden is used, assume the code has been annotated\n   correspondingly for the symbols needed.  */\n#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))\nvoid fnord () __attribute__((visibility(\"default\")));\n#endif\n\nvoid fnord () { int i=42; }\nint main ()\n{\n  void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);\n  int status = $lt_dlunknown;\n\n  if (self)\n    {\n      if (dlsym (self,\"fnord\"))       status = $lt_dlno_uscore;\n      else\n        {\n\t  if (dlsym( self,\"_fnord\"))  status = $lt_dlneed_uscore;\n          else puts (dlerror ());\n\t}\n      /* dlclose (self); */\n    }\n  else\n    puts (dlerror ());\n\n  return status;\n}]\n_LT_EOF\n  if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then\n    (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null\n    lt_status=$?\n    case x$lt_status in\n      x$lt_dlno_uscore) $1 ;;\n      x$lt_dlneed_uscore) $2 ;;\n      x$lt_dlunknown|x*) $3 ;;\n    esac\n  else :\n    # compilation failed\n    $3\n  fi\nfi\nrm -fr conftest*\n])# _LT_TRY_DLOPEN_SELF\n\n\n# LT_SYS_DLOPEN_SELF\n# ------------------\nAC_DEFUN([LT_SYS_DLOPEN_SELF],\n[m4_require([_LT_HEADER_DLFCN])dnl\nif test \"x$enable_dlopen\" != xyes; then\n  enable_dlopen=unknown\n  enable_dlopen_self=unknown\n  enable_dlopen_self_static=unknown\nelse\n  lt_cv_dlopen=no\n  lt_cv_dlopen_libs=\n\n  case $host_os in\n  beos*)\n    lt_cv_dlopen=\"load_add_on\"\n    lt_cv_dlopen_libs=\n    lt_cv_dlopen_self=yes\n    ;;\n\n  mingw* | pw32* | cegcc*)\n    lt_cv_dlopen=\"LoadLibrary\"\n    lt_cv_dlopen_libs=\n    ;;\n\n  cygwin*)\n    lt_cv_dlopen=\"dlopen\"\n    lt_cv_dlopen_libs=\n    ;;\n\n  darwin*)\n  # if libdl is installed we need to link against it\n    AC_CHECK_LIB([dl], [dlopen],\n\t\t[lt_cv_dlopen=\"dlopen\" lt_cv_dlopen_libs=\"-ldl\"],[\n    lt_cv_dlopen=\"dyld\"\n    lt_cv_dlopen_libs=\n    lt_cv_dlopen_self=yes\n    ])\n    ;;\n\n  *)\n    AC_CHECK_FUNC([shl_load],\n\t  [lt_cv_dlopen=\"shl_load\"],\n      [AC_CHECK_LIB([dld], [shl_load],\n\t    [lt_cv_dlopen=\"shl_load\" lt_cv_dlopen_libs=\"-ldld\"],\n\t[AC_CHECK_FUNC([dlopen],\n\t      [lt_cv_dlopen=\"dlopen\"],\n\t  [AC_CHECK_LIB([dl], [dlopen],\n\t\t[lt_cv_dlopen=\"dlopen\" lt_cv_dlopen_libs=\"-ldl\"],\n\t    [AC_CHECK_LIB([svld], [dlopen],\n\t\t  [lt_cv_dlopen=\"dlopen\" lt_cv_dlopen_libs=\"-lsvld\"],\n\t      [AC_CHECK_LIB([dld], [dld_link],\n\t\t    [lt_cv_dlopen=\"dld_link\" lt_cv_dlopen_libs=\"-ldld\"])\n\t      ])\n\t    ])\n\t  ])\n\t])\n      ])\n    ;;\n  esac\n\n  if test \"x$lt_cv_dlopen\" != xno; then\n    enable_dlopen=yes\n  else\n    enable_dlopen=no\n  fi\n\n  case $lt_cv_dlopen in\n  dlopen)\n    save_CPPFLAGS=\"$CPPFLAGS\"\n    test \"x$ac_cv_header_dlfcn_h\" = xyes && CPPFLAGS=\"$CPPFLAGS -DHAVE_DLFCN_H\"\n\n    save_LDFLAGS=\"$LDFLAGS\"\n    wl=$lt_prog_compiler_wl eval LDFLAGS=\\\"\\$LDFLAGS $export_dynamic_flag_spec\\\"\n\n    save_LIBS=\"$LIBS\"\n    LIBS=\"$lt_cv_dlopen_libs $LIBS\"\n\n    AC_CACHE_CHECK([whether a program can dlopen itself],\n\t  lt_cv_dlopen_self, [dnl\n\t  _LT_TRY_DLOPEN_SELF(\n\t    lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes,\n\t    lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross)\n    ])\n\n    if test \"x$lt_cv_dlopen_self\" = xyes; then\n      wl=$lt_prog_compiler_wl eval LDFLAGS=\\\"\\$LDFLAGS $lt_prog_compiler_static\\\"\n      AC_CACHE_CHECK([whether a statically linked program can dlopen itself],\n\t  lt_cv_dlopen_self_static, [dnl\n\t  _LT_TRY_DLOPEN_SELF(\n\t    lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes,\n\t    lt_cv_dlopen_self_static=no,  lt_cv_dlopen_self_static=cross)\n      ])\n    fi\n\n    CPPFLAGS=\"$save_CPPFLAGS\"\n    LDFLAGS=\"$save_LDFLAGS\"\n    LIBS=\"$save_LIBS\"\n    ;;\n  esac\n\n  case $lt_cv_dlopen_self in\n  yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;\n  *) enable_dlopen_self=unknown ;;\n  esac\n\n  case $lt_cv_dlopen_self_static in\n  yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;\n  *) enable_dlopen_self_static=unknown ;;\n  esac\nfi\n_LT_DECL([dlopen_support], [enable_dlopen], [0],\n\t [Whether dlopen is supported])\n_LT_DECL([dlopen_self], [enable_dlopen_self], [0],\n\t [Whether dlopen of programs is supported])\n_LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0],\n\t [Whether dlopen of statically linked programs is supported])\n])# LT_SYS_DLOPEN_SELF\n\n# Old name:\nAU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF])\ndnl aclocal-1.4 backwards compatibility:\ndnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], [])\n\n\n# _LT_COMPILER_C_O([TAGNAME])\n# ---------------------------\n# Check to see if options -c and -o are simultaneously supported by compiler.\n# This macro does not hard code the compiler like AC_PROG_CC_C_O.\nm4_defun([_LT_COMPILER_C_O],\n[m4_require([_LT_DECL_SED])dnl\nm4_require([_LT_FILEUTILS_DEFAULTS])dnl\nm4_require([_LT_TAG_COMPILER])dnl\nAC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext],\n  [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)],\n  [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no\n   $RM -r conftest 2>/dev/null\n   mkdir conftest\n   cd conftest\n   mkdir out\n   echo \"$lt_simple_compile_test_code\" > conftest.$ac_ext\n\n   lt_compiler_flag=\"-o out/conftest2.$ac_objext\"\n   # Insert the option either (1) after the last *FLAGS variable, or\n   # (2) before a word containing \"conftest.\", or (3) at the end.\n   # Note that $ac_compile itself does not contain backslashes and begins\n   # with a dollar sign (not a hyphen), so the echo should work correctly.\n   lt_compile=`echo \"$ac_compile\" | $SED \\\n   -e 's:.*FLAGS}\\{0,1\\} :&$lt_compiler_flag :; t' \\\n   -e 's: [[^ ]]*conftest\\.: $lt_compiler_flag&:; t' \\\n   -e 's:$: $lt_compiler_flag:'`\n   (eval echo \"\\\"\\$as_me:$LINENO: $lt_compile\\\"\" >&AS_MESSAGE_LOG_FD)\n   (eval \"$lt_compile\" 2>out/conftest.err)\n   ac_status=$?\n   cat out/conftest.err >&AS_MESSAGE_LOG_FD\n   echo \"$as_me:$LINENO: \\$? = $ac_status\" >&AS_MESSAGE_LOG_FD\n   if (exit $ac_status) && test -s out/conftest2.$ac_objext\n   then\n     # The compiler can only warn and ignore the option if not recognized\n     # So say no if there are warnings\n     $ECHO \"$_lt_compiler_boilerplate\" | $SED '/^$/d' > out/conftest.exp\n     $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2\n     if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then\n       _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes\n     fi\n   fi\n   chmod u+w . 2>&AS_MESSAGE_LOG_FD\n   $RM conftest*\n   # SGI C++ compiler will create directory out/ii_files/ for\n   # template instantiation\n   test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files\n   $RM out/* && rmdir out\n   cd ..\n   $RM -r conftest\n   $RM conftest*\n])\n_LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1],\n\t[Does compiler simultaneously support -c and -o options?])\n])# _LT_COMPILER_C_O\n\n\n# _LT_COMPILER_FILE_LOCKS([TAGNAME])\n# ----------------------------------\n# Check to see if we can do hard links to lock some files if needed\nm4_defun([_LT_COMPILER_FILE_LOCKS],\n[m4_require([_LT_ENABLE_LOCK])dnl\nm4_require([_LT_FILEUTILS_DEFAULTS])dnl\n_LT_COMPILER_C_O([$1])\n\nhard_links=\"nottested\"\nif test \"$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)\" = no && test \"$need_locks\" != no; then\n  # do not overwrite the value of need_locks provided by the user\n  AC_MSG_CHECKING([if we can lock with hard links])\n  hard_links=yes\n  $RM conftest*\n  ln conftest.a conftest.b 2>/dev/null && hard_links=no\n  touch conftest.a\n  ln conftest.a conftest.b 2>&5 || hard_links=no\n  ln conftest.a conftest.b 2>/dev/null && hard_links=no\n  AC_MSG_RESULT([$hard_links])\n  if test \"$hard_links\" = no; then\n    AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe])\n    need_locks=warn\n  fi\nelse\n  need_locks=no\nfi\n_LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?])\n])# _LT_COMPILER_FILE_LOCKS\n\n\n# _LT_CHECK_OBJDIR\n# ----------------\nm4_defun([_LT_CHECK_OBJDIR],\n[AC_CACHE_CHECK([for objdir], [lt_cv_objdir],\n[rm -f .libs 2>/dev/null\nmkdir .libs 2>/dev/null\nif test -d .libs; then\n  lt_cv_objdir=.libs\nelse\n  # MS-DOS does not allow filenames that begin with a dot.\n  lt_cv_objdir=_libs\nfi\nrmdir .libs 2>/dev/null])\nobjdir=$lt_cv_objdir\n_LT_DECL([], [objdir], [0],\n         [The name of the directory that contains temporary libtool files])dnl\nm4_pattern_allow([LT_OBJDIR])dnl\nAC_DEFINE_UNQUOTED(LT_OBJDIR, \"$lt_cv_objdir/\",\n  [Define to the sub-directory in which libtool stores uninstalled libraries.])\n])# _LT_CHECK_OBJDIR\n\n\n# _LT_LINKER_HARDCODE_LIBPATH([TAGNAME])\n# --------------------------------------\n# Check hardcoding attributes.\nm4_defun([_LT_LINKER_HARDCODE_LIBPATH],\n[AC_MSG_CHECKING([how to hardcode library paths into programs])\n_LT_TAGVAR(hardcode_action, $1)=\nif test -n \"$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\" ||\n   test -n \"$_LT_TAGVAR(runpath_var, $1)\" ||\n   test \"X$_LT_TAGVAR(hardcode_automatic, $1)\" = \"Xyes\" ; then\n\n  # We can hardcode non-existent directories.\n  if test \"$_LT_TAGVAR(hardcode_direct, $1)\" != no &&\n     # If the only mechanism to avoid hardcoding is shlibpath_var, we\n     # have to relink, otherwise we might link with an installed library\n     # when we should be linking with a yet-to-be-installed one\n     ## test \"$_LT_TAGVAR(hardcode_shlibpath_var, $1)\" != no &&\n     test \"$_LT_TAGVAR(hardcode_minus_L, $1)\" != no; then\n    # Linking always hardcodes the temporary library directory.\n    _LT_TAGVAR(hardcode_action, $1)=relink\n  else\n    # We can link without hardcoding, and we can hardcode nonexisting dirs.\n    _LT_TAGVAR(hardcode_action, $1)=immediate\n  fi\nelse\n  # We cannot hardcode anything, or else we can only hardcode existing\n  # directories.\n  _LT_TAGVAR(hardcode_action, $1)=unsupported\nfi\nAC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)])\n\nif test \"$_LT_TAGVAR(hardcode_action, $1)\" = relink ||\n   test \"$_LT_TAGVAR(inherit_rpath, $1)\" = yes; then\n  # Fast installation is not supported\n  enable_fast_install=no\nelif test \"$shlibpath_overrides_runpath\" = yes ||\n     test \"$enable_shared\" = no; then\n  # Fast installation is not necessary\n  enable_fast_install=needless\nfi\n_LT_TAGDECL([], [hardcode_action], [0],\n    [How to hardcode a shared library path into an executable])\n])# _LT_LINKER_HARDCODE_LIBPATH\n\n\n# _LT_CMD_STRIPLIB\n# ----------------\nm4_defun([_LT_CMD_STRIPLIB],\n[m4_require([_LT_DECL_EGREP])\nstriplib=\nold_striplib=\nAC_MSG_CHECKING([whether stripping libraries is possible])\nif test -n \"$STRIP\" && $STRIP -V 2>&1 | $GREP \"GNU strip\" >/dev/null; then\n  test -z \"$old_striplib\" && old_striplib=\"$STRIP --strip-debug\"\n  test -z \"$striplib\" && striplib=\"$STRIP --strip-unneeded\"\n  AC_MSG_RESULT([yes])\nelse\n# FIXME - insert some real tests, host_os isn't really good enough\n  case $host_os in\n  darwin*)\n    if test -n \"$STRIP\" ; then\n      striplib=\"$STRIP -x\"\n      old_striplib=\"$STRIP -S\"\n      AC_MSG_RESULT([yes])\n    else\n      AC_MSG_RESULT([no])\n    fi\n    ;;\n  *)\n    AC_MSG_RESULT([no])\n    ;;\n  esac\nfi\n_LT_DECL([], [old_striplib], [1], [Commands to strip libraries])\n_LT_DECL([], [striplib], [1])\n])# _LT_CMD_STRIPLIB\n\n\n# _LT_SYS_DYNAMIC_LINKER([TAG])\n# -----------------------------\n# PORTME Fill in your ld.so characteristics\nm4_defun([_LT_SYS_DYNAMIC_LINKER],\n[AC_REQUIRE([AC_CANONICAL_HOST])dnl\nm4_require([_LT_DECL_EGREP])dnl\nm4_require([_LT_FILEUTILS_DEFAULTS])dnl\nm4_require([_LT_DECL_OBJDUMP])dnl\nm4_require([_LT_DECL_SED])dnl\nm4_require([_LT_CHECK_SHELL_FEATURES])dnl\nAC_MSG_CHECKING([dynamic linker characteristics])\nm4_if([$1],\n\t[], [\nif test \"$GCC\" = yes; then\n  case $host_os in\n    darwin*) lt_awk_arg=\"/^libraries:/,/LR/\" ;;\n    *) lt_awk_arg=\"/^libraries:/\" ;;\n  esac\n  case $host_os in\n    mingw* | cegcc*) lt_sed_strip_eq=\"s,=\\([[A-Za-z]]:\\),\\1,g\" ;;\n    *) lt_sed_strip_eq=\"s,=/,/,g\" ;;\n  esac\n  lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e \"s/^libraries://\" -e $lt_sed_strip_eq`\n  case $lt_search_path_spec in\n  *\\;*)\n    # if the path contains \";\" then we assume it to be the separator\n    # otherwise default to the standard path separator (i.e. \":\") - it is\n    # assumed that no part of a normal pathname contains \";\" but that should\n    # okay in the real world where \";\" in dirpaths is itself problematic.\n    lt_search_path_spec=`$ECHO \"$lt_search_path_spec\" | $SED 's/;/ /g'`\n    ;;\n  *)\n    lt_search_path_spec=`$ECHO \"$lt_search_path_spec\" | $SED \"s/$PATH_SEPARATOR/ /g\"`\n    ;;\n  esac\n  # Ok, now we have the path, separated by spaces, we can step through it\n  # and add multilib dir if necessary.\n  lt_tmp_lt_search_path_spec=\n  lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null`\n  for lt_sys_path in $lt_search_path_spec; do\n    if test -d \"$lt_sys_path/$lt_multi_os_dir\"; then\n      lt_tmp_lt_search_path_spec=\"$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir\"\n    else\n      test -d \"$lt_sys_path\" && \\\n\tlt_tmp_lt_search_path_spec=\"$lt_tmp_lt_search_path_spec $lt_sys_path\"\n    fi\n  done\n  lt_search_path_spec=`$ECHO \"$lt_tmp_lt_search_path_spec\" | awk '\nBEGIN {RS=\" \"; FS=\"/|\\n\";} {\n  lt_foo=\"\";\n  lt_count=0;\n  for (lt_i = NF; lt_i > 0; lt_i--) {\n    if ($lt_i != \"\" && $lt_i != \".\") {\n      if ($lt_i == \"..\") {\n        lt_count++;\n      } else {\n        if (lt_count == 0) {\n          lt_foo=\"/\" $lt_i lt_foo;\n        } else {\n          lt_count--;\n        }\n      }\n    }\n  }\n  if (lt_foo != \"\") { lt_freq[[lt_foo]]++; }\n  if (lt_freq[[lt_foo]] == 1) { print lt_foo; }\n}'`\n  # AWK program above erroneously prepends '/' to C:/dos/paths\n  # for these hosts.\n  case $host_os in\n    mingw* | cegcc*) lt_search_path_spec=`$ECHO \"$lt_search_path_spec\" |\\\n      $SED 's,/\\([[A-Za-z]]:\\),\\1,g'` ;;\n  esac\n  sys_lib_search_path_spec=`$ECHO \"$lt_search_path_spec\" | $lt_NL2SP`\nelse\n  sys_lib_search_path_spec=\"/lib /usr/lib /usr/local/lib\"\nfi])\nlibrary_names_spec=\nlibname_spec='lib$name'\nsoname_spec=\nshrext_cmds=\".so\"\npostinstall_cmds=\npostuninstall_cmds=\nfinish_cmds=\nfinish_eval=\nshlibpath_var=\nshlibpath_overrides_runpath=unknown\nversion_type=none\ndynamic_linker=\"$host_os ld.so\"\nsys_lib_dlsearch_path_spec=\"/lib /usr/lib\"\nneed_lib_prefix=unknown\nhardcode_into_libs=no\n\n# when you set need_version to no, make sure it does not cause -set_version\n# flags to be left without arguments\nneed_version=unknown\n\ncase $host_os in\naix3*)\n  version_type=linux\n  library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'\n  shlibpath_var=LIBPATH\n\n  # AIX 3 has no versioning support, so we append a major version to the name.\n  soname_spec='${libname}${release}${shared_ext}$major'\n  ;;\n\naix[[4-9]]*)\n  version_type=linux\n  need_lib_prefix=no\n  need_version=no\n  hardcode_into_libs=yes\n  if test \"$host_cpu\" = ia64; then\n    # AIX 5 supports IA64\n    library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'\n    shlibpath_var=LD_LIBRARY_PATH\n  else\n    # With GCC up to 2.95.x, collect2 would create an import file\n    # for dependence libraries.  The import file would start with\n    # the line `#! .'.  This would cause the generated library to\n    # depend on `.', always an invalid library.  This was fixed in\n    # development snapshots of GCC prior to 3.0.\n    case $host_os in\n      aix4 | aix4.[[01]] | aix4.[[01]].*)\n      if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'\n\t   echo ' yes '\n\t   echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then\n\t:\n      else\n\tcan_build_shared=no\n      fi\n      ;;\n    esac\n    # AIX (on Power*) has no versioning support, so currently we can not hardcode correct\n    # soname into executable. Probably we can add versioning support to\n    # collect2, so additional links can be useful in future.\n    if test \"$aix_use_runtimelinking\" = yes; then\n      # If using run time linking (on AIX 4.2 or later) use lib<name>.so\n      # instead of lib<name>.a to let people know that these are not\n      # typical AIX shared libraries.\n      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'\n    else\n      # We preserve .a as extension for shared libraries through AIX4.2\n      # and later when we are not doing run time linking.\n      library_names_spec='${libname}${release}.a $libname.a'\n      soname_spec='${libname}${release}${shared_ext}$major'\n    fi\n    shlibpath_var=LIBPATH\n  fi\n  ;;\n\namigaos*)\n  case $host_cpu in\n  powerpc)\n    # Since July 2007 AmigaOS4 officially supports .so libraries.\n    # When compiling the executable, add -use-dynld -Lsobjs: to the compileline.\n    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'\n    ;;\n  m68k)\n    library_names_spec='$libname.ixlibrary $libname.a'\n    # Create ${libname}_ixlibrary.a entries in /sys/libs.\n    finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all \"$lib\" | $SED '\\''s%^.*/\\([[^/]]*\\)\\.ixlibrary$%\\1%'\\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show \"cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a\"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'\n    ;;\n  esac\n  ;;\n\nbeos*)\n  library_names_spec='${libname}${shared_ext}'\n  dynamic_linker=\"$host_os ld.so\"\n  shlibpath_var=LIBRARY_PATH\n  ;;\n\nbsdi[[45]]*)\n  version_type=linux\n  need_version=no\n  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'\n  soname_spec='${libname}${release}${shared_ext}$major'\n  finish_cmds='PATH=\"\\$PATH:/sbin\" ldconfig $libdir'\n  shlibpath_var=LD_LIBRARY_PATH\n  sys_lib_search_path_spec=\"/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib\"\n  sys_lib_dlsearch_path_spec=\"/shlib /usr/lib /usr/local/lib\"\n  # the default ld.so.conf also contains /usr/contrib/lib and\n  # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow\n  # libtool to hard-code these into programs\n  ;;\n\ncygwin* | mingw* | pw32* | cegcc*)\n  version_type=windows\n  shrext_cmds=\".dll\"\n  need_version=no\n  need_lib_prefix=no\n\n  case $GCC,$host_os in\n  yes,cygwin* | yes,mingw* | yes,pw32* | yes,cegcc*)\n    library_names_spec='$libname.dll.a'\n    # DLL is installed to $(libdir)/../bin by postinstall_cmds\n    postinstall_cmds='base_file=`basename \\${file}`~\n      dlpath=`$SHELL 2>&1 -c '\\''. $dir/'\\''\\${base_file}'\\''i; echo \\$dlname'\\''`~\n      dldir=$destdir/`dirname \\$dlpath`~\n      test -d \\$dldir || mkdir -p \\$dldir~\n      $install_prog $dir/$dlname \\$dldir/$dlname~\n      chmod a+x \\$dldir/$dlname~\n      if test -n '\\''$stripme'\\'' && test -n '\\''$striplib'\\''; then\n        eval '\\''$striplib \\$dldir/$dlname'\\'' || exit \\$?;\n      fi'\n    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\\''. $file; echo \\$dlname'\\''`~\n      dlpath=$dir/\\$dldll~\n       $RM \\$dlpath'\n    shlibpath_overrides_runpath=yes\n\n    case $host_os in\n    cygwin*)\n      # Cygwin DLLs use 'cyg' prefix rather than 'lib'\n      soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'\nm4_if([$1], [],[\n      sys_lib_search_path_spec=\"$sys_lib_search_path_spec /usr/lib/w32api\"])\n      ;;\n    mingw* | cegcc*)\n      # MinGW DLLs use traditional 'lib' prefix\n      soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'\n      ;;\n    pw32*)\n      # pw32 DLLs use 'pw' prefix rather than 'lib'\n      library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'\n      ;;\n    esac\n    ;;\n\n  *)\n    library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib'\n    ;;\n  esac\n  dynamic_linker='Win32 ld.exe'\n  # FIXME: first we should search . and the directory the executable is in\n  shlibpath_var=PATH\n  ;;\n\ndarwin* | rhapsody*)\n  dynamic_linker=\"$host_os dyld\"\n  version_type=darwin\n  need_lib_prefix=no\n  need_version=no\n  library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext'\n  soname_spec='${libname}${release}${major}$shared_ext'\n  shlibpath_overrides_runpath=yes\n  shlibpath_var=DYLD_LIBRARY_PATH\n  shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'\nm4_if([$1], [],[\n  sys_lib_search_path_spec=\"$sys_lib_search_path_spec /usr/local/lib\"])\n  sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'\n  ;;\n\ndgux*)\n  version_type=linux\n  need_lib_prefix=no\n  need_version=no\n  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'\n  soname_spec='${libname}${release}${shared_ext}$major'\n  shlibpath_var=LD_LIBRARY_PATH\n  ;;\n\nfreebsd* | dragonfly*)\n  # DragonFly does not have aout.  When/if they implement a new\n  # versioning mechanism, adjust this.\n  if test -x /usr/bin/objformat; then\n    objformat=`/usr/bin/objformat`\n  else\n    case $host_os in\n    freebsd[[23]].*) objformat=aout ;;\n    *) objformat=elf ;;\n    esac\n  fi\n  version_type=freebsd-$objformat\n  case $version_type in\n    freebsd-elf*)\n      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'\n      need_version=no\n      need_lib_prefix=no\n      ;;\n    freebsd-*)\n      library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'\n      need_version=yes\n      ;;\n  esac\n  shlibpath_var=LD_LIBRARY_PATH\n  case $host_os in\n  freebsd2.*)\n    shlibpath_overrides_runpath=yes\n    ;;\n  freebsd3.[[01]]* | freebsdelf3.[[01]]*)\n    shlibpath_overrides_runpath=yes\n    hardcode_into_libs=yes\n    ;;\n  freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \\\n  freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1)\n    shlibpath_overrides_runpath=no\n    hardcode_into_libs=yes\n    ;;\n  *) # from 4.6 on, and DragonFly\n    shlibpath_overrides_runpath=yes\n    hardcode_into_libs=yes\n    ;;\n  esac\n  ;;\n\nhaiku*)\n  version_type=linux\n  need_lib_prefix=no\n  need_version=no\n  dynamic_linker=\"$host_os runtime_loader\"\n  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'\n  soname_spec='${libname}${release}${shared_ext}$major'\n  shlibpath_var=LIBRARY_PATH\n  shlibpath_overrides_runpath=yes\n  sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib'\n  hardcode_into_libs=yes\n  ;;\n\nhpux9* | hpux10* | hpux11*)\n  # Give a soname corresponding to the major version so that dld.sl refuses to\n  # link against other versions.\n  version_type=sunos\n  need_lib_prefix=no\n  need_version=no\n  case $host_cpu in\n  ia64*)\n    shrext_cmds='.so'\n    hardcode_into_libs=yes\n    dynamic_linker=\"$host_os dld.so\"\n    shlibpath_var=LD_LIBRARY_PATH\n    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.\n    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'\n    soname_spec='${libname}${release}${shared_ext}$major'\n    if test \"X$HPUX_IA64_MODE\" = X32; then\n      sys_lib_search_path_spec=\"/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib\"\n    else\n      sys_lib_search_path_spec=\"/usr/lib/hpux64 /usr/local/lib/hpux64\"\n    fi\n    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec\n    ;;\n  hppa*64*)\n    shrext_cmds='.sl'\n    hardcode_into_libs=yes\n    dynamic_linker=\"$host_os dld.sl\"\n    shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH\n    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.\n    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'\n    soname_spec='${libname}${release}${shared_ext}$major'\n    sys_lib_search_path_spec=\"/usr/lib/pa20_64 /usr/ccs/lib/pa20_64\"\n    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec\n    ;;\n  *)\n    shrext_cmds='.sl'\n    dynamic_linker=\"$host_os dld.sl\"\n    shlibpath_var=SHLIB_PATH\n    shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH\n    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'\n    soname_spec='${libname}${release}${shared_ext}$major'\n    ;;\n  esac\n  # HP-UX runs *really* slowly unless shared libraries are mode 555, ...\n  postinstall_cmds='chmod 555 $lib'\n  # or fails outright, so override atomically:\n  install_override_mode=555\n  ;;\n\ninterix[[3-9]]*)\n  version_type=linux\n  need_lib_prefix=no\n  need_version=no\n  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'\n  soname_spec='${libname}${release}${shared_ext}$major'\n  dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'\n  shlibpath_var=LD_LIBRARY_PATH\n  shlibpath_overrides_runpath=no\n  hardcode_into_libs=yes\n  ;;\n\nirix5* | irix6* | nonstopux*)\n  case $host_os in\n    nonstopux*) version_type=nonstopux ;;\n    *)\n\tif test \"$lt_cv_prog_gnu_ld\" = yes; then\n\t\tversion_type=linux\n\telse\n\t\tversion_type=irix\n\tfi ;;\n  esac\n  need_lib_prefix=no\n  need_version=no\n  soname_spec='${libname}${release}${shared_ext}$major'\n  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'\n  case $host_os in\n  irix5* | nonstopux*)\n    libsuff= shlibsuff=\n    ;;\n  *)\n    case $LD in # libtool.m4 will add one of these switches to LD\n    *-32|*\"-32 \"|*-melf32bsmip|*\"-melf32bsmip \")\n      libsuff= shlibsuff= libmagic=32-bit;;\n    *-n32|*\"-n32 \"|*-melf32bmipn32|*\"-melf32bmipn32 \")\n      libsuff=32 shlibsuff=N32 libmagic=N32;;\n    *-64|*\"-64 \"|*-melf64bmip|*\"-melf64bmip \")\n      libsuff=64 shlibsuff=64 libmagic=64-bit;;\n    *) libsuff= shlibsuff= libmagic=never-match;;\n    esac\n    ;;\n  esac\n  shlibpath_var=LD_LIBRARY${shlibsuff}_PATH\n  shlibpath_overrides_runpath=no\n  sys_lib_search_path_spec=\"/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}\"\n  sys_lib_dlsearch_path_spec=\"/usr/lib${libsuff} /lib${libsuff}\"\n  hardcode_into_libs=yes\n  ;;\n\n# No shared lib support for Linux oldld, aout, or coff.\nlinux*oldld* | linux*aout* | linux*coff*)\n  dynamic_linker=no\n  ;;\n\n# This must be Linux ELF.\n\n# uclinux* changes (here and below) have been submitted to the libtool\n# project, but have not yet been accepted: they are GCC-local changes\n# for the time being.  (See\n# https://lists.gnu.org/archive/html/libtool-patches/2018-05/msg00000.html)\nlinux* | k*bsd*-gnu | kopensolaris*-gnu | gnu* | uclinuxfdpiceabi)\n  version_type=linux\n  need_lib_prefix=no\n  need_version=no\n  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'\n  soname_spec='${libname}${release}${shared_ext}$major'\n  finish_cmds='PATH=\"\\$PATH:/sbin\" ldconfig -n $libdir'\n  shlibpath_var=LD_LIBRARY_PATH\n  shlibpath_overrides_runpath=no\n\n  # Some binutils ld are patched to set DT_RUNPATH\n  AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath],\n    [lt_cv_shlibpath_overrides_runpath=no\n    save_LDFLAGS=$LDFLAGS\n    save_libdir=$libdir\n    eval \"libdir=/foo; wl=\\\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\\\"; \\\n\t LDFLAGS=\\\"\\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\\\"\"\n    AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])],\n      [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep \"RUNPATH.*$libdir\" >/dev/null],\n\t [lt_cv_shlibpath_overrides_runpath=yes])])\n    LDFLAGS=$save_LDFLAGS\n    libdir=$save_libdir\n    ])\n  shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath\n\n  # This implies no fast_install, which is unacceptable.\n  # Some rework will be needed to allow for fast_install\n  # before this can be enabled.\n  hardcode_into_libs=yes\n\n  # Append ld.so.conf contents to the search path\n  if test -f /etc/ld.so.conf; then\n    lt_ld_extra=`awk '/^include / { system(sprintf(\"cd /etc; cat %s 2>/dev/null\", \\[$]2)); skip = 1; } { if (!skip) print \\[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[\t ]*hwcap[\t ]/d;s/[:,\t]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/\"//g;/^$/d' | tr '\\n' ' '`\n    sys_lib_dlsearch_path_spec=\"/lib /usr/lib $lt_ld_extra\"\n  fi\n\n  # We used to test for /lib/ld.so.1 and disable shared libraries on\n  # powerpc, because MkLinux only supported shared libraries with the\n  # GNU dynamic linker.  Since this was broken with cross compilers,\n  # most powerpc-linux boxes support dynamic linking these days and\n  # people can always --disable-shared, the test was removed, and we\n  # assume the GNU/Linux dynamic linker is in use.\n  dynamic_linker='GNU/Linux ld.so'\n  ;;\n\nnetbsd*)\n  version_type=sunos\n  need_lib_prefix=no\n  need_version=no\n  if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then\n    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'\n    finish_cmds='PATH=\"\\$PATH:/sbin\" ldconfig -m $libdir'\n    dynamic_linker='NetBSD (a.out) ld.so'\n  else\n    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'\n    soname_spec='${libname}${release}${shared_ext}$major'\n    dynamic_linker='NetBSD ld.elf_so'\n  fi\n  shlibpath_var=LD_LIBRARY_PATH\n  shlibpath_overrides_runpath=yes\n  hardcode_into_libs=yes\n  ;;\n\nnewsos6)\n  version_type=linux\n  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'\n  shlibpath_var=LD_LIBRARY_PATH\n  shlibpath_overrides_runpath=yes\n  ;;\n\n*nto* | *qnx*)\n  version_type=qnx\n  need_lib_prefix=no\n  need_version=no\n  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'\n  soname_spec='${libname}${release}${shared_ext}$major'\n  shlibpath_var=LD_LIBRARY_PATH\n  shlibpath_overrides_runpath=no\n  hardcode_into_libs=yes\n  dynamic_linker='ldqnx.so'\n  ;;\n\nopenbsd*)\n  version_type=sunos\n  sys_lib_dlsearch_path_spec=\"/usr/lib\"\n  need_lib_prefix=no\n  # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.\n  case $host_os in\n    openbsd3.3 | openbsd3.3.*)\tneed_version=yes ;;\n    *)\t\t\t\tneed_version=no  ;;\n  esac\n  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'\n  finish_cmds='PATH=\"\\$PATH:/sbin\" ldconfig -m $libdir'\n  shlibpath_var=LD_LIBRARY_PATH\n  if test -z \"`echo __ELF__ | $CC -E - | $GREP __ELF__`\" || test \"$host_os-$host_cpu\" = \"openbsd2.8-powerpc\"; then\n    case $host_os in\n      openbsd2.[[89]] | openbsd2.[[89]].*)\n\tshlibpath_overrides_runpath=no\n\t;;\n      *)\n\tshlibpath_overrides_runpath=yes\n\t;;\n      esac\n  else\n    shlibpath_overrides_runpath=yes\n  fi\n  ;;\n\nos2*)\n  libname_spec='$name'\n  shrext_cmds=\".dll\"\n  need_lib_prefix=no\n  library_names_spec='$libname${shared_ext} $libname.a'\n  dynamic_linker='OS/2 ld.exe'\n  shlibpath_var=LIBPATH\n  ;;\n\nosf3* | osf4* | osf5*)\n  version_type=osf\n  need_lib_prefix=no\n  need_version=no\n  soname_spec='${libname}${release}${shared_ext}$major'\n  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'\n  shlibpath_var=LD_LIBRARY_PATH\n  sys_lib_search_path_spec=\"/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib\"\n  sys_lib_dlsearch_path_spec=\"$sys_lib_search_path_spec\"\n  ;;\n\nrdos*)\n  dynamic_linker=no\n  ;;\n\nsolaris*)\n  version_type=linux\n  need_lib_prefix=no\n  need_version=no\n  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'\n  soname_spec='${libname}${release}${shared_ext}$major'\n  shlibpath_var=LD_LIBRARY_PATH\n  shlibpath_overrides_runpath=yes\n  hardcode_into_libs=yes\n  # ldd complains unless libraries are executable\n  postinstall_cmds='chmod +x $lib'\n  ;;\n\nsunos4*)\n  version_type=sunos\n  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'\n  finish_cmds='PATH=\"\\$PATH:/usr/etc\" ldconfig $libdir'\n  shlibpath_var=LD_LIBRARY_PATH\n  shlibpath_overrides_runpath=yes\n  if test \"$with_gnu_ld\" = yes; then\n    need_lib_prefix=no\n  fi\n  need_version=yes\n  ;;\n\nsysv4 | sysv4.3*)\n  version_type=linux\n  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'\n  soname_spec='${libname}${release}${shared_ext}$major'\n  shlibpath_var=LD_LIBRARY_PATH\n  case $host_vendor in\n    sni)\n      shlibpath_overrides_runpath=no\n      need_lib_prefix=no\n      runpath_var=LD_RUN_PATH\n      ;;\n    siemens)\n      need_lib_prefix=no\n      ;;\n    motorola)\n      need_lib_prefix=no\n      need_version=no\n      shlibpath_overrides_runpath=no\n      sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'\n      ;;\n  esac\n  ;;\n\nsysv4*MP*)\n  if test -d /usr/nec ;then\n    version_type=linux\n    library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'\n    soname_spec='$libname${shared_ext}.$major'\n    shlibpath_var=LD_LIBRARY_PATH\n  fi\n  ;;\n\nsysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)\n  version_type=freebsd-elf\n  need_lib_prefix=no\n  need_version=no\n  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'\n  soname_spec='${libname}${release}${shared_ext}$major'\n  shlibpath_var=LD_LIBRARY_PATH\n  shlibpath_overrides_runpath=yes\n  hardcode_into_libs=yes\n  if test \"$with_gnu_ld\" = yes; then\n    sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'\n  else\n    sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'\n    case $host_os in\n      sco3.2v5*)\n        sys_lib_search_path_spec=\"$sys_lib_search_path_spec /lib\"\n\t;;\n    esac\n  fi\n  sys_lib_dlsearch_path_spec='/usr/lib'\n  ;;\n\ntpf*)\n  # TPF is a cross-target only.  Preferred cross-host = GNU/Linux.\n  version_type=linux\n  need_lib_prefix=no\n  need_version=no\n  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'\n  shlibpath_var=LD_LIBRARY_PATH\n  shlibpath_overrides_runpath=no\n  hardcode_into_libs=yes\n  ;;\n\nuts4*)\n  version_type=linux\n  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'\n  soname_spec='${libname}${release}${shared_ext}$major'\n  shlibpath_var=LD_LIBRARY_PATH\n  ;;\n\n# Shared libraries for VwWorks, >= 7 only at this stage\n# and (fpic) still incompatible with \"large\" code models\n# in a few configurations. Only for RTP mode in any case,\n# and upon explicit request at configure time.\nvxworks7*)\n  dynamic_linker=no\n  case ${with_multisubdir}-${enable_shared} in\n    *large*)\n      ;;\n    *mrtp*-yes)\n      version_type=linux\n      need_lib_prefix=no\n      need_version=no\n      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'\n      soname_spec='${libname}${release}${shared_ext}$major'\n      dynamic_linker=\"$host_os module_loader\"\n      ;;\n  esac\n  ;;\n*)\n  dynamic_linker=no\n  ;;\nesac\nAC_MSG_RESULT([$dynamic_linker])\ntest \"$dynamic_linker\" = no && can_build_shared=no\n\nvariables_saved_for_relink=\"PATH $shlibpath_var $runpath_var\"\nif test \"$GCC\" = yes; then\n  variables_saved_for_relink=\"$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH\"\nfi\n\nif test \"${lt_cv_sys_lib_search_path_spec+set}\" = set; then\n  sys_lib_search_path_spec=\"$lt_cv_sys_lib_search_path_spec\"\nfi\nif test \"${lt_cv_sys_lib_dlsearch_path_spec+set}\" = set; then\n  sys_lib_dlsearch_path_spec=\"$lt_cv_sys_lib_dlsearch_path_spec\"\nfi\n\n_LT_DECL([], [variables_saved_for_relink], [1],\n    [Variables whose values should be saved in libtool wrapper scripts and\n    restored at link time])\n_LT_DECL([], [need_lib_prefix], [0],\n    [Do we need the \"lib\" prefix for modules?])\n_LT_DECL([], [need_version], [0], [Do we need a version for libraries?])\n_LT_DECL([], [version_type], [0], [Library versioning type])\n_LT_DECL([], [runpath_var], [0],  [Shared library runtime path variable])\n_LT_DECL([], [shlibpath_var], [0],[Shared library path variable])\n_LT_DECL([], [shlibpath_overrides_runpath], [0],\n    [Is shlibpath searched before the hard-coded library search path?])\n_LT_DECL([], [libname_spec], [1], [Format of library name prefix])\n_LT_DECL([], [library_names_spec], [1],\n    [[List of archive names.  First name is the real one, the rest are links.\n    The last name is the one that the linker finds with -lNAME]])\n_LT_DECL([], [soname_spec], [1],\n    [[The coded name of the library, if different from the real name]])\n_LT_DECL([], [install_override_mode], [1],\n    [Permission mode override for installation of shared libraries])\n_LT_DECL([], [postinstall_cmds], [2],\n    [Command to use after installation of a shared archive])\n_LT_DECL([], [postuninstall_cmds], [2],\n    [Command to use after uninstallation of a shared archive])\n_LT_DECL([], [finish_cmds], [2],\n    [Commands used to finish a libtool library installation in a directory])\n_LT_DECL([], [finish_eval], [1],\n    [[As \"finish_cmds\", except a single script fragment to be evaled but\n    not shown]])\n_LT_DECL([], [hardcode_into_libs], [0],\n    [Whether we should hardcode library paths into libraries])\n_LT_DECL([], [sys_lib_search_path_spec], [2],\n    [Compile-time system search path for libraries])\n_LT_DECL([], [sys_lib_dlsearch_path_spec], [2],\n    [Run-time system search path for libraries])\n])# _LT_SYS_DYNAMIC_LINKER\n\n\n# _LT_PATH_TOOL_PREFIX(TOOL)\n# --------------------------\n# find a file program which can recognize shared library\nAC_DEFUN([_LT_PATH_TOOL_PREFIX],\n[m4_require([_LT_DECL_EGREP])dnl\nAC_MSG_CHECKING([for $1])\nAC_CACHE_VAL(lt_cv_path_MAGIC_CMD,\n[case $MAGIC_CMD in\n[[\\\\/*] |  ?:[\\\\/]*])\n  lt_cv_path_MAGIC_CMD=\"$MAGIC_CMD\" # Let the user override the test with a path.\n  ;;\n*)\n  lt_save_MAGIC_CMD=\"$MAGIC_CMD\"\n  lt_save_ifs=\"$IFS\"; IFS=$PATH_SEPARATOR\ndnl $ac_dummy forces splitting on constant user-supplied paths.\ndnl POSIX.2 word splitting is done only on the output of word expansions,\ndnl not every word.  This closes a longstanding sh security hole.\n  ac_dummy=\"m4_if([$2], , $PATH, [$2])\"\n  for ac_dir in $ac_dummy; do\n    IFS=\"$lt_save_ifs\"\n    test -z \"$ac_dir\" && ac_dir=.\n    if test -f $ac_dir/$1; then\n      lt_cv_path_MAGIC_CMD=\"$ac_dir/$1\"\n      if test -n \"$file_magic_test_file\"; then\n\tcase $deplibs_check_method in\n\t\"file_magic \"*)\n\t  file_magic_regex=`expr \"$deplibs_check_method\" : \"file_magic \\(.*\\)\"`\n\t  MAGIC_CMD=\"$lt_cv_path_MAGIC_CMD\"\n\t  if eval $file_magic_cmd \\$file_magic_test_file 2> /dev/null |\n\t    $EGREP \"$file_magic_regex\" > /dev/null; then\n\t    :\n\t  else\n\t    cat <<_LT_EOF 1>&2\n\n*** Warning: the command libtool uses to detect shared libraries,\n*** $file_magic_cmd, produces output that libtool cannot recognize.\n*** The result is that libtool may fail to recognize shared libraries\n*** as such.  This will affect the creation of libtool libraries that\n*** depend on shared libraries, but programs linked with such libtool\n*** libraries will work regardless of this problem.  Nevertheless, you\n*** may want to report the problem to your system manager and/or to\n*** bug-libtool@gnu.org\n\n_LT_EOF\n\t  fi ;;\n\tesac\n      fi\n      break\n    fi\n  done\n  IFS=\"$lt_save_ifs\"\n  MAGIC_CMD=\"$lt_save_MAGIC_CMD\"\n  ;;\nesac])\nMAGIC_CMD=\"$lt_cv_path_MAGIC_CMD\"\nif test -n \"$MAGIC_CMD\"; then\n  AC_MSG_RESULT($MAGIC_CMD)\nelse\n  AC_MSG_RESULT(no)\nfi\n_LT_DECL([], [MAGIC_CMD], [0],\n\t [Used to examine libraries when file_magic_cmd begins with \"file\"])dnl\n])# _LT_PATH_TOOL_PREFIX\n\n# Old name:\nAU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX])\ndnl aclocal-1.4 backwards compatibility:\ndnl AC_DEFUN([AC_PATH_TOOL_PREFIX], [])\n\n\n# _LT_PATH_MAGIC\n# --------------\n# find a file program which can recognize a shared library\nm4_defun([_LT_PATH_MAGIC],\n[_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH)\nif test -z \"$lt_cv_path_MAGIC_CMD\"; then\n  if test -n \"$ac_tool_prefix\"; then\n    _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH)\n  else\n    MAGIC_CMD=:\n  fi\nfi\n])# _LT_PATH_MAGIC\n\n\n# LT_PATH_LD\n# ----------\n# find the pathname to the GNU or non-GNU linker\nAC_DEFUN([LT_PATH_LD],\n[AC_REQUIRE([AC_PROG_CC])dnl\nAC_REQUIRE([AC_CANONICAL_HOST])dnl\nAC_REQUIRE([AC_CANONICAL_BUILD])dnl\nm4_require([_LT_DECL_SED])dnl\nm4_require([_LT_DECL_EGREP])dnl\nm4_require([_LT_PROG_ECHO_BACKSLASH])dnl\n\nAC_ARG_WITH([gnu-ld],\n    [AS_HELP_STRING([--with-gnu-ld],\n\t[assume the C compiler uses GNU ld @<:@default=no@:>@])],\n    [test \"$withval\" = no || with_gnu_ld=yes],\n    [with_gnu_ld=no])dnl\n\nac_prog=ld\nif test \"$GCC\" = yes; then\n  # Check if gcc -print-prog-name=ld gives a path.\n  AC_MSG_CHECKING([for ld used by $CC])\n  case $host in\n  *-*-mingw*)\n    # gcc leaves a trailing carriage return which upsets mingw\n    ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\\015'` ;;\n  *)\n    ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;\n  esac\n  case $ac_prog in\n    # Accept absolute paths.\n    [[\\\\/]]* | ?:[[\\\\/]]*)\n      re_direlt='/[[^/]][[^/]]*/\\.\\./'\n      # Canonicalize the pathname of ld\n      ac_prog=`$ECHO \"$ac_prog\"| $SED 's%\\\\\\\\%/%g'`\n      while $ECHO \"$ac_prog\" | $GREP \"$re_direlt\" > /dev/null 2>&1; do\n\tac_prog=`$ECHO $ac_prog| $SED \"s%$re_direlt%/%\"`\n      done\n      test -z \"$LD\" && LD=\"$ac_prog\"\n      ;;\n  \"\")\n    # If it fails, then pretend we aren't using GCC.\n    ac_prog=ld\n    ;;\n  *)\n    # If it is relative, then search for the first ld in PATH.\n    with_gnu_ld=unknown\n    ;;\n  esac\nelif test \"$with_gnu_ld\" = yes; then\n  AC_MSG_CHECKING([for GNU ld])\nelse\n  AC_MSG_CHECKING([for non-GNU ld])\nfi\nAC_CACHE_VAL(lt_cv_path_LD,\n[if test -z \"$LD\"; then\n  lt_save_ifs=\"$IFS\"; IFS=$PATH_SEPARATOR\n  for ac_dir in $PATH; do\n    IFS=\"$lt_save_ifs\"\n    test -z \"$ac_dir\" && ac_dir=.\n    if test -f \"$ac_dir/$ac_prog\" || test -f \"$ac_dir/$ac_prog$ac_exeext\"; then\n      lt_cv_path_LD=\"$ac_dir/$ac_prog\"\n      # Check to see if the program is GNU ld.  I'd rather use --version,\n      # but apparently some variants of GNU ld only accept -v.\n      # Break only if it was the GNU/non-GNU ld that we prefer.\n      case `\"$lt_cv_path_LD\" -v 2>&1 </dev/null` in\n      *GNU* | *'with BFD'*)\n\ttest \"$with_gnu_ld\" != no && break\n\t;;\n      *)\n\ttest \"$with_gnu_ld\" != yes && break\n\t;;\n      esac\n    fi\n  done\n  IFS=\"$lt_save_ifs\"\nelse\n  lt_cv_path_LD=\"$LD\" # Let the user override the test with a path.\nfi])\nLD=\"$lt_cv_path_LD\"\nif test -n \"$LD\"; then\n  AC_MSG_RESULT($LD)\nelse\n  AC_MSG_RESULT(no)\nfi\ntest -z \"$LD\" && AC_MSG_ERROR([no acceptable ld found in \\$PATH])\n_LT_PATH_LD_GNU\nAC_SUBST([LD])\n\n_LT_TAGDECL([], [LD], [1], [The linker used to build libraries])\n])# LT_PATH_LD\n\n# Old names:\nAU_ALIAS([AM_PROG_LD], [LT_PATH_LD])\nAU_ALIAS([AC_PROG_LD], [LT_PATH_LD])\ndnl aclocal-1.4 backwards compatibility:\ndnl AC_DEFUN([AM_PROG_LD], [])\ndnl AC_DEFUN([AC_PROG_LD], [])\n\n\n# _LT_PATH_LD_GNU\n#- --------------\nm4_defun([_LT_PATH_LD_GNU],\n[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], lt_cv_prog_gnu_ld,\n[# I'd rather use --version here, but apparently some GNU lds only accept -v.\ncase `$LD -v 2>&1 </dev/null` in\n*GNU* | *'with BFD'*)\n  lt_cv_prog_gnu_ld=yes\n  ;;\n*)\n  lt_cv_prog_gnu_ld=no\n  ;;\nesac])\nwith_gnu_ld=$lt_cv_prog_gnu_ld\n])# _LT_PATH_LD_GNU\n\n\n# _LT_CMD_RELOAD\n# --------------\n# find reload flag for linker\n#   -- PORTME Some linkers may need a different reload flag.\nm4_defun([_LT_CMD_RELOAD],\n[AC_CACHE_CHECK([for $LD option to reload object files],\n  lt_cv_ld_reload_flag,\n  [lt_cv_ld_reload_flag='-r'])\nreload_flag=$lt_cv_ld_reload_flag\ncase $reload_flag in\n\"\" | \" \"*) ;;\n*) reload_flag=\" $reload_flag\" ;;\nesac\nreload_cmds='$LD$reload_flag -o $output$reload_objs'\ncase $host_os in\n  darwin*)\n    if test \"$GCC\" = yes; then\n      reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs'\n    else\n      reload_cmds='$LD$reload_flag -o $output$reload_objs'\n    fi\n    ;;\nesac\n_LT_TAGDECL([], [reload_flag], [1], [How to create reloadable object files])dnl\n_LT_TAGDECL([], [reload_cmds], [2])dnl\n])# _LT_CMD_RELOAD\n\n\n# _LT_CHECK_MAGIC_METHOD\n# ----------------------\n# how to check for library dependencies\n#  -- PORTME fill in with the dynamic library characteristics\nm4_defun([_LT_CHECK_MAGIC_METHOD],\n[m4_require([_LT_DECL_EGREP])\nm4_require([_LT_DECL_OBJDUMP])\nAC_CACHE_CHECK([how to recognize dependent libraries],\nlt_cv_deplibs_check_method,\n[lt_cv_file_magic_cmd='$MAGIC_CMD'\nlt_cv_file_magic_test_file=\nlt_cv_deplibs_check_method='unknown'\n# Need to set the preceding variable on all platforms that support\n# interlibrary dependencies.\n# 'none' -- dependencies not supported.\n# `unknown' -- same as none, but documents that we really don't know.\n# 'pass_all' -- all dependencies passed with no checks.\n# 'test_compile' -- check by making test program.\n# 'file_magic [[regex]]' -- check by looking for files in library path\n# which responds to the $file_magic_cmd with a given extended regex.\n# If you have `file' or equivalent on your system and you're not sure\n# whether `pass_all' will *always* work, you probably want this one.\n\ncase $host_os in\naix[[4-9]]*)\n  lt_cv_deplibs_check_method=pass_all\n  ;;\n\nbeos*)\n  lt_cv_deplibs_check_method=pass_all\n  ;;\n\nbsdi[[45]]*)\n  lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)'\n  lt_cv_file_magic_cmd='/usr/bin/file -L'\n  lt_cv_file_magic_test_file=/shlib/libc.so\n  ;;\n\ncygwin*)\n  # func_win32_libid is a shell function defined in ltmain.sh\n  lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'\n  lt_cv_file_magic_cmd='func_win32_libid'\n  ;;\n\nmingw* | pw32*)\n  # Base MSYS/MinGW do not provide the 'file' command needed by\n  # func_win32_libid shell function, so use a weaker test based on 'objdump',\n  # unless we find 'file', for example because we are cross-compiling.\n  # func_win32_libid assumes BSD nm, so disallow it if using MS dumpbin.\n  if ( test \"$lt_cv_nm_interface\" = \"BSD nm\" && file / ) >/dev/null 2>&1; then\n    lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'\n    lt_cv_file_magic_cmd='func_win32_libid'\n  else\n    lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'\n    lt_cv_file_magic_cmd='$OBJDUMP -f'\n  fi\n  ;;\n\ncegcc*)\n  # use the weaker test based on 'objdump'. See mingw*.\n  lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?'\n  lt_cv_file_magic_cmd='$OBJDUMP -f'\n  ;;\n\ndarwin* | rhapsody*)\n  lt_cv_deplibs_check_method=pass_all\n  ;;\n\nfreebsd* | dragonfly*)\n  if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then\n    case $host_cpu in\n    i*86 )\n      # Not sure whether the presence of OpenBSD here was a mistake.\n      # Let's accept both of them until this is cleared up.\n      lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library'\n      lt_cv_file_magic_cmd=/usr/bin/file\n      lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`\n      ;;\n    esac\n  else\n    lt_cv_deplibs_check_method=pass_all\n  fi\n  ;;\n\ngnu*)\n  lt_cv_deplibs_check_method=pass_all\n  ;;\n\nhaiku*)\n  lt_cv_deplibs_check_method=pass_all\n  ;;\n\nhpux10.20* | hpux11*)\n  lt_cv_file_magic_cmd=/usr/bin/file\n  case $host_cpu in\n  ia64*)\n    lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64'\n    lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so\n    ;;\n  hppa*64*)\n    [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\\.[0-9]']\n    lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl\n    ;;\n  *)\n    lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\\.[[0-9]]) shared library'\n    lt_cv_file_magic_test_file=/usr/lib/libc.sl\n    ;;\n  esac\n  ;;\n\ninterix[[3-9]]*)\n  # PIC code is broken on Interix 3.x, that's why |\\.a not |_pic\\.a here\n  lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\\.so|\\.a)$'\n  ;;\n\nirix5* | irix6* | nonstopux*)\n  case $LD in\n  *-32|*\"-32 \") libmagic=32-bit;;\n  *-n32|*\"-n32 \") libmagic=N32;;\n  *-64|*\"-64 \") libmagic=64-bit;;\n  *) libmagic=never-match;;\n  esac\n  lt_cv_deplibs_check_method=pass_all\n  ;;\n\n# This must be Linux ELF.\nlinux* | k*bsd*-gnu | kopensolaris*-gnu | uclinuxfdpiceabi)\n  lt_cv_deplibs_check_method=pass_all\n  ;;\n\nnetbsd*)\n  if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then\n    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\\.so\\.[[0-9]]+\\.[[0-9]]+|_pic\\.a)$'\n  else\n    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\\.so|_pic\\.a)$'\n  fi\n  ;;\n\nnewos6*)\n  lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)'\n  lt_cv_file_magic_cmd=/usr/bin/file\n  lt_cv_file_magic_test_file=/usr/lib/libnls.so\n  ;;\n\n*nto* | *qnx*)\n  lt_cv_deplibs_check_method=pass_all\n  ;;\n\nopenbsd*)\n  if test -z \"`echo __ELF__ | $CC -E - | $GREP __ELF__`\" || test \"$host_os-$host_cpu\" = \"openbsd2.8-powerpc\"; then\n    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\\.so\\.[[0-9]]+\\.[[0-9]]+|\\.so|_pic\\.a)$'\n  else\n    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\\.so\\.[[0-9]]+\\.[[0-9]]+|_pic\\.a)$'\n  fi\n  ;;\n\nosf3* | osf4* | osf5*)\n  lt_cv_deplibs_check_method=pass_all\n  ;;\n\nrdos*)\n  lt_cv_deplibs_check_method=pass_all\n  ;;\n\nsolaris*)\n  lt_cv_deplibs_check_method=pass_all\n  ;;\n\nsysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)\n  lt_cv_deplibs_check_method=pass_all\n  ;;\n\nsysv4 | sysv4.3*)\n  case $host_vendor in\n  motorola)\n    lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]'\n    lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`\n    ;;\n  ncr)\n    lt_cv_deplibs_check_method=pass_all\n    ;;\n  sequent)\n    lt_cv_file_magic_cmd='/bin/file'\n    lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )'\n    ;;\n  sni)\n    lt_cv_file_magic_cmd='/bin/file'\n    lt_cv_deplibs_check_method=\"file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib\"\n    lt_cv_file_magic_test_file=/lib/libc.so\n    ;;\n  siemens)\n    lt_cv_deplibs_check_method=pass_all\n    ;;\n  pc)\n    lt_cv_deplibs_check_method=pass_all\n    ;;\n  esac\n  ;;\n\ntpf*)\n  lt_cv_deplibs_check_method=pass_all\n  ;;\nvxworks*)\n  # Assume VxWorks cross toolchains are built on Linux, possibly\n  # as canadian for Windows hosts.\n  lt_cv_deplibs_check_method=pass_all\n  ;;\nesac\n])\nfile_magic_cmd=$lt_cv_file_magic_cmd\ndeplibs_check_method=$lt_cv_deplibs_check_method\ntest -z \"$deplibs_check_method\" && deplibs_check_method=unknown\n\n_LT_DECL([], [deplibs_check_method], [1],\n    [Method to check whether dependent libraries are shared objects])\n_LT_DECL([], [file_magic_cmd], [1],\n    [Command to use when deplibs_check_method == \"file_magic\"])\n])# _LT_CHECK_MAGIC_METHOD\n\n\n# LT_PATH_NM\n# ----------\n# find the pathname to a BSD- or MS-compatible name lister, and any flags\n# needed to make it compatible\nAC_DEFUN([LT_PATH_NM],\n[AC_REQUIRE([AC_PROG_CC])dnl\nAC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM,\n[if test -n \"$NM\"; then\n   # Let the user override the nm to test.\n   lt_nm_to_check=\"$NM\"\n else\n   lt_nm_to_check=\"${ac_tool_prefix}nm\"\n   if test -n \"$ac_tool_prefix\" && test \"$build\" = \"$host\"; then\n     lt_nm_to_check=\"$lt_nm_to_check nm\"\n   fi\n fi\n for lt_tmp_nm in \"$lt_nm_to_check\"; do\n   lt_save_ifs=\"$IFS\"; IFS=$PATH_SEPARATOR\n   for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do\n     IFS=\"$lt_save_ifs\"\n     test -z \"$ac_dir\" && ac_dir=.\n     # Strip out any user-provided options from the nm to test twice,\n     # the first time to test to see if nm (rather than its options) has\n     # an explicit path, the second time to yield a file which can be\n     # nm'ed itself.\n     tmp_nm_path=\"`$ECHO \"$lt_tmp_nm\" | sed 's, -.*$,,'`\"\n     case \"$tmp_nm_path\" in\n     */*|*\\\\*) tmp_nm=\"$lt_tmp_nm\";;\n     *) tmp_nm=\"$ac_dir/$lt_tmp_nm\";;\n     esac\n     tmp_nm_to_nm=\"`$ECHO \"$tmp_nm\" | sed 's, -.*$,,'`\"\n     if test -f \"$tmp_nm_to_nm\" || test -f \"$tmp_nm_to_nm$ac_exeext\" ; then\n       # Check to see if the nm accepts a BSD-compat flag.\n       # Adding the `sed 1q' prevents false positives on HP-UX, which says:\n       #   nm: unknown option \"B\" ignored\n       case `\"$tmp_nm\" -B \"$tmp_nm_to_nm\" 2>&1 | grep -v '^ *$' | sed '1q'` in\n       *$tmp_nm*) lt_cv_path_NM=\"$tmp_nm -B\"\n\t break\n\t ;;\n       *)\n\t case `\"$tmp_nm\" -p \"$tmp_nm_to_nm\" 2>&1 | grep -v '^ *$' | sed '1q'` in\n\t *$tmp_nm*)\n\t   lt_cv_path_NM=\"$tmp_nm -p\"\n\t   break\n\t   ;;\n\t *)\n\t   lt_cv_path_NM=${lt_cv_path_NM=\"$tmp_nm\"} # keep the first match, but\n\t   continue # so that we can try to find one that supports BSD flags\n\t   ;;\n\t esac\n\t ;;\n       esac\n     fi\n   done\n   IFS=\"$lt_save_ifs\"\n done\n : ${lt_cv_path_NM=no}])\nif test \"$lt_cv_path_NM\" != \"no\"; then\n  NM=\"$lt_cv_path_NM\"\nelse\n  # Didn't find any BSD compatible name lister, look for dumpbin.\n  if test -n \"$DUMPBIN\"; then :\n    # Let the user override the test.\n  else\n    AC_CHECK_TOOLS(DUMPBIN, [dumpbin \"link -dump\"], :)\n    case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in\n    *COFF*)\n      DUMPBIN=\"$DUMPBIN -symbols\"\n      ;;\n    *)\n      DUMPBIN=:\n      ;;\n    esac\n  fi\n  AC_SUBST([DUMPBIN])\n  if test \"$DUMPBIN\" != \":\"; then\n    NM=\"$DUMPBIN\"\n  fi\nfi\ntest -z \"$NM\" && NM=nm\nAC_SUBST([NM])\n_LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl\n\nAC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface],\n  [lt_cv_nm_interface=\"BSD nm\"\n  echo \"int some_variable = 0;\" > conftest.$ac_ext\n  (eval echo \"\\\"\\$as_me:$LINENO: $ac_compile\\\"\" >&AS_MESSAGE_LOG_FD)\n  (eval \"$ac_compile\" 2>conftest.err)\n  cat conftest.err >&AS_MESSAGE_LOG_FD\n  (eval echo \"\\\"\\$as_me:$LINENO: $NM \\\\\\\"conftest.$ac_objext\\\\\\\"\\\"\" >&AS_MESSAGE_LOG_FD)\n  (eval \"$NM \\\"conftest.$ac_objext\\\"\" 2>conftest.err > conftest.out)\n  cat conftest.err >&AS_MESSAGE_LOG_FD\n  (eval echo \"\\\"\\$as_me:$LINENO: output\\\"\" >&AS_MESSAGE_LOG_FD)\n  cat conftest.out >&AS_MESSAGE_LOG_FD\n  if $GREP 'External.*some_variable' conftest.out > /dev/null; then\n    lt_cv_nm_interface=\"MS dumpbin\"\n  fi\n  rm -f conftest*])\n])# LT_PATH_NM\n\n# Old names:\nAU_ALIAS([AM_PROG_NM], [LT_PATH_NM])\nAU_ALIAS([AC_PROG_NM], [LT_PATH_NM])\ndnl aclocal-1.4 backwards compatibility:\ndnl AC_DEFUN([AM_PROG_NM], [])\ndnl AC_DEFUN([AC_PROG_NM], [])\n\n\n# LT_LIB_M\n# --------\n# check for math library\nAC_DEFUN([LT_LIB_M],\n[AC_REQUIRE([AC_CANONICAL_HOST])dnl\nLIBM=\ncase $host in\n*-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*)\n  # These system don't have libm, or don't need it\n  ;;\n*-ncr-sysv4.3*)\n  AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM=\"-lmw\")\n  AC_CHECK_LIB(m, cos, LIBM=\"$LIBM -lm\")\n  ;;\n*)\n  AC_CHECK_LIB(m, cos, LIBM=\"-lm\")\n  ;;\nesac\nAC_SUBST([LIBM])\n])# LT_LIB_M\n\n# Old name:\nAU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M])\ndnl aclocal-1.4 backwards compatibility:\ndnl AC_DEFUN([AC_CHECK_LIBM], [])\n\n\n# _LT_COMPILER_NO_RTTI([TAGNAME])\n# -------------------------------\nm4_defun([_LT_COMPILER_NO_RTTI],\n[m4_require([_LT_TAG_COMPILER])dnl\n\n_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=\n\nif test \"$GCC\" = yes; then\n  case $cc_basename in\n  nvcc*)\n    _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;;\n  *)\n    _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;;\n  esac\n\n  _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions],\n    lt_cv_prog_compiler_rtti_exceptions,\n    [-fno-rtti -fno-exceptions], [],\n    [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=\"$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions\"])\nfi\n_LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1],\n\t[Compiler flag to turn off builtin functions])\n])# _LT_COMPILER_NO_RTTI\n\n\n# _LT_CMD_GLOBAL_SYMBOLS\n# ----------------------\nm4_defun([_LT_CMD_GLOBAL_SYMBOLS],\n[AC_REQUIRE([AC_CANONICAL_HOST])dnl\nAC_REQUIRE([AC_PROG_CC])dnl\nAC_REQUIRE([AC_PROG_AWK])dnl\nAC_REQUIRE([LT_PATH_NM])dnl\nAC_REQUIRE([LT_PATH_LD])dnl\nm4_require([_LT_DECL_SED])dnl\nm4_require([_LT_DECL_EGREP])dnl\nm4_require([_LT_TAG_COMPILER])dnl\n\n# Check for command to grab the raw symbol name followed by C symbol from nm.\nAC_MSG_CHECKING([command to parse $NM output from $compiler object])\nAC_CACHE_VAL([lt_cv_sys_global_symbol_pipe],\n[\n# These are sane defaults that work on at least a few old systems.\n# [They come from Ultrix.  What could be older than Ultrix?!! ;)]\n\n# Character class describing NM global symbol codes.\nsymcode='[[BCDEGRST]]'\n\n# Regexp to match symbols that can be accessed directly from C.\nsympat='\\([[_A-Za-z]][[_A-Za-z0-9]]*\\)'\n\n# Define system-specific variables.\ncase $host_os in\naix*)\n  symcode='[[BCDT]]'\n  ;;\ncygwin* | mingw* | pw32* | cegcc*)\n  symcode='[[ABCDGISTW]]'\n  ;;\nhpux*)\n  if test \"$host_cpu\" = ia64; then\n    symcode='[[ABCDEGRST]]'\n  fi\n  ;;\nirix* | nonstopux*)\n  symcode='[[BCDEGRST]]'\n  ;;\nosf*)\n  symcode='[[BCDEGQRST]]'\n  ;;\nsolaris*)\n  symcode='[[BCDRT]]'\n  ;;\nsco3.2v5*)\n  symcode='[[DT]]'\n  ;;\nsysv4.2uw2*)\n  symcode='[[DT]]'\n  ;;\nsysv5* | sco5v6* | unixware* | OpenUNIX*)\n  symcode='[[ABDT]]'\n  ;;\nsysv4)\n  symcode='[[DFNSTU]]'\n  ;;\nesac\n\n# If we're using GNU nm, then use its standard symbol codes.\ncase `$NM -V 2>&1` in\n*GNU* | *'with BFD'*)\n  symcode='[[ABCDGIRSTW]]' ;;\nesac\n\n# Transform an extracted symbol line into a proper C declaration.\n# Some systems (esp. on ia64) link data and code symbols differently,\n# so use this general approach.\nlt_cv_sys_global_symbol_to_cdecl=\"sed -n -e 's/^T .* \\(.*\\)$/extern int \\1();/p' -e 's/^$symcode* .* \\(.*\\)$/extern char \\1;/p'\"\n\n# Transform an extracted symbol line into symbol name and symbol address\nlt_cv_sys_global_symbol_to_c_name_address=\"sed -n -e 's/^: \\([[^ ]]*\\) $/  {\\\\\\\"\\1\\\\\\\", (void *) 0},/p' -e 's/^$symcode* \\([[^ ]]*\\) \\([[^ ]]*\\)$/  {\\\"\\2\\\", (void *) \\&\\2},/p'\"\nlt_cv_sys_global_symbol_to_c_name_address_lib_prefix=\"sed -n -e 's/^: \\([[^ ]]*\\) $/  {\\\\\\\"\\1\\\\\\\", (void *) 0},/p' -e 's/^$symcode* \\([[^ ]]*\\) \\(lib[[^ ]]*\\)$/  {\\\"\\2\\\", (void *) \\&\\2},/p' -e 's/^$symcode* \\([[^ ]]*\\) \\([[^ ]]*\\)$/  {\\\"lib\\2\\\", (void *) \\&\\2},/p'\"\n\n# Handle CRLF in mingw tool chain\nopt_cr=\ncase $build_os in\nmingw*)\n  opt_cr=`$ECHO 'x\\{0,1\\}' | tr x '\\015'` # option cr in regexp\n  ;;\nesac\n\n# Try without a prefix underscore, then with it.\nfor ac_symprfx in \"\" \"_\"; do\n\n  # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol.\n  symxfrm=\"\\\\1 $ac_symprfx\\\\2 \\\\2\"\n\n  # Write the raw and C identifiers.\n  if test \"$lt_cv_nm_interface\" = \"MS dumpbin\"; then\n    # Fake it for dumpbin and say T for any non-static function\n    # and D for any global variable.\n    # Also find C++ and __fastcall symbols from MSVC++,\n    # which start with @ or ?.\n    lt_cv_sys_global_symbol_pipe=\"$AWK ['\"\\\n\"     {last_section=section; section=\\$ 3};\"\\\n\"     /Section length .*#relocs.*(pick any)/{hide[last_section]=1};\"\\\n\"     \\$ 0!~/External *\\|/{next};\"\\\n\"     / 0+ UNDEF /{next}; / UNDEF \\([^|]\\)*()/{next};\"\\\n\"     {if(hide[section]) next};\"\\\n\"     {f=0}; \\$ 0~/\\(\\).*\\|/{f=1}; {printf f ? \\\"T \\\" : \\\"D \\\"};\"\\\n\"     {split(\\$ 0, a, /\\||\\r/); split(a[2], s)};\"\\\n\"     s[1]~/^[@?]/{print s[1], s[1]; next};\"\\\n\"     s[1]~prfx {split(s[1],t,\\\"@\\\"); print t[1], substr(t[1],length(prfx))}\"\\\n\"     ' prfx=^$ac_symprfx]\"\n  else\n    lt_cv_sys_global_symbol_pipe=\"sed -n -e 's/^.*[[\t ]]\\($symcode$symcode*\\)[[\t ]][[\t ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'\"\n  fi\n\n  # Check to see that the pipe works correctly.\n  pipe_works=no\n\n  rm -f conftest*\n  cat > conftest.$ac_ext <<_LT_EOF\n#ifdef __cplusplus\nextern \"C\" {\n#endif\nchar nm_test_var;\nvoid nm_test_func(void);\nvoid nm_test_func(void){}\n#ifdef __cplusplus\n}\n#endif\nint main(){nm_test_var='a';nm_test_func();return(0);}\n_LT_EOF\n\n  if AC_TRY_EVAL(ac_compile); then\n    # Now try to grab the symbols.\n    nlist=conftest.nm\n    if AC_TRY_EVAL(NM conftest.$ac_objext \\| \"$lt_cv_sys_global_symbol_pipe\" \\> $nlist) && test -s \"$nlist\"; then\n      # Try sorting and uniquifying the output.\n      if sort \"$nlist\" | uniq > \"$nlist\"T; then\n\tmv -f \"$nlist\"T \"$nlist\"\n      else\n\trm -f \"$nlist\"T\n      fi\n\n      # Make sure that we snagged all the symbols we need.\n      if $GREP ' nm_test_var$' \"$nlist\" >/dev/null; then\n\tif $GREP ' nm_test_func$' \"$nlist\" >/dev/null; then\n\t  cat <<_LT_EOF > conftest.$ac_ext\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n_LT_EOF\n\t  # Now generate the symbol file.\n\t  eval \"$lt_cv_sys_global_symbol_to_cdecl\"' < \"$nlist\" | $GREP -v main >> conftest.$ac_ext'\n\n\t  cat <<_LT_EOF >> conftest.$ac_ext\n\n/* The mapping between symbol names and symbols.  */\nconst struct {\n  const char *name;\n  void       *address;\n}\nlt__PROGRAM__LTX_preloaded_symbols[[]] =\n{\n  { \"@PROGRAM@\", (void *) 0 },\n_LT_EOF\n\t  $SED \"s/^$symcode$symcode* \\(.*\\) \\(.*\\)$/  {\\\"\\2\\\", (void *) \\&\\2},/\" < \"$nlist\" | $GREP -v main >> conftest.$ac_ext\n\t  cat <<\\_LT_EOF >> conftest.$ac_ext\n  {0, (void *) 0}\n};\n\n/* This works around a problem in FreeBSD linker */\n#ifdef FREEBSD_WORKAROUND\nstatic const void *lt_preloaded_setup() {\n  return lt__PROGRAM__LTX_preloaded_symbols;\n}\n#endif\n\n#ifdef __cplusplus\n}\n#endif\n_LT_EOF\n\t  # Now try linking the two files.\n\t  mv conftest.$ac_objext conftstm.$ac_objext\n\t  lt_save_LIBS=\"$LIBS\"\n\t  lt_save_CFLAGS=\"$CFLAGS\"\n\t  LIBS=\"conftstm.$ac_objext\"\n\t  CFLAGS=\"$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)\"\n\t  if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then\n\t    pipe_works=yes\n\t  fi\n\t  LIBS=\"$lt_save_LIBS\"\n\t  CFLAGS=\"$lt_save_CFLAGS\"\n\telse\n\t  echo \"cannot find nm_test_func in $nlist\" >&AS_MESSAGE_LOG_FD\n\tfi\n      else\n\techo \"cannot find nm_test_var in $nlist\" >&AS_MESSAGE_LOG_FD\n      fi\n    else\n      echo \"cannot run $lt_cv_sys_global_symbol_pipe\" >&AS_MESSAGE_LOG_FD\n    fi\n  else\n    echo \"$progname: failed program was:\" >&AS_MESSAGE_LOG_FD\n    cat conftest.$ac_ext >&5\n  fi\n  rm -rf conftest* conftst*\n\n  # Do not use the global_symbol_pipe unless it works.\n  if test \"$pipe_works\" = yes; then\n    break\n  else\n    lt_cv_sys_global_symbol_pipe=\n  fi\ndone\n])\nif test -z \"$lt_cv_sys_global_symbol_pipe\"; then\n  lt_cv_sys_global_symbol_to_cdecl=\nfi\nif test -z \"$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl\"; then\n  AC_MSG_RESULT(failed)\nelse\n  AC_MSG_RESULT(ok)\nfi\n\n_LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1],\n    [Take the output of nm and produce a listing of raw symbols and C names])\n_LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1],\n    [Transform the output of nm in a proper C declaration])\n_LT_DECL([global_symbol_to_c_name_address],\n    [lt_cv_sys_global_symbol_to_c_name_address], [1],\n    [Transform the output of nm in a C name address pair])\n_LT_DECL([global_symbol_to_c_name_address_lib_prefix],\n    [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1],\n    [Transform the output of nm in a C name address pair when lib prefix is needed])\n]) # _LT_CMD_GLOBAL_SYMBOLS\n\n\n# _LT_COMPILER_PIC([TAGNAME])\n# ---------------------------\nm4_defun([_LT_COMPILER_PIC],\n[m4_require([_LT_TAG_COMPILER])dnl\n_LT_TAGVAR(lt_prog_compiler_wl, $1)=\n_LT_TAGVAR(lt_prog_compiler_pic, $1)=\n_LT_TAGVAR(lt_prog_compiler_static, $1)=\n\nAC_MSG_CHECKING([for $compiler option to produce PIC])\nm4_if([$1], [CXX], [\n  # C++ specific cases for pic, static, wl, etc.\n  if test \"$GXX\" = yes; then\n    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'\n    _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'\n\n    case $host_os in\n    aix*)\n      # All AIX code is PIC.\n      if test \"$host_cpu\" = ia64; then\n\t# AIX 5 now supports IA64 processor\n\t_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'\n      fi\n      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'\n      ;;\n\n    amigaos*)\n      case $host_cpu in\n      powerpc)\n            # see comment about AmigaOS4 .so support\n            _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'\n        ;;\n      m68k)\n            # FIXME: we need at least 68020 code to build shared libraries, but\n            # adding the `-m68020' flag to GCC prevents building anything better,\n            # like `-m68040'.\n            _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'\n        ;;\n      esac\n      ;;\n\n    beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)\n      # PIC is the default for these OSes.\n      ;;\n    mingw* | cygwin* | os2* | pw32* | cegcc*)\n      # This hack is so that the source file can tell whether it is being\n      # built for inclusion in a dll (and should export symbols for example).\n      # Although the cygwin gcc ignores -fPIC, still need this for old-style\n      # (--disable-auto-import) libraries\n      m4_if([$1], [GCJ], [],\n\t[_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])\n      ;;\n    darwin* | rhapsody*)\n      # PIC is the default on this platform\n      # Common symbols not allowed in MH_DYLIB files\n      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'\n      ;;\n    *djgpp*)\n      # DJGPP does not support shared libraries at all\n      _LT_TAGVAR(lt_prog_compiler_pic, $1)=\n      ;;\n    haiku*)\n      # PIC is the default for Haiku.\n      # The \"-static\" flag exists, but is broken.\n      _LT_TAGVAR(lt_prog_compiler_static, $1)=\n      ;;\n    interix[[3-9]]*)\n      # Interix 3.x gcc -fpic/-fPIC options generate broken code.\n      # Instead, we relocate shared libraries at runtime.\n      ;;\n    sysv4*MP*)\n      if test -d /usr/nec; then\n\t_LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic\n      fi\n      ;;\n    hpux*)\n      # PIC is the default for 64-bit PA HP-UX, but not for 32-bit\n      # PA HP-UX.  On IA64 HP-UX, PIC is the default but the pic flag\n      # sets the default TLS model and affects inlining.\n      case $host_cpu in\n      hppa*64*)\n\t;;\n      *)\n\t_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'\n\t;;\n      esac\n      ;;\n    *qnx* | *nto*)\n      # QNX uses GNU C++, but need to define -shared option too, otherwise\n      # it will coredump.\n      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'\n      ;;\n    *)\n      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'\n      ;;\n    esac\n  else\n    case $host_os in\n      aix[[4-9]]*)\n\t# All AIX code is PIC.\n\tif test \"$host_cpu\" = ia64; then\n\t  # AIX 5 now supports IA64 processor\n\t  _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'\n\telse\n\t  _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'\n\tfi\n\t;;\n      chorus*)\n\tcase $cc_basename in\n\tcxch68*)\n\t  # Green Hills C++ Compiler\n\t  # _LT_TAGVAR(lt_prog_compiler_static, $1)=\"--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a\"\n\t  ;;\n\tesac\n\t;;\n      dgux*)\n\tcase $cc_basename in\n\t  ec++*)\n\t    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'\n\t    ;;\n\t  ghcx*)\n\t    # Green Hills C++ Compiler\n\t    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'\n\t    ;;\n\t  *)\n\t    ;;\n\tesac\n\t;;\n      freebsd* | dragonfly*)\n\t# FreeBSD uses GNU C++\n\t;;\n      hpux9* | hpux10* | hpux11*)\n\tcase $cc_basename in\n\t  CC*)\n\t    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'\n\t    _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'\n\t    if test \"$host_cpu\" != ia64; then\n\t      _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'\n\t    fi\n\t    ;;\n\t  aCC*)\n\t    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'\n\t    _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'\n\t    case $host_cpu in\n\t    hppa*64*|ia64*)\n\t      # +Z the default\n\t      ;;\n\t    *)\n\t      _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'\n\t      ;;\n\t    esac\n\t    ;;\n\t  *)\n\t    ;;\n\tesac\n\t;;\n      interix*)\n\t# This is c89, which is MS Visual C++ (no shared libs)\n\t# Anyone wants to do a port?\n\t;;\n      irix5* | irix6* | nonstopux*)\n\tcase $cc_basename in\n\t  CC*)\n\t    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'\n\t    _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'\n\t    # CC pic flag -KPIC is the default.\n\t    ;;\n\t  *)\n\t    ;;\n\tesac\n\t;;\n      linux* | k*bsd*-gnu | kopensolaris*-gnu)\n\tcase $cc_basename in\n\t  KCC*)\n\t    # KAI C++ Compiler\n\t    _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'\n\t    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'\n\t    ;;\n\t  ecpc* )\n\t    # old Intel C++ for x86_64 which still supported -KPIC.\n\t    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'\n\t    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'\n\t    _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'\n\t    ;;\n\t  icpc* )\n\t    # Intel C++, used to be incompatible with GCC.\n\t    # ICC 10 doesn't accept -KPIC any more.\n\t    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'\n\t    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'\n\t    _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'\n\t    ;;\n\t  pgCC* | pgcpp*)\n\t    # Portland Group C++ compiler\n\t    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'\n\t    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'\n\t    _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'\n\t    ;;\n\t  cxx*)\n\t    # Compaq C++\n\t    # Make sure the PIC flag is empty.  It appears that all Alpha\n\t    # Linux and Compaq Tru64 Unix objects are PIC.\n\t    _LT_TAGVAR(lt_prog_compiler_pic, $1)=\n\t    _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'\n\t    ;;\n\t  xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*)\n\t    # IBM XL 8.0, 9.0 on PPC and BlueGene\n\t    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'\n\t    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic'\n\t    _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink'\n\t    ;;\n\t  *)\n\t    case `$CC -V 2>&1 | sed 5q` in\n\t    *Sun\\ C*)\n\t      # Sun C++ 5.9\n\t      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'\n\t      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'\n\t      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '\n\t      ;;\n\t    esac\n\t    ;;\n\tesac\n\t;;\n      lynxos*)\n\t;;\n      m88k*)\n\t;;\n      mvs*)\n\tcase $cc_basename in\n\t  cxx*)\n\t    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall'\n\t    ;;\n\t  *)\n\t    ;;\n\tesac\n\t;;\n      netbsd*)\n\t;;\n      *qnx* | *nto*)\n        # QNX uses GNU C++, but need to define -shared option too, otherwise\n        # it will coredump.\n        _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'\n        ;;\n      osf3* | osf4* | osf5*)\n\tcase $cc_basename in\n\t  KCC*)\n\t    _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'\n\t    ;;\n\t  RCC*)\n\t    # Rational C++ 2.4.1\n\t    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'\n\t    ;;\n\t  cxx*)\n\t    # Digital/Compaq C++\n\t    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'\n\t    # Make sure the PIC flag is empty.  It appears that all Alpha\n\t    # Linux and Compaq Tru64 Unix objects are PIC.\n\t    _LT_TAGVAR(lt_prog_compiler_pic, $1)=\n\t    _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'\n\t    ;;\n\t  *)\n\t    ;;\n\tesac\n\t;;\n      psos*)\n\t;;\n      solaris*)\n\tcase $cc_basename in\n\t  CC*)\n\t    # Sun C++ 4.2, 5.x and Centerline C++\n\t    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'\n\t    _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'\n\t    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '\n\t    ;;\n\t  gcx*)\n\t    # Green Hills C++ Compiler\n\t    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'\n\t    ;;\n\t  *)\n\t    ;;\n\tesac\n\t;;\n      sunos4*)\n\tcase $cc_basename in\n\t  CC*)\n\t    # Sun C++ 4.x\n\t    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'\n\t    _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'\n\t    ;;\n\t  lcc*)\n\t    # Lucid\n\t    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'\n\t    ;;\n\t  *)\n\t    ;;\n\tesac\n\t;;\n      sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)\n\tcase $cc_basename in\n\t  CC*)\n\t    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'\n\t    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'\n\t    _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'\n\t    ;;\n\tesac\n\t;;\n      tandem*)\n\tcase $cc_basename in\n\t  NCC*)\n\t    # NonStop-UX NCC 3.20\n\t    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'\n\t    ;;\n\t  *)\n\t    ;;\n\tesac\n\t;;\n      vxworks*)\n\t;;\n      *)\n\t_LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no\n\t;;\n    esac\n  fi\n],\n[\n  if test \"$GCC\" = yes; then\n    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'\n    _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'\n\n    case $host_os in\n      aix*)\n      # All AIX code is PIC.\n      if test \"$host_cpu\" = ia64; then\n\t# AIX 5 now supports IA64 processor\n\t_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'\n      fi\n      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'\n      ;;\n\n    amigaos*)\n      case $host_cpu in\n      powerpc)\n            # see comment about AmigaOS4 .so support\n            _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'\n        ;;\n      m68k)\n            # FIXME: we need at least 68020 code to build shared libraries, but\n            # adding the `-m68020' flag to GCC prevents building anything better,\n            # like `-m68040'.\n            _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'\n        ;;\n      esac\n      ;;\n\n    beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)\n      # PIC is the default for these OSes.\n      ;;\n\n    mingw* | cygwin* | pw32* | os2* | cegcc*)\n      # This hack is so that the source file can tell whether it is being\n      # built for inclusion in a dll (and should export symbols for example).\n      # Although the cygwin gcc ignores -fPIC, still need this for old-style\n      # (--disable-auto-import) libraries\n      m4_if([$1], [GCJ], [],\n\t[_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])\n      ;;\n\n    darwin* | rhapsody*)\n      # PIC is the default on this platform\n      # Common symbols not allowed in MH_DYLIB files\n      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'\n      ;;\n\n    haiku*)\n      # PIC is the default for Haiku.\n      # The \"-static\" flag exists, but is broken.\n      _LT_TAGVAR(lt_prog_compiler_static, $1)=\n      ;;\n\n    hpux*)\n      # PIC is the default for 64-bit PA HP-UX, but not for 32-bit\n      # PA HP-UX.  On IA64 HP-UX, PIC is the default but the pic flag\n      # sets the default TLS model and affects inlining.\n      case $host_cpu in\n      hppa*64*)\n\t# +Z the default\n\t;;\n      *)\n\t_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'\n\t;;\n      esac\n      ;;\n\n    interix[[3-9]]*)\n      # Interix 3.x gcc -fpic/-fPIC options generate broken code.\n      # Instead, we relocate shared libraries at runtime.\n      ;;\n\n    msdosdjgpp*)\n      # Just because we use GCC doesn't mean we suddenly get shared libraries\n      # on systems that don't support them.\n      _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no\n      enable_shared=no\n      ;;\n\n    *nto* | *qnx*)\n      # QNX uses GNU C++, but need to define -shared option too, otherwise\n      # it will coredump.\n      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'\n      ;;\n\n    sysv4*MP*)\n      if test -d /usr/nec; then\n\t_LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic\n      fi\n      ;;\n\n    *)\n      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'\n      ;;\n    esac\n\n    case $cc_basename in\n    nvcc*) # Cuda Compiler Driver 2.2\n      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker '\n      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Xcompiler -fPIC'\n      ;;\n    esac\n  else\n    # PORTME Check for flag to pass linker flags through the system compiler.\n    case $host_os in\n    aix*)\n      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'\n      if test \"$host_cpu\" = ia64; then\n\t# AIX 5 now supports IA64 processor\n\t_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'\n      else\n\t_LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'\n      fi\n      ;;\n\n    mingw* | cygwin* | pw32* | os2* | cegcc*)\n      # This hack is so that the source file can tell whether it is being\n      # built for inclusion in a dll (and should export symbols for example).\n      m4_if([$1], [GCJ], [],\n\t[_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])\n      ;;\n\n    hpux9* | hpux10* | hpux11*)\n      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'\n      # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but\n      # not for PA HP-UX.\n      case $host_cpu in\n      hppa*64*|ia64*)\n\t# +Z the default\n\t;;\n      *)\n\t_LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'\n\t;;\n      esac\n      # Is there a better lt_prog_compiler_static that works with the bundled CC?\n      _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'\n      ;;\n\n    irix5* | irix6* | nonstopux*)\n      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'\n      # PIC (with -KPIC) is the default.\n      _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'\n      ;;\n\n    linux* | k*bsd*-gnu | kopensolaris*-gnu)\n      case $cc_basename in\n      # old Intel for x86_64 which still supported -KPIC.\n      ecc*)\n\t_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'\n\t_LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'\n\t_LT_TAGVAR(lt_prog_compiler_static, $1)='-static'\n        ;;\n      # icc used to be incompatible with GCC.\n      # ICC 10 doesn't accept -KPIC any more.\n      icc* | ifort*)\n\t_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'\n\t_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'\n\t_LT_TAGVAR(lt_prog_compiler_static, $1)='-static'\n        ;;\n      # Lahey Fortran 8.1.\n      lf95*)\n\t_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'\n\t_LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared'\n\t_LT_TAGVAR(lt_prog_compiler_static, $1)='--static'\n\t;;\n      pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*)\n        # Portland Group compilers (*not* the Pentium gcc compiler,\n\t# which looks to be a dead project)\n\t_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'\n\t_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'\n\t_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'\n        ;;\n      ccc*)\n        _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'\n        # All Alpha code is PIC.\n        _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'\n        ;;\n      xl* | bgxl* | bgf* | mpixl*)\n\t# IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene\n\t_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'\n\t_LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic'\n\t_LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink'\n\t;;\n      *)\n\tcase `$CC -V 2>&1 | sed 5q` in\n\t*Sun\\ F* | *Sun*Fortran*)\n\t  # Sun Fortran 8.3 passes all unrecognized flags to the linker\n\t  _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'\n\t  _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'\n\t  _LT_TAGVAR(lt_prog_compiler_wl, $1)=''\n\t  ;;\n\t*Sun\\ C*)\n\t  # Sun C 5.9\n\t  _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'\n\t  _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'\n\t  _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'\n\t  ;;\n\tesac\n\t;;\n      esac\n      ;;\n\n    newsos6)\n      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'\n      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'\n      ;;\n\n    *nto* | *qnx*)\n      # QNX uses GNU C++, but need to define -shared option too, otherwise\n      # it will coredump.\n      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'\n      ;;\n\n    osf3* | osf4* | osf5*)\n      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'\n      # All OSF/1 code is PIC.\n      _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'\n      ;;\n\n    rdos*)\n      _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'\n      ;;\n\n    solaris*)\n      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'\n      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'\n      case $cc_basename in\n      f77* | f90* | f95*)\n\t_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';;\n      *)\n\t_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';;\n      esac\n      ;;\n\n    sunos4*)\n      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '\n      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'\n      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'\n      ;;\n\n    sysv4 | sysv4.2uw2* | sysv4.3*)\n      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'\n      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'\n      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'\n      ;;\n\n    sysv4*MP*)\n      if test -d /usr/nec ;then\n\t_LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic'\n\t_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'\n      fi\n      ;;\n\n    sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)\n      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'\n      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'\n      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'\n      ;;\n\n    unicos*)\n      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'\n      _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no\n      ;;\n\n    uts4*)\n      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'\n      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'\n      ;;\n\n    *)\n      _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no\n      ;;\n    esac\n  fi\n])\ncase $host_os in\n  # For platforms which do not support PIC, -DPIC is meaningless:\n  *djgpp*)\n    _LT_TAGVAR(lt_prog_compiler_pic, $1)=\n    ;;\n  *)\n    _LT_TAGVAR(lt_prog_compiler_pic, $1)=\"$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])\"\n    ;;\nesac\nAC_MSG_RESULT([$_LT_TAGVAR(lt_prog_compiler_pic, $1)])\n_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1],\n\t[How to pass a linker flag through the compiler])\n\n#\n# Check to make sure the PIC flag actually works.\n#\nif test -n \"$_LT_TAGVAR(lt_prog_compiler_pic, $1)\"; then\n  _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works],\n    [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)],\n    [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [],\n    [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in\n     \"\" | \" \"*) ;;\n     *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=\" $_LT_TAGVAR(lt_prog_compiler_pic, $1)\" ;;\n     esac],\n    [_LT_TAGVAR(lt_prog_compiler_pic, $1)=\n     _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no])\nfi\n_LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1],\n\t[Additional compiler flags for building library objects])\n\n#\n# Check to make sure the static flag actually works.\n#\nwl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\\\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\\\"\n_LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works],\n  _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1),\n  $lt_tmp_static_flag,\n  [],\n  [_LT_TAGVAR(lt_prog_compiler_static, $1)=])\n_LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1],\n\t[Compiler flag to prevent dynamic linking])\n])# _LT_COMPILER_PIC\n\n\n# _LT_LINKER_SHLIBS([TAGNAME])\n# ----------------------------\n# See if the linker supports building shared libraries.\nm4_defun([_LT_LINKER_SHLIBS],\n[AC_REQUIRE([LT_PATH_LD])dnl\nAC_REQUIRE([LT_PATH_NM])dnl\nm4_require([_LT_FILEUTILS_DEFAULTS])dnl\nm4_require([_LT_DECL_EGREP])dnl\nm4_require([_LT_DECL_SED])dnl\nm4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl\nm4_require([_LT_TAG_COMPILER])dnl\nAC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])\nm4_if([$1], [CXX], [\n  _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\\''s/.* //'\\'' | sort | uniq > $export_symbols'\n  case $host_os in\n  aix[[4-9]]*)\n    # If we're using GNU nm, then we don't want the \"-C\" option.\n    # -C means demangle to AIX nm, but means don't demangle with GNU nm\n    # Also, AIX nm treats weak defined symbols like other global defined\n    # symbols, whereas GNU nm marks them as \"W\".\n    if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then\n      _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\\''{ if (((\\$ 2 == \"T\") || (\\$ 2 == \"D\") || (\\$ 2 == \"B\") || (\\$ 2 == \"W\")) && ([substr](\\$ 3,1,1) != \".\")) { print \\$ 3 } }'\\'' | sort -u > $export_symbols'\n    else\n      _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\\''{ if (((\\$ 2 == \"T\") || (\\$ 2 == \"D\") || (\\$ 2 == \"B\") || (\\$ 2 == \"L\")) && ([substr](\\$ 3,1,1) != \".\")) { print \\$ 3 } }'\\'' | sort -u > $export_symbols'\n    fi\n    ;;\n  pw32*)\n    _LT_TAGVAR(export_symbols_cmds, $1)=\"$ltdll_cmds\"\n  ;;\n  cygwin* | mingw* | cegcc*)\n    _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\\([[^ ]]*\\)/\\1 DATA/;/^.*[[ ]]__nm__/s/^.*[[ ]]__nm__\\([[^ ]]*\\)[[ ]][[^ ]]*/\\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\\'' | sort | uniq > $export_symbols'\n  ;;\n  *)\n    _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\\''s/.* //'\\'' | sort | uniq > $export_symbols'\n  ;;\n  esac\n  _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*']\n], [\n  runpath_var=\n  _LT_TAGVAR(allow_undefined_flag, $1)=\n  _LT_TAGVAR(always_export_symbols, $1)=no\n  _LT_TAGVAR(archive_cmds, $1)=\n  _LT_TAGVAR(archive_expsym_cmds, $1)=\n  _LT_TAGVAR(compiler_needs_object, $1)=no\n  _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no\n  _LT_TAGVAR(export_dynamic_flag_spec, $1)=\n  _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\\''s/.* //'\\'' | sort | uniq > $export_symbols'\n  _LT_TAGVAR(hardcode_automatic, $1)=no\n  _LT_TAGVAR(hardcode_direct, $1)=no\n  _LT_TAGVAR(hardcode_direct_absolute, $1)=no\n  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=\n  _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=\n  _LT_TAGVAR(hardcode_libdir_separator, $1)=\n  _LT_TAGVAR(hardcode_minus_L, $1)=no\n  _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported\n  _LT_TAGVAR(inherit_rpath, $1)=no\n  _LT_TAGVAR(link_all_deplibs, $1)=unknown\n  _LT_TAGVAR(module_cmds, $1)=\n  _LT_TAGVAR(module_expsym_cmds, $1)=\n  _LT_TAGVAR(old_archive_from_new_cmds, $1)=\n  _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)=\n  _LT_TAGVAR(thread_safe_flag_spec, $1)=\n  _LT_TAGVAR(whole_archive_flag_spec, $1)=\n  # include_expsyms should be a list of space-separated symbols to be *always*\n  # included in the symbol list\n  _LT_TAGVAR(include_expsyms, $1)=\n  # exclude_expsyms can be an extended regexp of symbols to exclude\n  # it will be wrapped by ` (' and `)$', so one must not match beginning or\n  # end of line.  Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',\n  # as well as any symbol that contains `d'.\n  _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*']\n  # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out\n  # platforms (ab)use it in PIC code, but their linkers get confused if\n  # the symbol is explicitly referenced.  Since portable code cannot\n  # rely on this symbol name, it's probably fine to never include it in\n  # preloaded symbol tables.\n  # Exclude shared library initialization/finalization symbols.\ndnl Note also adjust exclude_expsyms for C++ above.\n  extract_expsyms_cmds=\n\n  case $host_os in\n  cygwin* | mingw* | pw32* | cegcc*)\n    # FIXME: the MSVC++ port hasn't been tested in a loooong time\n    # When not using gcc, we currently assume that we are using\n    # Microsoft Visual C++.\n    if test \"$GCC\" != yes; then\n      with_gnu_ld=no\n    fi\n    ;;\n  interix*)\n    # we just hope/assume this is gcc and not c89 (= MSVC++)\n    with_gnu_ld=yes\n    ;;\n  openbsd*)\n    with_gnu_ld=no\n    ;;\n  esac\n\n  _LT_TAGVAR(ld_shlibs, $1)=yes\n\n  # On some targets, GNU ld is compatible enough with the native linker\n  # that we're better off using the native interface for both.\n  lt_use_gnu_ld_interface=no\n  if test \"$with_gnu_ld\" = yes; then\n    case $host_os in\n      aix*)\n\t# The AIX port of GNU ld has always aspired to compatibility\n\t# with the native linker.  However, as the warning in the GNU ld\n\t# block says, versions before 2.19.5* couldn't really create working\n\t# shared libraries, regardless of the interface used.\n\tcase `$LD -v 2>&1` in\n\t  *\\ \\(GNU\\ Binutils\\)\\ 2.19.5*) ;;\n\t  *\\ \\(GNU\\ Binutils\\)\\ 2.[[2-9]]*) ;;\n\t  *\\ \\(GNU\\ Binutils\\)\\ [[3-9]]*) ;;\n\t  *)\n\t    lt_use_gnu_ld_interface=yes\n\t    ;;\n\tesac\n\t;;\n      *)\n\tlt_use_gnu_ld_interface=yes\n\t;;\n    esac\n  fi\n\n  if test \"$lt_use_gnu_ld_interface\" = yes; then\n    # If archive_cmds runs LD, not CC, wlarc should be empty\n    wlarc='${wl}'\n\n    # Set some defaults for GNU ld with shared library support. These\n    # are reset later if shared libraries are not supported. Putting them\n    # here allows them to be overridden if necessary.\n    runpath_var=LD_RUN_PATH\n    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'\n    _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'\n    # ancient GNU ld didn't support --whole-archive et. al.\n    if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then\n      _LT_TAGVAR(whole_archive_flag_spec, $1)=\"$wlarc\"'--whole-archive$convenience '\"$wlarc\"'--no-whole-archive'\n    else\n      _LT_TAGVAR(whole_archive_flag_spec, $1)=\n    fi\n    supports_anon_versioning=no\n    case `$LD -v 2>&1` in\n      *GNU\\ gold*) supports_anon_versioning=yes ;;\n      *\\ [[01]].* | *\\ 2.[[0-9]].* | *\\ 2.10.*) ;; # catch versions < 2.11\n      *\\ 2.11.93.0.2\\ *) supports_anon_versioning=yes ;; # RH7.3 ...\n      *\\ 2.11.92.0.12\\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...\n      *\\ 2.11.*) ;; # other 2.11 versions\n      *) supports_anon_versioning=yes ;;\n    esac\n\n    # See if GNU ld supports shared libraries.\n    case $host_os in\n    aix[[3-9]]*)\n      # On AIX/PPC, the GNU linker is very broken\n      if test \"$host_cpu\" != ia64; then\n\t_LT_TAGVAR(ld_shlibs, $1)=no\n\tcat <<_LT_EOF 1>&2\n\n*** Warning: the GNU linker, at least up to release 2.19, is reported\n*** to be unable to reliably create shared libraries on AIX.\n*** Therefore, libtool is disabling shared libraries support.  If you\n*** really care for shared libraries, you may want to install binutils\n*** 2.20 or above, or modify your PATH so that a non-GNU linker is found.\n*** You will then need to restart the configuration process.\n\n_LT_EOF\n      fi\n      ;;\n\n    amigaos*)\n      case $host_cpu in\n      powerpc)\n            # see comment about AmigaOS4 .so support\n            _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'\n            _LT_TAGVAR(archive_expsym_cmds, $1)=''\n        ;;\n      m68k)\n            _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO \"#define NAME $libname\" > $output_objdir/a2ixlibrary.data~$ECHO \"#define LIBRARY_ID 1\" >> $output_objdir/a2ixlibrary.data~$ECHO \"#define VERSION $major\" >> $output_objdir/a2ixlibrary.data~$ECHO \"#define REVISION $revision\" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'\n            _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'\n            _LT_TAGVAR(hardcode_minus_L, $1)=yes\n        ;;\n      esac\n      ;;\n\n    beos*)\n      if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then\n\t_LT_TAGVAR(allow_undefined_flag, $1)=unsupported\n\t# Joseph Beckenbach <jrb3@best.com> says some releases of gcc\n\t# support --undefined.  This deserves some investigation.  FIXME\n\t_LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'\n      else\n\t_LT_TAGVAR(ld_shlibs, $1)=no\n      fi\n      ;;\n\n    cygwin* | mingw* | pw32* | cegcc*)\n      # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,\n      # as there is no search path for DLLs.\n      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'\n      _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols'\n      _LT_TAGVAR(allow_undefined_flag, $1)=unsupported\n      _LT_TAGVAR(always_export_symbols, $1)=no\n      _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes\n      _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\\([[^ ]]*\\)/\\1 DATA/'\\'' | $SED -e '\\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\\'' | sort | uniq > $export_symbols'\n\n      if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then\n        _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'\n\t# If the export-symbols file already is a .def file (1st line\n\t# is EXPORTS), use it as is; otherwise, prepend...\n\t_LT_TAGVAR(archive_expsym_cmds, $1)='if test \"x`$SED 1q $export_symbols`\" = xEXPORTS; then\n\t  cp $export_symbols $output_objdir/$soname.def;\n\telse\n\t  echo EXPORTS > $output_objdir/$soname.def;\n\t  cat $export_symbols >> $output_objdir/$soname.def;\n\tfi~\n\t$CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'\n      else\n\t_LT_TAGVAR(ld_shlibs, $1)=no\n      fi\n      ;;\n\n    haiku*)\n      _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'\n      _LT_TAGVAR(link_all_deplibs, $1)=yes\n      ;;\n\n    interix[[3-9]]*)\n      _LT_TAGVAR(hardcode_direct, $1)=no\n      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no\n      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'\n      _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'\n      # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.\n      # Instead, shared libraries are loaded at an image base (0x10000000 by\n      # default) and relocated if they conflict, which is a slow very memory\n      # consuming and fragmenting process.  To avoid this, we pick a random,\n      # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link\n      # time.  Moving up from 0x10000000 also allows more sbrk(2) space.\n      _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \\* 262144 + 1342177280` -o $lib'\n      _LT_TAGVAR(archive_expsym_cmds, $1)='sed \"s,^,_,\" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \\* 262144 + 1342177280` -o $lib'\n      ;;\n\n    gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu | uclinuxfdpiceabi)\n      tmp_diet=no\n      if test \"$host_os\" = linux-dietlibc; then\n\tcase $cc_basename in\n\t  diet\\ *) tmp_diet=yes;;\t# linux-dietlibc with static linking (!diet-dyn)\n\tesac\n      fi\n      if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \\\n\t && test \"$tmp_diet\" = no\n      then\n\ttmp_addflag=' $pic_flag'\n\ttmp_sharedflag='-shared'\n\tcase $cc_basename,$host_cpu in\n        pgcc*)\t\t\t\t# Portland Group C compiler\n\t  _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\\\"\\\"; do test  -n \\\"$conv\\\" && new_convenience=\\\"$new_convenience,$conv\\\"; done; func_echo_all \\\"$new_convenience\\\"` ${wl}--no-whole-archive'\n\t  tmp_addflag=' $pic_flag'\n\t  ;;\n\tpgf77* | pgf90* | pgf95* | pgfortran*)\n\t\t\t\t\t# Portland Group f77 and f90 compilers\n\t  _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\\\"\\\"; do test  -n \\\"$conv\\\" && new_convenience=\\\"$new_convenience,$conv\\\"; done; func_echo_all \\\"$new_convenience\\\"` ${wl}--no-whole-archive'\n\t  tmp_addflag=' $pic_flag -Mnomain' ;;\n\tecc*,ia64* | icc*,ia64*)\t# Intel C compiler on ia64\n\t  tmp_addflag=' -i_dynamic' ;;\n\tefc*,ia64* | ifort*,ia64*)\t# Intel Fortran compiler on ia64\n\t  tmp_addflag=' -i_dynamic -nofor_main' ;;\n\tifc* | ifort*)\t\t\t# Intel Fortran compiler\n\t  tmp_addflag=' -nofor_main' ;;\n\tlf95*)\t\t\t\t# Lahey Fortran 8.1\n\t  _LT_TAGVAR(whole_archive_flag_spec, $1)=\n\t  tmp_sharedflag='--shared' ;;\n\txl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below)\n\t  tmp_sharedflag='-qmkshrobj'\n\t  tmp_addflag= ;;\n\tnvcc*)\t# Cuda Compiler Driver 2.2\n\t  _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\\\"\\\"; do test  -n \\\"$conv\\\" && new_convenience=\\\"$new_convenience,$conv\\\"; done; func_echo_all \\\"$new_convenience\\\"` ${wl}--no-whole-archive'\n\t  _LT_TAGVAR(compiler_needs_object, $1)=yes\n\t  ;;\n\tesac\n\tcase `$CC -V 2>&1 | sed 5q` in\n\t*Sun\\ C*)\t\t\t# Sun C 5.9\n\t  _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\\\"\\\"; do test -z \\\"$conv\\\" || new_convenience=\\\"$new_convenience,$conv\\\"; done; func_echo_all \\\"$new_convenience\\\"` ${wl}--no-whole-archive'\n\t  _LT_TAGVAR(compiler_needs_object, $1)=yes\n\t  tmp_sharedflag='-G' ;;\n\t*Sun\\ F*)\t\t\t# Sun Fortran 8.3\n\t  tmp_sharedflag='-G' ;;\n\tesac\n\t_LT_TAGVAR(archive_cmds, $1)='$CC '\"$tmp_sharedflag\"\"$tmp_addflag\"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'\n\n        if test \"x$supports_anon_versioning\" = xyes; then\n          _LT_TAGVAR(archive_expsym_cmds, $1)='echo \"{ global:\" > $output_objdir/$libname.ver~\n\t    cat $export_symbols | sed -e \"s/\\(.*\\)/\\1;/\" >> $output_objdir/$libname.ver~\n\t    echo \"local: *; };\" >> $output_objdir/$libname.ver~\n\t    $CC '\"$tmp_sharedflag\"\"$tmp_addflag\"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'\n        fi\n\n\tcase $cc_basename in\n\txlf* | bgf* | bgxlf* | mpixlf*)\n\t  # IBM XL Fortran 10.1 on PPC cannot create shared libs itself\n\t  _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive'\n\t  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=\n\t  _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir'\n\t  _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $compiler_flags -soname $soname -o $lib'\n\t  if test \"x$supports_anon_versioning\" = xyes; then\n\t    _LT_TAGVAR(archive_expsym_cmds, $1)='echo \"{ global:\" > $output_objdir/$libname.ver~\n\t      cat $export_symbols | sed -e \"s/\\(.*\\)/\\1;/\" >> $output_objdir/$libname.ver~\n\t      echo \"local: *; };\" >> $output_objdir/$libname.ver~\n\t      $LD -shared $libobjs $deplibs $compiler_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib'\n\t  fi\n\t  ;;\n\tesac\n      else\n        _LT_TAGVAR(ld_shlibs, $1)=no\n      fi\n      ;;\n\n    netbsd*)\n      if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then\n\t_LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'\n\twlarc=\n      else\n\t_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'\n\t_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'\n      fi\n      ;;\n\n    solaris*)\n      if $LD -v 2>&1 | $GREP 'BFD 2\\.8' > /dev/null; then\n\t_LT_TAGVAR(ld_shlibs, $1)=no\n\tcat <<_LT_EOF 1>&2\n\n*** Warning: The releases 2.8.* of the GNU linker cannot reliably\n*** create shared libraries on Solaris systems.  Therefore, libtool\n*** is disabling shared libraries support.  We urge you to upgrade GNU\n*** binutils to release 2.9.1 or newer.  Another option is to modify\n*** your PATH or compiler configuration so that the native linker is\n*** used, and then restart.\n\n_LT_EOF\n      elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then\n\t_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'\n\t_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'\n      else\n\t_LT_TAGVAR(ld_shlibs, $1)=no\n      fi\n      ;;\n\n    sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)\n      case `$LD -v 2>&1` in\n        *\\ [[01]].* | *\\ 2.[[0-9]].* | *\\ 2.1[[0-5]].*)\n\t_LT_TAGVAR(ld_shlibs, $1)=no\n\tcat <<_LT_EOF 1>&2\n\n*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not\n*** reliably create shared libraries on SCO systems.  Therefore, libtool\n*** is disabling shared libraries support.  We urge you to upgrade GNU\n*** binutils to release 2.16.91.0.3 or newer.  Another option is to modify\n*** your PATH or compiler configuration so that the native linker is\n*** used, and then restart.\n\n_LT_EOF\n\t;;\n\t*)\n\t  # For security reasons, it is highly recommended that you always\n\t  # use absolute paths for naming shared libraries, and exclude the\n\t  # DT_RUNPATH tag from executables and libraries.  But doing so\n\t  # requires that you compile everything twice, which is a pain.\n\t  if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then\n\t    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'\n\t    _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'\n\t    _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'\n\t  else\n\t    _LT_TAGVAR(ld_shlibs, $1)=no\n\t  fi\n\t;;\n      esac\n      ;;\n\n    sunos4*)\n      _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'\n      wlarc=\n      _LT_TAGVAR(hardcode_direct, $1)=yes\n      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no\n      ;;\n\n    *)\n      if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then\n\t_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'\n\t_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'\n      else\n\t_LT_TAGVAR(ld_shlibs, $1)=no\n      fi\n      ;;\n    esac\n\n    if test \"$_LT_TAGVAR(ld_shlibs, $1)\" = no; then\n      runpath_var=\n      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=\n      _LT_TAGVAR(export_dynamic_flag_spec, $1)=\n      _LT_TAGVAR(whole_archive_flag_spec, $1)=\n    fi\n  else\n    # PORTME fill in a description of your system's linker (not GNU ld)\n    case $host_os in\n    aix3*)\n      _LT_TAGVAR(allow_undefined_flag, $1)=unsupported\n      _LT_TAGVAR(always_export_symbols, $1)=yes\n      _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'\n      # Note: this linker hardcodes the directories in LIBPATH if there\n      # are no directories specified by -L.\n      _LT_TAGVAR(hardcode_minus_L, $1)=yes\n      if test \"$GCC\" = yes && test -z \"$lt_prog_compiler_static\"; then\n\t# Neither direct hardcoding nor static linking is supported with a\n\t# broken collect2.\n\t_LT_TAGVAR(hardcode_direct, $1)=unsupported\n      fi\n      ;;\n\n    aix[[4-9]]*)\n      if test \"$host_cpu\" = ia64; then\n\t# On IA64, the linker does run time linking by default, so we don't\n\t# have to do anything special.\n\taix_use_runtimelinking=no\n\texp_sym_flag='-Bexport'\n\tno_entry_flag=\"\"\n      else\n\t# If we're using GNU nm, then we don't want the \"-C\" option.\n\t# -C means demangle to AIX nm, but means don't demangle with GNU nm\n\t# Also, AIX nm treats weak defined symbols like other global\n\t# defined symbols, whereas GNU nm marks them as \"W\".\n\tif $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then\n\t  _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\\''{ if (((\\$ 2 == \"T\") || (\\$ 2 == \"D\") || (\\$ 2 == \"B\") || (\\$ 2 == \"W\")) && ([substr](\\$ 3,1,1) != \".\")) { print \\$ 3 } }'\\'' | sort -u > $export_symbols'\n\telse\n\t  _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\\''{ if (((\\$ 2 == \"T\") || (\\$ 2 == \"D\") || (\\$ 2 == \"B\") || (\\$ 2 == \"L\")) && ([substr](\\$ 3,1,1) != \".\")) { print \\$ 3 } }'\\'' | sort -u > $export_symbols'\n\tfi\n\taix_use_runtimelinking=no\n\n\t# Test if we are trying to use run time linking or normal\n\t# AIX style linking. If -brtl is somewhere in LDFLAGS, we\n\t# need to do runtime linking.\n\tcase $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*)\n\t  for ld_flag in $LDFLAGS; do\n\t  if (test $ld_flag = \"-brtl\" || test $ld_flag = \"-Wl,-brtl\"); then\n\t    aix_use_runtimelinking=yes\n\t    break\n\t  fi\n\t  done\n\t  ;;\n\tesac\n\n\texp_sym_flag='-bexport'\n\tno_entry_flag='-bnoentry'\n      fi\n\n      # When large executables or shared objects are built, AIX ld can\n      # have problems creating the table of contents.  If linking a library\n      # or program results in \"error TOC overflow\" add -mminimal-toc to\n      # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not\n      # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.\n\n      _LT_TAGVAR(archive_cmds, $1)=''\n      _LT_TAGVAR(hardcode_direct, $1)=yes\n      _LT_TAGVAR(hardcode_direct_absolute, $1)=yes\n      _LT_TAGVAR(hardcode_libdir_separator, $1)=':'\n      _LT_TAGVAR(link_all_deplibs, $1)=yes\n      _LT_TAGVAR(file_list_spec, $1)='${wl}-f,'\n\n      if test \"$GCC\" = yes; then\n\tcase $host_os in aix4.[[012]]|aix4.[[012]].*)\n\t# We only want to do this on AIX 4.2 and lower, the check\n\t# below for broken collect2 doesn't work under 4.3+\n\t  collect2name=`${CC} -print-prog-name=collect2`\n\t  if test -f \"$collect2name\" &&\n\t   strings \"$collect2name\" | $GREP resolve_lib_name >/dev/null\n\t  then\n\t  # We have reworked collect2\n\t  :\n\t  else\n\t  # We have old collect2\n\t  _LT_TAGVAR(hardcode_direct, $1)=unsupported\n\t  # It fails to find uninstalled libraries when the uninstalled\n\t  # path is not listed in the libpath.  Setting hardcode_minus_L\n\t  # to unsupported forces relinking\n\t  _LT_TAGVAR(hardcode_minus_L, $1)=yes\n\t  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'\n\t  _LT_TAGVAR(hardcode_libdir_separator, $1)=\n\t  fi\n\t  ;;\n\tesac\n\tshared_flag='-shared'\n\tif test \"$aix_use_runtimelinking\" = yes; then\n\t  shared_flag=\"$shared_flag \"'${wl}-G'\n\tfi\n      else\n\t# not using gcc\n\tif test \"$host_cpu\" = ia64; then\n\t# VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release\n\t# chokes on -Wl,-G. The following line is correct:\n\t  shared_flag='-G'\n\telse\n\t  if test \"$aix_use_runtimelinking\" = yes; then\n\t    shared_flag='${wl}-G'\n\t  else\n\t    shared_flag='${wl}-bM:SRE'\n\t  fi\n\tfi\n      fi\n\n      _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall'\n      # It seems that -bexpall does not export symbols beginning with\n      # underscore (_), so it is better to generate a list of symbols to export.\n      _LT_TAGVAR(always_export_symbols, $1)=yes\n      if test \"$aix_use_runtimelinking\" = yes; then\n\t# Warning - without using the other runtime loading flags (-brtl),\n\t# -berok will link without error, but may produce a broken library.\n\t_LT_TAGVAR(allow_undefined_flag, $1)='-berok'\n        # Determine the default libpath from the value encoded in an\n        # empty executable.\n        _LT_SYS_MODULE_PATH_AIX\n        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'\"$aix_libpath\"\n        _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '\"\\${wl}$no_entry_flag\"' $compiler_flags `if test \"x${allow_undefined_flag}\" != \"x\"; then func_echo_all \"${wl}${allow_undefined_flag}\"; else :; fi` '\"\\${wl}$exp_sym_flag:\\$export_symbols $shared_flag\"\n      else\n\tif test \"$host_cpu\" = ia64; then\n\t  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib'\n\t  _LT_TAGVAR(allow_undefined_flag, $1)=\"-z nodefs\"\n\t  _LT_TAGVAR(archive_expsym_cmds, $1)=\"\\$CC $shared_flag\"' -o $output_objdir/$soname $libobjs $deplibs '\"\\${wl}$no_entry_flag\"' $compiler_flags ${wl}${allow_undefined_flag} '\"\\${wl}$exp_sym_flag:\\$export_symbols\"\n\telse\n\t # Determine the default libpath from the value encoded in an\n\t # empty executable.\n\t _LT_SYS_MODULE_PATH_AIX\n\t _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'\"$aix_libpath\"\n\t  # Warning - without using the other run time loading flags,\n\t  # -berok will link without error, but may produce a broken library.\n\t  _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok'\n\t  _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok'\n\t  if test \"$with_gnu_ld\" = yes; then\n\t    # We only use this code for GNU lds that support --whole-archive.\n\t    _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive'\n\t  else\n\t    # Exported symbols can be pulled into shared objects from archives\n\t    _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience'\n\t  fi\n\t  _LT_TAGVAR(archive_cmds_need_lc, $1)=yes\n\t  # This is similar to how AIX traditionally builds its shared libraries.\n\t  _LT_TAGVAR(archive_expsym_cmds, $1)=\"\\$CC $shared_flag\"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'\n\tfi\n      fi\n      ;;\n\n    amigaos*)\n      case $host_cpu in\n      powerpc)\n            # see comment about AmigaOS4 .so support\n            _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'\n            _LT_TAGVAR(archive_expsym_cmds, $1)=''\n        ;;\n      m68k)\n            _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO \"#define NAME $libname\" > $output_objdir/a2ixlibrary.data~$ECHO \"#define LIBRARY_ID 1\" >> $output_objdir/a2ixlibrary.data~$ECHO \"#define VERSION $major\" >> $output_objdir/a2ixlibrary.data~$ECHO \"#define REVISION $revision\" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'\n            _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'\n            _LT_TAGVAR(hardcode_minus_L, $1)=yes\n        ;;\n      esac\n      ;;\n\n    bsdi[[45]]*)\n      _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic\n      ;;\n\n    cygwin* | mingw* | pw32* | cegcc*)\n      # When not using gcc, we currently assume that we are using\n      # Microsoft Visual C++.\n      # hardcode_libdir_flag_spec is actually meaningless, as there is\n      # no search path for DLLs.\n      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '\n      _LT_TAGVAR(allow_undefined_flag, $1)=unsupported\n      # Tell ltmain to make .lib files, not .a files.\n      libext=lib\n      # Tell ltmain to make .dll files, not .so files.\n      shrext_cmds=\".dll\"\n      # FIXME: Setting linknames here is a bad hack.\n      _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all \"$deplibs\" | $SED '\\''s/ -lc$//'\\''` -link -dll~linknames='\n      # The linker will automatically build a .lib file if we build a DLL.\n      _LT_TAGVAR(old_archive_from_new_cmds, $1)='true'\n      # FIXME: Should let the user specify the lib program.\n      _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs'\n      _LT_TAGVAR(fix_srcfile_path, $1)='`cygpath -w \"$srcfile\"`'\n      _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes\n      ;;\n\n    darwin* | rhapsody*)\n      _LT_DARWIN_LINKER_FEATURES($1)\n      ;;\n\n    dgux*)\n      _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'\n      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'\n      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no\n      ;;\n\n    # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor\n    # support.  Future versions do this automatically, but an explicit c++rt0.o\n    # does not break anything, and helps significantly (at the cost of a little\n    # extra space).\n    freebsd2.2*)\n      _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'\n      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'\n      _LT_TAGVAR(hardcode_direct, $1)=yes\n      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no\n      ;;\n\n    # Unfortunately, older versions of FreeBSD 2 do not have this feature.\n    freebsd2.*)\n      _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'\n      _LT_TAGVAR(hardcode_direct, $1)=yes\n      _LT_TAGVAR(hardcode_minus_L, $1)=yes\n      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no\n      ;;\n\n    # FreeBSD 3 and greater uses gcc -shared to do shared libraries.\n    freebsd* | dragonfly*)\n      _LT_TAGVAR(archive_cmds, $1)='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'\n      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'\n      _LT_TAGVAR(hardcode_direct, $1)=yes\n      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no\n      ;;\n\n    hpux9*)\n      if test \"$GCC\" = yes; then\n\t_LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'\n      else\n\t_LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'\n      fi\n      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'\n      _LT_TAGVAR(hardcode_libdir_separator, $1)=:\n      _LT_TAGVAR(hardcode_direct, $1)=yes\n\n      # hardcode_minus_L: Not really in the search PATH,\n      # but as the default location of the library.\n      _LT_TAGVAR(hardcode_minus_L, $1)=yes\n      _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'\n      ;;\n\n    hpux10*)\n      if test \"$GCC\" = yes && test \"$with_gnu_ld\" = no; then\n\t_LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'\n      else\n\t_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'\n      fi\n      if test \"$with_gnu_ld\" = no; then\n\t_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'\n\t_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir'\n\t_LT_TAGVAR(hardcode_libdir_separator, $1)=:\n\t_LT_TAGVAR(hardcode_direct, $1)=yes\n\t_LT_TAGVAR(hardcode_direct_absolute, $1)=yes\n\t_LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'\n\t# hardcode_minus_L: Not really in the search PATH,\n\t# but as the default location of the library.\n\t_LT_TAGVAR(hardcode_minus_L, $1)=yes\n      fi\n      ;;\n\n    hpux11*)\n      if test \"$GCC\" = yes && test \"$with_gnu_ld\" = no; then\n\tcase $host_cpu in\n\thppa*64*)\n\t  _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'\n\t  ;;\n\tia64*)\n\t  _LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'\n\t  ;;\n\t*)\n\t  _LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'\n\t  ;;\n\tesac\n      else\n\tcase $host_cpu in\n\thppa*64*)\n\t  _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'\n\t  ;;\n\tia64*)\n\t  _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'\n\t  ;;\n\t*)\n\tm4_if($1, [], [\n\t  # Older versions of the 11.00 compiler do not understand -b yet\n\t  # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does)\n\t  _LT_LINKER_OPTION([if $CC understands -b],\n\t    _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b],\n\t    [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'],\n\t    [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])],\n\t  [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'])\n\t  ;;\n\tesac\n      fi\n      if test \"$with_gnu_ld\" = no; then\n\t_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'\n\t_LT_TAGVAR(hardcode_libdir_separator, $1)=:\n\n\tcase $host_cpu in\n\thppa*64*|ia64*)\n\t  _LT_TAGVAR(hardcode_direct, $1)=no\n\t  _LT_TAGVAR(hardcode_shlibpath_var, $1)=no\n\t  ;;\n\t*)\n\t  _LT_TAGVAR(hardcode_direct, $1)=yes\n\t  _LT_TAGVAR(hardcode_direct_absolute, $1)=yes\n\t  _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'\n\n\t  # hardcode_minus_L: Not really in the search PATH,\n\t  # but as the default location of the library.\n\t  _LT_TAGVAR(hardcode_minus_L, $1)=yes\n\t  ;;\n\tesac\n      fi\n      ;;\n\n    irix5* | irix6* | nonstopux*)\n      if test \"$GCC\" = yes; then\n\t_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n \"$verstring\" && func_echo_all \"${wl}-set_version ${wl}$verstring\"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'\n\t# Try to use the -exported_symbol ld option, if it does not\n\t# work, assume that -exports_file does not work either and\n\t# implicitly export all symbols.\n        save_LDFLAGS=\"$LDFLAGS\"\n        LDFLAGS=\"$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null\"\n        AC_LINK_IFELSE([AC_LANG_SOURCE([int foo(void) {}])],\n          _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n \"$verstring\" && func_echo_all \"${wl}-set_version ${wl}$verstring\"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib'\n        )\n        LDFLAGS=\"$save_LDFLAGS\"\n      else\n\t_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n \"$verstring\" && func_echo_all \"-set_version $verstring\"` -update_registry ${output_objdir}/so_locations -o $lib'\n\t_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n \"$verstring\" && func_echo_all \"-set_version $verstring\"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib'\n      fi\n      _LT_TAGVAR(archive_cmds_need_lc, $1)='no'\n      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'\n      _LT_TAGVAR(hardcode_libdir_separator, $1)=:\n      _LT_TAGVAR(inherit_rpath, $1)=yes\n      _LT_TAGVAR(link_all_deplibs, $1)=yes\n      ;;\n\n    netbsd*)\n      if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then\n\t_LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'  # a.out\n      else\n\t_LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags'      # ELF\n      fi\n      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'\n      _LT_TAGVAR(hardcode_direct, $1)=yes\n      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no\n      ;;\n\n    newsos6)\n      _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'\n      _LT_TAGVAR(hardcode_direct, $1)=yes\n      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'\n      _LT_TAGVAR(hardcode_libdir_separator, $1)=:\n      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no\n      ;;\n\n    *nto* | *qnx*)\n      ;;\n\n    openbsd*)\n      if test -f /usr/libexec/ld.so; then\n\t_LT_TAGVAR(hardcode_direct, $1)=yes\n\t_LT_TAGVAR(hardcode_shlibpath_var, $1)=no\n\t_LT_TAGVAR(hardcode_direct_absolute, $1)=yes\n\tif test -z \"`echo __ELF__ | $CC -E - | $GREP __ELF__`\" || test \"$host_os-$host_cpu\" = \"openbsd2.8-powerpc\"; then\n\t  _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'\n\t  _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'\n\t  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'\n\t  _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'\n\telse\n\t  case $host_os in\n\t   openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*)\n\t     _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'\n\t     _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'\n\t     ;;\n\t   *)\n\t     _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'\n\t     _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'\n\t     ;;\n\t  esac\n\tfi\n      else\n\t_LT_TAGVAR(ld_shlibs, $1)=no\n      fi\n      ;;\n\n    os2*)\n      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'\n      _LT_TAGVAR(hardcode_minus_L, $1)=yes\n      _LT_TAGVAR(allow_undefined_flag, $1)=unsupported\n      _LT_TAGVAR(archive_cmds, $1)='$ECHO \"LIBRARY $libname INITINSTANCE\" > $output_objdir/$libname.def~$ECHO \"DESCRIPTION \\\"$libname\\\"\" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo \" SINGLE NONSHARED\" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'\n      _LT_TAGVAR(old_archive_from_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'\n      ;;\n\n    osf3*)\n      if test \"$GCC\" = yes; then\n\t_LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\\*'\n\t_LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n \"$verstring\" && func_echo_all \"${wl}-set_version ${wl}$verstring\"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'\n      else\n\t_LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \\*'\n\t_LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n \"$verstring\" && func_echo_all \"-set_version $verstring\"` -update_registry ${output_objdir}/so_locations -o $lib'\n      fi\n      _LT_TAGVAR(archive_cmds_need_lc, $1)='no'\n      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'\n      _LT_TAGVAR(hardcode_libdir_separator, $1)=:\n      ;;\n\n    osf4* | osf5*)\t# as osf3* with the addition of -msym flag\n      if test \"$GCC\" = yes; then\n\t_LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\\*'\n\t_LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n \"$verstring\" && func_echo_all \"${wl}-set_version ${wl}$verstring\"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'\n\t_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'\n      else\n\t_LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \\*'\n\t_LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n \"$verstring\" && func_echo_all \"-set_version $verstring\"` -update_registry ${output_objdir}/so_locations -o $lib'\n\t_LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf \"%s %s\\\\n\" -exported_symbol \"\\$i\" >> $lib.exp; done; printf \"%s\\\\n\" \"-hidden\">> $lib.exp~\n\t$CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n \"$verstring\" && $ECHO \"-set_version $verstring\"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp'\n\n\t# Both c and cxx compiler support -rpath directly\n\t_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'\n      fi\n      _LT_TAGVAR(archive_cmds_need_lc, $1)='no'\n      _LT_TAGVAR(hardcode_libdir_separator, $1)=:\n      ;;\n\n    solaris*)\n      _LT_TAGVAR(no_undefined_flag, $1)=' -z defs'\n      if test \"$GCC\" = yes; then\n\twlarc='${wl}'\n\t_LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'\n\t_LT_TAGVAR(archive_expsym_cmds, $1)='echo \"{ global:\" > $lib.exp~cat $export_symbols | $SED -e \"s/\\(.*\\)/\\1;/\" >> $lib.exp~echo \"local: *; };\" >> $lib.exp~\n\t  $CC -shared ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'\n      else\n\tcase `$CC -V 2>&1` in\n\t*\"Compilers 5.0\"*)\n\t  wlarc=''\n\t  _LT_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'\n\t  _LT_TAGVAR(archive_expsym_cmds, $1)='echo \"{ global:\" > $lib.exp~cat $export_symbols | $SED -e \"s/\\(.*\\)/\\1;/\" >> $lib.exp~echo \"local: *; };\" >> $lib.exp~\n\t  $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp'\n\t  ;;\n\t*)\n\t  wlarc='${wl}'\n\t  _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags'\n\t  _LT_TAGVAR(archive_expsym_cmds, $1)='echo \"{ global:\" > $lib.exp~cat $export_symbols | $SED -e \"s/\\(.*\\)/\\1;/\" >> $lib.exp~echo \"local: *; };\" >> $lib.exp~\n\t  $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'\n\t  ;;\n\tesac\n      fi\n      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'\n      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no\n      case $host_os in\n      solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;\n      *)\n\t# The compiler driver will combine and reorder linker options,\n\t# but understands `-z linker_flag'.  GCC discards it without `$wl',\n\t# but is careful enough not to reorder.\n\t# Supported since Solaris 2.6 (maybe 2.5.1?)\n\tif test \"$GCC\" = yes; then\n\t  _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'\n\telse\n\t  _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract'\n\tfi\n\t;;\n      esac\n      _LT_TAGVAR(link_all_deplibs, $1)=yes\n      ;;\n\n    sunos4*)\n      if test \"x$host_vendor\" = xsequent; then\n\t# Use $CC to link under sequent, because it throws in some extra .o\n\t# files that make .init and .fini sections work.\n\t_LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'\n      else\n\t_LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'\n      fi\n      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'\n      _LT_TAGVAR(hardcode_direct, $1)=yes\n      _LT_TAGVAR(hardcode_minus_L, $1)=yes\n      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no\n      ;;\n\n    sysv4)\n      case $host_vendor in\n\tsni)\n\t  _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'\n\t  _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true???\n\t;;\n\tsiemens)\n\t  ## LD is ld it makes a PLAMLIB\n\t  ## CC just makes a GrossModule.\n\t  _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags'\n\t  _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs'\n\t  _LT_TAGVAR(hardcode_direct, $1)=no\n        ;;\n\tmotorola)\n\t  _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'\n\t  _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie\n\t;;\n      esac\n      runpath_var='LD_RUN_PATH'\n      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no\n      ;;\n\n    sysv4.3*)\n      _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'\n      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no\n      _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport'\n      ;;\n\n    sysv4*MP*)\n      if test -d /usr/nec; then\n\t_LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'\n\t_LT_TAGVAR(hardcode_shlibpath_var, $1)=no\n\trunpath_var=LD_RUN_PATH\n\thardcode_runpath_var=yes\n\t_LT_TAGVAR(ld_shlibs, $1)=yes\n      fi\n      ;;\n\n    sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)\n      _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'\n      _LT_TAGVAR(archive_cmds_need_lc, $1)=no\n      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no\n      runpath_var='LD_RUN_PATH'\n\n      if test \"$GCC\" = yes; then\n\t_LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'\n\t_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'\n      else\n\t_LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'\n\t_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'\n      fi\n      ;;\n\n    sysv5* | sco3.2v5* | sco5v6*)\n      # Note: We can NOT use -z defs as we might desire, because we do not\n      # link with -lc, and that would cause any symbols used from libc to\n      # always be unresolved, which means just about no library would\n      # ever link correctly.  If we're not using GNU ld we use -z text\n      # though, which does catch some bad symbols but isn't as heavy-handed\n      # as -z defs.\n      _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'\n      _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs'\n      _LT_TAGVAR(archive_cmds_need_lc, $1)=no\n      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no\n      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir'\n      _LT_TAGVAR(hardcode_libdir_separator, $1)=':'\n      _LT_TAGVAR(link_all_deplibs, $1)=yes\n      _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport'\n      runpath_var='LD_RUN_PATH'\n\n      if test \"$GCC\" = yes; then\n\t_LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'\n\t_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'\n      else\n\t_LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'\n\t_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'\n      fi\n      ;;\n\n    uts4*)\n      _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'\n      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'\n      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no\n      ;;\n\n    *)\n      _LT_TAGVAR(ld_shlibs, $1)=no\n      ;;\n    esac\n\n    if test x$host_vendor = xsni; then\n      case $host in\n      sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)\n\t_LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Blargedynsym'\n\t;;\n      esac\n    fi\n  fi\n])\nAC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)])\ntest \"$_LT_TAGVAR(ld_shlibs, $1)\" = no && can_build_shared=no\n\n_LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld\n\n_LT_DECL([], [libext], [0], [Old archive suffix (normally \"a\")])dnl\n_LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally \".so\")])dnl\n_LT_DECL([], [extract_expsyms_cmds], [2],\n    [The commands to extract the exported symbol list from a shared archive])\n\n#\n# Do we need to explicitly link libc?\n#\ncase \"x$_LT_TAGVAR(archive_cmds_need_lc, $1)\" in\nx|xyes)\n  # Assume -lc should be added\n  _LT_TAGVAR(archive_cmds_need_lc, $1)=yes\n\n  if test \"$enable_shared\" = yes && test \"$GCC\" = yes; then\n    case $_LT_TAGVAR(archive_cmds, $1) in\n    *'~'*)\n      # FIXME: we may have to deal with multi-command sequences.\n      ;;\n    '$CC '*)\n      # Test whether the compiler implicitly links with -lc since on some\n      # systems, -lgcc has to come before -lc. If gcc already passes -lc\n      # to ld, don't add -lc before -lgcc.\n      AC_CACHE_CHECK([whether -lc should be explicitly linked in],\n\t[lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1),\n\t[$RM conftest*\n\techo \"$lt_simple_compile_test_code\" > conftest.$ac_ext\n\n\tif AC_TRY_EVAL(ac_compile) 2>conftest.err; then\n\t  soname=conftest\n\t  lib=conftest\n\t  libobjs=conftest.$ac_objext\n\t  deplibs=\n\t  wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1)\n\t  pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1)\n\t  compiler_flags=-v\n\t  linker_flags=-v\n\t  verstring=\n\t  output_objdir=.\n\t  libname=conftest\n\t  lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1)\n\t  _LT_TAGVAR(allow_undefined_flag, $1)=\n\t  if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\\>\\&1 \\| $GREP \\\" -lc \\\" \\>/dev/null 2\\>\\&1)\n\t  then\n\t    lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no\n\t  else\n\t    lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes\n\t  fi\n\t  _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag\n\telse\n\t  cat conftest.err 1>&5\n\tfi\n\t$RM conftest*\n\t])\n      _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)\n      ;;\n    esac\n  fi\n  ;;\nesac\n\n_LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0],\n    [Whether or not to add -lc for building shared libraries])\n_LT_TAGDECL([allow_libtool_libs_with_static_runtimes],\n    [enable_shared_with_static_runtimes], [0],\n    [Whether or not to disallow shared libs when runtime libs are static])\n_LT_TAGDECL([], [export_dynamic_flag_spec], [1],\n    [Compiler flag to allow reflexive dlopens])\n_LT_TAGDECL([], [whole_archive_flag_spec], [1],\n    [Compiler flag to generate shared objects directly from archives])\n_LT_TAGDECL([], [compiler_needs_object], [1],\n    [Whether the compiler copes with passing no objects directly])\n_LT_TAGDECL([], [old_archive_from_new_cmds], [2],\n    [Create an old-style archive from a shared archive])\n_LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2],\n    [Create a temporary old-style archive to link instead of a shared archive])\n_LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive])\n_LT_TAGDECL([], [archive_expsym_cmds], [2])\n_LT_TAGDECL([], [module_cmds], [2],\n    [Commands used to build a loadable module if different from building\n    a shared archive.])\n_LT_TAGDECL([], [module_expsym_cmds], [2])\n_LT_TAGDECL([], [with_gnu_ld], [1],\n    [Whether we are building with GNU ld or not])\n_LT_TAGDECL([], [allow_undefined_flag], [1],\n    [Flag that allows shared libraries with undefined symbols to be built])\n_LT_TAGDECL([], [no_undefined_flag], [1],\n    [Flag that enforces no undefined symbols])\n_LT_TAGDECL([], [hardcode_libdir_flag_spec], [1],\n    [Flag to hardcode $libdir into a binary during linking.\n    This must work even if $libdir does not exist])\n_LT_TAGDECL([], [hardcode_libdir_flag_spec_ld], [1],\n    [[If ld is used when linking, flag to hardcode $libdir into a binary\n    during linking.  This must work even if $libdir does not exist]])\n_LT_TAGDECL([], [hardcode_libdir_separator], [1],\n    [Whether we need a single \"-rpath\" flag with a separated argument])\n_LT_TAGDECL([], [hardcode_direct], [0],\n    [Set to \"yes\" if using DIR/libNAME${shared_ext} during linking hardcodes\n    DIR into the resulting binary])\n_LT_TAGDECL([], [hardcode_direct_absolute], [0],\n    [Set to \"yes\" if using DIR/libNAME${shared_ext} during linking hardcodes\n    DIR into the resulting binary and the resulting library dependency is\n    \"absolute\", i.e impossible to change by setting ${shlibpath_var} if the\n    library is relocated])\n_LT_TAGDECL([], [hardcode_minus_L], [0],\n    [Set to \"yes\" if using the -LDIR flag during linking hardcodes DIR\n    into the resulting binary])\n_LT_TAGDECL([], [hardcode_shlibpath_var], [0],\n    [Set to \"yes\" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR\n    into the resulting binary])\n_LT_TAGDECL([], [hardcode_automatic], [0],\n    [Set to \"yes\" if building a shared library automatically hardcodes DIR\n    into the library and all subsequent libraries and executables linked\n    against it])\n_LT_TAGDECL([], [inherit_rpath], [0],\n    [Set to yes if linker adds runtime paths of dependent libraries\n    to runtime path list])\n_LT_TAGDECL([], [link_all_deplibs], [0],\n    [Whether libtool must link a program against all its dependency libraries])\n_LT_TAGDECL([], [fix_srcfile_path], [1],\n    [Fix the shell variable $srcfile for the compiler])\n_LT_TAGDECL([], [always_export_symbols], [0],\n    [Set to \"yes\" if exported symbols are required])\n_LT_TAGDECL([], [export_symbols_cmds], [2],\n    [The commands to list exported symbols])\n_LT_TAGDECL([], [exclude_expsyms], [1],\n    [Symbols that should not be listed in the preloaded symbols])\n_LT_TAGDECL([], [include_expsyms], [1],\n    [Symbols that must always be exported])\n_LT_TAGDECL([], [prelink_cmds], [2],\n    [Commands necessary for linking programs (against libraries) with templates])\n_LT_TAGDECL([], [file_list_spec], [1],\n    [Specify filename containing input files])\ndnl FIXME: Not yet implemented\ndnl _LT_TAGDECL([], [thread_safe_flag_spec], [1],\ndnl    [Compiler flag to generate thread safe objects])\n])# _LT_LINKER_SHLIBS\n\n\n# _LT_LANG_C_CONFIG([TAG])\n# ------------------------\n# Ensure that the configuration variables for a C compiler are suitably\n# defined.  These variables are subsequently used by _LT_CONFIG to write\n# the compiler configuration to `libtool'.\nm4_defun([_LT_LANG_C_CONFIG],\n[m4_require([_LT_DECL_EGREP])dnl\nlt_save_CC=\"$CC\"\nAC_LANG_PUSH(C)\n\n# Source file extension for C test sources.\nac_ext=c\n\n# Object file extension for compiled C test sources.\nobjext=o\n_LT_TAGVAR(objext, $1)=$objext\n\n# Code to be used in simple compile tests\nlt_simple_compile_test_code=\"int some_variable = 0;\"\n\n# Code to be used in simple link tests\nlt_simple_link_test_code='int main(){return(0);}'\n\n_LT_TAG_COMPILER\n# Save the default compiler, since it gets overwritten when the other\n# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP.\ncompiler_DEFAULT=$CC\n\n# save warnings/boilerplate of simple test code\n_LT_COMPILER_BOILERPLATE\n_LT_LINKER_BOILERPLATE\n\n## CAVEAT EMPTOR:\n## There is no encapsulation within the following macros, do not change\n## the running order or otherwise move them around unless you know exactly\n## what you are doing...\nif test -n \"$compiler\"; then\n  _LT_COMPILER_NO_RTTI($1)\n  _LT_COMPILER_PIC($1)\n  _LT_COMPILER_C_O($1)\n  _LT_COMPILER_FILE_LOCKS($1)\n  _LT_LINKER_SHLIBS($1)\n  _LT_SYS_DYNAMIC_LINKER($1)\n  _LT_LINKER_HARDCODE_LIBPATH($1)\n  LT_SYS_DLOPEN_SELF\n  _LT_CMD_STRIPLIB\n\n  # Report which library types will actually be built\n  AC_MSG_CHECKING([if libtool supports shared libraries])\n  AC_MSG_RESULT([$can_build_shared])\n\n  AC_MSG_CHECKING([whether to build shared libraries])\n  test \"$can_build_shared\" = \"no\" && enable_shared=no\n\n  # On AIX, shared libraries and static libraries use the same namespace, and\n  # are all built from PIC.\n  case $host_os in\n  aix3*)\n    test \"$enable_shared\" = yes && enable_static=no\n    if test -n \"$RANLIB\"; then\n      archive_cmds=\"$archive_cmds~\\$RANLIB \\$lib\"\n      postinstall_cmds='$RANLIB $lib'\n    fi\n    ;;\n\n  aix[[4-9]]*)\n    if test \"$host_cpu\" != ia64 && test \"$aix_use_runtimelinking\" = no ; then\n      test \"$enable_shared\" = yes && enable_static=no\n    fi\n    ;;\n  esac\n  AC_MSG_RESULT([$enable_shared])\n\n  AC_MSG_CHECKING([whether to build static libraries])\n  # Make sure either enable_shared or enable_static is yes.\n  test \"$enable_shared\" = yes || enable_static=yes\n  AC_MSG_RESULT([$enable_static])\n\n  _LT_CONFIG($1)\nfi\nAC_LANG_POP\nCC=\"$lt_save_CC\"\n])# _LT_LANG_C_CONFIG\n\n\n# _LT_LANG_CXX_CONFIG([TAG])\n# --------------------------\n# Ensure that the configuration variables for a C++ compiler are suitably\n# defined.  These variables are subsequently used by _LT_CONFIG to write\n# the compiler configuration to `libtool'.\nm4_defun([_LT_LANG_CXX_CONFIG],\n[m4_require([_LT_FILEUTILS_DEFAULTS])dnl\nm4_require([_LT_DECL_EGREP])dnl\nif test -n \"$CXX\" && ( test \"X$CXX\" != \"Xno\" &&\n    ( (test \"X$CXX\" = \"Xg++\" && `g++ -v >/dev/null 2>&1` ) ||\n    (test \"X$CXX\" != \"Xg++\"))) ; then\n  AC_PROG_CXXCPP\nelse\n  _lt_caught_CXX_error=yes\nfi\n\nAC_LANG_PUSH(C++)\n_LT_TAGVAR(archive_cmds_need_lc, $1)=no\n_LT_TAGVAR(allow_undefined_flag, $1)=\n_LT_TAGVAR(always_export_symbols, $1)=no\n_LT_TAGVAR(archive_expsym_cmds, $1)=\n_LT_TAGVAR(compiler_needs_object, $1)=no\n_LT_TAGVAR(export_dynamic_flag_spec, $1)=\n_LT_TAGVAR(hardcode_direct, $1)=no\n_LT_TAGVAR(hardcode_direct_absolute, $1)=no\n_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=\n_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=\n_LT_TAGVAR(hardcode_libdir_separator, $1)=\n_LT_TAGVAR(hardcode_minus_L, $1)=no\n_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported\n_LT_TAGVAR(hardcode_automatic, $1)=no\n_LT_TAGVAR(inherit_rpath, $1)=no\n_LT_TAGVAR(module_cmds, $1)=\n_LT_TAGVAR(module_expsym_cmds, $1)=\n_LT_TAGVAR(link_all_deplibs, $1)=unknown\n_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds\n_LT_TAGVAR(reload_flag, $1)=$reload_flag\n_LT_TAGVAR(reload_cmds, $1)=$reload_cmds\n_LT_TAGVAR(no_undefined_flag, $1)=\n_LT_TAGVAR(whole_archive_flag_spec, $1)=\n_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no\n\n# Source file extension for C++ test sources.\nac_ext=cpp\n\n# Object file extension for compiled C++ test sources.\nobjext=o\n_LT_TAGVAR(objext, $1)=$objext\n\n# No sense in running all these tests if we already determined that\n# the CXX compiler isn't working.  Some variables (like enable_shared)\n# are currently assumed to apply to all compilers on this platform,\n# and will be corrupted by setting them based on a non-working compiler.\nif test \"$_lt_caught_CXX_error\" != yes; then\n  # Code to be used in simple compile tests\n  lt_simple_compile_test_code=\"int some_variable = 0;\"\n\n  # Code to be used in simple link tests\n  lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }'\n\n  # ltmain only uses $CC for tagged configurations so make sure $CC is set.\n  _LT_TAG_COMPILER\n\n  # save warnings/boilerplate of simple test code\n  _LT_COMPILER_BOILERPLATE\n  _LT_LINKER_BOILERPLATE\n\n  # Allow CC to be a program name with arguments.\n  lt_save_CC=$CC\n  lt_save_LD=$LD\n  lt_save_GCC=$GCC\n  GCC=$GXX\n  lt_save_with_gnu_ld=$with_gnu_ld\n  lt_save_path_LD=$lt_cv_path_LD\n  if test -n \"${lt_cv_prog_gnu_ldcxx+set}\"; then\n    lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx\n  else\n    $as_unset lt_cv_prog_gnu_ld\n  fi\n  if test -n \"${lt_cv_path_LDCXX+set}\"; then\n    lt_cv_path_LD=$lt_cv_path_LDCXX\n  else\n    $as_unset lt_cv_path_LD\n  fi\n  test -z \"${LDCXX+set}\" || LD=$LDCXX\n  CC=${CXX-\"c++\"}\n  compiler=$CC\n  _LT_TAGVAR(compiler, $1)=$CC\n  _LT_CC_BASENAME([$compiler])\n\n  if test -n \"$compiler\"; then\n    # We don't want -fno-exception when compiling C++ code, so set the\n    # no_builtin_flag separately\n    if test \"$GXX\" = yes; then\n      _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin'\n    else\n      _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=\n    fi\n\n    if test \"$GXX\" = yes; then\n      # Set up default GNU C++ configuration\n\n      LT_PATH_LD\n\n      # Check if GNU C++ uses GNU ld as the underlying linker, since the\n      # archiving commands below assume that GNU ld is being used.\n      if test \"$with_gnu_ld\" = yes; then\n        _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'\n        _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'\n\n        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'\n        _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'\n\n        # If archive_cmds runs LD, not CC, wlarc should be empty\n        # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to\n        #     investigate it a little bit more. (MM)\n        wlarc='${wl}'\n\n        # ancient GNU ld didn't support --whole-archive et. al.\n        if eval \"`$CC -print-prog-name=ld` --help 2>&1\" |\n\t  $GREP 'no-whole-archive' > /dev/null; then\n          _LT_TAGVAR(whole_archive_flag_spec, $1)=\"$wlarc\"'--whole-archive$convenience '\"$wlarc\"'--no-whole-archive'\n        else\n          _LT_TAGVAR(whole_archive_flag_spec, $1)=\n        fi\n      else\n        with_gnu_ld=no\n        wlarc=\n\n        # A generic and very simple default shared library creation\n        # command for GNU C++ for the case where it uses the native\n        # linker, instead of GNU ld.  If possible, this setting should\n        # overridden to take advantage of the native linker features on\n        # the platform it is being used on.\n        _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'\n      fi\n\n      # Commands to make compiler produce verbose output that lists\n      # what \"hidden\" libraries, object files and flags are used when\n      # linking a shared library.\n      output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v \"^Configured with:\" | $GREP \"\\-L\"'\n\n    else\n      GXX=no\n      with_gnu_ld=no\n      wlarc=\n    fi\n\n    # PORTME: fill in a description of your system's C++ link characteristics\n    AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])\n    _LT_TAGVAR(ld_shlibs, $1)=yes\n    case $host_os in\n      aix3*)\n        # FIXME: insert proper C++ library support\n        _LT_TAGVAR(ld_shlibs, $1)=no\n        ;;\n      aix[[4-9]]*)\n        if test \"$host_cpu\" = ia64; then\n          # On IA64, the linker does run time linking by default, so we don't\n          # have to do anything special.\n          aix_use_runtimelinking=no\n          exp_sym_flag='-Bexport'\n          no_entry_flag=\"\"\n        else\n          aix_use_runtimelinking=no\n\n          # Test if we are trying to use run time linking or normal\n          # AIX style linking. If -brtl is somewhere in LDFLAGS, we\n          # need to do runtime linking.\n          case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*)\n\t    for ld_flag in $LDFLAGS; do\n\t      case $ld_flag in\n\t      *-brtl*)\n\t        aix_use_runtimelinking=yes\n\t        break\n\t        ;;\n\t      esac\n\t    done\n\t    ;;\n          esac\n\n          exp_sym_flag='-bexport'\n          no_entry_flag='-bnoentry'\n        fi\n\n        # When large executables or shared objects are built, AIX ld can\n        # have problems creating the table of contents.  If linking a library\n        # or program results in \"error TOC overflow\" add -mminimal-toc to\n        # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not\n        # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.\n\n        _LT_TAGVAR(archive_cmds, $1)=''\n        _LT_TAGVAR(hardcode_direct, $1)=yes\n        _LT_TAGVAR(hardcode_direct_absolute, $1)=yes\n        _LT_TAGVAR(hardcode_libdir_separator, $1)=':'\n        _LT_TAGVAR(link_all_deplibs, $1)=yes\n        _LT_TAGVAR(file_list_spec, $1)='${wl}-f,'\n\n        if test \"$GXX\" = yes; then\n          case $host_os in aix4.[[012]]|aix4.[[012]].*)\n          # We only want to do this on AIX 4.2 and lower, the check\n          # below for broken collect2 doesn't work under 4.3+\n\t  collect2name=`${CC} -print-prog-name=collect2`\n\t  if test -f \"$collect2name\" &&\n\t     strings \"$collect2name\" | $GREP resolve_lib_name >/dev/null\n\t  then\n\t    # We have reworked collect2\n\t    :\n\t  else\n\t    # We have old collect2\n\t    _LT_TAGVAR(hardcode_direct, $1)=unsupported\n\t    # It fails to find uninstalled libraries when the uninstalled\n\t    # path is not listed in the libpath.  Setting hardcode_minus_L\n\t    # to unsupported forces relinking\n\t    _LT_TAGVAR(hardcode_minus_L, $1)=yes\n\t    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'\n\t    _LT_TAGVAR(hardcode_libdir_separator, $1)=\n\t  fi\n          esac\n          shared_flag='-shared'\n\t  if test \"$aix_use_runtimelinking\" = yes; then\n\t    shared_flag=\"$shared_flag \"'${wl}-G'\n\t  fi\n        else\n          # not using gcc\n          if test \"$host_cpu\" = ia64; then\n\t  # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release\n\t  # chokes on -Wl,-G. The following line is correct:\n\t  shared_flag='-G'\n          else\n\t    if test \"$aix_use_runtimelinking\" = yes; then\n\t      shared_flag='${wl}-G'\n\t    else\n\t      shared_flag='${wl}-bM:SRE'\n\t    fi\n          fi\n        fi\n\n        _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall'\n        # It seems that -bexpall does not export symbols beginning with\n        # underscore (_), so it is better to generate a list of symbols to\n\t# export.\n        _LT_TAGVAR(always_export_symbols, $1)=yes\n        if test \"$aix_use_runtimelinking\" = yes; then\n          # Warning - without using the other runtime loading flags (-brtl),\n          # -berok will link without error, but may produce a broken library.\n          _LT_TAGVAR(allow_undefined_flag, $1)='-berok'\n          # Determine the default libpath from the value encoded in an empty\n          # executable.\n          _LT_SYS_MODULE_PATH_AIX\n          _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'\"$aix_libpath\"\n\n          _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '\"\\${wl}$no_entry_flag\"' $compiler_flags `if test \"x${allow_undefined_flag}\" != \"x\"; then func_echo_all \"${wl}${allow_undefined_flag}\"; else :; fi` '\"\\${wl}$exp_sym_flag:\\$export_symbols $shared_flag\"\n        else\n          if test \"$host_cpu\" = ia64; then\n\t    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib'\n\t    _LT_TAGVAR(allow_undefined_flag, $1)=\"-z nodefs\"\n\t    _LT_TAGVAR(archive_expsym_cmds, $1)=\"\\$CC $shared_flag\"' -o $output_objdir/$soname $libobjs $deplibs '\"\\${wl}$no_entry_flag\"' $compiler_flags ${wl}${allow_undefined_flag} '\"\\${wl}$exp_sym_flag:\\$export_symbols\"\n          else\n\t    # Determine the default libpath from the value encoded in an\n\t    # empty executable.\n\t    _LT_SYS_MODULE_PATH_AIX\n\t    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'\"$aix_libpath\"\n\t    # Warning - without using the other run time loading flags,\n\t    # -berok will link without error, but may produce a broken library.\n\t    _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok'\n\t    _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok'\n\t    if test \"$with_gnu_ld\" = yes; then\n\t      # We only use this code for GNU lds that support --whole-archive.\n\t      _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive'\n\t    else\n\t      # Exported symbols can be pulled into shared objects from archives\n\t      _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience'\n\t    fi\n\t    _LT_TAGVAR(archive_cmds_need_lc, $1)=yes\n\t    # This is similar to how AIX traditionally builds its shared\n\t    # libraries.\n\t    _LT_TAGVAR(archive_expsym_cmds, $1)=\"\\$CC $shared_flag\"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'\n          fi\n        fi\n        ;;\n\n      beos*)\n\tif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then\n\t  _LT_TAGVAR(allow_undefined_flag, $1)=unsupported\n\t  # Joseph Beckenbach <jrb3@best.com> says some releases of gcc\n\t  # support --undefined.  This deserves some investigation.  FIXME\n\t  _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'\n\telse\n\t  _LT_TAGVAR(ld_shlibs, $1)=no\n\tfi\n\t;;\n\n      chorus*)\n        case $cc_basename in\n          *)\n\t  # FIXME: insert proper C++ library support\n\t  _LT_TAGVAR(ld_shlibs, $1)=no\n\t  ;;\n        esac\n        ;;\n\n      cygwin* | mingw* | pw32* | cegcc*)\n        # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,\n        # as there is no search path for DLLs.\n        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'\n        _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols'\n        _LT_TAGVAR(allow_undefined_flag, $1)=unsupported\n        _LT_TAGVAR(always_export_symbols, $1)=no\n        _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes\n\n        if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then\n          _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'\n          # If the export-symbols file already is a .def file (1st line\n          # is EXPORTS), use it as is; otherwise, prepend...\n          _LT_TAGVAR(archive_expsym_cmds, $1)='if test \"x`$SED 1q $export_symbols`\" = xEXPORTS; then\n\t    cp $export_symbols $output_objdir/$soname.def;\n          else\n\t    echo EXPORTS > $output_objdir/$soname.def;\n\t    cat $export_symbols >> $output_objdir/$soname.def;\n          fi~\n          $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'\n        else\n          _LT_TAGVAR(ld_shlibs, $1)=no\n        fi\n        ;;\n      darwin* | rhapsody*)\n        _LT_DARWIN_LINKER_FEATURES($1)\n\t;;\n\n      dgux*)\n        case $cc_basename in\n          ec++*)\n\t    # FIXME: insert proper C++ library support\n\t    _LT_TAGVAR(ld_shlibs, $1)=no\n\t    ;;\n          ghcx*)\n\t    # Green Hills C++ Compiler\n\t    # FIXME: insert proper C++ library support\n\t    _LT_TAGVAR(ld_shlibs, $1)=no\n\t    ;;\n          *)\n\t    # FIXME: insert proper C++ library support\n\t    _LT_TAGVAR(ld_shlibs, $1)=no\n\t    ;;\n        esac\n        ;;\n\n      freebsd2.*)\n        # C++ shared libraries reported to be fairly broken before\n\t# switch to ELF\n        _LT_TAGVAR(ld_shlibs, $1)=no\n        ;;\n\n      freebsd-elf*)\n        _LT_TAGVAR(archive_cmds_need_lc, $1)=no\n        ;;\n\n      freebsd* | dragonfly*)\n        # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF\n        # conventions\n        _LT_TAGVAR(ld_shlibs, $1)=yes\n        ;;\n\n      gnu*)\n        ;;\n\n      haiku*)\n        _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'\n        _LT_TAGVAR(link_all_deplibs, $1)=yes\n        ;;\n\n      hpux9*)\n        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'\n        _LT_TAGVAR(hardcode_libdir_separator, $1)=:\n        _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'\n        _LT_TAGVAR(hardcode_direct, $1)=yes\n        _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,\n\t\t\t\t             # but as the default\n\t\t\t\t             # location of the library.\n\n        case $cc_basename in\n          CC*)\n            # FIXME: insert proper C++ library support\n            _LT_TAGVAR(ld_shlibs, $1)=no\n            ;;\n          aCC*)\n            _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'\n            # Commands to make compiler produce verbose output that lists\n            # what \"hidden\" libraries, object files and flags are used when\n            # linking a shared library.\n            #\n            # There doesn't appear to be a way to prevent this compiler from\n            # explicitly linking system object files so we need to strip them\n            # from the output so that they don't get included in the library\n            # dependencies.\n            output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP \"\\-L\"`; list=\"\"; for z in $templist; do case $z in conftest.$objext) list=\"$list $z\";; *.$objext);; *) list=\"$list $z\";;esac; done; func_echo_all \"$list\"'\n            ;;\n          *)\n            if test \"$GXX\" = yes; then\n              _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'\n            else\n              # FIXME: insert proper C++ library support\n              _LT_TAGVAR(ld_shlibs, $1)=no\n            fi\n            ;;\n        esac\n        ;;\n\n      hpux10*|hpux11*)\n        if test $with_gnu_ld = no; then\n\t  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'\n\t  _LT_TAGVAR(hardcode_libdir_separator, $1)=:\n\n          case $host_cpu in\n            hppa*64*|ia64*)\n              ;;\n            *)\n\t      _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'\n              ;;\n          esac\n        fi\n        case $host_cpu in\n          hppa*64*|ia64*)\n            _LT_TAGVAR(hardcode_direct, $1)=no\n            _LT_TAGVAR(hardcode_shlibpath_var, $1)=no\n            ;;\n          *)\n            _LT_TAGVAR(hardcode_direct, $1)=yes\n            _LT_TAGVAR(hardcode_direct_absolute, $1)=yes\n            _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,\n\t\t\t\t\t         # but as the default\n\t\t\t\t\t         # location of the library.\n            ;;\n        esac\n\n        case $cc_basename in\n          CC*)\n\t    # FIXME: insert proper C++ library support\n\t    _LT_TAGVAR(ld_shlibs, $1)=no\n\t    ;;\n          aCC*)\n\t    case $host_cpu in\n\t      hppa*64*)\n\t        _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'\n\t        ;;\n\t      ia64*)\n\t        _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'\n\t        ;;\n\t      *)\n\t        _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'\n\t        ;;\n\t    esac\n\t    # Commands to make compiler produce verbose output that lists\n\t    # what \"hidden\" libraries, object files and flags are used when\n\t    # linking a shared library.\n\t    #\n\t    # There doesn't appear to be a way to prevent this compiler from\n\t    # explicitly linking system object files so we need to strip them\n\t    # from the output so that they don't get included in the library\n\t    # dependencies.\n\t    output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP \"\\-L\"`; list=\"\"; for z in $templist; do case $z in conftest.$objext) list=\"$list $z\";; *.$objext);; *) list=\"$list $z\";;esac; done; func_echo_all \"$list\"'\n\t    ;;\n          *)\n\t    if test \"$GXX\" = yes; then\n\t      if test $with_gnu_ld = no; then\n\t        case $host_cpu in\n\t          hppa*64*)\n\t            _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'\n\t            ;;\n\t          ia64*)\n\t            _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'\n\t            ;;\n\t          *)\n\t            _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'\n\t            ;;\n\t        esac\n\t      fi\n\t    else\n\t      # FIXME: insert proper C++ library support\n\t      _LT_TAGVAR(ld_shlibs, $1)=no\n\t    fi\n\t    ;;\n        esac\n        ;;\n\n      interix[[3-9]]*)\n\t_LT_TAGVAR(hardcode_direct, $1)=no\n\t_LT_TAGVAR(hardcode_shlibpath_var, $1)=no\n\t_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'\n\t_LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'\n\t# Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.\n\t# Instead, shared libraries are loaded at an image base (0x10000000 by\n\t# default) and relocated if they conflict, which is a slow very memory\n\t# consuming and fragmenting process.  To avoid this, we pick a random,\n\t# 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link\n\t# time.  Moving up from 0x10000000 also allows more sbrk(2) space.\n\t_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \\* 262144 + 1342177280` -o $lib'\n\t_LT_TAGVAR(archive_expsym_cmds, $1)='sed \"s,^,_,\" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \\* 262144 + 1342177280` -o $lib'\n\t;;\n      irix5* | irix6*)\n        case $cc_basename in\n          CC*)\n\t    # SGI C++\n\t    _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n \"$verstring\" && func_echo_all \"-set_version $verstring\"` -update_registry ${output_objdir}/so_locations -o $lib'\n\n\t    # Archives containing C++ object files must be created using\n\t    # \"CC -ar\", where \"CC\" is the IRIX C++ compiler.  This is\n\t    # necessary to make sure instantiated templates are included\n\t    # in the archive.\n\t    _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs'\n\t    ;;\n          *)\n\t    if test \"$GXX\" = yes; then\n\t      if test \"$with_gnu_ld\" = no; then\n\t        _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n \"$verstring\" && func_echo_all \"${wl}-set_version ${wl}$verstring\"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'\n\t      else\n\t        _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n \"$verstring\" && func_echo_all \"${wl}-set_version ${wl}$verstring\"` -o $lib'\n\t      fi\n\t    fi\n\t    _LT_TAGVAR(link_all_deplibs, $1)=yes\n\t    ;;\n        esac\n        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'\n        _LT_TAGVAR(hardcode_libdir_separator, $1)=:\n        _LT_TAGVAR(inherit_rpath, $1)=yes\n        ;;\n\n      linux* | k*bsd*-gnu | kopensolaris*-gnu)\n        case $cc_basename in\n          KCC*)\n\t    # Kuck and Associates, Inc. (KAI) C++ Compiler\n\n\t    # KCC will only create a shared library if the output file\n\t    # ends with \".so\" (or \".sl\" for HP-UX), so rename the library\n\t    # to its proper name (with version) after linking.\n\t    _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\\''s/\\([[^()0-9A-Za-z{}]]\\)/\\\\\\\\\\1/g'\\''`; templib=`echo $lib | $SED -e \"s/\\${tempext}\\..*/.so/\"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \\$templib; mv \\$templib $lib'\n\t    _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\\''s/\\([[^()0-9A-Za-z{}]]\\)/\\\\\\\\\\1/g'\\''`; templib=`echo $lib | $SED -e \"s/\\${tempext}\\..*/.so/\"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \\$templib ${wl}-retain-symbols-file,$export_symbols; mv \\$templib $lib'\n\t    # Commands to make compiler produce verbose output that lists\n\t    # what \"hidden\" libraries, object files and flags are used when\n\t    # linking a shared library.\n\t    #\n\t    # There doesn't appear to be a way to prevent this compiler from\n\t    # explicitly linking system object files so we need to strip them\n\t    # from the output so that they don't get included in the library\n\t    # dependencies.\n\t    output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP \"ld\"`; rm -f libconftest$shared_ext; list=\"\"; for z in $templist; do case $z in conftest.$objext) list=\"$list $z\";; *.$objext);; *) list=\"$list $z\";;esac; done; func_echo_all \"$list\"'\n\n\t    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'\n\t    _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'\n\n\t    # Archives containing C++ object files must be created using\n\t    # \"CC -Bstatic\", where \"CC\" is the KAI C++ compiler.\n\t    _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs'\n\t    ;;\n\t  icpc* | ecpc* )\n\t    # Intel C++\n\t    with_gnu_ld=yes\n\t    # version 8.0 and above of icpc choke on multiply defined symbols\n\t    # if we add $predep_objects and $postdep_objects, however 7.1 and\n\t    # earlier do not add the objects themselves.\n\t    case `$CC -V 2>&1` in\n\t      *\"Version 7.\"*)\n\t        _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'\n\t\t_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'\n\t\t;;\n\t      *)  # Version 8.0 or newer\n\t        tmp_idyn=\n\t        case $host_cpu in\n\t\t  ia64*) tmp_idyn=' -i_dynamic';;\n\t\tesac\n\t        _LT_TAGVAR(archive_cmds, $1)='$CC -shared'\"$tmp_idyn\"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'\n\t\t_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'\"$tmp_idyn\"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'\n\t\t;;\n\t    esac\n\t    _LT_TAGVAR(archive_cmds_need_lc, $1)=no\n\t    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'\n\t    _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'\n\t    _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive'\n\t    ;;\n          pgCC* | pgcpp*)\n            # Portland Group C++ compiler\n\t    case `$CC -V` in\n\t    *pgCC\\ [[1-5]].* | *pgcpp\\ [[1-5]].*)\n\t      _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~\n\t\trm -rf $tpldir~\n\t\t$CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~\n\t\tcompile_command=\"$compile_command `find $tpldir -name \\*.o | sort | $NL2SP`\"'\n\t      _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~\n\t\trm -rf $tpldir~\n\t\t$CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~\n\t\t$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \\*.o | sort | $NL2SP`~\n\t\t$RANLIB $oldlib'\n\t      _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~\n\t\trm -rf $tpldir~\n\t\t$CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~\n\t\t$CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \\*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'\n\t      _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~\n\t\trm -rf $tpldir~\n\t\t$CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~\n\t\t$CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \\*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'\n\t      ;;\n\t    *) # Version 6 and above use weak symbols\n\t      _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'\n\t      _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'\n\t      ;;\n\t    esac\n\n\t    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir'\n\t    _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'\n\t    _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\\\"\\\"; do test  -n \\\"$conv\\\" && new_convenience=\\\"$new_convenience,$conv\\\"; done; func_echo_all \\\"$new_convenience\\\"` ${wl}--no-whole-archive'\n            ;;\n\t  cxx*)\n\t    # Compaq C++\n\t    _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'\n\t    _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname  -o $lib ${wl}-retain-symbols-file $wl$export_symbols'\n\n\t    runpath_var=LD_RUN_PATH\n\t    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'\n\t    _LT_TAGVAR(hardcode_libdir_separator, $1)=:\n\n\t    # Commands to make compiler produce verbose output that lists\n\t    # what \"hidden\" libraries, object files and flags are used when\n\t    # linking a shared library.\n\t    #\n\t    # There doesn't appear to be a way to prevent this compiler from\n\t    # explicitly linking system object files so we need to strip them\n\t    # from the output so that they don't get included in the library\n\t    # dependencies.\n\t    output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP \"ld\"`; templist=`func_echo_all \"$templist\" | $SED \"s/\\(^.*ld.*\\)\\( .*ld .*$\\)/\\1/\"`; list=\"\"; for z in $templist; do case $z in conftest.$objext) list=\"$list $z\";; *.$objext);; *) list=\"$list $z\";;esac; done; func_echo_all \"X$list\" | $Xsed'\n\t    ;;\n\t  xl* | mpixl* | bgxl*)\n\t    # IBM XL 8.0 on PPC, with GNU ld\n\t    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'\n\t    _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'\n\t    _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'\n\t    if test \"x$supports_anon_versioning\" = xyes; then\n\t      _LT_TAGVAR(archive_expsym_cmds, $1)='echo \"{ global:\" > $output_objdir/$libname.ver~\n\t\tcat $export_symbols | sed -e \"s/\\(.*\\)/\\1;/\" >> $output_objdir/$libname.ver~\n\t\techo \"local: *; };\" >> $output_objdir/$libname.ver~\n\t\t$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'\n\t    fi\n\t    ;;\n\t  *)\n\t    case `$CC -V 2>&1 | sed 5q` in\n\t    *Sun\\ C*)\n\t      # Sun C++ 5.9\n\t      _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs'\n\t      _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'\n\t      _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols'\n\t      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'\n\t      _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\\\"\\\"; do test -z \\\"$conv\\\" || new_convenience=\\\"$new_convenience,$conv\\\"; done; func_echo_all \\\"$new_convenience\\\"` ${wl}--no-whole-archive'\n\t      _LT_TAGVAR(compiler_needs_object, $1)=yes\n\n\t      # Not sure whether something based on\n\t      # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1\n\t      # would be better.\n\t      output_verbose_link_cmd='func_echo_all'\n\n\t      # Archives containing C++ object files must be created using\n\t      # \"CC -xar\", where \"CC\" is the Sun C++ compiler.  This is\n\t      # necessary to make sure instantiated templates are included\n\t      # in the archive.\n\t      _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'\n\t      ;;\n\t    esac\n\t    ;;\n\tesac\n\t;;\n\n      lynxos*)\n        # FIXME: insert proper C++ library support\n\t_LT_TAGVAR(ld_shlibs, $1)=no\n\t;;\n\n      m88k*)\n        # FIXME: insert proper C++ library support\n        _LT_TAGVAR(ld_shlibs, $1)=no\n\t;;\n\n      mvs*)\n        case $cc_basename in\n          cxx*)\n\t    # FIXME: insert proper C++ library support\n\t    _LT_TAGVAR(ld_shlibs, $1)=no\n\t    ;;\n\t  *)\n\t    # FIXME: insert proper C++ library support\n\t    _LT_TAGVAR(ld_shlibs, $1)=no\n\t    ;;\n\tesac\n\t;;\n\n      netbsd*)\n        if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then\n\t  _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable  -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags'\n\t  wlarc=\n\t  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'\n\t  _LT_TAGVAR(hardcode_direct, $1)=yes\n\t  _LT_TAGVAR(hardcode_shlibpath_var, $1)=no\n\tfi\n\t# Workaround some broken pre-1.5 toolchains\n\toutput_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e \"s:-lgcc -lc -lgcc::\"'\n\t;;\n\n      *nto* | *qnx*)\n        _LT_TAGVAR(ld_shlibs, $1)=yes\n\t;;\n\n      openbsd2*)\n        # C++ shared libraries are fairly broken\n\t_LT_TAGVAR(ld_shlibs, $1)=no\n\t;;\n\n      openbsd*)\n\tif test -f /usr/libexec/ld.so; then\n\t  _LT_TAGVAR(hardcode_direct, $1)=yes\n\t  _LT_TAGVAR(hardcode_shlibpath_var, $1)=no\n\t  _LT_TAGVAR(hardcode_direct_absolute, $1)=yes\n\t  _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'\n\t  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'\n\t  if test -z \"`echo __ELF__ | $CC -E - | grep __ELF__`\" || test \"$host_os-$host_cpu\" = \"openbsd2.8-powerpc\"; then\n\t    _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib'\n\t    _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'\n\t    _LT_TAGVAR(whole_archive_flag_spec, $1)=\"$wlarc\"'--whole-archive$convenience '\"$wlarc\"'--no-whole-archive'\n\t  fi\n\t  output_verbose_link_cmd=func_echo_all\n\telse\n\t  _LT_TAGVAR(ld_shlibs, $1)=no\n\tfi\n\t;;\n\n      osf3* | osf4* | osf5*)\n        case $cc_basename in\n          KCC*)\n\t    # Kuck and Associates, Inc. (KAI) C++ Compiler\n\n\t    # KCC will only create a shared library if the output file\n\t    # ends with \".so\" (or \".sl\" for HP-UX), so rename the library\n\t    # to its proper name (with version) after linking.\n\t    _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\\''s/\\([[^()0-9A-Za-z{}]]\\)/\\\\\\\\\\1/g'\\''`; templib=`echo \"$lib\" | $SED -e \"s/\\${tempext}\\..*/.so/\"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \\$templib; mv \\$templib $lib'\n\n\t    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'\n\t    _LT_TAGVAR(hardcode_libdir_separator, $1)=:\n\n\t    # Archives containing C++ object files must be created using\n\t    # the KAI C++ compiler.\n\t    case $host in\n\t      osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;;\n\t      *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;;\n\t    esac\n\t    ;;\n          RCC*)\n\t    # Rational C++ 2.4.1\n\t    # FIXME: insert proper C++ library support\n\t    _LT_TAGVAR(ld_shlibs, $1)=no\n\t    ;;\n          cxx*)\n\t    case $host in\n\t      osf3*)\n\t        _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\\*'\n\t        _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n \"$verstring\" && func_echo_all \"${wl}-set_version $verstring\"` -update_registry ${output_objdir}/so_locations -o $lib'\n\t        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'\n\t\t;;\n\t      *)\n\t        _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \\*'\n\t        _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n \"$verstring\" && func_echo_all \"-set_version $verstring\"` -update_registry ${output_objdir}/so_locations -o $lib'\n\t        _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf \"%s %s\\\\n\" -exported_symbol \"\\$i\" >> $lib.exp; done~\n\t          echo \"-hidden\">> $lib.exp~\n\t          $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp  `test -n \"$verstring\" && $ECHO \"-set_version $verstring\"` -update_registry ${output_objdir}/so_locations -o $lib~\n\t          $RM $lib.exp'\n\t        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'\n\t\t;;\n\t    esac\n\n\t    _LT_TAGVAR(hardcode_libdir_separator, $1)=:\n\n\t    # Commands to make compiler produce verbose output that lists\n\t    # what \"hidden\" libraries, object files and flags are used when\n\t    # linking a shared library.\n\t    #\n\t    # There doesn't appear to be a way to prevent this compiler from\n\t    # explicitly linking system object files so we need to strip them\n\t    # from the output so that they don't get included in the library\n\t    # dependencies.\n\t    output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP \"ld\" | $GREP -v \"ld:\"`; templist=`func_echo_all \"$templist\" | $SED \"s/\\(^.*ld.*\\)\\( .*ld.*$\\)/\\1/\"`; list=\"\"; for z in $templist; do case $z in conftest.$objext) list=\"$list $z\";; *.$objext);; *) list=\"$list $z\";;esac; done; func_echo_all \"$list\"'\n\t    ;;\n\t  *)\n\t    if test \"$GXX\" = yes && test \"$with_gnu_ld\" = no; then\n\t      _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\\*'\n\t      case $host in\n\t        osf3*)\n\t          _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n \"$verstring\" && func_echo_all \"${wl}-set_version ${wl}$verstring\"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'\n\t\t  ;;\n\t        *)\n\t          _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n \"$verstring\" && func_echo_all \"${wl}-set_version ${wl}$verstring\"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'\n\t\t  ;;\n\t      esac\n\n\t      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'\n\t      _LT_TAGVAR(hardcode_libdir_separator, $1)=:\n\n\t      # Commands to make compiler produce verbose output that lists\n\t      # what \"hidden\" libraries, object files and flags are used when\n\t      # linking a shared library.\n\t      output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v \"^Configured with:\" | $GREP \"\\-L\"'\n\n\t    else\n\t      # FIXME: insert proper C++ library support\n\t      _LT_TAGVAR(ld_shlibs, $1)=no\n\t    fi\n\t    ;;\n        esac\n        ;;\n\n      psos*)\n        # FIXME: insert proper C++ library support\n        _LT_TAGVAR(ld_shlibs, $1)=no\n        ;;\n\n      sunos4*)\n        case $cc_basename in\n          CC*)\n\t    # Sun C++ 4.x\n\t    # FIXME: insert proper C++ library support\n\t    _LT_TAGVAR(ld_shlibs, $1)=no\n\t    ;;\n          lcc*)\n\t    # Lucid\n\t    # FIXME: insert proper C++ library support\n\t    _LT_TAGVAR(ld_shlibs, $1)=no\n\t    ;;\n          *)\n\t    # FIXME: insert proper C++ library support\n\t    _LT_TAGVAR(ld_shlibs, $1)=no\n\t    ;;\n        esac\n        ;;\n\n      solaris*)\n        case $cc_basename in\n          CC*)\n\t    # Sun C++ 4.2, 5.x and Centerline C++\n            _LT_TAGVAR(archive_cmds_need_lc,$1)=yes\n\t    _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs'\n\t    _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag}  -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'\n\t    _LT_TAGVAR(archive_expsym_cmds, $1)='echo \"{ global:\" > $lib.exp~cat $export_symbols | $SED -e \"s/\\(.*\\)/\\1;/\" >> $lib.exp~echo \"local: *; };\" >> $lib.exp~\n\t      $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'\n\n\t    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'\n\t    _LT_TAGVAR(hardcode_shlibpath_var, $1)=no\n\t    case $host_os in\n\t      solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;\n\t      *)\n\t\t# The compiler driver will combine and reorder linker options,\n\t\t# but understands `-z linker_flag'.\n\t        # Supported since Solaris 2.6 (maybe 2.5.1?)\n\t\t_LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract'\n\t        ;;\n\t    esac\n\t    _LT_TAGVAR(link_all_deplibs, $1)=yes\n\n\t    output_verbose_link_cmd='func_echo_all'\n\n\t    # Archives containing C++ object files must be created using\n\t    # \"CC -xar\", where \"CC\" is the Sun C++ compiler.  This is\n\t    # necessary to make sure instantiated templates are included\n\t    # in the archive.\n\t    _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'\n\t    ;;\n          gcx*)\n\t    # Green Hills C++ Compiler\n\t    _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'\n\n\t    # The C++ compiler must be used to create the archive.\n\t    _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs'\n\t    ;;\n          *)\n\t    # GNU C++ compiler with Solaris linker\n\t    if test \"$GXX\" = yes && test \"$with_gnu_ld\" = no; then\n\t      _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs'\n\t      if $CC --version | $GREP -v '^2\\.7' > /dev/null; then\n\t        _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'\n\t        _LT_TAGVAR(archive_expsym_cmds, $1)='echo \"{ global:\" > $lib.exp~cat $export_symbols | $SED -e \"s/\\(.*\\)/\\1;/\" >> $lib.exp~echo \"local: *; };\" >> $lib.exp~\n\t\t  $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'\n\n\t        # Commands to make compiler produce verbose output that lists\n\t        # what \"hidden\" libraries, object files and flags are used when\n\t        # linking a shared library.\n\t        output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v \"^Configured with:\" | $GREP \"\\-L\"'\n\t      else\n\t        # g++ 2.7 appears to require `-G' NOT `-shared' on this\n\t        # platform.\n\t        _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'\n\t        _LT_TAGVAR(archive_expsym_cmds, $1)='echo \"{ global:\" > $lib.exp~cat $export_symbols | $SED -e \"s/\\(.*\\)/\\1;/\" >> $lib.exp~echo \"local: *; };\" >> $lib.exp~\n\t\t  $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'\n\n\t        # Commands to make compiler produce verbose output that lists\n\t        # what \"hidden\" libraries, object files and flags are used when\n\t        # linking a shared library.\n\t        output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v \"^Configured with:\" | $GREP \"\\-L\"'\n\t      fi\n\n\t      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir'\n\t      case $host_os in\n\t\tsolaris2.[[0-5]] | solaris2.[[0-5]].*) ;;\n\t\t*)\n\t\t  _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'\n\t\t  ;;\n\t      esac\n\t    fi\n\t    ;;\n        esac\n        ;;\n\n    sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)\n      _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'\n      _LT_TAGVAR(archive_cmds_need_lc, $1)=no\n      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no\n      runpath_var='LD_RUN_PATH'\n\n      case $cc_basename in\n        CC*)\n\t  _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'\n\t  _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'\n\t  ;;\n\t*)\n\t  _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'\n\t  _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'\n\t  ;;\n      esac\n      ;;\n\n      sysv5* | sco3.2v5* | sco5v6*)\n\t# Note: We can NOT use -z defs as we might desire, because we do not\n\t# link with -lc, and that would cause any symbols used from libc to\n\t# always be unresolved, which means just about no library would\n\t# ever link correctly.  If we're not using GNU ld we use -z text\n\t# though, which does catch some bad symbols but isn't as heavy-handed\n\t# as -z defs.\n\t_LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'\n\t_LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs'\n\t_LT_TAGVAR(archive_cmds_need_lc, $1)=no\n\t_LT_TAGVAR(hardcode_shlibpath_var, $1)=no\n\t_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir'\n\t_LT_TAGVAR(hardcode_libdir_separator, $1)=':'\n\t_LT_TAGVAR(link_all_deplibs, $1)=yes\n\t_LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport'\n\trunpath_var='LD_RUN_PATH'\n\n\tcase $cc_basename in\n          CC*)\n\t    _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'\n\t    _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'\n\t    _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~\n\t      '\"$_LT_TAGVAR(old_archive_cmds, $1)\"\n\t    _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~\n\t      '\"$_LT_TAGVAR(reload_cmds, $1)\"\n\t    ;;\n\t  *)\n\t    _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'\n\t    _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'\n\t    ;;\n\tesac\n      ;;\n\n      tandem*)\n        case $cc_basename in\n          NCC*)\n\t    # NonStop-UX NCC 3.20\n\t    # FIXME: insert proper C++ library support\n\t    _LT_TAGVAR(ld_shlibs, $1)=no\n\t    ;;\n          *)\n\t    # FIXME: insert proper C++ library support\n\t    _LT_TAGVAR(ld_shlibs, $1)=no\n\t    ;;\n        esac\n        ;;\n\n      vxworks*)\n        # For VxWorks ports, we assume the use of a GNU linker with\n        # standard elf conventions.\n        _LT_TAGVAR(ld_shlibs, $1)=yes\n        ;;\n\n      *)\n        # FIXME: insert proper C++ library support\n        _LT_TAGVAR(ld_shlibs, $1)=no\n        ;;\n    esac\n\n    AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)])\n    test \"$_LT_TAGVAR(ld_shlibs, $1)\" = no && can_build_shared=no\n\n    _LT_TAGVAR(GCC, $1)=\"$GXX\"\n    _LT_TAGVAR(LD, $1)=\"$LD\"\n\n    ## CAVEAT EMPTOR:\n    ## There is no encapsulation within the following macros, do not change\n    ## the running order or otherwise move them around unless you know exactly\n    ## what you are doing...\n    _LT_SYS_HIDDEN_LIBDEPS($1)\n    _LT_COMPILER_PIC($1)\n    _LT_COMPILER_C_O($1)\n    _LT_COMPILER_FILE_LOCKS($1)\n    _LT_LINKER_SHLIBS($1)\n    _LT_SYS_DYNAMIC_LINKER($1)\n    _LT_LINKER_HARDCODE_LIBPATH($1)\n\n    _LT_CONFIG($1)\n  fi # test -n \"$compiler\"\n\n  CC=$lt_save_CC\n  LDCXX=$LD\n  LD=$lt_save_LD\n  GCC=$lt_save_GCC\n  with_gnu_ld=$lt_save_with_gnu_ld\n  lt_cv_path_LDCXX=$lt_cv_path_LD\n  lt_cv_path_LD=$lt_save_path_LD\n  lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld\n  lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld\nfi # test \"$_lt_caught_CXX_error\" != yes\n\nAC_LANG_POP\n])# _LT_LANG_CXX_CONFIG\n\n# _LT_SYS_HIDDEN_LIBDEPS([TAGNAME])\n# ---------------------------------\n# Figure out \"hidden\" library dependencies from verbose\n# compiler output when linking a shared library.\n# Parse the compiler output and extract the necessary\n# objects, libraries and library flags.\nm4_defun([_LT_SYS_HIDDEN_LIBDEPS],\n[m4_require([_LT_FILEUTILS_DEFAULTS])dnl\n# Dependencies to place before and after the object being linked:\n_LT_TAGVAR(predep_objects, $1)=\n_LT_TAGVAR(postdep_objects, $1)=\n_LT_TAGVAR(predeps, $1)=\n_LT_TAGVAR(postdeps, $1)=\n_LT_TAGVAR(compiler_lib_search_path, $1)=\n\ndnl we can't use the lt_simple_compile_test_code here,\ndnl because it contains code intended for an executable,\ndnl not a library.  It's possible we should let each\ndnl tag define a new lt_????_link_test_code variable,\ndnl but it's only used here...\nm4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF\nint a;\nvoid foo (void) { a = 0; }\n_LT_EOF\n], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF\nclass Foo\n{\npublic:\n  Foo (void) { a = 0; }\nprivate:\n  int a;\n};\n_LT_EOF\n], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF\n      subroutine foo\n      implicit none\n      integer*4 a\n      a=0\n      return\n      end\n_LT_EOF\n], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF\n      subroutine foo\n      implicit none\n      integer a\n      a=0\n      return\n      end\n_LT_EOF\n], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF\npublic class foo {\n  private int a;\n  public void bar (void) {\n    a = 0;\n  }\n};\n_LT_EOF\n])\ndnl Parse the compiler output and extract the necessary\ndnl objects, libraries and library flags.\nif AC_TRY_EVAL(ac_compile); then\n  # Parse the compiler output and extract the necessary\n  # objects, libraries and library flags.\n\n  # Sentinel used to keep track of whether or not we are before\n  # the conftest object file.\n  pre_test_object_deps_done=no\n\n  for p in `eval \"$output_verbose_link_cmd\"`; do\n    case $p in\n\n    -L* | -R* | -l*)\n       # Some compilers place space between \"-{L,R}\" and the path.\n       # Remove the space.\n       if test $p = \"-L\" ||\n          test $p = \"-R\"; then\n\t prev=$p\n\t continue\n       else\n\t prev=\n       fi\n\n       if test \"$pre_test_object_deps_done\" = no; then\n\t case $p in\n\t -L* | -R*)\n\t   # Internal compiler library paths should come after those\n\t   # provided the user.  The postdeps already come after the\n\t   # user supplied libs so there is no need to process them.\n\t   if test -z \"$_LT_TAGVAR(compiler_lib_search_path, $1)\"; then\n\t     _LT_TAGVAR(compiler_lib_search_path, $1)=\"${prev}${p}\"\n\t   else\n\t     _LT_TAGVAR(compiler_lib_search_path, $1)=\"${_LT_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}\"\n\t   fi\n\t   ;;\n\t # The \"-l\" case would never come before the object being\n\t # linked, so don't bother handling this case.\n\t esac\n       else\n\t if test -z \"$_LT_TAGVAR(postdeps, $1)\"; then\n\t   _LT_TAGVAR(postdeps, $1)=\"${prev}${p}\"\n\t else\n\t   _LT_TAGVAR(postdeps, $1)=\"${_LT_TAGVAR(postdeps, $1)} ${prev}${p}\"\n\t fi\n       fi\n       ;;\n\n    *.$objext)\n       # This assumes that the test object file only shows up\n       # once in the compiler output.\n       if test \"$p\" = \"conftest.$objext\"; then\n\t pre_test_object_deps_done=yes\n\t continue\n       fi\n\n       if test \"$pre_test_object_deps_done\" = no; then\n\t if test -z \"$_LT_TAGVAR(predep_objects, $1)\"; then\n\t   _LT_TAGVAR(predep_objects, $1)=\"$p\"\n\t else\n\t   _LT_TAGVAR(predep_objects, $1)=\"$_LT_TAGVAR(predep_objects, $1) $p\"\n\t fi\n       else\n\t if test -z \"$_LT_TAGVAR(postdep_objects, $1)\"; then\n\t   _LT_TAGVAR(postdep_objects, $1)=\"$p\"\n\t else\n\t   _LT_TAGVAR(postdep_objects, $1)=\"$_LT_TAGVAR(postdep_objects, $1) $p\"\n\t fi\n       fi\n       ;;\n\n    *) ;; # Ignore the rest.\n\n    esac\n  done\n\n  # Clean up.\n  rm -f a.out a.exe\nelse\n  echo \"libtool.m4: error: problem compiling $1 test program\"\nfi\n\n$RM -f confest.$objext\n\n# PORTME: override above test on systems where it is broken\nm4_if([$1], [CXX],\n[case $host_os in\ninterix[[3-9]]*)\n  # Interix 3.5 installs completely hosed .la files for C++, so rather than\n  # hack all around it, let's just trust \"g++\" to DTRT.\n  _LT_TAGVAR(predep_objects,$1)=\n  _LT_TAGVAR(postdep_objects,$1)=\n  _LT_TAGVAR(postdeps,$1)=\n  ;;\n\nlinux*)\n  case `$CC -V 2>&1 | sed 5q` in\n  *Sun\\ C*)\n    # Sun C++ 5.9\n\n    # The more standards-conforming stlport4 library is\n    # incompatible with the Cstd library. Avoid specifying\n    # it if it's in CXXFLAGS. Ignore libCrun as\n    # -library=stlport4 depends on it.\n    case \" $CXX $CXXFLAGS \" in\n    *\" -library=stlport4 \"*)\n      solaris_use_stlport4=yes\n      ;;\n    esac\n\n    if test \"$solaris_use_stlport4\" != yes; then\n      _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun'\n    fi\n    ;;\n  esac\n  ;;\n\nsolaris*)\n  case $cc_basename in\n  CC*)\n    # The more standards-conforming stlport4 library is\n    # incompatible with the Cstd library. Avoid specifying\n    # it if it's in CXXFLAGS. Ignore libCrun as\n    # -library=stlport4 depends on it.\n    case \" $CXX $CXXFLAGS \" in\n    *\" -library=stlport4 \"*)\n      solaris_use_stlport4=yes\n      ;;\n    esac\n\n    # Adding this requires a known-good setup of shared libraries for\n    # Sun compiler versions before 5.6, else PIC objects from an old\n    # archive will be linked into the output, leading to subtle bugs.\n    if test \"$solaris_use_stlport4\" != yes; then\n      _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun'\n    fi\n    ;;\n  esac\n  ;;\nesac\n])\n\ncase \" $_LT_TAGVAR(postdeps, $1) \" in\n*\" -lc \"*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;;\nesac\n _LT_TAGVAR(compiler_lib_search_dirs, $1)=\nif test -n \"${_LT_TAGVAR(compiler_lib_search_path, $1)}\"; then\n _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo \" ${_LT_TAGVAR(compiler_lib_search_path, $1)}\" | ${SED} -e 's! -L! !g' -e 's!^ !!'`\nfi\n_LT_TAGDECL([], [compiler_lib_search_dirs], [1],\n    [The directories searched by this compiler when creating a shared library])\n_LT_TAGDECL([], [predep_objects], [1],\n    [Dependencies to place before and after the objects being linked to\n    create a shared library])\n_LT_TAGDECL([], [postdep_objects], [1])\n_LT_TAGDECL([], [predeps], [1])\n_LT_TAGDECL([], [postdeps], [1])\n_LT_TAGDECL([], [compiler_lib_search_path], [1],\n    [The library search path used internally by the compiler when linking\n    a shared library])\n])# _LT_SYS_HIDDEN_LIBDEPS\n\n\n# _LT_LANG_F77_CONFIG([TAG])\n# --------------------------\n# Ensure that the configuration variables for a Fortran 77 compiler are\n# suitably defined.  These variables are subsequently used by _LT_CONFIG\n# to write the compiler configuration to `libtool'.\nm4_defun([_LT_LANG_F77_CONFIG],\n[AC_LANG_PUSH(Fortran 77)\nif test -z \"$F77\" || test \"X$F77\" = \"Xno\"; then\n  _lt_disable_F77=yes\nfi\n\n_LT_TAGVAR(archive_cmds_need_lc, $1)=no\n_LT_TAGVAR(allow_undefined_flag, $1)=\n_LT_TAGVAR(always_export_symbols, $1)=no\n_LT_TAGVAR(archive_expsym_cmds, $1)=\n_LT_TAGVAR(export_dynamic_flag_spec, $1)=\n_LT_TAGVAR(hardcode_direct, $1)=no\n_LT_TAGVAR(hardcode_direct_absolute, $1)=no\n_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=\n_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=\n_LT_TAGVAR(hardcode_libdir_separator, $1)=\n_LT_TAGVAR(hardcode_minus_L, $1)=no\n_LT_TAGVAR(hardcode_automatic, $1)=no\n_LT_TAGVAR(inherit_rpath, $1)=no\n_LT_TAGVAR(module_cmds, $1)=\n_LT_TAGVAR(module_expsym_cmds, $1)=\n_LT_TAGVAR(link_all_deplibs, $1)=unknown\n_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds\n_LT_TAGVAR(reload_flag, $1)=$reload_flag\n_LT_TAGVAR(reload_cmds, $1)=$reload_cmds\n_LT_TAGVAR(no_undefined_flag, $1)=\n_LT_TAGVAR(whole_archive_flag_spec, $1)=\n_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no\n\n# Source file extension for f77 test sources.\nac_ext=f\n\n# Object file extension for compiled f77 test sources.\nobjext=o\n_LT_TAGVAR(objext, $1)=$objext\n\n# No sense in running all these tests if we already determined that\n# the F77 compiler isn't working.  Some variables (like enable_shared)\n# are currently assumed to apply to all compilers on this platform,\n# and will be corrupted by setting them based on a non-working compiler.\nif test \"$_lt_disable_F77\" != yes; then\n  # Code to be used in simple compile tests\n  lt_simple_compile_test_code=\"\\\n      subroutine t\n      return\n      end\n\"\n\n  # Code to be used in simple link tests\n  lt_simple_link_test_code=\"\\\n      program t\n      end\n\"\n\n  # ltmain only uses $CC for tagged configurations so make sure $CC is set.\n  _LT_TAG_COMPILER\n\n  # save warnings/boilerplate of simple test code\n  _LT_COMPILER_BOILERPLATE\n  _LT_LINKER_BOILERPLATE\n\n  # Allow CC to be a program name with arguments.\n  lt_save_CC=\"$CC\"\n  lt_save_GCC=$GCC\n  CC=${F77-\"f77\"}\n  compiler=$CC\n  _LT_TAGVAR(compiler, $1)=$CC\n  _LT_CC_BASENAME([$compiler])\n  GCC=$G77\n  if test -n \"$compiler\"; then\n    AC_MSG_CHECKING([if libtool supports shared libraries])\n    AC_MSG_RESULT([$can_build_shared])\n\n    AC_MSG_CHECKING([whether to build shared libraries])\n    test \"$can_build_shared\" = \"no\" && enable_shared=no\n\n    # On AIX, shared libraries and static libraries use the same namespace, and\n    # are all built from PIC.\n    case $host_os in\n      aix3*)\n        test \"$enable_shared\" = yes && enable_static=no\n        if test -n \"$RANLIB\"; then\n          archive_cmds=\"$archive_cmds~\\$RANLIB \\$lib\"\n          postinstall_cmds='$RANLIB $lib'\n        fi\n        ;;\n      aix[[4-9]]*)\n\tif test \"$host_cpu\" != ia64 && test \"$aix_use_runtimelinking\" = no ; then\n\t  test \"$enable_shared\" = yes && enable_static=no\n\tfi\n        ;;\n    esac\n    AC_MSG_RESULT([$enable_shared])\n\n    AC_MSG_CHECKING([whether to build static libraries])\n    # Make sure either enable_shared or enable_static is yes.\n    test \"$enable_shared\" = yes || enable_static=yes\n    AC_MSG_RESULT([$enable_static])\n\n    _LT_TAGVAR(GCC, $1)=\"$G77\"\n    _LT_TAGVAR(LD, $1)=\"$LD\"\n\n    ## CAVEAT EMPTOR:\n    ## There is no encapsulation within the following macros, do not change\n    ## the running order or otherwise move them around unless you know exactly\n    ## what you are doing...\n    _LT_COMPILER_PIC($1)\n    _LT_COMPILER_C_O($1)\n    _LT_COMPILER_FILE_LOCKS($1)\n    _LT_LINKER_SHLIBS($1)\n    _LT_SYS_DYNAMIC_LINKER($1)\n    _LT_LINKER_HARDCODE_LIBPATH($1)\n\n    _LT_CONFIG($1)\n  fi # test -n \"$compiler\"\n\n  GCC=$lt_save_GCC\n  CC=\"$lt_save_CC\"\nfi # test \"$_lt_disable_F77\" != yes\n\nAC_LANG_POP\n])# _LT_LANG_F77_CONFIG\n\n\n# _LT_LANG_FC_CONFIG([TAG])\n# -------------------------\n# Ensure that the configuration variables for a Fortran compiler are\n# suitably defined.  These variables are subsequently used by _LT_CONFIG\n# to write the compiler configuration to `libtool'.\nm4_defun([_LT_LANG_FC_CONFIG],\n[AC_LANG_PUSH(Fortran)\n\nif test -z \"$FC\" || test \"X$FC\" = \"Xno\"; then\n  _lt_disable_FC=yes\nfi\n\n_LT_TAGVAR(archive_cmds_need_lc, $1)=no\n_LT_TAGVAR(allow_undefined_flag, $1)=\n_LT_TAGVAR(always_export_symbols, $1)=no\n_LT_TAGVAR(archive_expsym_cmds, $1)=\n_LT_TAGVAR(export_dynamic_flag_spec, $1)=\n_LT_TAGVAR(hardcode_direct, $1)=no\n_LT_TAGVAR(hardcode_direct_absolute, $1)=no\n_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=\n_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=\n_LT_TAGVAR(hardcode_libdir_separator, $1)=\n_LT_TAGVAR(hardcode_minus_L, $1)=no\n_LT_TAGVAR(hardcode_automatic, $1)=no\n_LT_TAGVAR(inherit_rpath, $1)=no\n_LT_TAGVAR(module_cmds, $1)=\n_LT_TAGVAR(module_expsym_cmds, $1)=\n_LT_TAGVAR(link_all_deplibs, $1)=unknown\n_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds\n_LT_TAGVAR(reload_flag, $1)=$reload_flag\n_LT_TAGVAR(reload_cmds, $1)=$reload_cmds\n_LT_TAGVAR(no_undefined_flag, $1)=\n_LT_TAGVAR(whole_archive_flag_spec, $1)=\n_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no\n\n# Source file extension for fc test sources.\nac_ext=${ac_fc_srcext-f}\n\n# Object file extension for compiled fc test sources.\nobjext=o\n_LT_TAGVAR(objext, $1)=$objext\n\n# No sense in running all these tests if we already determined that\n# the FC compiler isn't working.  Some variables (like enable_shared)\n# are currently assumed to apply to all compilers on this platform,\n# and will be corrupted by setting them based on a non-working compiler.\nif test \"$_lt_disable_FC\" != yes; then\n  # Code to be used in simple compile tests\n  lt_simple_compile_test_code=\"\\\n      subroutine t\n      return\n      end\n\"\n\n  # Code to be used in simple link tests\n  lt_simple_link_test_code=\"\\\n      program t\n      end\n\"\n\n  # ltmain only uses $CC for tagged configurations so make sure $CC is set.\n  _LT_TAG_COMPILER\n\n  # save warnings/boilerplate of simple test code\n  _LT_COMPILER_BOILERPLATE\n  _LT_LINKER_BOILERPLATE\n\n  # Allow CC to be a program name with arguments.\n  lt_save_CC=\"$CC\"\n  lt_save_GCC=$GCC\n  CC=${FC-\"f95\"}\n  compiler=$CC\n  GCC=$ac_cv_fc_compiler_gnu\n\n  _LT_TAGVAR(compiler, $1)=$CC\n  _LT_CC_BASENAME([$compiler])\n\n  if test -n \"$compiler\"; then\n    AC_MSG_CHECKING([if libtool supports shared libraries])\n    AC_MSG_RESULT([$can_build_shared])\n\n    AC_MSG_CHECKING([whether to build shared libraries])\n    test \"$can_build_shared\" = \"no\" && enable_shared=no\n\n    # On AIX, shared libraries and static libraries use the same namespace, and\n    # are all built from PIC.\n    case $host_os in\n      aix3*)\n        test \"$enable_shared\" = yes && enable_static=no\n        if test -n \"$RANLIB\"; then\n          archive_cmds=\"$archive_cmds~\\$RANLIB \\$lib\"\n          postinstall_cmds='$RANLIB $lib'\n        fi\n        ;;\n      aix[[4-9]]*)\n\tif test \"$host_cpu\" != ia64 && test \"$aix_use_runtimelinking\" = no ; then\n\t  test \"$enable_shared\" = yes && enable_static=no\n\tfi\n        ;;\n    esac\n    AC_MSG_RESULT([$enable_shared])\n\n    AC_MSG_CHECKING([whether to build static libraries])\n    # Make sure either enable_shared or enable_static is yes.\n    test \"$enable_shared\" = yes || enable_static=yes\n    AC_MSG_RESULT([$enable_static])\n\n    _LT_TAGVAR(GCC, $1)=\"$ac_cv_fc_compiler_gnu\"\n    _LT_TAGVAR(LD, $1)=\"$LD\"\n\n    ## CAVEAT EMPTOR:\n    ## There is no encapsulation within the following macros, do not change\n    ## the running order or otherwise move them around unless you know exactly\n    ## what you are doing...\n    _LT_SYS_HIDDEN_LIBDEPS($1)\n    _LT_COMPILER_PIC($1)\n    _LT_COMPILER_C_O($1)\n    _LT_COMPILER_FILE_LOCKS($1)\n    _LT_LINKER_SHLIBS($1)\n    _LT_SYS_DYNAMIC_LINKER($1)\n    _LT_LINKER_HARDCODE_LIBPATH($1)\n\n    _LT_CONFIG($1)\n  fi # test -n \"$compiler\"\n\n  GCC=$lt_save_GCC\n  CC=\"$lt_save_CC\"\nfi # test \"$_lt_disable_FC\" != yes\n\nAC_LANG_POP\n])# _LT_LANG_FC_CONFIG\n\n\n# _LT_LANG_GCJ_CONFIG([TAG])\n# --------------------------\n# Ensure that the configuration variables for the GNU Java Compiler compiler\n# are suitably defined.  These variables are subsequently used by _LT_CONFIG\n# to write the compiler configuration to `libtool'.\nm4_defun([_LT_LANG_GCJ_CONFIG],\n[AC_REQUIRE([LT_PROG_GCJ])dnl\nAC_LANG_SAVE\n\n# Source file extension for Java test sources.\nac_ext=java\n\n# Object file extension for compiled Java test sources.\nobjext=o\n_LT_TAGVAR(objext, $1)=$objext\n\n# Code to be used in simple compile tests\nlt_simple_compile_test_code=\"class foo {}\"\n\n# Code to be used in simple link tests\nlt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }'\n\n# ltmain only uses $CC for tagged configurations so make sure $CC is set.\n_LT_TAG_COMPILER\n\n# save warnings/boilerplate of simple test code\n_LT_COMPILER_BOILERPLATE\n_LT_LINKER_BOILERPLATE\n\n# Allow CC to be a program name with arguments.\nlt_save_CC=\"$CC\"\nlt_save_GCC=$GCC\nGCC=yes\nCC=${GCJ-\"gcj\"}\ncompiler=$CC\n_LT_TAGVAR(compiler, $1)=$CC\n_LT_TAGVAR(LD, $1)=\"$LD\"\n_LT_CC_BASENAME([$compiler])\n\n# GCJ did not exist at the time GCC didn't implicitly link libc in.\n_LT_TAGVAR(archive_cmds_need_lc, $1)=no\n\n_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds\n_LT_TAGVAR(reload_flag, $1)=$reload_flag\n_LT_TAGVAR(reload_cmds, $1)=$reload_cmds\n\n## CAVEAT EMPTOR:\n## There is no encapsulation within the following macros, do not change\n## the running order or otherwise move them around unless you know exactly\n## what you are doing...\nif test -n \"$compiler\"; then\n  _LT_COMPILER_NO_RTTI($1)\n  _LT_COMPILER_PIC($1)\n  _LT_COMPILER_C_O($1)\n  _LT_COMPILER_FILE_LOCKS($1)\n  _LT_LINKER_SHLIBS($1)\n  _LT_LINKER_HARDCODE_LIBPATH($1)\n\n  _LT_CONFIG($1)\nfi\n\nAC_LANG_RESTORE\n\nGCC=$lt_save_GCC\nCC=\"$lt_save_CC\"\n])# _LT_LANG_GCJ_CONFIG\n\n\n# _LT_LANG_RC_CONFIG([TAG])\n# -------------------------\n# Ensure that the configuration variables for the Windows resource compiler\n# are suitably defined.  These variables are subsequently used by _LT_CONFIG\n# to write the compiler configuration to `libtool'.\nm4_defun([_LT_LANG_RC_CONFIG],\n[AC_REQUIRE([LT_PROG_RC])dnl\nAC_LANG_SAVE\n\n# Source file extension for RC test sources.\nac_ext=rc\n\n# Object file extension for compiled RC test sources.\nobjext=o\n_LT_TAGVAR(objext, $1)=$objext\n\n# Code to be used in simple compile tests\nlt_simple_compile_test_code='sample MENU { MENUITEM \"&Soup\", 100, CHECKED }'\n\n# Code to be used in simple link tests\nlt_simple_link_test_code=\"$lt_simple_compile_test_code\"\n\n# ltmain only uses $CC for tagged configurations so make sure $CC is set.\n_LT_TAG_COMPILER\n\n# save warnings/boilerplate of simple test code\n_LT_COMPILER_BOILERPLATE\n_LT_LINKER_BOILERPLATE\n\n# Allow CC to be a program name with arguments.\nlt_save_CC=\"$CC\"\nlt_save_GCC=$GCC\nGCC=\nCC=${RC-\"windres\"}\ncompiler=$CC\n_LT_TAGVAR(compiler, $1)=$CC\n_LT_CC_BASENAME([$compiler])\n_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes\n\nif test -n \"$compiler\"; then\n  :\n  _LT_CONFIG($1)\nfi\n\nGCC=$lt_save_GCC\nAC_LANG_RESTORE\nCC=\"$lt_save_CC\"\n])# _LT_LANG_RC_CONFIG\n\n\n# LT_PROG_GCJ\n# -----------\nAC_DEFUN([LT_PROG_GCJ],\n[m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ],\n  [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ],\n    [AC_CHECK_TOOL(GCJ, gcj,)\n      test \"x${GCJFLAGS+set}\" = xset || GCJFLAGS=\"-g -O2\"\n      AC_SUBST(GCJFLAGS)])])[]dnl\n])\n\n# Old name:\nAU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ])\ndnl aclocal-1.4 backwards compatibility:\ndnl AC_DEFUN([LT_AC_PROG_GCJ], [])\n\n\n# LT_PROG_RC\n# ----------\nAC_DEFUN([LT_PROG_RC],\n[AC_CHECK_TOOL(RC, windres,)\n])\n\n# Old name:\nAU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC])\ndnl aclocal-1.4 backwards compatibility:\ndnl AC_DEFUN([LT_AC_PROG_RC], [])\n\n\n# _LT_DECL_EGREP\n# --------------\n# If we don't have a new enough Autoconf to choose the best grep\n# available, choose the one first in the user's PATH.\nm4_defun([_LT_DECL_EGREP],\n[AC_REQUIRE([AC_PROG_EGREP])dnl\nAC_REQUIRE([AC_PROG_FGREP])dnl\ntest -z \"$GREP\" && GREP=grep\n_LT_DECL([], [GREP], [1], [A grep program that handles long lines])\n_LT_DECL([], [EGREP], [1], [An ERE matcher])\n_LT_DECL([], [FGREP], [1], [A literal string matcher])\ndnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too\nAC_SUBST([GREP])\n])\n\n\n# _LT_DECL_OBJDUMP\n# --------------\n# If we don't have a new enough Autoconf to choose the best objdump\n# available, choose the one first in the user's PATH.\nm4_defun([_LT_DECL_OBJDUMP],\n[AC_CHECK_TOOL(OBJDUMP, objdump, false)\ntest -z \"$OBJDUMP\" && OBJDUMP=objdump\n_LT_DECL([], [OBJDUMP], [1], [An object symbol dumper])\nAC_SUBST([OBJDUMP])\n])\n\n\n# _LT_DECL_SED\n# ------------\n# Check for a fully-functional sed program, that truncates\n# as few characters as possible.  Prefer GNU sed if found.\nm4_defun([_LT_DECL_SED],\n[AC_PROG_SED\ntest -z \"$SED\" && SED=sed\nXsed=\"$SED -e 1s/^X//\"\n_LT_DECL([], [SED], [1], [A sed program that does not truncate output])\n_LT_DECL([], [Xsed], [\"\\$SED -e 1s/^X//\"],\n    [Sed that helps us avoid accidentally triggering echo(1) options like -n])\n])# _LT_DECL_SED\n\nm4_ifndef([AC_PROG_SED], [\n############################################################\n# NOTE: This macro has been submitted for inclusion into   #\n#  GNU Autoconf as AC_PROG_SED.  When it is available in   #\n#  a released version of Autoconf we should remove this    #\n#  macro and use it instead.                               #\n############################################################\n\nm4_defun([AC_PROG_SED],\n[AC_MSG_CHECKING([for a sed that does not truncate output])\nAC_CACHE_VAL(lt_cv_path_SED,\n[# Loop through the user's path and test for sed and gsed.\n# Then use that list of sed's as ones to test for truncation.\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n  for lt_ac_prog in sed gsed; do\n    for ac_exec_ext in '' $ac_executable_extensions; do\n      if $as_executable_p \"$as_dir/$lt_ac_prog$ac_exec_ext\"; then\n        lt_ac_sed_list=\"$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext\"\n      fi\n    done\n  done\ndone\nIFS=$as_save_IFS\nlt_ac_max=0\nlt_ac_count=0\n# Add /usr/xpg4/bin/sed as it is typically found on Solaris\n# along with /bin/sed that truncates output.\nfor lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do\n  test ! -f $lt_ac_sed && continue\n  cat /dev/null > conftest.in\n  lt_ac_count=0\n  echo $ECHO_N \"0123456789$ECHO_C\" >conftest.in\n  # Check for GNU sed and select it if it is found.\n  if \"$lt_ac_sed\" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then\n    lt_cv_path_SED=$lt_ac_sed\n    break\n  fi\n  while true; do\n    cat conftest.in conftest.in >conftest.tmp\n    mv conftest.tmp conftest.in\n    cp conftest.in conftest.nl\n    echo >>conftest.nl\n    $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break\n    cmp -s conftest.out conftest.nl || break\n    # 10000 chars as input seems more than enough\n    test $lt_ac_count -gt 10 && break\n    lt_ac_count=`expr $lt_ac_count + 1`\n    if test $lt_ac_count -gt $lt_ac_max; then\n      lt_ac_max=$lt_ac_count\n      lt_cv_path_SED=$lt_ac_sed\n    fi\n  done\ndone\n])\nSED=$lt_cv_path_SED\nAC_SUBST([SED])\nAC_MSG_RESULT([$SED])\n])#AC_PROG_SED\n])#m4_ifndef\n\n# Old name:\nAU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED])\ndnl aclocal-1.4 backwards compatibility:\ndnl AC_DEFUN([LT_AC_PROG_SED], [])\n\n\n# _LT_CHECK_SHELL_FEATURES\n# ------------------------\n# Find out whether the shell is Bourne or XSI compatible,\n# or has some other useful features.\nm4_defun([_LT_CHECK_SHELL_FEATURES],\n[AC_MSG_CHECKING([whether the shell understands some XSI constructs])\n# Try some XSI features\nxsi_shell=no\n( _lt_dummy=\"a/b/c\"\n  test \"${_lt_dummy##*/},${_lt_dummy%/*},\"${_lt_dummy%\"$_lt_dummy\"}, \\\n      = c,a/b,, \\\n    && eval 'test $(( 1 + 1 )) -eq 2 \\\n    && test \"${#_lt_dummy}\" -eq 5' ) >/dev/null 2>&1 \\\n  && xsi_shell=yes\nAC_MSG_RESULT([$xsi_shell])\n_LT_CONFIG_LIBTOOL_INIT([xsi_shell='$xsi_shell'])\n\nAC_MSG_CHECKING([whether the shell understands \"+=\"])\nlt_shell_append=no\n( foo=bar; set foo baz; eval \"$[1]+=\\$[2]\" && test \"$foo\" = barbaz ) \\\n    >/dev/null 2>&1 \\\n  && lt_shell_append=yes\nAC_MSG_RESULT([$lt_shell_append])\n_LT_CONFIG_LIBTOOL_INIT([lt_shell_append='$lt_shell_append'])\n\nif ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then\n  lt_unset=unset\nelse\n  lt_unset=false\nfi\n_LT_DECL([], [lt_unset], [0], [whether the shell understands \"unset\"])dnl\n\n# test EBCDIC or ASCII\ncase `echo X|tr X '\\101'` in\n A) # ASCII based system\n    # \\n is not interpreted correctly by Solaris 8 /usr/ucb/tr\n  lt_SP2NL='tr \\040 \\012'\n  lt_NL2SP='tr \\015\\012 \\040\\040'\n  ;;\n *) # EBCDIC based system\n  lt_SP2NL='tr \\100 \\n'\n  lt_NL2SP='tr \\r\\n \\100\\100'\n  ;;\nesac\n_LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl\n_LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl\n])# _LT_CHECK_SHELL_FEATURES\n\n\n# _LT_PROG_XSI_SHELLFNS\n# ---------------------\n# Bourne and XSI compatible variants of some useful shell functions.\nm4_defun([_LT_PROG_XSI_SHELLFNS],\n[case $xsi_shell in\n  yes)\n    cat << \\_LT_EOF >> \"$cfgfile\"\n\n# func_dirname file append nondir_replacement\n# Compute the dirname of FILE.  If nonempty, add APPEND to the result,\n# otherwise set result to NONDIR_REPLACEMENT.\nfunc_dirname ()\n{\n  case ${1} in\n    */*) func_dirname_result=\"${1%/*}${2}\" ;;\n    *  ) func_dirname_result=\"${3}\" ;;\n  esac\n}\n\n# func_basename file\nfunc_basename ()\n{\n  func_basename_result=\"${1##*/}\"\n}\n\n# func_dirname_and_basename file append nondir_replacement\n# perform func_basename and func_dirname in a single function\n# call:\n#   dirname:  Compute the dirname of FILE.  If nonempty,\n#             add APPEND to the result, otherwise set result\n#             to NONDIR_REPLACEMENT.\n#             value returned in \"$func_dirname_result\"\n#   basename: Compute filename of FILE.\n#             value retuned in \"$func_basename_result\"\n# Implementation must be kept synchronized with func_dirname\n# and func_basename. For efficiency, we do not delegate to\n# those functions but instead duplicate the functionality here.\nfunc_dirname_and_basename ()\n{\n  case ${1} in\n    */*) func_dirname_result=\"${1%/*}${2}\" ;;\n    *  ) func_dirname_result=\"${3}\" ;;\n  esac\n  func_basename_result=\"${1##*/}\"\n}\n\n# func_stripname prefix suffix name\n# strip PREFIX and SUFFIX off of NAME.\n# PREFIX and SUFFIX must not contain globbing or regex special\n# characters, hashes, percent signs, but SUFFIX may contain a leading\n# dot (in which case that matches only a dot).\nfunc_stripname ()\n{\n  # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are\n  # positional parameters, so assign one to ordinary parameter first.\n  func_stripname_result=${3}\n  func_stripname_result=${func_stripname_result#\"${1}\"}\n  func_stripname_result=${func_stripname_result%\"${2}\"}\n}\n\n# func_opt_split\nfunc_opt_split ()\n{\n  func_opt_split_opt=${1%%=*}\n  func_opt_split_arg=${1#*=}\n}\n\n# func_lo2o object\nfunc_lo2o ()\n{\n  case ${1} in\n    *.lo) func_lo2o_result=${1%.lo}.${objext} ;;\n    *)    func_lo2o_result=${1} ;;\n  esac\n}\n\n# func_xform libobj-or-source\nfunc_xform ()\n{\n  func_xform_result=${1%.*}.lo\n}\n\n# func_arith arithmetic-term...\nfunc_arith ()\n{\n  func_arith_result=$(( $[*] ))\n}\n\n# func_len string\n# STRING may not start with a hyphen.\nfunc_len ()\n{\n  func_len_result=${#1}\n}\n\n_LT_EOF\n    ;;\n  *) # Bourne compatible functions.\n    cat << \\_LT_EOF >> \"$cfgfile\"\n\n# func_dirname file append nondir_replacement\n# Compute the dirname of FILE.  If nonempty, add APPEND to the result,\n# otherwise set result to NONDIR_REPLACEMENT.\nfunc_dirname ()\n{\n  # Extract subdirectory from the argument.\n  func_dirname_result=`$ECHO \"${1}\" | $SED \"$dirname\"`\n  if test \"X$func_dirname_result\" = \"X${1}\"; then\n    func_dirname_result=\"${3}\"\n  else\n    func_dirname_result=\"$func_dirname_result${2}\"\n  fi\n}\n\n# func_basename file\nfunc_basename ()\n{\n  func_basename_result=`$ECHO \"${1}\" | $SED \"$basename\"`\n}\n\ndnl func_dirname_and_basename\ndnl A portable version of this function is already defined in general.m4sh\ndnl so there is no need for it here.\n\n# func_stripname prefix suffix name\n# strip PREFIX and SUFFIX off of NAME.\n# PREFIX and SUFFIX must not contain globbing or regex special\n# characters, hashes, percent signs, but SUFFIX may contain a leading\n# dot (in which case that matches only a dot).\n# func_strip_suffix prefix name\nfunc_stripname ()\n{\n  case ${2} in\n    .*) func_stripname_result=`$ECHO \"${3}\" | $SED \"s%^${1}%%; s%\\\\\\\\${2}\\$%%\"`;;\n    *)  func_stripname_result=`$ECHO \"${3}\" | $SED \"s%^${1}%%; s%${2}\\$%%\"`;;\n  esac\n}\n\n# sed scripts:\nmy_sed_long_opt='1s/^\\(-[[^=]]*\\)=.*/\\1/;q'\nmy_sed_long_arg='1s/^-[[^=]]*=//'\n\n# func_opt_split\nfunc_opt_split ()\n{\n  func_opt_split_opt=`$ECHO \"${1}\" | $SED \"$my_sed_long_opt\"`\n  func_opt_split_arg=`$ECHO \"${1}\" | $SED \"$my_sed_long_arg\"`\n}\n\n# func_lo2o object\nfunc_lo2o ()\n{\n  func_lo2o_result=`$ECHO \"${1}\" | $SED \"$lo2o\"`\n}\n\n# func_xform libobj-or-source\nfunc_xform ()\n{\n  func_xform_result=`$ECHO \"${1}\" | $SED 's/\\.[[^.]]*$/.lo/'`\n}\n\n# func_arith arithmetic-term...\nfunc_arith ()\n{\n  func_arith_result=`expr \"$[@]\"`\n}\n\n# func_len string\n# STRING may not start with a hyphen.\nfunc_len ()\n{\n  func_len_result=`expr \"$[1]\" : \".*\" 2>/dev/null || echo $max_cmd_len`\n}\n\n_LT_EOF\nesac\n\ncase $lt_shell_append in\n  yes)\n    cat << \\_LT_EOF >> \"$cfgfile\"\n\n# func_append var value\n# Append VALUE to the end of shell variable VAR.\nfunc_append ()\n{\n  eval \"$[1]+=\\$[2]\"\n}\n_LT_EOF\n    ;;\n  *)\n    cat << \\_LT_EOF >> \"$cfgfile\"\n\n# func_append var value\n# Append VALUE to the end of shell variable VAR.\nfunc_append ()\n{\n  eval \"$[1]=\\$$[1]\\$[2]\"\n}\n\n_LT_EOF\n    ;;\n  esac\n])\n"
  },
  {
    "path": "src/vendor/libbacktrace/config/ltoptions.m4",
    "content": "# Helper functions for option handling.                    -*- Autoconf -*-\n#\n#   Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation,\n#   Inc.\n#   Written by Gary V. Vaughan, 2004\n#\n# This file is free software; the Free Software Foundation gives\n# unlimited permission to copy and/or distribute it, with or without\n# modifications, as long as this notice is preserved.\n\n# serial 6 ltoptions.m4\n\n# This is to help aclocal find these macros, as it can't see m4_define.\nAC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])])\n\n\n# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME)\n# ------------------------------------------\nm4_define([_LT_MANGLE_OPTION],\n[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])])\n\n\n# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME)\n# ---------------------------------------\n# Set option OPTION-NAME for macro MACRO-NAME, and if there is a\n# matching handler defined, dispatch to it.  Other OPTION-NAMEs are\n# saved as a flag.\nm4_define([_LT_SET_OPTION],\n[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl\nm4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]),\n        _LT_MANGLE_DEFUN([$1], [$2]),\n    [m4_warning([Unknown $1 option `$2'])])[]dnl\n])\n\n\n# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET])\n# ------------------------------------------------------------\n# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.\nm4_define([_LT_IF_OPTION],\n[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])])\n\n\n# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET)\n# -------------------------------------------------------\n# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME\n# are set.\nm4_define([_LT_UNLESS_OPTIONS],\n[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),\n\t    [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option),\n\t\t      [m4_define([$0_found])])])[]dnl\nm4_ifdef([$0_found], [m4_undefine([$0_found])], [$3\n])[]dnl\n])\n\n\n# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST)\n# ----------------------------------------\n# OPTION-LIST is a space-separated list of Libtool options associated\n# with MACRO-NAME.  If any OPTION has a matching handler declared with\n# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about\n# the unknown option and exit.\nm4_defun([_LT_SET_OPTIONS],\n[# Set options\nm4_foreach([_LT_Option], m4_split(m4_normalize([$2])),\n    [_LT_SET_OPTION([$1], _LT_Option)])\n\nm4_if([$1],[LT_INIT],[\n  dnl\n  dnl Simply set some default values (i.e off) if boolean options were not\n  dnl specified:\n  _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no\n  ])\n  _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no\n  ])\n  dnl\n  dnl If no reference was made to various pairs of opposing options, then\n  dnl we run the default mode handler for the pair.  For example, if neither\n  dnl `shared' nor `disable-shared' was passed, we enable building of shared\n  dnl archives by default:\n  _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED])\n  _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC])\n  _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC])\n  _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install],\n  \t\t   [_LT_ENABLE_FAST_INSTALL])\n  ])\n])# _LT_SET_OPTIONS\n\n\n## --------------------------------- ##\n## Macros to handle LT_INIT options. ##\n## --------------------------------- ##\n\n# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME)\n# -----------------------------------------\nm4_define([_LT_MANGLE_DEFUN],\n[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])])\n\n\n# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE)\n# -----------------------------------------------\nm4_define([LT_OPTION_DEFINE],\n[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl\n])# LT_OPTION_DEFINE\n\n\n# dlopen\n# ------\nLT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes\n])\n\nAU_DEFUN([AC_LIBTOOL_DLOPEN],\n[_LT_SET_OPTION([LT_INIT], [dlopen])\nAC_DIAGNOSE([obsolete],\n[$0: Remove this warning and the call to _LT_SET_OPTION when you\nput the `dlopen' option into LT_INIT's first parameter.])\n])\n\ndnl aclocal-1.4 backwards compatibility:\ndnl AC_DEFUN([AC_LIBTOOL_DLOPEN], [])\n\n\n# win32-dll\n# ---------\n# Declare package support for building win32 dll's.\nLT_OPTION_DEFINE([LT_INIT], [win32-dll],\n[enable_win32_dll=yes\n\ncase $host in\n*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*)\n  AC_CHECK_TOOL(AS, as, false)\n  AC_CHECK_TOOL(DLLTOOL, dlltool, false)\n  AC_CHECK_TOOL(OBJDUMP, objdump, false)\n  ;;\nesac\n\ntest -z \"$AS\" && AS=as\n_LT_DECL([], [AS],      [1], [Assembler program])dnl\n\ntest -z \"$DLLTOOL\" && DLLTOOL=dlltool\n_LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl\n\ntest -z \"$OBJDUMP\" && OBJDUMP=objdump\n_LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl\n])# win32-dll\n\nAU_DEFUN([AC_LIBTOOL_WIN32_DLL],\n[AC_REQUIRE([AC_CANONICAL_HOST])dnl\n_LT_SET_OPTION([LT_INIT], [win32-dll])\nAC_DIAGNOSE([obsolete],\n[$0: Remove this warning and the call to _LT_SET_OPTION when you\nput the `win32-dll' option into LT_INIT's first parameter.])\n])\n\ndnl aclocal-1.4 backwards compatibility:\ndnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], [])\n\n\n# _LT_ENABLE_SHARED([DEFAULT])\n# ----------------------------\n# implement the --enable-shared flag, and supports the `shared' and\n# `disable-shared' LT_INIT options.\n# DEFAULT is either `yes' or `no'.  If omitted, it defaults to `yes'.\nm4_define([_LT_ENABLE_SHARED],\n[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl\nAC_ARG_ENABLE([shared],\n    [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@],\n\t[build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])],\n    [p=${PACKAGE-default}\n    case $enableval in\n    yes) enable_shared=yes ;;\n    no) enable_shared=no ;;\n    *)\n      enable_shared=no\n      # Look at the argument we got.  We use all the common list separators.\n      lt_save_ifs=\"$IFS\"; IFS=\"${IFS}$PATH_SEPARATOR,\"\n      for pkg in $enableval; do\n\tIFS=\"$lt_save_ifs\"\n\tif test \"X$pkg\" = \"X$p\"; then\n\t  enable_shared=yes\n\tfi\n      done\n      IFS=\"$lt_save_ifs\"\n      ;;\n    esac],\n    [enable_shared=]_LT_ENABLE_SHARED_DEFAULT)\n\n    _LT_DECL([build_libtool_libs], [enable_shared], [0],\n\t[Whether or not to build shared libraries])\n])# _LT_ENABLE_SHARED\n\nLT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])])\nLT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])])\n\n# Old names:\nAC_DEFUN([AC_ENABLE_SHARED],\n[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared])\n])\n\nAC_DEFUN([AC_DISABLE_SHARED],\n[_LT_SET_OPTION([LT_INIT], [disable-shared])\n])\n\nAU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)])\nAU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)])\n\ndnl aclocal-1.4 backwards compatibility:\ndnl AC_DEFUN([AM_ENABLE_SHARED], [])\ndnl AC_DEFUN([AM_DISABLE_SHARED], [])\n\n\n\n# _LT_ENABLE_STATIC([DEFAULT])\n# ----------------------------\n# implement the --enable-static flag, and support the `static' and\n# `disable-static' LT_INIT options.\n# DEFAULT is either `yes' or `no'.  If omitted, it defaults to `yes'.\nm4_define([_LT_ENABLE_STATIC],\n[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl\nAC_ARG_ENABLE([static],\n    [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@],\n\t[build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])],\n    [p=${PACKAGE-default}\n    case $enableval in\n    yes) enable_static=yes ;;\n    no) enable_static=no ;;\n    *)\n     enable_static=no\n      # Look at the argument we got.  We use all the common list separators.\n      lt_save_ifs=\"$IFS\"; IFS=\"${IFS}$PATH_SEPARATOR,\"\n      for pkg in $enableval; do\n\tIFS=\"$lt_save_ifs\"\n\tif test \"X$pkg\" = \"X$p\"; then\n\t  enable_static=yes\n\tfi\n      done\n      IFS=\"$lt_save_ifs\"\n      ;;\n    esac],\n    [enable_static=]_LT_ENABLE_STATIC_DEFAULT)\n\n    _LT_DECL([build_old_libs], [enable_static], [0],\n\t[Whether or not to build static libraries])\n])# _LT_ENABLE_STATIC\n\nLT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])])\nLT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])])\n\n# Old names:\nAC_DEFUN([AC_ENABLE_STATIC],\n[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static])\n])\n\nAC_DEFUN([AC_DISABLE_STATIC],\n[_LT_SET_OPTION([LT_INIT], [disable-static])\n])\n\nAU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)])\nAU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)])\n\ndnl aclocal-1.4 backwards compatibility:\ndnl AC_DEFUN([AM_ENABLE_STATIC], [])\ndnl AC_DEFUN([AM_DISABLE_STATIC], [])\n\n\n\n# _LT_ENABLE_FAST_INSTALL([DEFAULT])\n# ----------------------------------\n# implement the --enable-fast-install flag, and support the `fast-install'\n# and `disable-fast-install' LT_INIT options.\n# DEFAULT is either `yes' or `no'.  If omitted, it defaults to `yes'.\nm4_define([_LT_ENABLE_FAST_INSTALL],\n[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl\nAC_ARG_ENABLE([fast-install],\n    [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@],\n    [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])],\n    [p=${PACKAGE-default}\n    case $enableval in\n    yes) enable_fast_install=yes ;;\n    no) enable_fast_install=no ;;\n    *)\n      enable_fast_install=no\n      # Look at the argument we got.  We use all the common list separators.\n      lt_save_ifs=\"$IFS\"; IFS=\"${IFS}$PATH_SEPARATOR,\"\n      for pkg in $enableval; do\n\tIFS=\"$lt_save_ifs\"\n\tif test \"X$pkg\" = \"X$p\"; then\n\t  enable_fast_install=yes\n\tfi\n      done\n      IFS=\"$lt_save_ifs\"\n      ;;\n    esac],\n    [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT)\n\n_LT_DECL([fast_install], [enable_fast_install], [0],\n\t [Whether or not to optimize for fast installation])dnl\n])# _LT_ENABLE_FAST_INSTALL\n\nLT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])])\nLT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])])\n\n# Old names:\nAU_DEFUN([AC_ENABLE_FAST_INSTALL],\n[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install])\nAC_DIAGNOSE([obsolete],\n[$0: Remove this warning and the call to _LT_SET_OPTION when you put\nthe `fast-install' option into LT_INIT's first parameter.])\n])\n\nAU_DEFUN([AC_DISABLE_FAST_INSTALL],\n[_LT_SET_OPTION([LT_INIT], [disable-fast-install])\nAC_DIAGNOSE([obsolete],\n[$0: Remove this warning and the call to _LT_SET_OPTION when you put\nthe `disable-fast-install' option into LT_INIT's first parameter.])\n])\n\ndnl aclocal-1.4 backwards compatibility:\ndnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], [])\ndnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], [])\n\n\n# _LT_WITH_PIC([MODE])\n# --------------------\n# implement the --with-pic flag, and support the `pic-only' and `no-pic'\n# LT_INIT options.\n# MODE is either `yes' or `no'.  If omitted, it defaults to `both'.\nm4_define([_LT_WITH_PIC],\n[AC_ARG_WITH([pic],\n    [AS_HELP_STRING([--with-pic],\n\t[try to use only PIC/non-PIC objects @<:@default=use both@:>@])],\n    [pic_mode=\"$withval\"],\n    [pic_mode=default])\n\ntest -z \"$pic_mode\" && pic_mode=m4_default([$1], [default])\n\n_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl\n])# _LT_WITH_PIC\n\nLT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])])\nLT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])])\n\n# Old name:\nAU_DEFUN([AC_LIBTOOL_PICMODE],\n[_LT_SET_OPTION([LT_INIT], [pic-only])\nAC_DIAGNOSE([obsolete],\n[$0: Remove this warning and the call to _LT_SET_OPTION when you\nput the `pic-only' option into LT_INIT's first parameter.])\n])\n\ndnl aclocal-1.4 backwards compatibility:\ndnl AC_DEFUN([AC_LIBTOOL_PICMODE], [])\n\n## ----------------- ##\n## LTDL_INIT Options ##\n## ----------------- ##\n\nm4_define([_LTDL_MODE], [])\nLT_OPTION_DEFINE([LTDL_INIT], [nonrecursive],\n\t\t [m4_define([_LTDL_MODE], [nonrecursive])])\nLT_OPTION_DEFINE([LTDL_INIT], [recursive],\n\t\t [m4_define([_LTDL_MODE], [recursive])])\nLT_OPTION_DEFINE([LTDL_INIT], [subproject],\n\t\t [m4_define([_LTDL_MODE], [subproject])])\n\nm4_define([_LTDL_TYPE], [])\nLT_OPTION_DEFINE([LTDL_INIT], [installable],\n\t\t [m4_define([_LTDL_TYPE], [installable])])\nLT_OPTION_DEFINE([LTDL_INIT], [convenience],\n\t\t [m4_define([_LTDL_TYPE], [convenience])])\n"
  },
  {
    "path": "src/vendor/libbacktrace/config/ltsugar.m4",
    "content": "# ltsugar.m4 -- libtool m4 base layer.                         -*-Autoconf-*-\n#\n# Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc.\n# Written by Gary V. Vaughan, 2004\n#\n# This file is free software; the Free Software Foundation gives\n# unlimited permission to copy and/or distribute it, with or without\n# modifications, as long as this notice is preserved.\n\n# serial 6 ltsugar.m4\n\n# This is to help aclocal find these macros, as it can't see m4_define.\nAC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])])\n\n\n# lt_join(SEP, ARG1, [ARG2...])\n# -----------------------------\n# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their\n# associated separator.\n# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier\n# versions in m4sugar had bugs.\nm4_define([lt_join],\n[m4_if([$#], [1], [],\n       [$#], [2], [[$2]],\n       [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])])\nm4_define([_lt_join],\n[m4_if([$#$2], [2], [],\n       [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])])\n\n\n# lt_car(LIST)\n# lt_cdr(LIST)\n# ------------\n# Manipulate m4 lists.\n# These macros are necessary as long as will still need to support\n# Autoconf-2.59 which quotes differently.\nm4_define([lt_car], [[$1]])\nm4_define([lt_cdr],\n[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])],\n       [$#], 1, [],\n       [m4_dquote(m4_shift($@))])])\nm4_define([lt_unquote], $1)\n\n\n# lt_append(MACRO-NAME, STRING, [SEPARATOR])\n# ------------------------------------------\n# Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'.\n# Note that neither SEPARATOR nor STRING are expanded; they are appended\n# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked).\n# No SEPARATOR is output if MACRO-NAME was previously undefined (different\n# than defined and empty).\n#\n# This macro is needed until we can rely on Autoconf 2.62, since earlier\n# versions of m4sugar mistakenly expanded SEPARATOR but not STRING.\nm4_define([lt_append],\n[m4_define([$1],\n\t   m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])])\n\n\n\n# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...])\n# ----------------------------------------------------------\n# Produce a SEP delimited list of all paired combinations of elements of\n# PREFIX-LIST with SUFFIX1 through SUFFIXn.  Each element of the list\n# has the form PREFIXmINFIXSUFFIXn.\n# Needed until we can rely on m4_combine added in Autoconf 2.62.\nm4_define([lt_combine],\n[m4_if(m4_eval([$# > 3]), [1],\n       [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl\n[[m4_foreach([_Lt_prefix], [$2],\n\t     [m4_foreach([_Lt_suffix],\n\t\t]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[,\n\t[_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])])\n\n\n# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ])\n# -----------------------------------------------------------------------\n# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited\n# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ.\nm4_define([lt_if_append_uniq],\n[m4_ifdef([$1],\n\t  [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1],\n\t\t [lt_append([$1], [$2], [$3])$4],\n\t\t [$5])],\n\t  [lt_append([$1], [$2], [$3])$4])])\n\n\n# lt_dict_add(DICT, KEY, VALUE)\n# -----------------------------\nm4_define([lt_dict_add],\n[m4_define([$1($2)], [$3])])\n\n\n# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE)\n# --------------------------------------------\nm4_define([lt_dict_add_subkey],\n[m4_define([$1($2:$3)], [$4])])\n\n\n# lt_dict_fetch(DICT, KEY, [SUBKEY])\n# ----------------------------------\nm4_define([lt_dict_fetch],\n[m4_ifval([$3],\n\tm4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]),\n    m4_ifdef([$1($2)], [m4_defn([$1($2)])]))])\n\n\n# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE])\n# -----------------------------------------------------------------\nm4_define([lt_if_dict_fetch],\n[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4],\n\t[$5],\n    [$6])])\n\n\n# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...])\n# --------------------------------------------------------------\nm4_define([lt_dict_filter],\n[m4_if([$5], [], [],\n  [lt_join(m4_quote(m4_default([$4], [[, ]])),\n           lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]),\n\t\t      [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl\n])\n"
  },
  {
    "path": "src/vendor/libbacktrace/config/ltversion.m4",
    "content": "# ltversion.m4 -- version numbers\t\t\t-*- Autoconf -*-\n#\n#   Copyright (C) 2004 Free Software Foundation, Inc.\n#   Written by Scott James Remnant, 2004\n#\n# This file is free software; the Free Software Foundation gives\n# unlimited permission to copy and/or distribute it, with or without\n# modifications, as long as this notice is preserved.\n\n# Generated from ltversion.in.\n\n# serial 3134 ltversion.m4\n# This file is part of GNU Libtool\n\nm4_define([LT_PACKAGE_VERSION], [2.2.7a])\nm4_define([LT_PACKAGE_REVISION], [1.3134])\n\nAC_DEFUN([LTVERSION_VERSION],\n[macro_version='2.2.7a'\nmacro_revision='1.3134'\n_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?])\n_LT_DECL(, macro_revision, 0)\n])\n"
  },
  {
    "path": "src/vendor/libbacktrace/config/lt~obsolete.m4",
    "content": "# lt~obsolete.m4 -- aclocal satisfying obsolete definitions.    -*-Autoconf-*-\n#\n#   Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc.\n#   Written by Scott James Remnant, 2004.\n#\n# This file is free software; the Free Software Foundation gives\n# unlimited permission to copy and/or distribute it, with or without\n# modifications, as long as this notice is preserved.\n\n# serial 4 lt~obsolete.m4\n\n# These exist entirely to fool aclocal when bootstrapping libtool.\n#\n# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN)\n# which have later been changed to m4_define as they aren't part of the\n# exported API, or moved to Autoconf or Automake where they belong.\n#\n# The trouble is, aclocal is a bit thick.  It'll see the old AC_DEFUN\n# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us\n# using a macro with the same name in our local m4/libtool.m4 it'll\n# pull the old libtool.m4 in (it doesn't see our shiny new m4_define\n# and doesn't know about Autoconf macros at all.)\n#\n# So we provide this file, which has a silly filename so it's always\n# included after everything else.  This provides aclocal with the\n# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything\n# because those macros already exist, or will be overwritten later.\n# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. \n#\n# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here.\n# Yes, that means every name once taken will need to remain here until\n# we give up compatibility with versions before 1.7, at which point\n# we need to keep only those names which we still refer to.\n\n# This is to help aclocal find these macros, as it can't see m4_define.\nAC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])])\n\nm4_ifndef([AC_LIBTOOL_LINKER_OPTION],\t[AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])])\nm4_ifndef([AC_PROG_EGREP],\t\t[AC_DEFUN([AC_PROG_EGREP])])\nm4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH],\t[AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])])\nm4_ifndef([_LT_AC_SHELL_INIT],\t\t[AC_DEFUN([_LT_AC_SHELL_INIT])])\nm4_ifndef([_LT_AC_SYS_LIBPATH_AIX],\t[AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])])\nm4_ifndef([_LT_PROG_LTMAIN],\t\t[AC_DEFUN([_LT_PROG_LTMAIN])])\nm4_ifndef([_LT_AC_TAGVAR],\t\t[AC_DEFUN([_LT_AC_TAGVAR])])\nm4_ifndef([AC_LTDL_ENABLE_INSTALL],\t[AC_DEFUN([AC_LTDL_ENABLE_INSTALL])])\nm4_ifndef([AC_LTDL_PREOPEN],\t\t[AC_DEFUN([AC_LTDL_PREOPEN])])\nm4_ifndef([_LT_AC_SYS_COMPILER],\t[AC_DEFUN([_LT_AC_SYS_COMPILER])])\nm4_ifndef([_LT_AC_LOCK],\t\t[AC_DEFUN([_LT_AC_LOCK])])\nm4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE],\t[AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])])\nm4_ifndef([_LT_AC_TRY_DLOPEN_SELF],\t[AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])])\nm4_ifndef([AC_LIBTOOL_PROG_CC_C_O],\t[AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])])\nm4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])])\nm4_ifndef([AC_LIBTOOL_OBJDIR],\t\t[AC_DEFUN([AC_LIBTOOL_OBJDIR])])\nm4_ifndef([AC_LTDL_OBJDIR],\t\t[AC_DEFUN([AC_LTDL_OBJDIR])])\nm4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])])\nm4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP],\t[AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])])\nm4_ifndef([AC_PATH_MAGIC],\t\t[AC_DEFUN([AC_PATH_MAGIC])])\nm4_ifndef([AC_PROG_LD_GNU],\t\t[AC_DEFUN([AC_PROG_LD_GNU])])\nm4_ifndef([AC_PROG_LD_RELOAD_FLAG],\t[AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])])\nm4_ifndef([AC_DEPLIBS_CHECK_METHOD],\t[AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])])\nm4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])])\nm4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])])\nm4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])])\nm4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS],\t[AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])])\nm4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP],\t[AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])])\nm4_ifndef([LT_AC_PROG_EGREP],\t\t[AC_DEFUN([LT_AC_PROG_EGREP])])\nm4_ifndef([LT_AC_PROG_SED],\t\t[AC_DEFUN([LT_AC_PROG_SED])])\nm4_ifndef([_LT_CC_BASENAME],\t\t[AC_DEFUN([_LT_CC_BASENAME])])\nm4_ifndef([_LT_COMPILER_BOILERPLATE],\t[AC_DEFUN([_LT_COMPILER_BOILERPLATE])])\nm4_ifndef([_LT_LINKER_BOILERPLATE],\t[AC_DEFUN([_LT_LINKER_BOILERPLATE])])\nm4_ifndef([_AC_PROG_LIBTOOL],\t\t[AC_DEFUN([_AC_PROG_LIBTOOL])])\nm4_ifndef([AC_LIBTOOL_SETUP],\t\t[AC_DEFUN([AC_LIBTOOL_SETUP])])\nm4_ifndef([_LT_AC_CHECK_DLFCN],\t\t[AC_DEFUN([_LT_AC_CHECK_DLFCN])])\nm4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER],\t[AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])])\nm4_ifndef([_LT_AC_TAGCONFIG],\t\t[AC_DEFUN([_LT_AC_TAGCONFIG])])\nm4_ifndef([AC_DISABLE_FAST_INSTALL],\t[AC_DEFUN([AC_DISABLE_FAST_INSTALL])])\nm4_ifndef([_LT_AC_LANG_CXX],\t\t[AC_DEFUN([_LT_AC_LANG_CXX])])\nm4_ifndef([_LT_AC_LANG_F77],\t\t[AC_DEFUN([_LT_AC_LANG_F77])])\nm4_ifndef([_LT_AC_LANG_GCJ],\t\t[AC_DEFUN([_LT_AC_LANG_GCJ])])\nm4_ifndef([AC_LIBTOOL_LANG_C_CONFIG],\t[AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])])\nm4_ifndef([_LT_AC_LANG_C_CONFIG],\t[AC_DEFUN([_LT_AC_LANG_C_CONFIG])])\nm4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG],\t[AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])])\nm4_ifndef([_LT_AC_LANG_CXX_CONFIG],\t[AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])])\nm4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG],\t[AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])])\nm4_ifndef([_LT_AC_LANG_F77_CONFIG],\t[AC_DEFUN([_LT_AC_LANG_F77_CONFIG])])\nm4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG],\t[AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])])\nm4_ifndef([_LT_AC_LANG_GCJ_CONFIG],\t[AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])])\nm4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG],\t[AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])])\nm4_ifndef([_LT_AC_LANG_RC_CONFIG],\t[AC_DEFUN([_LT_AC_LANG_RC_CONFIG])])\nm4_ifndef([AC_LIBTOOL_CONFIG],\t\t[AC_DEFUN([AC_LIBTOOL_CONFIG])])\nm4_ifndef([_LT_AC_FILE_LTDLL_C],\t[AC_DEFUN([_LT_AC_FILE_LTDLL_C])])\nm4_ifndef([_LT_REQUIRED_DARWIN_CHECKS],\t[AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])])\nm4_ifndef([_LT_AC_PROG_CXXCPP],\t\t[AC_DEFUN([_LT_AC_PROG_CXXCPP])])\nm4_ifndef([_LT_PREPARE_SED_QUOTE_VARS],\t[AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])])\nm4_ifndef([_LT_PROG_ECHO_BACKSLASH],\t[AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])])\nm4_ifndef([_LT_PROG_F77],\t\t[AC_DEFUN([_LT_PROG_F77])])\nm4_ifndef([_LT_PROG_FC],\t\t[AC_DEFUN([_LT_PROG_FC])])\nm4_ifndef([_LT_PROG_CXX],\t\t[AC_DEFUN([_LT_PROG_CXX])])\n"
  },
  {
    "path": "src/vendor/libbacktrace/config/multi.m4",
    "content": "##                                                          -*- Autoconf -*-\n# Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2008\n# Free Software Foundation, Inc.\n#\n# This file is free software; the Free Software Foundation\n# gives unlimited permission to copy and/or distribute it,\n# with or without modifications, as long as this notice is preserved.\n\n# serial 6\n\n# AM_ENABLE_MULTILIB([MAKEFILE], [REL-TO-TOP-SRCDIR])\n# ---------------------------------------------------\n# Add --enable-multilib to configure.\nAC_DEFUN([AM_ENABLE_MULTILIB],\n[# Default to --enable-multilib\nAC_ARG_ENABLE(multilib,\n[  --enable-multilib       build many library versions (default)],\n[case \"$enableval\" in\n  yes) multilib=yes ;;\n  no)  multilib=no ;;\n  *)   AC_MSG_ERROR([bad value $enableval for multilib option]) ;;\n esac],\n\t      [multilib=yes])\n\n# We may get other options which we leave undocumented:\n# --with-target-subdir, --with-multisrctop, --with-multisubdir\n# See config-ml.in if you want the gory details.\n\nif test \"$srcdir\" = \".\"; then\n  if test \"$with_target_subdir\" != \".\"; then\n    multi_basedir=\"$srcdir/$with_multisrctop../$2\"\n  else\n    multi_basedir=\"$srcdir/$with_multisrctop$2\"\n  fi\nelse\n  multi_basedir=\"$srcdir/$2\"\nfi\nAC_SUBST(multi_basedir)\n\n# Even if the default multilib is not a cross compilation,\n# it may be that some of the other multilibs are.\nif test $cross_compiling = no && test $multilib = yes \\\n   && test \"x${with_multisubdir}\" != x ; then\n   cross_compiling=maybe\nfi\n\nAC_OUTPUT_COMMANDS([\n# Only add multilib support code if we just rebuilt the top-level\n# Makefile.\ncase \" $CONFIG_FILES \" in\n *\" ]m4_default([$1],Makefile)[ \"*)\n   ac_file=]m4_default([$1],Makefile)[ . ${multi_basedir}/config-ml.in\n   ;;\nesac],\n\t\t   [\nsrcdir=\"$srcdir\"\nhost=\"$host\"\ntarget=\"$target\"\nwith_multisubdir=\"$with_multisubdir\"\nwith_multisrctop=\"$with_multisrctop\"\nwith_target_subdir=\"$with_target_subdir\"\nac_configure_args=\"${multilib_arg} ${ac_configure_args}\"\nmulti_basedir=\"$multi_basedir\"\nCONFIG_SHELL=${CONFIG_SHELL-/bin/sh}\nCC=\"$CC\"\nCXX=\"$CXX\"\nGFORTRAN=\"$GFORTRAN\"\nGDC=\"$GDC\"])])dnl\n"
  },
  {
    "path": "src/vendor/libbacktrace/config/override.m4",
    "content": "dnl Fix Autoconf bugs by overriding broken internal Autoconf\ndnl macros with backports of fixes from newer releases.\ndnl\ndnl The override bits of this file should be a no-op for the newest\ndnl Autoconf version, which means they can be removed once the complete\ndnl tree has moved to a new enough Autoconf version.\ndnl\ndnl The _GCC_AUTOCONF_VERSION_TEST ensures that exactly the desired\ndnl Autoconf version is used.  It should be kept for consistency.\n\ndnl Use ifdef/ifelse over m4_ifdef/m4_ifelse to be clean for 2.13.\nifdef([m4_PACKAGE_VERSION], [\n\ndnl Provide m4_copy_force and m4_rename_force for old Autoconf versions.\n\nm4_ifndef([m4_copy_force],\n[m4_define([m4_copy_force],\n[m4_ifdef([$2], [m4_undefine([$2])])m4_copy($@)])])\n\nm4_ifndef([m4_rename_force],\n[m4_define([m4_rename_force],\n[m4_ifdef([$2], [m4_undefine([$2])])m4_rename($@)])])\n\ndnl AC_DEFUN a commonly used macro so this file is picked up.\nm4_copy([AC_PREREQ], [_AC_PREREQ])\nAC_DEFUN([AC_PREREQ], [frob])\nm4_copy_force([_AC_PREREQ], [AC_PREREQ])\n\n\ndnl Ensure exactly this Autoconf version is used\nm4_ifndef([_GCC_AUTOCONF_VERSION],\n  [m4_define([_GCC_AUTOCONF_VERSION], [2.69])])\n\ndnl Test for the exact version when AC_INIT is expanded.\ndnl This allows to update the tree in steps (for testing)\ndnl by putting\ndnl   m4_define([_GCC_AUTOCONF_VERSION], [X.Y])\ndnl in configure.ac before AC_INIT,\ndnl without rewriting this file.\ndnl Or for updating the whole tree at once with the definition above.\nAC_DEFUN([_GCC_AUTOCONF_VERSION_CHECK],\n[m4_if(m4_defn([_GCC_AUTOCONF_VERSION]),\n  m4_defn([m4_PACKAGE_VERSION]), [],\n  [m4_fatal([Please use exactly Autoconf ]_GCC_AUTOCONF_VERSION[ instead of ]m4_defn([m4_PACKAGE_VERSION])[.])])\n])\ndnl don't do this for libbacktrace\ndnl m4_define([AC_INIT], m4_defn([AC_INIT])[\ndnl _GCC_AUTOCONF_VERSION_CHECK\ndnl ])\n\n\ndnl Ensure we do not use a buggy M4.\nm4_if(m4_index([..wi.d.], [.d.]), [-1],\n  [m4_fatal(m4_do([m4 with buggy strstr detected.  Please install\nGNU M4 1.4.16 or newer and set the M4 environment variable]))])\n\n\ndnl Fix 2.64 cross compile detection for AVR and RTEMS\ndnl by not trying to compile fopen.\nm4_if(m4_defn([m4_PACKAGE_VERSION]), [2.64],\n  [m4_foreach([_GCC_LANG], [C, C++, Fortran, Fortran 77],\n     [m4_define([_AC_LANG_IO_PROGRAM(]_GCC_LANG[)], m4_defn([AC_LANG_PROGRAM(]_GCC_LANG[)]))])])\n\nm4_version_prereq([2.66],, [\ndnl We need AC_CHECK_DECL which works for overloaded C++ functions.\n\n# _AC_CHECK_DECL_BODY\n# -------------------\n# Shell function body for AC_CHECK_DECL.\nm4_define([_AC_CHECK_DECL_BODY],\n[  AS_LINENO_PUSH([$[]1])\n  [as_decl_name=`echo $][2|sed 's/ *(.*//'`]\n  [as_decl_use=`echo $][2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'`]\n  AC_CACHE_CHECK([whether $as_decl_name is declared], [$[]3],\n  [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([$[]4],\n[@%:@ifndef $[]as_decl_name\n@%:@ifdef __cplusplus\n  (void) $[]as_decl_use;\n@%:@else\n  (void) $[]as_decl_name;\n@%:@endif\n@%:@endif\n])],\n\t\t   [AS_VAR_SET([$[]3], [yes])],\n\t\t   [AS_VAR_SET([$[]3], [no])])])\n  AS_LINENO_POP\n])# _AC_CHECK_DECL_BODY\n\n# _AC_CHECK_DECLS(SYMBOL, ACTION-IF_FOUND, ACTION-IF-NOT-FOUND,\n#                 INCLUDES)\n# -------------------------------------------------------------\n# Helper to AC_CHECK_DECLS, which generates the check for a single\n# SYMBOL with INCLUDES, performs the AC_DEFINE, then expands\n# ACTION-IF-FOUND or ACTION-IF-NOT-FOUND.\nm4_define([_AC_CHECK_DECLS],\n[AC_CHECK_DECL([$1], [ac_have_decl=1], [ac_have_decl=0], [$4])]dnl\n[AC_DEFINE_UNQUOTED(AS_TR_CPP(m4_bpatsubst(HAVE_DECL_[$1],[ *(.*])),\n  [$ac_have_decl],\n  [Define to 1 if you have the declaration of `$1',\n   and to 0 if you don't.])]dnl\n[m4_ifvaln([$2$3], [AS_IF([test $ac_have_decl = 1], [$2], [$3])])])\n\n])\n\ndnl If flex/lex are not found, the top level configure sets LEX to\ndnl \"/path_to/missing flex\".  When AC_PROG_LEX tries to find the flex\ndnl output file, it calls $LEX to do so, but the current lightweight\ndnl \"missing\" won't create a file.  This results in an error.\ndnl Avoid calling the bulk of AC_PROG_LEX when $LEX is \"missing\".\nAC_DEFUN_ONCE([AC_PROG_LEX],\n[AC_CHECK_PROGS(LEX, flex lex, :)\ncase \"$LEX\" in\n  :|*\"missing \"*) ;;\n  *) _AC_PROG_LEX_YYTEXT_DECL ;;\nesac])\n\n])\n"
  },
  {
    "path": "src/vendor/libbacktrace/config/unwind_ipinfo.m4",
    "content": "dnl\ndnl Check whether _Unwind_GetIPInfo is available without doing a link\ndnl test so we can use this with libstdc++-v3 and libjava.  Need to\ndnl use $target to set defaults because automatic checking is not possible\ndnl without a link test (and maybe even with a link test).\ndnl\n\nAC_DEFUN([GCC_CHECK_UNWIND_GETIPINFO], [\n  AC_ARG_WITH(system-libunwind,\n  [  --with-system-libunwind use installed libunwind])\n  # If system-libunwind was not specifically set, pick a default setting.\n  if test x$with_system_libunwind = x; then\n    case ${target} in\n      ia64-*-hpux*) with_system_libunwind=yes ;;\n      *) with_system_libunwind=no ;;\n    esac\n  fi\n  # Based on system-libunwind and target, do we have ipinfo?\n  if  test x$with_system_libunwind = xyes; then\n    case ${target} in\n      ia64-*-*) have_unwind_getipinfo=no ;;\n      *) have_unwind_getipinfo=yes ;;\n    esac\n  else\n    # Darwin before version 9 does not have _Unwind_GetIPInfo.\n    changequote(,)\n    case ${target} in\n      *-*-darwin[3-8]|*-*-darwin[3-8].*) have_unwind_getipinfo=no ;;\n      *) have_unwind_getipinfo=yes ;;\n    esac\n    changequote([,])\n  fi\n\n  if test x$have_unwind_getipinfo = xyes; then\n    AC_DEFINE(HAVE_GETIPINFO, 1, [Define if _Unwind_GetIPInfo is available.])\n  fi\n])\n"
  },
  {
    "path": "src/vendor/libbacktrace/config/warnings.m4",
    "content": "# Autoconf include file defining macros related to compile-time warnings.\n\n# Copyright 2004, 2005, 2007, 2009, 2011 Free Software Foundation, Inc.\n\n#This file is part of GCC.\n\n#GCC is free software; you can redistribute it and/or modify it under\n#the terms of the GNU General Public License as published by the Free\n#Software Foundation; either version 3, or (at your option) any later\n#version.\n\n#GCC is distributed in the hope that it will be useful, but WITHOUT\n#ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\n#FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n#for more details.\n\n#You should have received a copy of the GNU General Public License\n#along with GCC; see the file COPYING3.  If not see\n#<http://www.gnu.org/licenses/>.\n\n# ACX_PROG_CC_WARNING_OPTS(WARNINGS, [VARIABLE = WARN_CFLAGS])\n#   Sets @VARIABLE@ to the subset of the given options which the\n#   compiler accepts.\nAC_DEFUN([ACX_PROG_CC_WARNING_OPTS],\n[AC_REQUIRE([AC_PROG_CC])dnl\nAC_LANG_PUSH(C)\nm4_pushdef([acx_Var], [m4_default([$2], [WARN_CFLAGS])])dnl\nAC_SUBST(acx_Var)dnl\nm4_expand_once([acx_Var=\n],m4_quote(acx_Var=))dnl\nsave_CFLAGS=\"$CFLAGS\"\nfor real_option in $1; do\n  # Do the check with the no- prefix removed since gcc silently\n  # accepts any -Wno-* option on purpose\n  case $real_option in\n    -Wno-*) option=-W`expr x$real_option : 'x-Wno-\\(.*\\)'` ;;\n    *) option=$real_option ;;\n  esac\n  AS_VAR_PUSHDEF([acx_Woption], [acx_cv_prog_cc_warning_$option])\n  AC_CACHE_CHECK([whether $CC supports $option], acx_Woption,\n    [CFLAGS=\"$option\"\n    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],[])],\n      [AS_VAR_SET(acx_Woption, yes)],\n      [AS_VAR_SET(acx_Woption, no)])\n  ])\n  AS_IF([test AS_VAR_GET(acx_Woption) = yes],\n        [acx_Var=\"$acx_Var${acx_Var:+ }$real_option\"])\n  AS_VAR_POPDEF([acx_Woption])dnl\ndone\nCFLAGS=\"$save_CFLAGS\"\nm4_popdef([acx_Var])dnl\nAC_LANG_POP(C)\n])# ACX_PROG_CC_WARNING_OPTS\n\n# ACX_PROG_CC_WARNING_ALMOST_PEDANTIC(WARNINGS, [VARIABLE = WARN_PEDANTIC])\n#   Append to VARIABLE \"-pedantic\" + the argument, if the compiler is GCC\n#   and accepts all of those options simultaneously, otherwise to nothing.\nAC_DEFUN([ACX_PROG_CC_WARNING_ALMOST_PEDANTIC],\n[AC_REQUIRE([AC_PROG_CC])dnl\nAC_LANG_PUSH(C)\nm4_pushdef([acx_Var], [m4_default([$2], [WARN_PEDANTIC])])dnl\nAC_SUBST(acx_Var)dnl\nm4_expand_once([acx_Var=\n],m4_quote(acx_Var=))dnl\n# Do the check with the no- prefix removed from the warning options\n# since gcc silently accepts any -Wno-* option on purpose\nm4_pushdef([acx_Woptions], [m4_bpatsubst([$1], [-Wno-], [-W])])dnl\nAS_VAR_PUSHDEF([acx_Pedantic], [acx_cv_prog_cc_pedantic_]acx_Woptions)dnl\nAS_IF([test \"$GCC\" = yes],\n[AC_CACHE_CHECK([whether $CC supports -pedantic ]acx_Woptions, acx_Pedantic,\n[save_CFLAGS=\"$CFLAGS\"\nCFLAGS=\"-pedantic acx_Woptions\"\nAC_COMPILE_IFELSE([AC_LANG_PROGRAM([],[])],\n   [AS_VAR_SET(acx_Pedantic, yes)],\n   [AS_VAR_SET(acx_Pedantic, no)])\nCFLAGS=\"$save_CFLAGS\"])\nAS_IF([test AS_VAR_GET(acx_Pedantic) = yes],\n      [acx_Var=\"$acx_Var${acx_Var:+ }-pedantic $1\"])\n])\nAS_VAR_POPDEF([acx_Pedantic])dnl\nm4_popdef([acx_Woptions])dnl\nm4_popdef([acx_Var])dnl\nAC_LANG_POP(C)\n])# ACX_PROG_CC_WARNING_ALMOST_PEDANTIC\n\n# ACX_PROG_CC_WARNINGS_ARE_ERRORS([x.y.z], [VARIABLE = WERROR])\n#   sets @VARIABLE@ to \"-Werror\" if the compiler is GCC >=x.y.z, or if\n#   --enable-werror-always was given on the command line, otherwise\n#   to nothing.\n#   If the argument is the word \"manual\" instead of a version number,\n#   then @VARIABLE@ will be set to -Werror only if --enable-werror-always\n#   appeared on the configure command line.\nAC_DEFUN([ACX_PROG_CC_WARNINGS_ARE_ERRORS],\n[AC_REQUIRE([AC_PROG_CC])dnl\nAC_LANG_PUSH(C)\nm4_pushdef([acx_Var], [m4_default([$2], [WERROR])])dnl\nAC_SUBST(acx_Var)dnl\nm4_expand_once([acx_Var=\n],m4_quote(acx_Var=))dnl\nAC_ARG_ENABLE(werror-always, \n    AS_HELP_STRING([--enable-werror-always],\n\t\t   [enable -Werror despite compiler version]),\n[], [enable_werror_always=no])\nAS_IF([test $enable_werror_always = yes],\n      [acx_Var=\"$acx_Var${acx_Var:+ }-Werror\"])\n m4_if($1, [manual],,\n [AS_VAR_PUSHDEF([acx_GCCvers], [acx_cv_prog_cc_gcc_$1_or_newer])dnl\n  AC_CACHE_CHECK([whether $CC is GCC >=$1], acx_GCCvers,\n    [set fnord `echo $1 | tr '.' ' '`\n     shift\n     AC_PREPROC_IFELSE(\n[#if __GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ \\\n  < [$]1 * 10000 + [$]2 * 100 + [$]3\n#error insufficient\n#endif],\n   [AS_VAR_SET(acx_GCCvers, yes)],\n   [AS_VAR_SET(acx_GCCvers, no)])])\n AS_IF([test AS_VAR_GET(acx_GCCvers) = yes],\n       [acx_Var=\"$acx_Var${acx_Var:+ }-Werror\"])\n  AS_VAR_POPDEF([acx_GCCvers])])\nm4_popdef([acx_Var])dnl\nAC_LANG_POP(C)\n])# ACX_PROG_CC_WARNINGS_ARE_ERRORS\n\n# ACX_PROG_CXX_WARNING_OPTS(WARNINGS, [VARIABLE = WARN_CXXFLAGS])\n#   Sets @VARIABLE@ to the subset of the given options which the\n#   compiler accepts.\nAC_DEFUN([ACX_PROG_CXX_WARNING_OPTS],\n[AC_REQUIRE([AC_PROG_CXX])dnl\nAC_LANG_PUSH(C++)\nm4_pushdef([acx_Var], [m4_default([$2], [WARN_CXXFLAGS])])dnl\nAC_SUBST(acx_Var)dnl\nm4_expand_once([acx_Var=\n],m4_quote(acx_Var=))dnl\nsave_CXXFLAGS=\"$CXXFLAGS\"\nfor real_option in $1; do\n  # Do the check with the no- prefix removed since gcc silently\n  # accepts any -Wno-* option on purpose\n  case $real_option in\n    -Wno-*) option=-W`expr x$real_option : 'x-Wno-\\(.*\\)'` ;;\n    *) option=$real_option ;;\n  esac\n  AS_VAR_PUSHDEF([acx_Woption], [acx_cv_prog_cc_warning_$option])\n  AC_CACHE_CHECK([whether $CXX supports $option], acx_Woption,\n    [CXXFLAGS=\"$option\"\n    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],[])],\n      [AS_VAR_SET(acx_Woption, yes)],\n      [AS_VAR_SET(acx_Woption, no)])\n  ])\n  AS_IF([test AS_VAR_GET(acx_Woption) = yes],\n        [acx_Var=\"$acx_Var${acx_Var:+ }$real_option\"])\n  AS_VAR_POPDEF([acx_Woption])dnl\ndone\nCXXFLAGS=\"$save_CXXFLAGS\"\nm4_popdef([acx_Var])dnl\nAC_LANG_POP(C++)\n])# ACX_PROG_CXX_WARNING_OPTS\n\n# ACX_PROG_CXX_WARNING_ALMOST_PEDANTIC(WARNINGS, [VARIABLE = WARN_PEDANTIC])\n#   Append to VARIABLE \"-pedantic\" + the argument, if the compiler is G++\n#   and accepts all of those options simultaneously, otherwise to nothing.\nAC_DEFUN([ACX_PROG_CXX_WARNING_ALMOST_PEDANTIC],\n[AC_REQUIRE([AC_PROG_CXX])dnl\nAC_LANG_PUSH(C++)\nm4_pushdef([acx_Var], [m4_default([$2], [WARN_PEDANTIC])])dnl\nAC_SUBST(acx_Var)dnl\nm4_expand_once([acx_Var=\n],m4_quote(acx_Var=))dnl\n# Do the check with the no- prefix removed from the warning options\n# since gcc silently accepts any -Wno-* option on purpose\nm4_pushdef([acx_Woptions], [m4_bpatsubst([$1], [-Wno-], [-W])])dnl\nAS_VAR_PUSHDEF([acx_Pedantic], [acx_cv_prog_cc_pedantic_]acx_Woptions)dnl\nAS_IF([test \"$GXX\" = yes],\n[AC_CACHE_CHECK([whether $CXX supports -pedantic ]acx_Woptions, acx_Pedantic,\n[save_CXXFLAGS=\"$CXXFLAGS\"\nCXXFLAGS=\"-pedantic acx_Woptions\"\nAC_COMPILE_IFELSE([AC_LANG_PROGRAM([],[])],\n   [AS_VAR_SET(acx_Pedantic, yes)],\n   [AS_VAR_SET(acx_Pedantic, no)])\nCXXFLAGS=\"$save_CXXFLAGS\"])\nAS_IF([test AS_VAR_GET(acx_Pedantic) = yes],\n      [acx_Var=\"$acx_Var${acx_Var:+ }-pedantic $1\"])\n])\nAS_VAR_POPDEF([acx_Pedantic])dnl\nm4_popdef([acx_Woptions])dnl\nm4_popdef([acx_Var])dnl\nAC_LANG_POP(C++)\n])# ACX_PROG_CXX_WARNING_ALMOST_PEDANTIC\n\n# ACX_PROG_CXX_WARNINGS_ARE_ERRORS([x.y.z], [VARIABLE = WERROR])\n#   sets @VARIABLE@ to \"-Werror\" if the compiler is G++ >=x.y.z, or if\n#   --enable-werror-always was given on the command line, otherwise\n#   to nothing.\n#   If the argument is the word \"manual\" instead of a version number,\n#   then @VARIABLE@ will be set to -Werror only if --enable-werror-always\n#   appeared on the configure command line.\nAC_DEFUN([ACX_PROG_CXX_WARNINGS_ARE_ERRORS],\n[AC_REQUIRE([AC_PROG_CXX])dnl\nAC_LANG_PUSH(C++)\nm4_pushdef([acx_Var], [m4_default([$2], [WERROR])])dnl\nAC_SUBST(acx_Var)dnl\nm4_expand_once([acx_Var=\n],m4_quote(acx_Var=))dnl\nAC_ARG_ENABLE(werror-always,\n    AS_HELP_STRING([--enable-werror-always],\n\t\t   [enable -Werror despite compiler version]),\n[], [enable_werror_always=no])\nAS_IF([test $enable_werror_always = yes],\n      [acx_Var=\"$acx_Var${acx_Var:+ }-Werror\"])\n m4_if($1, [manual],,\n [AS_VAR_PUSHDEF([acx_GXXvers], [acx_cv_prog_cxx_gxx_$1_or_newer])dnl\n  AC_CACHE_CHECK([whether $CXX is G++ >=$1], acx_GXXvers,\n    [set fnord `echo $1 | tr '.' ' '`\n     shift\n     AC_PREPROC_IFELSE(\n[#if __GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ \\\n  < [$]1 * 10000 + [$]2 * 100 + [$]3\n#error insufficient\n#endif],\n   [AS_VAR_SET(acx_GXXvers, yes)],\n   [AS_VAR_SET(acx_GXXvers, no)])])\n AS_IF([test AS_VAR_GET(acx_GXXvers) = yes],\n       [acx_Var=\"$acx_Var${acx_Var:+ }-Werror\"])\n  AS_VAR_POPDEF([acx_GXXvers])])\nm4_popdef([acx_Var])dnl\nAC_LANG_POP(C++)\n])# ACX_PROG_CXX_WARNINGS_ARE_ERRORS\n"
  },
  {
    "path": "src/vendor/libbacktrace/config.guess",
    "content": "#! /bin/sh\n# Attempt to guess a canonical system name.\n#   Copyright 1992-2021 Free Software Foundation, Inc.\n\ntimestamp='2021-01-25'\n\n# This file is free software; you can redistribute it and/or modify it\n# under the terms of the GNU General Public License as published by\n# the Free Software Foundation; either version 3 of the License, or\n# (at your option) any later version.\n#\n# This program is distributed in the hope that it will be useful, but\n# WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n# General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with this program; if not, see <https://www.gnu.org/licenses/>.\n#\n# As a special exception to the GNU General Public License, if you\n# distribute this file as part of a program that contains a\n# configuration script generated by Autoconf, you may include it under\n# the same distribution terms that you use for the rest of that\n# program.  This Exception is an additional permission under section 7\n# of the GNU General Public License, version 3 (\"GPLv3\").\n#\n# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.\n#\n# You can get the latest version of this script from:\n# https://git.savannah.gnu.org/cgit/config.git/plain/config.guess\n#\n# Please send patches to <config-patches@gnu.org>.\n\n\nme=$(echo \"$0\" | sed -e 's,.*/,,')\n\nusage=\"\\\nUsage: $0 [OPTION]\n\nOutput the configuration name of the system \\`$me' is run on.\n\nOptions:\n  -h, --help         print this help, then exit\n  -t, --time-stamp   print date of last modification, then exit\n  -v, --version      print version number, then exit\n\nReport bugs and patches to <config-patches@gnu.org>.\"\n\nversion=\"\\\nGNU config.guess ($timestamp)\n\nOriginally written by Per Bothner.\nCopyright 1992-2021 Free Software Foundation, Inc.\n\nThis is free software; see the source for copying conditions.  There is NO\nwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\"\n\nhelp=\"\nTry \\`$me --help' for more information.\"\n\n# Parse command line\nwhile test $# -gt 0 ; do\n  case $1 in\n    --time-stamp | --time* | -t )\n       echo \"$timestamp\" ; exit ;;\n    --version | -v )\n       echo \"$version\" ; exit ;;\n    --help | --h* | -h )\n       echo \"$usage\"; exit ;;\n    -- )     # Stop option processing\n       shift; break ;;\n    - )\t# Use stdin as input.\n       break ;;\n    -* )\n       echo \"$me: invalid option $1$help\" >&2\n       exit 1 ;;\n    * )\n       break ;;\n  esac\ndone\n\nif test $# != 0; then\n  echo \"$me: too many arguments$help\" >&2\n  exit 1\nfi\n\n# CC_FOR_BUILD -- compiler used by this script. Note that the use of a\n# compiler to aid in system detection is discouraged as it requires\n# temporary files to be created and, as you can see below, it is a\n# headache to deal with in a portable fashion.\n\n# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still\n# use `HOST_CC' if defined, but it is deprecated.\n\n# Portable tmp directory creation inspired by the Autoconf team.\n\ntmp=\n# shellcheck disable=SC2172\ntrap 'test -z \"$tmp\" || rm -fr \"$tmp\"' 0 1 2 13 15\n\nset_cc_for_build() {\n    # prevent multiple calls if $tmp is already set\n    test \"$tmp\" && return 0\n    : \"${TMPDIR=/tmp}\"\n    # shellcheck disable=SC2039\n    { tmp=$( (umask 077 && mktemp -d \"$TMPDIR/cgXXXXXX\") 2>/dev/null) && test -n \"$tmp\" && test -d \"$tmp\" ; } ||\n\t{ test -n \"$RANDOM\" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir \"$tmp\" 2>/dev/null) ; } ||\n\t{ tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir \"$tmp\" 2>/dev/null) && echo \"Warning: creating insecure temp directory\" >&2 ; } ||\n\t{ echo \"$me: cannot create a temporary directory in $TMPDIR\" >&2 ; exit 1 ; }\n    dummy=$tmp/dummy\n    case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in\n\t,,)    echo \"int x;\" > \"$dummy.c\"\n\t       for driver in cc gcc c89 c99 ; do\n\t\t   if ($driver -c -o \"$dummy.o\" \"$dummy.c\") >/dev/null 2>&1 ; then\n\t\t       CC_FOR_BUILD=\"$driver\"\n\t\t       break\n\t\t   fi\n\t       done\n\t       if test x\"$CC_FOR_BUILD\" = x ; then\n\t\t   CC_FOR_BUILD=no_compiler_found\n\t       fi\n\t       ;;\n\t,,*)   CC_FOR_BUILD=$CC ;;\n\t,*,*)  CC_FOR_BUILD=$HOST_CC ;;\n    esac\n}\n\n# This is needed to find uname on a Pyramid OSx when run in the BSD universe.\n# (ghazi@noc.rutgers.edu 1994-08-24)\nif test -f /.attbin/uname ; then\n\tPATH=$PATH:/.attbin ; export PATH\nfi\n\nUNAME_MACHINE=$( (uname -m) 2>/dev/null) || UNAME_MACHINE=unknown\nUNAME_RELEASE=$( (uname -r) 2>/dev/null) || UNAME_RELEASE=unknown\nUNAME_SYSTEM=$( (uname -s) 2>/dev/null) || UNAME_SYSTEM=unknown\nUNAME_VERSION=$( (uname -v) 2>/dev/null) || UNAME_VERSION=unknown\n\ncase \"$UNAME_SYSTEM\" in\nLinux|GNU|GNU/*)\n\tLIBC=unknown\n\n\tset_cc_for_build\n\tcat <<-EOF > \"$dummy.c\"\n\t#include <features.h>\n\t#if defined(__UCLIBC__)\n\tLIBC=uclibc\n\t#elif defined(__dietlibc__)\n\tLIBC=dietlibc\n\t#elif defined(__GLIBC__)\n\tLIBC=gnu\n\t#else\n\t#include <stdarg.h>\n\t/* First heuristic to detect musl libc.  */\n\t#ifdef __DEFINED_va_list\n\tLIBC=musl\n\t#endif\n\t#endif\n\tEOF\n\teval \"$($CC_FOR_BUILD -E \"$dummy.c\" 2>/dev/null | grep '^LIBC' | sed 's, ,,g')\"\n\n\t# Second heuristic to detect musl libc.\n\tif [ \"$LIBC\" = unknown ] &&\n\t   command -v ldd >/dev/null &&\n\t   ldd --version 2>&1 | grep -q ^musl; then\n\t\tLIBC=musl\n\tfi\n\n\t# If the system lacks a compiler, then just pick glibc.\n\t# We could probably try harder.\n\tif [ \"$LIBC\" = unknown ]; then\n\t\tLIBC=gnu\n\tfi\n\t;;\nesac\n\n# Note: order is significant - the case branches are not exclusive.\n\ncase \"$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION\" in\n    *:NetBSD:*:*)\n\t# NetBSD (nbsd) targets should (where applicable) match one or\n\t# more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,\n\t# *-*-netbsdecoff* and *-*-netbsd*.  For targets that recently\n\t# switched to ELF, *-*-netbsd* would select the old\n\t# object file format.  This provides both forward\n\t# compatibility and a consistent mechanism for selecting the\n\t# object file format.\n\t#\n\t# Note: NetBSD doesn't particularly care about the vendor\n\t# portion of the name.  We always set it to \"unknown\".\n\tUNAME_MACHINE_ARCH=$( (uname -p 2>/dev/null || \\\n\t    /sbin/sysctl -n hw.machine_arch 2>/dev/null || \\\n\t    /usr/sbin/sysctl -n hw.machine_arch 2>/dev/null || \\\n\t    echo unknown))\n\tcase \"$UNAME_MACHINE_ARCH\" in\n\t    aarch64eb) machine=aarch64_be-unknown ;;\n\t    armeb) machine=armeb-unknown ;;\n\t    arm*) machine=arm-unknown ;;\n\t    sh3el) machine=shl-unknown ;;\n\t    sh3eb) machine=sh-unknown ;;\n\t    sh5el) machine=sh5le-unknown ;;\n\t    earmv*)\n\t\tarch=$(echo \"$UNAME_MACHINE_ARCH\" | sed -e 's,^e\\(armv[0-9]\\).*$,\\1,')\n\t\tendian=$(echo \"$UNAME_MACHINE_ARCH\" | sed -ne 's,^.*\\(eb\\)$,\\1,p')\n\t\tmachine=\"${arch}${endian}\"-unknown\n\t\t;;\n\t    *) machine=\"$UNAME_MACHINE_ARCH\"-unknown ;;\n\tesac\n\t# The Operating System including object format, if it has switched\n\t# to ELF recently (or will in the future) and ABI.\n\tcase \"$UNAME_MACHINE_ARCH\" in\n\t    earm*)\n\t\tos=netbsdelf\n\t\t;;\n\t    arm*|i386|m68k|ns32k|sh3*|sparc|vax)\n\t\tset_cc_for_build\n\t\tif echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \\\n\t\t\t| grep -q __ELF__\n\t\tthen\n\t\t    # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).\n\t\t    # Return netbsd for either.  FIX?\n\t\t    os=netbsd\n\t\telse\n\t\t    os=netbsdelf\n\t\tfi\n\t\t;;\n\t    *)\n\t\tos=netbsd\n\t\t;;\n\tesac\n\t# Determine ABI tags.\n\tcase \"$UNAME_MACHINE_ARCH\" in\n\t    earm*)\n\t\texpr='s/^earmv[0-9]/-eabi/;s/eb$//'\n\t\tabi=$(echo \"$UNAME_MACHINE_ARCH\" | sed -e \"$expr\")\n\t\t;;\n\tesac\n\t# The OS release\n\t# Debian GNU/NetBSD machines have a different userland, and\n\t# thus, need a distinct triplet. However, they do not need\n\t# kernel version information, so it can be replaced with a\n\t# suitable tag, in the style of linux-gnu.\n\tcase \"$UNAME_VERSION\" in\n\t    Debian*)\n\t\trelease='-gnu'\n\t\t;;\n\t    *)\n\t\trelease=$(echo \"$UNAME_RELEASE\" | sed -e 's/[-_].*//' | cut -d. -f1,2)\n\t\t;;\n\tesac\n\t# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:\n\t# contains redundant information, the shorter form:\n\t# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.\n\techo \"$machine-${os}${release}${abi-}\"\n\texit ;;\n    *:Bitrig:*:*)\n\tUNAME_MACHINE_ARCH=$(arch | sed 's/Bitrig.//')\n\techo \"$UNAME_MACHINE_ARCH\"-unknown-bitrig\"$UNAME_RELEASE\"\n\texit ;;\n    *:OpenBSD:*:*)\n\tUNAME_MACHINE_ARCH=$(arch | sed 's/OpenBSD.//')\n\techo \"$UNAME_MACHINE_ARCH\"-unknown-openbsd\"$UNAME_RELEASE\"\n\texit ;;\n    *:LibertyBSD:*:*)\n\tUNAME_MACHINE_ARCH=$(arch | sed 's/^.*BSD\\.//')\n\techo \"$UNAME_MACHINE_ARCH\"-unknown-libertybsd\"$UNAME_RELEASE\"\n\texit ;;\n    *:MidnightBSD:*:*)\n\techo \"$UNAME_MACHINE\"-unknown-midnightbsd\"$UNAME_RELEASE\"\n\texit ;;\n    *:ekkoBSD:*:*)\n\techo \"$UNAME_MACHINE\"-unknown-ekkobsd\"$UNAME_RELEASE\"\n\texit ;;\n    *:SolidBSD:*:*)\n\techo \"$UNAME_MACHINE\"-unknown-solidbsd\"$UNAME_RELEASE\"\n\texit ;;\n    *:OS108:*:*)\n\techo \"$UNAME_MACHINE\"-unknown-os108_\"$UNAME_RELEASE\"\n\texit ;;\n    macppc:MirBSD:*:*)\n\techo powerpc-unknown-mirbsd\"$UNAME_RELEASE\"\n\texit ;;\n    *:MirBSD:*:*)\n\techo \"$UNAME_MACHINE\"-unknown-mirbsd\"$UNAME_RELEASE\"\n\texit ;;\n    *:Sortix:*:*)\n\techo \"$UNAME_MACHINE\"-unknown-sortix\n\texit ;;\n    *:Twizzler:*:*)\n\techo \"$UNAME_MACHINE\"-unknown-twizzler\n\texit ;;\n    *:Redox:*:*)\n\techo \"$UNAME_MACHINE\"-unknown-redox\n\texit ;;\n    mips:OSF1:*.*)\n\techo mips-dec-osf1\n\texit ;;\n    alpha:OSF1:*:*)\n\tcase $UNAME_RELEASE in\n\t*4.0)\n\t\tUNAME_RELEASE=$(/usr/sbin/sizer -v | awk '{print $3}')\n\t\t;;\n\t*5.*)\n\t\tUNAME_RELEASE=$(/usr/sbin/sizer -v | awk '{print $4}')\n\t\t;;\n\tesac\n\t# According to Compaq, /usr/sbin/psrinfo has been available on\n\t# OSF/1 and Tru64 systems produced since 1995.  I hope that\n\t# covers most systems running today.  This code pipes the CPU\n\t# types through head -n 1, so we only detect the type of CPU 0.\n\tALPHA_CPU_TYPE=$(/usr/sbin/psrinfo -v | sed -n -e 's/^  The alpha \\(.*\\) processor.*$/\\1/p' | head -n 1)\n\tcase \"$ALPHA_CPU_TYPE\" in\n\t    \"EV4 (21064)\")\n\t\tUNAME_MACHINE=alpha ;;\n\t    \"EV4.5 (21064)\")\n\t\tUNAME_MACHINE=alpha ;;\n\t    \"LCA4 (21066/21068)\")\n\t\tUNAME_MACHINE=alpha ;;\n\t    \"EV5 (21164)\")\n\t\tUNAME_MACHINE=alphaev5 ;;\n\t    \"EV5.6 (21164A)\")\n\t\tUNAME_MACHINE=alphaev56 ;;\n\t    \"EV5.6 (21164PC)\")\n\t\tUNAME_MACHINE=alphapca56 ;;\n\t    \"EV5.7 (21164PC)\")\n\t\tUNAME_MACHINE=alphapca57 ;;\n\t    \"EV6 (21264)\")\n\t\tUNAME_MACHINE=alphaev6 ;;\n\t    \"EV6.7 (21264A)\")\n\t\tUNAME_MACHINE=alphaev67 ;;\n\t    \"EV6.8CB (21264C)\")\n\t\tUNAME_MACHINE=alphaev68 ;;\n\t    \"EV6.8AL (21264B)\")\n\t\tUNAME_MACHINE=alphaev68 ;;\n\t    \"EV6.8CX (21264D)\")\n\t\tUNAME_MACHINE=alphaev68 ;;\n\t    \"EV6.9A (21264/EV69A)\")\n\t\tUNAME_MACHINE=alphaev69 ;;\n\t    \"EV7 (21364)\")\n\t\tUNAME_MACHINE=alphaev7 ;;\n\t    \"EV7.9 (21364A)\")\n\t\tUNAME_MACHINE=alphaev79 ;;\n\tesac\n\t# A Pn.n version is a patched version.\n\t# A Vn.n version is a released version.\n\t# A Tn.n version is a released field test version.\n\t# A Xn.n version is an unreleased experimental baselevel.\n\t# 1.2 uses \"1.2\" for uname -r.\n\techo \"$UNAME_MACHINE\"-dec-osf\"$(echo \"$UNAME_RELEASE\" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz)\"\n\t# Reset EXIT trap before exiting to avoid spurious non-zero exit code.\n\texitcode=$?\n\ttrap '' 0\n\texit $exitcode ;;\n    Amiga*:UNIX_System_V:4.0:*)\n\techo m68k-unknown-sysv4\n\texit ;;\n    *:[Aa]miga[Oo][Ss]:*:*)\n\techo \"$UNAME_MACHINE\"-unknown-amigaos\n\texit ;;\n    *:[Mm]orph[Oo][Ss]:*:*)\n\techo \"$UNAME_MACHINE\"-unknown-morphos\n\texit ;;\n    *:OS/390:*:*)\n\techo i370-ibm-openedition\n\texit ;;\n    *:z/VM:*:*)\n\techo s390-ibm-zvmoe\n\texit ;;\n    *:OS400:*:*)\n\techo powerpc-ibm-os400\n\texit ;;\n    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)\n\techo arm-acorn-riscix\"$UNAME_RELEASE\"\n\texit ;;\n    arm*:riscos:*:*|arm*:RISCOS:*:*)\n\techo arm-unknown-riscos\n\texit ;;\n    SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)\n\techo hppa1.1-hitachi-hiuxmpp\n\texit ;;\n    Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)\n\t# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.\n\tif test \"$( (/bin/universe) 2>/dev/null)\" = att ; then\n\t\techo pyramid-pyramid-sysv3\n\telse\n\t\techo pyramid-pyramid-bsd\n\tfi\n\texit ;;\n    NILE*:*:*:dcosx)\n\techo pyramid-pyramid-svr4\n\texit ;;\n    DRS?6000:unix:4.0:6*)\n\techo sparc-icl-nx6\n\texit ;;\n    DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)\n\tcase $(/usr/bin/uname -p) in\n\t    sparc) echo sparc-icl-nx7; exit ;;\n\tesac ;;\n    s390x:SunOS:*:*)\n\techo \"$UNAME_MACHINE\"-ibm-solaris2\"$(echo \"$UNAME_RELEASE\" | sed -e 's/[^.]*//')\"\n\texit ;;\n    sun4H:SunOS:5.*:*)\n\techo sparc-hal-solaris2\"$(echo \"$UNAME_RELEASE\"|sed -e 's/[^.]*//')\"\n\texit ;;\n    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)\n\techo sparc-sun-solaris2\"$(echo \"$UNAME_RELEASE\" | sed -e 's/[^.]*//')\"\n\texit ;;\n    i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)\n\techo i386-pc-auroraux\"$UNAME_RELEASE\"\n\texit ;;\n    i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)\n\tset_cc_for_build\n\tSUN_ARCH=i386\n\t# If there is a compiler, see if it is configured for 64-bit objects.\n\t# Note that the Sun cc does not turn __LP64__ into 1 like gcc does.\n\t# This test works for both compilers.\n\tif test \"$CC_FOR_BUILD\" != no_compiler_found; then\n\t    if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \\\n\t\t(CCOPTS=\"\" $CC_FOR_BUILD -E - 2>/dev/null) | \\\n\t\tgrep IS_64BIT_ARCH >/dev/null\n\t    then\n\t\tSUN_ARCH=x86_64\n\t    fi\n\tfi\n\techo \"$SUN_ARCH\"-pc-solaris2\"$(echo \"$UNAME_RELEASE\"|sed -e 's/[^.]*//')\"\n\texit ;;\n    sun4*:SunOS:6*:*)\n\t# According to config.sub, this is the proper way to canonicalize\n\t# SunOS6.  Hard to guess exactly what SunOS6 will be like, but\n\t# it's likely to be more like Solaris than SunOS4.\n\techo sparc-sun-solaris3\"$(echo \"$UNAME_RELEASE\"|sed -e 's/[^.]*//')\"\n\texit ;;\n    sun4*:SunOS:*:*)\n\tcase \"$(/usr/bin/arch -k)\" in\n\t    Series*|S4*)\n\t\tUNAME_RELEASE=$(uname -v)\n\t\t;;\n\tesac\n\t# Japanese Language versions have a version number like `4.1.3-JL'.\n\techo sparc-sun-sunos\"$(echo \"$UNAME_RELEASE\"|sed -e 's/-/_/')\"\n\texit ;;\n    sun3*:SunOS:*:*)\n\techo m68k-sun-sunos\"$UNAME_RELEASE\"\n\texit ;;\n    sun*:*:4.2BSD:*)\n\tUNAME_RELEASE=$( (sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null)\n\ttest \"x$UNAME_RELEASE\" = x && UNAME_RELEASE=3\n\tcase \"$(/bin/arch)\" in\n\t    sun3)\n\t\techo m68k-sun-sunos\"$UNAME_RELEASE\"\n\t\t;;\n\t    sun4)\n\t\techo sparc-sun-sunos\"$UNAME_RELEASE\"\n\t\t;;\n\tesac\n\texit ;;\n    aushp:SunOS:*:*)\n\techo sparc-auspex-sunos\"$UNAME_RELEASE\"\n\texit ;;\n    # The situation for MiNT is a little confusing.  The machine name\n    # can be virtually everything (everything which is not\n    # \"atarist\" or \"atariste\" at least should have a processor\n    # > m68000).  The system name ranges from \"MiNT\" over \"FreeMiNT\"\n    # to the lowercase version \"mint\" (or \"freemint\").  Finally\n    # the system name \"TOS\" denotes a system which is actually not\n    # MiNT.  But MiNT is downward compatible to TOS, so this should\n    # be no problem.\n    atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)\n\techo m68k-atari-mint\"$UNAME_RELEASE\"\n\texit ;;\n    atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)\n\techo m68k-atari-mint\"$UNAME_RELEASE\"\n\texit ;;\n    *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)\n\techo m68k-atari-mint\"$UNAME_RELEASE\"\n\texit ;;\n    milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)\n\techo m68k-milan-mint\"$UNAME_RELEASE\"\n\texit ;;\n    hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)\n\techo m68k-hades-mint\"$UNAME_RELEASE\"\n\texit ;;\n    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)\n\techo m68k-unknown-mint\"$UNAME_RELEASE\"\n\texit ;;\n    m68k:machten:*:*)\n\techo m68k-apple-machten\"$UNAME_RELEASE\"\n\texit ;;\n    powerpc:machten:*:*)\n\techo powerpc-apple-machten\"$UNAME_RELEASE\"\n\texit ;;\n    RISC*:Mach:*:*)\n\techo mips-dec-mach_bsd4.3\n\texit ;;\n    RISC*:ULTRIX:*:*)\n\techo mips-dec-ultrix\"$UNAME_RELEASE\"\n\texit ;;\n    VAX*:ULTRIX*:*:*)\n\techo vax-dec-ultrix\"$UNAME_RELEASE\"\n\texit ;;\n    2020:CLIX:*:* | 2430:CLIX:*:*)\n\techo clipper-intergraph-clix\"$UNAME_RELEASE\"\n\texit ;;\n    mips:*:*:UMIPS | mips:*:*:RISCos)\n\tset_cc_for_build\n\tsed 's/^\t//' << EOF > \"$dummy.c\"\n#ifdef __cplusplus\n#include <stdio.h>  /* for printf() prototype */\n\tint main (int argc, char *argv[]) {\n#else\n\tint main (argc, argv) int argc; char *argv[]; {\n#endif\n\t#if defined (host_mips) && defined (MIPSEB)\n\t#if defined (SYSTYPE_SYSV)\n\t  printf (\"mips-mips-riscos%ssysv\\\\n\", argv[1]); exit (0);\n\t#endif\n\t#if defined (SYSTYPE_SVR4)\n\t  printf (\"mips-mips-riscos%ssvr4\\\\n\", argv[1]); exit (0);\n\t#endif\n\t#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)\n\t  printf (\"mips-mips-riscos%sbsd\\\\n\", argv[1]); exit (0);\n\t#endif\n\t#endif\n\t  exit (-1);\n\t}\nEOF\n\t$CC_FOR_BUILD -o \"$dummy\" \"$dummy.c\" &&\n\t  dummyarg=$(echo \"$UNAME_RELEASE\" | sed -n 's/\\([0-9]*\\).*/\\1/p') &&\n\t  SYSTEM_NAME=$(\"$dummy\" \"$dummyarg\") &&\n\t    { echo \"$SYSTEM_NAME\"; exit; }\n\techo mips-mips-riscos\"$UNAME_RELEASE\"\n\texit ;;\n    Motorola:PowerMAX_OS:*:*)\n\techo powerpc-motorola-powermax\n\texit ;;\n    Motorola:*:4.3:PL8-*)\n\techo powerpc-harris-powermax\n\texit ;;\n    Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)\n\techo powerpc-harris-powermax\n\texit ;;\n    Night_Hawk:Power_UNIX:*:*)\n\techo powerpc-harris-powerunix\n\texit ;;\n    m88k:CX/UX:7*:*)\n\techo m88k-harris-cxux7\n\texit ;;\n    m88k:*:4*:R4*)\n\techo m88k-motorola-sysv4\n\texit ;;\n    m88k:*:3*:R3*)\n\techo m88k-motorola-sysv3\n\texit ;;\n    AViiON:dgux:*:*)\n\t# DG/UX returns AViiON for all architectures\n\tUNAME_PROCESSOR=$(/usr/bin/uname -p)\n\tif test \"$UNAME_PROCESSOR\" = mc88100 || test \"$UNAME_PROCESSOR\" = mc88110\n\tthen\n\t    if test \"$TARGET_BINARY_INTERFACE\"x = m88kdguxelfx || \\\n\t       test \"$TARGET_BINARY_INTERFACE\"x = x\n\t    then\n\t\techo m88k-dg-dgux\"$UNAME_RELEASE\"\n\t    else\n\t\techo m88k-dg-dguxbcs\"$UNAME_RELEASE\"\n\t    fi\n\telse\n\t    echo i586-dg-dgux\"$UNAME_RELEASE\"\n\tfi\n\texit ;;\n    M88*:DolphinOS:*:*)\t# DolphinOS (SVR3)\n\techo m88k-dolphin-sysv3\n\texit ;;\n    M88*:*:R3*:*)\n\t# Delta 88k system running SVR3\n\techo m88k-motorola-sysv3\n\texit ;;\n    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)\n\techo m88k-tektronix-sysv3\n\texit ;;\n    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)\n\techo m68k-tektronix-bsd\n\texit ;;\n    *:IRIX*:*:*)\n\techo mips-sgi-irix\"$(echo \"$UNAME_RELEASE\"|sed -e 's/-/_/g')\"\n\texit ;;\n    ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.\n\techo romp-ibm-aix     # uname -m gives an 8 hex-code CPU id\n\texit ;;               # Note that: echo \"'$(uname -s)'\" gives 'AIX '\n    i*86:AIX:*:*)\n\techo i386-ibm-aix\n\texit ;;\n    ia64:AIX:*:*)\n\tif test -x /usr/bin/oslevel ; then\n\t\tIBM_REV=$(/usr/bin/oslevel)\n\telse\n\t\tIBM_REV=\"$UNAME_VERSION.$UNAME_RELEASE\"\n\tfi\n\techo \"$UNAME_MACHINE\"-ibm-aix\"$IBM_REV\"\n\texit ;;\n    *:AIX:2:3)\n\tif grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then\n\t\tset_cc_for_build\n\t\tsed 's/^\t\t//' << EOF > \"$dummy.c\"\n\t\t#include <sys/systemcfg.h>\n\n\t\tmain()\n\t\t\t{\n\t\t\tif (!__power_pc())\n\t\t\t\texit(1);\n\t\t\tputs(\"powerpc-ibm-aix3.2.5\");\n\t\t\texit(0);\n\t\t\t}\nEOF\n\t\tif $CC_FOR_BUILD -o \"$dummy\" \"$dummy.c\" && SYSTEM_NAME=$(\"$dummy\")\n\t\tthen\n\t\t\techo \"$SYSTEM_NAME\"\n\t\telse\n\t\t\techo rs6000-ibm-aix3.2.5\n\t\tfi\n\telif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then\n\t\techo rs6000-ibm-aix3.2.4\n\telse\n\t\techo rs6000-ibm-aix3.2\n\tfi\n\texit ;;\n    *:AIX:*:[4567])\n\tIBM_CPU_ID=$(/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }')\n\tif /usr/sbin/lsattr -El \"$IBM_CPU_ID\" | grep ' POWER' >/dev/null 2>&1; then\n\t\tIBM_ARCH=rs6000\n\telse\n\t\tIBM_ARCH=powerpc\n\tfi\n\tif test -x /usr/bin/lslpp ; then\n\t\tIBM_REV=$(/usr/bin/lslpp -Lqc bos.rte.libc |\n\t\t\t   awk -F: '{ print $3 }' | sed s/[0-9]*$/0/)\n\telse\n\t\tIBM_REV=\"$UNAME_VERSION.$UNAME_RELEASE\"\n\tfi\n\techo \"$IBM_ARCH\"-ibm-aix\"$IBM_REV\"\n\texit ;;\n    *:AIX:*:*)\n\techo rs6000-ibm-aix\n\texit ;;\n    ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*)\n\techo romp-ibm-bsd4.4\n\texit ;;\n    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and\n\techo romp-ibm-bsd\"$UNAME_RELEASE\"   # 4.3 with uname added to\n\texit ;;                             # report: romp-ibm BSD 4.3\n    *:BOSX:*:*)\n\techo rs6000-bull-bosx\n\texit ;;\n    DPX/2?00:B.O.S.:*:*)\n\techo m68k-bull-sysv3\n\texit ;;\n    9000/[34]??:4.3bsd:1.*:*)\n\techo m68k-hp-bsd\n\texit ;;\n    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)\n\techo m68k-hp-bsd4.4\n\texit ;;\n    9000/[34678]??:HP-UX:*:*)\n\tHPUX_REV=$(echo \"$UNAME_RELEASE\"|sed -e 's/[^.]*.[0B]*//')\n\tcase \"$UNAME_MACHINE\" in\n\t    9000/31?)            HP_ARCH=m68000 ;;\n\t    9000/[34]??)         HP_ARCH=m68k ;;\n\t    9000/[678][0-9][0-9])\n\t\tif test -x /usr/bin/getconf; then\n\t\t    sc_cpu_version=$(/usr/bin/getconf SC_CPU_VERSION 2>/dev/null)\n\t\t    sc_kernel_bits=$(/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null)\n\t\t    case \"$sc_cpu_version\" in\n\t\t      523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0\n\t\t      528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1\n\t\t      532)                      # CPU_PA_RISC2_0\n\t\t\tcase \"$sc_kernel_bits\" in\n\t\t\t  32) HP_ARCH=hppa2.0n ;;\n\t\t\t  64) HP_ARCH=hppa2.0w ;;\n\t\t\t  '') HP_ARCH=hppa2.0 ;;   # HP-UX 10.20\n\t\t\tesac ;;\n\t\t    esac\n\t\tfi\n\t\tif test \"$HP_ARCH\" = \"\"; then\n\t\t    set_cc_for_build\n\t\t    sed 's/^\t\t//' << EOF > \"$dummy.c\"\n\n\t\t#define _HPUX_SOURCE\n\t\t#include <stdlib.h>\n\t\t#include <unistd.h>\n\n\t\tint main ()\n\t\t{\n\t\t#if defined(_SC_KERNEL_BITS)\n\t\t    long bits = sysconf(_SC_KERNEL_BITS);\n\t\t#endif\n\t\t    long cpu  = sysconf (_SC_CPU_VERSION);\n\n\t\t    switch (cpu)\n\t\t\t{\n\t\t\tcase CPU_PA_RISC1_0: puts (\"hppa1.0\"); break;\n\t\t\tcase CPU_PA_RISC1_1: puts (\"hppa1.1\"); break;\n\t\t\tcase CPU_PA_RISC2_0:\n\t\t#if defined(_SC_KERNEL_BITS)\n\t\t\t    switch (bits)\n\t\t\t\t{\n\t\t\t\tcase 64: puts (\"hppa2.0w\"); break;\n\t\t\t\tcase 32: puts (\"hppa2.0n\"); break;\n\t\t\t\tdefault: puts (\"hppa2.0\"); break;\n\t\t\t\t} break;\n\t\t#else  /* !defined(_SC_KERNEL_BITS) */\n\t\t\t    puts (\"hppa2.0\"); break;\n\t\t#endif\n\t\t\tdefault: puts (\"hppa1.0\"); break;\n\t\t\t}\n\t\t    exit (0);\n\t\t}\nEOF\n\t\t    (CCOPTS=\"\" $CC_FOR_BUILD -o \"$dummy\" \"$dummy.c\" 2>/dev/null) && HP_ARCH=$(\"$dummy\")\n\t\t    test -z \"$HP_ARCH\" && HP_ARCH=hppa\n\t\tfi ;;\n\tesac\n\tif test \"$HP_ARCH\" = hppa2.0w\n\tthen\n\t    set_cc_for_build\n\n\t    # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating\n\t    # 32-bit code.  hppa64-hp-hpux* has the same kernel and a compiler\n\t    # generating 64-bit code.  GNU and HP use different nomenclature:\n\t    #\n\t    # $ CC_FOR_BUILD=cc ./config.guess\n\t    # => hppa2.0w-hp-hpux11.23\n\t    # $ CC_FOR_BUILD=\"cc +DA2.0w\" ./config.guess\n\t    # => hppa64-hp-hpux11.23\n\n\t    if echo __LP64__ | (CCOPTS=\"\" $CC_FOR_BUILD -E - 2>/dev/null) |\n\t\tgrep -q __LP64__\n\t    then\n\t\tHP_ARCH=hppa2.0w\n\t    else\n\t\tHP_ARCH=hppa64\n\t    fi\n\tfi\n\techo \"$HP_ARCH\"-hp-hpux\"$HPUX_REV\"\n\texit ;;\n    ia64:HP-UX:*:*)\n\tHPUX_REV=$(echo \"$UNAME_RELEASE\"|sed -e 's/[^.]*.[0B]*//')\n\techo ia64-hp-hpux\"$HPUX_REV\"\n\texit ;;\n    3050*:HI-UX:*:*)\n\tset_cc_for_build\n\tsed 's/^\t//' << EOF > \"$dummy.c\"\n\t#include <unistd.h>\n\tint\n\tmain ()\n\t{\n\t  long cpu = sysconf (_SC_CPU_VERSION);\n\t  /* The order matters, because CPU_IS_HP_MC68K erroneously returns\n\t     true for CPU_PA_RISC1_0.  CPU_IS_PA_RISC returns correct\n\t     results, however.  */\n\t  if (CPU_IS_PA_RISC (cpu))\n\t    {\n\t      switch (cpu)\n\t\t{\n\t\t  case CPU_PA_RISC1_0: puts (\"hppa1.0-hitachi-hiuxwe2\"); break;\n\t\t  case CPU_PA_RISC1_1: puts (\"hppa1.1-hitachi-hiuxwe2\"); break;\n\t\t  case CPU_PA_RISC2_0: puts (\"hppa2.0-hitachi-hiuxwe2\"); break;\n\t\t  default: puts (\"hppa-hitachi-hiuxwe2\"); break;\n\t\t}\n\t    }\n\t  else if (CPU_IS_HP_MC68K (cpu))\n\t    puts (\"m68k-hitachi-hiuxwe2\");\n\t  else puts (\"unknown-hitachi-hiuxwe2\");\n\t  exit (0);\n\t}\nEOF\n\t$CC_FOR_BUILD -o \"$dummy\" \"$dummy.c\" && SYSTEM_NAME=$(\"$dummy\") &&\n\t\t{ echo \"$SYSTEM_NAME\"; exit; }\n\techo unknown-hitachi-hiuxwe2\n\texit ;;\n    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*)\n\techo hppa1.1-hp-bsd\n\texit ;;\n    9000/8??:4.3bsd:*:*)\n\techo hppa1.0-hp-bsd\n\texit ;;\n    *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)\n\techo hppa1.0-hp-mpeix\n\texit ;;\n    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*)\n\techo hppa1.1-hp-osf\n\texit ;;\n    hp8??:OSF1:*:*)\n\techo hppa1.0-hp-osf\n\texit ;;\n    i*86:OSF1:*:*)\n\tif test -x /usr/sbin/sysversion ; then\n\t    echo \"$UNAME_MACHINE\"-unknown-osf1mk\n\telse\n\t    echo \"$UNAME_MACHINE\"-unknown-osf1\n\tfi\n\texit ;;\n    parisc*:Lites*:*:*)\n\techo hppa1.1-hp-lites\n\texit ;;\n    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)\n\techo c1-convex-bsd\n\texit ;;\n    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)\n\tif getsysinfo -f scalar_acc\n\tthen echo c32-convex-bsd\n\telse echo c2-convex-bsd\n\tfi\n\texit ;;\n    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)\n\techo c34-convex-bsd\n\texit ;;\n    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)\n\techo c38-convex-bsd\n\texit ;;\n    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)\n\techo c4-convex-bsd\n\texit ;;\n    CRAY*Y-MP:*:*:*)\n\techo ymp-cray-unicos\"$UNAME_RELEASE\" | sed -e 's/\\.[^.]*$/.X/'\n\texit ;;\n    CRAY*[A-Z]90:*:*:*)\n\techo \"$UNAME_MACHINE\"-cray-unicos\"$UNAME_RELEASE\" \\\n\t| sed -e 's/CRAY.*\\([A-Z]90\\)/\\1/' \\\n\t      -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \\\n\t      -e 's/\\.[^.]*$/.X/'\n\texit ;;\n    CRAY*TS:*:*:*)\n\techo t90-cray-unicos\"$UNAME_RELEASE\" | sed -e 's/\\.[^.]*$/.X/'\n\texit ;;\n    CRAY*T3E:*:*:*)\n\techo alphaev5-cray-unicosmk\"$UNAME_RELEASE\" | sed -e 's/\\.[^.]*$/.X/'\n\texit ;;\n    CRAY*SV1:*:*:*)\n\techo sv1-cray-unicos\"$UNAME_RELEASE\" | sed -e 's/\\.[^.]*$/.X/'\n\texit ;;\n    *:UNICOS/mp:*:*)\n\techo craynv-cray-unicosmp\"$UNAME_RELEASE\" | sed -e 's/\\.[^.]*$/.X/'\n\texit ;;\n    F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)\n\tFUJITSU_PROC=$(uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz)\n\tFUJITSU_SYS=$(uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\\///')\n\tFUJITSU_REL=$(echo \"$UNAME_RELEASE\" | sed -e 's/ /_/')\n\techo \"${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}\"\n\texit ;;\n    5000:UNIX_System_V:4.*:*)\n\tFUJITSU_SYS=$(uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\\///')\n\tFUJITSU_REL=$(echo \"$UNAME_RELEASE\" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/')\n\techo \"sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}\"\n\texit ;;\n    i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\\ Embedded/OS:*:*)\n\techo \"$UNAME_MACHINE\"-pc-bsdi\"$UNAME_RELEASE\"\n\texit ;;\n    sparc*:BSD/OS:*:*)\n\techo sparc-unknown-bsdi\"$UNAME_RELEASE\"\n\texit ;;\n    *:BSD/OS:*:*)\n\techo \"$UNAME_MACHINE\"-unknown-bsdi\"$UNAME_RELEASE\"\n\texit ;;\n    arm:FreeBSD:*:*)\n\tUNAME_PROCESSOR=$(uname -p)\n\tset_cc_for_build\n\tif echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \\\n\t    | grep -q __ARM_PCS_VFP\n\tthen\n\t    echo \"${UNAME_PROCESSOR}\"-unknown-freebsd\"$(echo ${UNAME_RELEASE}|sed -e 's/[-(].*//')\"-gnueabi\n\telse\n\t    echo \"${UNAME_PROCESSOR}\"-unknown-freebsd\"$(echo ${UNAME_RELEASE}|sed -e 's/[-(].*//')\"-gnueabihf\n\tfi\n\texit ;;\n    *:FreeBSD:*:*)\n\tUNAME_PROCESSOR=$(/usr/bin/uname -p)\n\tcase \"$UNAME_PROCESSOR\" in\n\t    amd64)\n\t\tUNAME_PROCESSOR=x86_64 ;;\n\t    i386)\n\t\tUNAME_PROCESSOR=i586 ;;\n\tesac\n\techo \"$UNAME_PROCESSOR\"-unknown-freebsd\"$(echo \"$UNAME_RELEASE\"|sed -e 's/[-(].*//')\"\n\texit ;;\n    i*:CYGWIN*:*)\n\techo \"$UNAME_MACHINE\"-pc-cygwin\n\texit ;;\n    *:MINGW64*:*)\n\techo \"$UNAME_MACHINE\"-pc-mingw64\n\texit ;;\n    *:MINGW*:*)\n\techo \"$UNAME_MACHINE\"-pc-mingw32\n\texit ;;\n    *:MSYS*:*)\n\techo \"$UNAME_MACHINE\"-pc-msys\n\texit ;;\n    i*:PW*:*)\n\techo \"$UNAME_MACHINE\"-pc-pw32\n\texit ;;\n    *:Interix*:*)\n\tcase \"$UNAME_MACHINE\" in\n\t    x86)\n\t\techo i586-pc-interix\"$UNAME_RELEASE\"\n\t\texit ;;\n\t    authenticamd | genuineintel | EM64T)\n\t\techo x86_64-unknown-interix\"$UNAME_RELEASE\"\n\t\texit ;;\n\t    IA64)\n\t\techo ia64-unknown-interix\"$UNAME_RELEASE\"\n\t\texit ;;\n\tesac ;;\n    i*:UWIN*:*)\n\techo \"$UNAME_MACHINE\"-pc-uwin\n\texit ;;\n    amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)\n\techo x86_64-pc-cygwin\n\texit ;;\n    prep*:SunOS:5.*:*)\n\techo powerpcle-unknown-solaris2\"$(echo \"$UNAME_RELEASE\"|sed -e 's/[^.]*//')\"\n\texit ;;\n    *:GNU:*:*)\n\t# the GNU system\n\techo \"$(echo \"$UNAME_MACHINE\"|sed -e 's,[-/].*$,,')-unknown-$LIBC$(echo \"$UNAME_RELEASE\"|sed -e 's,/.*$,,')\"\n\texit ;;\n    *:GNU/*:*:*)\n\t# other systems with GNU libc and userland\n\techo \"$UNAME_MACHINE-unknown-$(echo \"$UNAME_SYSTEM\" | sed 's,^[^/]*/,,' | tr \"[:upper:]\" \"[:lower:]\")$(echo \"$UNAME_RELEASE\"|sed -e 's/[-(].*//')-$LIBC\"\n\texit ;;\n    *:Minix:*:*)\n\techo \"$UNAME_MACHINE\"-unknown-minix\n\texit ;;\n    aarch64:Linux:*:*)\n\techo \"$UNAME_MACHINE\"-unknown-linux-\"$LIBC\"\n\texit ;;\n    aarch64_be:Linux:*:*)\n\tUNAME_MACHINE=aarch64_be\n\techo \"$UNAME_MACHINE\"-unknown-linux-\"$LIBC\"\n\texit ;;\n    alpha:Linux:*:*)\n\tcase $(sed -n '/^cpu model/s/^.*: \\(.*\\)/\\1/p' /proc/cpuinfo 2>/dev/null) in\n\t  EV5)   UNAME_MACHINE=alphaev5 ;;\n\t  EV56)  UNAME_MACHINE=alphaev56 ;;\n\t  PCA56) UNAME_MACHINE=alphapca56 ;;\n\t  PCA57) UNAME_MACHINE=alphapca56 ;;\n\t  EV6)   UNAME_MACHINE=alphaev6 ;;\n\t  EV67)  UNAME_MACHINE=alphaev67 ;;\n\t  EV68*) UNAME_MACHINE=alphaev68 ;;\n\tesac\n\tobjdump --private-headers /bin/sh | grep -q ld.so.1\n\tif test \"$?\" = 0 ; then LIBC=gnulibc1 ; fi\n\techo \"$UNAME_MACHINE\"-unknown-linux-\"$LIBC\"\n\texit ;;\n    arc:Linux:*:* | arceb:Linux:*:*)\n\techo \"$UNAME_MACHINE\"-unknown-linux-\"$LIBC\"\n\texit ;;\n    arm*:Linux:*:*)\n\tset_cc_for_build\n\tif echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \\\n\t    | grep -q __ARM_EABI__\n\tthen\n\t    echo \"$UNAME_MACHINE\"-unknown-linux-\"$LIBC\"\n\telse\n\t    if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \\\n\t\t| grep -q __ARM_PCS_VFP\n\t    then\n\t\techo \"$UNAME_MACHINE\"-unknown-linux-\"$LIBC\"eabi\n\t    else\n\t\techo \"$UNAME_MACHINE\"-unknown-linux-\"$LIBC\"eabihf\n\t    fi\n\tfi\n\texit ;;\n    avr32*:Linux:*:*)\n\techo \"$UNAME_MACHINE\"-unknown-linux-\"$LIBC\"\n\texit ;;\n    cris:Linux:*:*)\n\techo \"$UNAME_MACHINE\"-axis-linux-\"$LIBC\"\n\texit ;;\n    crisv32:Linux:*:*)\n\techo \"$UNAME_MACHINE\"-axis-linux-\"$LIBC\"\n\texit ;;\n    e2k:Linux:*:*)\n\techo \"$UNAME_MACHINE\"-unknown-linux-\"$LIBC\"\n\texit ;;\n    frv:Linux:*:*)\n\techo \"$UNAME_MACHINE\"-unknown-linux-\"$LIBC\"\n\texit ;;\n    hexagon:Linux:*:*)\n\techo \"$UNAME_MACHINE\"-unknown-linux-\"$LIBC\"\n\texit ;;\n    i*86:Linux:*:*)\n\techo \"$UNAME_MACHINE\"-pc-linux-\"$LIBC\"\n\texit ;;\n    ia64:Linux:*:*)\n\techo \"$UNAME_MACHINE\"-unknown-linux-\"$LIBC\"\n\texit ;;\n    k1om:Linux:*:*)\n\techo \"$UNAME_MACHINE\"-unknown-linux-\"$LIBC\"\n\texit ;;\n    loongarch32:Linux:*:* | loongarch64:Linux:*:* | loongarchx32:Linux:*:*)\n\techo \"$UNAME_MACHINE\"-unknown-linux-\"$LIBC\"\n\texit ;;\n    m32r*:Linux:*:*)\n\techo \"$UNAME_MACHINE\"-unknown-linux-\"$LIBC\"\n\texit ;;\n    m68*:Linux:*:*)\n\techo \"$UNAME_MACHINE\"-unknown-linux-\"$LIBC\"\n\texit ;;\n    mips:Linux:*:* | mips64:Linux:*:*)\n\tset_cc_for_build\n\tIS_GLIBC=0\n\ttest x\"${LIBC}\" = xgnu && IS_GLIBC=1\n\tsed 's/^\t//' << EOF > \"$dummy.c\"\n\t#undef CPU\n\t#undef mips\n\t#undef mipsel\n\t#undef mips64\n\t#undef mips64el\n\t#if ${IS_GLIBC} && defined(_ABI64)\n\tLIBCABI=gnuabi64\n\t#else\n\t#if ${IS_GLIBC} && defined(_ABIN32)\n\tLIBCABI=gnuabin32\n\t#else\n\tLIBCABI=${LIBC}\n\t#endif\n\t#endif\n\n\t#if ${IS_GLIBC} && defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6\n\tCPU=mipsisa64r6\n\t#else\n\t#if ${IS_GLIBC} && !defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6\n\tCPU=mipsisa32r6\n\t#else\n\t#if defined(__mips64)\n\tCPU=mips64\n\t#else\n\tCPU=mips\n\t#endif\n\t#endif\n\t#endif\n\n\t#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)\n\tMIPS_ENDIAN=el\n\t#else\n\t#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)\n\tMIPS_ENDIAN=\n\t#else\n\tMIPS_ENDIAN=\n\t#endif\n\t#endif\nEOF\n\teval \"$($CC_FOR_BUILD -E \"$dummy.c\" 2>/dev/null | grep '^CPU\\|^MIPS_ENDIAN\\|^LIBCABI')\"\n\ttest \"x$CPU\" != x && { echo \"$CPU${MIPS_ENDIAN}-unknown-linux-$LIBCABI\"; exit; }\n\t;;\n    mips64el:Linux:*:*)\n\techo \"$UNAME_MACHINE\"-unknown-linux-\"$LIBC\"\n\texit ;;\n    openrisc*:Linux:*:*)\n\techo or1k-unknown-linux-\"$LIBC\"\n\texit ;;\n    or32:Linux:*:* | or1k*:Linux:*:*)\n\techo \"$UNAME_MACHINE\"-unknown-linux-\"$LIBC\"\n\texit ;;\n    padre:Linux:*:*)\n\techo sparc-unknown-linux-\"$LIBC\"\n\texit ;;\n    parisc64:Linux:*:* | hppa64:Linux:*:*)\n\techo hppa64-unknown-linux-\"$LIBC\"\n\texit ;;\n    parisc:Linux:*:* | hppa:Linux:*:*)\n\t# Look for CPU level\n\tcase $(grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2) in\n\t  PA7*) echo hppa1.1-unknown-linux-\"$LIBC\" ;;\n\t  PA8*) echo hppa2.0-unknown-linux-\"$LIBC\" ;;\n\t  *)    echo hppa-unknown-linux-\"$LIBC\" ;;\n\tesac\n\texit ;;\n    ppc64:Linux:*:*)\n\techo powerpc64-unknown-linux-\"$LIBC\"\n\texit ;;\n    ppc:Linux:*:*)\n\techo powerpc-unknown-linux-\"$LIBC\"\n\texit ;;\n    ppc64le:Linux:*:*)\n\techo powerpc64le-unknown-linux-\"$LIBC\"\n\texit ;;\n    ppcle:Linux:*:*)\n\techo powerpcle-unknown-linux-\"$LIBC\"\n\texit ;;\n    riscv32:Linux:*:* | riscv32be:Linux:*:* | riscv64:Linux:*:* | riscv64be:Linux:*:*)\n\techo \"$UNAME_MACHINE\"-unknown-linux-\"$LIBC\"\n\texit ;;\n    s390:Linux:*:* | s390x:Linux:*:*)\n\techo \"$UNAME_MACHINE\"-ibm-linux-\"$LIBC\"\n\texit ;;\n    sh64*:Linux:*:*)\n\techo \"$UNAME_MACHINE\"-unknown-linux-\"$LIBC\"\n\texit ;;\n    sh*:Linux:*:*)\n\techo \"$UNAME_MACHINE\"-unknown-linux-\"$LIBC\"\n\texit ;;\n    sparc:Linux:*:* | sparc64:Linux:*:*)\n\techo \"$UNAME_MACHINE\"-unknown-linux-\"$LIBC\"\n\texit ;;\n    tile*:Linux:*:*)\n\techo \"$UNAME_MACHINE\"-unknown-linux-\"$LIBC\"\n\texit ;;\n    vax:Linux:*:*)\n\techo \"$UNAME_MACHINE\"-dec-linux-\"$LIBC\"\n\texit ;;\n    x86_64:Linux:*:*)\n\tset_cc_for_build\n\tLIBCABI=$LIBC\n\tif test \"$CC_FOR_BUILD\" != no_compiler_found; then\n\t    if (echo '#ifdef __ILP32__'; echo IS_X32; echo '#endif') | \\\n\t\t(CCOPTS=\"\" $CC_FOR_BUILD -E - 2>/dev/null) | \\\n\t\tgrep IS_X32 >/dev/null\n\t    then\n\t\tLIBCABI=\"$LIBC\"x32\n\t    fi\n\tfi\n\techo \"$UNAME_MACHINE\"-pc-linux-\"$LIBCABI\"\n\texit ;;\n    xtensa*:Linux:*:*)\n\techo \"$UNAME_MACHINE\"-unknown-linux-\"$LIBC\"\n\texit ;;\n    i*86:DYNIX/ptx:4*:*)\n\t# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.\n\t# earlier versions are messed up and put the nodename in both\n\t# sysname and nodename.\n\techo i386-sequent-sysv4\n\texit ;;\n    i*86:UNIX_SV:4.2MP:2.*)\n\t# Unixware is an offshoot of SVR4, but it has its own version\n\t# number series starting with 2...\n\t# I am not positive that other SVR4 systems won't match this,\n\t# I just have to hope.  -- rms.\n\t# Use sysv4.2uw... so that sysv4* matches it.\n\techo \"$UNAME_MACHINE\"-pc-sysv4.2uw\"$UNAME_VERSION\"\n\texit ;;\n    i*86:OS/2:*:*)\n\t# If we were able to find `uname', then EMX Unix compatibility\n\t# is probably installed.\n\techo \"$UNAME_MACHINE\"-pc-os2-emx\n\texit ;;\n    i*86:XTS-300:*:STOP)\n\techo \"$UNAME_MACHINE\"-unknown-stop\n\texit ;;\n    i*86:atheos:*:*)\n\techo \"$UNAME_MACHINE\"-unknown-atheos\n\texit ;;\n    i*86:syllable:*:*)\n\techo \"$UNAME_MACHINE\"-pc-syllable\n\texit ;;\n    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)\n\techo i386-unknown-lynxos\"$UNAME_RELEASE\"\n\texit ;;\n    i*86:*DOS:*:*)\n\techo \"$UNAME_MACHINE\"-pc-msdosdjgpp\n\texit ;;\n    i*86:*:4.*:*)\n\tUNAME_REL=$(echo \"$UNAME_RELEASE\" | sed 's/\\/MP$//')\n\tif grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then\n\t\techo \"$UNAME_MACHINE\"-univel-sysv\"$UNAME_REL\"\n\telse\n\t\techo \"$UNAME_MACHINE\"-pc-sysv\"$UNAME_REL\"\n\tfi\n\texit ;;\n    i*86:*:5:[678]*)\n\t# UnixWare 7.x, OpenUNIX and OpenServer 6.\n\tcase $(/bin/uname -X | grep \"^Machine\") in\n\t    *486*)\t     UNAME_MACHINE=i486 ;;\n\t    *Pentium)\t     UNAME_MACHINE=i586 ;;\n\t    *Pent*|*Celeron) UNAME_MACHINE=i686 ;;\n\tesac\n\techo \"$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}\"\n\texit ;;\n    i*86:*:3.2:*)\n\tif test -f /usr/options/cb.name; then\n\t\tUNAME_REL=$(sed -n 's/.*Version //p' </usr/options/cb.name)\n\t\techo \"$UNAME_MACHINE\"-pc-isc\"$UNAME_REL\"\n\telif /bin/uname -X 2>/dev/null >/dev/null ; then\n\t\tUNAME_REL=$( (/bin/uname -X|grep Release|sed -e 's/.*= //'))\n\t\t(/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486\n\t\t(/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \\\n\t\t\t&& UNAME_MACHINE=i586\n\t\t(/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \\\n\t\t\t&& UNAME_MACHINE=i686\n\t\t(/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \\\n\t\t\t&& UNAME_MACHINE=i686\n\t\techo \"$UNAME_MACHINE\"-pc-sco\"$UNAME_REL\"\n\telse\n\t\techo \"$UNAME_MACHINE\"-pc-sysv32\n\tfi\n\texit ;;\n    pc:*:*:*)\n\t# Left here for compatibility:\n\t# uname -m prints for DJGPP always 'pc', but it prints nothing about\n\t# the processor, so we play safe by assuming i586.\n\t# Note: whatever this is, it MUST be the same as what config.sub\n\t# prints for the \"djgpp\" host, or else GDB configure will decide that\n\t# this is a cross-build.\n\techo i586-pc-msdosdjgpp\n\texit ;;\n    Intel:Mach:3*:*)\n\techo i386-pc-mach3\n\texit ;;\n    paragon:*:*:*)\n\techo i860-intel-osf1\n\texit ;;\n    i860:*:4.*:*) # i860-SVR4\n\tif grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then\n\t  echo i860-stardent-sysv\"$UNAME_RELEASE\" # Stardent Vistra i860-SVR4\n\telse # Add other i860-SVR4 vendors below as they are discovered.\n\t  echo i860-unknown-sysv\"$UNAME_RELEASE\"  # Unknown i860-SVR4\n\tfi\n\texit ;;\n    mini*:CTIX:SYS*5:*)\n\t# \"miniframe\"\n\techo m68010-convergent-sysv\n\texit ;;\n    mc68k:UNIX:SYSTEM5:3.51m)\n\techo m68k-convergent-sysv\n\texit ;;\n    M680?0:D-NIX:5.3:*)\n\techo m68k-diab-dnix\n\texit ;;\n    M68*:*:R3V[5678]*:*)\n\ttest -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;\n    3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)\n\tOS_REL=''\n\ttest -r /etc/.relid \\\n\t&& OS_REL=.$(sed -n 's/[^ ]* [^ ]* \\([0-9][0-9]\\).*/\\1/p' < /etc/.relid)\n\t/bin/uname -p 2>/dev/null | grep 86 >/dev/null \\\n\t  && { echo i486-ncr-sysv4.3\"$OS_REL\"; exit; }\n\t/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \\\n\t  && { echo i586-ncr-sysv4.3\"$OS_REL\"; exit; } ;;\n    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)\n\t/bin/uname -p 2>/dev/null | grep 86 >/dev/null \\\n\t  && { echo i486-ncr-sysv4; exit; } ;;\n    NCR*:*:4.2:* | MPRAS*:*:4.2:*)\n\tOS_REL='.3'\n\ttest -r /etc/.relid \\\n\t    && OS_REL=.$(sed -n 's/[^ ]* [^ ]* \\([0-9][0-9]\\).*/\\1/p' < /etc/.relid)\n\t/bin/uname -p 2>/dev/null | grep 86 >/dev/null \\\n\t    && { echo i486-ncr-sysv4.3\"$OS_REL\"; exit; }\n\t/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \\\n\t    && { echo i586-ncr-sysv4.3\"$OS_REL\"; exit; }\n\t/bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \\\n\t    && { echo i586-ncr-sysv4.3\"$OS_REL\"; exit; } ;;\n    m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)\n\techo m68k-unknown-lynxos\"$UNAME_RELEASE\"\n\texit ;;\n    mc68030:UNIX_System_V:4.*:*)\n\techo m68k-atari-sysv4\n\texit ;;\n    TSUNAMI:LynxOS:2.*:*)\n\techo sparc-unknown-lynxos\"$UNAME_RELEASE\"\n\texit ;;\n    rs6000:LynxOS:2.*:*)\n\techo rs6000-unknown-lynxos\"$UNAME_RELEASE\"\n\texit ;;\n    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)\n\techo powerpc-unknown-lynxos\"$UNAME_RELEASE\"\n\texit ;;\n    SM[BE]S:UNIX_SV:*:*)\n\techo mips-dde-sysv\"$UNAME_RELEASE\"\n\texit ;;\n    RM*:ReliantUNIX-*:*:*)\n\techo mips-sni-sysv4\n\texit ;;\n    RM*:SINIX-*:*:*)\n\techo mips-sni-sysv4\n\texit ;;\n    *:SINIX-*:*:*)\n\tif uname -p 2>/dev/null >/dev/null ; then\n\t\tUNAME_MACHINE=$( (uname -p) 2>/dev/null)\n\t\techo \"$UNAME_MACHINE\"-sni-sysv4\n\telse\n\t\techo ns32k-sni-sysv\n\tfi\n\texit ;;\n    PENTIUM:*:4.0*:*)\t# Unisys `ClearPath HMP IX 4000' SVR4/MP effort\n\t\t\t# says <Richard.M.Bartel@ccMail.Census.GOV>\n\techo i586-unisys-sysv4\n\texit ;;\n    *:UNIX_System_V:4*:FTX*)\n\t# From Gerald Hewes <hewes@openmarket.com>.\n\t# How about differentiating between stratus architectures? -djm\n\techo hppa1.1-stratus-sysv4\n\texit ;;\n    *:*:*:FTX*)\n\t# From seanf@swdc.stratus.com.\n\techo i860-stratus-sysv4\n\texit ;;\n    i*86:VOS:*:*)\n\t# From Paul.Green@stratus.com.\n\techo \"$UNAME_MACHINE\"-stratus-vos\n\texit ;;\n    *:VOS:*:*)\n\t# From Paul.Green@stratus.com.\n\techo hppa1.1-stratus-vos\n\texit ;;\n    mc68*:A/UX:*:*)\n\techo m68k-apple-aux\"$UNAME_RELEASE\"\n\texit ;;\n    news*:NEWS-OS:6*:*)\n\techo mips-sony-newsos6\n\texit ;;\n    R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)\n\tif test -d /usr/nec; then\n\t\techo mips-nec-sysv\"$UNAME_RELEASE\"\n\telse\n\t\techo mips-unknown-sysv\"$UNAME_RELEASE\"\n\tfi\n\texit ;;\n    BeBox:BeOS:*:*)\t# BeOS running on hardware made by Be, PPC only.\n\techo powerpc-be-beos\n\texit ;;\n    BeMac:BeOS:*:*)\t# BeOS running on Mac or Mac clone, PPC only.\n\techo powerpc-apple-beos\n\texit ;;\n    BePC:BeOS:*:*)\t# BeOS running on Intel PC compatible.\n\techo i586-pc-beos\n\texit ;;\n    BePC:Haiku:*:*)\t# Haiku running on Intel PC compatible.\n\techo i586-pc-haiku\n\texit ;;\n    x86_64:Haiku:*:*)\n\techo x86_64-unknown-haiku\n\texit ;;\n    SX-4:SUPER-UX:*:*)\n\techo sx4-nec-superux\"$UNAME_RELEASE\"\n\texit ;;\n    SX-5:SUPER-UX:*:*)\n\techo sx5-nec-superux\"$UNAME_RELEASE\"\n\texit ;;\n    SX-6:SUPER-UX:*:*)\n\techo sx6-nec-superux\"$UNAME_RELEASE\"\n\texit ;;\n    SX-7:SUPER-UX:*:*)\n\techo sx7-nec-superux\"$UNAME_RELEASE\"\n\texit ;;\n    SX-8:SUPER-UX:*:*)\n\techo sx8-nec-superux\"$UNAME_RELEASE\"\n\texit ;;\n    SX-8R:SUPER-UX:*:*)\n\techo sx8r-nec-superux\"$UNAME_RELEASE\"\n\texit ;;\n    SX-ACE:SUPER-UX:*:*)\n\techo sxace-nec-superux\"$UNAME_RELEASE\"\n\texit ;;\n    Power*:Rhapsody:*:*)\n\techo powerpc-apple-rhapsody\"$UNAME_RELEASE\"\n\texit ;;\n    *:Rhapsody:*:*)\n\techo \"$UNAME_MACHINE\"-apple-rhapsody\"$UNAME_RELEASE\"\n\texit ;;\n    arm64:Darwin:*:*)\n\techo aarch64-apple-darwin\"$UNAME_RELEASE\"\n\texit ;;\n    *:Darwin:*:*)\n\tUNAME_PROCESSOR=$(uname -p)\n\tcase $UNAME_PROCESSOR in\n\t    unknown) UNAME_PROCESSOR=powerpc ;;\n\tesac\n\tif command -v xcode-select > /dev/null 2> /dev/null && \\\n\t\t! xcode-select --print-path > /dev/null 2> /dev/null ; then\n\t    # Avoid executing cc if there is no toolchain installed as\n\t    # cc will be a stub that puts up a graphical alert\n\t    # prompting the user to install developer tools.\n\t    CC_FOR_BUILD=no_compiler_found\n\telse\n\t    set_cc_for_build\n\tfi\n\tif test \"$CC_FOR_BUILD\" != no_compiler_found; then\n\t    if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \\\n\t\t   (CCOPTS=\"\" $CC_FOR_BUILD -E - 2>/dev/null) | \\\n\t\t   grep IS_64BIT_ARCH >/dev/null\n\t    then\n\t\tcase $UNAME_PROCESSOR in\n\t\t    i386) UNAME_PROCESSOR=x86_64 ;;\n\t\t    powerpc) UNAME_PROCESSOR=powerpc64 ;;\n\t\tesac\n\t    fi\n\t    # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc\n\t    if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \\\n\t\t   (CCOPTS=\"\" $CC_FOR_BUILD -E - 2>/dev/null) | \\\n\t\t   grep IS_PPC >/dev/null\n\t    then\n\t\tUNAME_PROCESSOR=powerpc\n\t    fi\n\telif test \"$UNAME_PROCESSOR\" = i386 ; then\n\t    # uname -m returns i386 or x86_64\n\t    UNAME_PROCESSOR=$UNAME_MACHINE\n\tfi\n\techo \"$UNAME_PROCESSOR\"-apple-darwin\"$UNAME_RELEASE\"\n\texit ;;\n    *:procnto*:*:* | *:QNX:[0123456789]*:*)\n\tUNAME_PROCESSOR=$(uname -p)\n\tif test \"$UNAME_PROCESSOR\" = x86; then\n\t\tUNAME_PROCESSOR=i386\n\t\tUNAME_MACHINE=pc\n\tfi\n\techo \"$UNAME_PROCESSOR\"-\"$UNAME_MACHINE\"-nto-qnx\"$UNAME_RELEASE\"\n\texit ;;\n    *:QNX:*:4*)\n\techo i386-pc-qnx\n\texit ;;\n    NEO-*:NONSTOP_KERNEL:*:*)\n\techo neo-tandem-nsk\"$UNAME_RELEASE\"\n\texit ;;\n    NSE-*:NONSTOP_KERNEL:*:*)\n\techo nse-tandem-nsk\"$UNAME_RELEASE\"\n\texit ;;\n    NSR-*:NONSTOP_KERNEL:*:*)\n\techo nsr-tandem-nsk\"$UNAME_RELEASE\"\n\texit ;;\n    NSV-*:NONSTOP_KERNEL:*:*)\n\techo nsv-tandem-nsk\"$UNAME_RELEASE\"\n\texit ;;\n    NSX-*:NONSTOP_KERNEL:*:*)\n\techo nsx-tandem-nsk\"$UNAME_RELEASE\"\n\texit ;;\n    *:NonStop-UX:*:*)\n\techo mips-compaq-nonstopux\n\texit ;;\n    BS2000:POSIX*:*:*)\n\techo bs2000-siemens-sysv\n\texit ;;\n    DS/*:UNIX_System_V:*:*)\n\techo \"$UNAME_MACHINE\"-\"$UNAME_SYSTEM\"-\"$UNAME_RELEASE\"\n\texit ;;\n    *:Plan9:*:*)\n\t# \"uname -m\" is not consistent, so use $cputype instead. 386\n\t# is converted to i386 for consistency with other x86\n\t# operating systems.\n\t# shellcheck disable=SC2154\n\tif test \"$cputype\" = 386; then\n\t    UNAME_MACHINE=i386\n\telse\n\t    UNAME_MACHINE=\"$cputype\"\n\tfi\n\techo \"$UNAME_MACHINE\"-unknown-plan9\n\texit ;;\n    *:TOPS-10:*:*)\n\techo pdp10-unknown-tops10\n\texit ;;\n    *:TENEX:*:*)\n\techo pdp10-unknown-tenex\n\texit ;;\n    KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)\n\techo pdp10-dec-tops20\n\texit ;;\n    XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)\n\techo pdp10-xkl-tops20\n\texit ;;\n    *:TOPS-20:*:*)\n\techo pdp10-unknown-tops20\n\texit ;;\n    *:ITS:*:*)\n\techo pdp10-unknown-its\n\texit ;;\n    SEI:*:*:SEIUX)\n\techo mips-sei-seiux\"$UNAME_RELEASE\"\n\texit ;;\n    *:DragonFly:*:*)\n\techo \"$UNAME_MACHINE\"-unknown-dragonfly\"$(echo \"$UNAME_RELEASE\"|sed -e 's/[-(].*//')\"\n\texit ;;\n    *:*VMS:*:*)\n\tUNAME_MACHINE=$( (uname -p) 2>/dev/null)\n\tcase \"$UNAME_MACHINE\" in\n\t    A*) echo alpha-dec-vms ; exit ;;\n\t    I*) echo ia64-dec-vms ; exit ;;\n\t    V*) echo vax-dec-vms ; exit ;;\n\tesac ;;\n    *:XENIX:*:SysV)\n\techo i386-pc-xenix\n\texit ;;\n    i*86:skyos:*:*)\n\techo \"$UNAME_MACHINE\"-pc-skyos\"$(echo \"$UNAME_RELEASE\" | sed -e 's/ .*$//')\"\n\texit ;;\n    i*86:rdos:*:*)\n\techo \"$UNAME_MACHINE\"-pc-rdos\n\texit ;;\n    *:AROS:*:*)\n\techo \"$UNAME_MACHINE\"-unknown-aros\n\texit ;;\n    x86_64:VMkernel:*:*)\n\techo \"$UNAME_MACHINE\"-unknown-esx\n\texit ;;\n    amd64:Isilon\\ OneFS:*:*)\n\techo x86_64-unknown-onefs\n\texit ;;\n    *:Unleashed:*:*)\n\techo \"$UNAME_MACHINE\"-unknown-unleashed\"$UNAME_RELEASE\"\n\texit ;;\nesac\n\n# No uname command or uname output not recognized.\nset_cc_for_build\ncat > \"$dummy.c\" <<EOF\n#ifdef _SEQUENT_\n#include <sys/types.h>\n#include <sys/utsname.h>\n#endif\n#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__)\n#if defined (vax) || defined (__vax) || defined (__vax__) || defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__)\n#include <signal.h>\n#if defined(_SIZE_T_) || defined(SIGLOST)\n#include <sys/utsname.h>\n#endif\n#endif\n#endif\nmain ()\n{\n#if defined (sony)\n#if defined (MIPSEB)\n  /* BFD wants \"bsd\" instead of \"newsos\".  Perhaps BFD should be changed,\n     I don't know....  */\n  printf (\"mips-sony-bsd\\n\"); exit (0);\n#else\n#include <sys/param.h>\n  printf (\"m68k-sony-newsos%s\\n\",\n#ifdef NEWSOS4\n  \"4\"\n#else\n  \"\"\n#endif\n  ); exit (0);\n#endif\n#endif\n\n#if defined (NeXT)\n#if !defined (__ARCHITECTURE__)\n#define __ARCHITECTURE__ \"m68k\"\n#endif\n  int version;\n  version=$( (hostinfo | sed -n 's/.*NeXT Mach \\([0-9]*\\).*/\\1/p') 2>/dev/null);\n  if (version < 4)\n    printf (\"%s-next-nextstep%d\\n\", __ARCHITECTURE__, version);\n  else\n    printf (\"%s-next-openstep%d\\n\", __ARCHITECTURE__, version);\n  exit (0);\n#endif\n\n#if defined (MULTIMAX) || defined (n16)\n#if defined (UMAXV)\n  printf (\"ns32k-encore-sysv\\n\"); exit (0);\n#else\n#if defined (CMU)\n  printf (\"ns32k-encore-mach\\n\"); exit (0);\n#else\n  printf (\"ns32k-encore-bsd\\n\"); exit (0);\n#endif\n#endif\n#endif\n\n#if defined (__386BSD__)\n  printf (\"i386-pc-bsd\\n\"); exit (0);\n#endif\n\n#if defined (sequent)\n#if defined (i386)\n  printf (\"i386-sequent-dynix\\n\"); exit (0);\n#endif\n#if defined (ns32000)\n  printf (\"ns32k-sequent-dynix\\n\"); exit (0);\n#endif\n#endif\n\n#if defined (_SEQUENT_)\n  struct utsname un;\n\n  uname(&un);\n  if (strncmp(un.version, \"V2\", 2) == 0) {\n    printf (\"i386-sequent-ptx2\\n\"); exit (0);\n  }\n  if (strncmp(un.version, \"V1\", 2) == 0) { /* XXX is V1 correct? */\n    printf (\"i386-sequent-ptx1\\n\"); exit (0);\n  }\n  printf (\"i386-sequent-ptx\\n\"); exit (0);\n#endif\n\n#if defined (vax)\n#if !defined (ultrix)\n#include <sys/param.h>\n#if defined (BSD)\n#if BSD == 43\n  printf (\"vax-dec-bsd4.3\\n\"); exit (0);\n#else\n#if BSD == 199006\n  printf (\"vax-dec-bsd4.3reno\\n\"); exit (0);\n#else\n  printf (\"vax-dec-bsd\\n\"); exit (0);\n#endif\n#endif\n#else\n  printf (\"vax-dec-bsd\\n\"); exit (0);\n#endif\n#else\n#if defined(_SIZE_T_) || defined(SIGLOST)\n  struct utsname un;\n  uname (&un);\n  printf (\"vax-dec-ultrix%s\\n\", un.release); exit (0);\n#else\n  printf (\"vax-dec-ultrix\\n\"); exit (0);\n#endif\n#endif\n#endif\n#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__)\n#if defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__)\n#if defined(_SIZE_T_) || defined(SIGLOST)\n  struct utsname *un;\n  uname (&un);\n  printf (\"mips-dec-ultrix%s\\n\", un.release); exit (0);\n#else\n  printf (\"mips-dec-ultrix\\n\"); exit (0);\n#endif\n#endif\n#endif\n\n#if defined (alliant) && defined (i860)\n  printf (\"i860-alliant-bsd\\n\"); exit (0);\n#endif\n\n  exit (1);\n}\nEOF\n\n$CC_FOR_BUILD -o \"$dummy\" \"$dummy.c\" 2>/dev/null && SYSTEM_NAME=$($dummy) &&\n\t{ echo \"$SYSTEM_NAME\"; exit; }\n\n# Apollos put the system type in the environment.\ntest -d /usr/apollo && { echo \"$ISP-apollo-$SYSTYPE\"; exit; }\n\necho \"$0: unable to guess system type\" >&2\n\ncase \"$UNAME_MACHINE:$UNAME_SYSTEM\" in\n    mips:Linux | mips64:Linux)\n\t# If we got here on MIPS GNU/Linux, output extra information.\n\tcat >&2 <<EOF\n\nNOTE: MIPS GNU/Linux systems require a C compiler to fully recognize\nthe system type. Please install a C compiler and try again.\nEOF\n\t;;\nesac\n\ncat >&2 <<EOF\n\nThis script (version $timestamp), has failed to recognize the\noperating system you are using. If your script is old, overwrite *all*\ncopies of config.guess and config.sub with the latest versions from:\n\n  https://git.savannah.gnu.org/cgit/config.git/plain/config.guess\nand\n  https://git.savannah.gnu.org/cgit/config.git/plain/config.sub\nEOF\n\nyear=$(echo $timestamp | sed 's,-.*,,')\n# shellcheck disable=SC2003\nif test \"$(expr \"$(date +%Y)\" - \"$year\")\" -lt 3 ; then\n   cat >&2 <<EOF\n\nIf $0 has already been updated, send the following data and any\ninformation you think might be pertinent to config-patches@gnu.org to\nprovide the necessary information to handle your system.\n\nconfig.guess timestamp = $timestamp\n\nuname -m = $( (uname -m) 2>/dev/null || echo unknown)\nuname -r = $( (uname -r) 2>/dev/null || echo unknown)\nuname -s = $( (uname -s) 2>/dev/null || echo unknown)\nuname -v = $( (uname -v) 2>/dev/null || echo unknown)\n\n/usr/bin/uname -p = $( (/usr/bin/uname -p) 2>/dev/null)\n/bin/uname -X     = $( (/bin/uname -X) 2>/dev/null)\n\nhostinfo               = $( (hostinfo) 2>/dev/null)\n/bin/universe          = $( (/bin/universe) 2>/dev/null)\n/usr/bin/arch -k       = $( (/usr/bin/arch -k) 2>/dev/null)\n/bin/arch              = $( (/bin/arch) 2>/dev/null)\n/usr/bin/oslevel       = $( (/usr/bin/oslevel) 2>/dev/null)\n/usr/convex/getsysinfo = $( (/usr/convex/getsysinfo) 2>/dev/null)\n\nUNAME_MACHINE = \"$UNAME_MACHINE\"\nUNAME_RELEASE = \"$UNAME_RELEASE\"\nUNAME_SYSTEM  = \"$UNAME_SYSTEM\"\nUNAME_VERSION = \"$UNAME_VERSION\"\nEOF\nfi\n\nexit 1\n\n# Local variables:\n# eval: (add-hook 'before-save-hook 'time-stamp)\n# time-stamp-start: \"timestamp='\"\n# time-stamp-format: \"%:y-%02m-%02d\"\n# time-stamp-end: \"'\"\n# End:\n"
  },
  {
    "path": "src/vendor/libbacktrace/config.h.in",
    "content": "/* config.h.in.  Generated from configure.ac by autoheader.  */\n\n/* ELF size: 32 or 64 */\n#undef BACKTRACE_ELF_SIZE\n\n/* XCOFF size: 32 or 64 */\n#undef BACKTRACE_XCOFF_SIZE\n\n/* Define to 1 if you have the __atomic functions */\n#undef HAVE_ATOMIC_FUNCTIONS\n\n/* Define to 1 if you have the `clock_gettime' function. */\n#undef HAVE_CLOCK_GETTIME\n\n/* Define to 1 if you have the declaration of `getpagesize', and to 0 if you\n   don't. */\n#undef HAVE_DECL_GETPAGESIZE\n\n/* Define to 1 if you have the declaration of `strnlen', and to 0 if you\n   don't. */\n#undef HAVE_DECL_STRNLEN\n\n/* Define to 1 if you have the declaration of `_pgmptr', and to 0 if you\n   don't. */\n#undef HAVE_DECL__PGMPTR\n\n/* Define to 1 if you have the <dlfcn.h> header file. */\n#undef HAVE_DLFCN_H\n\n/* Define if dl_iterate_phdr is available. */\n#undef HAVE_DL_ITERATE_PHDR\n\n/* Define to 1 if you have the fcntl function */\n#undef HAVE_FCNTL\n\n/* Define if getexecname is available. */\n#undef HAVE_GETEXECNAME\n\n/* Define if _Unwind_GetIPInfo is available. */\n#undef HAVE_GETIPINFO\n\n/* Define to 1 if you have the <inttypes.h> header file. */\n#undef HAVE_INTTYPES_H\n\n/* Define to 1 if you have KERN_PROC and KERN_PROC_PATHNAME in <sys/sysctl.h>.\n   */\n#undef HAVE_KERN_PROC\n\n/* Define to 1 if you have KERN_PROCARGS and KERN_PROC_PATHNAME in\n   <sys/sysctl.h>. */\n#undef HAVE_KERN_PROC_ARGS\n\n/* Define if -llzma is available. */\n#undef HAVE_LIBLZMA\n\n/* Define to 1 if you have the <link.h> header file. */\n#undef HAVE_LINK_H\n\n/* Define if AIX loadquery is available. */\n#undef HAVE_LOADQUERY\n\n/* Define to 1 if you have the `lstat' function. */\n#undef HAVE_LSTAT\n\n/* Define to 1 if you have the <mach-o/dyld.h> header file. */\n#undef HAVE_MACH_O_DYLD_H\n\n/* Define to 1 if you have the <memory.h> header file. */\n#undef HAVE_MEMORY_H\n\n/* Define to 1 if you have the `readlink' function. */\n#undef HAVE_READLINK\n\n/* Define to 1 if you have the <stdint.h> header file. */\n#undef HAVE_STDINT_H\n\n/* Define to 1 if you have the <stdlib.h> header file. */\n#undef HAVE_STDLIB_H\n\n/* Define to 1 if you have the <strings.h> header file. */\n#undef HAVE_STRINGS_H\n\n/* Define to 1 if you have the <string.h> header file. */\n#undef HAVE_STRING_H\n\n/* Define to 1 if you have the __sync functions */\n#undef HAVE_SYNC_FUNCTIONS\n\n/* Define to 1 if you have the <sys/ldr.h> header file. */\n#undef HAVE_SYS_LDR_H\n\n/* Define to 1 if you have the <sys/link.h> header file. */\n#undef HAVE_SYS_LINK_H\n\n/* Define to 1 if you have the <sys/mman.h> header file. */\n#undef HAVE_SYS_MMAN_H\n\n/* Define to 1 if you have the <sys/stat.h> header file. */\n#undef HAVE_SYS_STAT_H\n\n/* Define to 1 if you have the <sys/types.h> header file. */\n#undef HAVE_SYS_TYPES_H\n\n/* Define to 1 if you have the <tlhelp32.h> header file. */\n#undef HAVE_TLHELP32_H\n\n/* Define to 1 if you have the <unistd.h> header file. */\n#undef HAVE_UNISTD_H\n\n/* Define to 1 if you have the <windows.h> header file. */\n#undef HAVE_WINDOWS_H\n\n/* Define if -lz is available. */\n#undef HAVE_ZLIB\n\n/* Define if -lzstd is available. */\n#undef HAVE_ZSTD\n\n/* Define to the sub-directory in which libtool stores uninstalled libraries.\n   */\n#undef LT_OBJDIR\n\n/* Define to the address where bug reports for this package should be sent. */\n#undef PACKAGE_BUGREPORT\n\n/* Define to the full name of this package. */\n#undef PACKAGE_NAME\n\n/* Define to the full name and version of this package. */\n#undef PACKAGE_STRING\n\n/* Define to the one symbol short name of this package. */\n#undef PACKAGE_TARNAME\n\n/* Define to the home page for this package. */\n#undef PACKAGE_URL\n\n/* Define to the version of this package. */\n#undef PACKAGE_VERSION\n\n/* Define to 1 if you have the ANSI C header files. */\n#undef STDC_HEADERS\n\n/* Enable extensions on AIX 3, Interix.  */\n#ifndef _ALL_SOURCE\n# undef _ALL_SOURCE\n#endif\n/* Enable GNU extensions on systems that have them.  */\n#ifndef _GNU_SOURCE\n# undef _GNU_SOURCE\n#endif\n/* Enable threading extensions on Solaris.  */\n#ifndef _POSIX_PTHREAD_SEMANTICS\n# undef _POSIX_PTHREAD_SEMANTICS\n#endif\n/* Enable extensions on HP NonStop.  */\n#ifndef _TANDEM_SOURCE\n# undef _TANDEM_SOURCE\n#endif\n/* Enable general extensions on Solaris.  */\n#ifndef __EXTENSIONS__\n# undef __EXTENSIONS__\n#endif\n\n\n/* Enable large inode numbers on Mac OS X 10.5.  */\n#ifndef _DARWIN_USE_64_BIT_INODE\n# define _DARWIN_USE_64_BIT_INODE 1\n#endif\n\n/* Number of bits in a file offset, on hosts where this is settable. */\n#undef _FILE_OFFSET_BITS\n\n/* Define for large files, on AIX-style hosts. */\n#undef _LARGE_FILES\n\n/* Define to 1 if on MINIX. */\n#undef _MINIX\n\n/* Define to 2 if the system does not provide POSIX.1 features except with\n   this defined. */\n#undef _POSIX_1_SOURCE\n\n/* Define to 1 if you need to in order for `stat' and other things to work. */\n#undef _POSIX_SOURCE\n"
  },
  {
    "path": "src/vendor/libbacktrace/config.sub",
    "content": "#! /bin/sh\n# Configuration validation subroutine script.\n#   Copyright 1992-2021 Free Software Foundation, Inc.\n\n# shellcheck disable=SC2006,SC2268 # see below for rationale\n\ntimestamp='2021-10-27'\n\n# This file is free software; you can redistribute it and/or modify it\n# under the terms of the GNU General Public License as published by\n# the Free Software Foundation; either version 3 of the License, or\n# (at your option) any later version.\n#\n# This program is distributed in the hope that it will be useful, but\n# WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n# General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with this program; if not, see <https://www.gnu.org/licenses/>.\n#\n# As a special exception to the GNU General Public License, if you\n# distribute this file as part of a program that contains a\n# configuration script generated by Autoconf, you may include it under\n# the same distribution terms that you use for the rest of that\n# program.  This Exception is an additional permission under section 7\n# of the GNU General Public License, version 3 (\"GPLv3\").\n\n\n# Please send patches to <config-patches@gnu.org>.\n#\n# Configuration subroutine to validate and canonicalize a configuration type.\n# Supply the specified configuration type as an argument.\n# If it is invalid, we print an error message on stderr and exit with code 1.\n# Otherwise, we print the canonical config type on stdout and succeed.\n\n# You can get the latest version of this script from:\n# https://git.savannah.gnu.org/cgit/config.git/plain/config.sub\n\n# This file is supposed to be the same for all GNU packages\n# and recognize all the CPU types, system types and aliases\n# that are meaningful with *any* GNU software.\n# Each package is responsible for reporting which valid configurations\n# it does not support.  The user should be able to distinguish\n# a failure to support a valid configuration from a meaningless\n# configuration.\n\n# The goal of this file is to map all the various variations of a given\n# machine specification into a single specification in the form:\n#\tCPU_TYPE-MANUFACTURER-OPERATING_SYSTEM\n# or in some cases, the newer four-part form:\n#\tCPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM\n# It is wrong to echo any other type of specification.\n\n# The \"shellcheck disable\" line above the timestamp inhibits complaints\n# about features and limitations of the classic Bourne shell that were\n# superseded or lifted in POSIX.  However, this script identifies a wide\n# variety of pre-POSIX systems that do not have POSIX shells at all, and\n# even some reasonably current systems (Solaris 10 as case-in-point) still\n# have a pre-POSIX /bin/sh.\n\nme=`echo \"$0\" | sed -e 's,.*/,,'`\n\nusage=\"\\\nUsage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS\n\nCanonicalize a configuration name.\n\nOptions:\n  -h, --help         print this help, then exit\n  -t, --time-stamp   print date of last modification, then exit\n  -v, --version      print version number, then exit\n\nReport bugs and patches to <config-patches@gnu.org>.\"\n\nversion=\"\\\nGNU config.sub ($timestamp)\n\nCopyright 1992-2021 Free Software Foundation, Inc.\n\nThis is free software; see the source for copying conditions.  There is NO\nwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\"\n\nhelp=\"\nTry \\`$me --help' for more information.\"\n\n# Parse command line\nwhile test $# -gt 0 ; do\n  case $1 in\n    --time-stamp | --time* | -t )\n       echo \"$timestamp\" ; exit ;;\n    --version | -v )\n       echo \"$version\" ; exit ;;\n    --help | --h* | -h )\n       echo \"$usage\"; exit ;;\n    -- )     # Stop option processing\n       shift; break ;;\n    - )\t# Use stdin as input.\n       break ;;\n    -* )\n       echo \"$me: invalid option $1$help\" >&2\n       exit 1 ;;\n\n    *local*)\n       # First pass through any local machine types.\n       echo \"$1\"\n       exit ;;\n\n    * )\n       break ;;\n  esac\ndone\n\ncase $# in\n 0) echo \"$me: missing argument$help\" >&2\n    exit 1;;\n 1) ;;\n *) echo \"$me: too many arguments$help\" >&2\n    exit 1;;\nesac\n\n# Split fields of configuration type\n# shellcheck disable=SC2162\nsaved_IFS=$IFS\nIFS=\"-\" read field1 field2 field3 field4 <<EOF\n$1\nEOF\nIFS=$saved_IFS\n\n# Separate into logical components for further validation\ncase $1 in\n\t*-*-*-*-*)\n\t\techo Invalid configuration \\`\"$1\"\\': more than four components >&2\n\t\texit 1\n\t\t;;\n\t*-*-*-*)\n\t\tbasic_machine=$field1-$field2\n\t\tbasic_os=$field3-$field4\n\t\t;;\n\t*-*-*)\n\t\t# Ambiguous whether COMPANY is present, or skipped and KERNEL-OS is two\n\t\t# parts\n\t\tmaybe_os=$field2-$field3\n\t\tcase $maybe_os in\n\t\t\tnto-qnx* | linux-* | uclinux-uclibc* \\\n\t\t\t| uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \\\n\t\t\t| netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \\\n\t\t\t| storm-chaos* | os2-emx* | rtmk-nova*)\n\t\t\t\tbasic_machine=$field1\n\t\t\t\tbasic_os=$maybe_os\n\t\t\t\t;;\n\t\t\tandroid-linux)\n\t\t\t\tbasic_machine=$field1-unknown\n\t\t\t\tbasic_os=linux-android\n\t\t\t\t;;\n\t\t\t*)\n\t\t\t\tbasic_machine=$field1-$field2\n\t\t\t\tbasic_os=$field3\n\t\t\t\t;;\n\t\tesac\n\t\t;;\n\t*-*)\n\t\t# A lone config we happen to match not fitting any pattern\n\t\tcase $field1-$field2 in\n\t\t\tdecstation-3100)\n\t\t\t\tbasic_machine=mips-dec\n\t\t\t\tbasic_os=\n\t\t\t\t;;\n\t\t\t*-*)\n\t\t\t\t# Second component is usually, but not always the OS\n\t\t\t\tcase $field2 in\n\t\t\t\t\t# Prevent following clause from handling this valid os\n\t\t\t\t\tsun*os*)\n\t\t\t\t\t\tbasic_machine=$field1\n\t\t\t\t\t\tbasic_os=$field2\n\t\t\t\t\t\t;;\n\t\t\t\t\tzephyr*)\n\t\t\t\t\t\tbasic_machine=$field1-unknown\n\t\t\t\t\t\tbasic_os=$field2\n\t\t\t\t\t\t;;\n\t\t\t\t\t# Manufacturers\n\t\t\t\t\tdec* | mips* | sequent* | encore* | pc533* | sgi* | sony* \\\n\t\t\t\t\t| att* | 7300* | 3300* | delta* | motorola* | sun[234]* \\\n\t\t\t\t\t| unicom* | ibm* | next | hp | isi* | apollo | altos* \\\n\t\t\t\t\t| convergent* | ncr* | news | 32* | 3600* | 3100* \\\n\t\t\t\t\t| hitachi* | c[123]* | convex* | sun | crds | omron* | dg \\\n\t\t\t\t\t| ultra | tti* | harris | dolphin | highlevel | gould \\\n\t\t\t\t\t| cbm | ns | masscomp | apple | axis | knuth | cray \\\n\t\t\t\t\t| microblaze* | sim | cisco \\\n\t\t\t\t\t| oki | wec | wrs | winbond)\n\t\t\t\t\t\tbasic_machine=$field1-$field2\n\t\t\t\t\t\tbasic_os=\n\t\t\t\t\t\t;;\n\t\t\t\t\t*)\n\t\t\t\t\t\tbasic_machine=$field1\n\t\t\t\t\t\tbasic_os=$field2\n\t\t\t\t\t\t;;\n\t\t\t\tesac\n\t\t\t;;\n\t\tesac\n\t\t;;\n\t*)\n\t\t# Convert single-component short-hands not valid as part of\n\t\t# multi-component configurations.\n\t\tcase $field1 in\n\t\t\t386bsd)\n\t\t\t\tbasic_machine=i386-pc\n\t\t\t\tbasic_os=bsd\n\t\t\t\t;;\n\t\t\ta29khif)\n\t\t\t\tbasic_machine=a29k-amd\n\t\t\t\tbasic_os=udi\n\t\t\t\t;;\n\t\t\tadobe68k)\n\t\t\t\tbasic_machine=m68010-adobe\n\t\t\t\tbasic_os=scout\n\t\t\t\t;;\n\t\t\talliant)\n\t\t\t\tbasic_machine=fx80-alliant\n\t\t\t\tbasic_os=\n\t\t\t\t;;\n\t\t\taltos | altos3068)\n\t\t\t\tbasic_machine=m68k-altos\n\t\t\t\tbasic_os=\n\t\t\t\t;;\n\t\t\tam29k)\n\t\t\t\tbasic_machine=a29k-none\n\t\t\t\tbasic_os=bsd\n\t\t\t\t;;\n\t\t\tamdahl)\n\t\t\t\tbasic_machine=580-amdahl\n\t\t\t\tbasic_os=sysv\n\t\t\t\t;;\n\t\t\tamiga)\n\t\t\t\tbasic_machine=m68k-unknown\n\t\t\t\tbasic_os=\n\t\t\t\t;;\n\t\t\tamigaos | amigados)\n\t\t\t\tbasic_machine=m68k-unknown\n\t\t\t\tbasic_os=amigaos\n\t\t\t\t;;\n\t\t\tamigaunix | amix)\n\t\t\t\tbasic_machine=m68k-unknown\n\t\t\t\tbasic_os=sysv4\n\t\t\t\t;;\n\t\t\tapollo68)\n\t\t\t\tbasic_machine=m68k-apollo\n\t\t\t\tbasic_os=sysv\n\t\t\t\t;;\n\t\t\tapollo68bsd)\n\t\t\t\tbasic_machine=m68k-apollo\n\t\t\t\tbasic_os=bsd\n\t\t\t\t;;\n\t\t\taros)\n\t\t\t\tbasic_machine=i386-pc\n\t\t\t\tbasic_os=aros\n\t\t\t\t;;\n\t\t\taux)\n\t\t\t\tbasic_machine=m68k-apple\n\t\t\t\tbasic_os=aux\n\t\t\t\t;;\n\t\t\tbalance)\n\t\t\t\tbasic_machine=ns32k-sequent\n\t\t\t\tbasic_os=dynix\n\t\t\t\t;;\n\t\t\tblackfin)\n\t\t\t\tbasic_machine=bfin-unknown\n\t\t\t\tbasic_os=linux\n\t\t\t\t;;\n\t\t\tcegcc)\n\t\t\t\tbasic_machine=arm-unknown\n\t\t\t\tbasic_os=cegcc\n\t\t\t\t;;\n\t\t\tconvex-c1)\n\t\t\t\tbasic_machine=c1-convex\n\t\t\t\tbasic_os=bsd\n\t\t\t\t;;\n\t\t\tconvex-c2)\n\t\t\t\tbasic_machine=c2-convex\n\t\t\t\tbasic_os=bsd\n\t\t\t\t;;\n\t\t\tconvex-c32)\n\t\t\t\tbasic_machine=c32-convex\n\t\t\t\tbasic_os=bsd\n\t\t\t\t;;\n\t\t\tconvex-c34)\n\t\t\t\tbasic_machine=c34-convex\n\t\t\t\tbasic_os=bsd\n\t\t\t\t;;\n\t\t\tconvex-c38)\n\t\t\t\tbasic_machine=c38-convex\n\t\t\t\tbasic_os=bsd\n\t\t\t\t;;\n\t\t\tcray)\n\t\t\t\tbasic_machine=j90-cray\n\t\t\t\tbasic_os=unicos\n\t\t\t\t;;\n\t\t\tcrds | unos)\n\t\t\t\tbasic_machine=m68k-crds\n\t\t\t\tbasic_os=\n\t\t\t\t;;\n\t\t\tda30)\n\t\t\t\tbasic_machine=m68k-da30\n\t\t\t\tbasic_os=\n\t\t\t\t;;\n\t\t\tdecstation | pmax | pmin | dec3100 | decstatn)\n\t\t\t\tbasic_machine=mips-dec\n\t\t\t\tbasic_os=\n\t\t\t\t;;\n\t\t\tdelta88)\n\t\t\t\tbasic_machine=m88k-motorola\n\t\t\t\tbasic_os=sysv3\n\t\t\t\t;;\n\t\t\tdicos)\n\t\t\t\tbasic_machine=i686-pc\n\t\t\t\tbasic_os=dicos\n\t\t\t\t;;\n\t\t\tdjgpp)\n\t\t\t\tbasic_machine=i586-pc\n\t\t\t\tbasic_os=msdosdjgpp\n\t\t\t\t;;\n\t\t\tebmon29k)\n\t\t\t\tbasic_machine=a29k-amd\n\t\t\t\tbasic_os=ebmon\n\t\t\t\t;;\n\t\t\tes1800 | OSE68k | ose68k | ose | OSE)\n\t\t\t\tbasic_machine=m68k-ericsson\n\t\t\t\tbasic_os=ose\n\t\t\t\t;;\n\t\t\tgmicro)\n\t\t\t\tbasic_machine=tron-gmicro\n\t\t\t\tbasic_os=sysv\n\t\t\t\t;;\n\t\t\tgo32)\n\t\t\t\tbasic_machine=i386-pc\n\t\t\t\tbasic_os=go32\n\t\t\t\t;;\n\t\t\th8300hms)\n\t\t\t\tbasic_machine=h8300-hitachi\n\t\t\t\tbasic_os=hms\n\t\t\t\t;;\n\t\t\th8300xray)\n\t\t\t\tbasic_machine=h8300-hitachi\n\t\t\t\tbasic_os=xray\n\t\t\t\t;;\n\t\t\th8500hms)\n\t\t\t\tbasic_machine=h8500-hitachi\n\t\t\t\tbasic_os=hms\n\t\t\t\t;;\n\t\t\tharris)\n\t\t\t\tbasic_machine=m88k-harris\n\t\t\t\tbasic_os=sysv3\n\t\t\t\t;;\n\t\t\thp300 | hp300hpux)\n\t\t\t\tbasic_machine=m68k-hp\n\t\t\t\tbasic_os=hpux\n\t\t\t\t;;\n\t\t\thp300bsd)\n\t\t\t\tbasic_machine=m68k-hp\n\t\t\t\tbasic_os=bsd\n\t\t\t\t;;\n\t\t\thppaosf)\n\t\t\t\tbasic_machine=hppa1.1-hp\n\t\t\t\tbasic_os=osf\n\t\t\t\t;;\n\t\t\thppro)\n\t\t\t\tbasic_machine=hppa1.1-hp\n\t\t\t\tbasic_os=proelf\n\t\t\t\t;;\n\t\t\ti386mach)\n\t\t\t\tbasic_machine=i386-mach\n\t\t\t\tbasic_os=mach\n\t\t\t\t;;\n\t\t\tisi68 | isi)\n\t\t\t\tbasic_machine=m68k-isi\n\t\t\t\tbasic_os=sysv\n\t\t\t\t;;\n\t\t\tm68knommu)\n\t\t\t\tbasic_machine=m68k-unknown\n\t\t\t\tbasic_os=linux\n\t\t\t\t;;\n\t\t\tmagnum | m3230)\n\t\t\t\tbasic_machine=mips-mips\n\t\t\t\tbasic_os=sysv\n\t\t\t\t;;\n\t\t\tmerlin)\n\t\t\t\tbasic_machine=ns32k-utek\n\t\t\t\tbasic_os=sysv\n\t\t\t\t;;\n\t\t\tmingw64)\n\t\t\t\tbasic_machine=x86_64-pc\n\t\t\t\tbasic_os=mingw64\n\t\t\t\t;;\n\t\t\tmingw32)\n\t\t\t\tbasic_machine=i686-pc\n\t\t\t\tbasic_os=mingw32\n\t\t\t\t;;\n\t\t\tmingw32ce)\n\t\t\t\tbasic_machine=arm-unknown\n\t\t\t\tbasic_os=mingw32ce\n\t\t\t\t;;\n\t\t\tmonitor)\n\t\t\t\tbasic_machine=m68k-rom68k\n\t\t\t\tbasic_os=coff\n\t\t\t\t;;\n\t\t\tmorphos)\n\t\t\t\tbasic_machine=powerpc-unknown\n\t\t\t\tbasic_os=morphos\n\t\t\t\t;;\n\t\t\tmoxiebox)\n\t\t\t\tbasic_machine=moxie-unknown\n\t\t\t\tbasic_os=moxiebox\n\t\t\t\t;;\n\t\t\tmsdos)\n\t\t\t\tbasic_machine=i386-pc\n\t\t\t\tbasic_os=msdos\n\t\t\t\t;;\n\t\t\tmsys)\n\t\t\t\tbasic_machine=i686-pc\n\t\t\t\tbasic_os=msys\n\t\t\t\t;;\n\t\t\tmvs)\n\t\t\t\tbasic_machine=i370-ibm\n\t\t\t\tbasic_os=mvs\n\t\t\t\t;;\n\t\t\tnacl)\n\t\t\t\tbasic_machine=le32-unknown\n\t\t\t\tbasic_os=nacl\n\t\t\t\t;;\n\t\t\tncr3000)\n\t\t\t\tbasic_machine=i486-ncr\n\t\t\t\tbasic_os=sysv4\n\t\t\t\t;;\n\t\t\tnetbsd386)\n\t\t\t\tbasic_machine=i386-pc\n\t\t\t\tbasic_os=netbsd\n\t\t\t\t;;\n\t\t\tnetwinder)\n\t\t\t\tbasic_machine=armv4l-rebel\n\t\t\t\tbasic_os=linux\n\t\t\t\t;;\n\t\t\tnews | news700 | news800 | news900)\n\t\t\t\tbasic_machine=m68k-sony\n\t\t\t\tbasic_os=newsos\n\t\t\t\t;;\n\t\t\tnews1000)\n\t\t\t\tbasic_machine=m68030-sony\n\t\t\t\tbasic_os=newsos\n\t\t\t\t;;\n\t\t\tnecv70)\n\t\t\t\tbasic_machine=v70-nec\n\t\t\t\tbasic_os=sysv\n\t\t\t\t;;\n\t\t\tnh3000)\n\t\t\t\tbasic_machine=m68k-harris\n\t\t\t\tbasic_os=cxux\n\t\t\t\t;;\n\t\t\tnh[45]000)\n\t\t\t\tbasic_machine=m88k-harris\n\t\t\t\tbasic_os=cxux\n\t\t\t\t;;\n\t\t\tnindy960)\n\t\t\t\tbasic_machine=i960-intel\n\t\t\t\tbasic_os=nindy\n\t\t\t\t;;\n\t\t\tmon960)\n\t\t\t\tbasic_machine=i960-intel\n\t\t\t\tbasic_os=mon960\n\t\t\t\t;;\n\t\t\tnonstopux)\n\t\t\t\tbasic_machine=mips-compaq\n\t\t\t\tbasic_os=nonstopux\n\t\t\t\t;;\n\t\t\tos400)\n\t\t\t\tbasic_machine=powerpc-ibm\n\t\t\t\tbasic_os=os400\n\t\t\t\t;;\n\t\t\tOSE68000 | ose68000)\n\t\t\t\tbasic_machine=m68000-ericsson\n\t\t\t\tbasic_os=ose\n\t\t\t\t;;\n\t\t\tos68k)\n\t\t\t\tbasic_machine=m68k-none\n\t\t\t\tbasic_os=os68k\n\t\t\t\t;;\n\t\t\tparagon)\n\t\t\t\tbasic_machine=i860-intel\n\t\t\t\tbasic_os=osf\n\t\t\t\t;;\n\t\t\tparisc)\n\t\t\t\tbasic_machine=hppa-unknown\n\t\t\t\tbasic_os=linux\n\t\t\t\t;;\n\t\t\tpsp)\n\t\t\t\tbasic_machine=mipsallegrexel-sony\n\t\t\t\tbasic_os=psp\n\t\t\t\t;;\n\t\t\tpw32)\n\t\t\t\tbasic_machine=i586-unknown\n\t\t\t\tbasic_os=pw32\n\t\t\t\t;;\n\t\t\trdos | rdos64)\n\t\t\t\tbasic_machine=x86_64-pc\n\t\t\t\tbasic_os=rdos\n\t\t\t\t;;\n\t\t\trdos32)\n\t\t\t\tbasic_machine=i386-pc\n\t\t\t\tbasic_os=rdos\n\t\t\t\t;;\n\t\t\trom68k)\n\t\t\t\tbasic_machine=m68k-rom68k\n\t\t\t\tbasic_os=coff\n\t\t\t\t;;\n\t\t\tsa29200)\n\t\t\t\tbasic_machine=a29k-amd\n\t\t\t\tbasic_os=udi\n\t\t\t\t;;\n\t\t\tsei)\n\t\t\t\tbasic_machine=mips-sei\n\t\t\t\tbasic_os=seiux\n\t\t\t\t;;\n\t\t\tsequent)\n\t\t\t\tbasic_machine=i386-sequent\n\t\t\t\tbasic_os=\n\t\t\t\t;;\n\t\t\tsps7)\n\t\t\t\tbasic_machine=m68k-bull\n\t\t\t\tbasic_os=sysv2\n\t\t\t\t;;\n\t\t\tst2000)\n\t\t\t\tbasic_machine=m68k-tandem\n\t\t\t\tbasic_os=\n\t\t\t\t;;\n\t\t\tstratus)\n\t\t\t\tbasic_machine=i860-stratus\n\t\t\t\tbasic_os=sysv4\n\t\t\t\t;;\n\t\t\tsun2)\n\t\t\t\tbasic_machine=m68000-sun\n\t\t\t\tbasic_os=\n\t\t\t\t;;\n\t\t\tsun2os3)\n\t\t\t\tbasic_machine=m68000-sun\n\t\t\t\tbasic_os=sunos3\n\t\t\t\t;;\n\t\t\tsun2os4)\n\t\t\t\tbasic_machine=m68000-sun\n\t\t\t\tbasic_os=sunos4\n\t\t\t\t;;\n\t\t\tsun3)\n\t\t\t\tbasic_machine=m68k-sun\n\t\t\t\tbasic_os=\n\t\t\t\t;;\n\t\t\tsun3os3)\n\t\t\t\tbasic_machine=m68k-sun\n\t\t\t\tbasic_os=sunos3\n\t\t\t\t;;\n\t\t\tsun3os4)\n\t\t\t\tbasic_machine=m68k-sun\n\t\t\t\tbasic_os=sunos4\n\t\t\t\t;;\n\t\t\tsun4)\n\t\t\t\tbasic_machine=sparc-sun\n\t\t\t\tbasic_os=\n\t\t\t\t;;\n\t\t\tsun4os3)\n\t\t\t\tbasic_machine=sparc-sun\n\t\t\t\tbasic_os=sunos3\n\t\t\t\t;;\n\t\t\tsun4os4)\n\t\t\t\tbasic_machine=sparc-sun\n\t\t\t\tbasic_os=sunos4\n\t\t\t\t;;\n\t\t\tsun4sol2)\n\t\t\t\tbasic_machine=sparc-sun\n\t\t\t\tbasic_os=solaris2\n\t\t\t\t;;\n\t\t\tsun386 | sun386i | roadrunner)\n\t\t\t\tbasic_machine=i386-sun\n\t\t\t\tbasic_os=\n\t\t\t\t;;\n\t\t\tsv1)\n\t\t\t\tbasic_machine=sv1-cray\n\t\t\t\tbasic_os=unicos\n\t\t\t\t;;\n\t\t\tsymmetry)\n\t\t\t\tbasic_machine=i386-sequent\n\t\t\t\tbasic_os=dynix\n\t\t\t\t;;\n\t\t\tt3e)\n\t\t\t\tbasic_machine=alphaev5-cray\n\t\t\t\tbasic_os=unicos\n\t\t\t\t;;\n\t\t\tt90)\n\t\t\t\tbasic_machine=t90-cray\n\t\t\t\tbasic_os=unicos\n\t\t\t\t;;\n\t\t\ttoad1)\n\t\t\t\tbasic_machine=pdp10-xkl\n\t\t\t\tbasic_os=tops20\n\t\t\t\t;;\n\t\t\ttpf)\n\t\t\t\tbasic_machine=s390x-ibm\n\t\t\t\tbasic_os=tpf\n\t\t\t\t;;\n\t\t\tudi29k)\n\t\t\t\tbasic_machine=a29k-amd\n\t\t\t\tbasic_os=udi\n\t\t\t\t;;\n\t\t\tultra3)\n\t\t\t\tbasic_machine=a29k-nyu\n\t\t\t\tbasic_os=sym1\n\t\t\t\t;;\n\t\t\tv810 | necv810)\n\t\t\t\tbasic_machine=v810-nec\n\t\t\t\tbasic_os=none\n\t\t\t\t;;\n\t\t\tvaxv)\n\t\t\t\tbasic_machine=vax-dec\n\t\t\t\tbasic_os=sysv\n\t\t\t\t;;\n\t\t\tvms)\n\t\t\t\tbasic_machine=vax-dec\n\t\t\t\tbasic_os=vms\n\t\t\t\t;;\n\t\t\tvsta)\n\t\t\t\tbasic_machine=i386-pc\n\t\t\t\tbasic_os=vsta\n\t\t\t\t;;\n\t\t\tvxworks960)\n\t\t\t\tbasic_machine=i960-wrs\n\t\t\t\tbasic_os=vxworks\n\t\t\t\t;;\n\t\t\tvxworks68)\n\t\t\t\tbasic_machine=m68k-wrs\n\t\t\t\tbasic_os=vxworks\n\t\t\t\t;;\n\t\t\tvxworks29k)\n\t\t\t\tbasic_machine=a29k-wrs\n\t\t\t\tbasic_os=vxworks\n\t\t\t\t;;\n\t\t\txbox)\n\t\t\t\tbasic_machine=i686-pc\n\t\t\t\tbasic_os=mingw32\n\t\t\t\t;;\n\t\t\tymp)\n\t\t\t\tbasic_machine=ymp-cray\n\t\t\t\tbasic_os=unicos\n\t\t\t\t;;\n\t\t\t*)\n\t\t\t\tbasic_machine=$1\n\t\t\t\tbasic_os=\n\t\t\t\t;;\n\t\tesac\n\t\t;;\nesac\n\n# Decode 1-component or ad-hoc basic machines\ncase $basic_machine in\n\t# Here we handle the default manufacturer of certain CPU types.  It is in\n\t# some cases the only manufacturer, in others, it is the most popular.\n\tw89k)\n\t\tcpu=hppa1.1\n\t\tvendor=winbond\n\t\t;;\n\top50n)\n\t\tcpu=hppa1.1\n\t\tvendor=oki\n\t\t;;\n\top60c)\n\t\tcpu=hppa1.1\n\t\tvendor=oki\n\t\t;;\n\tibm*)\n\t\tcpu=i370\n\t\tvendor=ibm\n\t\t;;\n\torion105)\n\t\tcpu=clipper\n\t\tvendor=highlevel\n\t\t;;\n\tmac | mpw | mac-mpw)\n\t\tcpu=m68k\n\t\tvendor=apple\n\t\t;;\n\tpmac | pmac-mpw)\n\t\tcpu=powerpc\n\t\tvendor=apple\n\t\t;;\n\n\t# Recognize the various machine names and aliases which stand\n\t# for a CPU type and a company and sometimes even an OS.\n\t3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)\n\t\tcpu=m68000\n\t\tvendor=att\n\t\t;;\n\t3b*)\n\t\tcpu=we32k\n\t\tvendor=att\n\t\t;;\n\tbluegene*)\n\t\tcpu=powerpc\n\t\tvendor=ibm\n\t\tbasic_os=cnk\n\t\t;;\n\tdecsystem10* | dec10*)\n\t\tcpu=pdp10\n\t\tvendor=dec\n\t\tbasic_os=tops10\n\t\t;;\n\tdecsystem20* | dec20*)\n\t\tcpu=pdp10\n\t\tvendor=dec\n\t\tbasic_os=tops20\n\t\t;;\n\tdelta | 3300 | motorola-3300 | motorola-delta \\\n\t      | 3300-motorola | delta-motorola)\n\t\tcpu=m68k\n\t\tvendor=motorola\n\t\t;;\n\tdpx2*)\n\t\tcpu=m68k\n\t\tvendor=bull\n\t\tbasic_os=sysv3\n\t\t;;\n\tencore | umax | mmax)\n\t\tcpu=ns32k\n\t\tvendor=encore\n\t\t;;\n\telxsi)\n\t\tcpu=elxsi\n\t\tvendor=elxsi\n\t\tbasic_os=${basic_os:-bsd}\n\t\t;;\n\tfx2800)\n\t\tcpu=i860\n\t\tvendor=alliant\n\t\t;;\n\tgenix)\n\t\tcpu=ns32k\n\t\tvendor=ns\n\t\t;;\n\th3050r* | hiux*)\n\t\tcpu=hppa1.1\n\t\tvendor=hitachi\n\t\tbasic_os=hiuxwe2\n\t\t;;\n\thp3k9[0-9][0-9] | hp9[0-9][0-9])\n\t\tcpu=hppa1.0\n\t\tvendor=hp\n\t\t;;\n\thp9k2[0-9][0-9] | hp9k31[0-9])\n\t\tcpu=m68000\n\t\tvendor=hp\n\t\t;;\n\thp9k3[2-9][0-9])\n\t\tcpu=m68k\n\t\tvendor=hp\n\t\t;;\n\thp9k6[0-9][0-9] | hp6[0-9][0-9])\n\t\tcpu=hppa1.0\n\t\tvendor=hp\n\t\t;;\n\thp9k7[0-79][0-9] | hp7[0-79][0-9])\n\t\tcpu=hppa1.1\n\t\tvendor=hp\n\t\t;;\n\thp9k78[0-9] | hp78[0-9])\n\t\t# FIXME: really hppa2.0-hp\n\t\tcpu=hppa1.1\n\t\tvendor=hp\n\t\t;;\n\thp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)\n\t\t# FIXME: really hppa2.0-hp\n\t\tcpu=hppa1.1\n\t\tvendor=hp\n\t\t;;\n\thp9k8[0-9][13679] | hp8[0-9][13679])\n\t\tcpu=hppa1.1\n\t\tvendor=hp\n\t\t;;\n\thp9k8[0-9][0-9] | hp8[0-9][0-9])\n\t\tcpu=hppa1.0\n\t\tvendor=hp\n\t\t;;\n\ti*86v32)\n\t\tcpu=`echo \"$1\" | sed -e 's/86.*/86/'`\n\t\tvendor=pc\n\t\tbasic_os=sysv32\n\t\t;;\n\ti*86v4*)\n\t\tcpu=`echo \"$1\" | sed -e 's/86.*/86/'`\n\t\tvendor=pc\n\t\tbasic_os=sysv4\n\t\t;;\n\ti*86v)\n\t\tcpu=`echo \"$1\" | sed -e 's/86.*/86/'`\n\t\tvendor=pc\n\t\tbasic_os=sysv\n\t\t;;\n\ti*86sol2)\n\t\tcpu=`echo \"$1\" | sed -e 's/86.*/86/'`\n\t\tvendor=pc\n\t\tbasic_os=solaris2\n\t\t;;\n\tj90 | j90-cray)\n\t\tcpu=j90\n\t\tvendor=cray\n\t\tbasic_os=${basic_os:-unicos}\n\t\t;;\n\tiris | iris4d)\n\t\tcpu=mips\n\t\tvendor=sgi\n\t\tcase $basic_os in\n\t\t    irix*)\n\t\t\t;;\n\t\t    *)\n\t\t\tbasic_os=irix4\n\t\t\t;;\n\t\tesac\n\t\t;;\n\tminiframe)\n\t\tcpu=m68000\n\t\tvendor=convergent\n\t\t;;\n\t*mint | mint[0-9]* | *MiNT | *MiNT[0-9]*)\n\t\tcpu=m68k\n\t\tvendor=atari\n\t\tbasic_os=mint\n\t\t;;\n\tnews-3600 | risc-news)\n\t\tcpu=mips\n\t\tvendor=sony\n\t\tbasic_os=newsos\n\t\t;;\n\tnext | m*-next)\n\t\tcpu=m68k\n\t\tvendor=next\n\t\tcase $basic_os in\n\t\t    openstep*)\n\t\t        ;;\n\t\t    nextstep*)\n\t\t\t;;\n\t\t    ns2*)\n\t\t      basic_os=nextstep2\n\t\t\t;;\n\t\t    *)\n\t\t      basic_os=nextstep3\n\t\t\t;;\n\t\tesac\n\t\t;;\n\tnp1)\n\t\tcpu=np1\n\t\tvendor=gould\n\t\t;;\n\top50n-* | op60c-*)\n\t\tcpu=hppa1.1\n\t\tvendor=oki\n\t\tbasic_os=proelf\n\t\t;;\n\tpa-hitachi)\n\t\tcpu=hppa1.1\n\t\tvendor=hitachi\n\t\tbasic_os=hiuxwe2\n\t\t;;\n\tpbd)\n\t\tcpu=sparc\n\t\tvendor=tti\n\t\t;;\n\tpbb)\n\t\tcpu=m68k\n\t\tvendor=tti\n\t\t;;\n\tpc532)\n\t\tcpu=ns32k\n\t\tvendor=pc532\n\t\t;;\n\tpn)\n\t\tcpu=pn\n\t\tvendor=gould\n\t\t;;\n\tpower)\n\t\tcpu=power\n\t\tvendor=ibm\n\t\t;;\n\tps2)\n\t\tcpu=i386\n\t\tvendor=ibm\n\t\t;;\n\trm[46]00)\n\t\tcpu=mips\n\t\tvendor=siemens\n\t\t;;\n\trtpc | rtpc-*)\n\t\tcpu=romp\n\t\tvendor=ibm\n\t\t;;\n\tsde)\n\t\tcpu=mipsisa32\n\t\tvendor=sde\n\t\tbasic_os=${basic_os:-elf}\n\t\t;;\n\tsimso-wrs)\n\t\tcpu=sparclite\n\t\tvendor=wrs\n\t\tbasic_os=vxworks\n\t\t;;\n\ttower | tower-32)\n\t\tcpu=m68k\n\t\tvendor=ncr\n\t\t;;\n\tvpp*|vx|vx-*)\n\t\tcpu=f301\n\t\tvendor=fujitsu\n\t\t;;\n\tw65)\n\t\tcpu=w65\n\t\tvendor=wdc\n\t\t;;\n\tw89k-*)\n\t\tcpu=hppa1.1\n\t\tvendor=winbond\n\t\tbasic_os=proelf\n\t\t;;\n\tnone)\n\t\tcpu=none\n\t\tvendor=none\n\t\t;;\n\tleon|leon[3-9])\n\t\tcpu=sparc\n\t\tvendor=$basic_machine\n\t\t;;\n\tleon-*|leon[3-9]-*)\n\t\tcpu=sparc\n\t\tvendor=`echo \"$basic_machine\" | sed 's/-.*//'`\n\t\t;;\n\n\t*-*)\n\t\t# shellcheck disable=SC2162\n\t\tsaved_IFS=$IFS\n\t\tIFS=\"-\" read cpu vendor <<EOF\n$basic_machine\nEOF\n\t\tIFS=$saved_IFS\n\t\t;;\n\t# We use `pc' rather than `unknown'\n\t# because (1) that's what they normally are, and\n\t# (2) the word \"unknown\" tends to confuse beginning users.\n\ti*86 | x86_64)\n\t\tcpu=$basic_machine\n\t\tvendor=pc\n\t\t;;\n\t# These rules are duplicated from below for sake of the special case above;\n\t# i.e. things that normalized to x86 arches should also default to \"pc\"\n\tpc98)\n\t\tcpu=i386\n\t\tvendor=pc\n\t\t;;\n\tx64 | amd64)\n\t\tcpu=x86_64\n\t\tvendor=pc\n\t\t;;\n\t# Recognize the basic CPU types without company name.\n\t*)\n\t\tcpu=$basic_machine\n\t\tvendor=unknown\n\t\t;;\nesac\n\nunset -v basic_machine\n\n# Decode basic machines in the full and proper CPU-Company form.\ncase $cpu-$vendor in\n\t# Here we handle the default manufacturer of certain CPU types in canonical form. It is in\n\t# some cases the only manufacturer, in others, it is the most popular.\n\tcraynv-unknown)\n\t\tvendor=cray\n\t\tbasic_os=${basic_os:-unicosmp}\n\t\t;;\n\tc90-unknown | c90-cray)\n\t\tvendor=cray\n\t\tbasic_os=${Basic_os:-unicos}\n\t\t;;\n\tfx80-unknown)\n\t\tvendor=alliant\n\t\t;;\n\tromp-unknown)\n\t\tvendor=ibm\n\t\t;;\n\tmmix-unknown)\n\t\tvendor=knuth\n\t\t;;\n\tmicroblaze-unknown | microblazeel-unknown)\n\t\tvendor=xilinx\n\t\t;;\n\trs6000-unknown)\n\t\tvendor=ibm\n\t\t;;\n\tvax-unknown)\n\t\tvendor=dec\n\t\t;;\n\tpdp11-unknown)\n\t\tvendor=dec\n\t\t;;\n\twe32k-unknown)\n\t\tvendor=att\n\t\t;;\n\tcydra-unknown)\n\t\tvendor=cydrome\n\t\t;;\n\ti370-ibm*)\n\t\tvendor=ibm\n\t\t;;\n\torion-unknown)\n\t\tvendor=highlevel\n\t\t;;\n\txps-unknown | xps100-unknown)\n\t\tcpu=xps100\n\t\tvendor=honeywell\n\t\t;;\n\n\t# Here we normalize CPU types with a missing or matching vendor\n\tdpx20-unknown | dpx20-bull)\n\t\tcpu=rs6000\n\t\tvendor=bull\n\t\tbasic_os=${basic_os:-bosx}\n\t\t;;\n\n\t# Here we normalize CPU types irrespective of the vendor\n\tamd64-*)\n\t\tcpu=x86_64\n\t\t;;\n\tblackfin-*)\n\t\tcpu=bfin\n\t\tbasic_os=linux\n\t\t;;\n\tc54x-*)\n\t\tcpu=tic54x\n\t\t;;\n\tc55x-*)\n\t\tcpu=tic55x\n\t\t;;\n\tc6x-*)\n\t\tcpu=tic6x\n\t\t;;\n\te500v[12]-*)\n\t\tcpu=powerpc\n\t\tbasic_os=${basic_os}\"spe\"\n\t\t;;\n\tmips3*-*)\n\t\tcpu=mips64\n\t\t;;\n\tms1-*)\n\t\tcpu=mt\n\t\t;;\n\tm68knommu-*)\n\t\tcpu=m68k\n\t\tbasic_os=linux\n\t\t;;\n\tm9s12z-* | m68hcs12z-* | hcs12z-* | s12z-*)\n\t\tcpu=s12z\n\t\t;;\n\topenrisc-*)\n\t\tcpu=or32\n\t\t;;\n\tparisc-*)\n\t\tcpu=hppa\n\t\tbasic_os=linux\n\t\t;;\n\tpentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)\n\t\tcpu=i586\n\t\t;;\n\tpentiumpro-* | p6-* | 6x86-* | athlon-* | athalon_*-*)\n\t\tcpu=i686\n\t\t;;\n\tpentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)\n\t\tcpu=i686\n\t\t;;\n\tpentium4-*)\n\t\tcpu=i786\n\t\t;;\n\tpc98-*)\n\t\tcpu=i386\n\t\t;;\n\tppc-* | ppcbe-*)\n\t\tcpu=powerpc\n\t\t;;\n\tppcle-* | powerpclittle-*)\n\t\tcpu=powerpcle\n\t\t;;\n\tppc64-*)\n\t\tcpu=powerpc64\n\t\t;;\n\tppc64le-* | powerpc64little-*)\n\t\tcpu=powerpc64le\n\t\t;;\n\tsb1-*)\n\t\tcpu=mipsisa64sb1\n\t\t;;\n\tsb1el-*)\n\t\tcpu=mipsisa64sb1el\n\t\t;;\n\tsh5e[lb]-*)\n\t\tcpu=`echo \"$cpu\" | sed 's/^\\(sh.\\)e\\(.\\)$/\\1\\2e/'`\n\t\t;;\n\tspur-*)\n\t\tcpu=spur\n\t\t;;\n\tstrongarm-* | thumb-*)\n\t\tcpu=arm\n\t\t;;\n\ttx39-*)\n\t\tcpu=mipstx39\n\t\t;;\n\ttx39el-*)\n\t\tcpu=mipstx39el\n\t\t;;\n\tx64-*)\n\t\tcpu=x86_64\n\t\t;;\n\txscale-* | xscalee[bl]-*)\n\t\tcpu=`echo \"$cpu\" | sed 's/^xscale/arm/'`\n\t\t;;\n\tarm64-*)\n\t\tcpu=aarch64\n\t\t;;\n\n\t# Recognize the canonical CPU Types that limit and/or modify the\n\t# company names they are paired with.\n\tcr16-*)\n\t\tbasic_os=${basic_os:-elf}\n\t\t;;\n\tcrisv32-* | etraxfs*-*)\n\t\tcpu=crisv32\n\t\tvendor=axis\n\t\t;;\n\tcris-* | etrax*-*)\n\t\tcpu=cris\n\t\tvendor=axis\n\t\t;;\n\tcrx-*)\n\t\tbasic_os=${basic_os:-elf}\n\t\t;;\n\tneo-tandem)\n\t\tcpu=neo\n\t\tvendor=tandem\n\t\t;;\n\tnse-tandem)\n\t\tcpu=nse\n\t\tvendor=tandem\n\t\t;;\n\tnsr-tandem)\n\t\tcpu=nsr\n\t\tvendor=tandem\n\t\t;;\n\tnsv-tandem)\n\t\tcpu=nsv\n\t\tvendor=tandem\n\t\t;;\n\tnsx-tandem)\n\t\tcpu=nsx\n\t\tvendor=tandem\n\t\t;;\n\tmipsallegrexel-sony)\n\t\tcpu=mipsallegrexel\n\t\tvendor=sony\n\t\t;;\n\ttile*-*)\n\t\tbasic_os=${basic_os:-linux-gnu}\n\t\t;;\n\n\t*)\n\t\t# Recognize the canonical CPU types that are allowed with any\n\t\t# company name.\n\t\tcase $cpu in\n\t\t\t1750a | 580 \\\n\t\t\t| a29k \\\n\t\t\t| aarch64 | aarch64_be \\\n\t\t\t| abacus \\\n\t\t\t| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] \\\n\t\t\t| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] \\\n\t\t\t| alphapca5[67] | alpha64pca5[67] \\\n\t\t\t| am33_2.0 \\\n\t\t\t| amdgcn \\\n\t\t\t| arc | arceb | arc32 | arc64 \\\n\t\t\t| arm | arm[lb]e | arme[lb] | armv* \\\n\t\t\t| avr | avr32 \\\n\t\t\t| asmjs \\\n\t\t\t| ba \\\n\t\t\t| be32 | be64 \\\n\t\t\t| bfin | bpf | bs2000 \\\n\t\t\t| c[123]* | c30 | [cjt]90 | c4x \\\n\t\t\t| c8051 | clipper | craynv | csky | cydra \\\n\t\t\t| d10v | d30v | dlx | dsp16xx \\\n\t\t\t| e2k | elxsi | epiphany \\\n\t\t\t| f30[01] | f700 | fido | fr30 | frv | ft32 | fx80 \\\n\t\t\t| h8300 | h8500 \\\n\t\t\t| hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \\\n\t\t\t| hexagon \\\n\t\t\t| i370 | i*86 | i860 | i960 | ia16 | ia64 \\\n\t\t\t| ip2k | iq2000 \\\n\t\t\t| k1om \\\n\t\t\t| le32 | le64 \\\n\t\t\t| lm32 \\\n\t\t\t| loongarch32 | loongarch64 | loongarchx32 \\\n\t\t\t| m32c | m32r | m32rle \\\n\t\t\t| m5200 | m68000 | m680[012346]0 | m68360 | m683?2 | m68k \\\n\t\t\t| m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x \\\n\t\t\t| m88110 | m88k | maxq | mb | mcore | mep | metag \\\n\t\t\t| microblaze | microblazeel \\\n\t\t\t| mips | mipsbe | mipseb | mipsel | mipsle \\\n\t\t\t| mips16 \\\n\t\t\t| mips64 | mips64eb | mips64el \\\n\t\t\t| mips64octeon | mips64octeonel \\\n\t\t\t| mips64orion | mips64orionel \\\n\t\t\t| mips64r5900 | mips64r5900el \\\n\t\t\t| mips64vr | mips64vrel \\\n\t\t\t| mips64vr4100 | mips64vr4100el \\\n\t\t\t| mips64vr4300 | mips64vr4300el \\\n\t\t\t| mips64vr5000 | mips64vr5000el \\\n\t\t\t| mips64vr5900 | mips64vr5900el \\\n\t\t\t| mipsisa32 | mipsisa32el \\\n\t\t\t| mipsisa32r2 | mipsisa32r2el \\\n\t\t\t| mipsisa32r3 | mipsisa32r3el \\\n\t\t\t| mipsisa32r5 | mipsisa32r5el \\\n\t\t\t| mipsisa32r6 | mipsisa32r6el \\\n\t\t\t| mipsisa64 | mipsisa64el \\\n\t\t\t| mipsisa64r2 | mipsisa64r2el \\\n\t\t\t| mipsisa64r3 | mipsisa64r3el \\\n\t\t\t| mipsisa64r5 | mipsisa64r5el \\\n\t\t\t| mipsisa64r6 | mipsisa64r6el \\\n\t\t\t| mipsisa64sb1 | mipsisa64sb1el \\\n\t\t\t| mipsisa64sr71k | mipsisa64sr71kel \\\n\t\t\t| mipsr5900 | mipsr5900el \\\n\t\t\t| mipstx39 | mipstx39el \\\n\t\t\t| mmix \\\n\t\t\t| mn10200 | mn10300 \\\n\t\t\t| moxie \\\n\t\t\t| mt \\\n\t\t\t| msp430 \\\n\t\t\t| nds32 | nds32le | nds32be \\\n\t\t\t| nfp \\\n\t\t\t| nios | nios2 | nios2eb | nios2el \\\n\t\t\t| none | np1 | ns16k | ns32k | nvptx \\\n\t\t\t| open8 \\\n\t\t\t| or1k* \\\n\t\t\t| or32 \\\n\t\t\t| orion \\\n\t\t\t| picochip \\\n\t\t\t| pdp10 | pdp11 | pj | pjl | pn | power \\\n\t\t\t| powerpc | powerpc64 | powerpc64le | powerpcle | powerpcspe \\\n\t\t\t| pru \\\n\t\t\t| pyramid \\\n\t\t\t| riscv | riscv32 | riscv32be | riscv64 | riscv64be \\\n\t\t\t| rl78 | romp | rs6000 | rx \\\n\t\t\t| s390 | s390x \\\n\t\t\t| score \\\n\t\t\t| sh | shl \\\n\t\t\t| sh[1234] | sh[24]a | sh[24]ae[lb] | sh[23]e | she[lb] | sh[lb]e \\\n\t\t\t| sh[1234]e[lb] |  sh[12345][lb]e | sh[23]ele | sh64 | sh64le \\\n\t\t\t| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet \\\n\t\t\t| sparclite \\\n\t\t\t| sparcv8 | sparcv9 | sparcv9b | sparcv9v | sv1 | sx* \\\n\t\t\t| spu \\\n\t\t\t| tahoe \\\n\t\t\t| thumbv7* \\\n\t\t\t| tic30 | tic4x | tic54x | tic55x | tic6x | tic80 \\\n\t\t\t| tron \\\n\t\t\t| ubicom32 \\\n\t\t\t| v70 | v850 | v850e | v850e1 | v850es | v850e2 | v850e2v3 \\\n\t\t\t| vax \\\n\t\t\t| visium \\\n\t\t\t| w65 \\\n\t\t\t| wasm32 | wasm64 \\\n\t\t\t| we32k \\\n\t\t\t| x86 | x86_64 | xc16x | xgate | xps100 \\\n\t\t\t| xstormy16 | xtensa* \\\n\t\t\t| ymp \\\n\t\t\t| z8k | z80)\n\t\t\t\t;;\n\n\t\t\t*)\n\t\t\t\techo Invalid configuration \\`\"$1\"\\': machine \\`\"$cpu-$vendor\"\\' not recognized 1>&2\n\t\t\t\texit 1\n\t\t\t\t;;\n\t\tesac\n\t\t;;\nesac\n\n# Here we canonicalize certain aliases for manufacturers.\ncase $vendor in\n\tdigital*)\n\t\tvendor=dec\n\t\t;;\n\tcommodore*)\n\t\tvendor=cbm\n\t\t;;\n\t*)\n\t\t;;\nesac\n\n# Decode manufacturer-specific aliases for certain operating systems.\n\nif test x$basic_os != x\nthen\n\n# First recognize some ad-hoc cases, or perhaps split kernel-os, or else just\n# set os.\ncase $basic_os in\n\tgnu/linux*)\n\t\tkernel=linux\n\t\tos=`echo \"$basic_os\" | sed -e 's|gnu/linux|gnu|'`\n\t\t;;\n\tos2-emx)\n\t\tkernel=os2\n\t\tos=`echo \"$basic_os\" | sed -e 's|os2-emx|emx|'`\n\t\t;;\n\tnto-qnx*)\n\t\tkernel=nto\n\t\tos=`echo \"$basic_os\" | sed -e 's|nto-qnx|qnx|'`\n\t\t;;\n\t*-*)\n\t\t# shellcheck disable=SC2162\n\t\tsaved_IFS=$IFS\n\t\tIFS=\"-\" read kernel os <<EOF\n$basic_os\nEOF\n\t\tIFS=$saved_IFS\n\t\t;;\n\t# Default OS when just kernel was specified\n\tnto*)\n\t\tkernel=nto\n\t\tos=`echo \"$basic_os\" | sed -e 's|nto|qnx|'`\n\t\t;;\n\tlinux*)\n\t\tkernel=linux\n\t\tos=`echo \"$basic_os\" | sed -e 's|linux|gnu|'`\n\t\t;;\n\t*)\n\t\tkernel=\n\t\tos=$basic_os\n\t\t;;\nesac\n\n# Now, normalize the OS (knowing we just have one component, it's not a kernel,\n# etc.)\ncase $os in\n\t# First match some system type aliases that might get confused\n\t# with valid system types.\n\t# solaris* is a basic system type, with this one exception.\n\tauroraux)\n\t\tos=auroraux\n\t\t;;\n\tbluegene*)\n\t\tos=cnk\n\t\t;;\n\tsolaris1 | solaris1.*)\n\t\tos=`echo \"$os\" | sed -e 's|solaris1|sunos4|'`\n\t\t;;\n\tsolaris)\n\t\tos=solaris2\n\t\t;;\n\tunixware*)\n\t\tos=sysv4.2uw\n\t\t;;\n\t# es1800 is here to avoid being matched by es* (a different OS)\n\tes1800*)\n\t\tos=ose\n\t\t;;\n\t# Some version numbers need modification\n\tchorusos*)\n\t\tos=chorusos\n\t\t;;\n\tisc)\n\t\tos=isc2.2\n\t\t;;\n\tsco6)\n\t\tos=sco5v6\n\t\t;;\n\tsco5)\n\t\tos=sco3.2v5\n\t\t;;\n\tsco4)\n\t\tos=sco3.2v4\n\t\t;;\n\tsco3.2.[4-9]*)\n\t\tos=`echo \"$os\" | sed -e 's/sco3.2./sco3.2v/'`\n\t\t;;\n\tsco*v* | scout)\n\t\t# Don't match below\n\t\t;;\n\tsco*)\n\t\tos=sco3.2v2\n\t\t;;\n\tpsos*)\n\t\tos=psos\n\t\t;;\n\tqnx*)\n\t\tos=qnx\n\t\t;;\n\thiux*)\n\t\tos=hiuxwe2\n\t\t;;\n\tlynx*178)\n\t\tos=lynxos178\n\t\t;;\n\tlynx*5)\n\t\tos=lynxos5\n\t\t;;\n\tlynxos*)\n\t\t# don't get caught up in next wildcard\n\t\t;;\n\tlynx*)\n\t\tos=lynxos\n\t\t;;\n\tmac[0-9]*)\n\t\tos=`echo \"$os\" | sed -e 's|mac|macos|'`\n\t\t;;\n\topened*)\n\t\tos=openedition\n\t\t;;\n\tos400*)\n\t\tos=os400\n\t\t;;\n\tsunos5*)\n\t\tos=`echo \"$os\" | sed -e 's|sunos5|solaris2|'`\n\t\t;;\n\tsunos6*)\n\t\tos=`echo \"$os\" | sed -e 's|sunos6|solaris3|'`\n\t\t;;\n\twince*)\n\t\tos=wince\n\t\t;;\n\tutek*)\n\t\tos=bsd\n\t\t;;\n\tdynix*)\n\t\tos=bsd\n\t\t;;\n\tacis*)\n\t\tos=aos\n\t\t;;\n\tatheos*)\n\t\tos=atheos\n\t\t;;\n\tsyllable*)\n\t\tos=syllable\n\t\t;;\n\t386bsd)\n\t\tos=bsd\n\t\t;;\n\tctix* | uts*)\n\t\tos=sysv\n\t\t;;\n\tnova*)\n\t\tos=rtmk-nova\n\t\t;;\n\tns2)\n\t\tos=nextstep2\n\t\t;;\n\t# Preserve the version number of sinix5.\n\tsinix5.*)\n\t\tos=`echo \"$os\" | sed -e 's|sinix|sysv|'`\n\t\t;;\n\tsinix*)\n\t\tos=sysv4\n\t\t;;\n\ttpf*)\n\t\tos=tpf\n\t\t;;\n\ttriton*)\n\t\tos=sysv3\n\t\t;;\n\toss*)\n\t\tos=sysv3\n\t\t;;\n\tsvr4*)\n\t\tos=sysv4\n\t\t;;\n\tsvr3)\n\t\tos=sysv3\n\t\t;;\n\tsysvr4)\n\t\tos=sysv4\n\t\t;;\n\tose*)\n\t\tos=ose\n\t\t;;\n\t*mint | mint[0-9]* | *MiNT | MiNT[0-9]*)\n\t\tos=mint\n\t\t;;\n\tdicos*)\n\t\tos=dicos\n\t\t;;\n\tpikeos*)\n\t\t# Until real need of OS specific support for\n\t\t# particular features comes up, bare metal\n\t\t# configurations are quite functional.\n\t\tcase $cpu in\n\t\t    arm*)\n\t\t\tos=eabi\n\t\t\t;;\n\t\t    *)\n\t\t\tos=elf\n\t\t\t;;\n\t\tesac\n\t\t;;\n\t*)\n\t\t# No normalization, but not necessarily accepted, that comes below.\n\t\t;;\nesac\n\nelse\n\n# Here we handle the default operating systems that come with various machines.\n# The value should be what the vendor currently ships out the door with their\n# machine or put another way, the most popular os provided with the machine.\n\n# Note that if you're going to try to match \"-MANUFACTURER\" here (say,\n# \"-sun\"), then you have to tell the case statement up towards the top\n# that MANUFACTURER isn't an operating system.  Otherwise, code above\n# will signal an error saying that MANUFACTURER isn't an operating\n# system, and we'll never get to this point.\n\nkernel=\ncase $cpu-$vendor in\n\tscore-*)\n\t\tos=elf\n\t\t;;\n\tspu-*)\n\t\tos=elf\n\t\t;;\n\t*-acorn)\n\t\tos=riscix1.2\n\t\t;;\n\tarm*-rebel)\n\t\tkernel=linux\n\t\tos=gnu\n\t\t;;\n\tarm*-semi)\n\t\tos=aout\n\t\t;;\n\tc4x-* | tic4x-*)\n\t\tos=coff\n\t\t;;\n\tc8051-*)\n\t\tos=elf\n\t\t;;\n\tclipper-intergraph)\n\t\tos=clix\n\t\t;;\n\thexagon-*)\n\t\tos=elf\n\t\t;;\n\ttic54x-*)\n\t\tos=coff\n\t\t;;\n\ttic55x-*)\n\t\tos=coff\n\t\t;;\n\ttic6x-*)\n\t\tos=coff\n\t\t;;\n\t# This must come before the *-dec entry.\n\tpdp10-*)\n\t\tos=tops20\n\t\t;;\n\tpdp11-*)\n\t\tos=none\n\t\t;;\n\t*-dec | vax-*)\n\t\tos=ultrix4.2\n\t\t;;\n\tm68*-apollo)\n\t\tos=domain\n\t\t;;\n\ti386-sun)\n\t\tos=sunos4.0.2\n\t\t;;\n\tm68000-sun)\n\t\tos=sunos3\n\t\t;;\n\tm68*-cisco)\n\t\tos=aout\n\t\t;;\n\tmep-*)\n\t\tos=elf\n\t\t;;\n\tmips*-cisco)\n\t\tos=elf\n\t\t;;\n\tmips*-*)\n\t\tos=elf\n\t\t;;\n\tor32-*)\n\t\tos=coff\n\t\t;;\n\t*-tti)\t# must be before sparc entry or we get the wrong os.\n\t\tos=sysv3\n\t\t;;\n\tsparc-* | *-sun)\n\t\tos=sunos4.1.1\n\t\t;;\n\tpru-*)\n\t\tos=elf\n\t\t;;\n\t*-be)\n\t\tos=beos\n\t\t;;\n\t*-ibm)\n\t\tos=aix\n\t\t;;\n\t*-knuth)\n\t\tos=mmixware\n\t\t;;\n\t*-wec)\n\t\tos=proelf\n\t\t;;\n\t*-winbond)\n\t\tos=proelf\n\t\t;;\n\t*-oki)\n\t\tos=proelf\n\t\t;;\n\t*-hp)\n\t\tos=hpux\n\t\t;;\n\t*-hitachi)\n\t\tos=hiux\n\t\t;;\n\ti860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)\n\t\tos=sysv\n\t\t;;\n\t*-cbm)\n\t\tos=amigaos\n\t\t;;\n\t*-dg)\n\t\tos=dgux\n\t\t;;\n\t*-dolphin)\n\t\tos=sysv3\n\t\t;;\n\tm68k-ccur)\n\t\tos=rtu\n\t\t;;\n\tm88k-omron*)\n\t\tos=luna\n\t\t;;\n\t*-next)\n\t\tos=nextstep\n\t\t;;\n\t*-sequent)\n\t\tos=ptx\n\t\t;;\n\t*-crds)\n\t\tos=unos\n\t\t;;\n\t*-ns)\n\t\tos=genix\n\t\t;;\n\ti370-*)\n\t\tos=mvs\n\t\t;;\n\t*-gould)\n\t\tos=sysv\n\t\t;;\n\t*-highlevel)\n\t\tos=bsd\n\t\t;;\n\t*-encore)\n\t\tos=bsd\n\t\t;;\n\t*-sgi)\n\t\tos=irix\n\t\t;;\n\t*-siemens)\n\t\tos=sysv4\n\t\t;;\n\t*-masscomp)\n\t\tos=rtu\n\t\t;;\n\tf30[01]-fujitsu | f700-fujitsu)\n\t\tos=uxpv\n\t\t;;\n\t*-rom68k)\n\t\tos=coff\n\t\t;;\n\t*-*bug)\n\t\tos=coff\n\t\t;;\n\t*-apple)\n\t\tos=macos\n\t\t;;\n\t*-atari*)\n\t\tos=mint\n\t\t;;\n\t*-wrs)\n\t\tos=vxworks\n\t\t;;\n\t*)\n\t\tos=none\n\t\t;;\nesac\n\nfi\n\n# Now, validate our (potentially fixed-up) OS.\ncase $os in\n\t# Sometimes we do \"kernel-libc\", so those need to count as OSes.\n\tmusl* | newlib* | relibc* | uclibc*)\n\t\t;;\n\t# Likewise for \"kernel-abi\"\n\teabi* | gnueabi*)\n\t\t;;\n\t# VxWorks passes extra cpu info in the 4th filed.\n\tsimlinux | simwindows | spe)\n\t\t;;\n\t# Now accept the basic system types.\n\t# The portable systems comes first.\n\t# Each alternative MUST end in a * to match a version number.\n\tgnu* | android* | bsd* | mach* | minix* | genix* | ultrix* | irix* \\\n\t     | *vms* | esix* | aix* | cnk* | sunos | sunos[34]* \\\n\t     | hpux* | unos* | osf* | luna* | dgux* | auroraux* | solaris* \\\n\t     | sym* |  plan9* | psp* | sim* | xray* | os68k* | v88r* \\\n\t     | hiux* | abug | nacl* | netware* | windows* \\\n\t     | os9* | macos* | osx* | ios* \\\n\t     | mpw* | magic* | mmixware* | mon960* | lnews* \\\n\t     | amigaos* | amigados* | msdos* | newsos* | unicos* | aof* \\\n\t     | aos* | aros* | cloudabi* | sortix* | twizzler* \\\n\t     | nindy* | vxsim* | vxworks* | ebmon* | hms* | mvs* \\\n\t     | clix* | riscos* | uniplus* | iris* | isc* | rtu* | xenix* \\\n\t     | mirbsd* | netbsd* | dicos* | openedition* | ose* \\\n\t     | bitrig* | openbsd* | secbsd* | solidbsd* | libertybsd* | os108* \\\n\t     | ekkobsd* | freebsd* | riscix* | lynxos* | os400* \\\n\t     | bosx* | nextstep* | cxux* | aout* | elf* | oabi* \\\n\t     | ptx* | coff* | ecoff* | winnt* | domain* | vsta* \\\n\t     | udi* | lites* | ieee* | go32* | aux* | hcos* \\\n\t     | chorusrdb* | cegcc* | glidix* | serenity* \\\n\t     | cygwin* | msys* | pe* | moss* | proelf* | rtems* \\\n\t     | midipix* | mingw32* | mingw64* | mint* \\\n\t     | uxpv* | beos* | mpeix* | udk* | moxiebox* \\\n\t     | interix* | uwin* | mks* | rhapsody* | darwin* \\\n\t     | openstep* | oskit* | conix* | pw32* | nonstopux* \\\n\t     | storm-chaos* | tops10* | tenex* | tops20* | its* \\\n\t     | os2* | vos* | palmos* | uclinux* | nucleus* | morphos* \\\n\t     | scout* | superux* | sysv* | rtmk* | tpf* | windiss* \\\n\t     | powermax* | dnix* | nx6 | nx7 | sei* | dragonfly* \\\n\t     | skyos* | haiku* | rdos* | toppers* | drops* | es* \\\n\t     | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \\\n\t     | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \\\n\t     | nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr* \\\n\t     | fiwix* )\n\t\t;;\n\t# This one is extra strict with allowed versions\n\tsco3.2v2 | sco3.2v[4-9]* | sco5v6*)\n\t\t# Don't forget version if it is 3.2v4 or newer.\n\t\t;;\n\tnone)\n\t\t;;\n\t*)\n\t\techo Invalid configuration \\`\"$1\"\\': OS \\`\"$os\"\\' not recognized 1>&2\n\t\texit 1\n\t\t;;\nesac\n\n# As a final step for OS-related things, validate the OS-kernel combination\n# (given a valid OS), if there is a kernel.\ncase $kernel-$os in\n\tlinux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* \\\n\t\t   | linux-musl* | linux-relibc* | linux-uclibc* )\n\t\t;;\n\tuclinux-uclibc* )\n\t\t;;\n\t-dietlibc* | -newlib* | -musl* | -relibc* | -uclibc* )\n\t\t# These are just libc implementations, not actual OSes, and thus\n\t\t# require a kernel.\n\t\techo \"Invalid configuration \\`$1': libc \\`$os' needs explicit kernel.\" 1>&2\n\t\texit 1\n\t\t;;\n\tkfreebsd*-gnu* | kopensolaris*-gnu*)\n\t\t;;\n\tvxworks-simlinux | vxworks-simwindows | vxworks-spe)\n\t\t;;\n\tnto-qnx*)\n\t\t;;\n\tos2-emx)\n\t\t;;\n\t*-eabi* | *-gnueabi*)\n\t\t;;\n\t-*)\n\t\t# Blank kernel with real OS is always fine.\n\t\t;;\n\t*-*)\n\t\techo \"Invalid configuration \\`$1': Kernel \\`$kernel' not known to work with OS \\`$os'.\" 1>&2\n\t\texit 1\n\t\t;;\nesac\n\n# Here we handle the case where we know the os, and the CPU type, but not the\n# manufacturer.  We pick the logical manufacturer.\ncase $vendor in\n\tunknown)\n\t\tcase $cpu-$os in\n\t\t\t*-riscix*)\n\t\t\t\tvendor=acorn\n\t\t\t\t;;\n\t\t\t*-sunos*)\n\t\t\t\tvendor=sun\n\t\t\t\t;;\n\t\t\t*-cnk* | *-aix*)\n\t\t\t\tvendor=ibm\n\t\t\t\t;;\n\t\t\t*-beos*)\n\t\t\t\tvendor=be\n\t\t\t\t;;\n\t\t\t*-hpux*)\n\t\t\t\tvendor=hp\n\t\t\t\t;;\n\t\t\t*-mpeix*)\n\t\t\t\tvendor=hp\n\t\t\t\t;;\n\t\t\t*-hiux*)\n\t\t\t\tvendor=hitachi\n\t\t\t\t;;\n\t\t\t*-unos*)\n\t\t\t\tvendor=crds\n\t\t\t\t;;\n\t\t\t*-dgux*)\n\t\t\t\tvendor=dg\n\t\t\t\t;;\n\t\t\t*-luna*)\n\t\t\t\tvendor=omron\n\t\t\t\t;;\n\t\t\t*-genix*)\n\t\t\t\tvendor=ns\n\t\t\t\t;;\n\t\t\t*-clix*)\n\t\t\t\tvendor=intergraph\n\t\t\t\t;;\n\t\t\t*-mvs* | *-opened*)\n\t\t\t\tvendor=ibm\n\t\t\t\t;;\n\t\t\t*-os400*)\n\t\t\t\tvendor=ibm\n\t\t\t\t;;\n\t\t\ts390-* | s390x-*)\n\t\t\t\tvendor=ibm\n\t\t\t\t;;\n\t\t\t*-ptx*)\n\t\t\t\tvendor=sequent\n\t\t\t\t;;\n\t\t\t*-tpf*)\n\t\t\t\tvendor=ibm\n\t\t\t\t;;\n\t\t\t*-vxsim* | *-vxworks* | *-windiss*)\n\t\t\t\tvendor=wrs\n\t\t\t\t;;\n\t\t\t*-aux*)\n\t\t\t\tvendor=apple\n\t\t\t\t;;\n\t\t\t*-hms*)\n\t\t\t\tvendor=hitachi\n\t\t\t\t;;\n\t\t\t*-mpw* | *-macos*)\n\t\t\t\tvendor=apple\n\t\t\t\t;;\n\t\t\t*-*mint | *-mint[0-9]* | *-*MiNT | *-MiNT[0-9]*)\n\t\t\t\tvendor=atari\n\t\t\t\t;;\n\t\t\t*-vos*)\n\t\t\t\tvendor=stratus\n\t\t\t\t;;\n\t\tesac\n\t\t;;\nesac\n\necho \"$cpu-$vendor-${kernel:+$kernel-}$os\"\nexit\n\n# Local variables:\n# eval: (add-hook 'before-save-hook 'time-stamp)\n# time-stamp-start: \"timestamp='\"\n# time-stamp-format: \"%:y-%02m-%02d\"\n# time-stamp-end: \"'\"\n# End:\n"
  },
  {
    "path": "src/vendor/libbacktrace/configure",
    "content": "#! /bin/sh\n# Guess values for system-dependent variables and create Makefiles.\n# Generated by GNU Autoconf 2.69 for package-unused version-unused.\n#\n#\n# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.\n#\n#\n# This configure script is free software; the Free Software Foundation\n# gives unlimited permission to copy, distribute and modify it.\n## -------------------- ##\n## M4sh Initialization. ##\n## -------------------- ##\n\n# Be more Bourne compatible\nDUALCASE=1; export DUALCASE # for MKS sh\nif test -n \"${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :\n  emulate sh\n  NULLCMD=:\n  # Pre-4.2 versions of Zsh do word splitting on ${1+\"$@\"}, which\n  # is contrary to our usage.  Disable this feature.\n  alias -g '${1+\"$@\"}'='\"$@\"'\n  setopt NO_GLOB_SUBST\nelse\n  case `(set -o) 2>/dev/null` in #(\n  *posix*) :\n    set -o posix ;; #(\n  *) :\n     ;;\nesac\nfi\n\n\nas_nl='\n'\nexport as_nl\n# Printing a long string crashes Solaris 7 /usr/bin/printf.\nas_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'\nas_echo=$as_echo$as_echo$as_echo$as_echo$as_echo\nas_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo\n# Prefer a ksh shell builtin over an external printf program on Solaris,\n# but without wasting forks for bash or zsh.\nif test -z \"$BASH_VERSION$ZSH_VERSION\" \\\n    && (test \"X`print -r -- $as_echo`\" = \"X$as_echo\") 2>/dev/null; then\n  as_echo='print -r --'\n  as_echo_n='print -rn --'\nelif (test \"X`printf %s $as_echo`\" = \"X$as_echo\") 2>/dev/null; then\n  as_echo='printf %s\\n'\n  as_echo_n='printf %s'\nelse\n  if test \"X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`\" = \"X-n $as_echo\"; then\n    as_echo_body='eval /usr/ucb/echo -n \"$1$as_nl\"'\n    as_echo_n='/usr/ucb/echo -n'\n  else\n    as_echo_body='eval expr \"X$1\" : \"X\\\\(.*\\\\)\"'\n    as_echo_n_body='eval\n      arg=$1;\n      case $arg in #(\n      *\"$as_nl\"*)\n\texpr \"X$arg\" : \"X\\\\(.*\\\\)$as_nl\";\n\targ=`expr \"X$arg\" : \".*$as_nl\\\\(.*\\\\)\"`;;\n      esac;\n      expr \"X$arg\" : \"X\\\\(.*\\\\)\" | tr -d \"$as_nl\"\n    '\n    export as_echo_n_body\n    as_echo_n='sh -c $as_echo_n_body as_echo'\n  fi\n  export as_echo_body\n  as_echo='sh -c $as_echo_body as_echo'\nfi\n\n# The user is always right.\nif test \"${PATH_SEPARATOR+set}\" != set; then\n  PATH_SEPARATOR=:\n  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {\n    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||\n      PATH_SEPARATOR=';'\n  }\nfi\n\n\n# IFS\n# We need space, tab and new line, in precisely that order.  Quoting is\n# there to prevent editors from complaining about space-tab.\n# (If _AS_PATH_WALK were called with IFS unset, it would disable word\n# splitting by setting IFS to empty value.)\nIFS=\" \"\"\t$as_nl\"\n\n# Find who we are.  Look in the path if we contain no directory separator.\nas_myself=\ncase $0 in #((\n  *[\\\\/]* ) as_myself=$0 ;;\n  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    test -r \"$as_dir/$0\" && as_myself=$as_dir/$0 && break\n  done\nIFS=$as_save_IFS\n\n     ;;\nesac\n# We did not find ourselves, most probably we were run as `sh COMMAND'\n# in which case we are not to be found in the path.\nif test \"x$as_myself\" = x; then\n  as_myself=$0\nfi\nif test ! -f \"$as_myself\"; then\n  $as_echo \"$as_myself: error: cannot find myself; rerun with an absolute file name\" >&2\n  exit 1\nfi\n\n# Unset variables that we do not need and which cause bugs (e.g. in\n# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the \"|| exit 1\"\n# suppresses any \"Segmentation fault\" message there.  '((' could\n# trigger a bug in pdksh 5.2.14.\nfor as_var in BASH_ENV ENV MAIL MAILPATH\ndo eval test x\\${$as_var+set} = xset \\\n  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :\ndone\nPS1='$ '\nPS2='> '\nPS4='+ '\n\n# NLS nuisances.\nLC_ALL=C\nexport LC_ALL\nLANGUAGE=C\nexport LANGUAGE\n\n# CDPATH.\n(unset CDPATH) >/dev/null 2>&1 && unset CDPATH\n\n# Use a proper internal environment variable to ensure we don't fall\n  # into an infinite loop, continuously re-executing ourselves.\n  if test x\"${_as_can_reexec}\" != xno && test \"x$CONFIG_SHELL\" != x; then\n    _as_can_reexec=no; export _as_can_reexec;\n    # We cannot yet assume a decent shell, so we have to provide a\n# neutralization value for shells without unset; and this also\n# works around shells that cannot unset nonexistent variables.\n# Preserve -v and -x to the replacement shell.\nBASH_ENV=/dev/null\nENV=/dev/null\n(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV\ncase $- in # ((((\n  *v*x* | *x*v* ) as_opts=-vx ;;\n  *v* ) as_opts=-v ;;\n  *x* ) as_opts=-x ;;\n  * ) as_opts= ;;\nesac\nexec $CONFIG_SHELL $as_opts \"$as_myself\" ${1+\"$@\"}\n# Admittedly, this is quite paranoid, since all the known shells bail\n# out after a failed `exec'.\n$as_echo \"$0: could not re-execute with $CONFIG_SHELL\" >&2\nas_fn_exit 255\n  fi\n  # We don't want this to propagate to other subprocesses.\n          { _as_can_reexec=; unset _as_can_reexec;}\nif test \"x$CONFIG_SHELL\" = x; then\n  as_bourne_compatible=\"if test -n \\\"\\${ZSH_VERSION+set}\\\" && (emulate sh) >/dev/null 2>&1; then :\n  emulate sh\n  NULLCMD=:\n  # Pre-4.2 versions of Zsh do word splitting on \\${1+\\\"\\$@\\\"}, which\n  # is contrary to our usage.  Disable this feature.\n  alias -g '\\${1+\\\"\\$@\\\"}'='\\\"\\$@\\\"'\n  setopt NO_GLOB_SUBST\nelse\n  case \\`(set -o) 2>/dev/null\\` in #(\n  *posix*) :\n    set -o posix ;; #(\n  *) :\n     ;;\nesac\nfi\n\"\n  as_required=\"as_fn_return () { (exit \\$1); }\nas_fn_success () { as_fn_return 0; }\nas_fn_failure () { as_fn_return 1; }\nas_fn_ret_success () { return 0; }\nas_fn_ret_failure () { return 1; }\n\nexitcode=0\nas_fn_success || { exitcode=1; echo as_fn_success failed.; }\nas_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }\nas_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }\nas_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }\nif ( set x; as_fn_ret_success y && test x = \\\"\\$1\\\" ); then :\n\nelse\n  exitcode=1; echo positional parameters were not saved.\nfi\ntest x\\$exitcode = x0 || exit 1\ntest -x / || exit 1\"\n  as_suggested=\"  as_lineno_1=\";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested\" as_lineno_1a=\\$LINENO\n  as_lineno_2=\";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested\" as_lineno_2a=\\$LINENO\n  eval 'test \\\"x\\$as_lineno_1'\\$as_run'\\\" != \\\"x\\$as_lineno_2'\\$as_run'\\\" &&\n  test \\\"x\\`expr \\$as_lineno_1'\\$as_run' + 1\\`\\\" = \\\"x\\$as_lineno_2'\\$as_run'\\\"' || exit 1\ntest \\$(( 1 + 1 )) = 2 || exit 1\n\n  test -n \\\"\\${ZSH_VERSION+set}\\${BASH_VERSION+set}\\\" || (\n    ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'\n    ECHO=\\$ECHO\\$ECHO\\$ECHO\\$ECHO\\$ECHO\n    ECHO=\\$ECHO\\$ECHO\\$ECHO\\$ECHO\\$ECHO\\$ECHO\n    PATH=/empty FPATH=/empty; export PATH FPATH\n    test \\\"X\\`printf %s \\$ECHO\\`\\\" = \\\"X\\$ECHO\\\" \\\\\n      || test \\\"X\\`print -r -- \\$ECHO\\`\\\" = \\\"X\\$ECHO\\\" ) || exit 1\"\n  if (eval \"$as_required\") 2>/dev/null; then :\n  as_have_required=yes\nelse\n  as_have_required=no\nfi\n  if test x$as_have_required = xyes && (eval \"$as_suggested\") 2>/dev/null; then :\n\nelse\n  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nas_found=false\nfor as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n  as_found=:\n  case $as_dir in #(\n\t /*)\n\t   for as_base in sh bash ksh sh5; do\n\t     # Try only shells that exist, to save several forks.\n\t     as_shell=$as_dir/$as_base\n\t     if { test -f \"$as_shell\" || test -f \"$as_shell.exe\"; } &&\n\t\t    { $as_echo \"$as_bourne_compatible\"\"$as_required\" | as_run=a \"$as_shell\"; } 2>/dev/null; then :\n  CONFIG_SHELL=$as_shell as_have_required=yes\n\t\t   if { $as_echo \"$as_bourne_compatible\"\"$as_suggested\" | as_run=a \"$as_shell\"; } 2>/dev/null; then :\n  break 2\nfi\nfi\n\t   done;;\n       esac\n  as_found=false\ndone\n$as_found || { if { test -f \"$SHELL\" || test -f \"$SHELL.exe\"; } &&\n\t      { $as_echo \"$as_bourne_compatible\"\"$as_required\" | as_run=a \"$SHELL\"; } 2>/dev/null; then :\n  CONFIG_SHELL=$SHELL as_have_required=yes\nfi; }\nIFS=$as_save_IFS\n\n\n      if test \"x$CONFIG_SHELL\" != x; then :\n  export CONFIG_SHELL\n             # We cannot yet assume a decent shell, so we have to provide a\n# neutralization value for shells without unset; and this also\n# works around shells that cannot unset nonexistent variables.\n# Preserve -v and -x to the replacement shell.\nBASH_ENV=/dev/null\nENV=/dev/null\n(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV\ncase $- in # ((((\n  *v*x* | *x*v* ) as_opts=-vx ;;\n  *v* ) as_opts=-v ;;\n  *x* ) as_opts=-x ;;\n  * ) as_opts= ;;\nesac\nexec $CONFIG_SHELL $as_opts \"$as_myself\" ${1+\"$@\"}\n# Admittedly, this is quite paranoid, since all the known shells bail\n# out after a failed `exec'.\n$as_echo \"$0: could not re-execute with $CONFIG_SHELL\" >&2\nexit 255\nfi\n\n    if test x$as_have_required = xno; then :\n  $as_echo \"$0: This script requires a shell more modern than all\"\n  $as_echo \"$0: the shells that I found on your system.\"\n  if test x${ZSH_VERSION+set} = xset ; then\n    $as_echo \"$0: In particular, zsh $ZSH_VERSION has bugs and should\"\n    $as_echo \"$0: be upgraded to zsh 4.3.4 or later.\"\n  else\n    $as_echo \"$0: Please tell bug-autoconf@gnu.org about your system,\n$0: including any error possibly output before this\n$0: message. Then install a modern shell, or manually run\n$0: the script under such a shell if you do have one.\"\n  fi\n  exit 1\nfi\nfi\nfi\nSHELL=${CONFIG_SHELL-/bin/sh}\nexport SHELL\n# Unset more variables known to interfere with behavior of common tools.\nCLICOLOR_FORCE= GREP_OPTIONS=\nunset CLICOLOR_FORCE GREP_OPTIONS\n\n## --------------------- ##\n## M4sh Shell Functions. ##\n## --------------------- ##\n# as_fn_unset VAR\n# ---------------\n# Portably unset VAR.\nas_fn_unset ()\n{\n  { eval $1=; unset $1;}\n}\nas_unset=as_fn_unset\n\n# as_fn_set_status STATUS\n# -----------------------\n# Set $? to STATUS, without forking.\nas_fn_set_status ()\n{\n  return $1\n} # as_fn_set_status\n\n# as_fn_exit STATUS\n# -----------------\n# Exit the shell with STATUS, even in a \"trap 0\" or \"set -e\" context.\nas_fn_exit ()\n{\n  set +e\n  as_fn_set_status $1\n  exit $1\n} # as_fn_exit\n\n# as_fn_mkdir_p\n# -------------\n# Create \"$as_dir\" as a directory, including parents if necessary.\nas_fn_mkdir_p ()\n{\n\n  case $as_dir in #(\n  -*) as_dir=./$as_dir;;\n  esac\n  test -d \"$as_dir\" || eval $as_mkdir_p || {\n    as_dirs=\n    while :; do\n      case $as_dir in #(\n      *\\'*) as_qdir=`$as_echo \"$as_dir\" | sed \"s/'/'\\\\\\\\\\\\\\\\''/g\"`;; #'(\n      *) as_qdir=$as_dir;;\n      esac\n      as_dirs=\"'$as_qdir' $as_dirs\"\n      as_dir=`$as_dirname -- \"$as_dir\" ||\n$as_expr X\"$as_dir\" : 'X\\(.*[^/]\\)//*[^/][^/]*/*$' \\| \\\n\t X\"$as_dir\" : 'X\\(//\\)[^/]' \\| \\\n\t X\"$as_dir\" : 'X\\(//\\)$' \\| \\\n\t X\"$as_dir\" : 'X\\(/\\)' \\| . 2>/dev/null ||\n$as_echo X\"$as_dir\" |\n    sed '/^X\\(.*[^/]\\)\\/\\/*[^/][^/]*\\/*$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\/\\)[^/].*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\/\\)$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\).*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  s/.*/./; q'`\n      test -d \"$as_dir\" && break\n    done\n    test -z \"$as_dirs\" || eval \"mkdir $as_dirs\"\n  } || test -d \"$as_dir\" || as_fn_error $? \"cannot create directory $as_dir\"\n\n\n} # as_fn_mkdir_p\n\n# as_fn_executable_p FILE\n# -----------------------\n# Test if FILE is an executable regular file.\nas_fn_executable_p ()\n{\n  test -f \"$1\" && test -x \"$1\"\n} # as_fn_executable_p\n# as_fn_append VAR VALUE\n# ----------------------\n# Append the text in VALUE to the end of the definition contained in VAR. Take\n# advantage of any shell optimizations that allow amortized linear growth over\n# repeated appends, instead of the typical quadratic growth present in naive\n# implementations.\nif (eval \"as_var=1; as_var+=2; test x\\$as_var = x12\") 2>/dev/null; then :\n  eval 'as_fn_append ()\n  {\n    eval $1+=\\$2\n  }'\nelse\n  as_fn_append ()\n  {\n    eval $1=\\$$1\\$2\n  }\nfi # as_fn_append\n\n# as_fn_arith ARG...\n# ------------------\n# Perform arithmetic evaluation on the ARGs, and store the result in the\n# global $as_val. Take advantage of shells that can avoid forks. The arguments\n# must be portable across $(()) and expr.\nif (eval \"test \\$(( 1 + 1 )) = 2\") 2>/dev/null; then :\n  eval 'as_fn_arith ()\n  {\n    as_val=$(( $* ))\n  }'\nelse\n  as_fn_arith ()\n  {\n    as_val=`expr \"$@\" || test $? -eq 1`\n  }\nfi # as_fn_arith\n\n\n# as_fn_error STATUS ERROR [LINENO LOG_FD]\n# ----------------------------------------\n# Output \"`basename $0`: error: ERROR\" to stderr. If LINENO and LOG_FD are\n# provided, also output the error to LOG_FD, referencing LINENO. Then exit the\n# script with STATUS, using 1 if that was 0.\nas_fn_error ()\n{\n  as_status=$1; test $as_status -eq 0 && as_status=1\n  if test \"$4\"; then\n    as_lineno=${as_lineno-\"$3\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n    $as_echo \"$as_me:${as_lineno-$LINENO}: error: $2\" >&$4\n  fi\n  $as_echo \"$as_me: error: $2\" >&2\n  as_fn_exit $as_status\n} # as_fn_error\n\nif expr a : '\\(a\\)' >/dev/null 2>&1 &&\n   test \"X`expr 00001 : '.*\\(...\\)'`\" = X001; then\n  as_expr=expr\nelse\n  as_expr=false\nfi\n\nif (basename -- /) >/dev/null 2>&1 && test \"X`basename -- / 2>&1`\" = \"X/\"; then\n  as_basename=basename\nelse\n  as_basename=false\nfi\n\nif (as_dir=`dirname -- /` && test \"X$as_dir\" = X/) >/dev/null 2>&1; then\n  as_dirname=dirname\nelse\n  as_dirname=false\nfi\n\nas_me=`$as_basename -- \"$0\" ||\n$as_expr X/\"$0\" : '.*/\\([^/][^/]*\\)/*$' \\| \\\n\t X\"$0\" : 'X\\(//\\)$' \\| \\\n\t X\"$0\" : 'X\\(/\\)' \\| . 2>/dev/null ||\n$as_echo X/\"$0\" |\n    sed '/^.*\\/\\([^/][^/]*\\)\\/*$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\/\\(\\/\\/\\)$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\/\\(\\/\\).*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  s/.*/./; q'`\n\n# Avoid depending upon Character Ranges.\nas_cr_letters='abcdefghijklmnopqrstuvwxyz'\nas_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'\nas_cr_Letters=$as_cr_letters$as_cr_LETTERS\nas_cr_digits='0123456789'\nas_cr_alnum=$as_cr_Letters$as_cr_digits\n\n\n  as_lineno_1=$LINENO as_lineno_1a=$LINENO\n  as_lineno_2=$LINENO as_lineno_2a=$LINENO\n  eval 'test \"x$as_lineno_1'$as_run'\" != \"x$as_lineno_2'$as_run'\" &&\n  test \"x`expr $as_lineno_1'$as_run' + 1`\" = \"x$as_lineno_2'$as_run'\"' || {\n  # Blame Lee E. McMahon (1931-1989) for sed's syntax.  :-)\n  sed -n '\n    p\n    /[$]LINENO/=\n  ' <$as_myself |\n    sed '\n      s/[$]LINENO.*/&-/\n      t lineno\n      b\n      :lineno\n      N\n      :loop\n      s/[$]LINENO\\([^'$as_cr_alnum'_].*\\n\\)\\(.*\\)/\\2\\1\\2/\n      t loop\n      s/-\\n.*//\n    ' >$as_me.lineno &&\n  chmod +x \"$as_me.lineno\" ||\n    { $as_echo \"$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell\" >&2; as_fn_exit 1; }\n\n  # If we had to re-execute with $CONFIG_SHELL, we're ensured to have\n  # already done that, so ensure we don't try to do so again and fall\n  # in an infinite loop.  This has already happened in practice.\n  _as_can_reexec=no; export _as_can_reexec\n  # Don't try to exec as it changes $[0], causing all sort of problems\n  # (the dirname of $[0] is not the place where we might find the\n  # original and so on.  Autoconf is especially sensitive to this).\n  . \"./$as_me.lineno\"\n  # Exit status is that of the last command.\n  exit\n}\n\nECHO_C= ECHO_N= ECHO_T=\ncase `echo -n x` in #(((((\n-n*)\n  case `echo 'xy\\c'` in\n  *c*) ECHO_T='\t';;\t# ECHO_T is single tab character.\n  xy)  ECHO_C='\\c';;\n  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null\n       ECHO_T='\t';;\n  esac;;\n*)\n  ECHO_N='-n';;\nesac\n\nrm -f conf$$ conf$$.exe conf$$.file\nif test -d conf$$.dir; then\n  rm -f conf$$.dir/conf$$.file\nelse\n  rm -f conf$$.dir\n  mkdir conf$$.dir 2>/dev/null\nfi\nif (echo >conf$$.file) 2>/dev/null; then\n  if ln -s conf$$.file conf$$ 2>/dev/null; then\n    as_ln_s='ln -s'\n    # ... but there are two gotchas:\n    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.\n    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.\n    # In both cases, we have to default to `cp -pR'.\n    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||\n      as_ln_s='cp -pR'\n  elif ln conf$$.file conf$$ 2>/dev/null; then\n    as_ln_s=ln\n  else\n    as_ln_s='cp -pR'\n  fi\nelse\n  as_ln_s='cp -pR'\nfi\nrm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file\nrmdir conf$$.dir 2>/dev/null\n\nif mkdir -p . 2>/dev/null; then\n  as_mkdir_p='mkdir -p \"$as_dir\"'\nelse\n  test -d ./-p && rmdir ./-p\n  as_mkdir_p=false\nfi\n\nas_test_x='test -x'\nas_executable_p=as_fn_executable_p\n\n# Sed expression to map a string onto a valid CPP name.\nas_tr_cpp=\"eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'\"\n\n# Sed expression to map a string onto a valid variable name.\nas_tr_sh=\"eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'\"\n\nSHELL=${CONFIG_SHELL-/bin/sh}\n\n\ntest -n \"$DJDIR\" || exec 7<&0 </dev/null\nexec 6>&1\n\n# Name of the host.\n# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,\n# so uname gets run too.\nac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`\n\n#\n# Initializations.\n#\nac_default_prefix=/usr/local\nac_clean_files=\nac_config_libobj_dir=.\nLIBOBJS=\ncross_compiling=no\nsubdirs=\nMFLAGS=\nMAKEFLAGS=\n\n# Identity of this package.\nPACKAGE_NAME='package-unused'\nPACKAGE_TARNAME='libbacktrace'\nPACKAGE_VERSION='version-unused'\nPACKAGE_STRING='package-unused version-unused'\nPACKAGE_BUGREPORT=''\nPACKAGE_URL=''\n\nac_unique_file=\"backtrace.h\"\n# Factoring default headers for most tests.\nac_includes_default=\"\\\n#include <stdio.h>\n#ifdef HAVE_SYS_TYPES_H\n# include <sys/types.h>\n#endif\n#ifdef HAVE_SYS_STAT_H\n# include <sys/stat.h>\n#endif\n#ifdef STDC_HEADERS\n# include <stdlib.h>\n# include <stddef.h>\n#else\n# ifdef HAVE_STDLIB_H\n#  include <stdlib.h>\n# endif\n#endif\n#ifdef HAVE_STRING_H\n# if !defined STDC_HEADERS && defined HAVE_MEMORY_H\n#  include <memory.h>\n# endif\n# include <string.h>\n#endif\n#ifdef HAVE_STRINGS_H\n# include <strings.h>\n#endif\n#ifdef HAVE_INTTYPES_H\n# include <inttypes.h>\n#endif\n#ifdef HAVE_STDINT_H\n# include <stdint.h>\n#endif\n#ifdef HAVE_UNISTD_H\n# include <unistd.h>\n#endif\"\n\nac_subst_vars='am__EXEEXT_FALSE\nam__EXEEXT_TRUE\nLTLIBOBJS\nLIBOBJS\nNATIVE_FALSE\nNATIVE_TRUE\nHAVE_LIBLZMA_FALSE\nHAVE_LIBLZMA_TRUE\nHAVE_MINIDEBUG_FALSE\nHAVE_MINIDEBUG_TRUE\nHAVE_COMM_FALSE\nHAVE_COMM_TRUE\nCOMM\nHAVE_XZ_FALSE\nHAVE_XZ_TRUE\nXZ\nUSE_DSYMUTIL_FALSE\nUSE_DSYMUTIL_TRUE\nHAVE_OBJCOPY_DEBUGLINK_FALSE\nHAVE_OBJCOPY_DEBUGLINK_TRUE\nREADELF\nOBJCOPY\nHAVE_COMPRESSED_DEBUG_ZSTD_FALSE\nHAVE_COMPRESSED_DEBUG_ZSTD_TRUE\nHAVE_ZSTD_FALSE\nHAVE_ZSTD_TRUE\nHAVE_COMPRESSED_DEBUG_ZLIB_GABI_FALSE\nHAVE_COMPRESSED_DEBUG_ZLIB_GABI_TRUE\nHAVE_COMPRESSED_DEBUG_ZLIB_GNU_FALSE\nHAVE_COMPRESSED_DEBUG_ZLIB_GNU_TRUE\nHAVE_BUILDID_FALSE\nHAVE_BUILDID_TRUE\nHAVE_ZLIB_FALSE\nHAVE_ZLIB_TRUE\nHAVE_DWARF5_FALSE\nHAVE_DWARF5_TRUE\nHAVE_PTHREAD_FALSE\nHAVE_PTHREAD_TRUE\nPTHREAD_CFLAGS\nCLOCK_GETTIME_LINK\nBACKTRACE_USES_MALLOC\nALLOC_FILE\nVIEW_FILE\nBACKTRACE_SUPPORTS_DATA\nBACKTRACE_SUPPORTED\nHAVE_ELF_FALSE\nHAVE_ELF_TRUE\nFORMAT_FILE\nBACKTRACE_SUPPORTS_THREADS\nPIC_FLAG\nWARN_FLAGS\nEXTRA_FLAGS\nBACKTRACE_FILE\nENABLE_DARWIN_AT_RPATH_FALSE\nENABLE_DARWIN_AT_RPATH_TRUE\nOTOOL64\nOTOOL\nLIPO\nNMEDIT\nDSYMUTIL\nAR\nOBJDUMP\nLN_S\nNM\nac_ct_DUMPBIN\nDUMPBIN\nLD\nFGREP\nSED\nLIBTOOL\nHAVE_DWZ_FALSE\nHAVE_DWZ_TRUE\nDWZ\nRANLIB\nMAINT\nMAINTAINER_MODE_FALSE\nMAINTAINER_MODE_TRUE\nAM_BACKSLASH\nAM_DEFAULT_VERBOSITY\nAM_DEFAULT_V\nAM_V\nam__untar\nam__tar\nAMTAR\nam__leading_dot\nSET_MAKE\nAWK\nmkdir_p\nMKDIR_P\nINSTALL_STRIP_PROGRAM\nSTRIP\ninstall_sh\nMAKEINFO\nAUTOHEADER\nAUTOMAKE\nAUTOCONF\nACLOCAL\nVERSION\nPACKAGE\nCYGPATH_W\nam__isrc\nINSTALL_DATA\nINSTALL_SCRIPT\nINSTALL_PROGRAM\nlibtool_VERSION\nEGREP\nGREP\nCPP\nOBJEXT\nEXEEXT\nac_ct_CC\nCPPFLAGS\nLDFLAGS\nCFLAGS\nCC\ntarget_os\ntarget_vendor\ntarget_cpu\ntarget\nhost_os\nhost_vendor\nhost_cpu\nhost\nbuild_os\nbuild_vendor\nbuild_cpu\nbuild\nmulti_basedir\ntarget_alias\nhost_alias\nbuild_alias\nLIBS\nECHO_T\nECHO_N\nECHO_C\nDEFS\nmandir\nlocaledir\nlibdir\npsdir\npdfdir\ndvidir\nhtmldir\ninfodir\ndocdir\noldincludedir\nincludedir\nlocalstatedir\nsharedstatedir\nsysconfdir\ndatadir\ndatarootdir\nlibexecdir\nsbindir\nbindir\nprogram_transform_name\nprefix\nexec_prefix\nPACKAGE_URL\nPACKAGE_BUGREPORT\nPACKAGE_STRING\nPACKAGE_VERSION\nPACKAGE_TARNAME\nPACKAGE_NAME\nPATH_SEPARATOR\nSHELL'\nac_subst_files=''\nac_user_opts='\nenable_option_checking\nenable_multilib\nenable_shared\nenable_silent_rules\nenable_maintainer_mode\nwith_target_subdir\nenable_static\nwith_pic\nenable_fast_install\nwith_gnu_ld\nenable_libtool_lock\nenable_darwin_at_rpath\nenable_largefile\nenable_werror\nwith_system_libunwind\nenable_host_shared\n'\n      ac_precious_vars='build_alias\nhost_alias\ntarget_alias\nCC\nCFLAGS\nLDFLAGS\nLIBS\nCPPFLAGS\nCPP\nOBJCOPY\nDSYMUTIL\nNM'\n\n\n# Initialize some variables set by options.\nac_init_help=\nac_init_version=false\nac_unrecognized_opts=\nac_unrecognized_sep=\n# The variables have the same names as the options, with\n# dashes changed to underlines.\ncache_file=/dev/null\nexec_prefix=NONE\nno_create=\nno_recursion=\nprefix=NONE\nprogram_prefix=NONE\nprogram_suffix=NONE\nprogram_transform_name=s,x,x,\nsilent=\nsite=\nsrcdir=\nverbose=\nx_includes=NONE\nx_libraries=NONE\n\n# Installation directory options.\n# These are left unexpanded so users can \"make install exec_prefix=/foo\"\n# and all the variables that are supposed to be based on exec_prefix\n# by default will actually change.\n# Use braces instead of parens because sh, perl, etc. also accept them.\n# (The list follows the same order as the GNU Coding Standards.)\nbindir='${exec_prefix}/bin'\nsbindir='${exec_prefix}/sbin'\nlibexecdir='${exec_prefix}/libexec'\ndatarootdir='${prefix}/share'\ndatadir='${datarootdir}'\nsysconfdir='${prefix}/etc'\nsharedstatedir='${prefix}/com'\nlocalstatedir='${prefix}/var'\nincludedir='${prefix}/include'\noldincludedir='/usr/include'\ndocdir='${datarootdir}/doc/${PACKAGE_TARNAME}'\ninfodir='${datarootdir}/info'\nhtmldir='${docdir}'\ndvidir='${docdir}'\npdfdir='${docdir}'\npsdir='${docdir}'\nlibdir='${exec_prefix}/lib'\nlocaledir='${datarootdir}/locale'\nmandir='${datarootdir}/man'\n\nac_prev=\nac_dashdash=\nfor ac_option\ndo\n  # If the previous option needs an argument, assign it.\n  if test -n \"$ac_prev\"; then\n    eval $ac_prev=\\$ac_option\n    ac_prev=\n    continue\n  fi\n\n  case $ac_option in\n  *=?*) ac_optarg=`expr \"X$ac_option\" : '[^=]*=\\(.*\\)'` ;;\n  *=)   ac_optarg= ;;\n  *)    ac_optarg=yes ;;\n  esac\n\n  # Accept the important Cygnus configure options, so we can diagnose typos.\n\n  case $ac_dashdash$ac_option in\n  --)\n    ac_dashdash=yes ;;\n\n  -bindir | --bindir | --bindi | --bind | --bin | --bi)\n    ac_prev=bindir ;;\n  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)\n    bindir=$ac_optarg ;;\n\n  -build | --build | --buil | --bui | --bu)\n    ac_prev=build_alias ;;\n  -build=* | --build=* | --buil=* | --bui=* | --bu=*)\n    build_alias=$ac_optarg ;;\n\n  -cache-file | --cache-file | --cache-fil | --cache-fi \\\n  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)\n    ac_prev=cache_file ;;\n  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \\\n  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)\n    cache_file=$ac_optarg ;;\n\n  --config-cache | -C)\n    cache_file=config.cache ;;\n\n  -datadir | --datadir | --datadi | --datad)\n    ac_prev=datadir ;;\n  -datadir=* | --datadir=* | --datadi=* | --datad=*)\n    datadir=$ac_optarg ;;\n\n  -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \\\n  | --dataroo | --dataro | --datar)\n    ac_prev=datarootdir ;;\n  -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \\\n  | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)\n    datarootdir=$ac_optarg ;;\n\n  -disable-* | --disable-*)\n    ac_useropt=`expr \"x$ac_option\" : 'x-*disable-\\(.*\\)'`\n    # Reject names that are not valid shell variable names.\n    expr \"x$ac_useropt\" : \".*[^-+._$as_cr_alnum]\" >/dev/null &&\n      as_fn_error $? \"invalid feature name: $ac_useropt\"\n    ac_useropt_orig=$ac_useropt\n    ac_useropt=`$as_echo \"$ac_useropt\" | sed 's/[-+.]/_/g'`\n    case $ac_user_opts in\n      *\"\n\"enable_$ac_useropt\"\n\"*) ;;\n      *) ac_unrecognized_opts=\"$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig\"\n\t ac_unrecognized_sep=', ';;\n    esac\n    eval enable_$ac_useropt=no ;;\n\n  -docdir | --docdir | --docdi | --doc | --do)\n    ac_prev=docdir ;;\n  -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)\n    docdir=$ac_optarg ;;\n\n  -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)\n    ac_prev=dvidir ;;\n  -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)\n    dvidir=$ac_optarg ;;\n\n  -enable-* | --enable-*)\n    ac_useropt=`expr \"x$ac_option\" : 'x-*enable-\\([^=]*\\)'`\n    # Reject names that are not valid shell variable names.\n    expr \"x$ac_useropt\" : \".*[^-+._$as_cr_alnum]\" >/dev/null &&\n      as_fn_error $? \"invalid feature name: $ac_useropt\"\n    ac_useropt_orig=$ac_useropt\n    ac_useropt=`$as_echo \"$ac_useropt\" | sed 's/[-+.]/_/g'`\n    case $ac_user_opts in\n      *\"\n\"enable_$ac_useropt\"\n\"*) ;;\n      *) ac_unrecognized_opts=\"$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig\"\n\t ac_unrecognized_sep=', ';;\n    esac\n    eval enable_$ac_useropt=\\$ac_optarg ;;\n\n  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \\\n  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \\\n  | --exec | --exe | --ex)\n    ac_prev=exec_prefix ;;\n  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \\\n  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \\\n  | --exec=* | --exe=* | --ex=*)\n    exec_prefix=$ac_optarg ;;\n\n  -gas | --gas | --ga | --g)\n    # Obsolete; use --with-gas.\n    with_gas=yes ;;\n\n  -help | --help | --hel | --he | -h)\n    ac_init_help=long ;;\n  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)\n    ac_init_help=recursive ;;\n  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)\n    ac_init_help=short ;;\n\n  -host | --host | --hos | --ho)\n    ac_prev=host_alias ;;\n  -host=* | --host=* | --hos=* | --ho=*)\n    host_alias=$ac_optarg ;;\n\n  -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)\n    ac_prev=htmldir ;;\n  -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \\\n  | --ht=*)\n    htmldir=$ac_optarg ;;\n\n  -includedir | --includedir | --includedi | --included | --include \\\n  | --includ | --inclu | --incl | --inc)\n    ac_prev=includedir ;;\n  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \\\n  | --includ=* | --inclu=* | --incl=* | --inc=*)\n    includedir=$ac_optarg ;;\n\n  -infodir | --infodir | --infodi | --infod | --info | --inf)\n    ac_prev=infodir ;;\n  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)\n    infodir=$ac_optarg ;;\n\n  -libdir | --libdir | --libdi | --libd)\n    ac_prev=libdir ;;\n  -libdir=* | --libdir=* | --libdi=* | --libd=*)\n    libdir=$ac_optarg ;;\n\n  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \\\n  | --libexe | --libex | --libe)\n    ac_prev=libexecdir ;;\n  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \\\n  | --libexe=* | --libex=* | --libe=*)\n    libexecdir=$ac_optarg ;;\n\n  -localedir | --localedir | --localedi | --localed | --locale)\n    ac_prev=localedir ;;\n  -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)\n    localedir=$ac_optarg ;;\n\n  -localstatedir | --localstatedir | --localstatedi | --localstated \\\n  | --localstate | --localstat | --localsta | --localst | --locals)\n    ac_prev=localstatedir ;;\n  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \\\n  | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)\n    localstatedir=$ac_optarg ;;\n\n  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)\n    ac_prev=mandir ;;\n  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)\n    mandir=$ac_optarg ;;\n\n  -nfp | --nfp | --nf)\n    # Obsolete; use --without-fp.\n    with_fp=no ;;\n\n  -no-create | --no-create | --no-creat | --no-crea | --no-cre \\\n  | --no-cr | --no-c | -n)\n    no_create=yes ;;\n\n  -no-recursion | --no-recursion | --no-recursio | --no-recursi \\\n  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)\n    no_recursion=yes ;;\n\n  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \\\n  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \\\n  | --oldin | --oldi | --old | --ol | --o)\n    ac_prev=oldincludedir ;;\n  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \\\n  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \\\n  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)\n    oldincludedir=$ac_optarg ;;\n\n  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)\n    ac_prev=prefix ;;\n  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)\n    prefix=$ac_optarg ;;\n\n  -program-prefix | --program-prefix | --program-prefi | --program-pref \\\n  | --program-pre | --program-pr | --program-p)\n    ac_prev=program_prefix ;;\n  -program-prefix=* | --program-prefix=* | --program-prefi=* \\\n  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)\n    program_prefix=$ac_optarg ;;\n\n  -program-suffix | --program-suffix | --program-suffi | --program-suff \\\n  | --program-suf | --program-su | --program-s)\n    ac_prev=program_suffix ;;\n  -program-suffix=* | --program-suffix=* | --program-suffi=* \\\n  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)\n    program_suffix=$ac_optarg ;;\n\n  -program-transform-name | --program-transform-name \\\n  | --program-transform-nam | --program-transform-na \\\n  | --program-transform-n | --program-transform- \\\n  | --program-transform | --program-transfor \\\n  | --program-transfo | --program-transf \\\n  | --program-trans | --program-tran \\\n  | --progr-tra | --program-tr | --program-t)\n    ac_prev=program_transform_name ;;\n  -program-transform-name=* | --program-transform-name=* \\\n  | --program-transform-nam=* | --program-transform-na=* \\\n  | --program-transform-n=* | --program-transform-=* \\\n  | --program-transform=* | --program-transfor=* \\\n  | --program-transfo=* | --program-transf=* \\\n  | --program-trans=* | --program-tran=* \\\n  | --progr-tra=* | --program-tr=* | --program-t=*)\n    program_transform_name=$ac_optarg ;;\n\n  -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)\n    ac_prev=pdfdir ;;\n  -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)\n    pdfdir=$ac_optarg ;;\n\n  -psdir | --psdir | --psdi | --psd | --ps)\n    ac_prev=psdir ;;\n  -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)\n    psdir=$ac_optarg ;;\n\n  -q | -quiet | --quiet | --quie | --qui | --qu | --q \\\n  | -silent | --silent | --silen | --sile | --sil)\n    silent=yes ;;\n\n  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)\n    ac_prev=sbindir ;;\n  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \\\n  | --sbi=* | --sb=*)\n    sbindir=$ac_optarg ;;\n\n  -sharedstatedir | --sharedstatedir | --sharedstatedi \\\n  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \\\n  | --sharedst | --shareds | --shared | --share | --shar \\\n  | --sha | --sh)\n    ac_prev=sharedstatedir ;;\n  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \\\n  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \\\n  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \\\n  | --sha=* | --sh=*)\n    sharedstatedir=$ac_optarg ;;\n\n  -site | --site | --sit)\n    ac_prev=site ;;\n  -site=* | --site=* | --sit=*)\n    site=$ac_optarg ;;\n\n  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)\n    ac_prev=srcdir ;;\n  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)\n    srcdir=$ac_optarg ;;\n\n  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \\\n  | --syscon | --sysco | --sysc | --sys | --sy)\n    ac_prev=sysconfdir ;;\n  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \\\n  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)\n    sysconfdir=$ac_optarg ;;\n\n  -target | --target | --targe | --targ | --tar | --ta | --t)\n    ac_prev=target_alias ;;\n  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)\n    target_alias=$ac_optarg ;;\n\n  -v | -verbose | --verbose | --verbos | --verbo | --verb)\n    verbose=yes ;;\n\n  -version | --version | --versio | --versi | --vers | -V)\n    ac_init_version=: ;;\n\n  -with-* | --with-*)\n    ac_useropt=`expr \"x$ac_option\" : 'x-*with-\\([^=]*\\)'`\n    # Reject names that are not valid shell variable names.\n    expr \"x$ac_useropt\" : \".*[^-+._$as_cr_alnum]\" >/dev/null &&\n      as_fn_error $? \"invalid package name: $ac_useropt\"\n    ac_useropt_orig=$ac_useropt\n    ac_useropt=`$as_echo \"$ac_useropt\" | sed 's/[-+.]/_/g'`\n    case $ac_user_opts in\n      *\"\n\"with_$ac_useropt\"\n\"*) ;;\n      *) ac_unrecognized_opts=\"$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig\"\n\t ac_unrecognized_sep=', ';;\n    esac\n    eval with_$ac_useropt=\\$ac_optarg ;;\n\n  -without-* | --without-*)\n    ac_useropt=`expr \"x$ac_option\" : 'x-*without-\\(.*\\)'`\n    # Reject names that are not valid shell variable names.\n    expr \"x$ac_useropt\" : \".*[^-+._$as_cr_alnum]\" >/dev/null &&\n      as_fn_error $? \"invalid package name: $ac_useropt\"\n    ac_useropt_orig=$ac_useropt\n    ac_useropt=`$as_echo \"$ac_useropt\" | sed 's/[-+.]/_/g'`\n    case $ac_user_opts in\n      *\"\n\"with_$ac_useropt\"\n\"*) ;;\n      *) ac_unrecognized_opts=\"$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig\"\n\t ac_unrecognized_sep=', ';;\n    esac\n    eval with_$ac_useropt=no ;;\n\n  --x)\n    # Obsolete; use --with-x.\n    with_x=yes ;;\n\n  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \\\n  | --x-incl | --x-inc | --x-in | --x-i)\n    ac_prev=x_includes ;;\n  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \\\n  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)\n    x_includes=$ac_optarg ;;\n\n  -x-libraries | --x-libraries | --x-librarie | --x-librari \\\n  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)\n    ac_prev=x_libraries ;;\n  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \\\n  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)\n    x_libraries=$ac_optarg ;;\n\n  -*) as_fn_error $? \"unrecognized option: \\`$ac_option'\nTry \\`$0 --help' for more information\"\n    ;;\n\n  *=*)\n    ac_envvar=`expr \"x$ac_option\" : 'x\\([^=]*\\)='`\n    # Reject names that are not valid shell variable names.\n    case $ac_envvar in #(\n      '' | [0-9]* | *[!_$as_cr_alnum]* )\n      as_fn_error $? \"invalid variable name: \\`$ac_envvar'\" ;;\n    esac\n    eval $ac_envvar=\\$ac_optarg\n    export $ac_envvar ;;\n\n  *)\n    # FIXME: should be removed in autoconf 3.0.\n    $as_echo \"$as_me: WARNING: you should use --build, --host, --target\" >&2\n    expr \"x$ac_option\" : \".*[^-._$as_cr_alnum]\" >/dev/null &&\n      $as_echo \"$as_me: WARNING: invalid host type: $ac_option\" >&2\n    : \"${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}\"\n    ;;\n\n  esac\ndone\n\nif test -n \"$ac_prev\"; then\n  ac_option=--`echo $ac_prev | sed 's/_/-/g'`\n  as_fn_error $? \"missing argument to $ac_option\"\nfi\n\nif test -n \"$ac_unrecognized_opts\"; then\n  case $enable_option_checking in\n    no) ;;\n    fatal) as_fn_error $? \"unrecognized options: $ac_unrecognized_opts\" ;;\n    *)     $as_echo \"$as_me: WARNING: unrecognized options: $ac_unrecognized_opts\" >&2 ;;\n  esac\nfi\n\n# Check all directory arguments for consistency.\nfor ac_var in\texec_prefix prefix bindir sbindir libexecdir datarootdir \\\n\t\tdatadir sysconfdir sharedstatedir localstatedir includedir \\\n\t\toldincludedir docdir infodir htmldir dvidir pdfdir psdir \\\n\t\tlibdir localedir mandir\ndo\n  eval ac_val=\\$$ac_var\n  # Remove trailing slashes.\n  case $ac_val in\n    */ )\n      ac_val=`expr \"X$ac_val\" : 'X\\(.*[^/]\\)' \\| \"X$ac_val\" : 'X\\(.*\\)'`\n      eval $ac_var=\\$ac_val;;\n  esac\n  # Be sure to have absolute directory names.\n  case $ac_val in\n    [\\\\/$]* | ?:[\\\\/]* )  continue;;\n    NONE | '' ) case $ac_var in *prefix ) continue;; esac;;\n  esac\n  as_fn_error $? \"expected an absolute directory name for --$ac_var: $ac_val\"\ndone\n\n# There might be people who depend on the old broken behavior: `$host'\n# used to hold the argument of --host etc.\n# FIXME: To remove some day.\nbuild=$build_alias\nhost=$host_alias\ntarget=$target_alias\n\n# FIXME: To remove some day.\nif test \"x$host_alias\" != x; then\n  if test \"x$build_alias\" = x; then\n    cross_compiling=maybe\n  elif test \"x$build_alias\" != \"x$host_alias\"; then\n    cross_compiling=yes\n  fi\nfi\n\nac_tool_prefix=\ntest -n \"$host_alias\" && ac_tool_prefix=$host_alias-\n\ntest \"$silent\" = yes && exec 6>/dev/null\n\n\nac_pwd=`pwd` && test -n \"$ac_pwd\" &&\nac_ls_di=`ls -di .` &&\nac_pwd_ls_di=`cd \"$ac_pwd\" && ls -di .` ||\n  as_fn_error $? \"working directory cannot be determined\"\ntest \"X$ac_ls_di\" = \"X$ac_pwd_ls_di\" ||\n  as_fn_error $? \"pwd does not report name of working directory\"\n\n\n# Find the source files, if location was not specified.\nif test -z \"$srcdir\"; then\n  ac_srcdir_defaulted=yes\n  # Try the directory containing this script, then the parent directory.\n  ac_confdir=`$as_dirname -- \"$as_myself\" ||\n$as_expr X\"$as_myself\" : 'X\\(.*[^/]\\)//*[^/][^/]*/*$' \\| \\\n\t X\"$as_myself\" : 'X\\(//\\)[^/]' \\| \\\n\t X\"$as_myself\" : 'X\\(//\\)$' \\| \\\n\t X\"$as_myself\" : 'X\\(/\\)' \\| . 2>/dev/null ||\n$as_echo X\"$as_myself\" |\n    sed '/^X\\(.*[^/]\\)\\/\\/*[^/][^/]*\\/*$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\/\\)[^/].*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\/\\)$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\).*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  s/.*/./; q'`\n  srcdir=$ac_confdir\n  if test ! -r \"$srcdir/$ac_unique_file\"; then\n    srcdir=..\n  fi\nelse\n  ac_srcdir_defaulted=no\nfi\nif test ! -r \"$srcdir/$ac_unique_file\"; then\n  test \"$ac_srcdir_defaulted\" = yes && srcdir=\"$ac_confdir or ..\"\n  as_fn_error $? \"cannot find sources ($ac_unique_file) in $srcdir\"\nfi\nac_msg=\"sources are in $srcdir, but \\`cd $srcdir' does not work\"\nac_abs_confdir=`(\n\tcd \"$srcdir\" && test -r \"./$ac_unique_file\" || as_fn_error $? \"$ac_msg\"\n\tpwd)`\n# When building in place, set srcdir=.\nif test \"$ac_abs_confdir\" = \"$ac_pwd\"; then\n  srcdir=.\nfi\n# Remove unnecessary trailing slashes from srcdir.\n# Double slashes in file names in object file debugging info\n# mess up M-x gdb in Emacs.\ncase $srcdir in\n*/) srcdir=`expr \"X$srcdir\" : 'X\\(.*[^/]\\)' \\| \"X$srcdir\" : 'X\\(.*\\)'`;;\nesac\nfor ac_var in $ac_precious_vars; do\n  eval ac_env_${ac_var}_set=\\${${ac_var}+set}\n  eval ac_env_${ac_var}_value=\\$${ac_var}\n  eval ac_cv_env_${ac_var}_set=\\${${ac_var}+set}\n  eval ac_cv_env_${ac_var}_value=\\$${ac_var}\ndone\n\n#\n# Report the --help message.\n#\nif test \"$ac_init_help\" = \"long\"; then\n  # Omit some internal or obsolete options to make the list less imposing.\n  # This message is too long to be a string in the A/UX 3.1 sh.\n  cat <<_ACEOF\n\\`configure' configures package-unused version-unused to adapt to many kinds of systems.\n\nUsage: $0 [OPTION]... [VAR=VALUE]...\n\nTo assign environment variables (e.g., CC, CFLAGS...), specify them as\nVAR=VALUE.  See below for descriptions of some of the useful variables.\n\nDefaults for the options are specified in brackets.\n\nConfiguration:\n  -h, --help              display this help and exit\n      --help=short        display options specific to this package\n      --help=recursive    display the short help of all the included packages\n  -V, --version           display version information and exit\n  -q, --quiet, --silent   do not print \\`checking ...' messages\n      --cache-file=FILE   cache test results in FILE [disabled]\n  -C, --config-cache      alias for \\`--cache-file=config.cache'\n  -n, --no-create         do not create output files\n      --srcdir=DIR        find the sources in DIR [configure dir or \\`..']\n\nInstallation directories:\n  --prefix=PREFIX         install architecture-independent files in PREFIX\n                          [$ac_default_prefix]\n  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX\n                          [PREFIX]\n\nBy default, \\`make install' will install all the files in\n\\`$ac_default_prefix/bin', \\`$ac_default_prefix/lib' etc.  You can specify\nan installation prefix other than \\`$ac_default_prefix' using \\`--prefix',\nfor instance \\`--prefix=\\$HOME'.\n\nFor better control, use the options below.\n\nFine tuning of the installation directories:\n  --bindir=DIR            user executables [EPREFIX/bin]\n  --sbindir=DIR           system admin executables [EPREFIX/sbin]\n  --libexecdir=DIR        program executables [EPREFIX/libexec]\n  --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]\n  --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]\n  --localstatedir=DIR     modifiable single-machine data [PREFIX/var]\n  --libdir=DIR            object code libraries [EPREFIX/lib]\n  --includedir=DIR        C header files [PREFIX/include]\n  --oldincludedir=DIR     C header files for non-gcc [/usr/include]\n  --datarootdir=DIR       read-only arch.-independent data root [PREFIX/share]\n  --datadir=DIR           read-only architecture-independent data [DATAROOTDIR]\n  --infodir=DIR           info documentation [DATAROOTDIR/info]\n  --localedir=DIR         locale-dependent data [DATAROOTDIR/locale]\n  --mandir=DIR            man documentation [DATAROOTDIR/man]\n  --docdir=DIR            documentation root [DATAROOTDIR/doc/libbacktrace]\n  --htmldir=DIR           html documentation [DOCDIR]\n  --dvidir=DIR            dvi documentation [DOCDIR]\n  --pdfdir=DIR            pdf documentation [DOCDIR]\n  --psdir=DIR             ps documentation [DOCDIR]\n_ACEOF\n\n  cat <<\\_ACEOF\n\nProgram names:\n  --program-prefix=PREFIX            prepend PREFIX to installed program names\n  --program-suffix=SUFFIX            append SUFFIX to installed program names\n  --program-transform-name=PROGRAM   run sed PROGRAM on installed program names\n\nSystem types:\n  --build=BUILD     configure for building on BUILD [guessed]\n  --host=HOST       cross-compile to build programs to run on HOST [BUILD]\n  --target=TARGET   configure for building compilers for TARGET [HOST]\n_ACEOF\nfi\n\nif test -n \"$ac_init_help\"; then\n  case $ac_init_help in\n     short | recursive ) echo \"Configuration of package-unused version-unused:\";;\n   esac\n  cat <<\\_ACEOF\n\nOptional Features:\n  --disable-option-checking  ignore unrecognized --enable/--with options\n  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)\n  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]\n  --enable-multilib       build many library versions (default)\n  --enable-shared[=PKGS]  build shared libraries [default=no]\n  --enable-silent-rules   less verbose build output (undo: \"make V=1\")\n  --disable-silent-rules  verbose build output (undo: \"make V=0\")\n  --enable-maintainer-mode\n                          enable make rules and dependencies not useful (and\n                          sometimes confusing) to the casual installer\n  --enable-static[=PKGS]  build static libraries [default=yes]\n  --enable-fast-install[=PKGS]\n                          optimize for fast installation [default=yes]\n  --disable-libtool-lock  avoid locking (might break parallel builds)\n  --enable-darwin-at-rpath\n                          install libraries with @rpath/library-name, requires\n                          rpaths to be added to executables\n  --disable-largefile     omit support for large files\n  --disable-werror        disable building with -Werror\n  --enable-host-shared    build host code as shared libraries\n\nOptional Packages:\n  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]\n  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)\n  --with-target-subdir=SUBDIR      Configuring in a subdirectory for target\n  --with-pic              try to use only PIC/non-PIC objects [default=use\n                          both]\n  --with-gnu-ld           assume the C compiler uses GNU ld [default=no]\n  --with-system-libunwind use installed libunwind\n\nSome influential environment variables:\n  CC          C compiler command\n  CFLAGS      C compiler flags\n  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a\n              nonstandard directory <lib dir>\n  LIBS        libraries to pass to the linker, e.g. -l<library>\n  CPPFLAGS    (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if\n              you have headers in a nonstandard directory <include dir>\n  CPP         C preprocessor\n  OBJCOPY     location of objcopy\n  DSYMUTIL    location of dsymutil\n  NM          location of nm\n\nUse these variables to override the choices made by `configure' or to help\nit to find libraries and programs with nonstandard names/locations.\n\nReport bugs to the package provider.\n_ACEOF\nac_status=$?\nfi\n\nif test \"$ac_init_help\" = \"recursive\"; then\n  # If there are subdirs, report their specific --help.\n  for ac_dir in : $ac_subdirs_all; do test \"x$ac_dir\" = x: && continue\n    test -d \"$ac_dir\" ||\n      { cd \"$srcdir\" && ac_pwd=`pwd` && srcdir=. && test -d \"$ac_dir\"; } ||\n      continue\n    ac_builddir=.\n\ncase \"$ac_dir\" in\n.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;\n*)\n  ac_dir_suffix=/`$as_echo \"$ac_dir\" | sed 's|^\\.[\\\\/]||'`\n  # A \"..\" for each directory in $ac_dir_suffix.\n  ac_top_builddir_sub=`$as_echo \"$ac_dir_suffix\" | sed 's|/[^\\\\/]*|/..|g;s|/||'`\n  case $ac_top_builddir_sub in\n  \"\") ac_top_builddir_sub=. ac_top_build_prefix= ;;\n  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;\n  esac ;;\nesac\nac_abs_top_builddir=$ac_pwd\nac_abs_builddir=$ac_pwd$ac_dir_suffix\n# for backward compatibility:\nac_top_builddir=$ac_top_build_prefix\n\ncase $srcdir in\n  .)  # We are building in place.\n    ac_srcdir=.\n    ac_top_srcdir=$ac_top_builddir_sub\n    ac_abs_top_srcdir=$ac_pwd ;;\n  [\\\\/]* | ?:[\\\\/]* )  # Absolute name.\n    ac_srcdir=$srcdir$ac_dir_suffix;\n    ac_top_srcdir=$srcdir\n    ac_abs_top_srcdir=$srcdir ;;\n  *) # Relative name.\n    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix\n    ac_top_srcdir=$ac_top_build_prefix$srcdir\n    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;\nesac\nac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix\n\n    cd \"$ac_dir\" || { ac_status=$?; continue; }\n    # Check for guested configure.\n    if test -f \"$ac_srcdir/configure.gnu\"; then\n      echo &&\n      $SHELL \"$ac_srcdir/configure.gnu\" --help=recursive\n    elif test -f \"$ac_srcdir/configure\"; then\n      echo &&\n      $SHELL \"$ac_srcdir/configure\" --help=recursive\n    else\n      $as_echo \"$as_me: WARNING: no configuration information is in $ac_dir\" >&2\n    fi || ac_status=$?\n    cd \"$ac_pwd\" || { ac_status=$?; break; }\n  done\nfi\n\ntest -n \"$ac_init_help\" && exit $ac_status\nif $ac_init_version; then\n  cat <<\\_ACEOF\npackage-unused configure version-unused\ngenerated by GNU Autoconf 2.69\n\nCopyright (C) 2012 Free Software Foundation, Inc.\nThis configure script is free software; the Free Software Foundation\ngives unlimited permission to copy, distribute and modify it.\n_ACEOF\n  exit\nfi\n\n## ------------------------ ##\n## Autoconf initialization. ##\n## ------------------------ ##\n\n# ac_fn_c_try_compile LINENO\n# --------------------------\n# Try to compile conftest.$ac_ext, and return whether this succeeded.\nac_fn_c_try_compile ()\n{\n  as_lineno=${as_lineno-\"$1\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n  rm -f conftest.$ac_objext\n  if { { ac_try=\"$ac_compile\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\n$as_echo \"$ac_try_echo\"; } >&5\n  (eval \"$ac_compile\") 2>conftest.err\n  ac_status=$?\n  if test -s conftest.err; then\n    grep -v '^ *+' conftest.err >conftest.er1\n    cat conftest.er1 >&5\n    mv -f conftest.er1 conftest.err\n  fi\n  $as_echo \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; } && {\n\t test -z \"$ac_c_werror_flag\" ||\n\t test ! -s conftest.err\n       } && test -s conftest.$ac_objext; then :\n  ac_retval=0\nelse\n  $as_echo \"$as_me: failed program was:\" >&5\nsed 's/^/| /' conftest.$ac_ext >&5\n\n\tac_retval=1\nfi\n  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno\n  as_fn_set_status $ac_retval\n\n} # ac_fn_c_try_compile\n\n# ac_fn_c_try_cpp LINENO\n# ----------------------\n# Try to preprocess conftest.$ac_ext, and return whether this succeeded.\nac_fn_c_try_cpp ()\n{\n  as_lineno=${as_lineno-\"$1\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n  if { { ac_try=\"$ac_cpp conftest.$ac_ext\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\n$as_echo \"$ac_try_echo\"; } >&5\n  (eval \"$ac_cpp conftest.$ac_ext\") 2>conftest.err\n  ac_status=$?\n  if test -s conftest.err; then\n    grep -v '^ *+' conftest.err >conftest.er1\n    cat conftest.er1 >&5\n    mv -f conftest.er1 conftest.err\n  fi\n  $as_echo \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; } > conftest.i && {\n\t test -z \"$ac_c_preproc_warn_flag$ac_c_werror_flag\" ||\n\t test ! -s conftest.err\n       }; then :\n  ac_retval=0\nelse\n  $as_echo \"$as_me: failed program was:\" >&5\nsed 's/^/| /' conftest.$ac_ext >&5\n\n    ac_retval=1\nfi\n  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno\n  as_fn_set_status $ac_retval\n\n} # ac_fn_c_try_cpp\n\n# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES\n# -------------------------------------------------------\n# Tests whether HEADER exists, giving a warning if it cannot be compiled using\n# the include files in INCLUDES and setting the cache variable VAR\n# accordingly.\nac_fn_c_check_header_mongrel ()\n{\n  as_lineno=${as_lineno-\"$1\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n  if eval \\${$3+:} false; then :\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $2\" >&5\n$as_echo_n \"checking for $2... \" >&6; }\nif eval \\${$3+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nfi\neval ac_res=\\$$3\n\t       { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_res\" >&5\n$as_echo \"$ac_res\" >&6; }\nelse\n  # Is the header compilable?\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking $2 usability\" >&5\n$as_echo_n \"checking $2 usability... \" >&6; }\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n$4\n#include <$2>\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  ac_header_compiler=yes\nelse\n  ac_header_compiler=no\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler\" >&5\n$as_echo \"$ac_header_compiler\" >&6; }\n\n# Is the header present?\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking $2 presence\" >&5\n$as_echo_n \"checking $2 presence... \" >&6; }\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <$2>\n_ACEOF\nif ac_fn_c_try_cpp \"$LINENO\"; then :\n  ac_header_preproc=yes\nelse\n  ac_header_preproc=no\nfi\nrm -f conftest.err conftest.i conftest.$ac_ext\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc\" >&5\n$as_echo \"$ac_header_preproc\" >&6; }\n\n# So?  What about this header?\ncase $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((\n  yes:no: )\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!\" >&5\n$as_echo \"$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!\" >&2;}\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result\" >&5\n$as_echo \"$as_me: WARNING: $2: proceeding with the compiler's result\" >&2;}\n    ;;\n  no:yes:* )\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled\" >&5\n$as_echo \"$as_me: WARNING: $2: present but cannot be compiled\" >&2;}\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: $2:     check for missing prerequisite headers?\" >&5\n$as_echo \"$as_me: WARNING: $2:     check for missing prerequisite headers?\" >&2;}\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation\" >&5\n$as_echo \"$as_me: WARNING: $2: see the Autoconf documentation\" >&2;}\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: $2:     section \\\"Present But Cannot Be Compiled\\\"\" >&5\n$as_echo \"$as_me: WARNING: $2:     section \\\"Present But Cannot Be Compiled\\\"\" >&2;}\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result\" >&5\n$as_echo \"$as_me: WARNING: $2: proceeding with the compiler's result\" >&2;}\n    ;;\nesac\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $2\" >&5\n$as_echo_n \"checking for $2... \" >&6; }\nif eval \\${$3+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  eval \"$3=\\$ac_header_compiler\"\nfi\neval ac_res=\\$$3\n\t       { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_res\" >&5\n$as_echo \"$ac_res\" >&6; }\nfi\n  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno\n\n} # ac_fn_c_check_header_mongrel\n\n# ac_fn_c_try_run LINENO\n# ----------------------\n# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes\n# that executables *can* be run.\nac_fn_c_try_run ()\n{\n  as_lineno=${as_lineno-\"$1\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n  if { { ac_try=\"$ac_link\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\n$as_echo \"$ac_try_echo\"; } >&5\n  (eval \"$ac_link\") 2>&5\n  ac_status=$?\n  $as_echo \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'\n  { { case \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\n$as_echo \"$ac_try_echo\"; } >&5\n  (eval \"$ac_try\") 2>&5\n  ac_status=$?\n  $as_echo \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; }; }; then :\n  ac_retval=0\nelse\n  $as_echo \"$as_me: program exited with status $ac_status\" >&5\n       $as_echo \"$as_me: failed program was:\" >&5\nsed 's/^/| /' conftest.$ac_ext >&5\n\n       ac_retval=$ac_status\nfi\n  rm -rf conftest.dSYM conftest_ipa8_conftest.oo\n  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno\n  as_fn_set_status $ac_retval\n\n} # ac_fn_c_try_run\n\n# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES\n# -------------------------------------------------------\n# Tests whether HEADER exists and can be compiled using the include files in\n# INCLUDES, setting the cache variable VAR accordingly.\nac_fn_c_check_header_compile ()\n{\n  as_lineno=${as_lineno-\"$1\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $2\" >&5\n$as_echo_n \"checking for $2... \" >&6; }\nif eval \\${$3+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n$4\n#include <$2>\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  eval \"$3=yes\"\nelse\n  eval \"$3=no\"\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\nfi\neval ac_res=\\$$3\n\t       { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_res\" >&5\n$as_echo \"$ac_res\" >&6; }\n  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno\n\n} # ac_fn_c_check_header_compile\n\n# ac_fn_c_try_link LINENO\n# -----------------------\n# Try to link conftest.$ac_ext, and return whether this succeeded.\nac_fn_c_try_link ()\n{\n  as_lineno=${as_lineno-\"$1\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n  rm -f conftest.$ac_objext conftest$ac_exeext\n  if { { ac_try=\"$ac_link\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\n$as_echo \"$ac_try_echo\"; } >&5\n  (eval \"$ac_link\") 2>conftest.err\n  ac_status=$?\n  if test -s conftest.err; then\n    grep -v '^ *+' conftest.err >conftest.er1\n    cat conftest.er1 >&5\n    mv -f conftest.er1 conftest.err\n  fi\n  $as_echo \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; } && {\n\t test -z \"$ac_c_werror_flag\" ||\n\t test ! -s conftest.err\n       } && test -s conftest$ac_exeext && {\n\t test \"$cross_compiling\" = yes ||\n\t test -x conftest$ac_exeext\n       }; then :\n  ac_retval=0\nelse\n  $as_echo \"$as_me: failed program was:\" >&5\nsed 's/^/| /' conftest.$ac_ext >&5\n\n\tac_retval=1\nfi\n  # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information\n  # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would\n  # interfere with the next link command; also delete a directory that is\n  # left behind by Apple's compiler.  We do this before executing the actions.\n  rm -rf conftest.dSYM conftest_ipa8_conftest.oo\n  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno\n  as_fn_set_status $ac_retval\n\n} # ac_fn_c_try_link\n\n# ac_fn_c_check_func LINENO FUNC VAR\n# ----------------------------------\n# Tests whether FUNC exists, setting the cache variable VAR accordingly\nac_fn_c_check_func ()\n{\n  as_lineno=${as_lineno-\"$1\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $2\" >&5\n$as_echo_n \"checking for $2... \" >&6; }\nif eval \\${$3+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n/* Define $2 to an innocuous variant, in case <limits.h> declares $2.\n   For example, HP-UX 11i <limits.h> declares gettimeofday.  */\n#define $2 innocuous_$2\n\n/* System header to define __stub macros and hopefully few prototypes,\n    which can conflict with char $2 (); below.\n    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since\n    <limits.h> exists even on freestanding compilers.  */\n\n#ifdef __STDC__\n# include <limits.h>\n#else\n# include <assert.h>\n#endif\n\n#undef $2\n\n/* Override any GCC internal prototype to avoid an error.\n   Use char because int might match the return type of a GCC\n   builtin and then its argument prototype would still apply.  */\n#ifdef __cplusplus\nextern \"C\"\n#endif\nchar $2 ();\n/* The GNU C library defines this for functions which it implements\n    to always fail with ENOSYS.  Some functions are actually named\n    something starting with __ and the normal name is an alias.  */\n#if defined __stub_$2 || defined __stub___$2\nchoke me\n#endif\n\nint\nmain ()\n{\nreturn $2 ();\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  eval \"$3=yes\"\nelse\n  eval \"$3=no\"\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nfi\neval ac_res=\\$$3\n\t       { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_res\" >&5\n$as_echo \"$ac_res\" >&6; }\n  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno\n\n} # ac_fn_c_check_func\n\n# ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES\n# ---------------------------------------------\n# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR\n# accordingly.\nac_fn_c_check_decl ()\n{\n  as_lineno=${as_lineno-\"$1\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n  as_decl_name=`echo $2|sed 's/ *(.*//'`\n  as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'`\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared\" >&5\n$as_echo_n \"checking whether $as_decl_name is declared... \" >&6; }\nif eval \\${$3+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n$4\nint\nmain ()\n{\n#ifndef $as_decl_name\n#ifdef __cplusplus\n  (void) $as_decl_use;\n#else\n  (void) $as_decl_name;\n#endif\n#endif\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  eval \"$3=yes\"\nelse\n  eval \"$3=no\"\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\nfi\neval ac_res=\\$$3\n\t       { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_res\" >&5\n$as_echo \"$ac_res\" >&6; }\n  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno\n\n} # ac_fn_c_check_decl\ncat >config.log <<_ACEOF\nThis file contains any messages produced by compilers while\nrunning configure, to aid debugging if configure makes a mistake.\n\nIt was created by package-unused $as_me version-unused, which was\ngenerated by GNU Autoconf 2.69.  Invocation command line was\n\n  $ $0 $@\n\n_ACEOF\nexec 5>>config.log\n{\ncat <<_ASUNAME\n## --------- ##\n## Platform. ##\n## --------- ##\n\nhostname = `(hostname || uname -n) 2>/dev/null | sed 1q`\nuname -m = `(uname -m) 2>/dev/null || echo unknown`\nuname -r = `(uname -r) 2>/dev/null || echo unknown`\nuname -s = `(uname -s) 2>/dev/null || echo unknown`\nuname -v = `(uname -v) 2>/dev/null || echo unknown`\n\n/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`\n/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`\n\n/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`\n/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`\n/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`\n/usr/bin/hostinfo      = `(/usr/bin/hostinfo) 2>/dev/null      || echo unknown`\n/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`\n/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`\n/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`\n\n_ASUNAME\n\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    $as_echo \"PATH: $as_dir\"\n  done\nIFS=$as_save_IFS\n\n} >&5\n\ncat >&5 <<_ACEOF\n\n\n## ----------- ##\n## Core tests. ##\n## ----------- ##\n\n_ACEOF\n\n\n# Keep a trace of the command line.\n# Strip out --no-create and --no-recursion so they do not pile up.\n# Strip out --silent because we don't want to record it for future runs.\n# Also quote any args containing shell meta-characters.\n# Make two passes to allow for proper duplicate-argument suppression.\nac_configure_args=\nac_configure_args0=\nac_configure_args1=\nac_must_keep_next=false\nfor ac_pass in 1 2\ndo\n  for ac_arg\n  do\n    case $ac_arg in\n    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;\n    -q | -quiet | --quiet | --quie | --qui | --qu | --q \\\n    | -silent | --silent | --silen | --sile | --sil)\n      continue ;;\n    *\\'*)\n      ac_arg=`$as_echo \"$ac_arg\" | sed \"s/'/'\\\\\\\\\\\\\\\\''/g\"` ;;\n    esac\n    case $ac_pass in\n    1) as_fn_append ac_configure_args0 \" '$ac_arg'\" ;;\n    2)\n      as_fn_append ac_configure_args1 \" '$ac_arg'\"\n      if test $ac_must_keep_next = true; then\n\tac_must_keep_next=false # Got value, back to normal.\n      else\n\tcase $ac_arg in\n\t  *=* | --config-cache | -C | -disable-* | --disable-* \\\n\t  | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \\\n\t  | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \\\n\t  | -with-* | --with-* | -without-* | --without-* | --x)\n\t    case \"$ac_configure_args0 \" in\n\t      \"$ac_configure_args1\"*\" '$ac_arg' \"* ) continue ;;\n\t    esac\n\t    ;;\n\t  -* ) ac_must_keep_next=true ;;\n\tesac\n      fi\n      as_fn_append ac_configure_args \" '$ac_arg'\"\n      ;;\n    esac\n  done\ndone\n{ ac_configure_args0=; unset ac_configure_args0;}\n{ ac_configure_args1=; unset ac_configure_args1;}\n\n# When interrupted or exit'd, cleanup temporary files, and complete\n# config.log.  We remove comments because anyway the quotes in there\n# would cause problems or look ugly.\n# WARNING: Use '\\'' to represent an apostrophe within the trap.\n# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.\ntrap 'exit_status=$?\n  # Save into config.log some information that might help in debugging.\n  {\n    echo\n\n    $as_echo \"## ---------------- ##\n## Cache variables. ##\n## ---------------- ##\"\n    echo\n    # The following way of writing the cache mishandles newlines in values,\n(\n  for ac_var in `(set) 2>&1 | sed -n '\\''s/^\\([a-zA-Z_][a-zA-Z0-9_]*\\)=.*/\\1/p'\\''`; do\n    eval ac_val=\\$$ac_var\n    case $ac_val in #(\n    *${as_nl}*)\n      case $ac_var in #(\n      *_cv_*) { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline\" >&5\n$as_echo \"$as_me: WARNING: cache variable $ac_var contains a newline\" >&2;} ;;\n      esac\n      case $ac_var in #(\n      _ | IFS | as_nl) ;; #(\n      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(\n      *) { eval $ac_var=; unset $ac_var;} ;;\n      esac ;;\n    esac\n  done\n  (set) 2>&1 |\n    case $as_nl`(ac_space='\\'' '\\''; set) 2>&1` in #(\n    *${as_nl}ac_space=\\ *)\n      sed -n \\\n\t\"s/'\\''/'\\''\\\\\\\\'\\'''\\''/g;\n\t  s/^\\\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\\\)=\\\\(.*\\\\)/\\\\1='\\''\\\\2'\\''/p\"\n      ;; #(\n    *)\n      sed -n \"/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p\"\n      ;;\n    esac |\n    sort\n)\n    echo\n\n    $as_echo \"## ----------------- ##\n## Output variables. ##\n## ----------------- ##\"\n    echo\n    for ac_var in $ac_subst_vars\n    do\n      eval ac_val=\\$$ac_var\n      case $ac_val in\n      *\\'\\''*) ac_val=`$as_echo \"$ac_val\" | sed \"s/'\\''/'\\''\\\\\\\\\\\\\\\\'\\'''\\''/g\"`;;\n      esac\n      $as_echo \"$ac_var='\\''$ac_val'\\''\"\n    done | sort\n    echo\n\n    if test -n \"$ac_subst_files\"; then\n      $as_echo \"## ------------------- ##\n## File substitutions. ##\n## ------------------- ##\"\n      echo\n      for ac_var in $ac_subst_files\n      do\n\teval ac_val=\\$$ac_var\n\tcase $ac_val in\n\t*\\'\\''*) ac_val=`$as_echo \"$ac_val\" | sed \"s/'\\''/'\\''\\\\\\\\\\\\\\\\'\\'''\\''/g\"`;;\n\tesac\n\t$as_echo \"$ac_var='\\''$ac_val'\\''\"\n      done | sort\n      echo\n    fi\n\n    if test -s confdefs.h; then\n      $as_echo \"## ----------- ##\n## confdefs.h. ##\n## ----------- ##\"\n      echo\n      cat confdefs.h\n      echo\n    fi\n    test \"$ac_signal\" != 0 &&\n      $as_echo \"$as_me: caught signal $ac_signal\"\n    $as_echo \"$as_me: exit $exit_status\"\n  } >&5\n  rm -f core *.core core.conftest.* &&\n    rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&\n    exit $exit_status\n' 0\nfor ac_signal in 1 2 13 15; do\n  trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal\ndone\nac_signal=0\n\n# confdefs.h avoids OS command line length limits that DEFS can exceed.\nrm -f -r conftest* confdefs.h\n\n$as_echo \"/* confdefs.h */\" > confdefs.h\n\n# Predefined preprocessor variables.\n\ncat >>confdefs.h <<_ACEOF\n#define PACKAGE_NAME \"$PACKAGE_NAME\"\n_ACEOF\n\ncat >>confdefs.h <<_ACEOF\n#define PACKAGE_TARNAME \"$PACKAGE_TARNAME\"\n_ACEOF\n\ncat >>confdefs.h <<_ACEOF\n#define PACKAGE_VERSION \"$PACKAGE_VERSION\"\n_ACEOF\n\ncat >>confdefs.h <<_ACEOF\n#define PACKAGE_STRING \"$PACKAGE_STRING\"\n_ACEOF\n\ncat >>confdefs.h <<_ACEOF\n#define PACKAGE_BUGREPORT \"$PACKAGE_BUGREPORT\"\n_ACEOF\n\ncat >>confdefs.h <<_ACEOF\n#define PACKAGE_URL \"$PACKAGE_URL\"\n_ACEOF\n\n\n# Let the site file select an alternate cache file if it wants to.\n# Prefer an explicitly selected file to automatically selected ones.\nac_site_file1=NONE\nac_site_file2=NONE\nif test -n \"$CONFIG_SITE\"; then\n  # We do not want a PATH search for config.site.\n  case $CONFIG_SITE in #((\n    -*)  ac_site_file1=./$CONFIG_SITE;;\n    */*) ac_site_file1=$CONFIG_SITE;;\n    *)   ac_site_file1=./$CONFIG_SITE;;\n  esac\nelif test \"x$prefix\" != xNONE; then\n  ac_site_file1=$prefix/share/config.site\n  ac_site_file2=$prefix/etc/config.site\nelse\n  ac_site_file1=$ac_default_prefix/share/config.site\n  ac_site_file2=$ac_default_prefix/etc/config.site\nfi\nfor ac_site_file in \"$ac_site_file1\" \"$ac_site_file2\"\ndo\n  test \"x$ac_site_file\" = xNONE && continue\n  if test /dev/null != \"$ac_site_file\" && test -r \"$ac_site_file\"; then\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file\" >&5\n$as_echo \"$as_me: loading site script $ac_site_file\" >&6;}\n    sed 's/^/| /' \"$ac_site_file\" >&5\n    . \"$ac_site_file\" \\\n      || { { $as_echo \"$as_me:${as_lineno-$LINENO}: error: in \\`$ac_pwd':\" >&5\n$as_echo \"$as_me: error: in \\`$ac_pwd':\" >&2;}\nas_fn_error $? \"failed to load site script $ac_site_file\nSee \\`config.log' for more details\" \"$LINENO\" 5; }\n  fi\ndone\n\nif test -r \"$cache_file\"; then\n  # Some versions of bash will fail to source /dev/null (special files\n  # actually), so we avoid doing that.  DJGPP emulates it as a regular file.\n  if test /dev/null != \"$cache_file\" && test -f \"$cache_file\"; then\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: loading cache $cache_file\" >&5\n$as_echo \"$as_me: loading cache $cache_file\" >&6;}\n    case $cache_file in\n      [\\\\/]* | ?:[\\\\/]* ) . \"$cache_file\";;\n      *)                      . \"./$cache_file\";;\n    esac\n  fi\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: creating cache $cache_file\" >&5\n$as_echo \"$as_me: creating cache $cache_file\" >&6;}\n  >$cache_file\nfi\n\n# Check that the precious variables saved in the cache have kept the same\n# value.\nac_cache_corrupted=false\nfor ac_var in $ac_precious_vars; do\n  eval ac_old_set=\\$ac_cv_env_${ac_var}_set\n  eval ac_new_set=\\$ac_env_${ac_var}_set\n  eval ac_old_val=\\$ac_cv_env_${ac_var}_value\n  eval ac_new_val=\\$ac_env_${ac_var}_value\n  case $ac_old_set,$ac_new_set in\n    set,)\n      { $as_echo \"$as_me:${as_lineno-$LINENO}: error: \\`$ac_var' was set to \\`$ac_old_val' in the previous run\" >&5\n$as_echo \"$as_me: error: \\`$ac_var' was set to \\`$ac_old_val' in the previous run\" >&2;}\n      ac_cache_corrupted=: ;;\n    ,set)\n      { $as_echo \"$as_me:${as_lineno-$LINENO}: error: \\`$ac_var' was not set in the previous run\" >&5\n$as_echo \"$as_me: error: \\`$ac_var' was not set in the previous run\" >&2;}\n      ac_cache_corrupted=: ;;\n    ,);;\n    *)\n      if test \"x$ac_old_val\" != \"x$ac_new_val\"; then\n\t# differences in whitespace do not lead to failure.\n\tac_old_val_w=`echo x $ac_old_val`\n\tac_new_val_w=`echo x $ac_new_val`\n\tif test \"$ac_old_val_w\" != \"$ac_new_val_w\"; then\n\t  { $as_echo \"$as_me:${as_lineno-$LINENO}: error: \\`$ac_var' has changed since the previous run:\" >&5\n$as_echo \"$as_me: error: \\`$ac_var' has changed since the previous run:\" >&2;}\n\t  ac_cache_corrupted=:\n\telse\n\t  { $as_echo \"$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \\`$ac_var' since the previous run:\" >&5\n$as_echo \"$as_me: warning: ignoring whitespace changes in \\`$ac_var' since the previous run:\" >&2;}\n\t  eval $ac_var=\\$ac_old_val\n\tfi\n\t{ $as_echo \"$as_me:${as_lineno-$LINENO}:   former value:  \\`$ac_old_val'\" >&5\n$as_echo \"$as_me:   former value:  \\`$ac_old_val'\" >&2;}\n\t{ $as_echo \"$as_me:${as_lineno-$LINENO}:   current value: \\`$ac_new_val'\" >&5\n$as_echo \"$as_me:   current value: \\`$ac_new_val'\" >&2;}\n      fi;;\n  esac\n  # Pass precious variables to config.status.\n  if test \"$ac_new_set\" = set; then\n    case $ac_new_val in\n    *\\'*) ac_arg=$ac_var=`$as_echo \"$ac_new_val\" | sed \"s/'/'\\\\\\\\\\\\\\\\''/g\"` ;;\n    *) ac_arg=$ac_var=$ac_new_val ;;\n    esac\n    case \" $ac_configure_args \" in\n      *\" '$ac_arg' \"*) ;; # Avoid dups.  Use of quotes ensures accuracy.\n      *) as_fn_append ac_configure_args \" '$ac_arg'\" ;;\n    esac\n  fi\ndone\nif $ac_cache_corrupted; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: error: in \\`$ac_pwd':\" >&5\n$as_echo \"$as_me: error: in \\`$ac_pwd':\" >&2;}\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build\" >&5\n$as_echo \"$as_me: error: changes in the environment can compromise the build\" >&2;}\n  as_fn_error $? \"run \\`make distclean' and/or \\`rm $cache_file' and start over\" \"$LINENO\" 5\nfi\n## -------------------- ##\n## Main body of script. ##\n## -------------------- ##\n\nac_ext=c\nac_cpp='$CPP $CPPFLAGS'\nac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'\nac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'\nac_compiler_gnu=$ac_cv_c_compiler_gnu\n\n\n\nac_config_headers=\"$ac_config_headers config.h\"\n\n\n\n# with_target_subdir is used when configured as part of a GCC tree.\nif test -n \"${with_target_subdir}\"; then\n  # Default to --enable-multilib\n# Check whether --enable-multilib was given.\nif test \"${enable_multilib+set}\" = set; then :\n  enableval=$enable_multilib; case \"$enableval\" in\n  yes) multilib=yes ;;\n  no)  multilib=no ;;\n  *)   as_fn_error $? \"bad value $enableval for multilib option\" \"$LINENO\" 5 ;;\n esac\nelse\n  multilib=yes\nfi\n\n\n# We may get other options which we leave undocumented:\n# --with-target-subdir, --with-multisrctop, --with-multisubdir\n# See config-ml.in if you want the gory details.\n\nif test \"$srcdir\" = \".\"; then\n  if test \"$with_target_subdir\" != \".\"; then\n    multi_basedir=\"$srcdir/$with_multisrctop../..\"\n  else\n    multi_basedir=\"$srcdir/$with_multisrctop..\"\n  fi\nelse\n  multi_basedir=\"$srcdir/..\"\nfi\n\n\n# Even if the default multilib is not a cross compilation,\n# it may be that some of the other multilibs are.\nif test $cross_compiling = no && test $multilib = yes \\\n   && test \"x${with_multisubdir}\" != x ; then\n   cross_compiling=maybe\nfi\n\nac_config_commands=\"$ac_config_commands default-1\"\n\nfi\n\nac_aux_dir=\nfor ac_dir in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"; do\n  if test -f \"$ac_dir/install-sh\"; then\n    ac_aux_dir=$ac_dir\n    ac_install_sh=\"$ac_aux_dir/install-sh -c\"\n    break\n  elif test -f \"$ac_dir/install.sh\"; then\n    ac_aux_dir=$ac_dir\n    ac_install_sh=\"$ac_aux_dir/install.sh -c\"\n    break\n  elif test -f \"$ac_dir/shtool\"; then\n    ac_aux_dir=$ac_dir\n    ac_install_sh=\"$ac_aux_dir/shtool install -c\"\n    break\n  fi\ndone\nif test -z \"$ac_aux_dir\"; then\n  as_fn_error $? \"cannot find install-sh, install.sh, or shtool in \\\"$srcdir\\\" \\\"$srcdir/..\\\" \\\"$srcdir/../..\\\"\" \"$LINENO\" 5\nfi\n\n# These three variables are undocumented and unsupported,\n# and are intended to be withdrawn in a future Autoconf release.\n# They can cause serious problems if a builder's source tree is in a directory\n# whose full name contains unusual characters.\nac_config_guess=\"$SHELL $ac_aux_dir/config.guess\"  # Please don't use this var.\nac_config_sub=\"$SHELL $ac_aux_dir/config.sub\"  # Please don't use this var.\nac_configure=\"$SHELL $ac_aux_dir/configure\"  # Please don't use this var.\n\n\n# Make sure we can run config.sub.\n$SHELL \"$ac_aux_dir/config.sub\" sun4 >/dev/null 2>&1 ||\n  as_fn_error $? \"cannot run $SHELL $ac_aux_dir/config.sub\" \"$LINENO\" 5\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking build system type\" >&5\n$as_echo_n \"checking build system type... \" >&6; }\nif ${ac_cv_build+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  ac_build_alias=$build_alias\ntest \"x$ac_build_alias\" = x &&\n  ac_build_alias=`$SHELL \"$ac_aux_dir/config.guess\"`\ntest \"x$ac_build_alias\" = x &&\n  as_fn_error $? \"cannot guess build type; you must specify one\" \"$LINENO\" 5\nac_cv_build=`$SHELL \"$ac_aux_dir/config.sub\" $ac_build_alias` ||\n  as_fn_error $? \"$SHELL $ac_aux_dir/config.sub $ac_build_alias failed\" \"$LINENO\" 5\n\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_build\" >&5\n$as_echo \"$ac_cv_build\" >&6; }\ncase $ac_cv_build in\n*-*-*) ;;\n*) as_fn_error $? \"invalid value of canonical build\" \"$LINENO\" 5;;\nesac\nbuild=$ac_cv_build\nac_save_IFS=$IFS; IFS='-'\nset x $ac_cv_build\nshift\nbuild_cpu=$1\nbuild_vendor=$2\nshift; shift\n# Remember, the first character of IFS is used to create $*,\n# except with old shells:\nbuild_os=$*\nIFS=$ac_save_IFS\ncase $build_os in *\\ *) build_os=`echo \"$build_os\" | sed 's/ /-/g'`;; esac\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking host system type\" >&5\n$as_echo_n \"checking host system type... \" >&6; }\nif ${ac_cv_host+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test \"x$host_alias\" = x; then\n  ac_cv_host=$ac_cv_build\nelse\n  ac_cv_host=`$SHELL \"$ac_aux_dir/config.sub\" $host_alias` ||\n    as_fn_error $? \"$SHELL $ac_aux_dir/config.sub $host_alias failed\" \"$LINENO\" 5\nfi\n\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_host\" >&5\n$as_echo \"$ac_cv_host\" >&6; }\ncase $ac_cv_host in\n*-*-*) ;;\n*) as_fn_error $? \"invalid value of canonical host\" \"$LINENO\" 5;;\nesac\nhost=$ac_cv_host\nac_save_IFS=$IFS; IFS='-'\nset x $ac_cv_host\nshift\nhost_cpu=$1\nhost_vendor=$2\nshift; shift\n# Remember, the first character of IFS is used to create $*,\n# except with old shells:\nhost_os=$*\nIFS=$ac_save_IFS\ncase $host_os in *\\ *) host_os=`echo \"$host_os\" | sed 's/ /-/g'`;; esac\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking target system type\" >&5\n$as_echo_n \"checking target system type... \" >&6; }\nif ${ac_cv_target+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test \"x$target_alias\" = x; then\n  ac_cv_target=$ac_cv_host\nelse\n  ac_cv_target=`$SHELL \"$ac_aux_dir/config.sub\" $target_alias` ||\n    as_fn_error $? \"$SHELL $ac_aux_dir/config.sub $target_alias failed\" \"$LINENO\" 5\nfi\n\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_target\" >&5\n$as_echo \"$ac_cv_target\" >&6; }\ncase $ac_cv_target in\n*-*-*) ;;\n*) as_fn_error $? \"invalid value of canonical target\" \"$LINENO\" 5;;\nesac\ntarget=$ac_cv_target\nac_save_IFS=$IFS; IFS='-'\nset x $ac_cv_target\nshift\ntarget_cpu=$1\ntarget_vendor=$2\nshift; shift\n# Remember, the first character of IFS is used to create $*,\n# except with old shells:\ntarget_os=$*\nIFS=$ac_save_IFS\ncase $target_os in *\\ *) target_os=`echo \"$target_os\" | sed 's/ /-/g'`;; esac\n\n\n# The aliases save the names the user supplied, while $host etc.\n# will get canonicalized.\ntest -n \"$target_alias\" &&\n  test \"$program_prefix$program_suffix$program_transform_name\" = \\\n    NONENONEs,x,x, &&\n  program_prefix=${target_alias}-\n\ntarget_alias=${target_alias-$host_alias}\n\n# Expand $ac_aux_dir to an absolute path.\nam_aux_dir=`cd \"$ac_aux_dir\" && pwd`\n\nac_ext=c\nac_cpp='$CPP $CPPFLAGS'\nac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'\nac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'\nac_compiler_gnu=$ac_cv_c_compiler_gnu\nif test -n \"$ac_tool_prefix\"; then\n  # Extract the first word of \"${ac_tool_prefix}gcc\", so it can be a program name with args.\nset dummy ${ac_tool_prefix}gcc; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_CC+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$CC\"; then\n  ac_cv_prog_CC=\"$CC\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_CC=\"${ac_tool_prefix}gcc\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nCC=$ac_cv_prog_CC\nif test -n \"$CC\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $CC\" >&5\n$as_echo \"$CC\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\nfi\nif test -z \"$ac_cv_prog_CC\"; then\n  ac_ct_CC=$CC\n  # Extract the first word of \"gcc\", so it can be a program name with args.\nset dummy gcc; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_ac_ct_CC+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$ac_ct_CC\"; then\n  ac_cv_prog_ac_ct_CC=\"$ac_ct_CC\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_ac_ct_CC=\"gcc\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nac_ct_CC=$ac_cv_prog_ac_ct_CC\nif test -n \"$ac_ct_CC\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC\" >&5\n$as_echo \"$ac_ct_CC\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n  if test \"x$ac_ct_CC\" = x; then\n    CC=\"\"\n  else\n    case $cross_compiling:$ac_tool_warned in\nyes:)\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet\" >&5\n$as_echo \"$as_me: WARNING: using cross tools not prefixed with host triplet\" >&2;}\nac_tool_warned=yes ;;\nesac\n    CC=$ac_ct_CC\n  fi\nelse\n  CC=\"$ac_cv_prog_CC\"\nfi\n\nif test -z \"$CC\"; then\n          if test -n \"$ac_tool_prefix\"; then\n    # Extract the first word of \"${ac_tool_prefix}cc\", so it can be a program name with args.\nset dummy ${ac_tool_prefix}cc; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_CC+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$CC\"; then\n  ac_cv_prog_CC=\"$CC\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_CC=\"${ac_tool_prefix}cc\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nCC=$ac_cv_prog_CC\nif test -n \"$CC\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $CC\" >&5\n$as_echo \"$CC\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\n  fi\nfi\nif test -z \"$CC\"; then\n  # Extract the first word of \"cc\", so it can be a program name with args.\nset dummy cc; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_CC+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$CC\"; then\n  ac_cv_prog_CC=\"$CC\" # Let the user override the test.\nelse\n  ac_prog_rejected=no\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    if test \"$as_dir/$ac_word$ac_exec_ext\" = \"/usr/ucb/cc\"; then\n       ac_prog_rejected=yes\n       continue\n     fi\n    ac_cv_prog_CC=\"cc\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nif test $ac_prog_rejected = yes; then\n  # We found a bogon in the path, so make sure we never use it.\n  set dummy $ac_cv_prog_CC\n  shift\n  if test $# != 0; then\n    # We chose a different compiler from the bogus one.\n    # However, it has the same basename, so the bogon will be chosen\n    # first if we set CC to just the basename; use the full file name.\n    shift\n    ac_cv_prog_CC=\"$as_dir/$ac_word${1+' '}$@\"\n  fi\nfi\nfi\nfi\nCC=$ac_cv_prog_CC\nif test -n \"$CC\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $CC\" >&5\n$as_echo \"$CC\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\nfi\nif test -z \"$CC\"; then\n  if test -n \"$ac_tool_prefix\"; then\n  for ac_prog in cl.exe\n  do\n    # Extract the first word of \"$ac_tool_prefix$ac_prog\", so it can be a program name with args.\nset dummy $ac_tool_prefix$ac_prog; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_CC+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$CC\"; then\n  ac_cv_prog_CC=\"$CC\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_CC=\"$ac_tool_prefix$ac_prog\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nCC=$ac_cv_prog_CC\nif test -n \"$CC\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $CC\" >&5\n$as_echo \"$CC\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\n    test -n \"$CC\" && break\n  done\nfi\nif test -z \"$CC\"; then\n  ac_ct_CC=$CC\n  for ac_prog in cl.exe\ndo\n  # Extract the first word of \"$ac_prog\", so it can be a program name with args.\nset dummy $ac_prog; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_ac_ct_CC+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$ac_ct_CC\"; then\n  ac_cv_prog_ac_ct_CC=\"$ac_ct_CC\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_ac_ct_CC=\"$ac_prog\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nac_ct_CC=$ac_cv_prog_ac_ct_CC\nif test -n \"$ac_ct_CC\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC\" >&5\n$as_echo \"$ac_ct_CC\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\n  test -n \"$ac_ct_CC\" && break\ndone\n\n  if test \"x$ac_ct_CC\" = x; then\n    CC=\"\"\n  else\n    case $cross_compiling:$ac_tool_warned in\nyes:)\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet\" >&5\n$as_echo \"$as_me: WARNING: using cross tools not prefixed with host triplet\" >&2;}\nac_tool_warned=yes ;;\nesac\n    CC=$ac_ct_CC\n  fi\nfi\n\nfi\n\n\ntest -z \"$CC\" && { { $as_echo \"$as_me:${as_lineno-$LINENO}: error: in \\`$ac_pwd':\" >&5\n$as_echo \"$as_me: error: in \\`$ac_pwd':\" >&2;}\nas_fn_error $? \"no acceptable C compiler found in \\$PATH\nSee \\`config.log' for more details\" \"$LINENO\" 5; }\n\n# Provide some information about the compiler.\n$as_echo \"$as_me:${as_lineno-$LINENO}: checking for C compiler version\" >&5\nset X $ac_compile\nac_compiler=$2\nfor ac_option in --version -v -V -qversion; do\n  { { ac_try=\"$ac_compiler $ac_option >&5\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\n$as_echo \"$ac_try_echo\"; } >&5\n  (eval \"$ac_compiler $ac_option >&5\") 2>conftest.err\n  ac_status=$?\n  if test -s conftest.err; then\n    sed '10a\\\n... rest of stderr output deleted ...\n         10q' conftest.err >conftest.er1\n    cat conftest.er1 >&5\n  fi\n  rm -f conftest.er1 conftest.err\n  $as_echo \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; }\ndone\n\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain ()\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nac_clean_files_save=$ac_clean_files\nac_clean_files=\"$ac_clean_files a.out a.out.dSYM a.exe b.out\"\n# Try to create an executable without -o first, disregard a.out.\n# It will help us diagnose broken compilers, and finding out an intuition\n# of exeext.\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether the C compiler works\" >&5\n$as_echo_n \"checking whether the C compiler works... \" >&6; }\nac_link_default=`$as_echo \"$ac_link\" | sed 's/ -o *conftest[^ ]*//'`\n\n# The possible output files:\nac_files=\"a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*\"\n\nac_rmfiles=\nfor ac_file in $ac_files\ndo\n  case $ac_file in\n    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;\n    * ) ac_rmfiles=\"$ac_rmfiles $ac_file\";;\n  esac\ndone\nrm -f $ac_rmfiles\n\nif { { ac_try=\"$ac_link_default\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\n$as_echo \"$ac_try_echo\"; } >&5\n  (eval \"$ac_link_default\") 2>&5\n  ac_status=$?\n  $as_echo \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; }; then :\n  # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.\n# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'\n# in a Makefile.  We should not override ac_cv_exeext if it was cached,\n# so that the user can short-circuit this test for compilers unknown to\n# Autoconf.\nfor ac_file in $ac_files ''\ndo\n  test -f \"$ac_file\" || continue\n  case $ac_file in\n    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )\n\t;;\n    [ab].out )\n\t# We found the default executable, but exeext='' is most\n\t# certainly right.\n\tbreak;;\n    *.* )\n\tif test \"${ac_cv_exeext+set}\" = set && test \"$ac_cv_exeext\" != no;\n\tthen :; else\n\t   ac_cv_exeext=`expr \"$ac_file\" : '[^.]*\\(\\..*\\)'`\n\tfi\n\t# We set ac_cv_exeext here because the later test for it is not\n\t# safe: cross compilers may not add the suffix if given an `-o'\n\t# argument, so we may need to know it at that point already.\n\t# Even if this section looks crufty: it has the advantage of\n\t# actually working.\n\tbreak;;\n    * )\n\tbreak;;\n  esac\ndone\ntest \"$ac_cv_exeext\" = no && ac_cv_exeext=\n\nelse\n  ac_file=''\nfi\nif test -z \"$ac_file\"; then :\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\n$as_echo \"$as_me: failed program was:\" >&5\nsed 's/^/| /' conftest.$ac_ext >&5\n\n{ { $as_echo \"$as_me:${as_lineno-$LINENO}: error: in \\`$ac_pwd':\" >&5\n$as_echo \"$as_me: error: in \\`$ac_pwd':\" >&2;}\nas_fn_error 77 \"C compiler cannot create executables\nSee \\`config.log' for more details\" \"$LINENO\" 5; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\n$as_echo \"yes\" >&6; }\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name\" >&5\n$as_echo_n \"checking for C compiler default output file name... \" >&6; }\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_file\" >&5\n$as_echo \"$ac_file\" >&6; }\nac_exeext=$ac_cv_exeext\n\nrm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out\nac_clean_files=$ac_clean_files_save\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for suffix of executables\" >&5\n$as_echo_n \"checking for suffix of executables... \" >&6; }\nif { { ac_try=\"$ac_link\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\n$as_echo \"$ac_try_echo\"; } >&5\n  (eval \"$ac_link\") 2>&5\n  ac_status=$?\n  $as_echo \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; }; then :\n  # If both `conftest.exe' and `conftest' are `present' (well, observable)\n# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will\n# work properly (i.e., refer to `conftest.exe'), while it won't with\n# `rm'.\nfor ac_file in conftest.exe conftest conftest.*; do\n  test -f \"$ac_file\" || continue\n  case $ac_file in\n    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;\n    *.* ) ac_cv_exeext=`expr \"$ac_file\" : '[^.]*\\(\\..*\\)'`\n\t  break;;\n    * ) break;;\n  esac\ndone\nelse\n  { { $as_echo \"$as_me:${as_lineno-$LINENO}: error: in \\`$ac_pwd':\" >&5\n$as_echo \"$as_me: error: in \\`$ac_pwd':\" >&2;}\nas_fn_error $? \"cannot compute suffix of executables: cannot compile and link\nSee \\`config.log' for more details\" \"$LINENO\" 5; }\nfi\nrm -f conftest conftest$ac_cv_exeext\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext\" >&5\n$as_echo \"$ac_cv_exeext\" >&6; }\n\nrm -f conftest.$ac_ext\nEXEEXT=$ac_cv_exeext\nac_exeext=$EXEEXT\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <stdio.h>\nint\nmain ()\n{\nFILE *f = fopen (\"conftest.out\", \"w\");\n return ferror (f) || fclose (f) != 0;\n\n  ;\n  return 0;\n}\n_ACEOF\nac_clean_files=\"$ac_clean_files conftest.out\"\n# Check that the compiler produces executables we can run.  If not, either\n# the compiler is broken, or we cross compile.\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling\" >&5\n$as_echo_n \"checking whether we are cross compiling... \" >&6; }\nif test \"$cross_compiling\" != yes; then\n  { { ac_try=\"$ac_link\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\n$as_echo \"$ac_try_echo\"; } >&5\n  (eval \"$ac_link\") 2>&5\n  ac_status=$?\n  $as_echo \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; }\n  if { ac_try='./conftest$ac_cv_exeext'\n  { { case \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\n$as_echo \"$ac_try_echo\"; } >&5\n  (eval \"$ac_try\") 2>&5\n  ac_status=$?\n  $as_echo \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; }; }; then\n    cross_compiling=no\n  else\n    if test \"$cross_compiling\" = maybe; then\n\tcross_compiling=yes\n    else\n\t{ { $as_echo \"$as_me:${as_lineno-$LINENO}: error: in \\`$ac_pwd':\" >&5\n$as_echo \"$as_me: error: in \\`$ac_pwd':\" >&2;}\nas_fn_error $? \"cannot run C compiled programs.\nIf you meant to cross compile, use \\`--host'.\nSee \\`config.log' for more details\" \"$LINENO\" 5; }\n    fi\n  fi\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $cross_compiling\" >&5\n$as_echo \"$cross_compiling\" >&6; }\n\nrm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out\nac_clean_files=$ac_clean_files_save\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for suffix of object files\" >&5\n$as_echo_n \"checking for suffix of object files... \" >&6; }\nif ${ac_cv_objext+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain ()\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nrm -f conftest.o conftest.obj\nif { { ac_try=\"$ac_compile\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\n$as_echo \"$ac_try_echo\"; } >&5\n  (eval \"$ac_compile\") 2>&5\n  ac_status=$?\n  $as_echo \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; }; then :\n  for ac_file in conftest.o conftest.obj conftest.*; do\n  test -f \"$ac_file\" || continue;\n  case $ac_file in\n    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;\n    *) ac_cv_objext=`expr \"$ac_file\" : '.*\\.\\(.*\\)'`\n       break;;\n  esac\ndone\nelse\n  $as_echo \"$as_me: failed program was:\" >&5\nsed 's/^/| /' conftest.$ac_ext >&5\n\n{ { $as_echo \"$as_me:${as_lineno-$LINENO}: error: in \\`$ac_pwd':\" >&5\n$as_echo \"$as_me: error: in \\`$ac_pwd':\" >&2;}\nas_fn_error $? \"cannot compute suffix of object files: cannot compile\nSee \\`config.log' for more details\" \"$LINENO\" 5; }\nfi\nrm -f conftest.$ac_cv_objext conftest.$ac_ext\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext\" >&5\n$as_echo \"$ac_cv_objext\" >&6; }\nOBJEXT=$ac_cv_objext\nac_objext=$OBJEXT\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler\" >&5\n$as_echo_n \"checking whether we are using the GNU C compiler... \" >&6; }\nif ${ac_cv_c_compiler_gnu+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain ()\n{\n#ifndef __GNUC__\n       choke me\n#endif\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  ac_compiler_gnu=yes\nelse\n  ac_compiler_gnu=no\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\nac_cv_c_compiler_gnu=$ac_compiler_gnu\n\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu\" >&5\n$as_echo \"$ac_cv_c_compiler_gnu\" >&6; }\nif test $ac_compiler_gnu = yes; then\n  GCC=yes\nelse\n  GCC=\nfi\nac_test_CFLAGS=${CFLAGS+set}\nac_save_CFLAGS=$CFLAGS\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g\" >&5\n$as_echo_n \"checking whether $CC accepts -g... \" >&6; }\nif ${ac_cv_prog_cc_g+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  ac_save_c_werror_flag=$ac_c_werror_flag\n   ac_c_werror_flag=yes\n   ac_cv_prog_cc_g=no\n   CFLAGS=\"-g\"\n   cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain ()\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  ac_cv_prog_cc_g=yes\nelse\n  CFLAGS=\"\"\n      cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain ()\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n\nelse\n  ac_c_werror_flag=$ac_save_c_werror_flag\n\t CFLAGS=\"-g\"\n\t cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain ()\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  ac_cv_prog_cc_g=yes\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\n   ac_c_werror_flag=$ac_save_c_werror_flag\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g\" >&5\n$as_echo \"$ac_cv_prog_cc_g\" >&6; }\nif test \"$ac_test_CFLAGS\" = set; then\n  CFLAGS=$ac_save_CFLAGS\nelif test $ac_cv_prog_cc_g = yes; then\n  if test \"$GCC\" = yes; then\n    CFLAGS=\"-g -O2\"\n  else\n    CFLAGS=\"-g\"\n  fi\nelse\n  if test \"$GCC\" = yes; then\n    CFLAGS=\"-O2\"\n  else\n    CFLAGS=\n  fi\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89\" >&5\n$as_echo_n \"checking for $CC option to accept ISO C89... \" >&6; }\nif ${ac_cv_prog_cc_c89+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  ac_cv_prog_cc_c89=no\nac_save_CC=$CC\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <stdarg.h>\n#include <stdio.h>\nstruct stat;\n/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */\nstruct buf { int x; };\nFILE * (*rcsopen) (struct buf *, struct stat *, int);\nstatic char *e (p, i)\n     char **p;\n     int i;\n{\n  return p[i];\n}\nstatic char *f (char * (*g) (char **, int), char **p, ...)\n{\n  char *s;\n  va_list v;\n  va_start (v,p);\n  s = g (p, va_arg (v,int));\n  va_end (v);\n  return s;\n}\n\n/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has\n   function prototypes and stuff, but not '\\xHH' hex character constants.\n   These don't provoke an error unfortunately, instead are silently treated\n   as 'x'.  The following induces an error, until -std is added to get\n   proper ANSI mode.  Curiously '\\x00'!='x' always comes out true, for an\n   array size at least.  It's necessary to write '\\x00'==0 to get something\n   that's true only with -std.  */\nint osf4_cc_array ['\\x00' == 0 ? 1 : -1];\n\n/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters\n   inside strings and character constants.  */\n#define FOO(x) 'x'\nint xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];\n\nint test (int i, double x);\nstruct s1 {int (*f) (int a);};\nstruct s2 {int (*f) (double a);};\nint pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);\nint argc;\nchar **argv;\nint\nmain ()\n{\nreturn f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];\n  ;\n  return 0;\n}\n_ACEOF\nfor ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \\\n\t-Ae \"-Aa -D_HPUX_SOURCE\" \"-Xc -D__EXTENSIONS__\"\ndo\n  CC=\"$ac_save_CC $ac_arg\"\n  if ac_fn_c_try_compile \"$LINENO\"; then :\n  ac_cv_prog_cc_c89=$ac_arg\nfi\nrm -f core conftest.err conftest.$ac_objext\n  test \"x$ac_cv_prog_cc_c89\" != \"xno\" && break\ndone\nrm -f conftest.$ac_ext\nCC=$ac_save_CC\n\nfi\n# AC_CACHE_VAL\ncase \"x$ac_cv_prog_cc_c89\" in\n  x)\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: result: none needed\" >&5\n$as_echo \"none needed\" >&6; } ;;\n  xno)\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: result: unsupported\" >&5\n$as_echo \"unsupported\" >&6; } ;;\n  *)\n    CC=\"$CC $ac_cv_prog_cc_c89\"\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89\" >&5\n$as_echo \"$ac_cv_prog_cc_c89\" >&6; } ;;\nesac\nif test \"x$ac_cv_prog_cc_c89\" != xno; then :\n\nfi\n\nac_ext=c\nac_cpp='$CPP $CPPFLAGS'\nac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'\nac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'\nac_compiler_gnu=$ac_cv_c_compiler_gnu\n\nac_ext=c\nac_cpp='$CPP $CPPFLAGS'\nac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'\nac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'\nac_compiler_gnu=$ac_cv_c_compiler_gnu\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together\" >&5\n$as_echo_n \"checking whether $CC understands -c and -o together... \" >&6; }\nif ${am_cv_prog_cc_c_o+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain ()\n{\n\n  ;\n  return 0;\n}\n_ACEOF\n  # Make sure it works both with $CC and with simple cc.\n  # Following AC_PROG_CC_C_O, we do the test twice because some\n  # compilers refuse to overwrite an existing .o file with -o,\n  # though they will create one.\n  am_cv_prog_cc_c_o=yes\n  for am_i in 1 2; do\n    if { echo \"$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext\" >&5\n   ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5\n   ac_status=$?\n   echo \"$as_me:$LINENO: \\$? = $ac_status\" >&5\n   (exit $ac_status); } \\\n         && test -f conftest2.$ac_objext; then\n      : OK\n    else\n      am_cv_prog_cc_c_o=no\n      break\n    fi\n  done\n  rm -f core conftest*\n  unset am_i\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o\" >&5\n$as_echo \"$am_cv_prog_cc_c_o\" >&6; }\nif test \"$am_cv_prog_cc_c_o\" != yes; then\n   # Losing compiler, so override with the script.\n   # FIXME: It is wrong to rewrite CC.\n   # But if we don't then we get into trouble of one sort or another.\n   # A longer-term fix would be to have automake use am__CC in this case,\n   # and then we could set am__CC=\"\\$(top_srcdir)/compile \\$(CC)\"\n   CC=\"$am_aux_dir/compile $CC\"\nfi\nac_ext=c\nac_cpp='$CPP $CPPFLAGS'\nac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'\nac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'\nac_compiler_gnu=$ac_cv_c_compiler_gnu\n\n\n\nac_ext=c\nac_cpp='$CPP $CPPFLAGS'\nac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'\nac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'\nac_compiler_gnu=$ac_cv_c_compiler_gnu\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor\" >&5\n$as_echo_n \"checking how to run the C preprocessor... \" >&6; }\n# On Suns, sometimes $CPP names a directory.\nif test -n \"$CPP\" && test -d \"$CPP\"; then\n  CPP=\nfi\nif test -z \"$CPP\"; then\n  if ${ac_cv_prog_CPP+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n      # Double quotes because CPP needs to be expanded\n    for CPP in \"$CC -E\" \"$CC -E -traditional-cpp\" \"/lib/cpp\"\n    do\n      ac_preproc_ok=false\nfor ac_c_preproc_warn_flag in '' yes\ndo\n  # Use a header file that comes with gcc, so configuring glibc\n  # with a fresh cross-compiler works.\n  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since\n  # <limits.h> exists even on freestanding compilers.\n  # On the NeXT, cc -E runs the code through the compiler's parser,\n  # not just through cpp. \"Syntax error\" is here to catch this case.\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#ifdef __STDC__\n# include <limits.h>\n#else\n# include <assert.h>\n#endif\n\t\t     Syntax error\n_ACEOF\nif ac_fn_c_try_cpp \"$LINENO\"; then :\n\nelse\n  # Broken: fails on valid input.\ncontinue\nfi\nrm -f conftest.err conftest.i conftest.$ac_ext\n\n  # OK, works on sane cases.  Now check whether nonexistent headers\n  # can be detected and how.\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <ac_nonexistent.h>\n_ACEOF\nif ac_fn_c_try_cpp \"$LINENO\"; then :\n  # Broken: success on invalid input.\ncontinue\nelse\n  # Passes both tests.\nac_preproc_ok=:\nbreak\nfi\nrm -f conftest.err conftest.i conftest.$ac_ext\n\ndone\n# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.\nrm -f conftest.i conftest.err conftest.$ac_ext\nif $ac_preproc_ok; then :\n  break\nfi\n\n    done\n    ac_cv_prog_CPP=$CPP\n\nfi\n  CPP=$ac_cv_prog_CPP\nelse\n  ac_cv_prog_CPP=$CPP\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $CPP\" >&5\n$as_echo \"$CPP\" >&6; }\nac_preproc_ok=false\nfor ac_c_preproc_warn_flag in '' yes\ndo\n  # Use a header file that comes with gcc, so configuring glibc\n  # with a fresh cross-compiler works.\n  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since\n  # <limits.h> exists even on freestanding compilers.\n  # On the NeXT, cc -E runs the code through the compiler's parser,\n  # not just through cpp. \"Syntax error\" is here to catch this case.\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#ifdef __STDC__\n# include <limits.h>\n#else\n# include <assert.h>\n#endif\n\t\t     Syntax error\n_ACEOF\nif ac_fn_c_try_cpp \"$LINENO\"; then :\n\nelse\n  # Broken: fails on valid input.\ncontinue\nfi\nrm -f conftest.err conftest.i conftest.$ac_ext\n\n  # OK, works on sane cases.  Now check whether nonexistent headers\n  # can be detected and how.\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <ac_nonexistent.h>\n_ACEOF\nif ac_fn_c_try_cpp \"$LINENO\"; then :\n  # Broken: success on invalid input.\ncontinue\nelse\n  # Passes both tests.\nac_preproc_ok=:\nbreak\nfi\nrm -f conftest.err conftest.i conftest.$ac_ext\n\ndone\n# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.\nrm -f conftest.i conftest.err conftest.$ac_ext\nif $ac_preproc_ok; then :\n\nelse\n  { { $as_echo \"$as_me:${as_lineno-$LINENO}: error: in \\`$ac_pwd':\" >&5\n$as_echo \"$as_me: error: in \\`$ac_pwd':\" >&2;}\nas_fn_error $? \"C preprocessor \\\"$CPP\\\" fails sanity check\nSee \\`config.log' for more details\" \"$LINENO\" 5; }\nfi\n\nac_ext=c\nac_cpp='$CPP $CPPFLAGS'\nac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'\nac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'\nac_compiler_gnu=$ac_cv_c_compiler_gnu\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e\" >&5\n$as_echo_n \"checking for grep that handles long lines and -e... \" >&6; }\nif ${ac_cv_path_GREP+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -z \"$GREP\"; then\n  ac_path_GREP_found=false\n  # Loop through the user's path and test for each of PROGNAME-LIST\n  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_prog in grep ggrep; do\n    for ac_exec_ext in '' $ac_executable_extensions; do\n      ac_path_GREP=\"$as_dir/$ac_prog$ac_exec_ext\"\n      as_fn_executable_p \"$ac_path_GREP\" || continue\n# Check for GNU ac_path_GREP and select it if it is found.\n  # Check for GNU $ac_path_GREP\ncase `\"$ac_path_GREP\" --version 2>&1` in\n*GNU*)\n  ac_cv_path_GREP=\"$ac_path_GREP\" ac_path_GREP_found=:;;\n*)\n  ac_count=0\n  $as_echo_n 0123456789 >\"conftest.in\"\n  while :\n  do\n    cat \"conftest.in\" \"conftest.in\" >\"conftest.tmp\"\n    mv \"conftest.tmp\" \"conftest.in\"\n    cp \"conftest.in\" \"conftest.nl\"\n    $as_echo 'GREP' >> \"conftest.nl\"\n    \"$ac_path_GREP\" -e 'GREP$' -e '-(cannot match)-' < \"conftest.nl\" >\"conftest.out\" 2>/dev/null || break\n    diff \"conftest.out\" \"conftest.nl\" >/dev/null 2>&1 || break\n    as_fn_arith $ac_count + 1 && ac_count=$as_val\n    if test $ac_count -gt ${ac_path_GREP_max-0}; then\n      # Best one so far, save it but keep looking for a better one\n      ac_cv_path_GREP=\"$ac_path_GREP\"\n      ac_path_GREP_max=$ac_count\n    fi\n    # 10*(2^10) chars as input seems more than enough\n    test $ac_count -gt 10 && break\n  done\n  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;\nesac\n\n      $ac_path_GREP_found && break 3\n    done\n  done\n  done\nIFS=$as_save_IFS\n  if test -z \"$ac_cv_path_GREP\"; then\n    as_fn_error $? \"no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin\" \"$LINENO\" 5\n  fi\nelse\n  ac_cv_path_GREP=$GREP\nfi\n\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP\" >&5\n$as_echo \"$ac_cv_path_GREP\" >&6; }\n GREP=\"$ac_cv_path_GREP\"\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for egrep\" >&5\n$as_echo_n \"checking for egrep... \" >&6; }\nif ${ac_cv_path_EGREP+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if echo a | $GREP -E '(a|b)' >/dev/null 2>&1\n   then ac_cv_path_EGREP=\"$GREP -E\"\n   else\n     if test -z \"$EGREP\"; then\n  ac_path_EGREP_found=false\n  # Loop through the user's path and test for each of PROGNAME-LIST\n  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_prog in egrep; do\n    for ac_exec_ext in '' $ac_executable_extensions; do\n      ac_path_EGREP=\"$as_dir/$ac_prog$ac_exec_ext\"\n      as_fn_executable_p \"$ac_path_EGREP\" || continue\n# Check for GNU ac_path_EGREP and select it if it is found.\n  # Check for GNU $ac_path_EGREP\ncase `\"$ac_path_EGREP\" --version 2>&1` in\n*GNU*)\n  ac_cv_path_EGREP=\"$ac_path_EGREP\" ac_path_EGREP_found=:;;\n*)\n  ac_count=0\n  $as_echo_n 0123456789 >\"conftest.in\"\n  while :\n  do\n    cat \"conftest.in\" \"conftest.in\" >\"conftest.tmp\"\n    mv \"conftest.tmp\" \"conftest.in\"\n    cp \"conftest.in\" \"conftest.nl\"\n    $as_echo 'EGREP' >> \"conftest.nl\"\n    \"$ac_path_EGREP\" 'EGREP$' < \"conftest.nl\" >\"conftest.out\" 2>/dev/null || break\n    diff \"conftest.out\" \"conftest.nl\" >/dev/null 2>&1 || break\n    as_fn_arith $ac_count + 1 && ac_count=$as_val\n    if test $ac_count -gt ${ac_path_EGREP_max-0}; then\n      # Best one so far, save it but keep looking for a better one\n      ac_cv_path_EGREP=\"$ac_path_EGREP\"\n      ac_path_EGREP_max=$ac_count\n    fi\n    # 10*(2^10) chars as input seems more than enough\n    test $ac_count -gt 10 && break\n  done\n  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;\nesac\n\n      $ac_path_EGREP_found && break 3\n    done\n  done\n  done\nIFS=$as_save_IFS\n  if test -z \"$ac_cv_path_EGREP\"; then\n    as_fn_error $? \"no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin\" \"$LINENO\" 5\n  fi\nelse\n  ac_cv_path_EGREP=$EGREP\nfi\n\n   fi\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP\" >&5\n$as_echo \"$ac_cv_path_EGREP\" >&6; }\n EGREP=\"$ac_cv_path_EGREP\"\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for ANSI C header files\" >&5\n$as_echo_n \"checking for ANSI C header files... \" >&6; }\nif ${ac_cv_header_stdc+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <stdlib.h>\n#include <stdarg.h>\n#include <string.h>\n#include <float.h>\n\nint\nmain ()\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  ac_cv_header_stdc=yes\nelse\n  ac_cv_header_stdc=no\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\n\nif test $ac_cv_header_stdc = yes; then\n  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <string.h>\n\n_ACEOF\nif (eval \"$ac_cpp conftest.$ac_ext\") 2>&5 |\n  $EGREP \"memchr\" >/dev/null 2>&1; then :\n\nelse\n  ac_cv_header_stdc=no\nfi\nrm -f conftest*\n\nfi\n\nif test $ac_cv_header_stdc = yes; then\n  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <stdlib.h>\n\n_ACEOF\nif (eval \"$ac_cpp conftest.$ac_ext\") 2>&5 |\n  $EGREP \"free\" >/dev/null 2>&1; then :\n\nelse\n  ac_cv_header_stdc=no\nfi\nrm -f conftest*\n\nfi\n\nif test $ac_cv_header_stdc = yes; then\n  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.\n  if test \"$cross_compiling\" = yes; then :\n  :\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <ctype.h>\n#include <stdlib.h>\n#if ((' ' & 0x0FF) == 0x020)\n# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')\n# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))\n#else\n# define ISLOWER(c) \\\n\t\t   (('a' <= (c) && (c) <= 'i') \\\n\t\t     || ('j' <= (c) && (c) <= 'r') \\\n\t\t     || ('s' <= (c) && (c) <= 'z'))\n# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))\n#endif\n\n#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))\nint\nmain ()\n{\n  int i;\n  for (i = 0; i < 256; i++)\n    if (XOR (islower (i), ISLOWER (i))\n\t|| toupper (i) != TOUPPER (i))\n      return 2;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_run \"$LINENO\"; then :\n\nelse\n  ac_cv_header_stdc=no\nfi\nrm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \\\n  conftest.$ac_objext conftest.beam conftest.$ac_ext\nfi\n\nfi\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc\" >&5\n$as_echo \"$ac_cv_header_stdc\" >&6; }\nif test $ac_cv_header_stdc = yes; then\n\n$as_echo \"#define STDC_HEADERS 1\" >>confdefs.h\n\nfi\n\n# On IRIX 5.3, sys/types and inttypes.h are conflicting.\nfor ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \\\n\t\t  inttypes.h stdint.h unistd.h\ndo :\n  as_ac_Header=`$as_echo \"ac_cv_header_$ac_header\" | $as_tr_sh`\nac_fn_c_check_header_compile \"$LINENO\" \"$ac_header\" \"$as_ac_Header\" \"$ac_includes_default\n\"\nif eval test \\\"x\\$\"$as_ac_Header\"\\\" = x\"yes\"; then :\n  cat >>confdefs.h <<_ACEOF\n#define `$as_echo \"HAVE_$ac_header\" | $as_tr_cpp` 1\n_ACEOF\n\nfi\n\ndone\n\n\n\n  ac_fn_c_check_header_mongrel \"$LINENO\" \"minix/config.h\" \"ac_cv_header_minix_config_h\" \"$ac_includes_default\"\nif test \"x$ac_cv_header_minix_config_h\" = xyes; then :\n  MINIX=yes\nelse\n  MINIX=\nfi\n\n\n  if test \"$MINIX\" = yes; then\n\n$as_echo \"#define _POSIX_SOURCE 1\" >>confdefs.h\n\n\n$as_echo \"#define _POSIX_1_SOURCE 2\" >>confdefs.h\n\n\n$as_echo \"#define _MINIX 1\" >>confdefs.h\n\n  fi\n\n\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether it is safe to define __EXTENSIONS__\" >&5\n$as_echo_n \"checking whether it is safe to define __EXTENSIONS__... \" >&6; }\nif ${ac_cv_safe_to_define___extensions__+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n#         define __EXTENSIONS__ 1\n          $ac_includes_default\nint\nmain ()\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  ac_cv_safe_to_define___extensions__=yes\nelse\n  ac_cv_safe_to_define___extensions__=no\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_safe_to_define___extensions__\" >&5\n$as_echo \"$ac_cv_safe_to_define___extensions__\" >&6; }\n  test $ac_cv_safe_to_define___extensions__ = yes &&\n    $as_echo \"#define __EXTENSIONS__ 1\" >>confdefs.h\n\n  $as_echo \"#define _ALL_SOURCE 1\" >>confdefs.h\n\n  $as_echo \"#define _GNU_SOURCE 1\" >>confdefs.h\n\n  $as_echo \"#define _POSIX_PTHREAD_SEMANTICS 1\" >>confdefs.h\n\n  $as_echo \"#define _TANDEM_SOURCE 1\" >>confdefs.h\n\n\n\n# Default to not building a shared library.\n# Check whether --enable-shared was given.\nif test \"${enable_shared+set}\" = set; then :\n  enableval=$enable_shared; p=${PACKAGE-default}\n    case $enableval in\n    yes) enable_shared=yes ;;\n    no) enable_shared=no ;;\n    *)\n      enable_shared=no\n      # Look at the argument we got.  We use all the common list separators.\n      lt_save_ifs=\"$IFS\"; IFS=\"${IFS}$PATH_SEPARATOR,\"\n      for pkg in $enableval; do\n\tIFS=\"$lt_save_ifs\"\n\tif test \"X$pkg\" = \"X$p\"; then\n\t  enable_shared=yes\n\tfi\n      done\n      IFS=\"$lt_save_ifs\"\n      ;;\n    esac\nelse\n  enable_shared=no\nfi\n\n\n\n\n\n\n\n\n\n\nlibtool_VERSION=1:0:0\n\n\n# 1.11.1: Require that version of automake.\n# foreign: Don't require README, INSTALL, NEWS, etc.\n# no-define: Don't define PACKAGE and VERSION.\n# no-dependencies: Don't generate automatic dependencies.\n#    (because it breaks when using bootstrap-lean, since some of the\n#    headers are gone at \"make install\" time).\n# -Wall: Issue all automake warnings.\n# -Wno-portability: Don't warn about constructs supported by GNU make.\n#    (because GCC requires GNU make anyhow).\nam__api_version='1.15'\n\n# Find a good install program.  We prefer a C program (faster),\n# so one script is as good as another.  But avoid the broken or\n# incompatible versions:\n# SysV /etc/install, /usr/sbin/install\n# SunOS /usr/etc/install\n# IRIX /sbin/install\n# AIX /bin/install\n# AmigaOS /C/install, which installs bootblocks on floppy discs\n# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag\n# AFS /usr/afsws/bin/install, which mishandles nonexistent args\n# SVR4 /usr/ucb/install, which tries to use the nonexistent group \"staff\"\n# OS/2's system install, which has a completely different semantic\n# ./install, which can be erroneously created by make from ./install.sh.\n# Reject install programs that cannot install multiple files.\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install\" >&5\n$as_echo_n \"checking for a BSD-compatible install... \" >&6; }\nif test -z \"$INSTALL\"; then\nif ${ac_cv_path_install+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    # Account for people who put trailing slashes in PATH elements.\ncase $as_dir/ in #((\n  ./ | .// | /[cC]/* | \\\n  /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \\\n  ?:[\\\\/]os2[\\\\/]install[\\\\/]* | ?:[\\\\/]OS2[\\\\/]INSTALL[\\\\/]* | \\\n  /usr/ucb/* ) ;;\n  *)\n    # OSF1 and SCO ODT 3.0 have their own names for install.\n    # Don't use installbsd from OSF since it installs stuff as root\n    # by default.\n    for ac_prog in ginstall scoinst install; do\n      for ac_exec_ext in '' $ac_executable_extensions; do\n\tif as_fn_executable_p \"$as_dir/$ac_prog$ac_exec_ext\"; then\n\t  if test $ac_prog = install &&\n\t    grep dspmsg \"$as_dir/$ac_prog$ac_exec_ext\" >/dev/null 2>&1; then\n\t    # AIX install.  It has an incompatible calling convention.\n\t    :\n\t  elif test $ac_prog = install &&\n\t    grep pwplus \"$as_dir/$ac_prog$ac_exec_ext\" >/dev/null 2>&1; then\n\t    # program-specific install script used by HP pwplus--don't use.\n\t    :\n\t  else\n\t    rm -rf conftest.one conftest.two conftest.dir\n\t    echo one > conftest.one\n\t    echo two > conftest.two\n\t    mkdir conftest.dir\n\t    if \"$as_dir/$ac_prog$ac_exec_ext\" -c conftest.one conftest.two \"`pwd`/conftest.dir\" &&\n\t      test -s conftest.one && test -s conftest.two &&\n\t      test -s conftest.dir/conftest.one &&\n\t      test -s conftest.dir/conftest.two\n\t    then\n\t      ac_cv_path_install=\"$as_dir/$ac_prog$ac_exec_ext -c\"\n\t      break 3\n\t    fi\n\t  fi\n\tfi\n      done\n    done\n    ;;\nesac\n\n  done\nIFS=$as_save_IFS\n\nrm -rf conftest.one conftest.two conftest.dir\n\nfi\n  if test \"${ac_cv_path_install+set}\" = set; then\n    INSTALL=$ac_cv_path_install\n  else\n    # As a last resort, use the slow shell script.  Don't cache a\n    # value for INSTALL within a source directory, because that will\n    # break other packages using the cache if that directory is\n    # removed, or if the value is a relative name.\n    INSTALL=$ac_install_sh\n  fi\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $INSTALL\" >&5\n$as_echo \"$INSTALL\" >&6; }\n\n# Use test -z because SunOS4 sh mishandles braces in ${var-val}.\n# It thinks the first close brace ends the variable substitution.\ntest -z \"$INSTALL_PROGRAM\" && INSTALL_PROGRAM='${INSTALL}'\n\ntest -z \"$INSTALL_SCRIPT\" && INSTALL_SCRIPT='${INSTALL}'\n\ntest -z \"$INSTALL_DATA\" && INSTALL_DATA='${INSTALL} -m 644'\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether build environment is sane\" >&5\n$as_echo_n \"checking whether build environment is sane... \" >&6; }\n# Reject unsafe characters in $srcdir or the absolute working directory\n# name.  Accept space and tab only in the latter.\nam_lf='\n'\ncase `pwd` in\n  *[\\\\\\\"\\#\\$\\&\\'\\`$am_lf]*)\n    as_fn_error $? \"unsafe absolute working directory name\" \"$LINENO\" 5;;\nesac\ncase $srcdir in\n  *[\\\\\\\"\\#\\$\\&\\'\\`$am_lf\\ \\\t]*)\n    as_fn_error $? \"unsafe srcdir value: '$srcdir'\" \"$LINENO\" 5;;\nesac\n\n# Do 'set' in a subshell so we don't clobber the current shell's\n# arguments.  Must try -L first in case configure is actually a\n# symlink; some systems play weird games with the mod time of symlinks\n# (eg FreeBSD returns the mod time of the symlink's containing\n# directory).\nif (\n   am_has_slept=no\n   for am_try in 1 2; do\n     echo \"timestamp, slept: $am_has_slept\" > conftest.file\n     set X `ls -Lt \"$srcdir/configure\" conftest.file 2> /dev/null`\n     if test \"$*\" = \"X\"; then\n\t# -L didn't work.\n\tset X `ls -t \"$srcdir/configure\" conftest.file`\n     fi\n     if test \"$*\" != \"X $srcdir/configure conftest.file\" \\\n\t&& test \"$*\" != \"X conftest.file $srcdir/configure\"; then\n\n\t# If neither matched, then we have a broken ls.  This can happen\n\t# if, for instance, CONFIG_SHELL is bash and it inherits a\n\t# broken ls alias from the environment.  This has actually\n\t# happened.  Such a system could not be considered \"sane\".\n\tas_fn_error $? \"ls -t appears to fail.  Make sure there is not a broken\n  alias in your environment\" \"$LINENO\" 5\n     fi\n     if test \"$2\" = conftest.file || test $am_try -eq 2; then\n       break\n     fi\n     # Just in case.\n     sleep 1\n     am_has_slept=yes\n   done\n   test \"$2\" = conftest.file\n   )\nthen\n   # Ok.\n   :\nelse\n   as_fn_error $? \"newly created file is older than distributed files!\nCheck your system clock\" \"$LINENO\" 5\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\n$as_echo \"yes\" >&6; }\n# If we didn't sleep, we still need to ensure time stamps of config.status and\n# generated files are strictly newer.\nam_sleep_pid=\nif grep 'slept: no' conftest.file >/dev/null 2>&1; then\n  ( sleep 1 ) &\n  am_sleep_pid=$!\nfi\n\nrm -f conftest.file\n\ntest \"$program_prefix\" != NONE &&\n  program_transform_name=\"s&^&$program_prefix&;$program_transform_name\"\n# Use a double $ so make ignores it.\ntest \"$program_suffix\" != NONE &&\n  program_transform_name=\"s&\\$&$program_suffix&;$program_transform_name\"\n# Double any \\ or $.\n# By default was `s,x,x', remove it if useless.\nac_script='s/[\\\\$]/&&/g;s/;s,x,x,$//'\nprogram_transform_name=`$as_echo \"$program_transform_name\" | sed \"$ac_script\"`\n\nif test x\"${MISSING+set}\" != xset; then\n  case $am_aux_dir in\n  *\\ * | *\\\t*)\n    MISSING=\"\\${SHELL} \\\"$am_aux_dir/missing\\\"\" ;;\n  *)\n    MISSING=\"\\${SHELL} $am_aux_dir/missing\" ;;\n  esac\nfi\n# Use eval to expand $SHELL\nif eval \"$MISSING --is-lightweight\"; then\n  am_missing_run=\"$MISSING \"\nelse\n  am_missing_run=\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing\" >&5\n$as_echo \"$as_me: WARNING: 'missing' script is too old or missing\" >&2;}\nfi\n\nif test x\"${install_sh+set}\" != xset; then\n  case $am_aux_dir in\n  *\\ * | *\\\t*)\n    install_sh=\"\\${SHELL} '$am_aux_dir/install-sh'\" ;;\n  *)\n    install_sh=\"\\${SHELL} $am_aux_dir/install-sh\"\n  esac\nfi\n\n# Installed binaries are usually stripped using 'strip' when the user\n# run \"make install-strip\".  However 'strip' might not be the right\n# tool to use in cross-compilation environments, therefore Automake\n# will honor the 'STRIP' environment variable to overrule this program.\nif test \"$cross_compiling\" != no; then\n  if test -n \"$ac_tool_prefix\"; then\n  # Extract the first word of \"${ac_tool_prefix}strip\", so it can be a program name with args.\nset dummy ${ac_tool_prefix}strip; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_STRIP+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$STRIP\"; then\n  ac_cv_prog_STRIP=\"$STRIP\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_STRIP=\"${ac_tool_prefix}strip\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nSTRIP=$ac_cv_prog_STRIP\nif test -n \"$STRIP\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $STRIP\" >&5\n$as_echo \"$STRIP\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\nfi\nif test -z \"$ac_cv_prog_STRIP\"; then\n  ac_ct_STRIP=$STRIP\n  # Extract the first word of \"strip\", so it can be a program name with args.\nset dummy strip; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_ac_ct_STRIP+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$ac_ct_STRIP\"; then\n  ac_cv_prog_ac_ct_STRIP=\"$ac_ct_STRIP\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_ac_ct_STRIP=\"strip\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP\nif test -n \"$ac_ct_STRIP\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP\" >&5\n$as_echo \"$ac_ct_STRIP\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n  if test \"x$ac_ct_STRIP\" = x; then\n    STRIP=\":\"\n  else\n    case $cross_compiling:$ac_tool_warned in\nyes:)\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet\" >&5\n$as_echo \"$as_me: WARNING: using cross tools not prefixed with host triplet\" >&2;}\nac_tool_warned=yes ;;\nesac\n    STRIP=$ac_ct_STRIP\n  fi\nelse\n  STRIP=\"$ac_cv_prog_STRIP\"\nfi\n\nfi\nINSTALL_STRIP_PROGRAM=\"\\$(install_sh) -c -s\"\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p\" >&5\n$as_echo_n \"checking for a thread-safe mkdir -p... \" >&6; }\nif test -z \"$MKDIR_P\"; then\n  if ${ac_cv_path_mkdir+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_prog in mkdir gmkdir; do\n\t for ac_exec_ext in '' $ac_executable_extensions; do\n\t   as_fn_executable_p \"$as_dir/$ac_prog$ac_exec_ext\" || continue\n\t   case `\"$as_dir/$ac_prog$ac_exec_ext\" --version 2>&1` in #(\n\t     'mkdir (GNU coreutils) '* | \\\n\t     'mkdir (coreutils) '* | \\\n\t     'mkdir (fileutils) '4.1*)\n\t       ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext\n\t       break 3;;\n\t   esac\n\t done\n       done\n  done\nIFS=$as_save_IFS\n\nfi\n\n  test -d ./--version && rmdir ./--version\n  if test \"${ac_cv_path_mkdir+set}\" = set; then\n    MKDIR_P=\"$ac_cv_path_mkdir -p\"\n  else\n    # As a last resort, use the slow shell script.  Don't cache a\n    # value for MKDIR_P within a source directory, because that will\n    # break other packages using the cache if that directory is\n    # removed, or if the value is a relative name.\n    MKDIR_P=\"$ac_install_sh -d\"\n  fi\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $MKDIR_P\" >&5\n$as_echo \"$MKDIR_P\" >&6; }\n\nfor ac_prog in gawk mawk nawk awk\ndo\n  # Extract the first word of \"$ac_prog\", so it can be a program name with args.\nset dummy $ac_prog; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_AWK+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$AWK\"; then\n  ac_cv_prog_AWK=\"$AWK\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_AWK=\"$ac_prog\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nAWK=$ac_cv_prog_AWK\nif test -n \"$AWK\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $AWK\" >&5\n$as_echo \"$AWK\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\n  test -n \"$AWK\" && break\ndone\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \\$(MAKE)\" >&5\n$as_echo_n \"checking whether ${MAKE-make} sets \\$(MAKE)... \" >&6; }\nset x ${MAKE-make}\nac_make=`$as_echo \"$2\" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`\nif eval \\${ac_cv_prog_make_${ac_make}_set+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  cat >conftest.make <<\\_ACEOF\nSHELL = /bin/sh\nall:\n\t@echo '@@@%%%=$(MAKE)=@@@%%%'\n_ACEOF\n# GNU make sometimes prints \"make[1]: Entering ...\", which would confuse us.\ncase `${MAKE-make} -f conftest.make 2>/dev/null` in\n  *@@@%%%=?*=@@@%%%*)\n    eval ac_cv_prog_make_${ac_make}_set=yes;;\n  *)\n    eval ac_cv_prog_make_${ac_make}_set=no;;\nesac\nrm -f conftest.make\nfi\nif eval test \\$ac_cv_prog_make_${ac_make}_set = yes; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\n$as_echo \"yes\" >&6; }\n  SET_MAKE=\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\n  SET_MAKE=\"MAKE=${MAKE-make}\"\nfi\n\nrm -rf .tst 2>/dev/null\nmkdir .tst 2>/dev/null\nif test -d .tst; then\n  am__leading_dot=.\nelse\n  am__leading_dot=_\nfi\nrmdir .tst 2>/dev/null\n\n# Check whether --enable-silent-rules was given.\nif test \"${enable_silent_rules+set}\" = set; then :\n  enableval=$enable_silent_rules;\nfi\n\ncase $enable_silent_rules in # (((\n  yes) AM_DEFAULT_VERBOSITY=0;;\n   no) AM_DEFAULT_VERBOSITY=1;;\n    *) AM_DEFAULT_VERBOSITY=1;;\nesac\nam_make=${MAKE-make}\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables\" >&5\n$as_echo_n \"checking whether $am_make supports nested variables... \" >&6; }\nif ${am_cv_make_support_nested_variables+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if $as_echo 'TRUE=$(BAR$(V))\nBAR0=false\nBAR1=true\nV=1\nam__doit:\n\t@$(TRUE)\n.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then\n  am_cv_make_support_nested_variables=yes\nelse\n  am_cv_make_support_nested_variables=no\nfi\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables\" >&5\n$as_echo \"$am_cv_make_support_nested_variables\" >&6; }\nif test $am_cv_make_support_nested_variables = yes; then\n    AM_V='$(V)'\n  AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'\nelse\n  AM_V=$AM_DEFAULT_VERBOSITY\n  AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY\nfi\nAM_BACKSLASH='\\'\n\nif test \"`cd $srcdir && pwd`\" != \"`pwd`\"; then\n  # Use -I$(srcdir) only when $(srcdir) != ., so that make's output\n  # is not polluted with repeated \"-I.\"\n  am__isrc=' -I$(srcdir)'\n  # test to see if srcdir already configured\n  if test -f $srcdir/config.status; then\n    as_fn_error $? \"source directory already configured; run \\\"make distclean\\\" there first\" \"$LINENO\" 5\n  fi\nfi\n\n# test whether we have cygpath\nif test -z \"$CYGPATH_W\"; then\n  if (cygpath --version) >/dev/null 2>/dev/null; then\n    CYGPATH_W='cygpath -w'\n  else\n    CYGPATH_W=echo\n  fi\nfi\n\n\n# Define the identity of the package.\n PACKAGE='libbacktrace'\n VERSION='version-unused'\n\n\n# Some tools Automake needs.\n\nACLOCAL=${ACLOCAL-\"${am_missing_run}aclocal-${am__api_version}\"}\n\n\nAUTOCONF=${AUTOCONF-\"${am_missing_run}autoconf\"}\n\n\nAUTOMAKE=${AUTOMAKE-\"${am_missing_run}automake-${am__api_version}\"}\n\n\nAUTOHEADER=${AUTOHEADER-\"${am_missing_run}autoheader\"}\n\n\nMAKEINFO=${MAKEINFO-\"${am_missing_run}makeinfo\"}\n\n# For better backward compatibility.  To be removed once Automake 1.9.x\n# dies out for good.  For more background, see:\n# <http://lists.gnu.org/archive/html/automake/2012-07/msg00001.html>\n# <http://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>\nmkdir_p='$(MKDIR_P)'\n\n# We need awk for the \"check\" target (and possibly the TAP driver).  The\n# system \"awk\" is bad on some platforms.\n# Always define AMTAR for backward compatibility.  Yes, it's still used\n# in the wild :-(  We should find a proper way to deprecate it ...\nAMTAR='$${TAR-tar}'\n\n\n# We'll loop over all known methods to create a tar archive until one works.\n_am_tools='gnutar  pax cpio none'\n\nam__tar='$${TAR-tar} chof - \"$$tardir\"' am__untar='$${TAR-tar} xf -'\n\n\n\n\n\n\n# POSIX will say in a future version that running \"rm -f\" with no argument\n# is OK; and we want to be able to make that assumption in our Makefile\n# recipes.  So use an aggressive probe to check that the usage we want is\n# actually supported \"in the wild\" to an acceptable degree.\n# See automake bug#10828.\n# To make any issue more visible, cause the running configure to be aborted\n# by default if the 'rm' program in use doesn't match our expectations; the\n# user can still override this though.\nif rm -f && rm -fr && rm -rf; then : OK; else\n  cat >&2 <<'END'\nOops!\n\nYour 'rm' program seems unable to run without file operands specified\non the command line, even when the '-f' option is present.  This is contrary\nto the behaviour of most rm programs out there, and not conforming with\nthe upcoming POSIX standard: <http://austingroupbugs.net/view.php?id=542>\n\nPlease tell bug-automake@gnu.org about your system, including the value\nof your $PATH and any error possibly output before this message.  This\ncan help us improve future automake versions.\n\nEND\n  if test x\"$ACCEPT_INFERIOR_RM_PROGRAM\" = x\"yes\"; then\n    echo 'Configuration will proceed anyway, since you have set the' >&2\n    echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to \"yes\"' >&2\n    echo >&2\n  else\n    cat >&2 <<'END'\nAborting the configuration process, to ensure you take notice of the issue.\n\nYou can download and install GNU coreutils to get an 'rm' implementation\nthat behaves properly: <http://www.gnu.org/software/coreutils/>.\n\nIf you want to complete the configuration process using your problematic\n'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM\nto \"yes\", and re-run configure.\n\nEND\n    as_fn_error $? \"Your 'rm' program is bad, sorry.\" \"$LINENO\" 5\n  fi\nfi\n\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles\" >&5\n$as_echo_n \"checking whether to enable maintainer-specific portions of Makefiles... \" >&6; }\n    # Check whether --enable-maintainer-mode was given.\nif test \"${enable_maintainer_mode+set}\" = set; then :\n  enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval\nelse\n  USE_MAINTAINER_MODE=no\nfi\n\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE\" >&5\n$as_echo \"$USE_MAINTAINER_MODE\" >&6; }\n   if test $USE_MAINTAINER_MODE = yes; then\n  MAINTAINER_MODE_TRUE=\n  MAINTAINER_MODE_FALSE='#'\nelse\n  MAINTAINER_MODE_TRUE='#'\n  MAINTAINER_MODE_FALSE=\nfi\n\n  MAINT=$MAINTAINER_MODE_TRUE\n\n\n\n\n# Check whether --with-target-subdir was given.\nif test \"${with_target_subdir+set}\" = set; then :\n  withval=$with_target_subdir;\nfi\n\n\n# We must force CC to /not/ be precious variables; otherwise\n# the wrong, non-multilib-adjusted value will be used in multilibs.\n# As a side effect, we have to subst CFLAGS ourselves.\n\n\nac_ext=c\nac_cpp='$CPP $CPPFLAGS'\nac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'\nac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'\nac_compiler_gnu=$ac_cv_c_compiler_gnu\nif test -n \"$ac_tool_prefix\"; then\n  # Extract the first word of \"${ac_tool_prefix}gcc\", so it can be a program name with args.\nset dummy ${ac_tool_prefix}gcc; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_CC+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$CC\"; then\n  ac_cv_prog_CC=\"$CC\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_CC=\"${ac_tool_prefix}gcc\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nCC=$ac_cv_prog_CC\nif test -n \"$CC\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $CC\" >&5\n$as_echo \"$CC\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\nfi\nif test -z \"$ac_cv_prog_CC\"; then\n  ac_ct_CC=$CC\n  # Extract the first word of \"gcc\", so it can be a program name with args.\nset dummy gcc; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_ac_ct_CC+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$ac_ct_CC\"; then\n  ac_cv_prog_ac_ct_CC=\"$ac_ct_CC\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_ac_ct_CC=\"gcc\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nac_ct_CC=$ac_cv_prog_ac_ct_CC\nif test -n \"$ac_ct_CC\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC\" >&5\n$as_echo \"$ac_ct_CC\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n  if test \"x$ac_ct_CC\" = x; then\n    CC=\"\"\n  else\n    case $cross_compiling:$ac_tool_warned in\nyes:)\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet\" >&5\n$as_echo \"$as_me: WARNING: using cross tools not prefixed with host triplet\" >&2;}\nac_tool_warned=yes ;;\nesac\n    CC=$ac_ct_CC\n  fi\nelse\n  CC=\"$ac_cv_prog_CC\"\nfi\n\nif test -z \"$CC\"; then\n          if test -n \"$ac_tool_prefix\"; then\n    # Extract the first word of \"${ac_tool_prefix}cc\", so it can be a program name with args.\nset dummy ${ac_tool_prefix}cc; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_CC+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$CC\"; then\n  ac_cv_prog_CC=\"$CC\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_CC=\"${ac_tool_prefix}cc\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nCC=$ac_cv_prog_CC\nif test -n \"$CC\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $CC\" >&5\n$as_echo \"$CC\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\n  fi\nfi\nif test -z \"$CC\"; then\n  # Extract the first word of \"cc\", so it can be a program name with args.\nset dummy cc; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_CC+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$CC\"; then\n  ac_cv_prog_CC=\"$CC\" # Let the user override the test.\nelse\n  ac_prog_rejected=no\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    if test \"$as_dir/$ac_word$ac_exec_ext\" = \"/usr/ucb/cc\"; then\n       ac_prog_rejected=yes\n       continue\n     fi\n    ac_cv_prog_CC=\"cc\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nif test $ac_prog_rejected = yes; then\n  # We found a bogon in the path, so make sure we never use it.\n  set dummy $ac_cv_prog_CC\n  shift\n  if test $# != 0; then\n    # We chose a different compiler from the bogus one.\n    # However, it has the same basename, so the bogon will be chosen\n    # first if we set CC to just the basename; use the full file name.\n    shift\n    ac_cv_prog_CC=\"$as_dir/$ac_word${1+' '}$@\"\n  fi\nfi\nfi\nfi\nCC=$ac_cv_prog_CC\nif test -n \"$CC\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $CC\" >&5\n$as_echo \"$CC\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\nfi\nif test -z \"$CC\"; then\n  if test -n \"$ac_tool_prefix\"; then\n  for ac_prog in cl.exe\n  do\n    # Extract the first word of \"$ac_tool_prefix$ac_prog\", so it can be a program name with args.\nset dummy $ac_tool_prefix$ac_prog; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_CC+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$CC\"; then\n  ac_cv_prog_CC=\"$CC\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_CC=\"$ac_tool_prefix$ac_prog\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nCC=$ac_cv_prog_CC\nif test -n \"$CC\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $CC\" >&5\n$as_echo \"$CC\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\n    test -n \"$CC\" && break\n  done\nfi\nif test -z \"$CC\"; then\n  ac_ct_CC=$CC\n  for ac_prog in cl.exe\ndo\n  # Extract the first word of \"$ac_prog\", so it can be a program name with args.\nset dummy $ac_prog; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_ac_ct_CC+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$ac_ct_CC\"; then\n  ac_cv_prog_ac_ct_CC=\"$ac_ct_CC\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_ac_ct_CC=\"$ac_prog\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nac_ct_CC=$ac_cv_prog_ac_ct_CC\nif test -n \"$ac_ct_CC\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC\" >&5\n$as_echo \"$ac_ct_CC\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\n  test -n \"$ac_ct_CC\" && break\ndone\n\n  if test \"x$ac_ct_CC\" = x; then\n    CC=\"\"\n  else\n    case $cross_compiling:$ac_tool_warned in\nyes:)\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet\" >&5\n$as_echo \"$as_me: WARNING: using cross tools not prefixed with host triplet\" >&2;}\nac_tool_warned=yes ;;\nesac\n    CC=$ac_ct_CC\n  fi\nfi\n\nfi\n\n\ntest -z \"$CC\" && { { $as_echo \"$as_me:${as_lineno-$LINENO}: error: in \\`$ac_pwd':\" >&5\n$as_echo \"$as_me: error: in \\`$ac_pwd':\" >&2;}\nas_fn_error $? \"no acceptable C compiler found in \\$PATH\nSee \\`config.log' for more details\" \"$LINENO\" 5; }\n\n# Provide some information about the compiler.\n$as_echo \"$as_me:${as_lineno-$LINENO}: checking for C compiler version\" >&5\nset X $ac_compile\nac_compiler=$2\nfor ac_option in --version -v -V -qversion; do\n  { { ac_try=\"$ac_compiler $ac_option >&5\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\n$as_echo \"$ac_try_echo\"; } >&5\n  (eval \"$ac_compiler $ac_option >&5\") 2>conftest.err\n  ac_status=$?\n  if test -s conftest.err; then\n    sed '10a\\\n... rest of stderr output deleted ...\n         10q' conftest.err >conftest.er1\n    cat conftest.er1 >&5\n  fi\n  rm -f conftest.er1 conftest.err\n  $as_echo \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; }\ndone\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler\" >&5\n$as_echo_n \"checking whether we are using the GNU C compiler... \" >&6; }\nif ${ac_cv_c_compiler_gnu+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain ()\n{\n#ifndef __GNUC__\n       choke me\n#endif\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  ac_compiler_gnu=yes\nelse\n  ac_compiler_gnu=no\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\nac_cv_c_compiler_gnu=$ac_compiler_gnu\n\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu\" >&5\n$as_echo \"$ac_cv_c_compiler_gnu\" >&6; }\nif test $ac_compiler_gnu = yes; then\n  GCC=yes\nelse\n  GCC=\nfi\nac_test_CFLAGS=${CFLAGS+set}\nac_save_CFLAGS=$CFLAGS\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g\" >&5\n$as_echo_n \"checking whether $CC accepts -g... \" >&6; }\nif ${ac_cv_prog_cc_g+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  ac_save_c_werror_flag=$ac_c_werror_flag\n   ac_c_werror_flag=yes\n   ac_cv_prog_cc_g=no\n   CFLAGS=\"-g\"\n   cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain ()\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  ac_cv_prog_cc_g=yes\nelse\n  CFLAGS=\"\"\n      cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain ()\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n\nelse\n  ac_c_werror_flag=$ac_save_c_werror_flag\n\t CFLAGS=\"-g\"\n\t cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain ()\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  ac_cv_prog_cc_g=yes\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\n   ac_c_werror_flag=$ac_save_c_werror_flag\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g\" >&5\n$as_echo \"$ac_cv_prog_cc_g\" >&6; }\nif test \"$ac_test_CFLAGS\" = set; then\n  CFLAGS=$ac_save_CFLAGS\nelif test $ac_cv_prog_cc_g = yes; then\n  if test \"$GCC\" = yes; then\n    CFLAGS=\"-g -O2\"\n  else\n    CFLAGS=\"-g\"\n  fi\nelse\n  if test \"$GCC\" = yes; then\n    CFLAGS=\"-O2\"\n  else\n    CFLAGS=\n  fi\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89\" >&5\n$as_echo_n \"checking for $CC option to accept ISO C89... \" >&6; }\nif ${ac_cv_prog_cc_c89+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  ac_cv_prog_cc_c89=no\nac_save_CC=$CC\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <stdarg.h>\n#include <stdio.h>\nstruct stat;\n/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */\nstruct buf { int x; };\nFILE * (*rcsopen) (struct buf *, struct stat *, int);\nstatic char *e (p, i)\n     char **p;\n     int i;\n{\n  return p[i];\n}\nstatic char *f (char * (*g) (char **, int), char **p, ...)\n{\n  char *s;\n  va_list v;\n  va_start (v,p);\n  s = g (p, va_arg (v,int));\n  va_end (v);\n  return s;\n}\n\n/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has\n   function prototypes and stuff, but not '\\xHH' hex character constants.\n   These don't provoke an error unfortunately, instead are silently treated\n   as 'x'.  The following induces an error, until -std is added to get\n   proper ANSI mode.  Curiously '\\x00'!='x' always comes out true, for an\n   array size at least.  It's necessary to write '\\x00'==0 to get something\n   that's true only with -std.  */\nint osf4_cc_array ['\\x00' == 0 ? 1 : -1];\n\n/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters\n   inside strings and character constants.  */\n#define FOO(x) 'x'\nint xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];\n\nint test (int i, double x);\nstruct s1 {int (*f) (int a);};\nstruct s2 {int (*f) (double a);};\nint pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);\nint argc;\nchar **argv;\nint\nmain ()\n{\nreturn f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];\n  ;\n  return 0;\n}\n_ACEOF\nfor ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \\\n\t-Ae \"-Aa -D_HPUX_SOURCE\" \"-Xc -D__EXTENSIONS__\"\ndo\n  CC=\"$ac_save_CC $ac_arg\"\n  if ac_fn_c_try_compile \"$LINENO\"; then :\n  ac_cv_prog_cc_c89=$ac_arg\nfi\nrm -f core conftest.err conftest.$ac_objext\n  test \"x$ac_cv_prog_cc_c89\" != \"xno\" && break\ndone\nrm -f conftest.$ac_ext\nCC=$ac_save_CC\n\nfi\n# AC_CACHE_VAL\ncase \"x$ac_cv_prog_cc_c89\" in\n  x)\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: result: none needed\" >&5\n$as_echo \"none needed\" >&6; } ;;\n  xno)\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: result: unsupported\" >&5\n$as_echo \"unsupported\" >&6; } ;;\n  *)\n    CC=\"$CC $ac_cv_prog_cc_c89\"\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89\" >&5\n$as_echo \"$ac_cv_prog_cc_c89\" >&6; } ;;\nesac\nif test \"x$ac_cv_prog_cc_c89\" != xno; then :\n\nfi\n\nac_ext=c\nac_cpp='$CPP $CPPFLAGS'\nac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'\nac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'\nac_compiler_gnu=$ac_cv_c_compiler_gnu\n\nac_ext=c\nac_cpp='$CPP $CPPFLAGS'\nac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'\nac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'\nac_compiler_gnu=$ac_cv_c_compiler_gnu\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together\" >&5\n$as_echo_n \"checking whether $CC understands -c and -o together... \" >&6; }\nif ${am_cv_prog_cc_c_o+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain ()\n{\n\n  ;\n  return 0;\n}\n_ACEOF\n  # Make sure it works both with $CC and with simple cc.\n  # Following AC_PROG_CC_C_O, we do the test twice because some\n  # compilers refuse to overwrite an existing .o file with -o,\n  # though they will create one.\n  am_cv_prog_cc_c_o=yes\n  for am_i in 1 2; do\n    if { echo \"$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext\" >&5\n   ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5\n   ac_status=$?\n   echo \"$as_me:$LINENO: \\$? = $ac_status\" >&5\n   (exit $ac_status); } \\\n         && test -f conftest2.$ac_objext; then\n      : OK\n    else\n      am_cv_prog_cc_c_o=no\n      break\n    fi\n  done\n  rm -f core conftest*\n  unset am_i\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o\" >&5\n$as_echo \"$am_cv_prog_cc_c_o\" >&6; }\nif test \"$am_cv_prog_cc_c_o\" != yes; then\n   # Losing compiler, so override with the script.\n   # FIXME: It is wrong to rewrite CC.\n   # But if we don't then we get into trouble of one sort or another.\n   # A longer-term fix would be to have automake use am__CC in this case,\n   # and then we could set am__CC=\"\\$(top_srcdir)/compile \\$(CC)\"\n   CC=\"$am_aux_dir/compile $CC\"\nfi\nac_ext=c\nac_cpp='$CPP $CPPFLAGS'\nac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'\nac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'\nac_compiler_gnu=$ac_cv_c_compiler_gnu\n\n\n\n\n\n\nif test -n \"$ac_tool_prefix\"; then\n  # Extract the first word of \"${ac_tool_prefix}ranlib\", so it can be a program name with args.\nset dummy ${ac_tool_prefix}ranlib; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_RANLIB+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$RANLIB\"; then\n  ac_cv_prog_RANLIB=\"$RANLIB\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_RANLIB=\"${ac_tool_prefix}ranlib\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nRANLIB=$ac_cv_prog_RANLIB\nif test -n \"$RANLIB\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $RANLIB\" >&5\n$as_echo \"$RANLIB\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\nfi\nif test -z \"$ac_cv_prog_RANLIB\"; then\n  ac_ct_RANLIB=$RANLIB\n  # Extract the first word of \"ranlib\", so it can be a program name with args.\nset dummy ranlib; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_ac_ct_RANLIB+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$ac_ct_RANLIB\"; then\n  ac_cv_prog_ac_ct_RANLIB=\"$ac_ct_RANLIB\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_ac_ct_RANLIB=\"ranlib\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB\nif test -n \"$ac_ct_RANLIB\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB\" >&5\n$as_echo \"$ac_ct_RANLIB\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n  if test \"x$ac_ct_RANLIB\" = x; then\n    RANLIB=\":\"\n  else\n    case $cross_compiling:$ac_tool_warned in\nyes:)\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet\" >&5\n$as_echo \"$as_me: WARNING: using cross tools not prefixed with host triplet\" >&2;}\nac_tool_warned=yes ;;\nesac\n    RANLIB=$ac_ct_RANLIB\n  fi\nelse\n  RANLIB=\"$ac_cv_prog_RANLIB\"\nfi\n\n\nfor ac_prog in gawk mawk nawk awk\ndo\n  # Extract the first word of \"$ac_prog\", so it can be a program name with args.\nset dummy $ac_prog; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_AWK+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$AWK\"; then\n  ac_cv_prog_AWK=\"$AWK\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_AWK=\"$ac_prog\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nAWK=$ac_cv_prog_AWK\nif test -n \"$AWK\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $AWK\" >&5\n$as_echo \"$AWK\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\n  test -n \"$AWK\" && break\ndone\n\ncase \"$AWK\" in\n\"\") as_fn_error $? \"can't build without awk\" \"$LINENO\" 5 ;;\nesac\n\n# Extract the first word of \"dwz\", so it can be a program name with args.\nset dummy dwz; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_DWZ+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$DWZ\"; then\n  ac_cv_prog_DWZ=\"$DWZ\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_DWZ=\"dwz\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nDWZ=$ac_cv_prog_DWZ\nif test -n \"$DWZ\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $DWZ\" >&5\n$as_echo \"$DWZ\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\n if test \"$DWZ\" != \"\"; then\n  HAVE_DWZ_TRUE=\n  HAVE_DWZ_FALSE='#'\nelse\n  HAVE_DWZ_TRUE='#'\n  HAVE_DWZ_FALSE=\nfi\n\n\ncase `pwd` in\n  *\\ * | *\\\t*)\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \\`pwd\\`\" >&5\n$as_echo \"$as_me: WARNING: Libtool does not cope well with whitespace in \\`pwd\\`\" >&2;} ;;\nesac\n\n\n\nmacro_version='2.2.7a'\nmacro_revision='1.3134'\n\n\n\n\n\n\n\n\n\n\n\n\n\nltmain=\"$ac_aux_dir/ltmain.sh\"\n\n# Backslashify metacharacters that are still active within\n# double-quoted strings.\nsed_quote_subst='s/\\([\"`$\\\\]\\)/\\\\\\1/g'\n\n# Same as above, but do not quote variable references.\ndouble_quote_subst='s/\\([\"`\\\\]\\)/\\\\\\1/g'\n\n# Sed substitution to delay expansion of an escaped shell variable in a\n# double_quote_subst'ed string.\ndelay_variable_subst='s/\\\\\\\\\\\\\\\\\\\\\\$/\\\\\\\\\\\\$/g'\n\n# Sed substitution to delay expansion of an escaped single quote.\ndelay_single_quote_subst='s/'\\''/'\\'\\\\\\\\\\\\\\'\\''/g'\n\n# Sed substitution to avoid accidental globbing in evaled expressions\nno_glob_subst='s/\\*/\\\\\\*/g'\n\nECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'\nECHO=$ECHO$ECHO$ECHO$ECHO$ECHO\nECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking how to print strings\" >&5\n$as_echo_n \"checking how to print strings... \" >&6; }\n# Test print first, because it will be a builtin if present.\nif test \"X`print -r -- -n 2>/dev/null`\" = X-n && \\\n   test \"X`print -r -- $ECHO 2>/dev/null`\" = \"X$ECHO\"; then\n  ECHO='print -r --'\nelif test \"X`printf %s $ECHO 2>/dev/null`\" = \"X$ECHO\"; then\n  ECHO='printf %s\\n'\nelse\n  # Use this function as a fallback that always works.\n  func_fallback_echo ()\n  {\n    eval 'cat <<_LTECHO_EOF\n$1\n_LTECHO_EOF'\n  }\n  ECHO='func_fallback_echo'\nfi\n\n# func_echo_all arg...\n# Invoke $ECHO with all args, space-separated.\nfunc_echo_all ()\n{\n    $ECHO \"\"\n}\n\ncase \"$ECHO\" in\n  printf*) { $as_echo \"$as_me:${as_lineno-$LINENO}: result: printf\" >&5\n$as_echo \"printf\" >&6; } ;;\n  print*) { $as_echo \"$as_me:${as_lineno-$LINENO}: result: print -r\" >&5\n$as_echo \"print -r\" >&6; } ;;\n  *) { $as_echo \"$as_me:${as_lineno-$LINENO}: result: cat\" >&5\n$as_echo \"cat\" >&6; } ;;\nesac\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output\" >&5\n$as_echo_n \"checking for a sed that does not truncate output... \" >&6; }\nif ${ac_cv_path_SED+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n            ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/\n     for ac_i in 1 2 3 4 5 6 7; do\n       ac_script=\"$ac_script$as_nl$ac_script\"\n     done\n     echo \"$ac_script\" 2>/dev/null | sed 99q >conftest.sed\n     { ac_script=; unset ac_script;}\n     if test -z \"$SED\"; then\n  ac_path_SED_found=false\n  # Loop through the user's path and test for each of PROGNAME-LIST\n  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_prog in sed gsed; do\n    for ac_exec_ext in '' $ac_executable_extensions; do\n      ac_path_SED=\"$as_dir/$ac_prog$ac_exec_ext\"\n      as_fn_executable_p \"$ac_path_SED\" || continue\n# Check for GNU ac_path_SED and select it if it is found.\n  # Check for GNU $ac_path_SED\ncase `\"$ac_path_SED\" --version 2>&1` in\n*GNU*)\n  ac_cv_path_SED=\"$ac_path_SED\" ac_path_SED_found=:;;\n*)\n  ac_count=0\n  $as_echo_n 0123456789 >\"conftest.in\"\n  while :\n  do\n    cat \"conftest.in\" \"conftest.in\" >\"conftest.tmp\"\n    mv \"conftest.tmp\" \"conftest.in\"\n    cp \"conftest.in\" \"conftest.nl\"\n    $as_echo '' >> \"conftest.nl\"\n    \"$ac_path_SED\" -f conftest.sed < \"conftest.nl\" >\"conftest.out\" 2>/dev/null || break\n    diff \"conftest.out\" \"conftest.nl\" >/dev/null 2>&1 || break\n    as_fn_arith $ac_count + 1 && ac_count=$as_val\n    if test $ac_count -gt ${ac_path_SED_max-0}; then\n      # Best one so far, save it but keep looking for a better one\n      ac_cv_path_SED=\"$ac_path_SED\"\n      ac_path_SED_max=$ac_count\n    fi\n    # 10*(2^10) chars as input seems more than enough\n    test $ac_count -gt 10 && break\n  done\n  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;\nesac\n\n      $ac_path_SED_found && break 3\n    done\n  done\n  done\nIFS=$as_save_IFS\n  if test -z \"$ac_cv_path_SED\"; then\n    as_fn_error $? \"no acceptable sed could be found in \\$PATH\" \"$LINENO\" 5\n  fi\nelse\n  ac_cv_path_SED=$SED\nfi\n\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED\" >&5\n$as_echo \"$ac_cv_path_SED\" >&6; }\n SED=\"$ac_cv_path_SED\"\n  rm -f conftest.sed\n\ntest -z \"$SED\" && SED=sed\nXsed=\"$SED -e 1s/^X//\"\n\n\n\n\n\n\n\n\n\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for fgrep\" >&5\n$as_echo_n \"checking for fgrep... \" >&6; }\nif ${ac_cv_path_FGREP+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1\n   then ac_cv_path_FGREP=\"$GREP -F\"\n   else\n     if test -z \"$FGREP\"; then\n  ac_path_FGREP_found=false\n  # Loop through the user's path and test for each of PROGNAME-LIST\n  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_prog in fgrep; do\n    for ac_exec_ext in '' $ac_executable_extensions; do\n      ac_path_FGREP=\"$as_dir/$ac_prog$ac_exec_ext\"\n      as_fn_executable_p \"$ac_path_FGREP\" || continue\n# Check for GNU ac_path_FGREP and select it if it is found.\n  # Check for GNU $ac_path_FGREP\ncase `\"$ac_path_FGREP\" --version 2>&1` in\n*GNU*)\n  ac_cv_path_FGREP=\"$ac_path_FGREP\" ac_path_FGREP_found=:;;\n*)\n  ac_count=0\n  $as_echo_n 0123456789 >\"conftest.in\"\n  while :\n  do\n    cat \"conftest.in\" \"conftest.in\" >\"conftest.tmp\"\n    mv \"conftest.tmp\" \"conftest.in\"\n    cp \"conftest.in\" \"conftest.nl\"\n    $as_echo 'FGREP' >> \"conftest.nl\"\n    \"$ac_path_FGREP\" FGREP < \"conftest.nl\" >\"conftest.out\" 2>/dev/null || break\n    diff \"conftest.out\" \"conftest.nl\" >/dev/null 2>&1 || break\n    as_fn_arith $ac_count + 1 && ac_count=$as_val\n    if test $ac_count -gt ${ac_path_FGREP_max-0}; then\n      # Best one so far, save it but keep looking for a better one\n      ac_cv_path_FGREP=\"$ac_path_FGREP\"\n      ac_path_FGREP_max=$ac_count\n    fi\n    # 10*(2^10) chars as input seems more than enough\n    test $ac_count -gt 10 && break\n  done\n  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;\nesac\n\n      $ac_path_FGREP_found && break 3\n    done\n  done\n  done\nIFS=$as_save_IFS\n  if test -z \"$ac_cv_path_FGREP\"; then\n    as_fn_error $? \"no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin\" \"$LINENO\" 5\n  fi\nelse\n  ac_cv_path_FGREP=$FGREP\nfi\n\n   fi\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP\" >&5\n$as_echo \"$ac_cv_path_FGREP\" >&6; }\n FGREP=\"$ac_cv_path_FGREP\"\n\n\ntest -z \"$GREP\" && GREP=grep\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n# Check whether --with-gnu-ld was given.\nif test \"${with_gnu_ld+set}\" = set; then :\n  withval=$with_gnu_ld; test \"$withval\" = no || with_gnu_ld=yes\nelse\n  with_gnu_ld=no\nfi\n\nac_prog=ld\nif test \"$GCC\" = yes; then\n  # Check if gcc -print-prog-name=ld gives a path.\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for ld used by $CC\" >&5\n$as_echo_n \"checking for ld used by $CC... \" >&6; }\n  case $host in\n  *-*-mingw*)\n    # gcc leaves a trailing carriage return which upsets mingw\n    ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\\015'` ;;\n  *)\n    ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;\n  esac\n  case $ac_prog in\n    # Accept absolute paths.\n    [\\\\/]* | ?:[\\\\/]*)\n      re_direlt='/[^/][^/]*/\\.\\./'\n      # Canonicalize the pathname of ld\n      ac_prog=`$ECHO \"$ac_prog\"| $SED 's%\\\\\\\\%/%g'`\n      while $ECHO \"$ac_prog\" | $GREP \"$re_direlt\" > /dev/null 2>&1; do\n\tac_prog=`$ECHO $ac_prog| $SED \"s%$re_direlt%/%\"`\n      done\n      test -z \"$LD\" && LD=\"$ac_prog\"\n      ;;\n  \"\")\n    # If it fails, then pretend we aren't using GCC.\n    ac_prog=ld\n    ;;\n  *)\n    # If it is relative, then search for the first ld in PATH.\n    with_gnu_ld=unknown\n    ;;\n  esac\nelif test \"$with_gnu_ld\" = yes; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for GNU ld\" >&5\n$as_echo_n \"checking for GNU ld... \" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for non-GNU ld\" >&5\n$as_echo_n \"checking for non-GNU ld... \" >&6; }\nfi\nif ${lt_cv_path_LD+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -z \"$LD\"; then\n  lt_save_ifs=\"$IFS\"; IFS=$PATH_SEPARATOR\n  for ac_dir in $PATH; do\n    IFS=\"$lt_save_ifs\"\n    test -z \"$ac_dir\" && ac_dir=.\n    if test -f \"$ac_dir/$ac_prog\" || test -f \"$ac_dir/$ac_prog$ac_exeext\"; then\n      lt_cv_path_LD=\"$ac_dir/$ac_prog\"\n      # Check to see if the program is GNU ld.  I'd rather use --version,\n      # but apparently some variants of GNU ld only accept -v.\n      # Break only if it was the GNU/non-GNU ld that we prefer.\n      case `\"$lt_cv_path_LD\" -v 2>&1 </dev/null` in\n      *GNU* | *'with BFD'*)\n\ttest \"$with_gnu_ld\" != no && break\n\t;;\n      *)\n\ttest \"$with_gnu_ld\" != yes && break\n\t;;\n      esac\n    fi\n  done\n  IFS=\"$lt_save_ifs\"\nelse\n  lt_cv_path_LD=\"$LD\" # Let the user override the test with a path.\nfi\nfi\n\nLD=\"$lt_cv_path_LD\"\nif test -n \"$LD\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $LD\" >&5\n$as_echo \"$LD\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\ntest -z \"$LD\" && as_fn_error $? \"no acceptable ld found in \\$PATH\" \"$LINENO\" 5\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld\" >&5\n$as_echo_n \"checking if the linker ($LD) is GNU ld... \" >&6; }\nif ${lt_cv_prog_gnu_ld+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  # I'd rather use --version here, but apparently some GNU lds only accept -v.\ncase `$LD -v 2>&1 </dev/null` in\n*GNU* | *'with BFD'*)\n  lt_cv_prog_gnu_ld=yes\n  ;;\n*)\n  lt_cv_prog_gnu_ld=no\n  ;;\nesac\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_gnu_ld\" >&5\n$as_echo \"$lt_cv_prog_gnu_ld\" >&6; }\nwith_gnu_ld=$lt_cv_prog_gnu_ld\n\n\n\n\n\n\n\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)\" >&5\n$as_echo_n \"checking for BSD- or MS-compatible name lister (nm)... \" >&6; }\nif ${lt_cv_path_NM+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$NM\"; then\n   # Let the user override the nm to test.\n   lt_nm_to_check=\"$NM\"\n else\n   lt_nm_to_check=\"${ac_tool_prefix}nm\"\n   if test -n \"$ac_tool_prefix\" && test \"$build\" = \"$host\"; then\n     lt_nm_to_check=\"$lt_nm_to_check nm\"\n   fi\n fi\n for lt_tmp_nm in \"$lt_nm_to_check\"; do\n   lt_save_ifs=\"$IFS\"; IFS=$PATH_SEPARATOR\n   for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do\n     IFS=\"$lt_save_ifs\"\n     test -z \"$ac_dir\" && ac_dir=.\n     # Strip out any user-provided options from the nm to test twice,\n     # the first time to test to see if nm (rather than its options) has\n     # an explicit path, the second time to yield a file which can be\n     # nm'ed itself.\n     tmp_nm_path=\"`$ECHO \"$lt_tmp_nm\" | sed 's, -.*$,,'`\"\n     case \"$tmp_nm_path\" in\n     */*|*\\\\*) tmp_nm=\"$lt_tmp_nm\";;\n     *) tmp_nm=\"$ac_dir/$lt_tmp_nm\";;\n     esac\n     tmp_nm_to_nm=\"`$ECHO \"$tmp_nm\" | sed 's, -.*$,,'`\"\n     if test -f \"$tmp_nm_to_nm\" || test -f \"$tmp_nm_to_nm$ac_exeext\" ; then\n       # Check to see if the nm accepts a BSD-compat flag.\n       # Adding the `sed 1q' prevents false positives on HP-UX, which says:\n       #   nm: unknown option \"B\" ignored\n       case `\"$tmp_nm\" -B \"$tmp_nm_to_nm\" 2>&1 | grep -v '^ *$' | sed '1q'` in\n       *$tmp_nm*) lt_cv_path_NM=\"$tmp_nm -B\"\n\t break\n\t ;;\n       *)\n\t case `\"$tmp_nm\" -p \"$tmp_nm_to_nm\" 2>&1 | grep -v '^ *$' | sed '1q'` in\n\t *$tmp_nm*)\n\t   lt_cv_path_NM=\"$tmp_nm -p\"\n\t   break\n\t   ;;\n\t *)\n\t   lt_cv_path_NM=${lt_cv_path_NM=\"$tmp_nm\"} # keep the first match, but\n\t   continue # so that we can try to find one that supports BSD flags\n\t   ;;\n\t esac\n\t ;;\n       esac\n     fi\n   done\n   IFS=\"$lt_save_ifs\"\n done\n : ${lt_cv_path_NM=no}\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM\" >&5\n$as_echo \"$lt_cv_path_NM\" >&6; }\nif test \"$lt_cv_path_NM\" != \"no\"; then\n  NM=\"$lt_cv_path_NM\"\nelse\n  # Didn't find any BSD compatible name lister, look for dumpbin.\n  if test -n \"$DUMPBIN\"; then :\n    # Let the user override the test.\n  else\n    if test -n \"$ac_tool_prefix\"; then\n  for ac_prog in dumpbin \"link -dump\"\n  do\n    # Extract the first word of \"$ac_tool_prefix$ac_prog\", so it can be a program name with args.\nset dummy $ac_tool_prefix$ac_prog; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_DUMPBIN+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$DUMPBIN\"; then\n  ac_cv_prog_DUMPBIN=\"$DUMPBIN\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_DUMPBIN=\"$ac_tool_prefix$ac_prog\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nDUMPBIN=$ac_cv_prog_DUMPBIN\nif test -n \"$DUMPBIN\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $DUMPBIN\" >&5\n$as_echo \"$DUMPBIN\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\n    test -n \"$DUMPBIN\" && break\n  done\nfi\nif test -z \"$DUMPBIN\"; then\n  ac_ct_DUMPBIN=$DUMPBIN\n  for ac_prog in dumpbin \"link -dump\"\ndo\n  # Extract the first word of \"$ac_prog\", so it can be a program name with args.\nset dummy $ac_prog; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$ac_ct_DUMPBIN\"; then\n  ac_cv_prog_ac_ct_DUMPBIN=\"$ac_ct_DUMPBIN\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_ac_ct_DUMPBIN=\"$ac_prog\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN\nif test -n \"$ac_ct_DUMPBIN\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN\" >&5\n$as_echo \"$ac_ct_DUMPBIN\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\n  test -n \"$ac_ct_DUMPBIN\" && break\ndone\n\n  if test \"x$ac_ct_DUMPBIN\" = x; then\n    DUMPBIN=\":\"\n  else\n    case $cross_compiling:$ac_tool_warned in\nyes:)\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet\" >&5\n$as_echo \"$as_me: WARNING: using cross tools not prefixed with host triplet\" >&2;}\nac_tool_warned=yes ;;\nesac\n    DUMPBIN=$ac_ct_DUMPBIN\n  fi\nfi\n\n    case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in\n    *COFF*)\n      DUMPBIN=\"$DUMPBIN -symbols\"\n      ;;\n    *)\n      DUMPBIN=:\n      ;;\n    esac\n  fi\n\n  if test \"$DUMPBIN\" != \":\"; then\n    NM=\"$DUMPBIN\"\n  fi\nfi\ntest -z \"$NM\" && NM=nm\n\n\n\n\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface\" >&5\n$as_echo_n \"checking the name lister ($NM) interface... \" >&6; }\nif ${lt_cv_nm_interface+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  lt_cv_nm_interface=\"BSD nm\"\n  echo \"int some_variable = 0;\" > conftest.$ac_ext\n  (eval echo \"\\\"\\$as_me:$LINENO: $ac_compile\\\"\" >&5)\n  (eval \"$ac_compile\" 2>conftest.err)\n  cat conftest.err >&5\n  (eval echo \"\\\"\\$as_me:$LINENO: $NM \\\\\\\"conftest.$ac_objext\\\\\\\"\\\"\" >&5)\n  (eval \"$NM \\\"conftest.$ac_objext\\\"\" 2>conftest.err > conftest.out)\n  cat conftest.err >&5\n  (eval echo \"\\\"\\$as_me:$LINENO: output\\\"\" >&5)\n  cat conftest.out >&5\n  if $GREP 'External.*some_variable' conftest.out > /dev/null; then\n    lt_cv_nm_interface=\"MS dumpbin\"\n  fi\n  rm -f conftest*\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface\" >&5\n$as_echo \"$lt_cv_nm_interface\" >&6; }\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether ln -s works\" >&5\n$as_echo_n \"checking whether ln -s works... \" >&6; }\nLN_S=$as_ln_s\nif test \"$LN_S\" = \"ln -s\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\n$as_echo \"yes\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no, using $LN_S\" >&5\n$as_echo \"no, using $LN_S\" >&6; }\nfi\n\n# find the maximum length of command line arguments\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments\" >&5\n$as_echo_n \"checking the maximum length of command line arguments... \" >&6; }\nif ${lt_cv_sys_max_cmd_len+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n    i=0\n  teststring=\"ABCD\"\n\n  case $build_os in\n  msdosdjgpp*)\n    # On DJGPP, this test can blow up pretty badly due to problems in libc\n    # (any single argument exceeding 2000 bytes causes a buffer overrun\n    # during glob expansion).  Even if it were fixed, the result of this\n    # check would be larger than it should be.\n    lt_cv_sys_max_cmd_len=12288;    # 12K is about right\n    ;;\n\n  gnu*)\n    # Under GNU Hurd, this test is not required because there is\n    # no limit to the length of command line arguments.\n    # Libtool will interpret -1 as no limit whatsoever\n    lt_cv_sys_max_cmd_len=-1;\n    ;;\n\n  cygwin* | mingw* | cegcc*)\n    # On Win9x/ME, this test blows up -- it succeeds, but takes\n    # about 5 minutes as the teststring grows exponentially.\n    # Worse, since 9x/ME are not pre-emptively multitasking,\n    # you end up with a \"frozen\" computer, even though with patience\n    # the test eventually succeeds (with a max line length of 256k).\n    # Instead, let's just punt: use the minimum linelength reported by\n    # all of the supported platforms: 8192 (on NT/2K/XP).\n    lt_cv_sys_max_cmd_len=8192;\n    ;;\n\n  mint*)\n    # On MiNT this can take a long time and run out of memory.\n    lt_cv_sys_max_cmd_len=8192;\n    ;;\n\n  amigaos*)\n    # On AmigaOS with pdksh, this test takes hours, literally.\n    # So we just punt and use a minimum line length of 8192.\n    lt_cv_sys_max_cmd_len=8192;\n    ;;\n\n  netbsd* | freebsd* | openbsd* | darwin* | dragonfly*)\n    # This has been around since 386BSD, at least.  Likely further.\n    if test -x /sbin/sysctl; then\n      lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`\n    elif test -x /usr/sbin/sysctl; then\n      lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`\n    else\n      lt_cv_sys_max_cmd_len=65536\t# usable default for all BSDs\n    fi\n    # And add a safety zone\n    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \\/ 4`\n    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \\* 3`\n    ;;\n\n  interix*)\n    # We know the value 262144 and hardcode it with a safety zone (like BSD)\n    lt_cv_sys_max_cmd_len=196608\n    ;;\n\n  osf*)\n    # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure\n    # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not\n    # nice to cause kernel panics so lets avoid the loop below.\n    # First set a reasonable default.\n    lt_cv_sys_max_cmd_len=16384\n    #\n    if test -x /sbin/sysconfig; then\n      case `/sbin/sysconfig -q proc exec_disable_arg_limit` in\n        *1*) lt_cv_sys_max_cmd_len=-1 ;;\n      esac\n    fi\n    ;;\n  sco3.2v5*)\n    lt_cv_sys_max_cmd_len=102400\n    ;;\n  sysv5* | sco5v6* | sysv4.2uw2*)\n    kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`\n    if test -n \"$kargmax\"; then\n      lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[\t ]//'`\n    else\n      lt_cv_sys_max_cmd_len=32768\n    fi\n    ;;\n  *)\n    lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null`\n    if test -n \"$lt_cv_sys_max_cmd_len\"; then\n      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \\/ 4`\n      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \\* 3`\n    else\n      # Make teststring a little bigger before we do anything with it.\n      # a 1K string should be a reasonable start.\n      for i in 1 2 3 4 5 6 7 8 ; do\n        teststring=$teststring$teststring\n      done\n      SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}\n      # If test is not a shell built-in, we'll probably end up computing a\n      # maximum length that is only half of the actual maximum length, but\n      # we can't tell.\n      while { test \"X\"`func_fallback_echo \"$teststring$teststring\" 2>/dev/null` \\\n\t         = \"X$teststring$teststring\"; } >/dev/null 2>&1 &&\n\t      test $i != 17 # 1/2 MB should be enough\n      do\n        i=`expr $i + 1`\n        teststring=$teststring$teststring\n      done\n      # Only check the string length outside the loop.\n      lt_cv_sys_max_cmd_len=`expr \"X$teststring\" : \".*\" 2>&1`\n      teststring=\n      # Add a significant safety factor because C++ compilers can tack on\n      # massive amounts of additional arguments before passing them to the\n      # linker.  It appears as though 1/2 is a usable value.\n      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \\/ 2`\n    fi\n    ;;\n  esac\n\nfi\n\nif test -n $lt_cv_sys_max_cmd_len ; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len\" >&5\n$as_echo \"$lt_cv_sys_max_cmd_len\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: none\" >&5\n$as_echo \"none\" >&6; }\nfi\nmax_cmd_len=$lt_cv_sys_max_cmd_len\n\n\n\n\n\n\n: ${CP=\"cp -f\"}\n: ${MV=\"mv -f\"}\n: ${RM=\"rm -f\"}\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether the shell understands some XSI constructs\" >&5\n$as_echo_n \"checking whether the shell understands some XSI constructs... \" >&6; }\n# Try some XSI features\nxsi_shell=no\n( _lt_dummy=\"a/b/c\"\n  test \"${_lt_dummy##*/},${_lt_dummy%/*},\"${_lt_dummy%\"$_lt_dummy\"}, \\\n      = c,a/b,, \\\n    && eval 'test $(( 1 + 1 )) -eq 2 \\\n    && test \"${#_lt_dummy}\" -eq 5' ) >/dev/null 2>&1 \\\n  && xsi_shell=yes\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $xsi_shell\" >&5\n$as_echo \"$xsi_shell\" >&6; }\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether the shell understands \\\"+=\\\"\" >&5\n$as_echo_n \"checking whether the shell understands \\\"+=\\\"... \" >&6; }\nlt_shell_append=no\n( foo=bar; set foo baz; eval \"$1+=\\$2\" && test \"$foo\" = barbaz ) \\\n    >/dev/null 2>&1 \\\n  && lt_shell_append=yes\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $lt_shell_append\" >&5\n$as_echo \"$lt_shell_append\" >&6; }\n\n\nif ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then\n  lt_unset=unset\nelse\n  lt_unset=false\nfi\n\n\n\n\n\n# test EBCDIC or ASCII\ncase `echo X|tr X '\\101'` in\n A) # ASCII based system\n    # \\n is not interpreted correctly by Solaris 8 /usr/ucb/tr\n  lt_SP2NL='tr \\040 \\012'\n  lt_NL2SP='tr \\015\\012 \\040\\040'\n  ;;\n *) # EBCDIC based system\n  lt_SP2NL='tr \\100 \\n'\n  lt_NL2SP='tr \\r\\n \\100\\100'\n  ;;\nesac\n\n\n\n\n\n\n\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files\" >&5\n$as_echo_n \"checking for $LD option to reload object files... \" >&6; }\nif ${lt_cv_ld_reload_flag+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  lt_cv_ld_reload_flag='-r'\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag\" >&5\n$as_echo \"$lt_cv_ld_reload_flag\" >&6; }\nreload_flag=$lt_cv_ld_reload_flag\ncase $reload_flag in\n\"\" | \" \"*) ;;\n*) reload_flag=\" $reload_flag\" ;;\nesac\nreload_cmds='$LD$reload_flag -o $output$reload_objs'\ncase $host_os in\n  darwin*)\n    if test \"$GCC\" = yes; then\n      reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs'\n    else\n      reload_cmds='$LD$reload_flag -o $output$reload_objs'\n    fi\n    ;;\nesac\n\n\n\n\n\n\n\n\n\nif test -n \"$ac_tool_prefix\"; then\n  # Extract the first word of \"${ac_tool_prefix}objdump\", so it can be a program name with args.\nset dummy ${ac_tool_prefix}objdump; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_OBJDUMP+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$OBJDUMP\"; then\n  ac_cv_prog_OBJDUMP=\"$OBJDUMP\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_OBJDUMP=\"${ac_tool_prefix}objdump\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nOBJDUMP=$ac_cv_prog_OBJDUMP\nif test -n \"$OBJDUMP\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $OBJDUMP\" >&5\n$as_echo \"$OBJDUMP\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\nfi\nif test -z \"$ac_cv_prog_OBJDUMP\"; then\n  ac_ct_OBJDUMP=$OBJDUMP\n  # Extract the first word of \"objdump\", so it can be a program name with args.\nset dummy objdump; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$ac_ct_OBJDUMP\"; then\n  ac_cv_prog_ac_ct_OBJDUMP=\"$ac_ct_OBJDUMP\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_ac_ct_OBJDUMP=\"objdump\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP\nif test -n \"$ac_ct_OBJDUMP\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP\" >&5\n$as_echo \"$ac_ct_OBJDUMP\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n  if test \"x$ac_ct_OBJDUMP\" = x; then\n    OBJDUMP=\"false\"\n  else\n    case $cross_compiling:$ac_tool_warned in\nyes:)\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet\" >&5\n$as_echo \"$as_me: WARNING: using cross tools not prefixed with host triplet\" >&2;}\nac_tool_warned=yes ;;\nesac\n    OBJDUMP=$ac_ct_OBJDUMP\n  fi\nelse\n  OBJDUMP=\"$ac_cv_prog_OBJDUMP\"\nfi\n\ntest -z \"$OBJDUMP\" && OBJDUMP=objdump\n\n\n\n\n\n\n\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries\" >&5\n$as_echo_n \"checking how to recognize dependent libraries... \" >&6; }\nif ${lt_cv_deplibs_check_method+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  lt_cv_file_magic_cmd='$MAGIC_CMD'\nlt_cv_file_magic_test_file=\nlt_cv_deplibs_check_method='unknown'\n# Need to set the preceding variable on all platforms that support\n# interlibrary dependencies.\n# 'none' -- dependencies not supported.\n# `unknown' -- same as none, but documents that we really don't know.\n# 'pass_all' -- all dependencies passed with no checks.\n# 'test_compile' -- check by making test program.\n# 'file_magic [[regex]]' -- check by looking for files in library path\n# which responds to the $file_magic_cmd with a given extended regex.\n# If you have `file' or equivalent on your system and you're not sure\n# whether `pass_all' will *always* work, you probably want this one.\n\ncase $host_os in\naix[4-9]*)\n  lt_cv_deplibs_check_method=pass_all\n  ;;\n\nbeos*)\n  lt_cv_deplibs_check_method=pass_all\n  ;;\n\nbsdi[45]*)\n  lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)'\n  lt_cv_file_magic_cmd='/usr/bin/file -L'\n  lt_cv_file_magic_test_file=/shlib/libc.so\n  ;;\n\ncygwin*)\n  # func_win32_libid is a shell function defined in ltmain.sh\n  lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'\n  lt_cv_file_magic_cmd='func_win32_libid'\n  ;;\n\nmingw* | pw32*)\n  # Base MSYS/MinGW do not provide the 'file' command needed by\n  # func_win32_libid shell function, so use a weaker test based on 'objdump',\n  # unless we find 'file', for example because we are cross-compiling.\n  # func_win32_libid assumes BSD nm, so disallow it if using MS dumpbin.\n  if ( test \"$lt_cv_nm_interface\" = \"BSD nm\" && file / ) >/dev/null 2>&1; then\n    lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'\n    lt_cv_file_magic_cmd='func_win32_libid'\n  else\n    lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'\n    lt_cv_file_magic_cmd='$OBJDUMP -f'\n  fi\n  ;;\n\ncegcc*)\n  # use the weaker test based on 'objdump'. See mingw*.\n  lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?'\n  lt_cv_file_magic_cmd='$OBJDUMP -f'\n  ;;\n\ndarwin* | rhapsody*)\n  lt_cv_deplibs_check_method=pass_all\n  ;;\n\nfreebsd* | dragonfly*)\n  if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then\n    case $host_cpu in\n    i*86 )\n      # Not sure whether the presence of OpenBSD here was a mistake.\n      # Let's accept both of them until this is cleared up.\n      lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library'\n      lt_cv_file_magic_cmd=/usr/bin/file\n      lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`\n      ;;\n    esac\n  else\n    lt_cv_deplibs_check_method=pass_all\n  fi\n  ;;\n\ngnu*)\n  lt_cv_deplibs_check_method=pass_all\n  ;;\n\nhaiku*)\n  lt_cv_deplibs_check_method=pass_all\n  ;;\n\nhpux10.20* | hpux11*)\n  lt_cv_file_magic_cmd=/usr/bin/file\n  case $host_cpu in\n  ia64*)\n    lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64'\n    lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so\n    ;;\n  hppa*64*)\n    lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\\.[0-9]'\n    lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl\n    ;;\n  *)\n    lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\\.[0-9]) shared library'\n    lt_cv_file_magic_test_file=/usr/lib/libc.sl\n    ;;\n  esac\n  ;;\n\ninterix[3-9]*)\n  # PIC code is broken on Interix 3.x, that's why |\\.a not |_pic\\.a here\n  lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\\.so|\\.a)$'\n  ;;\n\nirix5* | irix6* | nonstopux*)\n  case $LD in\n  *-32|*\"-32 \") libmagic=32-bit;;\n  *-n32|*\"-n32 \") libmagic=N32;;\n  *-64|*\"-64 \") libmagic=64-bit;;\n  *) libmagic=never-match;;\n  esac\n  lt_cv_deplibs_check_method=pass_all\n  ;;\n\n# This must be Linux ELF.\nlinux* | k*bsd*-gnu | kopensolaris*-gnu | uclinuxfdpiceabi)\n  lt_cv_deplibs_check_method=pass_all\n  ;;\n\nnetbsd*)\n  if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then\n    lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\\.so\\.[0-9]+\\.[0-9]+|_pic\\.a)$'\n  else\n    lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\\.so|_pic\\.a)$'\n  fi\n  ;;\n\nnewos6*)\n  lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)'\n  lt_cv_file_magic_cmd=/usr/bin/file\n  lt_cv_file_magic_test_file=/usr/lib/libnls.so\n  ;;\n\n*nto* | *qnx*)\n  lt_cv_deplibs_check_method=pass_all\n  ;;\n\nopenbsd*)\n  if test -z \"`echo __ELF__ | $CC -E - | $GREP __ELF__`\" || test \"$host_os-$host_cpu\" = \"openbsd2.8-powerpc\"; then\n    lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\\.so\\.[0-9]+\\.[0-9]+|\\.so|_pic\\.a)$'\n  else\n    lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\\.so\\.[0-9]+\\.[0-9]+|_pic\\.a)$'\n  fi\n  ;;\n\nosf3* | osf4* | osf5*)\n  lt_cv_deplibs_check_method=pass_all\n  ;;\n\nrdos*)\n  lt_cv_deplibs_check_method=pass_all\n  ;;\n\nsolaris*)\n  lt_cv_deplibs_check_method=pass_all\n  ;;\n\nsysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)\n  lt_cv_deplibs_check_method=pass_all\n  ;;\n\nsysv4 | sysv4.3*)\n  case $host_vendor in\n  motorola)\n    lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]'\n    lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`\n    ;;\n  ncr)\n    lt_cv_deplibs_check_method=pass_all\n    ;;\n  sequent)\n    lt_cv_file_magic_cmd='/bin/file'\n    lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )'\n    ;;\n  sni)\n    lt_cv_file_magic_cmd='/bin/file'\n    lt_cv_deplibs_check_method=\"file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib\"\n    lt_cv_file_magic_test_file=/lib/libc.so\n    ;;\n  siemens)\n    lt_cv_deplibs_check_method=pass_all\n    ;;\n  pc)\n    lt_cv_deplibs_check_method=pass_all\n    ;;\n  esac\n  ;;\n\ntpf*)\n  lt_cv_deplibs_check_method=pass_all\n  ;;\nvxworks*)\n  # Assume VxWorks cross toolchains are built on Linux, possibly\n  # as canadian for Windows hosts.\n  lt_cv_deplibs_check_method=pass_all\n  ;;\nesac\n\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method\" >&5\n$as_echo \"$lt_cv_deplibs_check_method\" >&6; }\nfile_magic_cmd=$lt_cv_file_magic_cmd\ndeplibs_check_method=$lt_cv_deplibs_check_method\ntest -z \"$deplibs_check_method\" && deplibs_check_method=unknown\n\n\n\n\n\n\n\n\n\n\n\n\nplugin_option=\nplugin_names=\"liblto_plugin.so liblto_plugin-0.dll cyglto_plugin-0.dll\"\nfor plugin in $plugin_names; do\n  plugin_so=`${CC} ${CFLAGS} --print-prog-name $plugin`\n  if test x$plugin_so = x$plugin; then\n    plugin_so=`${CC} ${CFLAGS} --print-file-name $plugin`\n  fi\n  if test x$plugin_so != x$plugin; then\n    plugin_option=\"--plugin $plugin_so\"\n    break\n  fi\ndone\n\nif test -n \"$ac_tool_prefix\"; then\n  # Extract the first word of \"${ac_tool_prefix}ar\", so it can be a program name with args.\nset dummy ${ac_tool_prefix}ar; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_AR+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$AR\"; then\n  ac_cv_prog_AR=\"$AR\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_AR=\"${ac_tool_prefix}ar\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nAR=$ac_cv_prog_AR\nif test -n \"$AR\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $AR\" >&5\n$as_echo \"$AR\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\nfi\nif test -z \"$ac_cv_prog_AR\"; then\n  ac_ct_AR=$AR\n  # Extract the first word of \"ar\", so it can be a program name with args.\nset dummy ar; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_ac_ct_AR+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$ac_ct_AR\"; then\n  ac_cv_prog_ac_ct_AR=\"$ac_ct_AR\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_ac_ct_AR=\"ar\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nac_ct_AR=$ac_cv_prog_ac_ct_AR\nif test -n \"$ac_ct_AR\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR\" >&5\n$as_echo \"$ac_ct_AR\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n  if test \"x$ac_ct_AR\" = x; then\n    AR=\"false\"\n  else\n    case $cross_compiling:$ac_tool_warned in\nyes:)\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet\" >&5\n$as_echo \"$as_me: WARNING: using cross tools not prefixed with host triplet\" >&2;}\nac_tool_warned=yes ;;\nesac\n    AR=$ac_ct_AR\n  fi\nelse\n  AR=\"$ac_cv_prog_AR\"\nfi\n\ntest -z \"$AR\" && AR=ar\nif test -n \"$plugin_option\"; then\n  if $AR --help 2>&1 | grep -q \"\\--plugin\"; then\n    touch conftest.c\n    $AR $plugin_option rc conftest.a conftest.c\n    if test \"$?\" != 0; then\n      { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: Failed: $AR $plugin_option rc\" >&5\n$as_echo \"$as_me: WARNING: Failed: $AR $plugin_option rc\" >&2;}\n    else\n      AR=\"$AR $plugin_option\"\n    fi\n    rm -f conftest.*\n  fi\nfi\ntest -z \"$AR_FLAGS\" && AR_FLAGS=cru\n\n\n\n\n\n\n\n\n\n\n\nif test -n \"$ac_tool_prefix\"; then\n  # Extract the first word of \"${ac_tool_prefix}strip\", so it can be a program name with args.\nset dummy ${ac_tool_prefix}strip; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_STRIP+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$STRIP\"; then\n  ac_cv_prog_STRIP=\"$STRIP\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_STRIP=\"${ac_tool_prefix}strip\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nSTRIP=$ac_cv_prog_STRIP\nif test -n \"$STRIP\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $STRIP\" >&5\n$as_echo \"$STRIP\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\nfi\nif test -z \"$ac_cv_prog_STRIP\"; then\n  ac_ct_STRIP=$STRIP\n  # Extract the first word of \"strip\", so it can be a program name with args.\nset dummy strip; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_ac_ct_STRIP+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$ac_ct_STRIP\"; then\n  ac_cv_prog_ac_ct_STRIP=\"$ac_ct_STRIP\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_ac_ct_STRIP=\"strip\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP\nif test -n \"$ac_ct_STRIP\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP\" >&5\n$as_echo \"$ac_ct_STRIP\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n  if test \"x$ac_ct_STRIP\" = x; then\n    STRIP=\":\"\n  else\n    case $cross_compiling:$ac_tool_warned in\nyes:)\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet\" >&5\n$as_echo \"$as_me: WARNING: using cross tools not prefixed with host triplet\" >&2;}\nac_tool_warned=yes ;;\nesac\n    STRIP=$ac_ct_STRIP\n  fi\nelse\n  STRIP=\"$ac_cv_prog_STRIP\"\nfi\n\ntest -z \"$STRIP\" && STRIP=:\n\n\n\n\n\n\nif test -n \"$ac_tool_prefix\"; then\n  # Extract the first word of \"${ac_tool_prefix}ranlib\", so it can be a program name with args.\nset dummy ${ac_tool_prefix}ranlib; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_RANLIB+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$RANLIB\"; then\n  ac_cv_prog_RANLIB=\"$RANLIB\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_RANLIB=\"${ac_tool_prefix}ranlib\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nRANLIB=$ac_cv_prog_RANLIB\nif test -n \"$RANLIB\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $RANLIB\" >&5\n$as_echo \"$RANLIB\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\nfi\nif test -z \"$ac_cv_prog_RANLIB\"; then\n  ac_ct_RANLIB=$RANLIB\n  # Extract the first word of \"ranlib\", so it can be a program name with args.\nset dummy ranlib; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_ac_ct_RANLIB+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$ac_ct_RANLIB\"; then\n  ac_cv_prog_ac_ct_RANLIB=\"$ac_ct_RANLIB\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_ac_ct_RANLIB=\"ranlib\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB\nif test -n \"$ac_ct_RANLIB\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB\" >&5\n$as_echo \"$ac_ct_RANLIB\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n  if test \"x$ac_ct_RANLIB\" = x; then\n    RANLIB=\":\"\n  else\n    case $cross_compiling:$ac_tool_warned in\nyes:)\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet\" >&5\n$as_echo \"$as_me: WARNING: using cross tools not prefixed with host triplet\" >&2;}\nac_tool_warned=yes ;;\nesac\n    RANLIB=$ac_ct_RANLIB\n  fi\nelse\n  RANLIB=\"$ac_cv_prog_RANLIB\"\nfi\n\ntest -z \"$RANLIB\" && RANLIB=:\nif test -n \"$plugin_option\" && test \"$RANLIB\" != \":\"; then\n  if $RANLIB --help 2>&1 | grep -q \"\\--plugin\"; then\n    RANLIB=\"$RANLIB $plugin_option\"\n  fi\nfi\n\n\n\n\n\n\n# Determine commands to create old-style static archives.\nold_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs'\nold_postinstall_cmds='chmod 644 $oldlib'\nold_postuninstall_cmds=\n\nif test -n \"$RANLIB\"; then\n  case $host_os in\n  openbsd*)\n    old_postinstall_cmds=\"$old_postinstall_cmds~\\$RANLIB -t \\$oldlib\"\n    ;;\n  *)\n    old_postinstall_cmds=\"$old_postinstall_cmds~\\$RANLIB \\$oldlib\"\n    ;;\n  esac\n  old_archive_cmds=\"$old_archive_cmds~\\$RANLIB \\$oldlib\"\nfi\n\ncase $host_os in\n  darwin*)\n    lock_old_archive_extraction=yes ;;\n  *)\n    lock_old_archive_extraction=no ;;\nesac\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n# If no C compiler was specified, use CC.\nLTCC=${LTCC-\"$CC\"}\n\n# If no C compiler flags were specified, use CFLAGS.\nLTCFLAGS=${LTCFLAGS-\"$CFLAGS\"}\n\n# Allow CC to be a program name with arguments.\ncompiler=$CC\n\n\n# Check for command to grab the raw symbol name followed by C symbol from nm.\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object\" >&5\n$as_echo_n \"checking command to parse $NM output from $compiler object... \" >&6; }\nif ${lt_cv_sys_global_symbol_pipe+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n\n# These are sane defaults that work on at least a few old systems.\n# [They come from Ultrix.  What could be older than Ultrix?!! ;)]\n\n# Character class describing NM global symbol codes.\nsymcode='[BCDEGRST]'\n\n# Regexp to match symbols that can be accessed directly from C.\nsympat='\\([_A-Za-z][_A-Za-z0-9]*\\)'\n\n# Define system-specific variables.\ncase $host_os in\naix*)\n  symcode='[BCDT]'\n  ;;\ncygwin* | mingw* | pw32* | cegcc*)\n  symcode='[ABCDGISTW]'\n  ;;\nhpux*)\n  if test \"$host_cpu\" = ia64; then\n    symcode='[ABCDEGRST]'\n  fi\n  ;;\nirix* | nonstopux*)\n  symcode='[BCDEGRST]'\n  ;;\nosf*)\n  symcode='[BCDEGQRST]'\n  ;;\nsolaris*)\n  symcode='[BCDRT]'\n  ;;\nsco3.2v5*)\n  symcode='[DT]'\n  ;;\nsysv4.2uw2*)\n  symcode='[DT]'\n  ;;\nsysv5* | sco5v6* | unixware* | OpenUNIX*)\n  symcode='[ABDT]'\n  ;;\nsysv4)\n  symcode='[DFNSTU]'\n  ;;\nesac\n\n# If we're using GNU nm, then use its standard symbol codes.\ncase `$NM -V 2>&1` in\n*GNU* | *'with BFD'*)\n  symcode='[ABCDGIRSTW]' ;;\nesac\n\n# Transform an extracted symbol line into a proper C declaration.\n# Some systems (esp. on ia64) link data and code symbols differently,\n# so use this general approach.\nlt_cv_sys_global_symbol_to_cdecl=\"sed -n -e 's/^T .* \\(.*\\)$/extern int \\1();/p' -e 's/^$symcode* .* \\(.*\\)$/extern char \\1;/p'\"\n\n# Transform an extracted symbol line into symbol name and symbol address\nlt_cv_sys_global_symbol_to_c_name_address=\"sed -n -e 's/^: \\([^ ]*\\) $/  {\\\\\\\"\\1\\\\\\\", (void *) 0},/p' -e 's/^$symcode* \\([^ ]*\\) \\([^ ]*\\)$/  {\\\"\\2\\\", (void *) \\&\\2},/p'\"\nlt_cv_sys_global_symbol_to_c_name_address_lib_prefix=\"sed -n -e 's/^: \\([^ ]*\\) $/  {\\\\\\\"\\1\\\\\\\", (void *) 0},/p' -e 's/^$symcode* \\([^ ]*\\) \\(lib[^ ]*\\)$/  {\\\"\\2\\\", (void *) \\&\\2},/p' -e 's/^$symcode* \\([^ ]*\\) \\([^ ]*\\)$/  {\\\"lib\\2\\\", (void *) \\&\\2},/p'\"\n\n# Handle CRLF in mingw tool chain\nopt_cr=\ncase $build_os in\nmingw*)\n  opt_cr=`$ECHO 'x\\{0,1\\}' | tr x '\\015'` # option cr in regexp\n  ;;\nesac\n\n# Try without a prefix underscore, then with it.\nfor ac_symprfx in \"\" \"_\"; do\n\n  # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol.\n  symxfrm=\"\\\\1 $ac_symprfx\\\\2 \\\\2\"\n\n  # Write the raw and C identifiers.\n  if test \"$lt_cv_nm_interface\" = \"MS dumpbin\"; then\n    # Fake it for dumpbin and say T for any non-static function\n    # and D for any global variable.\n    # Also find C++ and __fastcall symbols from MSVC++,\n    # which start with @ or ?.\n    lt_cv_sys_global_symbol_pipe=\"$AWK '\"\\\n\"     {last_section=section; section=\\$ 3};\"\\\n\"     /Section length .*#relocs.*(pick any)/{hide[last_section]=1};\"\\\n\"     \\$ 0!~/External *\\|/{next};\"\\\n\"     / 0+ UNDEF /{next}; / UNDEF \\([^|]\\)*()/{next};\"\\\n\"     {if(hide[section]) next};\"\\\n\"     {f=0}; \\$ 0~/\\(\\).*\\|/{f=1}; {printf f ? \\\"T \\\" : \\\"D \\\"};\"\\\n\"     {split(\\$ 0, a, /\\||\\r/); split(a[2], s)};\"\\\n\"     s[1]~/^[@?]/{print s[1], s[1]; next};\"\\\n\"     s[1]~prfx {split(s[1],t,\\\"@\\\"); print t[1], substr(t[1],length(prfx))}\"\\\n\"     ' prfx=^$ac_symprfx\"\n  else\n    lt_cv_sys_global_symbol_pipe=\"sed -n -e 's/^.*[\t ]\\($symcode$symcode*\\)[\t ][\t ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'\"\n  fi\n\n  # Check to see that the pipe works correctly.\n  pipe_works=no\n\n  rm -f conftest*\n  cat > conftest.$ac_ext <<_LT_EOF\n#ifdef __cplusplus\nextern \"C\" {\n#endif\nchar nm_test_var;\nvoid nm_test_func(void);\nvoid nm_test_func(void){}\n#ifdef __cplusplus\n}\n#endif\nint main(){nm_test_var='a';nm_test_func();return(0);}\n_LT_EOF\n\n  if { { eval echo \"\\\"\\$as_me\\\":${as_lineno-$LINENO}: \\\"$ac_compile\\\"\"; } >&5\n  (eval $ac_compile) 2>&5\n  ac_status=$?\n  $as_echo \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; }; then\n    # Now try to grab the symbols.\n    nlist=conftest.nm\n    if { { eval echo \"\\\"\\$as_me\\\":${as_lineno-$LINENO}: \\\"$NM conftest.$ac_objext \\| \"$lt_cv_sys_global_symbol_pipe\" \\> $nlist\\\"\"; } >&5\n  (eval $NM conftest.$ac_objext \\| \"$lt_cv_sys_global_symbol_pipe\" \\> $nlist) 2>&5\n  ac_status=$?\n  $as_echo \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; } && test -s \"$nlist\"; then\n      # Try sorting and uniquifying the output.\n      if sort \"$nlist\" | uniq > \"$nlist\"T; then\n\tmv -f \"$nlist\"T \"$nlist\"\n      else\n\trm -f \"$nlist\"T\n      fi\n\n      # Make sure that we snagged all the symbols we need.\n      if $GREP ' nm_test_var$' \"$nlist\" >/dev/null; then\n\tif $GREP ' nm_test_func$' \"$nlist\" >/dev/null; then\n\t  cat <<_LT_EOF > conftest.$ac_ext\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n_LT_EOF\n\t  # Now generate the symbol file.\n\t  eval \"$lt_cv_sys_global_symbol_to_cdecl\"' < \"$nlist\" | $GREP -v main >> conftest.$ac_ext'\n\n\t  cat <<_LT_EOF >> conftest.$ac_ext\n\n/* The mapping between symbol names and symbols.  */\nconst struct {\n  const char *name;\n  void       *address;\n}\nlt__PROGRAM__LTX_preloaded_symbols[] =\n{\n  { \"@PROGRAM@\", (void *) 0 },\n_LT_EOF\n\t  $SED \"s/^$symcode$symcode* \\(.*\\) \\(.*\\)$/  {\\\"\\2\\\", (void *) \\&\\2},/\" < \"$nlist\" | $GREP -v main >> conftest.$ac_ext\n\t  cat <<\\_LT_EOF >> conftest.$ac_ext\n  {0, (void *) 0}\n};\n\n/* This works around a problem in FreeBSD linker */\n#ifdef FREEBSD_WORKAROUND\nstatic const void *lt_preloaded_setup() {\n  return lt__PROGRAM__LTX_preloaded_symbols;\n}\n#endif\n\n#ifdef __cplusplus\n}\n#endif\n_LT_EOF\n\t  # Now try linking the two files.\n\t  mv conftest.$ac_objext conftstm.$ac_objext\n\t  lt_save_LIBS=\"$LIBS\"\n\t  lt_save_CFLAGS=\"$CFLAGS\"\n\t  LIBS=\"conftstm.$ac_objext\"\n\t  CFLAGS=\"$CFLAGS$lt_prog_compiler_no_builtin_flag\"\n\t  if { { eval echo \"\\\"\\$as_me\\\":${as_lineno-$LINENO}: \\\"$ac_link\\\"\"; } >&5\n  (eval $ac_link) 2>&5\n  ac_status=$?\n  $as_echo \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; } && test -s conftest${ac_exeext}; then\n\t    pipe_works=yes\n\t  fi\n\t  LIBS=\"$lt_save_LIBS\"\n\t  CFLAGS=\"$lt_save_CFLAGS\"\n\telse\n\t  echo \"cannot find nm_test_func in $nlist\" >&5\n\tfi\n      else\n\techo \"cannot find nm_test_var in $nlist\" >&5\n      fi\n    else\n      echo \"cannot run $lt_cv_sys_global_symbol_pipe\" >&5\n    fi\n  else\n    echo \"$progname: failed program was:\" >&5\n    cat conftest.$ac_ext >&5\n  fi\n  rm -rf conftest* conftst*\n\n  # Do not use the global_symbol_pipe unless it works.\n  if test \"$pipe_works\" = yes; then\n    break\n  else\n    lt_cv_sys_global_symbol_pipe=\n  fi\ndone\n\nfi\n\nif test -z \"$lt_cv_sys_global_symbol_pipe\"; then\n  lt_cv_sys_global_symbol_to_cdecl=\nfi\nif test -z \"$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: failed\" >&5\n$as_echo \"failed\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: ok\" >&5\n$as_echo \"ok\" >&6; }\nfi\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n# Check whether --enable-libtool-lock was given.\nif test \"${enable_libtool_lock+set}\" = set; then :\n  enableval=$enable_libtool_lock;\nfi\n\ntest \"x$enable_libtool_lock\" != xno && enable_libtool_lock=yes\n\n# Some flags need to be propagated to the compiler or linker for good\n# libtool support.\ncase $host in\nia64-*-hpux*)\n  # Find out which ABI we are using.\n  echo 'int i;' > conftest.$ac_ext\n  if { { eval echo \"\\\"\\$as_me\\\":${as_lineno-$LINENO}: \\\"$ac_compile\\\"\"; } >&5\n  (eval $ac_compile) 2>&5\n  ac_status=$?\n  $as_echo \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; }; then\n    case `/usr/bin/file conftest.$ac_objext` in\n      *ELF-32*)\n\tHPUX_IA64_MODE=\"32\"\n\t;;\n      *ELF-64*)\n\tHPUX_IA64_MODE=\"64\"\n\t;;\n    esac\n  fi\n  rm -rf conftest*\n  ;;\n*-*-irix6*)\n  # Find out which ABI we are using.\n  echo '#line '$LINENO' \"configure\"' > conftest.$ac_ext\n  if { { eval echo \"\\\"\\$as_me\\\":${as_lineno-$LINENO}: \\\"$ac_compile\\\"\"; } >&5\n  (eval $ac_compile) 2>&5\n  ac_status=$?\n  $as_echo \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; }; then\n    if test \"$lt_cv_prog_gnu_ld\" = yes; then\n      case `/usr/bin/file conftest.$ac_objext` in\n\t*32-bit*)\n\t  LD=\"${LD-ld} -melf32bsmip\"\n\t  ;;\n\t*N32*)\n\t  LD=\"${LD-ld} -melf32bmipn32\"\n\t  ;;\n\t*64-bit*)\n\t  LD=\"${LD-ld} -melf64bmip\"\n\t;;\n      esac\n    else\n      case `/usr/bin/file conftest.$ac_objext` in\n\t*32-bit*)\n\t  LD=\"${LD-ld} -32\"\n\t  ;;\n\t*N32*)\n\t  LD=\"${LD-ld} -n32\"\n\t  ;;\n\t*64-bit*)\n\t  LD=\"${LD-ld} -64\"\n\t  ;;\n      esac\n    fi\n  fi\n  rm -rf conftest*\n  ;;\n\nx86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \\\ns390*-*linux*|s390*-*tpf*|sparc*-*linux*)\n  # Find out which ABI we are using.\n  echo 'int i;' > conftest.$ac_ext\n  if { { eval echo \"\\\"\\$as_me\\\":${as_lineno-$LINENO}: \\\"$ac_compile\\\"\"; } >&5\n  (eval $ac_compile) 2>&5\n  ac_status=$?\n  $as_echo \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; }; then\n    case `/usr/bin/file conftest.o` in\n      *32-bit*)\n\tcase $host in\n\t  x86_64-*kfreebsd*-gnu)\n\t    LD=\"${LD-ld} -m elf_i386_fbsd\"\n\t    ;;\n\t  x86_64-*linux*)\n\t    case `/usr/bin/file conftest.o` in\n\t      *x86-64*)\n\t\tLD=\"${LD-ld} -m elf32_x86_64\"\n\t\t;;\n\t      *)\n\t\tLD=\"${LD-ld} -m elf_i386\"\n\t\t;;\n\t    esac\n\t    ;;\n\t  powerpc64le-*linux*)\n\t    LD=\"${LD-ld} -m elf32lppclinux\"\n\t    ;;\n\t  powerpc64-*linux*)\n\t    LD=\"${LD-ld} -m elf32ppclinux\"\n\t    ;;\n\t  s390x-*linux*)\n\t    LD=\"${LD-ld} -m elf_s390\"\n\t    ;;\n\t  sparc64-*linux*)\n\t    LD=\"${LD-ld} -m elf32_sparc\"\n\t    ;;\n\tesac\n\t;;\n      *64-bit*)\n\tcase $host in\n\t  x86_64-*kfreebsd*-gnu)\n\t    LD=\"${LD-ld} -m elf_x86_64_fbsd\"\n\t    ;;\n\t  x86_64-*linux*)\n\t    LD=\"${LD-ld} -m elf_x86_64\"\n\t    ;;\n\t  powerpcle-*linux*)\n\t    LD=\"${LD-ld} -m elf64lppc\"\n\t    ;;\n\t  powerpc-*linux*)\n\t    LD=\"${LD-ld} -m elf64ppc\"\n\t    ;;\n\t  s390*-*linux*|s390*-*tpf*)\n\t    LD=\"${LD-ld} -m elf64_s390\"\n\t    ;;\n\t  sparc*-*linux*)\n\t    LD=\"${LD-ld} -m elf64_sparc\"\n\t    ;;\n\tesac\n\t;;\n    esac\n  fi\n  rm -rf conftest*\n  ;;\n\n*-*-sco3.2v5*)\n  # On SCO OpenServer 5, we need -belf to get full-featured binaries.\n  SAVE_CFLAGS=\"$CFLAGS\"\n  CFLAGS=\"$CFLAGS -belf\"\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf\" >&5\n$as_echo_n \"checking whether the C compiler needs -belf... \" >&6; }\nif ${lt_cv_cc_needs_belf+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  ac_ext=c\nac_cpp='$CPP $CPPFLAGS'\nac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'\nac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'\nac_compiler_gnu=$ac_cv_c_compiler_gnu\n\n     cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain ()\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  lt_cv_cc_needs_belf=yes\nelse\n  lt_cv_cc_needs_belf=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\n     ac_ext=c\nac_cpp='$CPP $CPPFLAGS'\nac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'\nac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'\nac_compiler_gnu=$ac_cv_c_compiler_gnu\n\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf\" >&5\n$as_echo \"$lt_cv_cc_needs_belf\" >&6; }\n  if test x\"$lt_cv_cc_needs_belf\" != x\"yes\"; then\n    # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf\n    CFLAGS=\"$SAVE_CFLAGS\"\n  fi\n  ;;\nsparc*-*solaris*)\n  # Find out which ABI we are using.\n  echo 'int i;' > conftest.$ac_ext\n  if { { eval echo \"\\\"\\$as_me\\\":${as_lineno-$LINENO}: \\\"$ac_compile\\\"\"; } >&5\n  (eval $ac_compile) 2>&5\n  ac_status=$?\n  $as_echo \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; }; then\n    case `/usr/bin/file conftest.o` in\n    *64-bit*)\n      case $lt_cv_prog_gnu_ld in\n      yes*) LD=\"${LD-ld} -m elf64_sparc\" ;;\n      *)\n\tif ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then\n\t  LD=\"${LD-ld} -64\"\n\tfi\n\t;;\n      esac\n      ;;\n    esac\n  fi\n  rm -rf conftest*\n  ;;\nesac\n\nneed_locks=\"$enable_libtool_lock\"\n\n\n  case $host_os in\n    rhapsody* | darwin*)\n    if test -n \"$ac_tool_prefix\"; then\n  # Extract the first word of \"${ac_tool_prefix}dsymutil\", so it can be a program name with args.\nset dummy ${ac_tool_prefix}dsymutil; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_DSYMUTIL+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$DSYMUTIL\"; then\n  ac_cv_prog_DSYMUTIL=\"$DSYMUTIL\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_DSYMUTIL=\"${ac_tool_prefix}dsymutil\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nDSYMUTIL=$ac_cv_prog_DSYMUTIL\nif test -n \"$DSYMUTIL\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL\" >&5\n$as_echo \"$DSYMUTIL\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\nfi\nif test -z \"$ac_cv_prog_DSYMUTIL\"; then\n  ac_ct_DSYMUTIL=$DSYMUTIL\n  # Extract the first word of \"dsymutil\", so it can be a program name with args.\nset dummy dsymutil; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$ac_ct_DSYMUTIL\"; then\n  ac_cv_prog_ac_ct_DSYMUTIL=\"$ac_ct_DSYMUTIL\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_ac_ct_DSYMUTIL=\"dsymutil\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL\nif test -n \"$ac_ct_DSYMUTIL\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL\" >&5\n$as_echo \"$ac_ct_DSYMUTIL\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n  if test \"x$ac_ct_DSYMUTIL\" = x; then\n    DSYMUTIL=\":\"\n  else\n    case $cross_compiling:$ac_tool_warned in\nyes:)\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet\" >&5\n$as_echo \"$as_me: WARNING: using cross tools not prefixed with host triplet\" >&2;}\nac_tool_warned=yes ;;\nesac\n    DSYMUTIL=$ac_ct_DSYMUTIL\n  fi\nelse\n  DSYMUTIL=\"$ac_cv_prog_DSYMUTIL\"\nfi\n\n    if test -n \"$ac_tool_prefix\"; then\n  # Extract the first word of \"${ac_tool_prefix}nmedit\", so it can be a program name with args.\nset dummy ${ac_tool_prefix}nmedit; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_NMEDIT+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$NMEDIT\"; then\n  ac_cv_prog_NMEDIT=\"$NMEDIT\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_NMEDIT=\"${ac_tool_prefix}nmedit\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nNMEDIT=$ac_cv_prog_NMEDIT\nif test -n \"$NMEDIT\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $NMEDIT\" >&5\n$as_echo \"$NMEDIT\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\nfi\nif test -z \"$ac_cv_prog_NMEDIT\"; then\n  ac_ct_NMEDIT=$NMEDIT\n  # Extract the first word of \"nmedit\", so it can be a program name with args.\nset dummy nmedit; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_ac_ct_NMEDIT+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$ac_ct_NMEDIT\"; then\n  ac_cv_prog_ac_ct_NMEDIT=\"$ac_ct_NMEDIT\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_ac_ct_NMEDIT=\"nmedit\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT\nif test -n \"$ac_ct_NMEDIT\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT\" >&5\n$as_echo \"$ac_ct_NMEDIT\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n  if test \"x$ac_ct_NMEDIT\" = x; then\n    NMEDIT=\":\"\n  else\n    case $cross_compiling:$ac_tool_warned in\nyes:)\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet\" >&5\n$as_echo \"$as_me: WARNING: using cross tools not prefixed with host triplet\" >&2;}\nac_tool_warned=yes ;;\nesac\n    NMEDIT=$ac_ct_NMEDIT\n  fi\nelse\n  NMEDIT=\"$ac_cv_prog_NMEDIT\"\nfi\n\n    if test -n \"$ac_tool_prefix\"; then\n  # Extract the first word of \"${ac_tool_prefix}lipo\", so it can be a program name with args.\nset dummy ${ac_tool_prefix}lipo; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_LIPO+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$LIPO\"; then\n  ac_cv_prog_LIPO=\"$LIPO\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_LIPO=\"${ac_tool_prefix}lipo\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nLIPO=$ac_cv_prog_LIPO\nif test -n \"$LIPO\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $LIPO\" >&5\n$as_echo \"$LIPO\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\nfi\nif test -z \"$ac_cv_prog_LIPO\"; then\n  ac_ct_LIPO=$LIPO\n  # Extract the first word of \"lipo\", so it can be a program name with args.\nset dummy lipo; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_ac_ct_LIPO+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$ac_ct_LIPO\"; then\n  ac_cv_prog_ac_ct_LIPO=\"$ac_ct_LIPO\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_ac_ct_LIPO=\"lipo\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO\nif test -n \"$ac_ct_LIPO\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO\" >&5\n$as_echo \"$ac_ct_LIPO\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n  if test \"x$ac_ct_LIPO\" = x; then\n    LIPO=\":\"\n  else\n    case $cross_compiling:$ac_tool_warned in\nyes:)\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet\" >&5\n$as_echo \"$as_me: WARNING: using cross tools not prefixed with host triplet\" >&2;}\nac_tool_warned=yes ;;\nesac\n    LIPO=$ac_ct_LIPO\n  fi\nelse\n  LIPO=\"$ac_cv_prog_LIPO\"\nfi\n\n    if test -n \"$ac_tool_prefix\"; then\n  # Extract the first word of \"${ac_tool_prefix}otool\", so it can be a program name with args.\nset dummy ${ac_tool_prefix}otool; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_OTOOL+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$OTOOL\"; then\n  ac_cv_prog_OTOOL=\"$OTOOL\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_OTOOL=\"${ac_tool_prefix}otool\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nOTOOL=$ac_cv_prog_OTOOL\nif test -n \"$OTOOL\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $OTOOL\" >&5\n$as_echo \"$OTOOL\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\nfi\nif test -z \"$ac_cv_prog_OTOOL\"; then\n  ac_ct_OTOOL=$OTOOL\n  # Extract the first word of \"otool\", so it can be a program name with args.\nset dummy otool; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_ac_ct_OTOOL+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$ac_ct_OTOOL\"; then\n  ac_cv_prog_ac_ct_OTOOL=\"$ac_ct_OTOOL\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_ac_ct_OTOOL=\"otool\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL\nif test -n \"$ac_ct_OTOOL\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL\" >&5\n$as_echo \"$ac_ct_OTOOL\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n  if test \"x$ac_ct_OTOOL\" = x; then\n    OTOOL=\":\"\n  else\n    case $cross_compiling:$ac_tool_warned in\nyes:)\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet\" >&5\n$as_echo \"$as_me: WARNING: using cross tools not prefixed with host triplet\" >&2;}\nac_tool_warned=yes ;;\nesac\n    OTOOL=$ac_ct_OTOOL\n  fi\nelse\n  OTOOL=\"$ac_cv_prog_OTOOL\"\nfi\n\n    if test -n \"$ac_tool_prefix\"; then\n  # Extract the first word of \"${ac_tool_prefix}otool64\", so it can be a program name with args.\nset dummy ${ac_tool_prefix}otool64; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_OTOOL64+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$OTOOL64\"; then\n  ac_cv_prog_OTOOL64=\"$OTOOL64\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_OTOOL64=\"${ac_tool_prefix}otool64\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nOTOOL64=$ac_cv_prog_OTOOL64\nif test -n \"$OTOOL64\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $OTOOL64\" >&5\n$as_echo \"$OTOOL64\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\nfi\nif test -z \"$ac_cv_prog_OTOOL64\"; then\n  ac_ct_OTOOL64=$OTOOL64\n  # Extract the first word of \"otool64\", so it can be a program name with args.\nset dummy otool64; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_ac_ct_OTOOL64+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$ac_ct_OTOOL64\"; then\n  ac_cv_prog_ac_ct_OTOOL64=\"$ac_ct_OTOOL64\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_ac_ct_OTOOL64=\"otool64\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64\nif test -n \"$ac_ct_OTOOL64\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64\" >&5\n$as_echo \"$ac_ct_OTOOL64\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n  if test \"x$ac_ct_OTOOL64\" = x; then\n    OTOOL64=\":\"\n  else\n    case $cross_compiling:$ac_tool_warned in\nyes:)\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet\" >&5\n$as_echo \"$as_me: WARNING: using cross tools not prefixed with host triplet\" >&2;}\nac_tool_warned=yes ;;\nesac\n    OTOOL64=$ac_ct_OTOOL64\n  fi\nelse\n  OTOOL64=\"$ac_cv_prog_OTOOL64\"\nfi\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag\" >&5\n$as_echo_n \"checking for -single_module linker flag... \" >&6; }\nif ${lt_cv_apple_cc_single_mod+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  lt_cv_apple_cc_single_mod=no\n      if test -z \"${LT_MULTI_MODULE}\"; then\n\t# By default we will add the -single_module flag. You can override\n\t# by either setting the environment variable LT_MULTI_MODULE\n\t# non-empty at configure time, or by adding -multi_module to the\n\t# link flags.\n\trm -rf libconftest.dylib*\n\techo \"int foo(void){return 1;}\" > conftest.c\n\techo \"$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \\\n-dynamiclib -Wl,-single_module conftest.c\" >&5\n\t$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \\\n\t  -dynamiclib -Wl,-single_module conftest.c 2>conftest.err\n        _lt_result=$?\n\tif test -f libconftest.dylib && test ! -s conftest.err && test $_lt_result = 0; then\n\t  lt_cv_apple_cc_single_mod=yes\n\telse\n\t  cat conftest.err >&5\n\tfi\n\trm -rf libconftest.dylib*\n\trm -f conftest.*\n      fi\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod\" >&5\n$as_echo \"$lt_cv_apple_cc_single_mod\" >&6; }\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag\" >&5\n$as_echo_n \"checking for -exported_symbols_list linker flag... \" >&6; }\nif ${lt_cv_ld_exported_symbols_list+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  lt_cv_ld_exported_symbols_list=no\n      save_LDFLAGS=$LDFLAGS\n      echo \"_main\" > conftest.sym\n      LDFLAGS=\"$LDFLAGS -Wl,-exported_symbols_list,conftest.sym\"\n      cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain ()\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  lt_cv_ld_exported_symbols_list=yes\nelse\n  lt_cv_ld_exported_symbols_list=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\n\tLDFLAGS=\"$save_LDFLAGS\"\n\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list\" >&5\n$as_echo \"$lt_cv_ld_exported_symbols_list\" >&6; }\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag\" >&5\n$as_echo_n \"checking for -force_load linker flag... \" >&6; }\nif ${lt_cv_ld_force_load+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  lt_cv_ld_force_load=no\n      cat > conftest.c << _LT_EOF\nint forced_loaded() { return 2;}\n_LT_EOF\n      echo \"$LTCC $LTCFLAGS -c -o conftest.o conftest.c\" >&5\n      $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5\n      echo \"$AR cru libconftest.a conftest.o\" >&5\n      $AR cru libconftest.a conftest.o 2>&5\n      cat > conftest.c << _LT_EOF\nint main() { return 0;}\n_LT_EOF\n      echo \"$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a\" >&5\n      $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err\n      _lt_result=$?\n      if test -f conftest && test ! -s conftest.err && test $_lt_result = 0 && $GREP forced_load conftest 2>&1 >/dev/null; then\n\tlt_cv_ld_force_load=yes\n      else\n\tcat conftest.err >&5\n      fi\n        rm -f conftest.err libconftest.a conftest conftest.c\n        rm -rf conftest.dSYM\n\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load\" >&5\n$as_echo \"$lt_cv_ld_force_load\" >&6; }\n    # Allow for Darwin 4-7 (macOS 10.0-10.3) although these are not expect to\n    # build without first building modern cctools / linker.\n    case $host_cpu-$host_os in\n    *-rhapsody* | *-darwin1.[012])\n      _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;;\n    *-darwin1.*)\n      _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;\n    *-darwin*)\n      # darwin 5.x (macOS 10.1) onwards we only need to adjust when the\n      # deployment target is forced to an earlier version.\n      case ${MACOSX_DEPLOYMENT_TARGET-UNSET},$host in\n\tUNSET,*-darwin[89]*|UNSET,*-darwin[12][0-9]*)\n\t  ;;\n\t10.[012][,.]*)\n\t  _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'\n\t  ;;\n\t*)\n\t  ;;\n     esac\n    ;;\n  esac\n    if test \"$lt_cv_apple_cc_single_mod\" = \"yes\"; then\n      _lt_dar_single_mod='$single_module'\n    fi\n    if test \"$lt_cv_ld_exported_symbols_list\" = \"yes\"; then\n      _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym'\n    else\n      _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}'\n    fi\n    if test \"$DSYMUTIL\" != \":\" && test \"$lt_cv_ld_force_load\" = \"no\"; then\n      _lt_dsymutil='~$DSYMUTIL $lib || :'\n    else\n      _lt_dsymutil=\n    fi\n    ;;\n  esac\n\nfor ac_header in dlfcn.h\ndo :\n  ac_fn_c_check_header_compile \"$LINENO\" \"dlfcn.h\" \"ac_cv_header_dlfcn_h\" \"$ac_includes_default\n\"\nif test \"x$ac_cv_header_dlfcn_h\" = xyes; then :\n  cat >>confdefs.h <<_ACEOF\n#define HAVE_DLFCN_H 1\n_ACEOF\n\nfi\n\ndone\n\n\n\n\n\n# Set options\n\n\n\n        enable_dlopen=no\n\n\n  enable_win32_dll=no\n\n\n\n  # Check whether --enable-static was given.\nif test \"${enable_static+set}\" = set; then :\n  enableval=$enable_static; p=${PACKAGE-default}\n    case $enableval in\n    yes) enable_static=yes ;;\n    no) enable_static=no ;;\n    *)\n     enable_static=no\n      # Look at the argument we got.  We use all the common list separators.\n      lt_save_ifs=\"$IFS\"; IFS=\"${IFS}$PATH_SEPARATOR,\"\n      for pkg in $enableval; do\n\tIFS=\"$lt_save_ifs\"\n\tif test \"X$pkg\" = \"X$p\"; then\n\t  enable_static=yes\n\tfi\n      done\n      IFS=\"$lt_save_ifs\"\n      ;;\n    esac\nelse\n  enable_static=yes\nfi\n\n\n\n\n\n\n\n\n\n\n# Check whether --with-pic was given.\nif test \"${with_pic+set}\" = set; then :\n  withval=$with_pic; pic_mode=\"$withval\"\nelse\n  pic_mode=default\nfi\n\n\ntest -z \"$pic_mode\" && pic_mode=default\n\n\n\n\n\n\n\n  # Check whether --enable-fast-install was given.\nif test \"${enable_fast_install+set}\" = set; then :\n  enableval=$enable_fast_install; p=${PACKAGE-default}\n    case $enableval in\n    yes) enable_fast_install=yes ;;\n    no) enable_fast_install=no ;;\n    *)\n      enable_fast_install=no\n      # Look at the argument we got.  We use all the common list separators.\n      lt_save_ifs=\"$IFS\"; IFS=\"${IFS}$PATH_SEPARATOR,\"\n      for pkg in $enableval; do\n\tIFS=\"$lt_save_ifs\"\n\tif test \"X$pkg\" = \"X$p\"; then\n\t  enable_fast_install=yes\n\tfi\n      done\n      IFS=\"$lt_save_ifs\"\n      ;;\n    esac\nelse\n  enable_fast_install=yes\nfi\n\n\n\n\n\n\n\n\n\n\n\n# This can be used to rebuild libtool when needed\nLIBTOOL_DEPS=\"$ltmain\"\n\n# Always use our own libtool.\nLIBTOOL='$(SHELL) $(top_builddir)/libtool'\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\ntest -z \"$LN_S\" && LN_S=\"ln -s\"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nif test -n \"${ZSH_VERSION+set}\" ; then\n   setopt NO_GLOB_SUBST\nfi\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for objdir\" >&5\n$as_echo_n \"checking for objdir... \" >&6; }\nif ${lt_cv_objdir+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  rm -f .libs 2>/dev/null\nmkdir .libs 2>/dev/null\nif test -d .libs; then\n  lt_cv_objdir=.libs\nelse\n  # MS-DOS does not allow filenames that begin with a dot.\n  lt_cv_objdir=_libs\nfi\nrmdir .libs 2>/dev/null\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir\" >&5\n$as_echo \"$lt_cv_objdir\" >&6; }\nobjdir=$lt_cv_objdir\n\n\n\n\n\ncat >>confdefs.h <<_ACEOF\n#define LT_OBJDIR \"$lt_cv_objdir/\"\n_ACEOF\n\n\n\n\ncase $host_os in\naix3*)\n  # AIX sometimes has problems with the GCC collect2 program.  For some\n  # reason, if we set the COLLECT_NAMES environment variable, the problems\n  # vanish in a puff of smoke.\n  if test \"X${COLLECT_NAMES+set}\" != Xset; then\n    COLLECT_NAMES=\n    export COLLECT_NAMES\n  fi\n  ;;\nesac\n\n# Global variables:\nofile=libtool\ncan_build_shared=yes\n\n# All known linkers require a `.a' archive for static linking (except MSVC,\n# which needs '.lib').\nlibext=a\n\nwith_gnu_ld=\"$lt_cv_prog_gnu_ld\"\n\nold_CC=\"$CC\"\nold_CFLAGS=\"$CFLAGS\"\n\n# Set sane defaults for various variables\ntest -z \"$CC\" && CC=cc\ntest -z \"$LTCC\" && LTCC=$CC\ntest -z \"$LTCFLAGS\" && LTCFLAGS=$CFLAGS\ntest -z \"$LD\" && LD=ld\ntest -z \"$ac_objext\" && ac_objext=o\n\nfor cc_temp in $compiler\"\"; do\n  case $cc_temp in\n    compile | *[\\\\/]compile | ccache | *[\\\\/]ccache ) ;;\n    distcc | *[\\\\/]distcc | purify | *[\\\\/]purify ) ;;\n    \\-*) ;;\n    *) break;;\n  esac\ndone\ncc_basename=`$ECHO \"$cc_temp\" | $SED \"s%.*/%%; s%^$host_alias-%%\"`\n\n\n# Only perform the check for file, if the check method requires it\ntest -z \"$MAGIC_CMD\" && MAGIC_CMD=file\ncase $deplibs_check_method in\nfile_magic*)\n  if test \"$file_magic_cmd\" = '$MAGIC_CMD'; then\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file\" >&5\n$as_echo_n \"checking for ${ac_tool_prefix}file... \" >&6; }\nif ${lt_cv_path_MAGIC_CMD+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  case $MAGIC_CMD in\n[\\\\/*] |  ?:[\\\\/]*)\n  lt_cv_path_MAGIC_CMD=\"$MAGIC_CMD\" # Let the user override the test with a path.\n  ;;\n*)\n  lt_save_MAGIC_CMD=\"$MAGIC_CMD\"\n  lt_save_ifs=\"$IFS\"; IFS=$PATH_SEPARATOR\n  ac_dummy=\"/usr/bin$PATH_SEPARATOR$PATH\"\n  for ac_dir in $ac_dummy; do\n    IFS=\"$lt_save_ifs\"\n    test -z \"$ac_dir\" && ac_dir=.\n    if test -f $ac_dir/${ac_tool_prefix}file; then\n      lt_cv_path_MAGIC_CMD=\"$ac_dir/${ac_tool_prefix}file\"\n      if test -n \"$file_magic_test_file\"; then\n\tcase $deplibs_check_method in\n\t\"file_magic \"*)\n\t  file_magic_regex=`expr \"$deplibs_check_method\" : \"file_magic \\(.*\\)\"`\n\t  MAGIC_CMD=\"$lt_cv_path_MAGIC_CMD\"\n\t  if eval $file_magic_cmd \\$file_magic_test_file 2> /dev/null |\n\t    $EGREP \"$file_magic_regex\" > /dev/null; then\n\t    :\n\t  else\n\t    cat <<_LT_EOF 1>&2\n\n*** Warning: the command libtool uses to detect shared libraries,\n*** $file_magic_cmd, produces output that libtool cannot recognize.\n*** The result is that libtool may fail to recognize shared libraries\n*** as such.  This will affect the creation of libtool libraries that\n*** depend on shared libraries, but programs linked with such libtool\n*** libraries will work regardless of this problem.  Nevertheless, you\n*** may want to report the problem to your system manager and/or to\n*** bug-libtool@gnu.org\n\n_LT_EOF\n\t  fi ;;\n\tesac\n      fi\n      break\n    fi\n  done\n  IFS=\"$lt_save_ifs\"\n  MAGIC_CMD=\"$lt_save_MAGIC_CMD\"\n  ;;\nesac\nfi\n\nMAGIC_CMD=\"$lt_cv_path_MAGIC_CMD\"\nif test -n \"$MAGIC_CMD\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD\" >&5\n$as_echo \"$MAGIC_CMD\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\n\n\n\nif test -z \"$lt_cv_path_MAGIC_CMD\"; then\n  if test -n \"$ac_tool_prefix\"; then\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for file\" >&5\n$as_echo_n \"checking for file... \" >&6; }\nif ${lt_cv_path_MAGIC_CMD+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  case $MAGIC_CMD in\n[\\\\/*] |  ?:[\\\\/]*)\n  lt_cv_path_MAGIC_CMD=\"$MAGIC_CMD\" # Let the user override the test with a path.\n  ;;\n*)\n  lt_save_MAGIC_CMD=\"$MAGIC_CMD\"\n  lt_save_ifs=\"$IFS\"; IFS=$PATH_SEPARATOR\n  ac_dummy=\"/usr/bin$PATH_SEPARATOR$PATH\"\n  for ac_dir in $ac_dummy; do\n    IFS=\"$lt_save_ifs\"\n    test -z \"$ac_dir\" && ac_dir=.\n    if test -f $ac_dir/file; then\n      lt_cv_path_MAGIC_CMD=\"$ac_dir/file\"\n      if test -n \"$file_magic_test_file\"; then\n\tcase $deplibs_check_method in\n\t\"file_magic \"*)\n\t  file_magic_regex=`expr \"$deplibs_check_method\" : \"file_magic \\(.*\\)\"`\n\t  MAGIC_CMD=\"$lt_cv_path_MAGIC_CMD\"\n\t  if eval $file_magic_cmd \\$file_magic_test_file 2> /dev/null |\n\t    $EGREP \"$file_magic_regex\" > /dev/null; then\n\t    :\n\t  else\n\t    cat <<_LT_EOF 1>&2\n\n*** Warning: the command libtool uses to detect shared libraries,\n*** $file_magic_cmd, produces output that libtool cannot recognize.\n*** The result is that libtool may fail to recognize shared libraries\n*** as such.  This will affect the creation of libtool libraries that\n*** depend on shared libraries, but programs linked with such libtool\n*** libraries will work regardless of this problem.  Nevertheless, you\n*** may want to report the problem to your system manager and/or to\n*** bug-libtool@gnu.org\n\n_LT_EOF\n\t  fi ;;\n\tesac\n      fi\n      break\n    fi\n  done\n  IFS=\"$lt_save_ifs\"\n  MAGIC_CMD=\"$lt_save_MAGIC_CMD\"\n  ;;\nesac\nfi\n\nMAGIC_CMD=\"$lt_cv_path_MAGIC_CMD\"\nif test -n \"$MAGIC_CMD\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD\" >&5\n$as_echo \"$MAGIC_CMD\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\n  else\n    MAGIC_CMD=:\n  fi\nfi\n\n  fi\n  ;;\nesac\n\n# Use C for the default configuration in the libtool script\n\nlt_save_CC=\"$CC\"\nac_ext=c\nac_cpp='$CPP $CPPFLAGS'\nac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'\nac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'\nac_compiler_gnu=$ac_cv_c_compiler_gnu\n\n\n# Source file extension for C test sources.\nac_ext=c\n\n# Object file extension for compiled C test sources.\nobjext=o\nobjext=$objext\n\n# Code to be used in simple compile tests\nlt_simple_compile_test_code=\"int some_variable = 0;\"\n\n# Code to be used in simple link tests\nlt_simple_link_test_code='int main(){return(0);}'\n\n\n\n\n\n\n\n# If no C compiler was specified, use CC.\nLTCC=${LTCC-\"$CC\"}\n\n# If no C compiler flags were specified, use CFLAGS.\nLTCFLAGS=${LTCFLAGS-\"$CFLAGS\"}\n\n# Allow CC to be a program name with arguments.\ncompiler=$CC\n\n# Save the default compiler, since it gets overwritten when the other\n# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP.\ncompiler_DEFAULT=$CC\n\n# save warnings/boilerplate of simple test code\nac_outfile=conftest.$ac_objext\necho \"$lt_simple_compile_test_code\" >conftest.$ac_ext\neval \"$ac_compile\" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err\n_lt_compiler_boilerplate=`cat conftest.err`\n$RM conftest*\n\nac_outfile=conftest.$ac_objext\necho \"$lt_simple_link_test_code\" >conftest.$ac_ext\neval \"$ac_link\" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err\n_lt_linker_boilerplate=`cat conftest.err`\n$RM -r conftest*\n\n\n## CAVEAT EMPTOR:\n## There is no encapsulation within the following macros, do not change\n## the running order or otherwise move them around unless you know exactly\n## what you are doing...\nif test -n \"$compiler\"; then\n\nlt_prog_compiler_no_builtin_flag=\n\nif test \"$GCC\" = yes; then\n  case $cc_basename in\n  nvcc*)\n    lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;;\n  *)\n    lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;;\n  esac\n\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions\" >&5\n$as_echo_n \"checking if $compiler supports -fno-rtti -fno-exceptions... \" >&6; }\nif ${lt_cv_prog_compiler_rtti_exceptions+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  lt_cv_prog_compiler_rtti_exceptions=no\n   ac_outfile=conftest.$ac_objext\n   echo \"$lt_simple_compile_test_code\" > conftest.$ac_ext\n   lt_compiler_flag=\"-fno-rtti -fno-exceptions\"\n   # Insert the option either (1) after the last *FLAGS variable, or\n   # (2) before a word containing \"conftest.\", or (3) at the end.\n   # Note that $ac_compile itself does not contain backslashes and begins\n   # with a dollar sign (not a hyphen), so the echo should work correctly.\n   # The option is referenced via a variable to avoid confusing sed.\n   lt_compile=`echo \"$ac_compile\" | $SED \\\n   -e 's:.*FLAGS}\\{0,1\\} :&$lt_compiler_flag :; t' \\\n   -e 's: [^ ]*conftest\\.: $lt_compiler_flag&:; t' \\\n   -e 's:$: $lt_compiler_flag:'`\n   (eval echo \"\\\"\\$as_me:$LINENO: $lt_compile\\\"\" >&5)\n   (eval \"$lt_compile\" 2>conftest.err)\n   ac_status=$?\n   cat conftest.err >&5\n   echo \"$as_me:$LINENO: \\$? = $ac_status\" >&5\n   if (exit $ac_status) && test -s \"$ac_outfile\"; then\n     # The compiler can only warn and ignore the option if not recognized\n     # So say no if there are warnings other than the usual output.\n     $ECHO \"$_lt_compiler_boilerplate\" | $SED '/^$/d' >conftest.exp\n     $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2\n     if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then\n       lt_cv_prog_compiler_rtti_exceptions=yes\n     fi\n   fi\n   $RM conftest*\n\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions\" >&5\n$as_echo \"$lt_cv_prog_compiler_rtti_exceptions\" >&6; }\n\nif test x\"$lt_cv_prog_compiler_rtti_exceptions\" = xyes; then\n    lt_prog_compiler_no_builtin_flag=\"$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions\"\nelse\n    :\nfi\n\nfi\n\n\n\n\n\n\n  lt_prog_compiler_wl=\nlt_prog_compiler_pic=\nlt_prog_compiler_static=\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC\" >&5\n$as_echo_n \"checking for $compiler option to produce PIC... \" >&6; }\n\n  if test \"$GCC\" = yes; then\n    lt_prog_compiler_wl='-Wl,'\n    lt_prog_compiler_static='-static'\n\n    case $host_os in\n      aix*)\n      # All AIX code is PIC.\n      if test \"$host_cpu\" = ia64; then\n\t# AIX 5 now supports IA64 processor\n\tlt_prog_compiler_static='-Bstatic'\n      fi\n      lt_prog_compiler_pic='-fPIC'\n      ;;\n\n    amigaos*)\n      case $host_cpu in\n      powerpc)\n            # see comment about AmigaOS4 .so support\n            lt_prog_compiler_pic='-fPIC'\n        ;;\n      m68k)\n            # FIXME: we need at least 68020 code to build shared libraries, but\n            # adding the `-m68020' flag to GCC prevents building anything better,\n            # like `-m68040'.\n            lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4'\n        ;;\n      esac\n      ;;\n\n    beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)\n      # PIC is the default for these OSes.\n      ;;\n\n    mingw* | cygwin* | pw32* | os2* | cegcc*)\n      # This hack is so that the source file can tell whether it is being\n      # built for inclusion in a dll (and should export symbols for example).\n      # Although the cygwin gcc ignores -fPIC, still need this for old-style\n      # (--disable-auto-import) libraries\n      lt_prog_compiler_pic='-DDLL_EXPORT'\n      ;;\n\n    darwin* | rhapsody*)\n      # PIC is the default on this platform\n      # Common symbols not allowed in MH_DYLIB files\n      lt_prog_compiler_pic='-fno-common'\n      ;;\n\n    haiku*)\n      # PIC is the default for Haiku.\n      # The \"-static\" flag exists, but is broken.\n      lt_prog_compiler_static=\n      ;;\n\n    hpux*)\n      # PIC is the default for 64-bit PA HP-UX, but not for 32-bit\n      # PA HP-UX.  On IA64 HP-UX, PIC is the default but the pic flag\n      # sets the default TLS model and affects inlining.\n      case $host_cpu in\n      hppa*64*)\n\t# +Z the default\n\t;;\n      *)\n\tlt_prog_compiler_pic='-fPIC'\n\t;;\n      esac\n      ;;\n\n    interix[3-9]*)\n      # Interix 3.x gcc -fpic/-fPIC options generate broken code.\n      # Instead, we relocate shared libraries at runtime.\n      ;;\n\n    msdosdjgpp*)\n      # Just because we use GCC doesn't mean we suddenly get shared libraries\n      # on systems that don't support them.\n      lt_prog_compiler_can_build_shared=no\n      enable_shared=no\n      ;;\n\n    *nto* | *qnx*)\n      # QNX uses GNU C++, but need to define -shared option too, otherwise\n      # it will coredump.\n      lt_prog_compiler_pic='-fPIC -shared'\n      ;;\n\n    sysv4*MP*)\n      if test -d /usr/nec; then\n\tlt_prog_compiler_pic=-Kconform_pic\n      fi\n      ;;\n\n    *)\n      lt_prog_compiler_pic='-fPIC'\n      ;;\n    esac\n\n    case $cc_basename in\n    nvcc*) # Cuda Compiler Driver 2.2\n      lt_prog_compiler_wl='-Xlinker '\n      lt_prog_compiler_pic='-Xcompiler -fPIC'\n      ;;\n    esac\n  else\n    # PORTME Check for flag to pass linker flags through the system compiler.\n    case $host_os in\n    aix*)\n      lt_prog_compiler_wl='-Wl,'\n      if test \"$host_cpu\" = ia64; then\n\t# AIX 5 now supports IA64 processor\n\tlt_prog_compiler_static='-Bstatic'\n      else\n\tlt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp'\n      fi\n      ;;\n\n    mingw* | cygwin* | pw32* | os2* | cegcc*)\n      # This hack is so that the source file can tell whether it is being\n      # built for inclusion in a dll (and should export symbols for example).\n      lt_prog_compiler_pic='-DDLL_EXPORT'\n      ;;\n\n    hpux9* | hpux10* | hpux11*)\n      lt_prog_compiler_wl='-Wl,'\n      # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but\n      # not for PA HP-UX.\n      case $host_cpu in\n      hppa*64*|ia64*)\n\t# +Z the default\n\t;;\n      *)\n\tlt_prog_compiler_pic='+Z'\n\t;;\n      esac\n      # Is there a better lt_prog_compiler_static that works with the bundled CC?\n      lt_prog_compiler_static='${wl}-a ${wl}archive'\n      ;;\n\n    irix5* | irix6* | nonstopux*)\n      lt_prog_compiler_wl='-Wl,'\n      # PIC (with -KPIC) is the default.\n      lt_prog_compiler_static='-non_shared'\n      ;;\n\n    linux* | k*bsd*-gnu | kopensolaris*-gnu)\n      case $cc_basename in\n      # old Intel for x86_64 which still supported -KPIC.\n      ecc*)\n\tlt_prog_compiler_wl='-Wl,'\n\tlt_prog_compiler_pic='-KPIC'\n\tlt_prog_compiler_static='-static'\n        ;;\n      # icc used to be incompatible with GCC.\n      # ICC 10 doesn't accept -KPIC any more.\n      icc* | ifort*)\n\tlt_prog_compiler_wl='-Wl,'\n\tlt_prog_compiler_pic='-fPIC'\n\tlt_prog_compiler_static='-static'\n        ;;\n      # Lahey Fortran 8.1.\n      lf95*)\n\tlt_prog_compiler_wl='-Wl,'\n\tlt_prog_compiler_pic='--shared'\n\tlt_prog_compiler_static='--static'\n\t;;\n      pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*)\n        # Portland Group compilers (*not* the Pentium gcc compiler,\n\t# which looks to be a dead project)\n\tlt_prog_compiler_wl='-Wl,'\n\tlt_prog_compiler_pic='-fpic'\n\tlt_prog_compiler_static='-Bstatic'\n        ;;\n      ccc*)\n        lt_prog_compiler_wl='-Wl,'\n        # All Alpha code is PIC.\n        lt_prog_compiler_static='-non_shared'\n        ;;\n      xl* | bgxl* | bgf* | mpixl*)\n\t# IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene\n\tlt_prog_compiler_wl='-Wl,'\n\tlt_prog_compiler_pic='-qpic'\n\tlt_prog_compiler_static='-qstaticlink'\n\t;;\n      *)\n\tcase `$CC -V 2>&1 | sed 5q` in\n\t*Sun\\ F* | *Sun*Fortran*)\n\t  # Sun Fortran 8.3 passes all unrecognized flags to the linker\n\t  lt_prog_compiler_pic='-KPIC'\n\t  lt_prog_compiler_static='-Bstatic'\n\t  lt_prog_compiler_wl=''\n\t  ;;\n\t*Sun\\ C*)\n\t  # Sun C 5.9\n\t  lt_prog_compiler_pic='-KPIC'\n\t  lt_prog_compiler_static='-Bstatic'\n\t  lt_prog_compiler_wl='-Wl,'\n\t  ;;\n\tesac\n\t;;\n      esac\n      ;;\n\n    newsos6)\n      lt_prog_compiler_pic='-KPIC'\n      lt_prog_compiler_static='-Bstatic'\n      ;;\n\n    *nto* | *qnx*)\n      # QNX uses GNU C++, but need to define -shared option too, otherwise\n      # it will coredump.\n      lt_prog_compiler_pic='-fPIC -shared'\n      ;;\n\n    osf3* | osf4* | osf5*)\n      lt_prog_compiler_wl='-Wl,'\n      # All OSF/1 code is PIC.\n      lt_prog_compiler_static='-non_shared'\n      ;;\n\n    rdos*)\n      lt_prog_compiler_static='-non_shared'\n      ;;\n\n    solaris*)\n      lt_prog_compiler_pic='-KPIC'\n      lt_prog_compiler_static='-Bstatic'\n      case $cc_basename in\n      f77* | f90* | f95*)\n\tlt_prog_compiler_wl='-Qoption ld ';;\n      *)\n\tlt_prog_compiler_wl='-Wl,';;\n      esac\n      ;;\n\n    sunos4*)\n      lt_prog_compiler_wl='-Qoption ld '\n      lt_prog_compiler_pic='-PIC'\n      lt_prog_compiler_static='-Bstatic'\n      ;;\n\n    sysv4 | sysv4.2uw2* | sysv4.3*)\n      lt_prog_compiler_wl='-Wl,'\n      lt_prog_compiler_pic='-KPIC'\n      lt_prog_compiler_static='-Bstatic'\n      ;;\n\n    sysv4*MP*)\n      if test -d /usr/nec ;then\n\tlt_prog_compiler_pic='-Kconform_pic'\n\tlt_prog_compiler_static='-Bstatic'\n      fi\n      ;;\n\n    sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)\n      lt_prog_compiler_wl='-Wl,'\n      lt_prog_compiler_pic='-KPIC'\n      lt_prog_compiler_static='-Bstatic'\n      ;;\n\n    unicos*)\n      lt_prog_compiler_wl='-Wl,'\n      lt_prog_compiler_can_build_shared=no\n      ;;\n\n    uts4*)\n      lt_prog_compiler_pic='-pic'\n      lt_prog_compiler_static='-Bstatic'\n      ;;\n\n    *)\n      lt_prog_compiler_can_build_shared=no\n      ;;\n    esac\n  fi\n\ncase $host_os in\n  # For platforms which do not support PIC, -DPIC is meaningless:\n  *djgpp*)\n    lt_prog_compiler_pic=\n    ;;\n  *)\n    lt_prog_compiler_pic=\"$lt_prog_compiler_pic -DPIC\"\n    ;;\nesac\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $lt_prog_compiler_pic\" >&5\n$as_echo \"$lt_prog_compiler_pic\" >&6; }\n\n\n\n\n\n\n#\n# Check to make sure the PIC flag actually works.\n#\nif test -n \"$lt_prog_compiler_pic\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works\" >&5\n$as_echo_n \"checking if $compiler PIC flag $lt_prog_compiler_pic works... \" >&6; }\nif ${lt_cv_prog_compiler_pic_works+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  lt_cv_prog_compiler_pic_works=no\n   ac_outfile=conftest.$ac_objext\n   echo \"$lt_simple_compile_test_code\" > conftest.$ac_ext\n   lt_compiler_flag=\"$lt_prog_compiler_pic -DPIC\"\n   # Insert the option either (1) after the last *FLAGS variable, or\n   # (2) before a word containing \"conftest.\", or (3) at the end.\n   # Note that $ac_compile itself does not contain backslashes and begins\n   # with a dollar sign (not a hyphen), so the echo should work correctly.\n   # The option is referenced via a variable to avoid confusing sed.\n   lt_compile=`echo \"$ac_compile\" | $SED \\\n   -e 's:.*FLAGS}\\{0,1\\} :&$lt_compiler_flag :; t' \\\n   -e 's: [^ ]*conftest\\.: $lt_compiler_flag&:; t' \\\n   -e 's:$: $lt_compiler_flag:'`\n   (eval echo \"\\\"\\$as_me:$LINENO: $lt_compile\\\"\" >&5)\n   (eval \"$lt_compile\" 2>conftest.err)\n   ac_status=$?\n   cat conftest.err >&5\n   echo \"$as_me:$LINENO: \\$? = $ac_status\" >&5\n   if (exit $ac_status) && test -s \"$ac_outfile\"; then\n     # The compiler can only warn and ignore the option if not recognized\n     # So say no if there are warnings other than the usual output.\n     $ECHO \"$_lt_compiler_boilerplate\" | $SED '/^$/d' >conftest.exp\n     $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2\n     if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then\n       lt_cv_prog_compiler_pic_works=yes\n     fi\n   fi\n   $RM conftest*\n\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works\" >&5\n$as_echo \"$lt_cv_prog_compiler_pic_works\" >&6; }\n\nif test x\"$lt_cv_prog_compiler_pic_works\" = xyes; then\n    case $lt_prog_compiler_pic in\n     \"\" | \" \"*) ;;\n     *) lt_prog_compiler_pic=\" $lt_prog_compiler_pic\" ;;\n     esac\nelse\n    lt_prog_compiler_pic=\n     lt_prog_compiler_can_build_shared=no\nfi\n\nfi\n\n\n\n\n\n\n#\n# Check to make sure the static flag actually works.\n#\nwl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\\\"$lt_prog_compiler_static\\\"\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works\" >&5\n$as_echo_n \"checking if $compiler static flag $lt_tmp_static_flag works... \" >&6; }\nif ${lt_cv_prog_compiler_static_works+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  lt_cv_prog_compiler_static_works=no\n   save_LDFLAGS=\"$LDFLAGS\"\n   LDFLAGS=\"$LDFLAGS $lt_tmp_static_flag\"\n   echo \"$lt_simple_link_test_code\" > conftest.$ac_ext\n   if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then\n     # The linker can only warn and ignore the option if not recognized\n     # So say no if there are warnings\n     if test -s conftest.err; then\n       # Append any errors to the config.log.\n       cat conftest.err 1>&5\n       $ECHO \"$_lt_linker_boilerplate\" | $SED '/^$/d' > conftest.exp\n       $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2\n       if diff conftest.exp conftest.er2 >/dev/null; then\n         lt_cv_prog_compiler_static_works=yes\n       fi\n     else\n       lt_cv_prog_compiler_static_works=yes\n     fi\n   fi\n   $RM -r conftest*\n   LDFLAGS=\"$save_LDFLAGS\"\n\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works\" >&5\n$as_echo \"$lt_cv_prog_compiler_static_works\" >&6; }\n\nif test x\"$lt_cv_prog_compiler_static_works\" = xyes; then\n    :\nelse\n    lt_prog_compiler_static=\nfi\n\n\n\n\n\n\n\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext\" >&5\n$as_echo_n \"checking if $compiler supports -c -o file.$ac_objext... \" >&6; }\nif ${lt_cv_prog_compiler_c_o+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  lt_cv_prog_compiler_c_o=no\n   $RM -r conftest 2>/dev/null\n   mkdir conftest\n   cd conftest\n   mkdir out\n   echo \"$lt_simple_compile_test_code\" > conftest.$ac_ext\n\n   lt_compiler_flag=\"-o out/conftest2.$ac_objext\"\n   # Insert the option either (1) after the last *FLAGS variable, or\n   # (2) before a word containing \"conftest.\", or (3) at the end.\n   # Note that $ac_compile itself does not contain backslashes and begins\n   # with a dollar sign (not a hyphen), so the echo should work correctly.\n   lt_compile=`echo \"$ac_compile\" | $SED \\\n   -e 's:.*FLAGS}\\{0,1\\} :&$lt_compiler_flag :; t' \\\n   -e 's: [^ ]*conftest\\.: $lt_compiler_flag&:; t' \\\n   -e 's:$: $lt_compiler_flag:'`\n   (eval echo \"\\\"\\$as_me:$LINENO: $lt_compile\\\"\" >&5)\n   (eval \"$lt_compile\" 2>out/conftest.err)\n   ac_status=$?\n   cat out/conftest.err >&5\n   echo \"$as_me:$LINENO: \\$? = $ac_status\" >&5\n   if (exit $ac_status) && test -s out/conftest2.$ac_objext\n   then\n     # The compiler can only warn and ignore the option if not recognized\n     # So say no if there are warnings\n     $ECHO \"$_lt_compiler_boilerplate\" | $SED '/^$/d' > out/conftest.exp\n     $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2\n     if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then\n       lt_cv_prog_compiler_c_o=yes\n     fi\n   fi\n   chmod u+w . 2>&5\n   $RM conftest*\n   # SGI C++ compiler will create directory out/ii_files/ for\n   # template instantiation\n   test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files\n   $RM out/* && rmdir out\n   cd ..\n   $RM -r conftest\n   $RM conftest*\n\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o\" >&5\n$as_echo \"$lt_cv_prog_compiler_c_o\" >&6; }\n\n\n\n\n\n\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext\" >&5\n$as_echo_n \"checking if $compiler supports -c -o file.$ac_objext... \" >&6; }\nif ${lt_cv_prog_compiler_c_o+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  lt_cv_prog_compiler_c_o=no\n   $RM -r conftest 2>/dev/null\n   mkdir conftest\n   cd conftest\n   mkdir out\n   echo \"$lt_simple_compile_test_code\" > conftest.$ac_ext\n\n   lt_compiler_flag=\"-o out/conftest2.$ac_objext\"\n   # Insert the option either (1) after the last *FLAGS variable, or\n   # (2) before a word containing \"conftest.\", or (3) at the end.\n   # Note that $ac_compile itself does not contain backslashes and begins\n   # with a dollar sign (not a hyphen), so the echo should work correctly.\n   lt_compile=`echo \"$ac_compile\" | $SED \\\n   -e 's:.*FLAGS}\\{0,1\\} :&$lt_compiler_flag :; t' \\\n   -e 's: [^ ]*conftest\\.: $lt_compiler_flag&:; t' \\\n   -e 's:$: $lt_compiler_flag:'`\n   (eval echo \"\\\"\\$as_me:$LINENO: $lt_compile\\\"\" >&5)\n   (eval \"$lt_compile\" 2>out/conftest.err)\n   ac_status=$?\n   cat out/conftest.err >&5\n   echo \"$as_me:$LINENO: \\$? = $ac_status\" >&5\n   if (exit $ac_status) && test -s out/conftest2.$ac_objext\n   then\n     # The compiler can only warn and ignore the option if not recognized\n     # So say no if there are warnings\n     $ECHO \"$_lt_compiler_boilerplate\" | $SED '/^$/d' > out/conftest.exp\n     $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2\n     if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then\n       lt_cv_prog_compiler_c_o=yes\n     fi\n   fi\n   chmod u+w . 2>&5\n   $RM conftest*\n   # SGI C++ compiler will create directory out/ii_files/ for\n   # template instantiation\n   test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files\n   $RM out/* && rmdir out\n   cd ..\n   $RM -r conftest\n   $RM conftest*\n\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o\" >&5\n$as_echo \"$lt_cv_prog_compiler_c_o\" >&6; }\n\n\n\n\nhard_links=\"nottested\"\nif test \"$lt_cv_prog_compiler_c_o\" = no && test \"$need_locks\" != no; then\n  # do not overwrite the value of need_locks provided by the user\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links\" >&5\n$as_echo_n \"checking if we can lock with hard links... \" >&6; }\n  hard_links=yes\n  $RM conftest*\n  ln conftest.a conftest.b 2>/dev/null && hard_links=no\n  touch conftest.a\n  ln conftest.a conftest.b 2>&5 || hard_links=no\n  ln conftest.a conftest.b 2>/dev/null && hard_links=no\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $hard_links\" >&5\n$as_echo \"$hard_links\" >&6; }\n  if test \"$hard_links\" = no; then\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: \\`$CC' does not support \\`-c -o', so \\`make -j' may be unsafe\" >&5\n$as_echo \"$as_me: WARNING: \\`$CC' does not support \\`-c -o', so \\`make -j' may be unsafe\" >&2;}\n    need_locks=warn\n  fi\nelse\n  need_locks=no\nfi\n\n\n\n\n\n\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries\" >&5\n$as_echo_n \"checking whether the $compiler linker ($LD) supports shared libraries... \" >&6; }\n\n  runpath_var=\n  allow_undefined_flag=\n  always_export_symbols=no\n  archive_cmds=\n  archive_expsym_cmds=\n  compiler_needs_object=no\n  enable_shared_with_static_runtimes=no\n  export_dynamic_flag_spec=\n  export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\\''s/.* //'\\'' | sort | uniq > $export_symbols'\n  hardcode_automatic=no\n  hardcode_direct=no\n  hardcode_direct_absolute=no\n  hardcode_libdir_flag_spec=\n  hardcode_libdir_flag_spec_ld=\n  hardcode_libdir_separator=\n  hardcode_minus_L=no\n  hardcode_shlibpath_var=unsupported\n  inherit_rpath=no\n  link_all_deplibs=unknown\n  module_cmds=\n  module_expsym_cmds=\n  old_archive_from_new_cmds=\n  old_archive_from_expsyms_cmds=\n  thread_safe_flag_spec=\n  whole_archive_flag_spec=\n  # include_expsyms should be a list of space-separated symbols to be *always*\n  # included in the symbol list\n  include_expsyms=\n  # exclude_expsyms can be an extended regexp of symbols to exclude\n  # it will be wrapped by ` (' and `)$', so one must not match beginning or\n  # end of line.  Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',\n  # as well as any symbol that contains `d'.\n  exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'\n  # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out\n  # platforms (ab)use it in PIC code, but their linkers get confused if\n  # the symbol is explicitly referenced.  Since portable code cannot\n  # rely on this symbol name, it's probably fine to never include it in\n  # preloaded symbol tables.\n  # Exclude shared library initialization/finalization symbols.\n  extract_expsyms_cmds=\n\n  case $host_os in\n  cygwin* | mingw* | pw32* | cegcc*)\n    # FIXME: the MSVC++ port hasn't been tested in a loooong time\n    # When not using gcc, we currently assume that we are using\n    # Microsoft Visual C++.\n    if test \"$GCC\" != yes; then\n      with_gnu_ld=no\n    fi\n    ;;\n  interix*)\n    # we just hope/assume this is gcc and not c89 (= MSVC++)\n    with_gnu_ld=yes\n    ;;\n  openbsd*)\n    with_gnu_ld=no\n    ;;\n  esac\n\n  ld_shlibs=yes\n\n  # On some targets, GNU ld is compatible enough with the native linker\n  # that we're better off using the native interface for both.\n  lt_use_gnu_ld_interface=no\n  if test \"$with_gnu_ld\" = yes; then\n    case $host_os in\n      aix*)\n\t# The AIX port of GNU ld has always aspired to compatibility\n\t# with the native linker.  However, as the warning in the GNU ld\n\t# block says, versions before 2.19.5* couldn't really create working\n\t# shared libraries, regardless of the interface used.\n\tcase `$LD -v 2>&1` in\n\t  *\\ \\(GNU\\ Binutils\\)\\ 2.19.5*) ;;\n\t  *\\ \\(GNU\\ Binutils\\)\\ 2.[2-9]*) ;;\n\t  *\\ \\(GNU\\ Binutils\\)\\ [3-9]*) ;;\n\t  *)\n\t    lt_use_gnu_ld_interface=yes\n\t    ;;\n\tesac\n\t;;\n      *)\n\tlt_use_gnu_ld_interface=yes\n\t;;\n    esac\n  fi\n\n  if test \"$lt_use_gnu_ld_interface\" = yes; then\n    # If archive_cmds runs LD, not CC, wlarc should be empty\n    wlarc='${wl}'\n\n    # Set some defaults for GNU ld with shared library support. These\n    # are reset later if shared libraries are not supported. Putting them\n    # here allows them to be overridden if necessary.\n    runpath_var=LD_RUN_PATH\n    hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'\n    export_dynamic_flag_spec='${wl}--export-dynamic'\n    # ancient GNU ld didn't support --whole-archive et. al.\n    if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then\n      whole_archive_flag_spec=\"$wlarc\"'--whole-archive$convenience '\"$wlarc\"'--no-whole-archive'\n    else\n      whole_archive_flag_spec=\n    fi\n    supports_anon_versioning=no\n    case `$LD -v 2>&1` in\n      *GNU\\ gold*) supports_anon_versioning=yes ;;\n      *\\ [01].* | *\\ 2.[0-9].* | *\\ 2.10.*) ;; # catch versions < 2.11\n      *\\ 2.11.93.0.2\\ *) supports_anon_versioning=yes ;; # RH7.3 ...\n      *\\ 2.11.92.0.12\\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...\n      *\\ 2.11.*) ;; # other 2.11 versions\n      *) supports_anon_versioning=yes ;;\n    esac\n\n    # See if GNU ld supports shared libraries.\n    case $host_os in\n    aix[3-9]*)\n      # On AIX/PPC, the GNU linker is very broken\n      if test \"$host_cpu\" != ia64; then\n\tld_shlibs=no\n\tcat <<_LT_EOF 1>&2\n\n*** Warning: the GNU linker, at least up to release 2.19, is reported\n*** to be unable to reliably create shared libraries on AIX.\n*** Therefore, libtool is disabling shared libraries support.  If you\n*** really care for shared libraries, you may want to install binutils\n*** 2.20 or above, or modify your PATH so that a non-GNU linker is found.\n*** You will then need to restart the configuration process.\n\n_LT_EOF\n      fi\n      ;;\n\n    amigaos*)\n      case $host_cpu in\n      powerpc)\n            # see comment about AmigaOS4 .so support\n            archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'\n            archive_expsym_cmds=''\n        ;;\n      m68k)\n            archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO \"#define NAME $libname\" > $output_objdir/a2ixlibrary.data~$ECHO \"#define LIBRARY_ID 1\" >> $output_objdir/a2ixlibrary.data~$ECHO \"#define VERSION $major\" >> $output_objdir/a2ixlibrary.data~$ECHO \"#define REVISION $revision\" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'\n            hardcode_libdir_flag_spec='-L$libdir'\n            hardcode_minus_L=yes\n        ;;\n      esac\n      ;;\n\n    beos*)\n      if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then\n\tallow_undefined_flag=unsupported\n\t# Joseph Beckenbach <jrb3@best.com> says some releases of gcc\n\t# support --undefined.  This deserves some investigation.  FIXME\n\tarchive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'\n      else\n\tld_shlibs=no\n      fi\n      ;;\n\n    cygwin* | mingw* | pw32* | cegcc*)\n      # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless,\n      # as there is no search path for DLLs.\n      hardcode_libdir_flag_spec='-L$libdir'\n      export_dynamic_flag_spec='${wl}--export-all-symbols'\n      allow_undefined_flag=unsupported\n      always_export_symbols=no\n      enable_shared_with_static_runtimes=yes\n      export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\\''/^[BCDGRS][ ]/s/.*[ ]\\([^ ]*\\)/\\1 DATA/'\\'' | $SED -e '\\''/^[AITW][ ]/s/.*[ ]//'\\'' | sort | uniq > $export_symbols'\n\n      if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then\n        archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'\n\t# If the export-symbols file already is a .def file (1st line\n\t# is EXPORTS), use it as is; otherwise, prepend...\n\tarchive_expsym_cmds='if test \"x`$SED 1q $export_symbols`\" = xEXPORTS; then\n\t  cp $export_symbols $output_objdir/$soname.def;\n\telse\n\t  echo EXPORTS > $output_objdir/$soname.def;\n\t  cat $export_symbols >> $output_objdir/$soname.def;\n\tfi~\n\t$CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'\n      else\n\tld_shlibs=no\n      fi\n      ;;\n\n    haiku*)\n      archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'\n      link_all_deplibs=yes\n      ;;\n\n    interix[3-9]*)\n      hardcode_direct=no\n      hardcode_shlibpath_var=no\n      hardcode_libdir_flag_spec='${wl}-rpath,$libdir'\n      export_dynamic_flag_spec='${wl}-E'\n      # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.\n      # Instead, shared libraries are loaded at an image base (0x10000000 by\n      # default) and relocated if they conflict, which is a slow very memory\n      # consuming and fragmenting process.  To avoid this, we pick a random,\n      # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link\n      # time.  Moving up from 0x10000000 also allows more sbrk(2) space.\n      archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \\* 262144 + 1342177280` -o $lib'\n      archive_expsym_cmds='sed \"s,^,_,\" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \\* 262144 + 1342177280` -o $lib'\n      ;;\n\n    gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu | uclinuxfdpiceabi)\n      tmp_diet=no\n      if test \"$host_os\" = linux-dietlibc; then\n\tcase $cc_basename in\n\t  diet\\ *) tmp_diet=yes;;\t# linux-dietlibc with static linking (!diet-dyn)\n\tesac\n      fi\n      if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \\\n\t && test \"$tmp_diet\" = no\n      then\n\ttmp_addflag=' $pic_flag'\n\ttmp_sharedflag='-shared'\n\tcase $cc_basename,$host_cpu in\n        pgcc*)\t\t\t\t# Portland Group C compiler\n\t  whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\\\"\\\"; do test  -n \\\"$conv\\\" && new_convenience=\\\"$new_convenience,$conv\\\"; done; func_echo_all \\\"$new_convenience\\\"` ${wl}--no-whole-archive'\n\t  tmp_addflag=' $pic_flag'\n\t  ;;\n\tpgf77* | pgf90* | pgf95* | pgfortran*)\n\t\t\t\t\t# Portland Group f77 and f90 compilers\n\t  whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\\\"\\\"; do test  -n \\\"$conv\\\" && new_convenience=\\\"$new_convenience,$conv\\\"; done; func_echo_all \\\"$new_convenience\\\"` ${wl}--no-whole-archive'\n\t  tmp_addflag=' $pic_flag -Mnomain' ;;\n\tecc*,ia64* | icc*,ia64*)\t# Intel C compiler on ia64\n\t  tmp_addflag=' -i_dynamic' ;;\n\tefc*,ia64* | ifort*,ia64*)\t# Intel Fortran compiler on ia64\n\t  tmp_addflag=' -i_dynamic -nofor_main' ;;\n\tifc* | ifort*)\t\t\t# Intel Fortran compiler\n\t  tmp_addflag=' -nofor_main' ;;\n\tlf95*)\t\t\t\t# Lahey Fortran 8.1\n\t  whole_archive_flag_spec=\n\t  tmp_sharedflag='--shared' ;;\n\txl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below)\n\t  tmp_sharedflag='-qmkshrobj'\n\t  tmp_addflag= ;;\n\tnvcc*)\t# Cuda Compiler Driver 2.2\n\t  whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\\\"\\\"; do test  -n \\\"$conv\\\" && new_convenience=\\\"$new_convenience,$conv\\\"; done; func_echo_all \\\"$new_convenience\\\"` ${wl}--no-whole-archive'\n\t  compiler_needs_object=yes\n\t  ;;\n\tesac\n\tcase `$CC -V 2>&1 | sed 5q` in\n\t*Sun\\ C*)\t\t\t# Sun C 5.9\n\t  whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\\\"\\\"; do test -z \\\"$conv\\\" || new_convenience=\\\"$new_convenience,$conv\\\"; done; func_echo_all \\\"$new_convenience\\\"` ${wl}--no-whole-archive'\n\t  compiler_needs_object=yes\n\t  tmp_sharedflag='-G' ;;\n\t*Sun\\ F*)\t\t\t# Sun Fortran 8.3\n\t  tmp_sharedflag='-G' ;;\n\tesac\n\tarchive_cmds='$CC '\"$tmp_sharedflag\"\"$tmp_addflag\"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'\n\n        if test \"x$supports_anon_versioning\" = xyes; then\n          archive_expsym_cmds='echo \"{ global:\" > $output_objdir/$libname.ver~\n\t    cat $export_symbols | sed -e \"s/\\(.*\\)/\\1;/\" >> $output_objdir/$libname.ver~\n\t    echo \"local: *; };\" >> $output_objdir/$libname.ver~\n\t    $CC '\"$tmp_sharedflag\"\"$tmp_addflag\"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'\n        fi\n\n\tcase $cc_basename in\n\txlf* | bgf* | bgxlf* | mpixlf*)\n\t  # IBM XL Fortran 10.1 on PPC cannot create shared libs itself\n\t  whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive'\n\t  hardcode_libdir_flag_spec=\n\t  hardcode_libdir_flag_spec_ld='-rpath $libdir'\n\t  archive_cmds='$LD -shared $libobjs $deplibs $compiler_flags -soname $soname -o $lib'\n\t  if test \"x$supports_anon_versioning\" = xyes; then\n\t    archive_expsym_cmds='echo \"{ global:\" > $output_objdir/$libname.ver~\n\t      cat $export_symbols | sed -e \"s/\\(.*\\)/\\1;/\" >> $output_objdir/$libname.ver~\n\t      echo \"local: *; };\" >> $output_objdir/$libname.ver~\n\t      $LD -shared $libobjs $deplibs $compiler_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib'\n\t  fi\n\t  ;;\n\tesac\n      else\n        ld_shlibs=no\n      fi\n      ;;\n\n    netbsd*)\n      if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then\n\tarchive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'\n\twlarc=\n      else\n\tarchive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'\n\tarchive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'\n      fi\n      ;;\n\n    solaris*)\n      if $LD -v 2>&1 | $GREP 'BFD 2\\.8' > /dev/null; then\n\tld_shlibs=no\n\tcat <<_LT_EOF 1>&2\n\n*** Warning: The releases 2.8.* of the GNU linker cannot reliably\n*** create shared libraries on Solaris systems.  Therefore, libtool\n*** is disabling shared libraries support.  We urge you to upgrade GNU\n*** binutils to release 2.9.1 or newer.  Another option is to modify\n*** your PATH or compiler configuration so that the native linker is\n*** used, and then restart.\n\n_LT_EOF\n      elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then\n\tarchive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'\n\tarchive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'\n      else\n\tld_shlibs=no\n      fi\n      ;;\n\n    sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)\n      case `$LD -v 2>&1` in\n        *\\ [01].* | *\\ 2.[0-9].* | *\\ 2.1[0-5].*)\n\tld_shlibs=no\n\tcat <<_LT_EOF 1>&2\n\n*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not\n*** reliably create shared libraries on SCO systems.  Therefore, libtool\n*** is disabling shared libraries support.  We urge you to upgrade GNU\n*** binutils to release 2.16.91.0.3 or newer.  Another option is to modify\n*** your PATH or compiler configuration so that the native linker is\n*** used, and then restart.\n\n_LT_EOF\n\t;;\n\t*)\n\t  # For security reasons, it is highly recommended that you always\n\t  # use absolute paths for naming shared libraries, and exclude the\n\t  # DT_RUNPATH tag from executables and libraries.  But doing so\n\t  # requires that you compile everything twice, which is a pain.\n\t  if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then\n\t    hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'\n\t    archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'\n\t    archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'\n\t  else\n\t    ld_shlibs=no\n\t  fi\n\t;;\n      esac\n      ;;\n\n    sunos4*)\n      archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'\n      wlarc=\n      hardcode_direct=yes\n      hardcode_shlibpath_var=no\n      ;;\n\n    *)\n      if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then\n\tarchive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'\n\tarchive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'\n      else\n\tld_shlibs=no\n      fi\n      ;;\n    esac\n\n    if test \"$ld_shlibs\" = no; then\n      runpath_var=\n      hardcode_libdir_flag_spec=\n      export_dynamic_flag_spec=\n      whole_archive_flag_spec=\n    fi\n  else\n    # PORTME fill in a description of your system's linker (not GNU ld)\n    case $host_os in\n    aix3*)\n      allow_undefined_flag=unsupported\n      always_export_symbols=yes\n      archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'\n      # Note: this linker hardcodes the directories in LIBPATH if there\n      # are no directories specified by -L.\n      hardcode_minus_L=yes\n      if test \"$GCC\" = yes && test -z \"$lt_prog_compiler_static\"; then\n\t# Neither direct hardcoding nor static linking is supported with a\n\t# broken collect2.\n\thardcode_direct=unsupported\n      fi\n      ;;\n\n    aix[4-9]*)\n      if test \"$host_cpu\" = ia64; then\n\t# On IA64, the linker does run time linking by default, so we don't\n\t# have to do anything special.\n\taix_use_runtimelinking=no\n\texp_sym_flag='-Bexport'\n\tno_entry_flag=\"\"\n      else\n\t# If we're using GNU nm, then we don't want the \"-C\" option.\n\t# -C means demangle to AIX nm, but means don't demangle with GNU nm\n\t# Also, AIX nm treats weak defined symbols like other global\n\t# defined symbols, whereas GNU nm marks them as \"W\".\n\tif $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then\n\t  export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\\''{ if (((\\$ 2 == \"T\") || (\\$ 2 == \"D\") || (\\$ 2 == \"B\") || (\\$ 2 == \"W\")) && (substr(\\$ 3,1,1) != \".\")) { print \\$ 3 } }'\\'' | sort -u > $export_symbols'\n\telse\n\t  export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\\''{ if (((\\$ 2 == \"T\") || (\\$ 2 == \"D\") || (\\$ 2 == \"B\") || (\\$ 2 == \"L\")) && (substr(\\$ 3,1,1) != \".\")) { print \\$ 3 } }'\\'' | sort -u > $export_symbols'\n\tfi\n\taix_use_runtimelinking=no\n\n\t# Test if we are trying to use run time linking or normal\n\t# AIX style linking. If -brtl is somewhere in LDFLAGS, we\n\t# need to do runtime linking.\n\tcase $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*)\n\t  for ld_flag in $LDFLAGS; do\n\t  if (test $ld_flag = \"-brtl\" || test $ld_flag = \"-Wl,-brtl\"); then\n\t    aix_use_runtimelinking=yes\n\t    break\n\t  fi\n\t  done\n\t  ;;\n\tesac\n\n\texp_sym_flag='-bexport'\n\tno_entry_flag='-bnoentry'\n      fi\n\n      # When large executables or shared objects are built, AIX ld can\n      # have problems creating the table of contents.  If linking a library\n      # or program results in \"error TOC overflow\" add -mminimal-toc to\n      # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not\n      # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.\n\n      archive_cmds=''\n      hardcode_direct=yes\n      hardcode_direct_absolute=yes\n      hardcode_libdir_separator=':'\n      link_all_deplibs=yes\n      file_list_spec='${wl}-f,'\n\n      if test \"$GCC\" = yes; then\n\tcase $host_os in aix4.[012]|aix4.[012].*)\n\t# We only want to do this on AIX 4.2 and lower, the check\n\t# below for broken collect2 doesn't work under 4.3+\n\t  collect2name=`${CC} -print-prog-name=collect2`\n\t  if test -f \"$collect2name\" &&\n\t   strings \"$collect2name\" | $GREP resolve_lib_name >/dev/null\n\t  then\n\t  # We have reworked collect2\n\t  :\n\t  else\n\t  # We have old collect2\n\t  hardcode_direct=unsupported\n\t  # It fails to find uninstalled libraries when the uninstalled\n\t  # path is not listed in the libpath.  Setting hardcode_minus_L\n\t  # to unsupported forces relinking\n\t  hardcode_minus_L=yes\n\t  hardcode_libdir_flag_spec='-L$libdir'\n\t  hardcode_libdir_separator=\n\t  fi\n\t  ;;\n\tesac\n\tshared_flag='-shared'\n\tif test \"$aix_use_runtimelinking\" = yes; then\n\t  shared_flag=\"$shared_flag \"'${wl}-G'\n\tfi\n      else\n\t# not using gcc\n\tif test \"$host_cpu\" = ia64; then\n\t# VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release\n\t# chokes on -Wl,-G. The following line is correct:\n\t  shared_flag='-G'\n\telse\n\t  if test \"$aix_use_runtimelinking\" = yes; then\n\t    shared_flag='${wl}-G'\n\t  else\n\t    shared_flag='${wl}-bM:SRE'\n\t  fi\n\tfi\n      fi\n\n      export_dynamic_flag_spec='${wl}-bexpall'\n      # It seems that -bexpall does not export symbols beginning with\n      # underscore (_), so it is better to generate a list of symbols to export.\n      always_export_symbols=yes\n      if test \"$aix_use_runtimelinking\" = yes; then\n\t# Warning - without using the other runtime loading flags (-brtl),\n\t# -berok will link without error, but may produce a broken library.\n\tallow_undefined_flag='-berok'\n        # Determine the default libpath from the value encoded in an\n        # empty executable.\n        cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain ()\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n\nlt_aix_libpath_sed='\n    /Import File Strings/,/^$/ {\n\t/^0/ {\n\t    s/^0  *\\(.*\\)$/\\1/\n\t    p\n\t}\n    }'\naix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e \"$lt_aix_libpath_sed\"`\n# Check for a 64-bit object if we didn't find anything.\nif test -z \"$aix_libpath\"; then\n  aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e \"$lt_aix_libpath_sed\"`\nfi\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nif test -z \"$aix_libpath\"; then aix_libpath=\"/usr/lib:/lib\"; fi\n\n        hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'\"$aix_libpath\"\n        archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs '\"\\${wl}$no_entry_flag\"' $compiler_flags `if test \"x${allow_undefined_flag}\" != \"x\"; then func_echo_all \"${wl}${allow_undefined_flag}\"; else :; fi` '\"\\${wl}$exp_sym_flag:\\$export_symbols $shared_flag\"\n      else\n\tif test \"$host_cpu\" = ia64; then\n\t  hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib'\n\t  allow_undefined_flag=\"-z nodefs\"\n\t  archive_expsym_cmds=\"\\$CC $shared_flag\"' -o $output_objdir/$soname $libobjs $deplibs '\"\\${wl}$no_entry_flag\"' $compiler_flags ${wl}${allow_undefined_flag} '\"\\${wl}$exp_sym_flag:\\$export_symbols\"\n\telse\n\t # Determine the default libpath from the value encoded in an\n\t # empty executable.\n\t cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain ()\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n\nlt_aix_libpath_sed='\n    /Import File Strings/,/^$/ {\n\t/^0/ {\n\t    s/^0  *\\(.*\\)$/\\1/\n\t    p\n\t}\n    }'\naix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e \"$lt_aix_libpath_sed\"`\n# Check for a 64-bit object if we didn't find anything.\nif test -z \"$aix_libpath\"; then\n  aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e \"$lt_aix_libpath_sed\"`\nfi\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nif test -z \"$aix_libpath\"; then aix_libpath=\"/usr/lib:/lib\"; fi\n\n\t hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'\"$aix_libpath\"\n\t  # Warning - without using the other run time loading flags,\n\t  # -berok will link without error, but may produce a broken library.\n\t  no_undefined_flag=' ${wl}-bernotok'\n\t  allow_undefined_flag=' ${wl}-berok'\n\t  if test \"$with_gnu_ld\" = yes; then\n\t    # We only use this code for GNU lds that support --whole-archive.\n\t    whole_archive_flag_spec='${wl}--whole-archive$convenience ${wl}--no-whole-archive'\n\t  else\n\t    # Exported symbols can be pulled into shared objects from archives\n\t    whole_archive_flag_spec='$convenience'\n\t  fi\n\t  archive_cmds_need_lc=yes\n\t  # This is similar to how AIX traditionally builds its shared libraries.\n\t  archive_expsym_cmds=\"\\$CC $shared_flag\"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'\n\tfi\n      fi\n      ;;\n\n    amigaos*)\n      case $host_cpu in\n      powerpc)\n            # see comment about AmigaOS4 .so support\n            archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'\n            archive_expsym_cmds=''\n        ;;\n      m68k)\n            archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO \"#define NAME $libname\" > $output_objdir/a2ixlibrary.data~$ECHO \"#define LIBRARY_ID 1\" >> $output_objdir/a2ixlibrary.data~$ECHO \"#define VERSION $major\" >> $output_objdir/a2ixlibrary.data~$ECHO \"#define REVISION $revision\" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'\n            hardcode_libdir_flag_spec='-L$libdir'\n            hardcode_minus_L=yes\n        ;;\n      esac\n      ;;\n\n    bsdi[45]*)\n      export_dynamic_flag_spec=-rdynamic\n      ;;\n\n    cygwin* | mingw* | pw32* | cegcc*)\n      # When not using gcc, we currently assume that we are using\n      # Microsoft Visual C++.\n      # hardcode_libdir_flag_spec is actually meaningless, as there is\n      # no search path for DLLs.\n      hardcode_libdir_flag_spec=' '\n      allow_undefined_flag=unsupported\n      # Tell ltmain to make .lib files, not .a files.\n      libext=lib\n      # Tell ltmain to make .dll files, not .so files.\n      shrext_cmds=\".dll\"\n      # FIXME: Setting linknames here is a bad hack.\n      archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all \"$deplibs\" | $SED '\\''s/ -lc$//'\\''` -link -dll~linknames='\n      # The linker will automatically build a .lib file if we build a DLL.\n      old_archive_from_new_cmds='true'\n      # FIXME: Should let the user specify the lib program.\n      old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs'\n      fix_srcfile_path='`cygpath -w \"$srcfile\"`'\n      enable_shared_with_static_runtimes=yes\n      ;;\n\n    darwin* | rhapsody*)\n\n\n\n  # Publish an arg to allow the user to select that Darwin host (and target)\n  # libraries should be given install-names like @rpath/libfoo.dylib.  This\n  # requires that the user of the library then adds an 'rpath' to the DSO that\n  # needs access.\n  # NOTE: there are defaults below, for systems that support rpaths.  The person\n  # configuring can override the defaults for any system version that supports\n  # them - they are, however, forced off for system versions without support.\n  # Check whether --enable-darwin-at-rpath was given.\nif test \"${enable_darwin_at_rpath+set}\" = set; then :\n  enableval=$enable_darwin_at_rpath; if test \"x$enable_darwin_at_rpath\" = \"xyes\"; then\n    # This is not supported before macOS 10.5 / Darwin9.\n    case ${MACOSX_DEPLOYMENT_TARGET-UNSET},$host_os in\n      UNSET,darwin[4-8]*|UNSET,rhapsody*|10.[0-4][,.]*)\n\t{ $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: Darwin @rpath library names are incompatible with OSX versions earlier than 10.5 (rpaths disabled)\" >&5\n$as_echo \"$as_me: WARNING: Darwin @rpath library names are incompatible with OSX versions earlier than 10.5 (rpaths disabled)\" >&2;}\n\tenable_darwin_at_rpath=no\n      ;;\n    esac\n   fi\nelse\n  case ${MACOSX_DEPLOYMENT_TARGET-UNSET},$host_os in\n    # As above, before 10.5 / Darwin9 this does not work.\n     UNSET,darwin[4-8]*|UNSET,rhapsody*|10.[0-4][,.]*)\n       enable_darwin_at_rpath=no\n       ;;\n\n    # We cannot build and test reliably on macOS 10.11+ (Darwin15+) without use\n    # of rpaths, since runpaths set via DYLD_LIBRARY_PATH are elided by key\n    # system executables (e.g. /bin/sh).  Force rpaths on for these systems.\n      UNSET,darwin1[5-9]*|UNSET,darwin2*|10.1[1-9][,.]*|1[1-9].*[,.]* )\n      { $as_echo \"$as_me:${as_lineno-$LINENO}: @rpath library names are needed on macOS versions later than 10.11 (rpaths have been enabled)\" >&5\n$as_echo \"$as_me: @rpath library names are needed on macOS versions later than 10.11 (rpaths have been enabled)\" >&6;}\n      enable_darwin_at_rpath=yes\n      ;;\n    # NOTE: we are not (yet) doing anything for 10.5 .. 10.10, since they can\n    # work with either DYLD_LIBRARY_PATH or embedded rpaths.\n\n    esac\n\nfi\n\n\n  archive_cmds_need_lc=no\n  hardcode_direct=no\n  hardcode_automatic=yes\n  hardcode_shlibpath_var=unsupported\n  if test \"$lt_cv_ld_force_load\" = \"yes\"; then\n    whole_archive_flag_spec='`for conv in $convenience\\\"\\\"; do test  -n \\\"$conv\\\" && new_convenience=\\\"$new_convenience ${wl}-force_load,$conv\\\"; done; func_echo_all \\\"$new_convenience\\\"`'\n  else\n    whole_archive_flag_spec=''\n  fi\n  link_all_deplibs=yes\n  allow_undefined_flag=\"$_lt_dar_allow_undefined\"\n  case $cc_basename in\n     ifort*) _lt_dar_can_shared=yes ;;\n     *) _lt_dar_can_shared=$GCC ;;\n  esac\n  if test \"$_lt_dar_can_shared\" = \"yes\"; then\n    output_verbose_link_cmd=func_echo_all\n    _lt_install_name='\\$rpath/\\$soname'\n    if test \"x$enable_darwin_at_rpath\" = \"xyes\"; then\n      _lt_install_name='@rpath/\\$soname'\n    fi\n    archive_cmds=\"\\$CC -dynamiclib \\$allow_undefined_flag -o \\$lib \\$libobjs \\$deplibs \\$compiler_flags -install_name ${_lt_install_name} \\$verstring ${_lt_dsymutil}\"\n    module_cmds=\"\\$CC \\$allow_undefined_flag -o \\$lib -bundle \\$libobjs \\$deplibs \\$compiler_flags${_lt_dsymutil}\"\n    archive_expsym_cmds=\"sed 's,^,_,' < \\$export_symbols > \\$output_objdir/\\${libname}-symbols.expsym~\\$CC -dynamiclib \\$allow_undefined_flag -o \\$lib \\$libobjs \\$deplibs \\$compiler_flags -install_name ${_lt_install_name} \\$verstring ${_lt_dar_export_syms}${_lt_dsymutil}\"\n    module_expsym_cmds=\"sed -e 's,^,_,' < \\$export_symbols > \\$output_objdir/\\${libname}-symbols.expsym~\\$CC \\$allow_undefined_flag -o \\$lib -bundle \\$libobjs \\$deplibs \\$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}\"\n\n  else\n  ld_shlibs=no\n  fi\n\n      ;;\n\n    dgux*)\n      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'\n      hardcode_libdir_flag_spec='-L$libdir'\n      hardcode_shlibpath_var=no\n      ;;\n\n    # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor\n    # support.  Future versions do this automatically, but an explicit c++rt0.o\n    # does not break anything, and helps significantly (at the cost of a little\n    # extra space).\n    freebsd2.2*)\n      archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'\n      hardcode_libdir_flag_spec='-R$libdir'\n      hardcode_direct=yes\n      hardcode_shlibpath_var=no\n      ;;\n\n    # Unfortunately, older versions of FreeBSD 2 do not have this feature.\n    freebsd2.*)\n      archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'\n      hardcode_direct=yes\n      hardcode_minus_L=yes\n      hardcode_shlibpath_var=no\n      ;;\n\n    # FreeBSD 3 and greater uses gcc -shared to do shared libraries.\n    freebsd* | dragonfly*)\n      archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'\n      hardcode_libdir_flag_spec='-R$libdir'\n      hardcode_direct=yes\n      hardcode_shlibpath_var=no\n      ;;\n\n    hpux9*)\n      if test \"$GCC\" = yes; then\n\tarchive_cmds='$RM $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'\n      else\n\tarchive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'\n      fi\n      hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'\n      hardcode_libdir_separator=:\n      hardcode_direct=yes\n\n      # hardcode_minus_L: Not really in the search PATH,\n      # but as the default location of the library.\n      hardcode_minus_L=yes\n      export_dynamic_flag_spec='${wl}-E'\n      ;;\n\n    hpux10*)\n      if test \"$GCC\" = yes && test \"$with_gnu_ld\" = no; then\n\tarchive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'\n      else\n\tarchive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'\n      fi\n      if test \"$with_gnu_ld\" = no; then\n\thardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'\n\thardcode_libdir_flag_spec_ld='+b $libdir'\n\thardcode_libdir_separator=:\n\thardcode_direct=yes\n\thardcode_direct_absolute=yes\n\texport_dynamic_flag_spec='${wl}-E'\n\t# hardcode_minus_L: Not really in the search PATH,\n\t# but as the default location of the library.\n\thardcode_minus_L=yes\n      fi\n      ;;\n\n    hpux11*)\n      if test \"$GCC\" = yes && test \"$with_gnu_ld\" = no; then\n\tcase $host_cpu in\n\thppa*64*)\n\t  archive_cmds='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'\n\t  ;;\n\tia64*)\n\t  archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'\n\t  ;;\n\t*)\n\t  archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'\n\t  ;;\n\tesac\n      else\n\tcase $host_cpu in\n\thppa*64*)\n\t  archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'\n\t  ;;\n\tia64*)\n\t  archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'\n\t  ;;\n\t*)\n\n\t  # Older versions of the 11.00 compiler do not understand -b yet\n\t  # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does)\n\t  { $as_echo \"$as_me:${as_lineno-$LINENO}: checking if $CC understands -b\" >&5\n$as_echo_n \"checking if $CC understands -b... \" >&6; }\nif ${lt_cv_prog_compiler__b+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  lt_cv_prog_compiler__b=no\n   save_LDFLAGS=\"$LDFLAGS\"\n   LDFLAGS=\"$LDFLAGS -b\"\n   echo \"$lt_simple_link_test_code\" > conftest.$ac_ext\n   if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then\n     # The linker can only warn and ignore the option if not recognized\n     # So say no if there are warnings\n     if test -s conftest.err; then\n       # Append any errors to the config.log.\n       cat conftest.err 1>&5\n       $ECHO \"$_lt_linker_boilerplate\" | $SED '/^$/d' > conftest.exp\n       $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2\n       if diff conftest.exp conftest.er2 >/dev/null; then\n         lt_cv_prog_compiler__b=yes\n       fi\n     else\n       lt_cv_prog_compiler__b=yes\n     fi\n   fi\n   $RM -r conftest*\n   LDFLAGS=\"$save_LDFLAGS\"\n\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b\" >&5\n$as_echo \"$lt_cv_prog_compiler__b\" >&6; }\n\nif test x\"$lt_cv_prog_compiler__b\" = xyes; then\n    archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'\nelse\n    archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'\nfi\n\n\t  ;;\n\tesac\n      fi\n      if test \"$with_gnu_ld\" = no; then\n\thardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'\n\thardcode_libdir_separator=:\n\n\tcase $host_cpu in\n\thppa*64*|ia64*)\n\t  hardcode_direct=no\n\t  hardcode_shlibpath_var=no\n\t  ;;\n\t*)\n\t  hardcode_direct=yes\n\t  hardcode_direct_absolute=yes\n\t  export_dynamic_flag_spec='${wl}-E'\n\n\t  # hardcode_minus_L: Not really in the search PATH,\n\t  # but as the default location of the library.\n\t  hardcode_minus_L=yes\n\t  ;;\n\tesac\n      fi\n      ;;\n\n    irix5* | irix6* | nonstopux*)\n      if test \"$GCC\" = yes; then\n\tarchive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n \"$verstring\" && func_echo_all \"${wl}-set_version ${wl}$verstring\"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'\n\t# Try to use the -exported_symbol ld option, if it does not\n\t# work, assume that -exports_file does not work either and\n\t# implicitly export all symbols.\n        save_LDFLAGS=\"$LDFLAGS\"\n        LDFLAGS=\"$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null\"\n        cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\nint foo(void) {}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n \"$verstring\" && func_echo_all \"${wl}-set_version ${wl}$verstring\"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib'\n\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\n        LDFLAGS=\"$save_LDFLAGS\"\n      else\n\tarchive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n \"$verstring\" && func_echo_all \"-set_version $verstring\"` -update_registry ${output_objdir}/so_locations -o $lib'\n\tarchive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n \"$verstring\" && func_echo_all \"-set_version $verstring\"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib'\n      fi\n      archive_cmds_need_lc='no'\n      hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'\n      hardcode_libdir_separator=:\n      inherit_rpath=yes\n      link_all_deplibs=yes\n      ;;\n\n    netbsd*)\n      if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then\n\tarchive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'  # a.out\n      else\n\tarchive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags'      # ELF\n      fi\n      hardcode_libdir_flag_spec='-R$libdir'\n      hardcode_direct=yes\n      hardcode_shlibpath_var=no\n      ;;\n\n    newsos6)\n      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'\n      hardcode_direct=yes\n      hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'\n      hardcode_libdir_separator=:\n      hardcode_shlibpath_var=no\n      ;;\n\n    *nto* | *qnx*)\n      ;;\n\n    openbsd*)\n      if test -f /usr/libexec/ld.so; then\n\thardcode_direct=yes\n\thardcode_shlibpath_var=no\n\thardcode_direct_absolute=yes\n\tif test -z \"`echo __ELF__ | $CC -E - | $GREP __ELF__`\" || test \"$host_os-$host_cpu\" = \"openbsd2.8-powerpc\"; then\n\t  archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'\n\t  archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'\n\t  hardcode_libdir_flag_spec='${wl}-rpath,$libdir'\n\t  export_dynamic_flag_spec='${wl}-E'\n\telse\n\t  case $host_os in\n\t   openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)\n\t     archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'\n\t     hardcode_libdir_flag_spec='-R$libdir'\n\t     ;;\n\t   *)\n\t     archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'\n\t     hardcode_libdir_flag_spec='${wl}-rpath,$libdir'\n\t     ;;\n\t  esac\n\tfi\n      else\n\tld_shlibs=no\n      fi\n      ;;\n\n    os2*)\n      hardcode_libdir_flag_spec='-L$libdir'\n      hardcode_minus_L=yes\n      allow_undefined_flag=unsupported\n      archive_cmds='$ECHO \"LIBRARY $libname INITINSTANCE\" > $output_objdir/$libname.def~$ECHO \"DESCRIPTION \\\"$libname\\\"\" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo \" SINGLE NONSHARED\" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'\n      old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'\n      ;;\n\n    osf3*)\n      if test \"$GCC\" = yes; then\n\tallow_undefined_flag=' ${wl}-expect_unresolved ${wl}\\*'\n\tarchive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n \"$verstring\" && func_echo_all \"${wl}-set_version ${wl}$verstring\"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'\n      else\n\tallow_undefined_flag=' -expect_unresolved \\*'\n\tarchive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n \"$verstring\" && func_echo_all \"-set_version $verstring\"` -update_registry ${output_objdir}/so_locations -o $lib'\n      fi\n      archive_cmds_need_lc='no'\n      hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'\n      hardcode_libdir_separator=:\n      ;;\n\n    osf4* | osf5*)\t# as osf3* with the addition of -msym flag\n      if test \"$GCC\" = yes; then\n\tallow_undefined_flag=' ${wl}-expect_unresolved ${wl}\\*'\n\tarchive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n \"$verstring\" && func_echo_all \"${wl}-set_version ${wl}$verstring\"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'\n\thardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'\n      else\n\tallow_undefined_flag=' -expect_unresolved \\*'\n\tarchive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n \"$verstring\" && func_echo_all \"-set_version $verstring\"` -update_registry ${output_objdir}/so_locations -o $lib'\n\tarchive_expsym_cmds='for i in `cat $export_symbols`; do printf \"%s %s\\\\n\" -exported_symbol \"\\$i\" >> $lib.exp; done; printf \"%s\\\\n\" \"-hidden\">> $lib.exp~\n\t$CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n \"$verstring\" && $ECHO \"-set_version $verstring\"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp'\n\n\t# Both c and cxx compiler support -rpath directly\n\thardcode_libdir_flag_spec='-rpath $libdir'\n      fi\n      archive_cmds_need_lc='no'\n      hardcode_libdir_separator=:\n      ;;\n\n    solaris*)\n      no_undefined_flag=' -z defs'\n      if test \"$GCC\" = yes; then\n\twlarc='${wl}'\n\tarchive_cmds='$CC -shared ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'\n\tarchive_expsym_cmds='echo \"{ global:\" > $lib.exp~cat $export_symbols | $SED -e \"s/\\(.*\\)/\\1;/\" >> $lib.exp~echo \"local: *; };\" >> $lib.exp~\n\t  $CC -shared ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'\n      else\n\tcase `$CC -V 2>&1` in\n\t*\"Compilers 5.0\"*)\n\t  wlarc=''\n\t  archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'\n\t  archive_expsym_cmds='echo \"{ global:\" > $lib.exp~cat $export_symbols | $SED -e \"s/\\(.*\\)/\\1;/\" >> $lib.exp~echo \"local: *; };\" >> $lib.exp~\n\t  $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp'\n\t  ;;\n\t*)\n\t  wlarc='${wl}'\n\t  archive_cmds='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags'\n\t  archive_expsym_cmds='echo \"{ global:\" > $lib.exp~cat $export_symbols | $SED -e \"s/\\(.*\\)/\\1;/\" >> $lib.exp~echo \"local: *; };\" >> $lib.exp~\n\t  $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'\n\t  ;;\n\tesac\n      fi\n      hardcode_libdir_flag_spec='-R$libdir'\n      hardcode_shlibpath_var=no\n      case $host_os in\n      solaris2.[0-5] | solaris2.[0-5].*) ;;\n      *)\n\t# The compiler driver will combine and reorder linker options,\n\t# but understands `-z linker_flag'.  GCC discards it without `$wl',\n\t# but is careful enough not to reorder.\n\t# Supported since Solaris 2.6 (maybe 2.5.1?)\n\tif test \"$GCC\" = yes; then\n\t  whole_archive_flag_spec='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'\n\telse\n\t  whole_archive_flag_spec='-z allextract$convenience -z defaultextract'\n\tfi\n\t;;\n      esac\n      link_all_deplibs=yes\n      ;;\n\n    sunos4*)\n      if test \"x$host_vendor\" = xsequent; then\n\t# Use $CC to link under sequent, because it throws in some extra .o\n\t# files that make .init and .fini sections work.\n\tarchive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'\n      else\n\tarchive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'\n      fi\n      hardcode_libdir_flag_spec='-L$libdir'\n      hardcode_direct=yes\n      hardcode_minus_L=yes\n      hardcode_shlibpath_var=no\n      ;;\n\n    sysv4)\n      case $host_vendor in\n\tsni)\n\t  archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'\n\t  hardcode_direct=yes # is this really true???\n\t;;\n\tsiemens)\n\t  ## LD is ld it makes a PLAMLIB\n\t  ## CC just makes a GrossModule.\n\t  archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags'\n\t  reload_cmds='$CC -r -o $output$reload_objs'\n\t  hardcode_direct=no\n        ;;\n\tmotorola)\n\t  archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'\n\t  hardcode_direct=no #Motorola manual says yes, but my tests say they lie\n\t;;\n      esac\n      runpath_var='LD_RUN_PATH'\n      hardcode_shlibpath_var=no\n      ;;\n\n    sysv4.3*)\n      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'\n      hardcode_shlibpath_var=no\n      export_dynamic_flag_spec='-Bexport'\n      ;;\n\n    sysv4*MP*)\n      if test -d /usr/nec; then\n\tarchive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'\n\thardcode_shlibpath_var=no\n\trunpath_var=LD_RUN_PATH\n\thardcode_runpath_var=yes\n\tld_shlibs=yes\n      fi\n      ;;\n\n    sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*)\n      no_undefined_flag='${wl}-z,text'\n      archive_cmds_need_lc=no\n      hardcode_shlibpath_var=no\n      runpath_var='LD_RUN_PATH'\n\n      if test \"$GCC\" = yes; then\n\tarchive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'\n\tarchive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'\n      else\n\tarchive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'\n\tarchive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'\n      fi\n      ;;\n\n    sysv5* | sco3.2v5* | sco5v6*)\n      # Note: We can NOT use -z defs as we might desire, because we do not\n      # link with -lc, and that would cause any symbols used from libc to\n      # always be unresolved, which means just about no library would\n      # ever link correctly.  If we're not using GNU ld we use -z text\n      # though, which does catch some bad symbols but isn't as heavy-handed\n      # as -z defs.\n      no_undefined_flag='${wl}-z,text'\n      allow_undefined_flag='${wl}-z,nodefs'\n      archive_cmds_need_lc=no\n      hardcode_shlibpath_var=no\n      hardcode_libdir_flag_spec='${wl}-R,$libdir'\n      hardcode_libdir_separator=':'\n      link_all_deplibs=yes\n      export_dynamic_flag_spec='${wl}-Bexport'\n      runpath_var='LD_RUN_PATH'\n\n      if test \"$GCC\" = yes; then\n\tarchive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'\n\tarchive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'\n      else\n\tarchive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'\n\tarchive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'\n      fi\n      ;;\n\n    uts4*)\n      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'\n      hardcode_libdir_flag_spec='-L$libdir'\n      hardcode_shlibpath_var=no\n      ;;\n\n    *)\n      ld_shlibs=no\n      ;;\n    esac\n\n    if test x$host_vendor = xsni; then\n      case $host in\n      sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)\n\texport_dynamic_flag_spec='${wl}-Blargedynsym'\n\t;;\n      esac\n    fi\n  fi\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ld_shlibs\" >&5\n$as_echo \"$ld_shlibs\" >&6; }\ntest \"$ld_shlibs\" = no && can_build_shared=no\n\nwith_gnu_ld=$with_gnu_ld\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n#\n# Do we need to explicitly link libc?\n#\ncase \"x$archive_cmds_need_lc\" in\nx|xyes)\n  # Assume -lc should be added\n  archive_cmds_need_lc=yes\n\n  if test \"$enable_shared\" = yes && test \"$GCC\" = yes; then\n    case $archive_cmds in\n    *'~'*)\n      # FIXME: we may have to deal with multi-command sequences.\n      ;;\n    '$CC '*)\n      # Test whether the compiler implicitly links with -lc since on some\n      # systems, -lgcc has to come before -lc. If gcc already passes -lc\n      # to ld, don't add -lc before -lgcc.\n      { $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in\" >&5\n$as_echo_n \"checking whether -lc should be explicitly linked in... \" >&6; }\nif ${lt_cv_archive_cmds_need_lc+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  $RM conftest*\n\techo \"$lt_simple_compile_test_code\" > conftest.$ac_ext\n\n\tif { { eval echo \"\\\"\\$as_me\\\":${as_lineno-$LINENO}: \\\"$ac_compile\\\"\"; } >&5\n  (eval $ac_compile) 2>&5\n  ac_status=$?\n  $as_echo \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; } 2>conftest.err; then\n\t  soname=conftest\n\t  lib=conftest\n\t  libobjs=conftest.$ac_objext\n\t  deplibs=\n\t  wl=$lt_prog_compiler_wl\n\t  pic_flag=$lt_prog_compiler_pic\n\t  compiler_flags=-v\n\t  linker_flags=-v\n\t  verstring=\n\t  output_objdir=.\n\t  libname=conftest\n\t  lt_save_allow_undefined_flag=$allow_undefined_flag\n\t  allow_undefined_flag=\n\t  if { { eval echo \"\\\"\\$as_me\\\":${as_lineno-$LINENO}: \\\"$archive_cmds 2\\>\\&1 \\| $GREP \\\" -lc \\\" \\>/dev/null 2\\>\\&1\\\"\"; } >&5\n  (eval $archive_cmds 2\\>\\&1 \\| $GREP \\\" -lc \\\" \\>/dev/null 2\\>\\&1) 2>&5\n  ac_status=$?\n  $as_echo \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; }\n\t  then\n\t    lt_cv_archive_cmds_need_lc=no\n\t  else\n\t    lt_cv_archive_cmds_need_lc=yes\n\t  fi\n\t  allow_undefined_flag=$lt_save_allow_undefined_flag\n\telse\n\t  cat conftest.err 1>&5\n\tfi\n\t$RM conftest*\n\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc\" >&5\n$as_echo \"$lt_cv_archive_cmds_need_lc\" >&6; }\n      archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc\n      ;;\n    esac\n  fi\n  ;;\nesac\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics\" >&5\n$as_echo_n \"checking dynamic linker characteristics... \" >&6; }\n\nif test \"$GCC\" = yes; then\n  case $host_os in\n    darwin*) lt_awk_arg=\"/^libraries:/,/LR/\" ;;\n    *) lt_awk_arg=\"/^libraries:/\" ;;\n  esac\n  case $host_os in\n    mingw* | cegcc*) lt_sed_strip_eq=\"s,=\\([A-Za-z]:\\),\\1,g\" ;;\n    *) lt_sed_strip_eq=\"s,=/,/,g\" ;;\n  esac\n  lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e \"s/^libraries://\" -e $lt_sed_strip_eq`\n  case $lt_search_path_spec in\n  *\\;*)\n    # if the path contains \";\" then we assume it to be the separator\n    # otherwise default to the standard path separator (i.e. \":\") - it is\n    # assumed that no part of a normal pathname contains \";\" but that should\n    # okay in the real world where \";\" in dirpaths is itself problematic.\n    lt_search_path_spec=`$ECHO \"$lt_search_path_spec\" | $SED 's/;/ /g'`\n    ;;\n  *)\n    lt_search_path_spec=`$ECHO \"$lt_search_path_spec\" | $SED \"s/$PATH_SEPARATOR/ /g\"`\n    ;;\n  esac\n  # Ok, now we have the path, separated by spaces, we can step through it\n  # and add multilib dir if necessary.\n  lt_tmp_lt_search_path_spec=\n  lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null`\n  for lt_sys_path in $lt_search_path_spec; do\n    if test -d \"$lt_sys_path/$lt_multi_os_dir\"; then\n      lt_tmp_lt_search_path_spec=\"$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir\"\n    else\n      test -d \"$lt_sys_path\" && \\\n\tlt_tmp_lt_search_path_spec=\"$lt_tmp_lt_search_path_spec $lt_sys_path\"\n    fi\n  done\n  lt_search_path_spec=`$ECHO \"$lt_tmp_lt_search_path_spec\" | awk '\nBEGIN {RS=\" \"; FS=\"/|\\n\";} {\n  lt_foo=\"\";\n  lt_count=0;\n  for (lt_i = NF; lt_i > 0; lt_i--) {\n    if ($lt_i != \"\" && $lt_i != \".\") {\n      if ($lt_i == \"..\") {\n        lt_count++;\n      } else {\n        if (lt_count == 0) {\n          lt_foo=\"/\" $lt_i lt_foo;\n        } else {\n          lt_count--;\n        }\n      }\n    }\n  }\n  if (lt_foo != \"\") { lt_freq[lt_foo]++; }\n  if (lt_freq[lt_foo] == 1) { print lt_foo; }\n}'`\n  # AWK program above erroneously prepends '/' to C:/dos/paths\n  # for these hosts.\n  case $host_os in\n    mingw* | cegcc*) lt_search_path_spec=`$ECHO \"$lt_search_path_spec\" |\\\n      $SED 's,/\\([A-Za-z]:\\),\\1,g'` ;;\n  esac\n  sys_lib_search_path_spec=`$ECHO \"$lt_search_path_spec\" | $lt_NL2SP`\nelse\n  sys_lib_search_path_spec=\"/lib /usr/lib /usr/local/lib\"\nfi\nlibrary_names_spec=\nlibname_spec='lib$name'\nsoname_spec=\nshrext_cmds=\".so\"\npostinstall_cmds=\npostuninstall_cmds=\nfinish_cmds=\nfinish_eval=\nshlibpath_var=\nshlibpath_overrides_runpath=unknown\nversion_type=none\ndynamic_linker=\"$host_os ld.so\"\nsys_lib_dlsearch_path_spec=\"/lib /usr/lib\"\nneed_lib_prefix=unknown\nhardcode_into_libs=no\n\n# when you set need_version to no, make sure it does not cause -set_version\n# flags to be left without arguments\nneed_version=unknown\n\ncase $host_os in\naix3*)\n  version_type=linux\n  library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'\n  shlibpath_var=LIBPATH\n\n  # AIX 3 has no versioning support, so we append a major version to the name.\n  soname_spec='${libname}${release}${shared_ext}$major'\n  ;;\n\naix[4-9]*)\n  version_type=linux\n  need_lib_prefix=no\n  need_version=no\n  hardcode_into_libs=yes\n  if test \"$host_cpu\" = ia64; then\n    # AIX 5 supports IA64\n    library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'\n    shlibpath_var=LD_LIBRARY_PATH\n  else\n    # With GCC up to 2.95.x, collect2 would create an import file\n    # for dependence libraries.  The import file would start with\n    # the line `#! .'.  This would cause the generated library to\n    # depend on `.', always an invalid library.  This was fixed in\n    # development snapshots of GCC prior to 3.0.\n    case $host_os in\n      aix4 | aix4.[01] | aix4.[01].*)\n      if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'\n\t   echo ' yes '\n\t   echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then\n\t:\n      else\n\tcan_build_shared=no\n      fi\n      ;;\n    esac\n    # AIX (on Power*) has no versioning support, so currently we can not hardcode correct\n    # soname into executable. Probably we can add versioning support to\n    # collect2, so additional links can be useful in future.\n    if test \"$aix_use_runtimelinking\" = yes; then\n      # If using run time linking (on AIX 4.2 or later) use lib<name>.so\n      # instead of lib<name>.a to let people know that these are not\n      # typical AIX shared libraries.\n      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'\n    else\n      # We preserve .a as extension for shared libraries through AIX4.2\n      # and later when we are not doing run time linking.\n      library_names_spec='${libname}${release}.a $libname.a'\n      soname_spec='${libname}${release}${shared_ext}$major'\n    fi\n    shlibpath_var=LIBPATH\n  fi\n  ;;\n\namigaos*)\n  case $host_cpu in\n  powerpc)\n    # Since July 2007 AmigaOS4 officially supports .so libraries.\n    # When compiling the executable, add -use-dynld -Lsobjs: to the compileline.\n    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'\n    ;;\n  m68k)\n    library_names_spec='$libname.ixlibrary $libname.a'\n    # Create ${libname}_ixlibrary.a entries in /sys/libs.\n    finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all \"$lib\" | $SED '\\''s%^.*/\\([^/]*\\)\\.ixlibrary$%\\1%'\\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show \"cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a\"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'\n    ;;\n  esac\n  ;;\n\nbeos*)\n  library_names_spec='${libname}${shared_ext}'\n  dynamic_linker=\"$host_os ld.so\"\n  shlibpath_var=LIBRARY_PATH\n  ;;\n\nbsdi[45]*)\n  version_type=linux\n  need_version=no\n  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'\n  soname_spec='${libname}${release}${shared_ext}$major'\n  finish_cmds='PATH=\"\\$PATH:/sbin\" ldconfig $libdir'\n  shlibpath_var=LD_LIBRARY_PATH\n  sys_lib_search_path_spec=\"/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib\"\n  sys_lib_dlsearch_path_spec=\"/shlib /usr/lib /usr/local/lib\"\n  # the default ld.so.conf also contains /usr/contrib/lib and\n  # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow\n  # libtool to hard-code these into programs\n  ;;\n\ncygwin* | mingw* | pw32* | cegcc*)\n  version_type=windows\n  shrext_cmds=\".dll\"\n  need_version=no\n  need_lib_prefix=no\n\n  case $GCC,$host_os in\n  yes,cygwin* | yes,mingw* | yes,pw32* | yes,cegcc*)\n    library_names_spec='$libname.dll.a'\n    # DLL is installed to $(libdir)/../bin by postinstall_cmds\n    postinstall_cmds='base_file=`basename \\${file}`~\n      dlpath=`$SHELL 2>&1 -c '\\''. $dir/'\\''\\${base_file}'\\''i; echo \\$dlname'\\''`~\n      dldir=$destdir/`dirname \\$dlpath`~\n      test -d \\$dldir || mkdir -p \\$dldir~\n      $install_prog $dir/$dlname \\$dldir/$dlname~\n      chmod a+x \\$dldir/$dlname~\n      if test -n '\\''$stripme'\\'' && test -n '\\''$striplib'\\''; then\n        eval '\\''$striplib \\$dldir/$dlname'\\'' || exit \\$?;\n      fi'\n    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\\''. $file; echo \\$dlname'\\''`~\n      dlpath=$dir/\\$dldll~\n       $RM \\$dlpath'\n    shlibpath_overrides_runpath=yes\n\n    case $host_os in\n    cygwin*)\n      # Cygwin DLLs use 'cyg' prefix rather than 'lib'\n      soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'\n\n      sys_lib_search_path_spec=\"$sys_lib_search_path_spec /usr/lib/w32api\"\n      ;;\n    mingw* | cegcc*)\n      # MinGW DLLs use traditional 'lib' prefix\n      soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'\n      ;;\n    pw32*)\n      # pw32 DLLs use 'pw' prefix rather than 'lib'\n      library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'\n      ;;\n    esac\n    ;;\n\n  *)\n    library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib'\n    ;;\n  esac\n  dynamic_linker='Win32 ld.exe'\n  # FIXME: first we should search . and the directory the executable is in\n  shlibpath_var=PATH\n  ;;\n\ndarwin* | rhapsody*)\n  dynamic_linker=\"$host_os dyld\"\n  version_type=darwin\n  need_lib_prefix=no\n  need_version=no\n  library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext'\n  soname_spec='${libname}${release}${major}$shared_ext'\n  shlibpath_overrides_runpath=yes\n  shlibpath_var=DYLD_LIBRARY_PATH\n  shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'\n\n  sys_lib_search_path_spec=\"$sys_lib_search_path_spec /usr/local/lib\"\n  sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'\n  ;;\n\ndgux*)\n  version_type=linux\n  need_lib_prefix=no\n  need_version=no\n  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'\n  soname_spec='${libname}${release}${shared_ext}$major'\n  shlibpath_var=LD_LIBRARY_PATH\n  ;;\n\nfreebsd* | dragonfly*)\n  # DragonFly does not have aout.  When/if they implement a new\n  # versioning mechanism, adjust this.\n  if test -x /usr/bin/objformat; then\n    objformat=`/usr/bin/objformat`\n  else\n    case $host_os in\n    freebsd[23].*) objformat=aout ;;\n    *) objformat=elf ;;\n    esac\n  fi\n  version_type=freebsd-$objformat\n  case $version_type in\n    freebsd-elf*)\n      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'\n      need_version=no\n      need_lib_prefix=no\n      ;;\n    freebsd-*)\n      library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'\n      need_version=yes\n      ;;\n  esac\n  shlibpath_var=LD_LIBRARY_PATH\n  case $host_os in\n  freebsd2.*)\n    shlibpath_overrides_runpath=yes\n    ;;\n  freebsd3.[01]* | freebsdelf3.[01]*)\n    shlibpath_overrides_runpath=yes\n    hardcode_into_libs=yes\n    ;;\n  freebsd3.[2-9]* | freebsdelf3.[2-9]* | \\\n  freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1)\n    shlibpath_overrides_runpath=no\n    hardcode_into_libs=yes\n    ;;\n  *) # from 4.6 on, and DragonFly\n    shlibpath_overrides_runpath=yes\n    hardcode_into_libs=yes\n    ;;\n  esac\n  ;;\n\nhaiku*)\n  version_type=linux\n  need_lib_prefix=no\n  need_version=no\n  dynamic_linker=\"$host_os runtime_loader\"\n  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'\n  soname_spec='${libname}${release}${shared_ext}$major'\n  shlibpath_var=LIBRARY_PATH\n  shlibpath_overrides_runpath=yes\n  sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib'\n  hardcode_into_libs=yes\n  ;;\n\nhpux9* | hpux10* | hpux11*)\n  # Give a soname corresponding to the major version so that dld.sl refuses to\n  # link against other versions.\n  version_type=sunos\n  need_lib_prefix=no\n  need_version=no\n  case $host_cpu in\n  ia64*)\n    shrext_cmds='.so'\n    hardcode_into_libs=yes\n    dynamic_linker=\"$host_os dld.so\"\n    shlibpath_var=LD_LIBRARY_PATH\n    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.\n    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'\n    soname_spec='${libname}${release}${shared_ext}$major'\n    if test \"X$HPUX_IA64_MODE\" = X32; then\n      sys_lib_search_path_spec=\"/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib\"\n    else\n      sys_lib_search_path_spec=\"/usr/lib/hpux64 /usr/local/lib/hpux64\"\n    fi\n    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec\n    ;;\n  hppa*64*)\n    shrext_cmds='.sl'\n    hardcode_into_libs=yes\n    dynamic_linker=\"$host_os dld.sl\"\n    shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH\n    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.\n    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'\n    soname_spec='${libname}${release}${shared_ext}$major'\n    sys_lib_search_path_spec=\"/usr/lib/pa20_64 /usr/ccs/lib/pa20_64\"\n    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec\n    ;;\n  *)\n    shrext_cmds='.sl'\n    dynamic_linker=\"$host_os dld.sl\"\n    shlibpath_var=SHLIB_PATH\n    shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH\n    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'\n    soname_spec='${libname}${release}${shared_ext}$major'\n    ;;\n  esac\n  # HP-UX runs *really* slowly unless shared libraries are mode 555, ...\n  postinstall_cmds='chmod 555 $lib'\n  # or fails outright, so override atomically:\n  install_override_mode=555\n  ;;\n\ninterix[3-9]*)\n  version_type=linux\n  need_lib_prefix=no\n  need_version=no\n  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'\n  soname_spec='${libname}${release}${shared_ext}$major'\n  dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'\n  shlibpath_var=LD_LIBRARY_PATH\n  shlibpath_overrides_runpath=no\n  hardcode_into_libs=yes\n  ;;\n\nirix5* | irix6* | nonstopux*)\n  case $host_os in\n    nonstopux*) version_type=nonstopux ;;\n    *)\n\tif test \"$lt_cv_prog_gnu_ld\" = yes; then\n\t\tversion_type=linux\n\telse\n\t\tversion_type=irix\n\tfi ;;\n  esac\n  need_lib_prefix=no\n  need_version=no\n  soname_spec='${libname}${release}${shared_ext}$major'\n  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'\n  case $host_os in\n  irix5* | nonstopux*)\n    libsuff= shlibsuff=\n    ;;\n  *)\n    case $LD in # libtool.m4 will add one of these switches to LD\n    *-32|*\"-32 \"|*-melf32bsmip|*\"-melf32bsmip \")\n      libsuff= shlibsuff= libmagic=32-bit;;\n    *-n32|*\"-n32 \"|*-melf32bmipn32|*\"-melf32bmipn32 \")\n      libsuff=32 shlibsuff=N32 libmagic=N32;;\n    *-64|*\"-64 \"|*-melf64bmip|*\"-melf64bmip \")\n      libsuff=64 shlibsuff=64 libmagic=64-bit;;\n    *) libsuff= shlibsuff= libmagic=never-match;;\n    esac\n    ;;\n  esac\n  shlibpath_var=LD_LIBRARY${shlibsuff}_PATH\n  shlibpath_overrides_runpath=no\n  sys_lib_search_path_spec=\"/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}\"\n  sys_lib_dlsearch_path_spec=\"/usr/lib${libsuff} /lib${libsuff}\"\n  hardcode_into_libs=yes\n  ;;\n\n# No shared lib support for Linux oldld, aout, or coff.\nlinux*oldld* | linux*aout* | linux*coff*)\n  dynamic_linker=no\n  ;;\n\n# This must be Linux ELF.\n\n# uclinux* changes (here and below) have been submitted to the libtool\n# project, but have not yet been accepted: they are GCC-local changes\n# for the time being.  (See\n# https://lists.gnu.org/archive/html/libtool-patches/2018-05/msg00000.html)\nlinux* | k*bsd*-gnu | kopensolaris*-gnu | gnu* | uclinuxfdpiceabi)\n  version_type=linux\n  need_lib_prefix=no\n  need_version=no\n  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'\n  soname_spec='${libname}${release}${shared_ext}$major'\n  finish_cmds='PATH=\"\\$PATH:/sbin\" ldconfig -n $libdir'\n  shlibpath_var=LD_LIBRARY_PATH\n  shlibpath_overrides_runpath=no\n\n  # Some binutils ld are patched to set DT_RUNPATH\n  if ${lt_cv_shlibpath_overrides_runpath+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  lt_cv_shlibpath_overrides_runpath=no\n    save_LDFLAGS=$LDFLAGS\n    save_libdir=$libdir\n    eval \"libdir=/foo; wl=\\\"$lt_prog_compiler_wl\\\"; \\\n\t LDFLAGS=\\\"\\$LDFLAGS $hardcode_libdir_flag_spec\\\"\"\n    cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain ()\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  if  ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep \"RUNPATH.*$libdir\" >/dev/null; then :\n  lt_cv_shlibpath_overrides_runpath=yes\nfi\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\n    LDFLAGS=$save_LDFLAGS\n    libdir=$save_libdir\n\nfi\n\n  shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath\n\n  # This implies no fast_install, which is unacceptable.\n  # Some rework will be needed to allow for fast_install\n  # before this can be enabled.\n  hardcode_into_libs=yes\n\n  # Append ld.so.conf contents to the search path\n  if test -f /etc/ld.so.conf; then\n    lt_ld_extra=`awk '/^include / { system(sprintf(\"cd /etc; cat %s 2>/dev/null\", \\$2)); skip = 1; } { if (!skip) print \\$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[\t ]*hwcap[\t ]/d;s/[:,\t]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/\"//g;/^$/d' | tr '\\n' ' '`\n    sys_lib_dlsearch_path_spec=\"/lib /usr/lib $lt_ld_extra\"\n  fi\n\n  # We used to test for /lib/ld.so.1 and disable shared libraries on\n  # powerpc, because MkLinux only supported shared libraries with the\n  # GNU dynamic linker.  Since this was broken with cross compilers,\n  # most powerpc-linux boxes support dynamic linking these days and\n  # people can always --disable-shared, the test was removed, and we\n  # assume the GNU/Linux dynamic linker is in use.\n  dynamic_linker='GNU/Linux ld.so'\n  ;;\n\nnetbsd*)\n  version_type=sunos\n  need_lib_prefix=no\n  need_version=no\n  if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then\n    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'\n    finish_cmds='PATH=\"\\$PATH:/sbin\" ldconfig -m $libdir'\n    dynamic_linker='NetBSD (a.out) ld.so'\n  else\n    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'\n    soname_spec='${libname}${release}${shared_ext}$major'\n    dynamic_linker='NetBSD ld.elf_so'\n  fi\n  shlibpath_var=LD_LIBRARY_PATH\n  shlibpath_overrides_runpath=yes\n  hardcode_into_libs=yes\n  ;;\n\nnewsos6)\n  version_type=linux\n  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'\n  shlibpath_var=LD_LIBRARY_PATH\n  shlibpath_overrides_runpath=yes\n  ;;\n\n*nto* | *qnx*)\n  version_type=qnx\n  need_lib_prefix=no\n  need_version=no\n  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'\n  soname_spec='${libname}${release}${shared_ext}$major'\n  shlibpath_var=LD_LIBRARY_PATH\n  shlibpath_overrides_runpath=no\n  hardcode_into_libs=yes\n  dynamic_linker='ldqnx.so'\n  ;;\n\nopenbsd*)\n  version_type=sunos\n  sys_lib_dlsearch_path_spec=\"/usr/lib\"\n  need_lib_prefix=no\n  # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.\n  case $host_os in\n    openbsd3.3 | openbsd3.3.*)\tneed_version=yes ;;\n    *)\t\t\t\tneed_version=no  ;;\n  esac\n  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'\n  finish_cmds='PATH=\"\\$PATH:/sbin\" ldconfig -m $libdir'\n  shlibpath_var=LD_LIBRARY_PATH\n  if test -z \"`echo __ELF__ | $CC -E - | $GREP __ELF__`\" || test \"$host_os-$host_cpu\" = \"openbsd2.8-powerpc\"; then\n    case $host_os in\n      openbsd2.[89] | openbsd2.[89].*)\n\tshlibpath_overrides_runpath=no\n\t;;\n      *)\n\tshlibpath_overrides_runpath=yes\n\t;;\n      esac\n  else\n    shlibpath_overrides_runpath=yes\n  fi\n  ;;\n\nos2*)\n  libname_spec='$name'\n  shrext_cmds=\".dll\"\n  need_lib_prefix=no\n  library_names_spec='$libname${shared_ext} $libname.a'\n  dynamic_linker='OS/2 ld.exe'\n  shlibpath_var=LIBPATH\n  ;;\n\nosf3* | osf4* | osf5*)\n  version_type=osf\n  need_lib_prefix=no\n  need_version=no\n  soname_spec='${libname}${release}${shared_ext}$major'\n  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'\n  shlibpath_var=LD_LIBRARY_PATH\n  sys_lib_search_path_spec=\"/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib\"\n  sys_lib_dlsearch_path_spec=\"$sys_lib_search_path_spec\"\n  ;;\n\nrdos*)\n  dynamic_linker=no\n  ;;\n\nsolaris*)\n  version_type=linux\n  need_lib_prefix=no\n  need_version=no\n  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'\n  soname_spec='${libname}${release}${shared_ext}$major'\n  shlibpath_var=LD_LIBRARY_PATH\n  shlibpath_overrides_runpath=yes\n  hardcode_into_libs=yes\n  # ldd complains unless libraries are executable\n  postinstall_cmds='chmod +x $lib'\n  ;;\n\nsunos4*)\n  version_type=sunos\n  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'\n  finish_cmds='PATH=\"\\$PATH:/usr/etc\" ldconfig $libdir'\n  shlibpath_var=LD_LIBRARY_PATH\n  shlibpath_overrides_runpath=yes\n  if test \"$with_gnu_ld\" = yes; then\n    need_lib_prefix=no\n  fi\n  need_version=yes\n  ;;\n\nsysv4 | sysv4.3*)\n  version_type=linux\n  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'\n  soname_spec='${libname}${release}${shared_ext}$major'\n  shlibpath_var=LD_LIBRARY_PATH\n  case $host_vendor in\n    sni)\n      shlibpath_overrides_runpath=no\n      need_lib_prefix=no\n      runpath_var=LD_RUN_PATH\n      ;;\n    siemens)\n      need_lib_prefix=no\n      ;;\n    motorola)\n      need_lib_prefix=no\n      need_version=no\n      shlibpath_overrides_runpath=no\n      sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'\n      ;;\n  esac\n  ;;\n\nsysv4*MP*)\n  if test -d /usr/nec ;then\n    version_type=linux\n    library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'\n    soname_spec='$libname${shared_ext}.$major'\n    shlibpath_var=LD_LIBRARY_PATH\n  fi\n  ;;\n\nsysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)\n  version_type=freebsd-elf\n  need_lib_prefix=no\n  need_version=no\n  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'\n  soname_spec='${libname}${release}${shared_ext}$major'\n  shlibpath_var=LD_LIBRARY_PATH\n  shlibpath_overrides_runpath=yes\n  hardcode_into_libs=yes\n  if test \"$with_gnu_ld\" = yes; then\n    sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'\n  else\n    sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'\n    case $host_os in\n      sco3.2v5*)\n        sys_lib_search_path_spec=\"$sys_lib_search_path_spec /lib\"\n\t;;\n    esac\n  fi\n  sys_lib_dlsearch_path_spec='/usr/lib'\n  ;;\n\ntpf*)\n  # TPF is a cross-target only.  Preferred cross-host = GNU/Linux.\n  version_type=linux\n  need_lib_prefix=no\n  need_version=no\n  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'\n  shlibpath_var=LD_LIBRARY_PATH\n  shlibpath_overrides_runpath=no\n  hardcode_into_libs=yes\n  ;;\n\nuts4*)\n  version_type=linux\n  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'\n  soname_spec='${libname}${release}${shared_ext}$major'\n  shlibpath_var=LD_LIBRARY_PATH\n  ;;\n\n# Shared libraries for VwWorks, >= 7 only at this stage\n# and (fpic) still incompatible with \"large\" code models\n# in a few configurations. Only for RTP mode in any case,\n# and upon explicit request at configure time.\nvxworks7*)\n  dynamic_linker=no\n  case ${with_multisubdir}-${enable_shared} in\n    *large*)\n      ;;\n    *mrtp*-yes)\n      version_type=linux\n      need_lib_prefix=no\n      need_version=no\n      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'\n      soname_spec='${libname}${release}${shared_ext}$major'\n      dynamic_linker=\"$host_os module_loader\"\n      ;;\n  esac\n  ;;\n*)\n  dynamic_linker=no\n  ;;\nesac\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $dynamic_linker\" >&5\n$as_echo \"$dynamic_linker\" >&6; }\ntest \"$dynamic_linker\" = no && can_build_shared=no\n\nvariables_saved_for_relink=\"PATH $shlibpath_var $runpath_var\"\nif test \"$GCC\" = yes; then\n  variables_saved_for_relink=\"$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH\"\nfi\n\nif test \"${lt_cv_sys_lib_search_path_spec+set}\" = set; then\n  sys_lib_search_path_spec=\"$lt_cv_sys_lib_search_path_spec\"\nfi\nif test \"${lt_cv_sys_lib_dlsearch_path_spec+set}\" = set; then\n  sys_lib_dlsearch_path_spec=\"$lt_cv_sys_lib_dlsearch_path_spec\"\nfi\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs\" >&5\n$as_echo_n \"checking how to hardcode library paths into programs... \" >&6; }\nhardcode_action=\nif test -n \"$hardcode_libdir_flag_spec\" ||\n   test -n \"$runpath_var\" ||\n   test \"X$hardcode_automatic\" = \"Xyes\" ; then\n\n  # We can hardcode non-existent directories.\n  if test \"$hardcode_direct\" != no &&\n     # If the only mechanism to avoid hardcoding is shlibpath_var, we\n     # have to relink, otherwise we might link with an installed library\n     # when we should be linking with a yet-to-be-installed one\n     ## test \"$_LT_TAGVAR(hardcode_shlibpath_var, )\" != no &&\n     test \"$hardcode_minus_L\" != no; then\n    # Linking always hardcodes the temporary library directory.\n    hardcode_action=relink\n  else\n    # We can link without hardcoding, and we can hardcode nonexisting dirs.\n    hardcode_action=immediate\n  fi\nelse\n  # We cannot hardcode anything, or else we can only hardcode existing\n  # directories.\n  hardcode_action=unsupported\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $hardcode_action\" >&5\n$as_echo \"$hardcode_action\" >&6; }\n\nif test \"$hardcode_action\" = relink ||\n   test \"$inherit_rpath\" = yes; then\n  # Fast installation is not supported\n  enable_fast_install=no\nelif test \"$shlibpath_overrides_runpath\" = yes ||\n     test \"$enable_shared\" = no; then\n  # Fast installation is not necessary\n  enable_fast_install=needless\nfi\n\n\n\n\n\n\n  if test \"x$enable_dlopen\" != xyes; then\n  enable_dlopen=unknown\n  enable_dlopen_self=unknown\n  enable_dlopen_self_static=unknown\nelse\n  lt_cv_dlopen=no\n  lt_cv_dlopen_libs=\n\n  case $host_os in\n  beos*)\n    lt_cv_dlopen=\"load_add_on\"\n    lt_cv_dlopen_libs=\n    lt_cv_dlopen_self=yes\n    ;;\n\n  mingw* | pw32* | cegcc*)\n    lt_cv_dlopen=\"LoadLibrary\"\n    lt_cv_dlopen_libs=\n    ;;\n\n  cygwin*)\n    lt_cv_dlopen=\"dlopen\"\n    lt_cv_dlopen_libs=\n    ;;\n\n  darwin*)\n  # if libdl is installed we need to link against it\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl\" >&5\n$as_echo_n \"checking for dlopen in -ldl... \" >&6; }\nif ${ac_cv_lib_dl_dlopen+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  ac_check_lib_save_LIBS=$LIBS\nLIBS=\"-ldl  $LIBS\"\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n/* Override any GCC internal prototype to avoid an error.\n   Use char because int might match the return type of a GCC\n   builtin and then its argument prototype would still apply.  */\n#ifdef __cplusplus\nextern \"C\"\n#endif\nchar dlopen ();\nint\nmain ()\n{\nreturn dlopen ();\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  ac_cv_lib_dl_dlopen=yes\nelse\n  ac_cv_lib_dl_dlopen=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nLIBS=$ac_check_lib_save_LIBS\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen\" >&5\n$as_echo \"$ac_cv_lib_dl_dlopen\" >&6; }\nif test \"x$ac_cv_lib_dl_dlopen\" = xyes; then :\n  lt_cv_dlopen=\"dlopen\" lt_cv_dlopen_libs=\"-ldl\"\nelse\n\n    lt_cv_dlopen=\"dyld\"\n    lt_cv_dlopen_libs=\n    lt_cv_dlopen_self=yes\n\nfi\n\n    ;;\n\n  *)\n    ac_fn_c_check_func \"$LINENO\" \"shl_load\" \"ac_cv_func_shl_load\"\nif test \"x$ac_cv_func_shl_load\" = xyes; then :\n  lt_cv_dlopen=\"shl_load\"\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld\" >&5\n$as_echo_n \"checking for shl_load in -ldld... \" >&6; }\nif ${ac_cv_lib_dld_shl_load+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  ac_check_lib_save_LIBS=$LIBS\nLIBS=\"-ldld  $LIBS\"\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n/* Override any GCC internal prototype to avoid an error.\n   Use char because int might match the return type of a GCC\n   builtin and then its argument prototype would still apply.  */\n#ifdef __cplusplus\nextern \"C\"\n#endif\nchar shl_load ();\nint\nmain ()\n{\nreturn shl_load ();\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  ac_cv_lib_dld_shl_load=yes\nelse\n  ac_cv_lib_dld_shl_load=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nLIBS=$ac_check_lib_save_LIBS\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load\" >&5\n$as_echo \"$ac_cv_lib_dld_shl_load\" >&6; }\nif test \"x$ac_cv_lib_dld_shl_load\" = xyes; then :\n  lt_cv_dlopen=\"shl_load\" lt_cv_dlopen_libs=\"-ldld\"\nelse\n  ac_fn_c_check_func \"$LINENO\" \"dlopen\" \"ac_cv_func_dlopen\"\nif test \"x$ac_cv_func_dlopen\" = xyes; then :\n  lt_cv_dlopen=\"dlopen\"\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl\" >&5\n$as_echo_n \"checking for dlopen in -ldl... \" >&6; }\nif ${ac_cv_lib_dl_dlopen+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  ac_check_lib_save_LIBS=$LIBS\nLIBS=\"-ldl  $LIBS\"\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n/* Override any GCC internal prototype to avoid an error.\n   Use char because int might match the return type of a GCC\n   builtin and then its argument prototype would still apply.  */\n#ifdef __cplusplus\nextern \"C\"\n#endif\nchar dlopen ();\nint\nmain ()\n{\nreturn dlopen ();\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  ac_cv_lib_dl_dlopen=yes\nelse\n  ac_cv_lib_dl_dlopen=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nLIBS=$ac_check_lib_save_LIBS\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen\" >&5\n$as_echo \"$ac_cv_lib_dl_dlopen\" >&6; }\nif test \"x$ac_cv_lib_dl_dlopen\" = xyes; then :\n  lt_cv_dlopen=\"dlopen\" lt_cv_dlopen_libs=\"-ldl\"\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld\" >&5\n$as_echo_n \"checking for dlopen in -lsvld... \" >&6; }\nif ${ac_cv_lib_svld_dlopen+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  ac_check_lib_save_LIBS=$LIBS\nLIBS=\"-lsvld  $LIBS\"\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n/* Override any GCC internal prototype to avoid an error.\n   Use char because int might match the return type of a GCC\n   builtin and then its argument prototype would still apply.  */\n#ifdef __cplusplus\nextern \"C\"\n#endif\nchar dlopen ();\nint\nmain ()\n{\nreturn dlopen ();\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  ac_cv_lib_svld_dlopen=yes\nelse\n  ac_cv_lib_svld_dlopen=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nLIBS=$ac_check_lib_save_LIBS\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen\" >&5\n$as_echo \"$ac_cv_lib_svld_dlopen\" >&6; }\nif test \"x$ac_cv_lib_svld_dlopen\" = xyes; then :\n  lt_cv_dlopen=\"dlopen\" lt_cv_dlopen_libs=\"-lsvld\"\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld\" >&5\n$as_echo_n \"checking for dld_link in -ldld... \" >&6; }\nif ${ac_cv_lib_dld_dld_link+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  ac_check_lib_save_LIBS=$LIBS\nLIBS=\"-ldld  $LIBS\"\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n/* Override any GCC internal prototype to avoid an error.\n   Use char because int might match the return type of a GCC\n   builtin and then its argument prototype would still apply.  */\n#ifdef __cplusplus\nextern \"C\"\n#endif\nchar dld_link ();\nint\nmain ()\n{\nreturn dld_link ();\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  ac_cv_lib_dld_dld_link=yes\nelse\n  ac_cv_lib_dld_dld_link=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nLIBS=$ac_check_lib_save_LIBS\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link\" >&5\n$as_echo \"$ac_cv_lib_dld_dld_link\" >&6; }\nif test \"x$ac_cv_lib_dld_dld_link\" = xyes; then :\n  lt_cv_dlopen=\"dld_link\" lt_cv_dlopen_libs=\"-ldld\"\nfi\n\n\nfi\n\n\nfi\n\n\nfi\n\n\nfi\n\n\nfi\n\n    ;;\n  esac\n\n  if test \"x$lt_cv_dlopen\" != xno; then\n    enable_dlopen=yes\n  else\n    enable_dlopen=no\n  fi\n\n  case $lt_cv_dlopen in\n  dlopen)\n    save_CPPFLAGS=\"$CPPFLAGS\"\n    test \"x$ac_cv_header_dlfcn_h\" = xyes && CPPFLAGS=\"$CPPFLAGS -DHAVE_DLFCN_H\"\n\n    save_LDFLAGS=\"$LDFLAGS\"\n    wl=$lt_prog_compiler_wl eval LDFLAGS=\\\"\\$LDFLAGS $export_dynamic_flag_spec\\\"\n\n    save_LIBS=\"$LIBS\"\n    LIBS=\"$lt_cv_dlopen_libs $LIBS\"\n\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself\" >&5\n$as_echo_n \"checking whether a program can dlopen itself... \" >&6; }\nif ${lt_cv_dlopen_self+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  \t  if test \"$cross_compiling\" = yes; then :\n  lt_cv_dlopen_self=cross\nelse\n  lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2\n  lt_status=$lt_dlunknown\n  cat > conftest.$ac_ext <<_LT_EOF\n#line 11398 \"configure\"\n#include \"confdefs.h\"\n\n#if HAVE_DLFCN_H\n#include <dlfcn.h>\n#endif\n\n#include <stdio.h>\n\n#ifdef RTLD_GLOBAL\n#  define LT_DLGLOBAL\t\tRTLD_GLOBAL\n#else\n#  ifdef DL_GLOBAL\n#    define LT_DLGLOBAL\t\tDL_GLOBAL\n#  else\n#    define LT_DLGLOBAL\t\t0\n#  endif\n#endif\n\n/* We may have to define LT_DLLAZY_OR_NOW in the command line if we\n   find out it does not work in some platform. */\n#ifndef LT_DLLAZY_OR_NOW\n#  ifdef RTLD_LAZY\n#    define LT_DLLAZY_OR_NOW\t\tRTLD_LAZY\n#  else\n#    ifdef DL_LAZY\n#      define LT_DLLAZY_OR_NOW\t\tDL_LAZY\n#    else\n#      ifdef RTLD_NOW\n#        define LT_DLLAZY_OR_NOW\tRTLD_NOW\n#      else\n#        ifdef DL_NOW\n#          define LT_DLLAZY_OR_NOW\tDL_NOW\n#        else\n#          define LT_DLLAZY_OR_NOW\t0\n#        endif\n#      endif\n#    endif\n#  endif\n#endif\n\n/* When -fvisbility=hidden is used, assume the code has been annotated\n   correspondingly for the symbols needed.  */\n#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))\nvoid fnord () __attribute__((visibility(\"default\")));\n#endif\n\nvoid fnord () { int i=42; }\nint main ()\n{\n  void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);\n  int status = $lt_dlunknown;\n\n  if (self)\n    {\n      if (dlsym (self,\"fnord\"))       status = $lt_dlno_uscore;\n      else\n        {\n\t  if (dlsym( self,\"_fnord\"))  status = $lt_dlneed_uscore;\n          else puts (dlerror ());\n\t}\n      /* dlclose (self); */\n    }\n  else\n    puts (dlerror ());\n\n  return status;\n}\n_LT_EOF\n  if { { eval echo \"\\\"\\$as_me\\\":${as_lineno-$LINENO}: \\\"$ac_link\\\"\"; } >&5\n  (eval $ac_link) 2>&5\n  ac_status=$?\n  $as_echo \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then\n    (./conftest; exit; ) >&5 2>/dev/null\n    lt_status=$?\n    case x$lt_status in\n      x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;;\n      x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;;\n      x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;;\n    esac\n  else :\n    # compilation failed\n    lt_cv_dlopen_self=no\n  fi\nfi\nrm -fr conftest*\n\n\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self\" >&5\n$as_echo \"$lt_cv_dlopen_self\" >&6; }\n\n    if test \"x$lt_cv_dlopen_self\" = xyes; then\n      wl=$lt_prog_compiler_wl eval LDFLAGS=\\\"\\$LDFLAGS $lt_prog_compiler_static\\\"\n      { $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself\" >&5\n$as_echo_n \"checking whether a statically linked program can dlopen itself... \" >&6; }\nif ${lt_cv_dlopen_self_static+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  \t  if test \"$cross_compiling\" = yes; then :\n  lt_cv_dlopen_self_static=cross\nelse\n  lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2\n  lt_status=$lt_dlunknown\n  cat > conftest.$ac_ext <<_LT_EOF\n#line 11504 \"configure\"\n#include \"confdefs.h\"\n\n#if HAVE_DLFCN_H\n#include <dlfcn.h>\n#endif\n\n#include <stdio.h>\n\n#ifdef RTLD_GLOBAL\n#  define LT_DLGLOBAL\t\tRTLD_GLOBAL\n#else\n#  ifdef DL_GLOBAL\n#    define LT_DLGLOBAL\t\tDL_GLOBAL\n#  else\n#    define LT_DLGLOBAL\t\t0\n#  endif\n#endif\n\n/* We may have to define LT_DLLAZY_OR_NOW in the command line if we\n   find out it does not work in some platform. */\n#ifndef LT_DLLAZY_OR_NOW\n#  ifdef RTLD_LAZY\n#    define LT_DLLAZY_OR_NOW\t\tRTLD_LAZY\n#  else\n#    ifdef DL_LAZY\n#      define LT_DLLAZY_OR_NOW\t\tDL_LAZY\n#    else\n#      ifdef RTLD_NOW\n#        define LT_DLLAZY_OR_NOW\tRTLD_NOW\n#      else\n#        ifdef DL_NOW\n#          define LT_DLLAZY_OR_NOW\tDL_NOW\n#        else\n#          define LT_DLLAZY_OR_NOW\t0\n#        endif\n#      endif\n#    endif\n#  endif\n#endif\n\n/* When -fvisbility=hidden is used, assume the code has been annotated\n   correspondingly for the symbols needed.  */\n#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))\nvoid fnord () __attribute__((visibility(\"default\")));\n#endif\n\nvoid fnord () { int i=42; }\nint main ()\n{\n  void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);\n  int status = $lt_dlunknown;\n\n  if (self)\n    {\n      if (dlsym (self,\"fnord\"))       status = $lt_dlno_uscore;\n      else\n        {\n\t  if (dlsym( self,\"_fnord\"))  status = $lt_dlneed_uscore;\n          else puts (dlerror ());\n\t}\n      /* dlclose (self); */\n    }\n  else\n    puts (dlerror ());\n\n  return status;\n}\n_LT_EOF\n  if { { eval echo \"\\\"\\$as_me\\\":${as_lineno-$LINENO}: \\\"$ac_link\\\"\"; } >&5\n  (eval $ac_link) 2>&5\n  ac_status=$?\n  $as_echo \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then\n    (./conftest; exit; ) >&5 2>/dev/null\n    lt_status=$?\n    case x$lt_status in\n      x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;;\n      x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;;\n      x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;;\n    esac\n  else :\n    # compilation failed\n    lt_cv_dlopen_self_static=no\n  fi\nfi\nrm -fr conftest*\n\n\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static\" >&5\n$as_echo \"$lt_cv_dlopen_self_static\" >&6; }\n    fi\n\n    CPPFLAGS=\"$save_CPPFLAGS\"\n    LDFLAGS=\"$save_LDFLAGS\"\n    LIBS=\"$save_LIBS\"\n    ;;\n  esac\n\n  case $lt_cv_dlopen_self in\n  yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;\n  *) enable_dlopen_self=unknown ;;\n  esac\n\n  case $lt_cv_dlopen_self_static in\n  yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;\n  *) enable_dlopen_self_static=unknown ;;\n  esac\nfi\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nstriplib=\nold_striplib=\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible\" >&5\n$as_echo_n \"checking whether stripping libraries is possible... \" >&6; }\nif test -n \"$STRIP\" && $STRIP -V 2>&1 | $GREP \"GNU strip\" >/dev/null; then\n  test -z \"$old_striplib\" && old_striplib=\"$STRIP --strip-debug\"\n  test -z \"$striplib\" && striplib=\"$STRIP --strip-unneeded\"\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\n$as_echo \"yes\" >&6; }\nelse\n# FIXME - insert some real tests, host_os isn't really good enough\n  case $host_os in\n  darwin*)\n    if test -n \"$STRIP\" ; then\n      striplib=\"$STRIP -x\"\n      old_striplib=\"$STRIP -S\"\n      { $as_echo \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\n$as_echo \"yes\" >&6; }\n    else\n      { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\n    fi\n    ;;\n  *)\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\n    ;;\n  esac\nfi\n\n\n\n\n\n\n\n\n\n\n\n\n  # Report which library types will actually be built\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries\" >&5\n$as_echo_n \"checking if libtool supports shared libraries... \" >&6; }\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $can_build_shared\" >&5\n$as_echo \"$can_build_shared\" >&6; }\n\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries\" >&5\n$as_echo_n \"checking whether to build shared libraries... \" >&6; }\n  test \"$can_build_shared\" = \"no\" && enable_shared=no\n\n  # On AIX, shared libraries and static libraries use the same namespace, and\n  # are all built from PIC.\n  case $host_os in\n  aix3*)\n    test \"$enable_shared\" = yes && enable_static=no\n    if test -n \"$RANLIB\"; then\n      archive_cmds=\"$archive_cmds~\\$RANLIB \\$lib\"\n      postinstall_cmds='$RANLIB $lib'\n    fi\n    ;;\n\n  aix[4-9]*)\n    if test \"$host_cpu\" != ia64 && test \"$aix_use_runtimelinking\" = no ; then\n      test \"$enable_shared\" = yes && enable_static=no\n    fi\n    ;;\n  esac\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $enable_shared\" >&5\n$as_echo \"$enable_shared\" >&6; }\n\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether to build static libraries\" >&5\n$as_echo_n \"checking whether to build static libraries... \" >&6; }\n  # Make sure either enable_shared or enable_static is yes.\n  test \"$enable_shared\" = yes || enable_static=yes\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $enable_static\" >&5\n$as_echo \"$enable_static\" >&6; }\n\n\n\n\nfi\nac_ext=c\nac_cpp='$CPP $CPPFLAGS'\nac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'\nac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'\nac_compiler_gnu=$ac_cv_c_compiler_gnu\n\nCC=\"$lt_save_CC\"\n\n\n\n\n\n\n\n\n\n\n\n\n\n        ac_config_commands=\"$ac_config_commands libtool\"\n\n\n\n\n# Only expand once:\n\n\n\n\n if test x$enable_darwin_at_rpath = xyes; then\n  ENABLE_DARWIN_AT_RPATH_TRUE=\n  ENABLE_DARWIN_AT_RPATH_FALSE='#'\nelse\n  ENABLE_DARWIN_AT_RPATH_TRUE='#'\n  ENABLE_DARWIN_AT_RPATH_FALSE=\nfi\n\n\n# Check whether --enable-largefile was given.\nif test \"${enable_largefile+set}\" = set; then :\n  enableval=$enable_largefile;\nfi\n\nif test \"$enable_largefile\" != no; then\n\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for special C compiler options needed for large files\" >&5\n$as_echo_n \"checking for special C compiler options needed for large files... \" >&6; }\nif ${ac_cv_sys_largefile_CC+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  ac_cv_sys_largefile_CC=no\n     if test \"$GCC\" != yes; then\n       ac_save_CC=$CC\n       while :; do\n\t # IRIX 6.2 and later do not support large files by default,\n\t # so use the C compiler's -n32 option if that helps.\n\t cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <sys/types.h>\n /* Check that off_t can represent 2**63 - 1 correctly.\n    We can't simply define LARGE_OFF_T to be 9223372036854775807,\n    since some C++ compilers masquerading as C compilers\n    incorrectly reject 9223372036854775807.  */\n#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))\n  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721\n\t\t       && LARGE_OFF_T % 2147483647 == 1)\n\t\t      ? 1 : -1];\nint\nmain ()\n{\n\n  ;\n  return 0;\n}\n_ACEOF\n\t if ac_fn_c_try_compile \"$LINENO\"; then :\n  break\nfi\nrm -f core conftest.err conftest.$ac_objext\n\t CC=\"$CC -n32\"\n\t if ac_fn_c_try_compile \"$LINENO\"; then :\n  ac_cv_sys_largefile_CC=' -n32'; break\nfi\nrm -f core conftest.err conftest.$ac_objext\n\t break\n       done\n       CC=$ac_save_CC\n       rm -f conftest.$ac_ext\n    fi\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_CC\" >&5\n$as_echo \"$ac_cv_sys_largefile_CC\" >&6; }\n  if test \"$ac_cv_sys_largefile_CC\" != no; then\n    CC=$CC$ac_cv_sys_largefile_CC\n  fi\n\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for _FILE_OFFSET_BITS value needed for large files\" >&5\n$as_echo_n \"checking for _FILE_OFFSET_BITS value needed for large files... \" >&6; }\nif ${ac_cv_sys_file_offset_bits+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  while :; do\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <sys/types.h>\n /* Check that off_t can represent 2**63 - 1 correctly.\n    We can't simply define LARGE_OFF_T to be 9223372036854775807,\n    since some C++ compilers masquerading as C compilers\n    incorrectly reject 9223372036854775807.  */\n#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))\n  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721\n\t\t       && LARGE_OFF_T % 2147483647 == 1)\n\t\t      ? 1 : -1];\nint\nmain ()\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  ac_cv_sys_file_offset_bits=no; break\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#define _FILE_OFFSET_BITS 64\n#include <sys/types.h>\n /* Check that off_t can represent 2**63 - 1 correctly.\n    We can't simply define LARGE_OFF_T to be 9223372036854775807,\n    since some C++ compilers masquerading as C compilers\n    incorrectly reject 9223372036854775807.  */\n#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))\n  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721\n\t\t       && LARGE_OFF_T % 2147483647 == 1)\n\t\t      ? 1 : -1];\nint\nmain ()\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  ac_cv_sys_file_offset_bits=64; break\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\n  ac_cv_sys_file_offset_bits=unknown\n  break\ndone\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_file_offset_bits\" >&5\n$as_echo \"$ac_cv_sys_file_offset_bits\" >&6; }\ncase $ac_cv_sys_file_offset_bits in #(\n  no | unknown) ;;\n  *)\ncat >>confdefs.h <<_ACEOF\n#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits\n_ACEOF\n;;\nesac\nrm -rf conftest*\n  if test $ac_cv_sys_file_offset_bits = unknown; then\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for _LARGE_FILES value needed for large files\" >&5\n$as_echo_n \"checking for _LARGE_FILES value needed for large files... \" >&6; }\nif ${ac_cv_sys_large_files+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  while :; do\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <sys/types.h>\n /* Check that off_t can represent 2**63 - 1 correctly.\n    We can't simply define LARGE_OFF_T to be 9223372036854775807,\n    since some C++ compilers masquerading as C compilers\n    incorrectly reject 9223372036854775807.  */\n#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))\n  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721\n\t\t       && LARGE_OFF_T % 2147483647 == 1)\n\t\t      ? 1 : -1];\nint\nmain ()\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  ac_cv_sys_large_files=no; break\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#define _LARGE_FILES 1\n#include <sys/types.h>\n /* Check that off_t can represent 2**63 - 1 correctly.\n    We can't simply define LARGE_OFF_T to be 9223372036854775807,\n    since some C++ compilers masquerading as C compilers\n    incorrectly reject 9223372036854775807.  */\n#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))\n  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721\n\t\t       && LARGE_OFF_T % 2147483647 == 1)\n\t\t      ? 1 : -1];\nint\nmain ()\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  ac_cv_sys_large_files=1; break\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\n  ac_cv_sys_large_files=unknown\n  break\ndone\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_large_files\" >&5\n$as_echo \"$ac_cv_sys_large_files\" >&6; }\ncase $ac_cv_sys_large_files in #(\n  no | unknown) ;;\n  *)\ncat >>confdefs.h <<_ACEOF\n#define _LARGE_FILES $ac_cv_sys_large_files\n_ACEOF\n;;\nesac\nrm -rf conftest*\n  fi\n\n\nfi\n\n\nbacktrace_supported=yes\n\nif test -n \"${with_target_subdir}\"; then\n  # We are compiling a GCC library.  We can assume that the unwind\n  # library exists.\n  BACKTRACE_FILE=\"backtrace.lo simple.lo\"\nelse\n  ac_fn_c_check_header_mongrel \"$LINENO\" \"unwind.h\" \"ac_cv_header_unwind_h\" \"$ac_includes_default\"\nif test \"x$ac_cv_header_unwind_h\" = xyes; then :\n  ac_fn_c_check_func \"$LINENO\" \"_Unwind_Backtrace\" \"ac_cv_func__Unwind_Backtrace\"\nif test \"x$ac_cv_func__Unwind_Backtrace\" = xyes; then :\n  BACKTRACE_FILE=\"backtrace.lo simple.lo\"\nelse\n  BACKTRACE_FILE=\"nounwind.lo\"\n                    backtrace_supported=no\nfi\n\nelse\n  BACKTRACE_FILE=\"nounwind.lo\"\n     backtrace_supported=no\nfi\n\n\nfi\n\n\nEXTRA_FLAGS=\nif test -n \"${with_target_subdir}\"; then\n  EXTRA_FLAGS=\"-funwind-tables -frandom-seed=\\$@\"\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for -funwind-tables option\" >&5\n$as_echo_n \"checking for -funwind-tables option... \" >&6; }\nif ${libbacktrace_cv_c_unwind_tables+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  CFLAGS_hold=\"$CFLAGS\"\n     CFLAGS=\"$CFLAGS -funwind-tables\"\n     cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\nstatic int f() { return 0; }\nint\nmain ()\n{\nreturn f();\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  libbacktrace_cv_c_unwind_tables=yes\nelse\n  libbacktrace_cv_c_unwind_tables=no\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\n     CFLAGS=\"$CFLAGS_hold\"\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $libbacktrace_cv_c_unwind_tables\" >&5\n$as_echo \"$libbacktrace_cv_c_unwind_tables\" >&6; }\n  if test \"$libbacktrace_cv_c_unwind_tables\" = \"yes\"; then\n    EXTRA_FLAGS=-funwind-tables\n  fi\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for -frandom-seed=string option\" >&5\n$as_echo_n \"checking for -frandom-seed=string option... \" >&6; }\nif ${libbacktrace_cv_c_random_seed_string+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  CFLAGS_hold=\"$CFLAGS\"\n     CFLAGS=\"$CFLAGS -frandom-seed=conftest.lo\"\n     cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain ()\n{\nreturn 0;\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  libbacktrace_cv_c_random_seed_string=yes\nelse\n  libbacktrace_cv_c_random_seed_string=no\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\n     CFLAGS=\"$CFLAGS_hold\"\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $libbacktrace_cv_c_random_seed_string\" >&5\n$as_echo \"$libbacktrace_cv_c_random_seed_string\" >&6; }\n  if test \"$libbacktrace_cv_c_random_seed_string\" = \"yes\"; then\n    EXTRA_FLAGS=\"$EXTRA_FLAGS -frandom-seed=\\$@\"\n  fi\nfi\n\n\nac_ext=c\nac_cpp='$CPP $CPPFLAGS'\nac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'\nac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'\nac_compiler_gnu=$ac_cv_c_compiler_gnu\n\nWARN_FLAGS=\nsave_CFLAGS=\"$CFLAGS\"\nfor real_option in -W -Wall -Wwrite-strings -Wstrict-prototypes \\\n\t\t\t  -Wmissing-prototypes -Wold-style-definition \\\n\t\t\t  -Wmissing-format-attribute -Wcast-qual \\\n\t\t\t  -Wno-attributes -Wno-unknown-attributes; do\n  # Do the check with the no- prefix removed since gcc silently\n  # accepts any -Wno-* option on purpose\n  case $real_option in\n    -Wno-*) option=-W`expr x$real_option : 'x-Wno-\\(.*\\)'` ;;\n    *) option=$real_option ;;\n  esac\n  as_acx_Woption=`$as_echo \"acx_cv_prog_cc_warning_$option\" | $as_tr_sh`\n\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether $CC supports $option\" >&5\n$as_echo_n \"checking whether $CC supports $option... \" >&6; }\nif eval \\${$as_acx_Woption+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  CFLAGS=\"$option\"\n    cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain ()\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  eval \"$as_acx_Woption=yes\"\nelse\n  eval \"$as_acx_Woption=no\"\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\n\nfi\neval ac_res=\\$$as_acx_Woption\n\t       { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_res\" >&5\n$as_echo \"$ac_res\" >&6; }\n  if test `eval 'as_val=${'$as_acx_Woption'};$as_echo \"$as_val\"'` = yes; then :\n  WARN_FLAGS=\"$WARN_FLAGS${WARN_FLAGS:+ }$real_option\"\nfi\n  done\nCFLAGS=\"$save_CFLAGS\"\nac_ext=c\nac_cpp='$CPP $CPPFLAGS'\nac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'\nac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'\nac_compiler_gnu=$ac_cv_c_compiler_gnu\n\n\n\n# Check whether --enable-werror was given.\nif test \"${enable_werror+set}\" = set; then :\n  enableval=$enable_werror;\nfi\n\nif test \"x$enable_werror\" != \"xno\" && test -n \"${with_target_subdir}\"; then :\n  WARN_FLAGS=\"$WARN_FLAGS -Werror\"\nfi\n\n\n\nif test -n \"${with_target_subdir}\"; then\n\n\n# Check whether --with-system-libunwind was given.\nif test \"${with_system_libunwind+set}\" = set; then :\n  withval=$with_system_libunwind;\nfi\n\n  # If system-libunwind was not specifically set, pick a default setting.\n  if test x$with_system_libunwind = x; then\n    case ${target} in\n      ia64-*-hpux*) with_system_libunwind=yes ;;\n      *) with_system_libunwind=no ;;\n    esac\n  fi\n  # Based on system-libunwind and target, do we have ipinfo?\n  if  test x$with_system_libunwind = xyes; then\n    case ${target} in\n      ia64-*-*) have_unwind_getipinfo=no ;;\n      *) have_unwind_getipinfo=yes ;;\n    esac\n  else\n    # Darwin before version 9 does not have _Unwind_GetIPInfo.\n\n    case ${target} in\n      *-*-darwin[3-8]|*-*-darwin[3-8].*) have_unwind_getipinfo=no ;;\n      *) have_unwind_getipinfo=yes ;;\n    esac\n\n  fi\n\n  if test x$have_unwind_getipinfo = xyes; then\n\n$as_echo \"#define HAVE_GETIPINFO 1\" >>confdefs.h\n\n  fi\n\nelse\n  ac_save_CFFLAGS=\"$CFLAGS\"\n  CFLAGS=\"$CFLAGS -Werror-implicit-function-declaration\"\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for _Unwind_GetIPInfo\" >&5\n$as_echo_n \"checking for _Unwind_GetIPInfo... \" >&6; }\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include \"unwind.h\"\n\tstruct _Unwind_Context *context;\n\tint ip_before_insn = 0;\nint\nmain ()\n{\nreturn _Unwind_GetIPInfo (context, &ip_before_insn);\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  have_unwind_getipinfo=yes\nelse\n  have_unwind_getipinfo=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\n  CFLAGS=\"$ac_save_CFLAGS\"\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $have_unwind_getipinfo\" >&5\n$as_echo \"$have_unwind_getipinfo\" >&6; }\n  if test \"$have_unwind_getipinfo\" = \"yes\"; then\n\n$as_echo \"#define HAVE_GETIPINFO 1\" >>confdefs.h\n\n  fi\nfi\n\n# Enable --enable-host-shared.\n# Check whether --enable-host-shared was given.\nif test \"${enable_host_shared+set}\" = set; then :\n  enableval=$enable_host_shared; PIC_FLAG=-fPIC\nelse\n  PIC_FLAG=\nfi\n\n\n\n# Test for __sync support.\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking __sync extensions\" >&5\n$as_echo_n \"checking __sync extensions... \" >&6; }\nif ${libbacktrace_cv_sys_sync+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"${with_target_subdir}\"; then\n   case \"${host}\" in\n   hppa*-*-hpux*) libbacktrace_cv_sys_sync=no ;;\n   *) libbacktrace_cv_sys_sync=yes ;;\n   esac\n else\n   cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\nint i;\nint\nmain ()\n{\n__sync_bool_compare_and_swap (&i, i, i);\n                       __sync_lock_test_and_set (&i, 1);\n                       __sync_lock_release (&i);\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  libbacktrace_cv_sys_sync=yes\nelse\n  libbacktrace_cv_sys_sync=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\n fi\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $libbacktrace_cv_sys_sync\" >&5\n$as_echo \"$libbacktrace_cv_sys_sync\" >&6; }\nBACKTRACE_SUPPORTS_THREADS=0\nif test \"$libbacktrace_cv_sys_sync\" = \"yes\"; then\n  BACKTRACE_SUPPORTS_THREADS=1\n\n$as_echo \"#define HAVE_SYNC_FUNCTIONS 1\" >>confdefs.h\n\nfi\n\n\n# Test for __atomic support.\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking __atomic extensions\" >&5\n$as_echo_n \"checking __atomic extensions... \" >&6; }\nif ${libbacktrace_cv_sys_atomic+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"${with_target_subdir}\"; then\n   libbacktrace_cv_sys_atomic=yes\n else\n   cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\nint i;\nint\nmain ()\n{\n__atomic_load_n (&i, __ATOMIC_ACQUIRE);\n\t\t       __atomic_store_n (&i, 1, __ATOMIC_RELEASE);\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  libbacktrace_cv_sys_atomic=yes\nelse\n  libbacktrace_cv_sys_atomic=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\n fi\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $libbacktrace_cv_sys_atomic\" >&5\n$as_echo \"$libbacktrace_cv_sys_atomic\" >&6; }\nif test \"$libbacktrace_cv_sys_atomic\" = \"yes\"; then\n\n$as_echo \"#define HAVE_ATOMIC_FUNCTIONS 1\" >>confdefs.h\n\nfi\n\n# The library needs to be able to read the executable itself.  Compile\n# a file to determine the executable format.  The awk script\n# filetype.awk prints out the file type.\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking output filetype\" >&5\n$as_echo_n \"checking output filetype... \" >&6; }\nif ${libbacktrace_cv_sys_filetype+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  filetype=\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\nint i;\nint\nmain ()\n{\nint j;\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  filetype=`${AWK} -f $srcdir/filetype.awk conftest.$ac_objext`\nelse\n  { { $as_echo \"$as_me:${as_lineno-$LINENO}: error: in \\`$ac_pwd':\" >&5\n$as_echo \"$as_me: error: in \\`$ac_pwd':\" >&2;}\nas_fn_error $? \"compiler failed\nSee \\`config.log' for more details\" \"$LINENO\" 5; }\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\nlibbacktrace_cv_sys_filetype=$filetype\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $libbacktrace_cv_sys_filetype\" >&5\n$as_echo \"$libbacktrace_cv_sys_filetype\" >&6; }\n\n# Match the file type to decide what files to compile.\nFORMAT_FILE=\nbacktrace_supports_data=yes\ncase \"$libbacktrace_cv_sys_filetype\" in\nelf*) FORMAT_FILE=\"elf.lo\" ;;\nmacho) FORMAT_FILE=\"macho.lo\" ;;\npecoff) FORMAT_FILE=\"pecoff.lo\"\n        backtrace_supports_data=no\n\t;;\nxcoff*) FORMAT_FILE=\"xcoff.lo\"\n        backtrace_supports_data=no\n        ;;\n*) { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: could not determine output file type\" >&5\n$as_echo \"$as_me: WARNING: could not determine output file type\" >&2;}\n   FORMAT_FILE=\"unknown.lo\"\n   backtrace_supported=no\n   ;;\nesac\n\n\n# ELF defines.\nelfsize=\ncase \"$libbacktrace_cv_sys_filetype\" in\nelf32) elfsize=32 ;;\nelf64) elfsize=64 ;;\n*)     elfsize=unused\nesac\n\ncat >>confdefs.h <<_ACEOF\n#define BACKTRACE_ELF_SIZE $elfsize\n_ACEOF\n\n if test \"$FORMAT_FILE\" = \"elf.lo\"; then\n  HAVE_ELF_TRUE=\n  HAVE_ELF_FALSE='#'\nelse\n  HAVE_ELF_TRUE='#'\n  HAVE_ELF_FALSE=\nfi\n\n\n# XCOFF defines.\nxcoffsize=\ncase \"$libbacktrace_cv_sys_filetype\" in\nxcoff32) xcoffsize=32 ;;\nxcoff64) xcoffsize=64 ;;\n*)       xcoffsize=unused\nesac\n\ncat >>confdefs.h <<_ACEOF\n#define BACKTRACE_XCOFF_SIZE $xcoffsize\n_ACEOF\n\n\nBACKTRACE_SUPPORTED=0\nif test \"$backtrace_supported\" = \"yes\"; then\n  BACKTRACE_SUPPORTED=1\nfi\n\n\nBACKTRACE_SUPPORTS_DATA=0\nif test \"$backtrace_supports_data\" = \"yes\"; then\n  BACKTRACE_SUPPORTS_DATA=1\nfi\n\n\nfor ac_header in sys/mman.h\ndo :\n  ac_fn_c_check_header_mongrel \"$LINENO\" \"sys/mman.h\" \"ac_cv_header_sys_mman_h\" \"$ac_includes_default\"\nif test \"x$ac_cv_header_sys_mman_h\" = xyes; then :\n  cat >>confdefs.h <<_ACEOF\n#define HAVE_SYS_MMAN_H 1\n_ACEOF\n\nfi\n\ndone\n\nif test \"$ac_cv_header_sys_mman_h\" = \"no\"; then\n  have_mmap=no\nelse\n  if test -n \"${with_target_subdir}\"; then\n    # When built as a GCC target library, we can't do a link test.  We\n    # simply assume that if we have mman.h, we have mmap.\n    have_mmap=yes\n    case \"${host}\" in\n    spu-*-*|*-*-msdosdjgpp)\n        # The SPU does not have mmap, but it has a sys/mman.h header file\n        # containing \"mmap_eaddr\" and the mmap flags, confusing the test.\n        # DJGPP also has sys/man.h, but no mmap\n\thave_mmap=no ;;\n    esac\n  else\n    ac_fn_c_check_func \"$LINENO\" \"mmap\" \"ac_cv_func_mmap\"\nif test \"x$ac_cv_func_mmap\" = xyes; then :\n  have_mmap=yes\nelse\n  have_mmap=no\nfi\n\n  fi\nfi\nif test \"$have_mmap\" = \"no\"; then\n  VIEW_FILE=read.lo\n  ALLOC_FILE=alloc.lo\nelse\n  VIEW_FILE=mmapio.lo\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n#include <sys/mman.h>\n#if !defined(MAP_ANONYMOUS) && !defined(MAP_ANON)\n  #error no MAP_ANONYMOUS\n#endif\n\n_ACEOF\nif ac_fn_c_try_cpp \"$LINENO\"; then :\n  ALLOC_FILE=mmap.lo\nelse\n  ALLOC_FILE=alloc.lo\nfi\nrm -f conftest.err conftest.i conftest.$ac_ext\nfi\n\n\n\nBACKTRACE_USES_MALLOC=0\nif test \"$ALLOC_FILE\" = \"alloc.lo\"; then\n  BACKTRACE_USES_MALLOC=1\nfi\n\n\n# Check for dl_iterate_phdr.\nfor ac_header in link.h sys/link.h\ndo :\n  as_ac_Header=`$as_echo \"ac_cv_header_$ac_header\" | $as_tr_sh`\nac_fn_c_check_header_mongrel \"$LINENO\" \"$ac_header\" \"$as_ac_Header\" \"$ac_includes_default\"\nif eval test \\\"x\\$\"$as_ac_Header\"\\\" = x\"yes\"; then :\n  cat >>confdefs.h <<_ACEOF\n#define `$as_echo \"HAVE_$ac_header\" | $as_tr_cpp` 1\n_ACEOF\n\nfi\n\ndone\n\nif test \"$ac_cv_header_link_h\" = \"no\" -a \"$ac_cv_header_sys_link_h\" = \"no\"; then\n  have_dl_iterate_phdr=no\nelse\n  if test -n \"${with_target_subdir}\"; then\n    link_h=link.h\n    if test \"$ac_cv_header_link_h\" = \"no\"; then\n       link_h=sys/link.h\n    fi\n    # When built as a GCC target library, we can't do a link test.\n    cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <$link_h>\n\n_ACEOF\nif (eval \"$ac_cpp conftest.$ac_ext\") 2>&5 |\n  $EGREP \"dl_iterate_phdr\" >/dev/null 2>&1; then :\n  have_dl_iterate_phdr=yes\nelse\n  have_dl_iterate_phdr=no\nfi\nrm -f conftest*\n\n    case \"${host}\" in\n    *-*-solaris2.10*)\n        # Avoid dl_iterate_phdr on Solaris 10, where it is in the\n    \t# header file but is only in -ldl.\n\thave_dl_iterate_phdr=no ;;\n    esac\n  else\n    ac_fn_c_check_func \"$LINENO\" \"dl_iterate_phdr\" \"ac_cv_func_dl_iterate_phdr\"\nif test \"x$ac_cv_func_dl_iterate_phdr\" = xyes; then :\n  have_dl_iterate_phdr=yes\nelse\n  have_dl_iterate_phdr=no\nfi\n\n  fi\nfi\nif test \"$have_dl_iterate_phdr\" = \"yes\"; then\n\n$as_echo \"#define HAVE_DL_ITERATE_PHDR 1\" >>confdefs.h\n\nfi\n\n# Check for header file for Mach-O image functions.\nfor ac_header in mach-o/dyld.h\ndo :\n  ac_fn_c_check_header_mongrel \"$LINENO\" \"mach-o/dyld.h\" \"ac_cv_header_mach_o_dyld_h\" \"$ac_includes_default\"\nif test \"x$ac_cv_header_mach_o_dyld_h\" = xyes; then :\n  cat >>confdefs.h <<_ACEOF\n#define HAVE_MACH_O_DYLD_H 1\n_ACEOF\n\nfi\n\ndone\n\n\n# Check for loadquery.\nfor ac_header in sys/ldr.h\ndo :\n  ac_fn_c_check_header_mongrel \"$LINENO\" \"sys/ldr.h\" \"ac_cv_header_sys_ldr_h\" \"$ac_includes_default\"\nif test \"x$ac_cv_header_sys_ldr_h\" = xyes; then :\n  cat >>confdefs.h <<_ACEOF\n#define HAVE_SYS_LDR_H 1\n_ACEOF\n\nfi\n\ndone\n\nif test \"$ac_cv_header_sys_ldr_h\" = \"no\"; then\n  have_loadquery=no\nelse\n  if test -n \"${with_target_subdir}\"; then\n    # When built as a GCC target library, we can't do a link test.\n    cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <sys/ldr.h>\n\n_ACEOF\nif (eval \"$ac_cpp conftest.$ac_ext\") 2>&5 |\n  $EGREP \"loadquery\" >/dev/null 2>&1; then :\n  have_loadquery=yes\nelse\n  have_loadquery=no\nfi\nrm -f conftest*\n\n  else\n    ac_fn_c_check_func \"$LINENO\" \"loadquery\" \"ac_cv_func_loadquery\"\nif test \"x$ac_cv_func_loadquery\" = xyes; then :\n  have_loadquery=yes\nelse\n  have_loadquery=no\nfi\n\n  fi\nfi\nif test \"$have_loadquery\" = \"yes\"; then\n\n$as_echo \"#define HAVE_LOADQUERY 1\" >>confdefs.h\n\nfi\n\nfor ac_header in windows.h\ndo :\n  ac_fn_c_check_header_mongrel \"$LINENO\" \"windows.h\" \"ac_cv_header_windows_h\" \"$ac_includes_default\"\nif test \"x$ac_cv_header_windows_h\" = xyes; then :\n  cat >>confdefs.h <<_ACEOF\n#define HAVE_WINDOWS_H 1\n_ACEOF\n\nfi\n\ndone\n\nfor ac_header in tlhelp32.h\ndo :\n  ac_fn_c_check_header_compile \"$LINENO\" \"tlhelp32.h\" \"ac_cv_header_tlhelp32_h\" \"#ifdef HAVE_WINDOWS_H\n#  include <windows.h>\n#endif\n\"\nif test \"x$ac_cv_header_tlhelp32_h\" = xyes; then :\n  cat >>confdefs.h <<_ACEOF\n#define HAVE_TLHELP32_H 1\n_ACEOF\n\nfi\n\ndone\n\n\n# Check for the fcntl function.\nif test -n \"${with_target_subdir}\"; then\n   case \"${host}\" in\n   *-*-mingw*) have_fcntl=no ;;\n   spu-*-*) have_fcntl=no ;;\n   *) have_fcntl=yes ;;\n   esac\nelse\n  ac_fn_c_check_func \"$LINENO\" \"fcntl\" \"ac_cv_func_fcntl\"\nif test \"x$ac_cv_func_fcntl\" = xyes; then :\n  have_fcntl=yes\nelse\n  have_fcntl=no\nfi\n\nfi\nif test \"$have_fcntl\" = \"yes\"; then\n\n$as_echo \"#define HAVE_FCNTL 1\" >>confdefs.h\n\nfi\n\nac_fn_c_check_decl \"$LINENO\" \"strnlen\" \"ac_cv_have_decl_strnlen\" \"$ac_includes_default\"\nif test \"x$ac_cv_have_decl_strnlen\" = xyes; then :\n  ac_have_decl=1\nelse\n  ac_have_decl=0\nfi\n\ncat >>confdefs.h <<_ACEOF\n#define HAVE_DECL_STRNLEN $ac_have_decl\n_ACEOF\nac_fn_c_check_decl \"$LINENO\" \"getpagesize\" \"ac_cv_have_decl_getpagesize\" \"$ac_includes_default\"\nif test \"x$ac_cv_have_decl_getpagesize\" = xyes; then :\n  ac_have_decl=1\nelse\n  ac_have_decl=0\nfi\n\ncat >>confdefs.h <<_ACEOF\n#define HAVE_DECL_GETPAGESIZE $ac_have_decl\n_ACEOF\n\nfor ac_func in lstat readlink\ndo :\n  as_ac_var=`$as_echo \"ac_cv_func_$ac_func\" | $as_tr_sh`\nac_fn_c_check_func \"$LINENO\" \"$ac_func\" \"$as_ac_var\"\nif eval test \\\"x\\$\"$as_ac_var\"\\\" = x\"yes\"; then :\n  cat >>confdefs.h <<_ACEOF\n#define `$as_echo \"HAVE_$ac_func\" | $as_tr_cpp` 1\n_ACEOF\n\nfi\ndone\n\n\n# Check for getexecname function.\nif test -n \"${with_target_subdir}\"; then\n   case \"${host}\" in\n   *-*-solaris2*) have_getexecname=yes ;;\n   *) have_getexecname=no ;;\n   esac\nelse\n  ac_fn_c_check_func \"$LINENO\" \"getexecname\" \"ac_cv_func_getexecname\"\nif test \"x$ac_cv_func_getexecname\" = xyes; then :\n  have_getexecname=yes\nelse\n  have_getexecname=no\nfi\n\nfi\nif test \"$have_getexecname\" = \"yes\"; then\n\n$as_echo \"#define HAVE_GETEXECNAME 1\" >>confdefs.h\n\nfi\n\n# Check for _pgmptr variable, contains the executable filename on windows\nac_fn_c_check_decl \"$LINENO\" \"_pgmptr\" \"ac_cv_have_decl__pgmptr\" \"$ac_includes_default\"\nif test \"x$ac_cv_have_decl__pgmptr\" = xyes; then :\n  ac_have_decl=1\nelse\n  ac_have_decl=0\nfi\n\ncat >>confdefs.h <<_ACEOF\n#define HAVE_DECL__PGMPTR $ac_have_decl\n_ACEOF\n\n\n# Check for sysctl definitions.\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for KERN_PROC\" >&5\n$as_echo_n \"checking for KERN_PROC... \" >&6; }\nif ${libbacktrace_cv_proc+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n#include <sys/types.h>\n#include <sys/sysctl.h>\n\nint\nmain ()\n{\nint mib0 = CTL_KERN; int mib1 = KERN_PROC; int mib2 = KERN_PROC_PATHNAME;\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  libbacktrace_cv_proc=yes\nelse\n  libbacktrace_cv_proc=no\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $libbacktrace_cv_proc\" >&5\n$as_echo \"$libbacktrace_cv_proc\" >&6; }\nif test \"$libbacktrace_cv_proc\" = \"yes\"; then\n\n$as_echo \"#define HAVE_KERN_PROC 1\" >>confdefs.h\n\nfi\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for KERN_PROG_ARGS\" >&5\n$as_echo_n \"checking for KERN_PROG_ARGS... \" >&6; }\nif ${libbacktrace_cv_procargs+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n#include <sys/types.h>\n#include <sys/sysctl.h>\n\nint\nmain ()\n{\nint mib0 = CTL_KERN; int mib1 = KERN_PROC_ARGS; int mib2 = KERN_PROC_PATHNAME;\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  libbacktrace_cv_procargs=yes\nelse\n  libbacktrace_cv_procargs=no\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $libbacktrace_cv_procargs\" >&5\n$as_echo \"$libbacktrace_cv_procargs\" >&6; }\nif test \"$libbacktrace_cv_procargs\" = \"yes\"; then\n\n$as_echo \"#define HAVE_KERN_PROC_ARGS 1\" >>confdefs.h\n\nfi\n\n# Check for the clock_gettime function.\nfor ac_func in clock_gettime\ndo :\n  ac_fn_c_check_func \"$LINENO\" \"clock_gettime\" \"ac_cv_func_clock_gettime\"\nif test \"x$ac_cv_func_clock_gettime\" = xyes; then :\n  cat >>confdefs.h <<_ACEOF\n#define HAVE_CLOCK_GETTIME 1\n_ACEOF\n\nfi\ndone\n\nclock_gettime_link=\n# At least for glibc, clock_gettime is in librt.  But don't\n# pull that in if it still doesn't give us the function we want.  This\n# test is copied from libgomp, and modified to not link in -lrt as\n# we're using this for test timing only.\nif test \"$ac_cv_func_clock_gettime\" = no; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for clock_gettime in -lrt\" >&5\n$as_echo_n \"checking for clock_gettime in -lrt... \" >&6; }\nif ${ac_cv_lib_rt_clock_gettime+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  ac_check_lib_save_LIBS=$LIBS\nLIBS=\"-lrt  $LIBS\"\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n/* Override any GCC internal prototype to avoid an error.\n   Use char because int might match the return type of a GCC\n   builtin and then its argument prototype would still apply.  */\n#ifdef __cplusplus\nextern \"C\"\n#endif\nchar clock_gettime ();\nint\nmain ()\n{\nreturn clock_gettime ();\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  ac_cv_lib_rt_clock_gettime=yes\nelse\n  ac_cv_lib_rt_clock_gettime=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nLIBS=$ac_check_lib_save_LIBS\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_clock_gettime\" >&5\n$as_echo \"$ac_cv_lib_rt_clock_gettime\" >&6; }\nif test \"x$ac_cv_lib_rt_clock_gettime\" = xyes; then :\n  CLOCK_GETTIME_LINK=-lrt\n\n$as_echo \"#define HAVE_CLOCK_GETTIME 1\" >>confdefs.h\n\nfi\n\nfi\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether -pthread is supported\" >&5\n$as_echo_n \"checking whether -pthread is supported... \" >&6; }\nif ${libgo_cv_lib_pthread+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  CFLAGS_hold=$CFLAGS\nCFLAGS=\"$CFLAGS -pthread\"\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\nint i;\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  libgo_cv_lib_pthread=yes\nelse\n  libgo_cv_lib_pthread=no\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\nCFLAGS=$CFLAGS_hold\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $libgo_cv_lib_pthread\" >&5\n$as_echo \"$libgo_cv_lib_pthread\" >&6; }\nPTHREAD_CFLAGS=\nif test \"$libgo_cv_lib_pthread\" = yes; then\n  PTHREAD_CFLAGS=-pthread\nfi\n\n\n if test \"$libgo_cv_lib_pthread\" = yes; then\n  HAVE_PTHREAD_TRUE=\n  HAVE_PTHREAD_FALSE='#'\nelse\n  HAVE_PTHREAD_TRUE='#'\n  HAVE_PTHREAD_FALSE=\nfi\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether -gdwarf-5 is supported\" >&5\n$as_echo_n \"checking whether -gdwarf-5 is supported... \" >&6; }\nif ${libbacktrace_cv_lib_dwarf5+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  CFLAGS_hold=$CFLAGS\nCFLAGS=\"$CFLAGS -gdwarf-5\"\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\nint i;\nint\nmain ()\n{\nreturn 0;\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  libbacktrace_cv_lib_dwarf5=yes\nelse\n  libbacktrace_cv_lib_dwarf5=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nCFLAGS=$CFLAGS_hold\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $libbacktrace_cv_lib_dwarf5\" >&5\n$as_echo \"$libbacktrace_cv_lib_dwarf5\" >&6; }\n if test \"$libbacktrace_cv_lib_dwarf5\" = yes; then\n  HAVE_DWARF5_TRUE=\n  HAVE_DWARF5_FALSE='#'\nelse\n  HAVE_DWARF5_TRUE='#'\n  HAVE_DWARF5_FALSE=\nfi\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for compress in -lz\" >&5\n$as_echo_n \"checking for compress in -lz... \" >&6; }\nif ${ac_cv_lib_z_compress+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  ac_check_lib_save_LIBS=$LIBS\nLIBS=\"-lz  $LIBS\"\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n/* Override any GCC internal prototype to avoid an error.\n   Use char because int might match the return type of a GCC\n   builtin and then its argument prototype would still apply.  */\n#ifdef __cplusplus\nextern \"C\"\n#endif\nchar compress ();\nint\nmain ()\n{\nreturn compress ();\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  ac_cv_lib_z_compress=yes\nelse\n  ac_cv_lib_z_compress=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nLIBS=$ac_check_lib_save_LIBS\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_compress\" >&5\n$as_echo \"$ac_cv_lib_z_compress\" >&6; }\nif test \"x$ac_cv_lib_z_compress\" = xyes; then :\n\n$as_echo \"#define HAVE_ZLIB 1\" >>confdefs.h\n\nfi\n\n if test \"$ac_cv_lib_z_compress\" = yes; then\n  HAVE_ZLIB_TRUE=\n  HAVE_ZLIB_FALSE='#'\nelse\n  HAVE_ZLIB_TRUE='#'\n  HAVE_ZLIB_FALSE=\nfi\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether --build-id is supported\" >&5\n$as_echo_n \"checking whether --build-id is supported... \" >&6; }\nif ${libbacktrace_cv_ld_buildid+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  LDFLAGS_hold=$LDFLAGS\nLDFLAGS=\"$LDFLAGS -Wl,--build-id\"\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain ()\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  libbacktrace_cv_ld_buildid=yes\nelse\n  libbacktrace_cv_ld_buildid=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nLDFLAGS=$LDFLAGS_hold\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $libbacktrace_cv_ld_buildid\" >&5\n$as_echo \"$libbacktrace_cv_ld_buildid\" >&6; }\n if test \"$libbacktrace_cv_ld_buildid\" = yes; then\n  HAVE_BUILDID_TRUE=\n  HAVE_BUILDID_FALSE='#'\nelse\n  HAVE_BUILDID_TRUE='#'\n  HAVE_BUILDID_FALSE=\nfi\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether --compress-debug-sections=zlib-gnu is supported\" >&5\n$as_echo_n \"checking whether --compress-debug-sections=zlib-gnu is supported... \" >&6; }\nif ${libgo_cv_ld_compress_zlib_gnu+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  LDFLAGS_hold=$LDFLAGS\nLDFLAGS=\"$LDFLAGS -Wl,--compress-debug-sections=zlib-gnu\"\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain ()\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  libgo_cv_ld_compress_zlib_gnu=yes\nelse\n  libgo_cv_ld_compress_zlib_gnu=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nLDFLAGS=$LDFLAGS_hold\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $libgo_cv_ld_compress_zlib_gnu\" >&5\n$as_echo \"$libgo_cv_ld_compress_zlib_gnu\" >&6; }\n if test \"$libgo_cv_ld_compress_zlib_gnu\" = yes; then\n  HAVE_COMPRESSED_DEBUG_ZLIB_GNU_TRUE=\n  HAVE_COMPRESSED_DEBUG_ZLIB_GNU_FALSE='#'\nelse\n  HAVE_COMPRESSED_DEBUG_ZLIB_GNU_TRUE='#'\n  HAVE_COMPRESSED_DEBUG_ZLIB_GNU_FALSE=\nfi\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether --compress-debug-sections=zlib-gabi is supported\" >&5\n$as_echo_n \"checking whether --compress-debug-sections=zlib-gabi is supported... \" >&6; }\nif ${libgo_cv_ld_compress_zlib_gabi+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  LDFLAGS_hold=$LDFLAGS\nLDFLAGS=\"$LDFLAGS -Wl,--compress-debug-sections=zlib-gabi\"\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain ()\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  libgo_cv_ld_compress_zlib_gabi=yes\nelse\n  libgo_cv_ld_compress_zlib_gabi=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nLDFLAGS=$LDFLAGS_hold\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $libgo_cv_ld_compress_zlib_gabi\" >&5\n$as_echo \"$libgo_cv_ld_compress_zlib_gabi\" >&6; }\n if test \"$libgo_cv_ld_compress_zlib_gabi\" = yes; then\n  HAVE_COMPRESSED_DEBUG_ZLIB_GABI_TRUE=\n  HAVE_COMPRESSED_DEBUG_ZLIB_GABI_FALSE='#'\nelse\n  HAVE_COMPRESSED_DEBUG_ZLIB_GABI_TRUE='#'\n  HAVE_COMPRESSED_DEBUG_ZLIB_GABI_FALSE=\nfi\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for ZSTD_compress in -lzstd\" >&5\n$as_echo_n \"checking for ZSTD_compress in -lzstd... \" >&6; }\nif ${ac_cv_lib_zstd_ZSTD_compress+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  ac_check_lib_save_LIBS=$LIBS\nLIBS=\"-lzstd  $LIBS\"\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n/* Override any GCC internal prototype to avoid an error.\n   Use char because int might match the return type of a GCC\n   builtin and then its argument prototype would still apply.  */\n#ifdef __cplusplus\nextern \"C\"\n#endif\nchar ZSTD_compress ();\nint\nmain ()\n{\nreturn ZSTD_compress ();\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  ac_cv_lib_zstd_ZSTD_compress=yes\nelse\n  ac_cv_lib_zstd_ZSTD_compress=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nLIBS=$ac_check_lib_save_LIBS\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_zstd_ZSTD_compress\" >&5\n$as_echo \"$ac_cv_lib_zstd_ZSTD_compress\" >&6; }\nif test \"x$ac_cv_lib_zstd_ZSTD_compress\" = xyes; then :\n\n$as_echo \"#define HAVE_ZSTD 1\" >>confdefs.h\n\nfi\n\n if test \"$ac_cv_lib_zstd_ZSTD_compress\" = yes; then\n  HAVE_ZSTD_TRUE=\n  HAVE_ZSTD_FALSE='#'\nelse\n  HAVE_ZSTD_TRUE='#'\n  HAVE_ZSTD_FALSE=\nfi\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether --compress-debug-sections=zstd is supported\" >&5\n$as_echo_n \"checking whether --compress-debug-sections=zstd is supported... \" >&6; }\nif ${libgo_cv_ld_compress_zstd+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  LDFLAGS_hold=$LDFLAGS\nLDFLAGS=\"$LDFLAGS -Wl,--compress-debug-sections=zstd\"\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain ()\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  libgo_cv_ld_compress_zstd=yes\nelse\n  libgo_cv_ld_compress_zstd=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nLDFLAGS=$LDFLAGS_hold\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $libgo_cv_ld_compress_zstd\" >&5\n$as_echo \"$libgo_cv_ld_compress_zstd\" >&6; }\n if test \"$libgo_cv_ld_compress_zstd\" = yes; then\n  HAVE_COMPRESSED_DEBUG_ZSTD_TRUE=\n  HAVE_COMPRESSED_DEBUG_ZSTD_FALSE='#'\nelse\n  HAVE_COMPRESSED_DEBUG_ZSTD_TRUE='#'\n  HAVE_COMPRESSED_DEBUG_ZSTD_FALSE=\nfi\n\n\n\n# Extract the first word of \"objcopy\", so it can be a program name with args.\nset dummy objcopy; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_OBJCOPY+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$OBJCOPY\"; then\n  ac_cv_prog_OBJCOPY=\"$OBJCOPY\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_OBJCOPY=\"objcopy\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nOBJCOPY=$ac_cv_prog_OBJCOPY\nif test -n \"$OBJCOPY\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $OBJCOPY\" >&5\n$as_echo \"$OBJCOPY\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\n# Extract the first word of \"readelf\", so it can be a program name with args.\nset dummy readelf; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_READELF+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$READELF\"; then\n  ac_cv_prog_READELF=\"$READELF\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_READELF=\"readelf\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nREADELF=$ac_cv_prog_READELF\nif test -n \"$READELF\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $READELF\" >&5\n$as_echo \"$READELF\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether objcopy supports debuglink\" >&5\n$as_echo_n \"checking whether objcopy supports debuglink... \" >&6; }\nif ${libbacktrace_cv_objcopy_debuglink+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"${with_target_subdir}\"; then\n  libbacktrace_cv_objcopy_debuglink=no\nelif ! test -n \"${OBJCOPY}\"; then\n  libbacktrace_cv_objcopy_debuglink=no\nelif ${OBJCOPY} --help | grep add-gnu-debuglink >/dev/null 2>&1; then\n  libbacktrace_cv_objcopy_debuglink=yes\nelse\n  libbacktrace_cv_objcopy_debuglink=no\nfi\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $libbacktrace_cv_objcopy_debuglink\" >&5\n$as_echo \"$libbacktrace_cv_objcopy_debuglink\" >&6; }\n if test \"$libbacktrace_cv_objcopy_debuglink\" = yes; then\n  HAVE_OBJCOPY_DEBUGLINK_TRUE=\n  HAVE_OBJCOPY_DEBUGLINK_FALSE='#'\nelse\n  HAVE_OBJCOPY_DEBUGLINK_TRUE='#'\n  HAVE_OBJCOPY_DEBUGLINK_FALSE=\nfi\n\n\n\n# Extract the first word of \"dsymutil\", so it can be a program name with args.\nset dummy dsymutil; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_DSYMUTIL+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$DSYMUTIL\"; then\n  ac_cv_prog_DSYMUTIL=\"$DSYMUTIL\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_DSYMUTIL=\"dsymutil\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nDSYMUTIL=$ac_cv_prog_DSYMUTIL\nif test -n \"$DSYMUTIL\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL\" >&5\n$as_echo \"$DSYMUTIL\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\n if test -n \"${DSYMUTIL}\" -a \"$FORMAT_FILE\" = \"macho.lo\"; then\n  USE_DSYMUTIL_TRUE=\n  USE_DSYMUTIL_FALSE='#'\nelse\n  USE_DSYMUTIL_TRUE='#'\n  USE_DSYMUTIL_FALSE=\nfi\n\n\n\n# Extract the first word of \"nm\", so it can be a program name with args.\nset dummy nm; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_NM+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$NM\"; then\n  ac_cv_prog_NM=\"$NM\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_NM=\"nm\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nNM=$ac_cv_prog_NM\nif test -n \"$NM\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $NM\" >&5\n$as_echo \"$NM\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\n\n# Extract the first word of \"xz\", so it can be a program name with args.\nset dummy xz; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_XZ+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$XZ\"; then\n  ac_cv_prog_XZ=\"$XZ\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_XZ=\"xz\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nXZ=$ac_cv_prog_XZ\nif test -n \"$XZ\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $XZ\" >&5\n$as_echo \"$XZ\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\n if test \"$XZ\" != \"\"; then\n  HAVE_XZ_TRUE=\n  HAVE_XZ_FALSE='#'\nelse\n  HAVE_XZ_TRUE='#'\n  HAVE_XZ_FALSE=\nfi\n\n# Extract the first word of \"comm\", so it can be a program name with args.\nset dummy comm; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_COMM+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$COMM\"; then\n  ac_cv_prog_COMM=\"$COMM\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_COMM=\"comm\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nCOMM=$ac_cv_prog_COMM\nif test -n \"$COMM\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $COMM\" >&5\n$as_echo \"$COMM\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\n if test \"$COMM\" != \"\"; then\n  HAVE_COMM_TRUE=\n  HAVE_COMM_FALSE='#'\nelse\n  HAVE_COMM_TRUE='#'\n  HAVE_COMM_FALSE=\nfi\n\n\n if test \"${with_target_subdir}\" = \"\" -a \"$FORMAT_FILE\" = \"elf.lo\" -a \"${OBJCOPY}\" != \"\" -a \"${NM}\" != \"\" -a \"${XZ}\" != \"\" -a \"${COMM}\" != \"\"; then\n  HAVE_MINIDEBUG_TRUE=\n  HAVE_MINIDEBUG_FALSE='#'\nelse\n  HAVE_MINIDEBUG_TRUE='#'\n  HAVE_MINIDEBUG_FALSE=\nfi\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for lzma_auto_decoder in -llzma\" >&5\n$as_echo_n \"checking for lzma_auto_decoder in -llzma... \" >&6; }\nif ${ac_cv_lib_lzma_lzma_auto_decoder+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  ac_check_lib_save_LIBS=$LIBS\nLIBS=\"-llzma  $LIBS\"\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n/* Override any GCC internal prototype to avoid an error.\n   Use char because int might match the return type of a GCC\n   builtin and then its argument prototype would still apply.  */\n#ifdef __cplusplus\nextern \"C\"\n#endif\nchar lzma_auto_decoder ();\nint\nmain ()\n{\nreturn lzma_auto_decoder ();\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  ac_cv_lib_lzma_lzma_auto_decoder=yes\nelse\n  ac_cv_lib_lzma_lzma_auto_decoder=no\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nLIBS=$ac_check_lib_save_LIBS\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lzma_lzma_auto_decoder\" >&5\n$as_echo \"$ac_cv_lib_lzma_lzma_auto_decoder\" >&6; }\nif test \"x$ac_cv_lib_lzma_lzma_auto_decoder\" = xyes; then :\n\n$as_echo \"#define HAVE_LIBLZMA 1\" >>confdefs.h\n\nfi\n\n if test \"$ac_cv_lib_lzma_lzma_auto_decoder\" = yes; then\n  HAVE_LIBLZMA_TRUE=\n  HAVE_LIBLZMA_FALSE='#'\nelse\n  HAVE_LIBLZMA_TRUE='#'\n  HAVE_LIBLZMA_FALSE=\nfi\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether tests can run\" >&5\n$as_echo_n \"checking whether tests can run... \" >&6; }\nif ${libbacktrace_cv_sys_native+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test \"$cross_compiling\" = yes; then :\n  libbacktrace_cv_sys_native=no\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain ()\n{\nreturn 0;\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_run \"$LINENO\"; then :\n  libbacktrace_cv_sys_native=yes\nelse\n  libbacktrace_cv_sys_native=no\nfi\nrm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \\\n  conftest.$ac_objext conftest.beam conftest.$ac_ext\nfi\n\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $libbacktrace_cv_sys_native\" >&5\n$as_echo \"$libbacktrace_cv_sys_native\" >&6; }\n if test \"$libbacktrace_cv_sys_native\" = \"yes\"; then\n  NATIVE_TRUE=\n  NATIVE_FALSE='#'\nelse\n  NATIVE_TRUE='#'\n  NATIVE_FALSE=\nfi\n\n\nif test \"${multilib}\" = \"yes\"; then\n  multilib_arg=\"--enable-multilib\"\nelse\n  multilib_arg=\nfi\n\nac_config_files=\"$ac_config_files Makefile backtrace-supported.h\"\n\nac_config_files=\"$ac_config_files install-debuginfo-for-buildid.sh\"\n\n\n# We need multilib support, but only if configuring for the target.\nac_config_commands=\"$ac_config_commands default\"\n\n\ncat >confcache <<\\_ACEOF\n# This file is a shell script that caches the results of configure\n# tests run on this system so they can be shared between configure\n# scripts and configure runs, see configure's option --config-cache.\n# It is not useful on other systems.  If it contains results you don't\n# want to keep, you may remove or edit it.\n#\n# config.status only pays attention to the cache file if you give it\n# the --recheck option to rerun configure.\n#\n# `ac_cv_env_foo' variables (set or unset) will be overridden when\n# loading this file, other *unset* `ac_cv_foo' will be assigned the\n# following values.\n\n_ACEOF\n\n# The following way of writing the cache mishandles newlines in values,\n# but we know of no workaround that is simple, portable, and efficient.\n# So, we kill variables containing newlines.\n# Ultrix sh set writes to stderr and can't be redirected directly,\n# and sets the high bit in the cache file unless we assign to the vars.\n(\n  for ac_var in `(set) 2>&1 | sed -n 's/^\\([a-zA-Z_][a-zA-Z0-9_]*\\)=.*/\\1/p'`; do\n    eval ac_val=\\$$ac_var\n    case $ac_val in #(\n    *${as_nl}*)\n      case $ac_var in #(\n      *_cv_*) { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline\" >&5\n$as_echo \"$as_me: WARNING: cache variable $ac_var contains a newline\" >&2;} ;;\n      esac\n      case $ac_var in #(\n      _ | IFS | as_nl) ;; #(\n      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(\n      *) { eval $ac_var=; unset $ac_var;} ;;\n      esac ;;\n    esac\n  done\n\n  (set) 2>&1 |\n    case $as_nl`(ac_space=' '; set) 2>&1` in #(\n    *${as_nl}ac_space=\\ *)\n      # `set' does not quote correctly, so add quotes: double-quote\n      # substitution turns \\\\\\\\ into \\\\, and sed turns \\\\ into \\.\n      sed -n \\\n\t\"s/'/'\\\\\\\\''/g;\n\t  s/^\\\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\\\)=\\\\(.*\\\\)/\\\\1='\\\\2'/p\"\n      ;; #(\n    *)\n      # `set' quotes correctly as required by POSIX, so do not add quotes.\n      sed -n \"/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p\"\n      ;;\n    esac |\n    sort\n) |\n  sed '\n     /^ac_cv_env_/b end\n     t clear\n     :clear\n     s/^\\([^=]*\\)=\\(.*[{}].*\\)$/test \"${\\1+set}\" = set || &/\n     t end\n     s/^\\([^=]*\\)=\\(.*\\)$/\\1=${\\1=\\2}/\n     :end' >>confcache\nif diff \"$cache_file\" confcache >/dev/null 2>&1; then :; else\n  if test -w \"$cache_file\"; then\n    if test \"x$cache_file\" != \"x/dev/null\"; then\n      { $as_echo \"$as_me:${as_lineno-$LINENO}: updating cache $cache_file\" >&5\n$as_echo \"$as_me: updating cache $cache_file\" >&6;}\n      if test ! -f \"$cache_file\" || test -h \"$cache_file\"; then\n\tcat confcache >\"$cache_file\"\n      else\n        case $cache_file in #(\n        */* | ?:*)\n\t  mv -f confcache \"$cache_file\"$$ &&\n\t  mv -f \"$cache_file\"$$ \"$cache_file\" ;; #(\n        *)\n\t  mv -f confcache \"$cache_file\" ;;\n\tesac\n      fi\n    fi\n  else\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file\" >&5\n$as_echo \"$as_me: not updating unwritable cache $cache_file\" >&6;}\n  fi\nfi\nrm -f confcache\n\ntest \"x$prefix\" = xNONE && prefix=$ac_default_prefix\n# Let make expand exec_prefix.\ntest \"x$exec_prefix\" = xNONE && exec_prefix='${prefix}'\n\nDEFS=-DHAVE_CONFIG_H\n\nac_libobjs=\nac_ltlibobjs=\nU=\nfor ac_i in : $LIBOBJS; do test \"x$ac_i\" = x: && continue\n  # 1. Remove the extension, and $U if already installed.\n  ac_script='s/\\$U\\././;s/\\.o$//;s/\\.obj$//'\n  ac_i=`$as_echo \"$ac_i\" | sed \"$ac_script\"`\n  # 2. Prepend LIBOBJDIR.  When used with automake>=1.10 LIBOBJDIR\n  #    will be set to the directory where LIBOBJS objects are built.\n  as_fn_append ac_libobjs \" \\${LIBOBJDIR}$ac_i\\$U.$ac_objext\"\n  as_fn_append ac_ltlibobjs \" \\${LIBOBJDIR}$ac_i\"'$U.lo'\ndone\nLIBOBJS=$ac_libobjs\n\nLTLIBOBJS=$ac_ltlibobjs\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure\" >&5\n$as_echo_n \"checking that generated files are newer than configure... \" >&6; }\n   if test -n \"$am_sleep_pid\"; then\n     # Hide warnings about reused PIDs.\n     wait $am_sleep_pid 2>/dev/null\n   fi\n   { $as_echo \"$as_me:${as_lineno-$LINENO}: result: done\" >&5\n$as_echo \"done\" >&6; }\n if test -n \"$EXEEXT\"; then\n  am__EXEEXT_TRUE=\n  am__EXEEXT_FALSE='#'\nelse\n  am__EXEEXT_TRUE='#'\n  am__EXEEXT_FALSE=\nfi\n\nif test -z \"${MAINTAINER_MODE_TRUE}\" && test -z \"${MAINTAINER_MODE_FALSE}\"; then\n  as_fn_error $? \"conditional \\\"MAINTAINER_MODE\\\" was never defined.\nUsually this means the macro was only invoked conditionally.\" \"$LINENO\" 5\nfi\nif test -z \"${HAVE_DWZ_TRUE}\" && test -z \"${HAVE_DWZ_FALSE}\"; then\n  as_fn_error $? \"conditional \\\"HAVE_DWZ\\\" was never defined.\nUsually this means the macro was only invoked conditionally.\" \"$LINENO\" 5\nfi\nif test -z \"${ENABLE_DARWIN_AT_RPATH_TRUE}\" && test -z \"${ENABLE_DARWIN_AT_RPATH_FALSE}\"; then\n  as_fn_error $? \"conditional \\\"ENABLE_DARWIN_AT_RPATH\\\" was never defined.\nUsually this means the macro was only invoked conditionally.\" \"$LINENO\" 5\nfi\nif test -z \"${HAVE_ELF_TRUE}\" && test -z \"${HAVE_ELF_FALSE}\"; then\n  as_fn_error $? \"conditional \\\"HAVE_ELF\\\" was never defined.\nUsually this means the macro was only invoked conditionally.\" \"$LINENO\" 5\nfi\nif test -z \"${HAVE_PTHREAD_TRUE}\" && test -z \"${HAVE_PTHREAD_FALSE}\"; then\n  as_fn_error $? \"conditional \\\"HAVE_PTHREAD\\\" was never defined.\nUsually this means the macro was only invoked conditionally.\" \"$LINENO\" 5\nfi\nif test -z \"${HAVE_DWARF5_TRUE}\" && test -z \"${HAVE_DWARF5_FALSE}\"; then\n  as_fn_error $? \"conditional \\\"HAVE_DWARF5\\\" was never defined.\nUsually this means the macro was only invoked conditionally.\" \"$LINENO\" 5\nfi\nif test -z \"${HAVE_ZLIB_TRUE}\" && test -z \"${HAVE_ZLIB_FALSE}\"; then\n  as_fn_error $? \"conditional \\\"HAVE_ZLIB\\\" was never defined.\nUsually this means the macro was only invoked conditionally.\" \"$LINENO\" 5\nfi\nif test -z \"${HAVE_BUILDID_TRUE}\" && test -z \"${HAVE_BUILDID_FALSE}\"; then\n  as_fn_error $? \"conditional \\\"HAVE_BUILDID\\\" was never defined.\nUsually this means the macro was only invoked conditionally.\" \"$LINENO\" 5\nfi\nif test -z \"${HAVE_COMPRESSED_DEBUG_ZLIB_GNU_TRUE}\" && test -z \"${HAVE_COMPRESSED_DEBUG_ZLIB_GNU_FALSE}\"; then\n  as_fn_error $? \"conditional \\\"HAVE_COMPRESSED_DEBUG_ZLIB_GNU\\\" was never defined.\nUsually this means the macro was only invoked conditionally.\" \"$LINENO\" 5\nfi\nif test -z \"${HAVE_COMPRESSED_DEBUG_ZLIB_GABI_TRUE}\" && test -z \"${HAVE_COMPRESSED_DEBUG_ZLIB_GABI_FALSE}\"; then\n  as_fn_error $? \"conditional \\\"HAVE_COMPRESSED_DEBUG_ZLIB_GABI\\\" was never defined.\nUsually this means the macro was only invoked conditionally.\" \"$LINENO\" 5\nfi\nif test -z \"${HAVE_ZSTD_TRUE}\" && test -z \"${HAVE_ZSTD_FALSE}\"; then\n  as_fn_error $? \"conditional \\\"HAVE_ZSTD\\\" was never defined.\nUsually this means the macro was only invoked conditionally.\" \"$LINENO\" 5\nfi\nif test -z \"${HAVE_COMPRESSED_DEBUG_ZSTD_TRUE}\" && test -z \"${HAVE_COMPRESSED_DEBUG_ZSTD_FALSE}\"; then\n  as_fn_error $? \"conditional \\\"HAVE_COMPRESSED_DEBUG_ZSTD\\\" was never defined.\nUsually this means the macro was only invoked conditionally.\" \"$LINENO\" 5\nfi\nif test -z \"${HAVE_OBJCOPY_DEBUGLINK_TRUE}\" && test -z \"${HAVE_OBJCOPY_DEBUGLINK_FALSE}\"; then\n  as_fn_error $? \"conditional \\\"HAVE_OBJCOPY_DEBUGLINK\\\" was never defined.\nUsually this means the macro was only invoked conditionally.\" \"$LINENO\" 5\nfi\nif test -z \"${USE_DSYMUTIL_TRUE}\" && test -z \"${USE_DSYMUTIL_FALSE}\"; then\n  as_fn_error $? \"conditional \\\"USE_DSYMUTIL\\\" was never defined.\nUsually this means the macro was only invoked conditionally.\" \"$LINENO\" 5\nfi\nif test -z \"${HAVE_XZ_TRUE}\" && test -z \"${HAVE_XZ_FALSE}\"; then\n  as_fn_error $? \"conditional \\\"HAVE_XZ\\\" was never defined.\nUsually this means the macro was only invoked conditionally.\" \"$LINENO\" 5\nfi\nif test -z \"${HAVE_COMM_TRUE}\" && test -z \"${HAVE_COMM_FALSE}\"; then\n  as_fn_error $? \"conditional \\\"HAVE_COMM\\\" was never defined.\nUsually this means the macro was only invoked conditionally.\" \"$LINENO\" 5\nfi\nif test -z \"${HAVE_MINIDEBUG_TRUE}\" && test -z \"${HAVE_MINIDEBUG_FALSE}\"; then\n  as_fn_error $? \"conditional \\\"HAVE_MINIDEBUG\\\" was never defined.\nUsually this means the macro was only invoked conditionally.\" \"$LINENO\" 5\nfi\nif test -z \"${HAVE_LIBLZMA_TRUE}\" && test -z \"${HAVE_LIBLZMA_FALSE}\"; then\n  as_fn_error $? \"conditional \\\"HAVE_LIBLZMA\\\" was never defined.\nUsually this means the macro was only invoked conditionally.\" \"$LINENO\" 5\nfi\nif test -z \"${NATIVE_TRUE}\" && test -z \"${NATIVE_FALSE}\"; then\n  as_fn_error $? \"conditional \\\"NATIVE\\\" was never defined.\nUsually this means the macro was only invoked conditionally.\" \"$LINENO\" 5\nfi\n\n: \"${CONFIG_STATUS=./config.status}\"\nac_write_fail=0\nac_clean_files_save=$ac_clean_files\nac_clean_files=\"$ac_clean_files $CONFIG_STATUS\"\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS\" >&5\n$as_echo \"$as_me: creating $CONFIG_STATUS\" >&6;}\nas_write_fail=0\ncat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1\n#! $SHELL\n# Generated by $as_me.\n# Run this file to recreate the current configuration.\n# Compiler output produced by configure, useful for debugging\n# configure, is in config.log if it exists.\n\ndebug=false\nac_cs_recheck=false\nac_cs_silent=false\n\nSHELL=\\${CONFIG_SHELL-$SHELL}\nexport SHELL\n_ASEOF\ncat >>$CONFIG_STATUS <<\\_ASEOF || as_write_fail=1\n## -------------------- ##\n## M4sh Initialization. ##\n## -------------------- ##\n\n# Be more Bourne compatible\nDUALCASE=1; export DUALCASE # for MKS sh\nif test -n \"${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :\n  emulate sh\n  NULLCMD=:\n  # Pre-4.2 versions of Zsh do word splitting on ${1+\"$@\"}, which\n  # is contrary to our usage.  Disable this feature.\n  alias -g '${1+\"$@\"}'='\"$@\"'\n  setopt NO_GLOB_SUBST\nelse\n  case `(set -o) 2>/dev/null` in #(\n  *posix*) :\n    set -o posix ;; #(\n  *) :\n     ;;\nesac\nfi\n\n\nas_nl='\n'\nexport as_nl\n# Printing a long string crashes Solaris 7 /usr/bin/printf.\nas_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'\nas_echo=$as_echo$as_echo$as_echo$as_echo$as_echo\nas_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo\n# Prefer a ksh shell builtin over an external printf program on Solaris,\n# but without wasting forks for bash or zsh.\nif test -z \"$BASH_VERSION$ZSH_VERSION\" \\\n    && (test \"X`print -r -- $as_echo`\" = \"X$as_echo\") 2>/dev/null; then\n  as_echo='print -r --'\n  as_echo_n='print -rn --'\nelif (test \"X`printf %s $as_echo`\" = \"X$as_echo\") 2>/dev/null; then\n  as_echo='printf %s\\n'\n  as_echo_n='printf %s'\nelse\n  if test \"X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`\" = \"X-n $as_echo\"; then\n    as_echo_body='eval /usr/ucb/echo -n \"$1$as_nl\"'\n    as_echo_n='/usr/ucb/echo -n'\n  else\n    as_echo_body='eval expr \"X$1\" : \"X\\\\(.*\\\\)\"'\n    as_echo_n_body='eval\n      arg=$1;\n      case $arg in #(\n      *\"$as_nl\"*)\n\texpr \"X$arg\" : \"X\\\\(.*\\\\)$as_nl\";\n\targ=`expr \"X$arg\" : \".*$as_nl\\\\(.*\\\\)\"`;;\n      esac;\n      expr \"X$arg\" : \"X\\\\(.*\\\\)\" | tr -d \"$as_nl\"\n    '\n    export as_echo_n_body\n    as_echo_n='sh -c $as_echo_n_body as_echo'\n  fi\n  export as_echo_body\n  as_echo='sh -c $as_echo_body as_echo'\nfi\n\n# The user is always right.\nif test \"${PATH_SEPARATOR+set}\" != set; then\n  PATH_SEPARATOR=:\n  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {\n    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||\n      PATH_SEPARATOR=';'\n  }\nfi\n\n\n# IFS\n# We need space, tab and new line, in precisely that order.  Quoting is\n# there to prevent editors from complaining about space-tab.\n# (If _AS_PATH_WALK were called with IFS unset, it would disable word\n# splitting by setting IFS to empty value.)\nIFS=\" \"\"\t$as_nl\"\n\n# Find who we are.  Look in the path if we contain no directory separator.\nas_myself=\ncase $0 in #((\n  *[\\\\/]* ) as_myself=$0 ;;\n  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    test -r \"$as_dir/$0\" && as_myself=$as_dir/$0 && break\n  done\nIFS=$as_save_IFS\n\n     ;;\nesac\n# We did not find ourselves, most probably we were run as `sh COMMAND'\n# in which case we are not to be found in the path.\nif test \"x$as_myself\" = x; then\n  as_myself=$0\nfi\nif test ! -f \"$as_myself\"; then\n  $as_echo \"$as_myself: error: cannot find myself; rerun with an absolute file name\" >&2\n  exit 1\nfi\n\n# Unset variables that we do not need and which cause bugs (e.g. in\n# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the \"|| exit 1\"\n# suppresses any \"Segmentation fault\" message there.  '((' could\n# trigger a bug in pdksh 5.2.14.\nfor as_var in BASH_ENV ENV MAIL MAILPATH\ndo eval test x\\${$as_var+set} = xset \\\n  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :\ndone\nPS1='$ '\nPS2='> '\nPS4='+ '\n\n# NLS nuisances.\nLC_ALL=C\nexport LC_ALL\nLANGUAGE=C\nexport LANGUAGE\n\n# CDPATH.\n(unset CDPATH) >/dev/null 2>&1 && unset CDPATH\n\n\n# as_fn_error STATUS ERROR [LINENO LOG_FD]\n# ----------------------------------------\n# Output \"`basename $0`: error: ERROR\" to stderr. If LINENO and LOG_FD are\n# provided, also output the error to LOG_FD, referencing LINENO. Then exit the\n# script with STATUS, using 1 if that was 0.\nas_fn_error ()\n{\n  as_status=$1; test $as_status -eq 0 && as_status=1\n  if test \"$4\"; then\n    as_lineno=${as_lineno-\"$3\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n    $as_echo \"$as_me:${as_lineno-$LINENO}: error: $2\" >&$4\n  fi\n  $as_echo \"$as_me: error: $2\" >&2\n  as_fn_exit $as_status\n} # as_fn_error\n\n\n# as_fn_set_status STATUS\n# -----------------------\n# Set $? to STATUS, without forking.\nas_fn_set_status ()\n{\n  return $1\n} # as_fn_set_status\n\n# as_fn_exit STATUS\n# -----------------\n# Exit the shell with STATUS, even in a \"trap 0\" or \"set -e\" context.\nas_fn_exit ()\n{\n  set +e\n  as_fn_set_status $1\n  exit $1\n} # as_fn_exit\n\n# as_fn_unset VAR\n# ---------------\n# Portably unset VAR.\nas_fn_unset ()\n{\n  { eval $1=; unset $1;}\n}\nas_unset=as_fn_unset\n# as_fn_append VAR VALUE\n# ----------------------\n# Append the text in VALUE to the end of the definition contained in VAR. Take\n# advantage of any shell optimizations that allow amortized linear growth over\n# repeated appends, instead of the typical quadratic growth present in naive\n# implementations.\nif (eval \"as_var=1; as_var+=2; test x\\$as_var = x12\") 2>/dev/null; then :\n  eval 'as_fn_append ()\n  {\n    eval $1+=\\$2\n  }'\nelse\n  as_fn_append ()\n  {\n    eval $1=\\$$1\\$2\n  }\nfi # as_fn_append\n\n# as_fn_arith ARG...\n# ------------------\n# Perform arithmetic evaluation on the ARGs, and store the result in the\n# global $as_val. Take advantage of shells that can avoid forks. The arguments\n# must be portable across $(()) and expr.\nif (eval \"test \\$(( 1 + 1 )) = 2\") 2>/dev/null; then :\n  eval 'as_fn_arith ()\n  {\n    as_val=$(( $* ))\n  }'\nelse\n  as_fn_arith ()\n  {\n    as_val=`expr \"$@\" || test $? -eq 1`\n  }\nfi # as_fn_arith\n\n\nif expr a : '\\(a\\)' >/dev/null 2>&1 &&\n   test \"X`expr 00001 : '.*\\(...\\)'`\" = X001; then\n  as_expr=expr\nelse\n  as_expr=false\nfi\n\nif (basename -- /) >/dev/null 2>&1 && test \"X`basename -- / 2>&1`\" = \"X/\"; then\n  as_basename=basename\nelse\n  as_basename=false\nfi\n\nif (as_dir=`dirname -- /` && test \"X$as_dir\" = X/) >/dev/null 2>&1; then\n  as_dirname=dirname\nelse\n  as_dirname=false\nfi\n\nas_me=`$as_basename -- \"$0\" ||\n$as_expr X/\"$0\" : '.*/\\([^/][^/]*\\)/*$' \\| \\\n\t X\"$0\" : 'X\\(//\\)$' \\| \\\n\t X\"$0\" : 'X\\(/\\)' \\| . 2>/dev/null ||\n$as_echo X/\"$0\" |\n    sed '/^.*\\/\\([^/][^/]*\\)\\/*$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\/\\(\\/\\/\\)$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\/\\(\\/\\).*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  s/.*/./; q'`\n\n# Avoid depending upon Character Ranges.\nas_cr_letters='abcdefghijklmnopqrstuvwxyz'\nas_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'\nas_cr_Letters=$as_cr_letters$as_cr_LETTERS\nas_cr_digits='0123456789'\nas_cr_alnum=$as_cr_Letters$as_cr_digits\n\nECHO_C= ECHO_N= ECHO_T=\ncase `echo -n x` in #(((((\n-n*)\n  case `echo 'xy\\c'` in\n  *c*) ECHO_T='\t';;\t# ECHO_T is single tab character.\n  xy)  ECHO_C='\\c';;\n  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null\n       ECHO_T='\t';;\n  esac;;\n*)\n  ECHO_N='-n';;\nesac\n\nrm -f conf$$ conf$$.exe conf$$.file\nif test -d conf$$.dir; then\n  rm -f conf$$.dir/conf$$.file\nelse\n  rm -f conf$$.dir\n  mkdir conf$$.dir 2>/dev/null\nfi\nif (echo >conf$$.file) 2>/dev/null; then\n  if ln -s conf$$.file conf$$ 2>/dev/null; then\n    as_ln_s='ln -s'\n    # ... but there are two gotchas:\n    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.\n    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.\n    # In both cases, we have to default to `cp -pR'.\n    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||\n      as_ln_s='cp -pR'\n  elif ln conf$$.file conf$$ 2>/dev/null; then\n    as_ln_s=ln\n  else\n    as_ln_s='cp -pR'\n  fi\nelse\n  as_ln_s='cp -pR'\nfi\nrm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file\nrmdir conf$$.dir 2>/dev/null\n\n\n# as_fn_mkdir_p\n# -------------\n# Create \"$as_dir\" as a directory, including parents if necessary.\nas_fn_mkdir_p ()\n{\n\n  case $as_dir in #(\n  -*) as_dir=./$as_dir;;\n  esac\n  test -d \"$as_dir\" || eval $as_mkdir_p || {\n    as_dirs=\n    while :; do\n      case $as_dir in #(\n      *\\'*) as_qdir=`$as_echo \"$as_dir\" | sed \"s/'/'\\\\\\\\\\\\\\\\''/g\"`;; #'(\n      *) as_qdir=$as_dir;;\n      esac\n      as_dirs=\"'$as_qdir' $as_dirs\"\n      as_dir=`$as_dirname -- \"$as_dir\" ||\n$as_expr X\"$as_dir\" : 'X\\(.*[^/]\\)//*[^/][^/]*/*$' \\| \\\n\t X\"$as_dir\" : 'X\\(//\\)[^/]' \\| \\\n\t X\"$as_dir\" : 'X\\(//\\)$' \\| \\\n\t X\"$as_dir\" : 'X\\(/\\)' \\| . 2>/dev/null ||\n$as_echo X\"$as_dir\" |\n    sed '/^X\\(.*[^/]\\)\\/\\/*[^/][^/]*\\/*$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\/\\)[^/].*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\/\\)$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\).*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  s/.*/./; q'`\n      test -d \"$as_dir\" && break\n    done\n    test -z \"$as_dirs\" || eval \"mkdir $as_dirs\"\n  } || test -d \"$as_dir\" || as_fn_error $? \"cannot create directory $as_dir\"\n\n\n} # as_fn_mkdir_p\nif mkdir -p . 2>/dev/null; then\n  as_mkdir_p='mkdir -p \"$as_dir\"'\nelse\n  test -d ./-p && rmdir ./-p\n  as_mkdir_p=false\nfi\n\n\n# as_fn_executable_p FILE\n# -----------------------\n# Test if FILE is an executable regular file.\nas_fn_executable_p ()\n{\n  test -f \"$1\" && test -x \"$1\"\n} # as_fn_executable_p\nas_test_x='test -x'\nas_executable_p=as_fn_executable_p\n\n# Sed expression to map a string onto a valid CPP name.\nas_tr_cpp=\"eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'\"\n\n# Sed expression to map a string onto a valid variable name.\nas_tr_sh=\"eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'\"\n\n\nexec 6>&1\n## ----------------------------------- ##\n## Main body of $CONFIG_STATUS script. ##\n## ----------------------------------- ##\n_ASEOF\ntest $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1\n\ncat >>$CONFIG_STATUS <<\\_ACEOF || ac_write_fail=1\n# Save the log message, to keep $0 and so on meaningful, and to\n# report actual input values of CONFIG_FILES etc. instead of their\n# values after options handling.\nac_log=\"\nThis file was extended by package-unused $as_me version-unused, which was\ngenerated by GNU Autoconf 2.69.  Invocation command line was\n\n  CONFIG_FILES    = $CONFIG_FILES\n  CONFIG_HEADERS  = $CONFIG_HEADERS\n  CONFIG_LINKS    = $CONFIG_LINKS\n  CONFIG_COMMANDS = $CONFIG_COMMANDS\n  $ $0 $@\n\non `(hostname || uname -n) 2>/dev/null | sed 1q`\n\"\n\n_ACEOF\n\ncase $ac_config_files in *\"\n\"*) set x $ac_config_files; shift; ac_config_files=$*;;\nesac\n\ncase $ac_config_headers in *\"\n\"*) set x $ac_config_headers; shift; ac_config_headers=$*;;\nesac\n\n\ncat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1\n# Files that config.status was made for.\nconfig_files=\"$ac_config_files\"\nconfig_headers=\"$ac_config_headers\"\nconfig_commands=\"$ac_config_commands\"\n\n_ACEOF\n\ncat >>$CONFIG_STATUS <<\\_ACEOF || ac_write_fail=1\nac_cs_usage=\"\\\n\\`$as_me' instantiates files and other configuration actions\nfrom templates according to the current configuration.  Unless the files\nand actions are specified as TAGs, all are instantiated by default.\n\nUsage: $0 [OPTION]... [TAG]...\n\n  -h, --help       print this help, then exit\n  -V, --version    print version number and configuration settings, then exit\n      --config     print configuration, then exit\n  -q, --quiet, --silent\n                   do not print progress messages\n  -d, --debug      don't remove temporary files\n      --recheck    update $as_me by reconfiguring in the same conditions\n      --file=FILE[:TEMPLATE]\n                   instantiate the configuration file FILE\n      --header=FILE[:TEMPLATE]\n                   instantiate the configuration header FILE\n\nConfiguration files:\n$config_files\n\nConfiguration headers:\n$config_headers\n\nConfiguration commands:\n$config_commands\n\nReport bugs to the package provider.\"\n\n_ACEOF\ncat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1\nac_cs_config=\"`$as_echo \"$ac_configure_args\" | sed 's/^ //; s/[\\\\\"\"\\`\\$]/\\\\\\\\&/g'`\"\nac_cs_version=\"\\\\\npackage-unused config.status version-unused\nconfigured by $0, generated by GNU Autoconf 2.69,\n  with options \\\\\"\\$ac_cs_config\\\\\"\n\nCopyright (C) 2012 Free Software Foundation, Inc.\nThis config.status script is free software; the Free Software Foundation\ngives unlimited permission to copy, distribute and modify it.\"\n\nac_pwd='$ac_pwd'\nsrcdir='$srcdir'\nINSTALL='$INSTALL'\nMKDIR_P='$MKDIR_P'\nAWK='$AWK'\ntest -n \"\\$AWK\" || AWK=awk\n_ACEOF\n\ncat >>$CONFIG_STATUS <<\\_ACEOF || ac_write_fail=1\n# The default lists apply if the user does not specify any file.\nac_need_defaults=:\nwhile test $# != 0\ndo\n  case $1 in\n  --*=?*)\n    ac_option=`expr \"X$1\" : 'X\\([^=]*\\)='`\n    ac_optarg=`expr \"X$1\" : 'X[^=]*=\\(.*\\)'`\n    ac_shift=:\n    ;;\n  --*=)\n    ac_option=`expr \"X$1\" : 'X\\([^=]*\\)='`\n    ac_optarg=\n    ac_shift=:\n    ;;\n  *)\n    ac_option=$1\n    ac_optarg=$2\n    ac_shift=shift\n    ;;\n  esac\n\n  case $ac_option in\n  # Handling of the options.\n  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)\n    ac_cs_recheck=: ;;\n  --version | --versio | --versi | --vers | --ver | --ve | --v | -V )\n    $as_echo \"$ac_cs_version\"; exit ;;\n  --config | --confi | --conf | --con | --co | --c )\n    $as_echo \"$ac_cs_config\"; exit ;;\n  --debug | --debu | --deb | --de | --d | -d )\n    debug=: ;;\n  --file | --fil | --fi | --f )\n    $ac_shift\n    case $ac_optarg in\n    *\\'*) ac_optarg=`$as_echo \"$ac_optarg\" | sed \"s/'/'\\\\\\\\\\\\\\\\''/g\"` ;;\n    '') as_fn_error $? \"missing file argument\" ;;\n    esac\n    as_fn_append CONFIG_FILES \" '$ac_optarg'\"\n    ac_need_defaults=false;;\n  --header | --heade | --head | --hea )\n    $ac_shift\n    case $ac_optarg in\n    *\\'*) ac_optarg=`$as_echo \"$ac_optarg\" | sed \"s/'/'\\\\\\\\\\\\\\\\''/g\"` ;;\n    esac\n    as_fn_append CONFIG_HEADERS \" '$ac_optarg'\"\n    ac_need_defaults=false;;\n  --he | --h)\n    # Conflict between --help and --header\n    as_fn_error $? \"ambiguous option: \\`$1'\nTry \\`$0 --help' for more information.\";;\n  --help | --hel | -h )\n    $as_echo \"$ac_cs_usage\"; exit ;;\n  -q | -quiet | --quiet | --quie | --qui | --qu | --q \\\n  | -silent | --silent | --silen | --sile | --sil | --si | --s)\n    ac_cs_silent=: ;;\n\n  # This is an error.\n  -*) as_fn_error $? \"unrecognized option: \\`$1'\nTry \\`$0 --help' for more information.\" ;;\n\n  *) as_fn_append ac_config_targets \" $1\"\n     ac_need_defaults=false ;;\n\n  esac\n  shift\ndone\n\nac_configure_extra_args=\n\nif $ac_cs_silent; then\n  exec 6>/dev/null\n  ac_configure_extra_args=\"$ac_configure_extra_args --silent\"\nfi\n\n_ACEOF\ncat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1\nif \\$ac_cs_recheck; then\n  set X $SHELL '$0' $ac_configure_args \\$ac_configure_extra_args --no-create --no-recursion\n  shift\n  \\$as_echo \"running CONFIG_SHELL=$SHELL \\$*\" >&6\n  CONFIG_SHELL='$SHELL'\n  export CONFIG_SHELL\n  exec \"\\$@\"\nfi\n\n_ACEOF\ncat >>$CONFIG_STATUS <<\\_ACEOF || ac_write_fail=1\nexec 5>>config.log\n{\n  echo\n  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX\n## Running $as_me. ##\n_ASBOX\n  $as_echo \"$ac_log\"\n} >&5\n\n_ACEOF\ncat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1\n#\n# INIT-COMMANDS\n#\n\nsrcdir=\"$srcdir\"\nhost=\"$host\"\ntarget=\"$target\"\nwith_multisubdir=\"$with_multisubdir\"\nwith_multisrctop=\"$with_multisrctop\"\nwith_target_subdir=\"$with_target_subdir\"\nac_configure_args=\"${multilib_arg} ${ac_configure_args}\"\nmulti_basedir=\"$multi_basedir\"\nCONFIG_SHELL=${CONFIG_SHELL-/bin/sh}\nCC=\"$CC\"\nCXX=\"$CXX\"\nGFORTRAN=\"$GFORTRAN\"\nGDC=\"$GDC\"\n\n\n# The HP-UX ksh and POSIX shell print the target directory to stdout\n# if CDPATH is set.\n(unset CDPATH) >/dev/null 2>&1 && unset CDPATH\n\nsed_quote_subst='$sed_quote_subst'\ndouble_quote_subst='$double_quote_subst'\ndelay_variable_subst='$delay_variable_subst'\nenable_shared='`$ECHO \"$enable_shared\" | $SED \"$delay_single_quote_subst\"`'\nmacro_version='`$ECHO \"$macro_version\" | $SED \"$delay_single_quote_subst\"`'\nmacro_revision='`$ECHO \"$macro_revision\" | $SED \"$delay_single_quote_subst\"`'\nenable_static='`$ECHO \"$enable_static\" | $SED \"$delay_single_quote_subst\"`'\npic_mode='`$ECHO \"$pic_mode\" | $SED \"$delay_single_quote_subst\"`'\nenable_fast_install='`$ECHO \"$enable_fast_install\" | $SED \"$delay_single_quote_subst\"`'\nSHELL='`$ECHO \"$SHELL\" | $SED \"$delay_single_quote_subst\"`'\nECHO='`$ECHO \"$ECHO\" | $SED \"$delay_single_quote_subst\"`'\nhost_alias='`$ECHO \"$host_alias\" | $SED \"$delay_single_quote_subst\"`'\nhost='`$ECHO \"$host\" | $SED \"$delay_single_quote_subst\"`'\nhost_os='`$ECHO \"$host_os\" | $SED \"$delay_single_quote_subst\"`'\nbuild_alias='`$ECHO \"$build_alias\" | $SED \"$delay_single_quote_subst\"`'\nbuild='`$ECHO \"$build\" | $SED \"$delay_single_quote_subst\"`'\nbuild_os='`$ECHO \"$build_os\" | $SED \"$delay_single_quote_subst\"`'\nSED='`$ECHO \"$SED\" | $SED \"$delay_single_quote_subst\"`'\nXsed='`$ECHO \"$Xsed\" | $SED \"$delay_single_quote_subst\"`'\nGREP='`$ECHO \"$GREP\" | $SED \"$delay_single_quote_subst\"`'\nEGREP='`$ECHO \"$EGREP\" | $SED \"$delay_single_quote_subst\"`'\nFGREP='`$ECHO \"$FGREP\" | $SED \"$delay_single_quote_subst\"`'\nLD='`$ECHO \"$LD\" | $SED \"$delay_single_quote_subst\"`'\nNM='`$ECHO \"$NM\" | $SED \"$delay_single_quote_subst\"`'\nLN_S='`$ECHO \"$LN_S\" | $SED \"$delay_single_quote_subst\"`'\nmax_cmd_len='`$ECHO \"$max_cmd_len\" | $SED \"$delay_single_quote_subst\"`'\nac_objext='`$ECHO \"$ac_objext\" | $SED \"$delay_single_quote_subst\"`'\nexeext='`$ECHO \"$exeext\" | $SED \"$delay_single_quote_subst\"`'\nlt_unset='`$ECHO \"$lt_unset\" | $SED \"$delay_single_quote_subst\"`'\nlt_SP2NL='`$ECHO \"$lt_SP2NL\" | $SED \"$delay_single_quote_subst\"`'\nlt_NL2SP='`$ECHO \"$lt_NL2SP\" | $SED \"$delay_single_quote_subst\"`'\nreload_flag='`$ECHO \"$reload_flag\" | $SED \"$delay_single_quote_subst\"`'\nreload_cmds='`$ECHO \"$reload_cmds\" | $SED \"$delay_single_quote_subst\"`'\nOBJDUMP='`$ECHO \"$OBJDUMP\" | $SED \"$delay_single_quote_subst\"`'\ndeplibs_check_method='`$ECHO \"$deplibs_check_method\" | $SED \"$delay_single_quote_subst\"`'\nfile_magic_cmd='`$ECHO \"$file_magic_cmd\" | $SED \"$delay_single_quote_subst\"`'\nAR='`$ECHO \"$AR\" | $SED \"$delay_single_quote_subst\"`'\nAR_FLAGS='`$ECHO \"$AR_FLAGS\" | $SED \"$delay_single_quote_subst\"`'\nSTRIP='`$ECHO \"$STRIP\" | $SED \"$delay_single_quote_subst\"`'\nRANLIB='`$ECHO \"$RANLIB\" | $SED \"$delay_single_quote_subst\"`'\nold_postinstall_cmds='`$ECHO \"$old_postinstall_cmds\" | $SED \"$delay_single_quote_subst\"`'\nold_postuninstall_cmds='`$ECHO \"$old_postuninstall_cmds\" | $SED \"$delay_single_quote_subst\"`'\nold_archive_cmds='`$ECHO \"$old_archive_cmds\" | $SED \"$delay_single_quote_subst\"`'\nlock_old_archive_extraction='`$ECHO \"$lock_old_archive_extraction\" | $SED \"$delay_single_quote_subst\"`'\nCC='`$ECHO \"$CC\" | $SED \"$delay_single_quote_subst\"`'\nCFLAGS='`$ECHO \"$CFLAGS\" | $SED \"$delay_single_quote_subst\"`'\ncompiler='`$ECHO \"$compiler\" | $SED \"$delay_single_quote_subst\"`'\nGCC='`$ECHO \"$GCC\" | $SED \"$delay_single_quote_subst\"`'\nlt_cv_sys_global_symbol_pipe='`$ECHO \"$lt_cv_sys_global_symbol_pipe\" | $SED \"$delay_single_quote_subst\"`'\nlt_cv_sys_global_symbol_to_cdecl='`$ECHO \"$lt_cv_sys_global_symbol_to_cdecl\" | $SED \"$delay_single_quote_subst\"`'\nlt_cv_sys_global_symbol_to_c_name_address='`$ECHO \"$lt_cv_sys_global_symbol_to_c_name_address\" | $SED \"$delay_single_quote_subst\"`'\nlt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO \"$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix\" | $SED \"$delay_single_quote_subst\"`'\nobjdir='`$ECHO \"$objdir\" | $SED \"$delay_single_quote_subst\"`'\nMAGIC_CMD='`$ECHO \"$MAGIC_CMD\" | $SED \"$delay_single_quote_subst\"`'\nlt_prog_compiler_no_builtin_flag='`$ECHO \"$lt_prog_compiler_no_builtin_flag\" | $SED \"$delay_single_quote_subst\"`'\nlt_prog_compiler_wl='`$ECHO \"$lt_prog_compiler_wl\" | $SED \"$delay_single_quote_subst\"`'\nlt_prog_compiler_pic='`$ECHO \"$lt_prog_compiler_pic\" | $SED \"$delay_single_quote_subst\"`'\nlt_prog_compiler_static='`$ECHO \"$lt_prog_compiler_static\" | $SED \"$delay_single_quote_subst\"`'\nlt_cv_prog_compiler_c_o='`$ECHO \"$lt_cv_prog_compiler_c_o\" | $SED \"$delay_single_quote_subst\"`'\nneed_locks='`$ECHO \"$need_locks\" | $SED \"$delay_single_quote_subst\"`'\nDSYMUTIL='`$ECHO \"$DSYMUTIL\" | $SED \"$delay_single_quote_subst\"`'\nNMEDIT='`$ECHO \"$NMEDIT\" | $SED \"$delay_single_quote_subst\"`'\nLIPO='`$ECHO \"$LIPO\" | $SED \"$delay_single_quote_subst\"`'\nOTOOL='`$ECHO \"$OTOOL\" | $SED \"$delay_single_quote_subst\"`'\nOTOOL64='`$ECHO \"$OTOOL64\" | $SED \"$delay_single_quote_subst\"`'\nlibext='`$ECHO \"$libext\" | $SED \"$delay_single_quote_subst\"`'\nshrext_cmds='`$ECHO \"$shrext_cmds\" | $SED \"$delay_single_quote_subst\"`'\nextract_expsyms_cmds='`$ECHO \"$extract_expsyms_cmds\" | $SED \"$delay_single_quote_subst\"`'\narchive_cmds_need_lc='`$ECHO \"$archive_cmds_need_lc\" | $SED \"$delay_single_quote_subst\"`'\nenable_shared_with_static_runtimes='`$ECHO \"$enable_shared_with_static_runtimes\" | $SED \"$delay_single_quote_subst\"`'\nexport_dynamic_flag_spec='`$ECHO \"$export_dynamic_flag_spec\" | $SED \"$delay_single_quote_subst\"`'\nwhole_archive_flag_spec='`$ECHO \"$whole_archive_flag_spec\" | $SED \"$delay_single_quote_subst\"`'\ncompiler_needs_object='`$ECHO \"$compiler_needs_object\" | $SED \"$delay_single_quote_subst\"`'\nold_archive_from_new_cmds='`$ECHO \"$old_archive_from_new_cmds\" | $SED \"$delay_single_quote_subst\"`'\nold_archive_from_expsyms_cmds='`$ECHO \"$old_archive_from_expsyms_cmds\" | $SED \"$delay_single_quote_subst\"`'\narchive_cmds='`$ECHO \"$archive_cmds\" | $SED \"$delay_single_quote_subst\"`'\narchive_expsym_cmds='`$ECHO \"$archive_expsym_cmds\" | $SED \"$delay_single_quote_subst\"`'\nmodule_cmds='`$ECHO \"$module_cmds\" | $SED \"$delay_single_quote_subst\"`'\nmodule_expsym_cmds='`$ECHO \"$module_expsym_cmds\" | $SED \"$delay_single_quote_subst\"`'\nwith_gnu_ld='`$ECHO \"$with_gnu_ld\" | $SED \"$delay_single_quote_subst\"`'\nallow_undefined_flag='`$ECHO \"$allow_undefined_flag\" | $SED \"$delay_single_quote_subst\"`'\nno_undefined_flag='`$ECHO \"$no_undefined_flag\" | $SED \"$delay_single_quote_subst\"`'\nhardcode_libdir_flag_spec='`$ECHO \"$hardcode_libdir_flag_spec\" | $SED \"$delay_single_quote_subst\"`'\nhardcode_libdir_flag_spec_ld='`$ECHO \"$hardcode_libdir_flag_spec_ld\" | $SED \"$delay_single_quote_subst\"`'\nhardcode_libdir_separator='`$ECHO \"$hardcode_libdir_separator\" | $SED \"$delay_single_quote_subst\"`'\nhardcode_direct='`$ECHO \"$hardcode_direct\" | $SED \"$delay_single_quote_subst\"`'\nhardcode_direct_absolute='`$ECHO \"$hardcode_direct_absolute\" | $SED \"$delay_single_quote_subst\"`'\nhardcode_minus_L='`$ECHO \"$hardcode_minus_L\" | $SED \"$delay_single_quote_subst\"`'\nhardcode_shlibpath_var='`$ECHO \"$hardcode_shlibpath_var\" | $SED \"$delay_single_quote_subst\"`'\nhardcode_automatic='`$ECHO \"$hardcode_automatic\" | $SED \"$delay_single_quote_subst\"`'\ninherit_rpath='`$ECHO \"$inherit_rpath\" | $SED \"$delay_single_quote_subst\"`'\nlink_all_deplibs='`$ECHO \"$link_all_deplibs\" | $SED \"$delay_single_quote_subst\"`'\nfix_srcfile_path='`$ECHO \"$fix_srcfile_path\" | $SED \"$delay_single_quote_subst\"`'\nalways_export_symbols='`$ECHO \"$always_export_symbols\" | $SED \"$delay_single_quote_subst\"`'\nexport_symbols_cmds='`$ECHO \"$export_symbols_cmds\" | $SED \"$delay_single_quote_subst\"`'\nexclude_expsyms='`$ECHO \"$exclude_expsyms\" | $SED \"$delay_single_quote_subst\"`'\ninclude_expsyms='`$ECHO \"$include_expsyms\" | $SED \"$delay_single_quote_subst\"`'\nprelink_cmds='`$ECHO \"$prelink_cmds\" | $SED \"$delay_single_quote_subst\"`'\nfile_list_spec='`$ECHO \"$file_list_spec\" | $SED \"$delay_single_quote_subst\"`'\nvariables_saved_for_relink='`$ECHO \"$variables_saved_for_relink\" | $SED \"$delay_single_quote_subst\"`'\nneed_lib_prefix='`$ECHO \"$need_lib_prefix\" | $SED \"$delay_single_quote_subst\"`'\nneed_version='`$ECHO \"$need_version\" | $SED \"$delay_single_quote_subst\"`'\nversion_type='`$ECHO \"$version_type\" | $SED \"$delay_single_quote_subst\"`'\nrunpath_var='`$ECHO \"$runpath_var\" | $SED \"$delay_single_quote_subst\"`'\nshlibpath_var='`$ECHO \"$shlibpath_var\" | $SED \"$delay_single_quote_subst\"`'\nshlibpath_overrides_runpath='`$ECHO \"$shlibpath_overrides_runpath\" | $SED \"$delay_single_quote_subst\"`'\nlibname_spec='`$ECHO \"$libname_spec\" | $SED \"$delay_single_quote_subst\"`'\nlibrary_names_spec='`$ECHO \"$library_names_spec\" | $SED \"$delay_single_quote_subst\"`'\nsoname_spec='`$ECHO \"$soname_spec\" | $SED \"$delay_single_quote_subst\"`'\ninstall_override_mode='`$ECHO \"$install_override_mode\" | $SED \"$delay_single_quote_subst\"`'\npostinstall_cmds='`$ECHO \"$postinstall_cmds\" | $SED \"$delay_single_quote_subst\"`'\npostuninstall_cmds='`$ECHO \"$postuninstall_cmds\" | $SED \"$delay_single_quote_subst\"`'\nfinish_cmds='`$ECHO \"$finish_cmds\" | $SED \"$delay_single_quote_subst\"`'\nfinish_eval='`$ECHO \"$finish_eval\" | $SED \"$delay_single_quote_subst\"`'\nhardcode_into_libs='`$ECHO \"$hardcode_into_libs\" | $SED \"$delay_single_quote_subst\"`'\nsys_lib_search_path_spec='`$ECHO \"$sys_lib_search_path_spec\" | $SED \"$delay_single_quote_subst\"`'\nsys_lib_dlsearch_path_spec='`$ECHO \"$sys_lib_dlsearch_path_spec\" | $SED \"$delay_single_quote_subst\"`'\nhardcode_action='`$ECHO \"$hardcode_action\" | $SED \"$delay_single_quote_subst\"`'\nenable_dlopen='`$ECHO \"$enable_dlopen\" | $SED \"$delay_single_quote_subst\"`'\nenable_dlopen_self='`$ECHO \"$enable_dlopen_self\" | $SED \"$delay_single_quote_subst\"`'\nenable_dlopen_self_static='`$ECHO \"$enable_dlopen_self_static\" | $SED \"$delay_single_quote_subst\"`'\nold_striplib='`$ECHO \"$old_striplib\" | $SED \"$delay_single_quote_subst\"`'\nstriplib='`$ECHO \"$striplib\" | $SED \"$delay_single_quote_subst\"`'\n\nLTCC='$LTCC'\nLTCFLAGS='$LTCFLAGS'\ncompiler='$compiler_DEFAULT'\n\n# A function that is used when there is no print builtin or printf.\nfunc_fallback_echo ()\n{\n  eval 'cat <<_LTECHO_EOF\n\\$1\n_LTECHO_EOF'\n}\n\n# Quote evaled strings.\nfor var in SHELL \\\nECHO \\\nSED \\\nGREP \\\nEGREP \\\nFGREP \\\nLD \\\nNM \\\nLN_S \\\nlt_SP2NL \\\nlt_NL2SP \\\nreload_flag \\\nOBJDUMP \\\ndeplibs_check_method \\\nfile_magic_cmd \\\nAR \\\nAR_FLAGS \\\nSTRIP \\\nRANLIB \\\nCC \\\nCFLAGS \\\ncompiler \\\nlt_cv_sys_global_symbol_pipe \\\nlt_cv_sys_global_symbol_to_cdecl \\\nlt_cv_sys_global_symbol_to_c_name_address \\\nlt_cv_sys_global_symbol_to_c_name_address_lib_prefix \\\nlt_prog_compiler_no_builtin_flag \\\nlt_prog_compiler_wl \\\nlt_prog_compiler_pic \\\nlt_prog_compiler_static \\\nlt_cv_prog_compiler_c_o \\\nneed_locks \\\nDSYMUTIL \\\nNMEDIT \\\nLIPO \\\nOTOOL \\\nOTOOL64 \\\nshrext_cmds \\\nexport_dynamic_flag_spec \\\nwhole_archive_flag_spec \\\ncompiler_needs_object \\\nwith_gnu_ld \\\nallow_undefined_flag \\\nno_undefined_flag \\\nhardcode_libdir_flag_spec \\\nhardcode_libdir_flag_spec_ld \\\nhardcode_libdir_separator \\\nfix_srcfile_path \\\nexclude_expsyms \\\ninclude_expsyms \\\nfile_list_spec \\\nvariables_saved_for_relink \\\nlibname_spec \\\nlibrary_names_spec \\\nsoname_spec \\\ninstall_override_mode \\\nfinish_eval \\\nold_striplib \\\nstriplib; do\n    case \\`eval \\\\\\\\\\$ECHO \\\\\\\\\"\"\\\\\\\\\\$\\$var\"\\\\\\\\\"\\` in\n    *[\\\\\\\\\\\\\\`\\\\\"\\\\\\$]*)\n      eval \"lt_\\$var=\\\\\\\\\\\\\"\\\\\\`\\\\\\$ECHO \\\\\"\\\\\\$\\$var\\\\\" | \\\\\\$SED \\\\\"\\\\\\$sed_quote_subst\\\\\"\\\\\\`\\\\\\\\\\\\\"\"\n      ;;\n    *)\n      eval \"lt_\\$var=\\\\\\\\\\\\\"\\\\\\$\\$var\\\\\\\\\\\\\"\"\n      ;;\n    esac\ndone\n\n# Double-quote double-evaled strings.\nfor var in reload_cmds \\\nold_postinstall_cmds \\\nold_postuninstall_cmds \\\nold_archive_cmds \\\nextract_expsyms_cmds \\\nold_archive_from_new_cmds \\\nold_archive_from_expsyms_cmds \\\narchive_cmds \\\narchive_expsym_cmds \\\nmodule_cmds \\\nmodule_expsym_cmds \\\nexport_symbols_cmds \\\nprelink_cmds \\\npostinstall_cmds \\\npostuninstall_cmds \\\nfinish_cmds \\\nsys_lib_search_path_spec \\\nsys_lib_dlsearch_path_spec; do\n    case \\`eval \\\\\\\\\\$ECHO \\\\\\\\\"\"\\\\\\\\\\$\\$var\"\\\\\\\\\"\\` in\n    *[\\\\\\\\\\\\\\`\\\\\"\\\\\\$]*)\n      eval \"lt_\\$var=\\\\\\\\\\\\\"\\\\\\`\\\\\\$ECHO \\\\\"\\\\\\$\\$var\\\\\" | \\\\\\$SED -e \\\\\"\\\\\\$double_quote_subst\\\\\" -e \\\\\"\\\\\\$sed_quote_subst\\\\\" -e \\\\\"\\\\\\$delay_variable_subst\\\\\"\\\\\\`\\\\\\\\\\\\\"\"\n      ;;\n    *)\n      eval \"lt_\\$var=\\\\\\\\\\\\\"\\\\\\$\\$var\\\\\\\\\\\\\"\"\n      ;;\n    esac\ndone\n\nac_aux_dir='$ac_aux_dir'\nxsi_shell='$xsi_shell'\nlt_shell_append='$lt_shell_append'\n\n# See if we are running on zsh, and set the options which allow our\n# commands through without removal of \\ escapes INIT.\nif test -n \"\\${ZSH_VERSION+set}\" ; then\n   setopt NO_GLOB_SUBST\nfi\n\n\n    PACKAGE='$PACKAGE'\n    VERSION='$VERSION'\n    TIMESTAMP='$TIMESTAMP'\n    RM='$RM'\n    ofile='$ofile'\n\n\n\n\n# Variables needed in config.status (file generation) which aren't already\n# passed by autoconf.\nSUBDIRS=\"$SUBDIRS\"\n\n\n_ACEOF\n\ncat >>$CONFIG_STATUS <<\\_ACEOF || ac_write_fail=1\n\n# Handling of arguments.\nfor ac_config_target in $ac_config_targets\ndo\n  case $ac_config_target in\n    \"config.h\") CONFIG_HEADERS=\"$CONFIG_HEADERS config.h\" ;;\n    \"default-1\") CONFIG_COMMANDS=\"$CONFIG_COMMANDS default-1\" ;;\n    \"libtool\") CONFIG_COMMANDS=\"$CONFIG_COMMANDS libtool\" ;;\n    \"Makefile\") CONFIG_FILES=\"$CONFIG_FILES Makefile\" ;;\n    \"backtrace-supported.h\") CONFIG_FILES=\"$CONFIG_FILES backtrace-supported.h\" ;;\n    \"install-debuginfo-for-buildid.sh\") CONFIG_FILES=\"$CONFIG_FILES install-debuginfo-for-buildid.sh\" ;;\n    \"default\") CONFIG_COMMANDS=\"$CONFIG_COMMANDS default\" ;;\n\n  *) as_fn_error $? \"invalid argument: \\`$ac_config_target'\" \"$LINENO\" 5;;\n  esac\ndone\n\n\n# If the user did not use the arguments to specify the items to instantiate,\n# then the envvar interface is used.  Set only those that are not.\n# We use the long form for the default assignment because of an extremely\n# bizarre bug on SunOS 4.1.3.\nif $ac_need_defaults; then\n  test \"${CONFIG_FILES+set}\" = set || CONFIG_FILES=$config_files\n  test \"${CONFIG_HEADERS+set}\" = set || CONFIG_HEADERS=$config_headers\n  test \"${CONFIG_COMMANDS+set}\" = set || CONFIG_COMMANDS=$config_commands\nfi\n\n# Have a temporary directory for convenience.  Make it in the build tree\n# simply because there is no reason against having it here, and in addition,\n# creating and moving files from /tmp can sometimes cause problems.\n# Hook for its removal unless debugging.\n# Note that there is a small window in which the directory will not be cleaned:\n# after its creation but before its name has been assigned to `$tmp'.\n$debug ||\n{\n  tmp= ac_tmp=\n  trap 'exit_status=$?\n  : \"${ac_tmp:=$tmp}\"\n  { test ! -d \"$ac_tmp\" || rm -fr \"$ac_tmp\"; } && exit $exit_status\n' 0\n  trap 'as_fn_exit 1' 1 2 13 15\n}\n# Create a (secure) tmp directory for tmp files.\n\n{\n  tmp=`(umask 077 && mktemp -d \"./confXXXXXX\") 2>/dev/null` &&\n  test -d \"$tmp\"\n}  ||\n{\n  tmp=./conf$$-$RANDOM\n  (umask 077 && mkdir \"$tmp\")\n} || as_fn_error $? \"cannot create a temporary directory in .\" \"$LINENO\" 5\nac_tmp=$tmp\n\n# Set up the scripts for CONFIG_FILES section.\n# No need to generate them if there are no CONFIG_FILES.\n# This happens for instance with `./config.status config.h'.\nif test -n \"$CONFIG_FILES\"; then\n\n\nac_cr=`echo X | tr X '\\015'`\n# On cygwin, bash can eat \\r inside `` if the user requested igncr.\n# But we know of no other shell where ac_cr would be empty at this\n# point, so we can use a bashism as a fallback.\nif test \"x$ac_cr\" = x; then\n  eval ac_cr=\\$\\'\\\\r\\'\nfi\nac_cs_awk_cr=`$AWK 'BEGIN { print \"a\\rb\" }' </dev/null 2>/dev/null`\nif test \"$ac_cs_awk_cr\" = \"a${ac_cr}b\"; then\n  ac_cs_awk_cr='\\\\r'\nelse\n  ac_cs_awk_cr=$ac_cr\nfi\n\necho 'BEGIN {' >\"$ac_tmp/subs1.awk\" &&\n_ACEOF\n\n\n{\n  echo \"cat >conf$$subs.awk <<_ACEOF\" &&\n  echo \"$ac_subst_vars\" | sed 's/.*/&!$&$ac_delim/' &&\n  echo \"_ACEOF\"\n} >conf$$subs.sh ||\n  as_fn_error $? \"could not make $CONFIG_STATUS\" \"$LINENO\" 5\nac_delim_num=`echo \"$ac_subst_vars\" | grep -c '^'`\nac_delim='%!_!# '\nfor ac_last_try in false false false false false :; do\n  . ./conf$$subs.sh ||\n    as_fn_error $? \"could not make $CONFIG_STATUS\" \"$LINENO\" 5\n\n  ac_delim_n=`sed -n \"s/.*$ac_delim\\$/X/p\" conf$$subs.awk | grep -c X`\n  if test $ac_delim_n = $ac_delim_num; then\n    break\n  elif $ac_last_try; then\n    as_fn_error $? \"could not make $CONFIG_STATUS\" \"$LINENO\" 5\n  else\n    ac_delim=\"$ac_delim!$ac_delim _$ac_delim!! \"\n  fi\ndone\nrm -f conf$$subs.sh\n\ncat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1\ncat >>\"\\$ac_tmp/subs1.awk\" <<\\\\_ACAWK &&\n_ACEOF\nsed -n '\nh\ns/^/S[\"/; s/!.*/\"]=/\np\ng\ns/^[^!]*!//\n:repl\nt repl\ns/'\"$ac_delim\"'$//\nt delim\n:nl\nh\ns/\\(.\\{148\\}\\)..*/\\1/\nt more1\ns/[\"\\\\]/\\\\&/g; s/^/\"/; s/$/\\\\n\"\\\\/\np\nn\nb repl\n:more1\ns/[\"\\\\]/\\\\&/g; s/^/\"/; s/$/\"\\\\/\np\ng\ns/.\\{148\\}//\nt nl\n:delim\nh\ns/\\(.\\{148\\}\\)..*/\\1/\nt more2\ns/[\"\\\\]/\\\\&/g; s/^/\"/; s/$/\"/\np\nb\n:more2\ns/[\"\\\\]/\\\\&/g; s/^/\"/; s/$/\"\\\\/\np\ng\ns/.\\{148\\}//\nt delim\n' <conf$$subs.awk | sed '\n/^[^\"\"]/{\n  N\n  s/\\n//\n}\n' >>$CONFIG_STATUS || ac_write_fail=1\nrm -f conf$$subs.awk\ncat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1\n_ACAWK\ncat >>\"\\$ac_tmp/subs1.awk\" <<_ACAWK &&\n  for (key in S) S_is_set[key] = 1\n  FS = \"\u0007\"\n\n}\n{\n  line = $ 0\n  nfields = split(line, field, \"@\")\n  substed = 0\n  len = length(field[1])\n  for (i = 2; i < nfields; i++) {\n    key = field[i]\n    keylen = length(key)\n    if (S_is_set[key]) {\n      value = S[key]\n      line = substr(line, 1, len) \"\" value \"\" substr(line, len + keylen + 3)\n      len += length(value) + length(field[++i])\n      substed = 1\n    } else\n      len += 1 + keylen\n  }\n\n  print line\n}\n\n_ACAWK\n_ACEOF\ncat >>$CONFIG_STATUS <<\\_ACEOF || ac_write_fail=1\nif sed \"s/$ac_cr//\" < /dev/null > /dev/null 2>&1; then\n  sed \"s/$ac_cr\\$//; s/$ac_cr/$ac_cs_awk_cr/g\"\nelse\n  cat\nfi < \"$ac_tmp/subs1.awk\" > \"$ac_tmp/subs.awk\" \\\n  || as_fn_error $? \"could not setup config files machinery\" \"$LINENO\" 5\n_ACEOF\n\n# VPATH may cause trouble with some makes, so we remove sole $(srcdir),\n# ${srcdir} and @srcdir@ entries from VPATH if srcdir is \".\", strip leading and\n# trailing colons and then remove the whole line if VPATH becomes empty\n# (actually we leave an empty line to preserve line numbers).\nif test \"x$srcdir\" = x.; then\n  ac_vpsub='/^[\t ]*VPATH[\t ]*=[\t ]*/{\nh\ns///\ns/^/:/\ns/[\t ]*$/:/\ns/:\\$(srcdir):/:/g\ns/:\\${srcdir}:/:/g\ns/:@srcdir@:/:/g\ns/^:*//\ns/:*$//\nx\ns/\\(=[\t ]*\\).*/\\1/\nG\ns/\\n//\ns/^[^=]*=[\t ]*$//\n}'\nfi\n\ncat >>$CONFIG_STATUS <<\\_ACEOF || ac_write_fail=1\nfi # test -n \"$CONFIG_FILES\"\n\n# Set up the scripts for CONFIG_HEADERS section.\n# No need to generate them if there are no CONFIG_HEADERS.\n# This happens for instance with `./config.status Makefile'.\nif test -n \"$CONFIG_HEADERS\"; then\ncat >\"$ac_tmp/defines.awk\" <<\\_ACAWK ||\nBEGIN {\n_ACEOF\n\n# Transform confdefs.h into an awk script `defines.awk', embedded as\n# here-document in config.status, that substitutes the proper values into\n# config.h.in to produce config.h.\n\n# Create a delimiter string that does not exist in confdefs.h, to ease\n# handling of long lines.\nac_delim='%!_!# '\nfor ac_last_try in false false :; do\n  ac_tt=`sed -n \"/$ac_delim/p\" confdefs.h`\n  if test -z \"$ac_tt\"; then\n    break\n  elif $ac_last_try; then\n    as_fn_error $? \"could not make $CONFIG_HEADERS\" \"$LINENO\" 5\n  else\n    ac_delim=\"$ac_delim!$ac_delim _$ac_delim!! \"\n  fi\ndone\n\n# For the awk script, D is an array of macro values keyed by name,\n# likewise P contains macro parameters if any.  Preserve backslash\n# newline sequences.\n\nac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*\nsed -n '\ns/.\\{148\\}/&'\"$ac_delim\"'/g\nt rset\n:rset\ns/^[\t ]*#[\t ]*define[\t ][\t ]*/ /\nt def\nd\n:def\ns/\\\\$//\nt bsnl\ns/[\"\\\\]/\\\\&/g\ns/^ \\('\"$ac_word_re\"'\\)\\(([^()]*)\\)[\t ]*\\(.*\\)/P[\"\\1\"]=\"\\2\"\\\nD[\"\\1\"]=\" \\3\"/p\ns/^ \\('\"$ac_word_re\"'\\)[\t ]*\\(.*\\)/D[\"\\1\"]=\" \\2\"/p\nd\n:bsnl\ns/[\"\\\\]/\\\\&/g\ns/^ \\('\"$ac_word_re\"'\\)\\(([^()]*)\\)[\t ]*\\(.*\\)/P[\"\\1\"]=\"\\2\"\\\nD[\"\\1\"]=\" \\3\\\\\\\\\\\\n\"\\\\/p\nt cont\ns/^ \\('\"$ac_word_re\"'\\)[\t ]*\\(.*\\)/D[\"\\1\"]=\" \\2\\\\\\\\\\\\n\"\\\\/p\nt cont\nd\n:cont\nn\ns/.\\{148\\}/&'\"$ac_delim\"'/g\nt clear\n:clear\ns/\\\\$//\nt bsnlc\ns/[\"\\\\]/\\\\&/g; s/^/\"/; s/$/\"/p\nd\n:bsnlc\ns/[\"\\\\]/\\\\&/g; s/^/\"/; s/$/\\\\\\\\\\\\n\"\\\\/p\nb cont\n' <confdefs.h | sed '\ns/'\"$ac_delim\"'/\"\\\\\\\n\"/g' >>$CONFIG_STATUS || ac_write_fail=1\n\ncat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1\n  for (key in D) D_is_set[key] = 1\n  FS = \"\u0007\"\n}\n/^[\\t ]*#[\\t ]*(define|undef)[\\t ]+$ac_word_re([\\t (]|\\$)/ {\n  line = \\$ 0\n  split(line, arg, \" \")\n  if (arg[1] == \"#\") {\n    defundef = arg[2]\n    mac1 = arg[3]\n  } else {\n    defundef = substr(arg[1], 2)\n    mac1 = arg[2]\n  }\n  split(mac1, mac2, \"(\") #)\n  macro = mac2[1]\n  prefix = substr(line, 1, index(line, defundef) - 1)\n  if (D_is_set[macro]) {\n    # Preserve the white space surrounding the \"#\".\n    print prefix \"define\", macro P[macro] D[macro]\n    next\n  } else {\n    # Replace #undef with comments.  This is necessary, for example,\n    # in the case of _POSIX_SOURCE, which is predefined and required\n    # on some systems where configure will not decide to define it.\n    if (defundef == \"undef\") {\n      print \"/*\", prefix defundef, macro, \"*/\"\n      next\n    }\n  }\n}\n{ print }\n_ACAWK\n_ACEOF\ncat >>$CONFIG_STATUS <<\\_ACEOF || ac_write_fail=1\n  as_fn_error $? \"could not setup config headers machinery\" \"$LINENO\" 5\nfi # test -n \"$CONFIG_HEADERS\"\n\n\neval set X \"  :F $CONFIG_FILES  :H $CONFIG_HEADERS    :C $CONFIG_COMMANDS\"\nshift\nfor ac_tag\ndo\n  case $ac_tag in\n  :[FHLC]) ac_mode=$ac_tag; continue;;\n  esac\n  case $ac_mode$ac_tag in\n  :[FHL]*:*);;\n  :L* | :C*:*) as_fn_error $? \"invalid tag \\`$ac_tag'\" \"$LINENO\" 5;;\n  :[FH]-) ac_tag=-:-;;\n  :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;\n  esac\n  ac_save_IFS=$IFS\n  IFS=:\n  set x $ac_tag\n  IFS=$ac_save_IFS\n  shift\n  ac_file=$1\n  shift\n\n  case $ac_mode in\n  :L) ac_source=$1;;\n  :[FH])\n    ac_file_inputs=\n    for ac_f\n    do\n      case $ac_f in\n      -) ac_f=\"$ac_tmp/stdin\";;\n      *) # Look for the file first in the build tree, then in the source tree\n\t # (if the path is not absolute).  The absolute path cannot be DOS-style,\n\t # because $ac_f cannot contain `:'.\n\t test -f \"$ac_f\" ||\n\t   case $ac_f in\n\t   [\\\\/$]*) false;;\n\t   *) test -f \"$srcdir/$ac_f\" && ac_f=\"$srcdir/$ac_f\";;\n\t   esac ||\n\t   as_fn_error 1 \"cannot find input file: \\`$ac_f'\" \"$LINENO\" 5;;\n      esac\n      case $ac_f in *\\'*) ac_f=`$as_echo \"$ac_f\" | sed \"s/'/'\\\\\\\\\\\\\\\\''/g\"`;; esac\n      as_fn_append ac_file_inputs \" '$ac_f'\"\n    done\n\n    # Let's still pretend it is `configure' which instantiates (i.e., don't\n    # use $as_me), people would be surprised to read:\n    #    /* config.h.  Generated by config.status.  */\n    configure_input='Generated from '`\n\t  $as_echo \"$*\" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'\n\t`' by configure.'\n    if test x\"$ac_file\" != x-; then\n      configure_input=\"$ac_file.  $configure_input\"\n      { $as_echo \"$as_me:${as_lineno-$LINENO}: creating $ac_file\" >&5\n$as_echo \"$as_me: creating $ac_file\" >&6;}\n    fi\n    # Neutralize special characters interpreted by sed in replacement strings.\n    case $configure_input in #(\n    *\\&* | *\\|* | *\\\\* )\n       ac_sed_conf_input=`$as_echo \"$configure_input\" |\n       sed 's/[\\\\\\\\&|]/\\\\\\\\&/g'`;; #(\n    *) ac_sed_conf_input=$configure_input;;\n    esac\n\n    case $ac_tag in\n    *:-:* | *:-) cat >\"$ac_tmp/stdin\" \\\n      || as_fn_error $? \"could not create $ac_file\" \"$LINENO\" 5 ;;\n    esac\n    ;;\n  esac\n\n  ac_dir=`$as_dirname -- \"$ac_file\" ||\n$as_expr X\"$ac_file\" : 'X\\(.*[^/]\\)//*[^/][^/]*/*$' \\| \\\n\t X\"$ac_file\" : 'X\\(//\\)[^/]' \\| \\\n\t X\"$ac_file\" : 'X\\(//\\)$' \\| \\\n\t X\"$ac_file\" : 'X\\(/\\)' \\| . 2>/dev/null ||\n$as_echo X\"$ac_file\" |\n    sed '/^X\\(.*[^/]\\)\\/\\/*[^/][^/]*\\/*$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\/\\)[^/].*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\/\\)$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\).*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  s/.*/./; q'`\n  as_dir=\"$ac_dir\"; as_fn_mkdir_p\n  ac_builddir=.\n\ncase \"$ac_dir\" in\n.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;\n*)\n  ac_dir_suffix=/`$as_echo \"$ac_dir\" | sed 's|^\\.[\\\\/]||'`\n  # A \"..\" for each directory in $ac_dir_suffix.\n  ac_top_builddir_sub=`$as_echo \"$ac_dir_suffix\" | sed 's|/[^\\\\/]*|/..|g;s|/||'`\n  case $ac_top_builddir_sub in\n  \"\") ac_top_builddir_sub=. ac_top_build_prefix= ;;\n  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;\n  esac ;;\nesac\nac_abs_top_builddir=$ac_pwd\nac_abs_builddir=$ac_pwd$ac_dir_suffix\n# for backward compatibility:\nac_top_builddir=$ac_top_build_prefix\n\ncase $srcdir in\n  .)  # We are building in place.\n    ac_srcdir=.\n    ac_top_srcdir=$ac_top_builddir_sub\n    ac_abs_top_srcdir=$ac_pwd ;;\n  [\\\\/]* | ?:[\\\\/]* )  # Absolute name.\n    ac_srcdir=$srcdir$ac_dir_suffix;\n    ac_top_srcdir=$srcdir\n    ac_abs_top_srcdir=$srcdir ;;\n  *) # Relative name.\n    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix\n    ac_top_srcdir=$ac_top_build_prefix$srcdir\n    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;\nesac\nac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix\n\n\n  case $ac_mode in\n  :F)\n  #\n  # CONFIG_FILE\n  #\n\n  case $INSTALL in\n  [\\\\/$]* | ?:[\\\\/]* ) ac_INSTALL=$INSTALL ;;\n  *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;\n  esac\n  ac_MKDIR_P=$MKDIR_P\n  case $MKDIR_P in\n  [\\\\/$]* | ?:[\\\\/]* ) ;;\n  */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;;\n  esac\n_ACEOF\n\ncat >>$CONFIG_STATUS <<\\_ACEOF || ac_write_fail=1\n# If the template does not know about datarootdir, expand it.\n# FIXME: This hack should be removed a few years after 2.60.\nac_datarootdir_hack=; ac_datarootdir_seen=\nac_sed_dataroot='\n/datarootdir/ {\n  p\n  q\n}\n/@datadir@/p\n/@docdir@/p\n/@infodir@/p\n/@localedir@/p\n/@mandir@/p'\ncase `eval \"sed -n \\\"\\$ac_sed_dataroot\\\" $ac_file_inputs\"` in\n*datarootdir*) ac_datarootdir_seen=yes;;\n*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting\" >&5\n$as_echo \"$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting\" >&2;}\n_ACEOF\ncat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1\n  ac_datarootdir_hack='\n  s&@datadir@&$datadir&g\n  s&@docdir@&$docdir&g\n  s&@infodir@&$infodir&g\n  s&@localedir@&$localedir&g\n  s&@mandir@&$mandir&g\n  s&\\\\\\${datarootdir}&$datarootdir&g' ;;\nesac\n_ACEOF\n\n# Neutralize VPATH when `$srcdir' = `.'.\n# Shell code in configure.ac might set extrasub.\n# FIXME: do we really want to maintain this feature?\ncat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1\nac_sed_extra=\"$ac_vpsub\n$extrasub\n_ACEOF\ncat >>$CONFIG_STATUS <<\\_ACEOF || ac_write_fail=1\n:t\n/@[a-zA-Z_][a-zA-Z_0-9]*@/!b\ns|@configure_input@|$ac_sed_conf_input|;t t\ns&@top_builddir@&$ac_top_builddir_sub&;t t\ns&@top_build_prefix@&$ac_top_build_prefix&;t t\ns&@srcdir@&$ac_srcdir&;t t\ns&@abs_srcdir@&$ac_abs_srcdir&;t t\ns&@top_srcdir@&$ac_top_srcdir&;t t\ns&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t\ns&@builddir@&$ac_builddir&;t t\ns&@abs_builddir@&$ac_abs_builddir&;t t\ns&@abs_top_builddir@&$ac_abs_top_builddir&;t t\ns&@INSTALL@&$ac_INSTALL&;t t\ns&@MKDIR_P@&$ac_MKDIR_P&;t t\n$ac_datarootdir_hack\n\"\neval sed \\\"\\$ac_sed_extra\\\" \"$ac_file_inputs\" | $AWK -f \"$ac_tmp/subs.awk\" \\\n  >$ac_tmp/out || as_fn_error $? \"could not create $ac_file\" \"$LINENO\" 5\n\ntest -z \"$ac_datarootdir_hack$ac_datarootdir_seen\" &&\n  { ac_out=`sed -n '/\\${datarootdir}/p' \"$ac_tmp/out\"`; test -n \"$ac_out\"; } &&\n  { ac_out=`sed -n '/^[\t ]*datarootdir[\t ]*:*=/p' \\\n      \"$ac_tmp/out\"`; test -z \"$ac_out\"; } &&\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \\`datarootdir'\nwhich seems to be undefined.  Please make sure it is defined\" >&5\n$as_echo \"$as_me: WARNING: $ac_file contains a reference to the variable \\`datarootdir'\nwhich seems to be undefined.  Please make sure it is defined\" >&2;}\n\n  rm -f \"$ac_tmp/stdin\"\n  case $ac_file in\n  -) cat \"$ac_tmp/out\" && rm -f \"$ac_tmp/out\";;\n  *) rm -f \"$ac_file\" && mv \"$ac_tmp/out\" \"$ac_file\";;\n  esac \\\n  || as_fn_error $? \"could not create $ac_file\" \"$LINENO\" 5\n ;;\n  :H)\n  #\n  # CONFIG_HEADER\n  #\n  if test x\"$ac_file\" != x-; then\n    {\n      $as_echo \"/* $configure_input  */\" \\\n      && eval '$AWK -f \"$ac_tmp/defines.awk\"' \"$ac_file_inputs\"\n    } >\"$ac_tmp/config.h\" \\\n      || as_fn_error $? \"could not create $ac_file\" \"$LINENO\" 5\n    if diff \"$ac_file\" \"$ac_tmp/config.h\" >/dev/null 2>&1; then\n      { $as_echo \"$as_me:${as_lineno-$LINENO}: $ac_file is unchanged\" >&5\n$as_echo \"$as_me: $ac_file is unchanged\" >&6;}\n    else\n      rm -f \"$ac_file\"\n      mv \"$ac_tmp/config.h\" \"$ac_file\" \\\n\t|| as_fn_error $? \"could not create $ac_file\" \"$LINENO\" 5\n    fi\n  else\n    $as_echo \"/* $configure_input  */\" \\\n      && eval '$AWK -f \"$ac_tmp/defines.awk\"' \"$ac_file_inputs\" \\\n      || as_fn_error $? \"could not create -\" \"$LINENO\" 5\n  fi\n# Compute \"$ac_file\"'s index in $config_headers.\n_am_arg=\"$ac_file\"\n_am_stamp_count=1\nfor _am_header in $config_headers :; do\n  case $_am_header in\n    $_am_arg | $_am_arg:* )\n      break ;;\n    * )\n      _am_stamp_count=`expr $_am_stamp_count + 1` ;;\n  esac\ndone\necho \"timestamp for $_am_arg\" >`$as_dirname -- \"$_am_arg\" ||\n$as_expr X\"$_am_arg\" : 'X\\(.*[^/]\\)//*[^/][^/]*/*$' \\| \\\n\t X\"$_am_arg\" : 'X\\(//\\)[^/]' \\| \\\n\t X\"$_am_arg\" : 'X\\(//\\)$' \\| \\\n\t X\"$_am_arg\" : 'X\\(/\\)' \\| . 2>/dev/null ||\n$as_echo X\"$_am_arg\" |\n    sed '/^X\\(.*[^/]\\)\\/\\/*[^/][^/]*\\/*$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\/\\)[^/].*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\/\\)$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\).*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  s/.*/./; q'`/stamp-h$_am_stamp_count\n ;;\n\n  :C)  { $as_echo \"$as_me:${as_lineno-$LINENO}: executing $ac_file commands\" >&5\n$as_echo \"$as_me: executing $ac_file commands\" >&6;}\n ;;\n  esac\n\n\n  case $ac_file$ac_mode in\n    \"default-1\":C)\n# Only add multilib support code if we just rebuilt the top-level\n# Makefile.\ncase \" $CONFIG_FILES \" in\n *\" Makefile \"*)\n   ac_file=Makefile . ${multi_basedir}/config-ml.in\n   ;;\nesac ;;\n    \"libtool\":C)\n\n    # See if we are running on zsh, and set the options which allow our\n    # commands through without removal of \\ escapes.\n    if test -n \"${ZSH_VERSION+set}\" ; then\n      setopt NO_GLOB_SUBST\n    fi\n\n    cfgfile=\"${ofile}T\"\n    trap \"$RM \\\"$cfgfile\\\"; exit 1\" 1 2 15\n    $RM \"$cfgfile\"\n\n    cat <<_LT_EOF >> \"$cfgfile\"\n#! $SHELL\n\n# `$ECHO \"$ofile\" | sed 's%^.*/%%'` - Provide generalized library-building support services.\n# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION\n# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:\n# NOTE: Changes made to this file will be lost: look at ltmain.sh.\n#\n#   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,\n#                 2006, 2007, 2008, 2009 Free Software Foundation, Inc.\n#   Written by Gordon Matzigkeit, 1996\n#\n#   This file is part of GNU Libtool.\n#\n# GNU Libtool is free software; you can redistribute it and/or\n# modify it under the terms of the GNU General Public License as\n# published by the Free Software Foundation; either version 2 of\n# the License, or (at your option) any later version.\n#\n# As a special exception to the GNU General Public License,\n# if you distribute this file as part of a program or library that\n# is built using GNU Libtool, you may include this file under the\n# same distribution terms that you use for the rest of that program.\n#\n# GNU Libtool is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with GNU Libtool; see the file COPYING.  If not, a copy\n# can be downloaded from http://www.gnu.org/licenses/gpl.html, or\n# obtained by writing to the Free Software Foundation, Inc.,\n# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n\n\n# The names of the tagged configurations supported by this script.\navailable_tags=\"\"\n\n# ### BEGIN LIBTOOL CONFIG\n\n# Whether or not to build shared libraries.\nbuild_libtool_libs=$enable_shared\n\n# Which release of libtool.m4 was used?\nmacro_version=$macro_version\nmacro_revision=$macro_revision\n\n# Whether or not to build static libraries.\nbuild_old_libs=$enable_static\n\n# What type of objects to build.\npic_mode=$pic_mode\n\n# Whether or not to optimize for fast installation.\nfast_install=$enable_fast_install\n\n# Shell to use when invoking shell scripts.\nSHELL=$lt_SHELL\n\n# An echo program that protects backslashes.\nECHO=$lt_ECHO\n\n# The host system.\nhost_alias=$host_alias\nhost=$host\nhost_os=$host_os\n\n# The build system.\nbuild_alias=$build_alias\nbuild=$build\nbuild_os=$build_os\n\n# A sed program that does not truncate output.\nSED=$lt_SED\n\n# Sed that helps us avoid accidentally triggering echo(1) options like -n.\nXsed=\"\\$SED -e 1s/^X//\"\n\n# A grep program that handles long lines.\nGREP=$lt_GREP\n\n# An ERE matcher.\nEGREP=$lt_EGREP\n\n# A literal string matcher.\nFGREP=$lt_FGREP\n\n# A BSD- or MS-compatible name lister.\nNM=$lt_NM\n\n# Whether we need soft or hard links.\nLN_S=$lt_LN_S\n\n# What is the maximum length of a command?\nmax_cmd_len=$max_cmd_len\n\n# Object file suffix (normally \"o\").\nobjext=$ac_objext\n\n# Executable file suffix (normally \"\").\nexeext=$exeext\n\n# whether the shell understands \"unset\".\nlt_unset=$lt_unset\n\n# turn spaces into newlines.\nSP2NL=$lt_lt_SP2NL\n\n# turn newlines into spaces.\nNL2SP=$lt_lt_NL2SP\n\n# An object symbol dumper.\nOBJDUMP=$lt_OBJDUMP\n\n# Method to check whether dependent libraries are shared objects.\ndeplibs_check_method=$lt_deplibs_check_method\n\n# Command to use when deplibs_check_method == \"file_magic\".\nfile_magic_cmd=$lt_file_magic_cmd\n\n# The archiver.\nAR=$lt_AR\nAR_FLAGS=$lt_AR_FLAGS\n\n# A symbol stripping program.\nSTRIP=$lt_STRIP\n\n# Commands used to install an old-style archive.\nRANLIB=$lt_RANLIB\nold_postinstall_cmds=$lt_old_postinstall_cmds\nold_postuninstall_cmds=$lt_old_postuninstall_cmds\n\n# Whether to use a lock for old archive extraction.\nlock_old_archive_extraction=$lock_old_archive_extraction\n\n# A C compiler.\nLTCC=$lt_CC\n\n# LTCC compiler flags.\nLTCFLAGS=$lt_CFLAGS\n\n# Take the output of nm and produce a listing of raw symbols and C names.\nglobal_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe\n\n# Transform the output of nm in a proper C declaration.\nglobal_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl\n\n# Transform the output of nm in a C name address pair.\nglobal_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address\n\n# Transform the output of nm in a C name address pair when lib prefix is needed.\nglobal_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix\n\n# The name of the directory that contains temporary libtool files.\nobjdir=$objdir\n\n# Used to examine libraries when file_magic_cmd begins with \"file\".\nMAGIC_CMD=$MAGIC_CMD\n\n# Must we lock files when doing compilation?\nneed_locks=$lt_need_locks\n\n# Tool to manipulate archived DWARF debug symbol files on Mac OS X.\nDSYMUTIL=$lt_DSYMUTIL\n\n# Tool to change global to local symbols on Mac OS X.\nNMEDIT=$lt_NMEDIT\n\n# Tool to manipulate fat objects and archives on Mac OS X.\nLIPO=$lt_LIPO\n\n# ldd/readelf like tool for Mach-O binaries on Mac OS X.\nOTOOL=$lt_OTOOL\n\n# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4.\nOTOOL64=$lt_OTOOL64\n\n# Old archive suffix (normally \"a\").\nlibext=$libext\n\n# Shared library suffix (normally \".so\").\nshrext_cmds=$lt_shrext_cmds\n\n# The commands to extract the exported symbol list from a shared archive.\nextract_expsyms_cmds=$lt_extract_expsyms_cmds\n\n# Variables whose values should be saved in libtool wrapper scripts and\n# restored at link time.\nvariables_saved_for_relink=$lt_variables_saved_for_relink\n\n# Do we need the \"lib\" prefix for modules?\nneed_lib_prefix=$need_lib_prefix\n\n# Do we need a version for libraries?\nneed_version=$need_version\n\n# Library versioning type.\nversion_type=$version_type\n\n# Shared library runtime path variable.\nrunpath_var=$runpath_var\n\n# Shared library path variable.\nshlibpath_var=$shlibpath_var\n\n# Is shlibpath searched before the hard-coded library search path?\nshlibpath_overrides_runpath=$shlibpath_overrides_runpath\n\n# Format of library name prefix.\nlibname_spec=$lt_libname_spec\n\n# List of archive names.  First name is the real one, the rest are links.\n# The last name is the one that the linker finds with -lNAME\nlibrary_names_spec=$lt_library_names_spec\n\n# The coded name of the library, if different from the real name.\nsoname_spec=$lt_soname_spec\n\n# Permission mode override for installation of shared libraries.\ninstall_override_mode=$lt_install_override_mode\n\n# Command to use after installation of a shared archive.\npostinstall_cmds=$lt_postinstall_cmds\n\n# Command to use after uninstallation of a shared archive.\npostuninstall_cmds=$lt_postuninstall_cmds\n\n# Commands used to finish a libtool library installation in a directory.\nfinish_cmds=$lt_finish_cmds\n\n# As \"finish_cmds\", except a single script fragment to be evaled but\n# not shown.\nfinish_eval=$lt_finish_eval\n\n# Whether we should hardcode library paths into libraries.\nhardcode_into_libs=$hardcode_into_libs\n\n# Compile-time system search path for libraries.\nsys_lib_search_path_spec=$lt_sys_lib_search_path_spec\n\n# Run-time system search path for libraries.\nsys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec\n\n# Whether dlopen is supported.\ndlopen_support=$enable_dlopen\n\n# Whether dlopen of programs is supported.\ndlopen_self=$enable_dlopen_self\n\n# Whether dlopen of statically linked programs is supported.\ndlopen_self_static=$enable_dlopen_self_static\n\n# Commands to strip libraries.\nold_striplib=$lt_old_striplib\nstriplib=$lt_striplib\n\n\n# The linker used to build libraries.\nLD=$lt_LD\n\n# How to create reloadable object files.\nreload_flag=$lt_reload_flag\nreload_cmds=$lt_reload_cmds\n\n# Commands used to build an old-style archive.\nold_archive_cmds=$lt_old_archive_cmds\n\n# A language specific compiler.\nCC=$lt_compiler\n\n# Is the compiler the GNU compiler?\nwith_gcc=$GCC\n\n# Compiler flag to turn off builtin functions.\nno_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag\n\n# How to pass a linker flag through the compiler.\nwl=$lt_lt_prog_compiler_wl\n\n# Additional compiler flags for building library objects.\npic_flag=$lt_lt_prog_compiler_pic\n\n# Compiler flag to prevent dynamic linking.\nlink_static_flag=$lt_lt_prog_compiler_static\n\n# Does compiler simultaneously support -c and -o options?\ncompiler_c_o=$lt_lt_cv_prog_compiler_c_o\n\n# Whether or not to add -lc for building shared libraries.\nbuild_libtool_need_lc=$archive_cmds_need_lc\n\n# Whether or not to disallow shared libs when runtime libs are static.\nallow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes\n\n# Compiler flag to allow reflexive dlopens.\nexport_dynamic_flag_spec=$lt_export_dynamic_flag_spec\n\n# Compiler flag to generate shared objects directly from archives.\nwhole_archive_flag_spec=$lt_whole_archive_flag_spec\n\n# Whether the compiler copes with passing no objects directly.\ncompiler_needs_object=$lt_compiler_needs_object\n\n# Create an old-style archive from a shared archive.\nold_archive_from_new_cmds=$lt_old_archive_from_new_cmds\n\n# Create a temporary old-style archive to link instead of a shared archive.\nold_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds\n\n# Commands used to build a shared archive.\narchive_cmds=$lt_archive_cmds\narchive_expsym_cmds=$lt_archive_expsym_cmds\n\n# Commands used to build a loadable module if different from building\n# a shared archive.\nmodule_cmds=$lt_module_cmds\nmodule_expsym_cmds=$lt_module_expsym_cmds\n\n# Whether we are building with GNU ld or not.\nwith_gnu_ld=$lt_with_gnu_ld\n\n# Flag that allows shared libraries with undefined symbols to be built.\nallow_undefined_flag=$lt_allow_undefined_flag\n\n# Flag that enforces no undefined symbols.\nno_undefined_flag=$lt_no_undefined_flag\n\n# Flag to hardcode \\$libdir into a binary during linking.\n# This must work even if \\$libdir does not exist\nhardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec\n\n# If ld is used when linking, flag to hardcode \\$libdir into a binary\n# during linking.  This must work even if \\$libdir does not exist.\nhardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld\n\n# Whether we need a single \"-rpath\" flag with a separated argument.\nhardcode_libdir_separator=$lt_hardcode_libdir_separator\n\n# Set to \"yes\" if using DIR/libNAME\\${shared_ext} during linking hardcodes\n# DIR into the resulting binary.\nhardcode_direct=$hardcode_direct\n\n# Set to \"yes\" if using DIR/libNAME\\${shared_ext} during linking hardcodes\n# DIR into the resulting binary and the resulting library dependency is\n# \"absolute\",i.e impossible to change by setting \\${shlibpath_var} if the\n# library is relocated.\nhardcode_direct_absolute=$hardcode_direct_absolute\n\n# Set to \"yes\" if using the -LDIR flag during linking hardcodes DIR\n# into the resulting binary.\nhardcode_minus_L=$hardcode_minus_L\n\n# Set to \"yes\" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR\n# into the resulting binary.\nhardcode_shlibpath_var=$hardcode_shlibpath_var\n\n# Set to \"yes\" if building a shared library automatically hardcodes DIR\n# into the library and all subsequent libraries and executables linked\n# against it.\nhardcode_automatic=$hardcode_automatic\n\n# Set to yes if linker adds runtime paths of dependent libraries\n# to runtime path list.\ninherit_rpath=$inherit_rpath\n\n# Whether libtool must link a program against all its dependency libraries.\nlink_all_deplibs=$link_all_deplibs\n\n# Fix the shell variable \\$srcfile for the compiler.\nfix_srcfile_path=$lt_fix_srcfile_path\n\n# Set to \"yes\" if exported symbols are required.\nalways_export_symbols=$always_export_symbols\n\n# The commands to list exported symbols.\nexport_symbols_cmds=$lt_export_symbols_cmds\n\n# Symbols that should not be listed in the preloaded symbols.\nexclude_expsyms=$lt_exclude_expsyms\n\n# Symbols that must always be exported.\ninclude_expsyms=$lt_include_expsyms\n\n# Commands necessary for linking programs (against libraries) with templates.\nprelink_cmds=$lt_prelink_cmds\n\n# Specify filename containing input files.\nfile_list_spec=$lt_file_list_spec\n\n# How to hardcode a shared library path into an executable.\nhardcode_action=$hardcode_action\n\n# ### END LIBTOOL CONFIG\n\n_LT_EOF\n\n  case $host_os in\n  aix3*)\n    cat <<\\_LT_EOF >> \"$cfgfile\"\n# AIX sometimes has problems with the GCC collect2 program.  For some\n# reason, if we set the COLLECT_NAMES environment variable, the problems\n# vanish in a puff of smoke.\nif test \"X${COLLECT_NAMES+set}\" != Xset; then\n  COLLECT_NAMES=\n  export COLLECT_NAMES\nfi\n_LT_EOF\n    ;;\n  esac\n\n\nltmain=\"$ac_aux_dir/ltmain.sh\"\n\n\n  # We use sed instead of cat because bash on DJGPP gets confused if\n  # if finds mixed CR/LF and LF-only lines.  Since sed operates in\n  # text mode, it properly converts lines to CR/LF.  This bash problem\n  # is reportedly fixed, but why not run on old versions too?\n  sed '/^# Generated shell functions inserted here/q' \"$ltmain\" >> \"$cfgfile\" \\\n    || (rm -f \"$cfgfile\"; exit 1)\n\n  case $xsi_shell in\n  yes)\n    cat << \\_LT_EOF >> \"$cfgfile\"\n\n# func_dirname file append nondir_replacement\n# Compute the dirname of FILE.  If nonempty, add APPEND to the result,\n# otherwise set result to NONDIR_REPLACEMENT.\nfunc_dirname ()\n{\n  case ${1} in\n    */*) func_dirname_result=\"${1%/*}${2}\" ;;\n    *  ) func_dirname_result=\"${3}\" ;;\n  esac\n}\n\n# func_basename file\nfunc_basename ()\n{\n  func_basename_result=\"${1##*/}\"\n}\n\n# func_dirname_and_basename file append nondir_replacement\n# perform func_basename and func_dirname in a single function\n# call:\n#   dirname:  Compute the dirname of FILE.  If nonempty,\n#             add APPEND to the result, otherwise set result\n#             to NONDIR_REPLACEMENT.\n#             value returned in \"$func_dirname_result\"\n#   basename: Compute filename of FILE.\n#             value retuned in \"$func_basename_result\"\n# Implementation must be kept synchronized with func_dirname\n# and func_basename. For efficiency, we do not delegate to\n# those functions but instead duplicate the functionality here.\nfunc_dirname_and_basename ()\n{\n  case ${1} in\n    */*) func_dirname_result=\"${1%/*}${2}\" ;;\n    *  ) func_dirname_result=\"${3}\" ;;\n  esac\n  func_basename_result=\"${1##*/}\"\n}\n\n# func_stripname prefix suffix name\n# strip PREFIX and SUFFIX off of NAME.\n# PREFIX and SUFFIX must not contain globbing or regex special\n# characters, hashes, percent signs, but SUFFIX may contain a leading\n# dot (in which case that matches only a dot).\nfunc_stripname ()\n{\n  # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are\n  # positional parameters, so assign one to ordinary parameter first.\n  func_stripname_result=${3}\n  func_stripname_result=${func_stripname_result#\"${1}\"}\n  func_stripname_result=${func_stripname_result%\"${2}\"}\n}\n\n# func_opt_split\nfunc_opt_split ()\n{\n  func_opt_split_opt=${1%%=*}\n  func_opt_split_arg=${1#*=}\n}\n\n# func_lo2o object\nfunc_lo2o ()\n{\n  case ${1} in\n    *.lo) func_lo2o_result=${1%.lo}.${objext} ;;\n    *)    func_lo2o_result=${1} ;;\n  esac\n}\n\n# func_xform libobj-or-source\nfunc_xform ()\n{\n  func_xform_result=${1%.*}.lo\n}\n\n# func_arith arithmetic-term...\nfunc_arith ()\n{\n  func_arith_result=$(( $* ))\n}\n\n# func_len string\n# STRING may not start with a hyphen.\nfunc_len ()\n{\n  func_len_result=${#1}\n}\n\n_LT_EOF\n    ;;\n  *) # Bourne compatible functions.\n    cat << \\_LT_EOF >> \"$cfgfile\"\n\n# func_dirname file append nondir_replacement\n# Compute the dirname of FILE.  If nonempty, add APPEND to the result,\n# otherwise set result to NONDIR_REPLACEMENT.\nfunc_dirname ()\n{\n  # Extract subdirectory from the argument.\n  func_dirname_result=`$ECHO \"${1}\" | $SED \"$dirname\"`\n  if test \"X$func_dirname_result\" = \"X${1}\"; then\n    func_dirname_result=\"${3}\"\n  else\n    func_dirname_result=\"$func_dirname_result${2}\"\n  fi\n}\n\n# func_basename file\nfunc_basename ()\n{\n  func_basename_result=`$ECHO \"${1}\" | $SED \"$basename\"`\n}\n\n\n# func_stripname prefix suffix name\n# strip PREFIX and SUFFIX off of NAME.\n# PREFIX and SUFFIX must not contain globbing or regex special\n# characters, hashes, percent signs, but SUFFIX may contain a leading\n# dot (in which case that matches only a dot).\n# func_strip_suffix prefix name\nfunc_stripname ()\n{\n  case ${2} in\n    .*) func_stripname_result=`$ECHO \"${3}\" | $SED \"s%^${1}%%; s%\\\\\\\\${2}\\$%%\"`;;\n    *)  func_stripname_result=`$ECHO \"${3}\" | $SED \"s%^${1}%%; s%${2}\\$%%\"`;;\n  esac\n}\n\n# sed scripts:\nmy_sed_long_opt='1s/^\\(-[^=]*\\)=.*/\\1/;q'\nmy_sed_long_arg='1s/^-[^=]*=//'\n\n# func_opt_split\nfunc_opt_split ()\n{\n  func_opt_split_opt=`$ECHO \"${1}\" | $SED \"$my_sed_long_opt\"`\n  func_opt_split_arg=`$ECHO \"${1}\" | $SED \"$my_sed_long_arg\"`\n}\n\n# func_lo2o object\nfunc_lo2o ()\n{\n  func_lo2o_result=`$ECHO \"${1}\" | $SED \"$lo2o\"`\n}\n\n# func_xform libobj-or-source\nfunc_xform ()\n{\n  func_xform_result=`$ECHO \"${1}\" | $SED 's/\\.[^.]*$/.lo/'`\n}\n\n# func_arith arithmetic-term...\nfunc_arith ()\n{\n  func_arith_result=`expr \"$@\"`\n}\n\n# func_len string\n# STRING may not start with a hyphen.\nfunc_len ()\n{\n  func_len_result=`expr \"$1\" : \".*\" 2>/dev/null || echo $max_cmd_len`\n}\n\n_LT_EOF\nesac\n\ncase $lt_shell_append in\n  yes)\n    cat << \\_LT_EOF >> \"$cfgfile\"\n\n# func_append var value\n# Append VALUE to the end of shell variable VAR.\nfunc_append ()\n{\n  eval \"$1+=\\$2\"\n}\n_LT_EOF\n    ;;\n  *)\n    cat << \\_LT_EOF >> \"$cfgfile\"\n\n# func_append var value\n# Append VALUE to the end of shell variable VAR.\nfunc_append ()\n{\n  eval \"$1=\\$$1\\$2\"\n}\n\n_LT_EOF\n    ;;\n  esac\n\n\n  sed -n '/^# Generated shell functions inserted here/,$p' \"$ltmain\" >> \"$cfgfile\" \\\n    || (rm -f \"$cfgfile\"; exit 1)\n\n  mv -f \"$cfgfile\" \"$ofile\" ||\n    (rm -f \"$ofile\" && cp \"$cfgfile\" \"$ofile\" && rm -f \"$cfgfile\")\n  chmod +x \"$ofile\"\n\n ;;\n    \"install-debuginfo-for-buildid.sh\":F) chmod +x install-debuginfo-for-buildid.sh ;;\n    \"default\":C) if test -n \"$CONFIG_FILES\"; then\n   if test -n \"${with_target_subdir}\"; then\n     # Multilibs need MULTISUBDIR defined correctly in certain makefiles so\n     # that multilib installs will end up installed in the correct place.\n     # The testsuite needs it for multilib-aware ABI baseline files.\n     # To work around this not being passed down from config-ml.in ->\n     # srcdir/Makefile.am -> srcdir/{src,libsupc++,...}/Makefile.am, manually\n     # append it here.  Only modify Makefiles that have just been created.\n     #\n     # Also, get rid of this simulated-VPATH thing that automake does.\n     cat > vpsed << \\_EOF\n  s!`test -f '$<' || echo '$(srcdir)/'`!!\n_EOF\n     for i in $SUBDIRS; do\n      case $CONFIG_FILES in\n       *${i}/Makefile*)\n\t #echo \"Adding MULTISUBDIR to $i/Makefile\"\n\t sed -f vpsed $i/Makefile > tmp\n\t grep '^MULTISUBDIR =' Makefile >> tmp\n\t mv tmp $i/Makefile\n\t ;;\n      esac\n     done\n     rm vpsed\n   fi\n fi\n ;;\n\n  esac\ndone # for ac_tag\n\n\nas_fn_exit 0\n_ACEOF\nac_clean_files=$ac_clean_files_save\n\ntest $ac_write_fail = 0 ||\n  as_fn_error $? \"write failure creating $CONFIG_STATUS\" \"$LINENO\" 5\n\n\n# configure is writing to config.log, and then calls config.status.\n# config.status does its own redirection, appending to config.log.\n# Unfortunately, on DOS this fails, as config.log is still kept open\n# by configure, so config.status won't be able to write to it; its\n# output is simply discarded.  So we exec the FD to /dev/null,\n# effectively closing config.log, so it can be properly (re)opened and\n# appended to by config.status.  When coming back to configure, we\n# need to make the FD available again.\nif test \"$no_create\" != yes; then\n  ac_cs_success=:\n  ac_config_status_args=\n  test \"$silent\" = yes &&\n    ac_config_status_args=\"$ac_config_status_args --quiet\"\n  exec 5>/dev/null\n  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false\n  exec 5>>config.log\n  # Use ||, not &&, to avoid exiting from the if with $? = 1, which\n  # would make configure fail if this is the last instruction.\n  $ac_cs_success || as_fn_exit 1\nfi\nif test -n \"$ac_unrecognized_opts\" && test \"$enable_option_checking\" != no; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts\" >&5\n$as_echo \"$as_me: WARNING: unrecognized options: $ac_unrecognized_opts\" >&2;}\nfi\n\n"
  },
  {
    "path": "src/vendor/libbacktrace/configure.ac",
    "content": "# configure.ac -- Backtrace configure script.\n# Copyright (C) 2012-2024 Free Software Foundation, Inc.\n\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions are\n# met:\n\n#     (1) Redistributions of source code must retain the above copyright\n#     notice, this list of conditions and the following disclaimer.\n\n#     (2) Redistributions in binary form must reproduce the above copyright\n#     notice, this list of conditions and the following disclaimer in\n#     the documentation and/or other materials provided with the\n#     distribution.\n\n#     (3) The name of the author may not be used to\n#     endorse or promote products derived from this software without\n#     specific prior written permission.\n\n# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n# DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,\n# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\n# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n# POSSIBILITY OF SUCH DAMAGE.\n\nAC_PREREQ(2.69)\nAC_INIT(package-unused, version-unused,, libbacktrace)\nAC_CONFIG_SRCDIR(backtrace.h)\nAC_CONFIG_HEADER(config.h)\nAC_CONFIG_MACRO_DIR(config)\n\n# with_target_subdir is used when configured as part of a GCC tree.\nif test -n \"${with_target_subdir}\"; then\n  AM_ENABLE_MULTILIB(, ..)\nfi\n\nAC_CANONICAL_SYSTEM\ntarget_alias=${target_alias-$host_alias}\n\nAC_USE_SYSTEM_EXTENSIONS\n\n# Default to not building a shared library.\nAC_DISABLE_SHARED\n\nlibtool_VERSION=1:0:0\nAC_SUBST(libtool_VERSION)\n\n# 1.11.1: Require that version of automake.\n# foreign: Don't require README, INSTALL, NEWS, etc.\n# no-define: Don't define PACKAGE and VERSION.\n# no-dependencies: Don't generate automatic dependencies.\n#    (because it breaks when using bootstrap-lean, since some of the\n#    headers are gone at \"make install\" time).\n# -Wall: Issue all automake warnings.\n# -Wno-portability: Don't warn about constructs supported by GNU make.\n#    (because GCC requires GNU make anyhow).\nAM_INIT_AUTOMAKE([1.11.1 foreign no-dist no-define no-dependencies -Wall -Wno-portability])\n\nAM_MAINTAINER_MODE\n\nAC_ARG_WITH(target-subdir,\n[  --with-target-subdir=SUBDIR      Configuring in a subdirectory for target])\n\n# We must force CC to /not/ be precious variables; otherwise\n# the wrong, non-multilib-adjusted value will be used in multilibs.\n# As a side effect, we have to subst CFLAGS ourselves.\nm4_rename([_AC_ARG_VAR_PRECIOUS],[backtrace_PRECIOUS])\nm4_define([_AC_ARG_VAR_PRECIOUS],[])\nAC_PROG_CC\nm4_rename_force([backtrace_PRECIOUS],[_AC_ARG_VAR_PRECIOUS])\n\nAC_SUBST(CFLAGS)\n\nAC_PROG_RANLIB\n\nAC_PROG_AWK\ncase \"$AWK\" in\n\"\") AC_MSG_ERROR([can't build without awk]) ;;\nesac\n\nAC_CHECK_PROG(DWZ, dwz, dwz)\nAM_CONDITIONAL(HAVE_DWZ, test \"$DWZ\" != \"\")\n\nLT_INIT\nAM_PROG_LIBTOOL\n\nAM_CONDITIONAL([ENABLE_DARWIN_AT_RPATH], [test x$enable_darwin_at_rpath = xyes])\n\nAC_SYS_LARGEFILE\n\nbacktrace_supported=yes\n\nif test -n \"${with_target_subdir}\"; then\n  # We are compiling a GCC library.  We can assume that the unwind\n  # library exists.\n  BACKTRACE_FILE=\"backtrace.lo simple.lo\"\nelse\n  AC_CHECK_HEADER([unwind.h],\n    [AC_CHECK_FUNC([_Unwind_Backtrace],\n\t           [BACKTRACE_FILE=\"backtrace.lo simple.lo\"],\n\t\t   [BACKTRACE_FILE=\"nounwind.lo\"\n                    backtrace_supported=no])],\n    [BACKTRACE_FILE=\"nounwind.lo\"\n     backtrace_supported=no])\nfi\nAC_SUBST(BACKTRACE_FILE)\n\nEXTRA_FLAGS=\nif test -n \"${with_target_subdir}\"; then\n  EXTRA_FLAGS=\"-funwind-tables -frandom-seed=\\$@\"\nelse\n  AC_CACHE_CHECK([for -funwind-tables option],\n    [libbacktrace_cv_c_unwind_tables],\n    [CFLAGS_hold=\"$CFLAGS\"\n     CFLAGS=\"$CFLAGS -funwind-tables\"\n     AC_COMPILE_IFELSE(\n       [AC_LANG_PROGRAM([static int f() { return 0; }], [return f();])],\n       [libbacktrace_cv_c_unwind_tables=yes],\n       [libbacktrace_cv_c_unwind_tables=no])\n     CFLAGS=\"$CFLAGS_hold\"])\n  if test \"$libbacktrace_cv_c_unwind_tables\" = \"yes\"; then\n    EXTRA_FLAGS=-funwind-tables\n  fi\n  AC_CACHE_CHECK([for -frandom-seed=string option],\n    [libbacktrace_cv_c_random_seed_string],\n    [CFLAGS_hold=\"$CFLAGS\"\n     CFLAGS=\"$CFLAGS -frandom-seed=conftest.lo\"\n     AC_COMPILE_IFELSE(\n       [AC_LANG_PROGRAM([], [return 0;])],\n       [libbacktrace_cv_c_random_seed_string=yes],\n       [libbacktrace_cv_c_random_seed_string=no])\n     CFLAGS=\"$CFLAGS_hold\"])\n  if test \"$libbacktrace_cv_c_random_seed_string\" = \"yes\"; then\n    EXTRA_FLAGS=\"$EXTRA_FLAGS -frandom-seed=\\$@\"\n  fi\nfi\nAC_SUBST(EXTRA_FLAGS)\n\nACX_PROG_CC_WARNING_OPTS([-W -Wall -Wwrite-strings -Wstrict-prototypes \\\n\t\t\t  -Wmissing-prototypes -Wold-style-definition \\\n\t\t\t  -Wmissing-format-attribute -Wcast-qual \\\n\t\t\t  -Wno-attributes -Wno-unknown-attributes],\n\t\t\t  [WARN_FLAGS])\n\nAC_ARG_ENABLE([werror],\n  [AS_HELP_STRING([--disable-werror], [disable building with -Werror])])\nAS_IF([test \"x$enable_werror\" != \"xno\" && test -n \"${with_target_subdir}\"],\n  [WARN_FLAGS=\"$WARN_FLAGS -Werror\"])\n\nAC_SUBST(WARN_FLAGS)\n\nif test -n \"${with_target_subdir}\"; then\n  GCC_CHECK_UNWIND_GETIPINFO\nelse\n  ac_save_CFFLAGS=\"$CFLAGS\"\n  CFLAGS=\"$CFLAGS -Werror-implicit-function-declaration\"\n  AC_MSG_CHECKING([for _Unwind_GetIPInfo])\n  AC_LINK_IFELSE(\n    [AC_LANG_PROGRAM(\n       [#include \"unwind.h\"\n\tstruct _Unwind_Context *context;\n\tint ip_before_insn = 0;],\n\t[return _Unwind_GetIPInfo (context, &ip_before_insn);])],\n\t[have_unwind_getipinfo=yes], [have_unwind_getipinfo=no])\n  CFLAGS=\"$ac_save_CFLAGS\"\n  AC_MSG_RESULT([$have_unwind_getipinfo])\n  if test \"$have_unwind_getipinfo\" = \"yes\"; then\n    AC_DEFINE(HAVE_GETIPINFO, 1, [Define if _Unwind_GetIPInfo is available.])\n  fi\nfi\n\n# Enable --enable-host-shared.\nAC_ARG_ENABLE(host-shared,\n[AS_HELP_STRING([--enable-host-shared],\n\t\t[build host code as shared libraries])],\n[PIC_FLAG=-fPIC], [PIC_FLAG=])\nAC_SUBST(PIC_FLAG)\n\n# Test for __sync support.\nAC_CACHE_CHECK([__sync extensions],\n[libbacktrace_cv_sys_sync],\n[if test -n \"${with_target_subdir}\"; then\n   case \"${host}\" in\n   hppa*-*-hpux*) libbacktrace_cv_sys_sync=no ;;\n   *) libbacktrace_cv_sys_sync=yes ;;\n   esac\n else\n   AC_LINK_IFELSE(\n     [AC_LANG_PROGRAM([int i;],\n                      [__sync_bool_compare_and_swap (&i, i, i);\n                       __sync_lock_test_and_set (&i, 1);\n                       __sync_lock_release (&i);])],\n     [libbacktrace_cv_sys_sync=yes],\n     [libbacktrace_cv_sys_sync=no])\n fi])\nBACKTRACE_SUPPORTS_THREADS=0\nif test \"$libbacktrace_cv_sys_sync\" = \"yes\"; then\n  BACKTRACE_SUPPORTS_THREADS=1\n  AC_DEFINE([HAVE_SYNC_FUNCTIONS], 1,\n\t    [Define to 1 if you have the __sync functions])\nfi\nAC_SUBST(BACKTRACE_SUPPORTS_THREADS)\n\n# Test for __atomic support.\nAC_CACHE_CHECK([__atomic extensions],\n[libbacktrace_cv_sys_atomic],\n[if test -n \"${with_target_subdir}\"; then\n   libbacktrace_cv_sys_atomic=yes\n else\n   AC_LINK_IFELSE(\n     [AC_LANG_PROGRAM([int i;],\n     \t\t      [__atomic_load_n (&i, __ATOMIC_ACQUIRE);\n\t\t       __atomic_store_n (&i, 1, __ATOMIC_RELEASE);])],\n     [libbacktrace_cv_sys_atomic=yes],\n     [libbacktrace_cv_sys_atomic=no])\n fi])\nif test \"$libbacktrace_cv_sys_atomic\" = \"yes\"; then\n  AC_DEFINE([HAVE_ATOMIC_FUNCTIONS], 1,\n\t    [Define to 1 if you have the __atomic functions])\nfi\n\n# The library needs to be able to read the executable itself.  Compile\n# a file to determine the executable format.  The awk script\n# filetype.awk prints out the file type.\nAC_CACHE_CHECK([output filetype],\n[libbacktrace_cv_sys_filetype],\n[filetype=\nAC_COMPILE_IFELSE(\n  [AC_LANG_PROGRAM([int i;], [int j;])],\n  [filetype=`${AWK} -f $srcdir/filetype.awk conftest.$ac_objext`],\n  [AC_MSG_FAILURE([compiler failed])])\nlibbacktrace_cv_sys_filetype=$filetype])\n\n# Match the file type to decide what files to compile.\nFORMAT_FILE=\nbacktrace_supports_data=yes\ncase \"$libbacktrace_cv_sys_filetype\" in\nelf*) FORMAT_FILE=\"elf.lo\" ;;\nmacho) FORMAT_FILE=\"macho.lo\" ;;\npecoff) FORMAT_FILE=\"pecoff.lo\"\n        backtrace_supports_data=no\n\t;;\nxcoff*) FORMAT_FILE=\"xcoff.lo\"\n        backtrace_supports_data=no\n        ;;\n*) AC_MSG_WARN([could not determine output file type])\n   FORMAT_FILE=\"unknown.lo\"\n   backtrace_supported=no\n   ;;\nesac\nAC_SUBST(FORMAT_FILE)\n\n# ELF defines.\nelfsize=\ncase \"$libbacktrace_cv_sys_filetype\" in\nelf32) elfsize=32 ;;\nelf64) elfsize=64 ;;\n*)     elfsize=unused\nesac\nAC_DEFINE_UNQUOTED([BACKTRACE_ELF_SIZE], [$elfsize], [ELF size: 32 or 64])\nAM_CONDITIONAL(HAVE_ELF, test \"$FORMAT_FILE\" = \"elf.lo\")\n\n# XCOFF defines.\nxcoffsize=\ncase \"$libbacktrace_cv_sys_filetype\" in\nxcoff32) xcoffsize=32 ;;\nxcoff64) xcoffsize=64 ;;\n*)       xcoffsize=unused\nesac\nAC_DEFINE_UNQUOTED([BACKTRACE_XCOFF_SIZE], [$xcoffsize], [XCOFF size: 32 or 64])\n\nBACKTRACE_SUPPORTED=0\nif test \"$backtrace_supported\" = \"yes\"; then\n  BACKTRACE_SUPPORTED=1\nfi\nAC_SUBST(BACKTRACE_SUPPORTED)\n\nBACKTRACE_SUPPORTS_DATA=0\nif test \"$backtrace_supports_data\" = \"yes\"; then\n  BACKTRACE_SUPPORTS_DATA=1\nfi\nAC_SUBST(BACKTRACE_SUPPORTS_DATA)\n\nAC_CHECK_HEADERS(sys/mman.h)\nif test \"$ac_cv_header_sys_mman_h\" = \"no\"; then\n  have_mmap=no\nelse\n  if test -n \"${with_target_subdir}\"; then\n    # When built as a GCC target library, we can't do a link test.  We\n    # simply assume that if we have mman.h, we have mmap.\n    have_mmap=yes\n    case \"${host}\" in\n    spu-*-*|*-*-msdosdjgpp)\n        # The SPU does not have mmap, but it has a sys/mman.h header file\n        # containing \"mmap_eaddr\" and the mmap flags, confusing the test.\n        # DJGPP also has sys/man.h, but no mmap\n\thave_mmap=no ;;\n    esac\n  else\n    AC_CHECK_FUNC(mmap, [have_mmap=yes], [have_mmap=no])\n  fi\nfi\nif test \"$have_mmap\" = \"no\"; then\n  VIEW_FILE=read.lo\n  ALLOC_FILE=alloc.lo\nelse\n  VIEW_FILE=mmapio.lo\n  AC_PREPROC_IFELSE([AC_LANG_SOURCE([\n#include <sys/mman.h>\n#if !defined(MAP_ANONYMOUS) && !defined(MAP_ANON)\n  #error no MAP_ANONYMOUS\n#endif\n])], [ALLOC_FILE=mmap.lo], [ALLOC_FILE=alloc.lo])\nfi\nAC_SUBST(VIEW_FILE)\nAC_SUBST(ALLOC_FILE)\n\nBACKTRACE_USES_MALLOC=0\nif test \"$ALLOC_FILE\" = \"alloc.lo\"; then\n  BACKTRACE_USES_MALLOC=1\nfi\nAC_SUBST(BACKTRACE_USES_MALLOC)\n\n# Check for dl_iterate_phdr.\nAC_CHECK_HEADERS(link.h sys/link.h)\nif test \"$ac_cv_header_link_h\" = \"no\" -a \"$ac_cv_header_sys_link_h\" = \"no\"; then\n  have_dl_iterate_phdr=no\nelse\n  if test -n \"${with_target_subdir}\"; then\n    link_h=link.h\n    if test \"$ac_cv_header_link_h\" = \"no\"; then\n       link_h=sys/link.h\n    fi\n    # When built as a GCC target library, we can't do a link test.\n    AC_EGREP_HEADER([dl_iterate_phdr], [$link_h], [have_dl_iterate_phdr=yes],\n\t\t    [have_dl_iterate_phdr=no])\n    case \"${host}\" in\n    *-*-solaris2.10*)\n        # Avoid dl_iterate_phdr on Solaris 10, where it is in the\n    \t# header file but is only in -ldl.\n\thave_dl_iterate_phdr=no ;;\n    esac\n  else\n    AC_CHECK_FUNC([dl_iterate_phdr], [have_dl_iterate_phdr=yes],\n\t\t  [have_dl_iterate_phdr=no])\n  fi\nfi\nif test \"$have_dl_iterate_phdr\" = \"yes\"; then\n  AC_DEFINE(HAVE_DL_ITERATE_PHDR, 1, [Define if dl_iterate_phdr is available.])\nfi\n\n# Check for header file for Mach-O image functions.\nAC_CHECK_HEADERS(mach-o/dyld.h)\n\n# Check for loadquery.\nAC_CHECK_HEADERS(sys/ldr.h)\nif test \"$ac_cv_header_sys_ldr_h\" = \"no\"; then\n  have_loadquery=no\nelse\n  if test -n \"${with_target_subdir}\"; then\n    # When built as a GCC target library, we can't do a link test.\n    AC_EGREP_HEADER([loadquery], [sys/ldr.h], [have_loadquery=yes],\n\t\t    [have_loadquery=no])\n  else\n    AC_CHECK_FUNC([loadquery], [have_loadquery=yes],\n\t\t  [have_loadquery=no])\n  fi\nfi\nif test \"$have_loadquery\" = \"yes\"; then\n  AC_DEFINE(HAVE_LOADQUERY, 1, [Define if AIX loadquery is available.])\nfi\n\nAC_CHECK_HEADERS(windows.h)\nAC_CHECK_HEADERS(tlhelp32.h, [], [],\n[#ifdef HAVE_WINDOWS_H\n#  include <windows.h>\n#endif])\n\n# Check for the fcntl function.\nif test -n \"${with_target_subdir}\"; then\n   case \"${host}\" in\n   *-*-mingw*) have_fcntl=no ;;\n   spu-*-*) have_fcntl=no ;;\n   *) have_fcntl=yes ;;\n   esac\nelse\n  AC_CHECK_FUNC(fcntl, [have_fcntl=yes], [have_fcntl=no])\nfi\nif test \"$have_fcntl\" = \"yes\"; then\n  AC_DEFINE([HAVE_FCNTL], 1,\n\t    [Define to 1 if you have the fcntl function])\nfi\n\nAC_CHECK_DECLS([strnlen, getpagesize])\nAC_CHECK_FUNCS(lstat readlink)\n\n# Check for getexecname function.\nif test -n \"${with_target_subdir}\"; then\n   case \"${host}\" in\n   *-*-solaris2*) have_getexecname=yes ;;\n   *) have_getexecname=no ;;\n   esac\nelse\n  AC_CHECK_FUNC(getexecname, [have_getexecname=yes], [have_getexecname=no])\nfi\nif test \"$have_getexecname\" = \"yes\"; then\n  AC_DEFINE(HAVE_GETEXECNAME, 1, [Define if getexecname is available.])\nfi\n\n# Check for _pgmptr variable, contains the executable filename on windows\nAC_CHECK_DECLS([_pgmptr])\n\n# Check for sysctl definitions.\n\nAC_CACHE_CHECK([for KERN_PROC],\n[libbacktrace_cv_proc],\n[AC_COMPILE_IFELSE(\n  [AC_LANG_PROGRAM([\n#include <sys/types.h>\n#include <sys/sysctl.h>\n], [int mib0 = CTL_KERN; int mib1 = KERN_PROC; int mib2 = KERN_PROC_PATHNAME;])],\n  [libbacktrace_cv_proc=yes],\n  [libbacktrace_cv_proc=no])])\nif test \"$libbacktrace_cv_proc\" = \"yes\"; then\n  AC_DEFINE([HAVE_KERN_PROC], 1,\n            [Define to 1 if you have KERN_PROC and KERN_PROC_PATHNAME in <sys/sysctl.h>.])\nfi\n\nAC_CACHE_CHECK([for KERN_PROG_ARGS],\n[libbacktrace_cv_procargs],\n[AC_COMPILE_IFELSE(\n  [AC_LANG_PROGRAM([\n#include <sys/types.h>\n#include <sys/sysctl.h>\n], [int mib0 = CTL_KERN; int mib1 = KERN_PROC_ARGS; int mib2 = KERN_PROC_PATHNAME;])],\n  [libbacktrace_cv_procargs=yes],\n  [libbacktrace_cv_procargs=no])])\nif test \"$libbacktrace_cv_procargs\" = \"yes\"; then\n  AC_DEFINE([HAVE_KERN_PROC_ARGS], 1,\n            [Define to 1 if you have KERN_PROCARGS and KERN_PROC_PATHNAME in <sys/sysctl.h>.])\nfi\n\n# Check for the clock_gettime function.\nAC_CHECK_FUNCS(clock_gettime)\nclock_gettime_link=\n# At least for glibc, clock_gettime is in librt.  But don't\n# pull that in if it still doesn't give us the function we want.  This\n# test is copied from libgomp, and modified to not link in -lrt as\n# we're using this for test timing only.\nif test \"$ac_cv_func_clock_gettime\" = no; then\n  AC_CHECK_LIB(rt, clock_gettime,\n    [CLOCK_GETTIME_LINK=-lrt\n     AC_DEFINE(HAVE_CLOCK_GETTIME, 1,\n\t       [Define to 1 if you have the `clock_gettime' function.])])\nfi\nAC_SUBST(CLOCK_GETTIME_LINK)\n\ndnl Test whether the compiler supports the -pthread option.\nAC_CACHE_CHECK([whether -pthread is supported],\n[libgo_cv_lib_pthread],\n[CFLAGS_hold=$CFLAGS\nCFLAGS=\"$CFLAGS -pthread\"\nAC_COMPILE_IFELSE([AC_LANG_SOURCE([int i;])],\n[libgo_cv_lib_pthread=yes],\n[libgo_cv_lib_pthread=no])\nCFLAGS=$CFLAGS_hold])\nPTHREAD_CFLAGS=\nif test \"$libgo_cv_lib_pthread\" = yes; then\n  PTHREAD_CFLAGS=-pthread\nfi\nAC_SUBST(PTHREAD_CFLAGS)\n\nAM_CONDITIONAL(HAVE_PTHREAD, test \"$libgo_cv_lib_pthread\" = yes)\n\ndnl Test whether the compiler and the linker support the -gdwarf-5 option.\nAC_CACHE_CHECK([whether -gdwarf-5 is supported],\n[libbacktrace_cv_lib_dwarf5],\n[CFLAGS_hold=$CFLAGS\nCFLAGS=\"$CFLAGS -gdwarf-5\"\nAC_LINK_IFELSE([AC_LANG_PROGRAM([int i;], [return 0;])],\n[libbacktrace_cv_lib_dwarf5=yes],\n[libbacktrace_cv_lib_dwarf5=no])\nCFLAGS=$CFLAGS_hold])\nAM_CONDITIONAL(HAVE_DWARF5, test \"$libbacktrace_cv_lib_dwarf5\" = yes)\n\nAC_CHECK_LIB([z], [compress],\n    [AC_DEFINE(HAVE_ZLIB, 1, [Define if -lz is available.])])\nAM_CONDITIONAL(HAVE_ZLIB, test \"$ac_cv_lib_z_compress\" = yes)\n\ndnl Test whether the linker supports the --build-id option.\nAC_CACHE_CHECK([whether --build-id is supported],\n[libbacktrace_cv_ld_buildid],\n[LDFLAGS_hold=$LDFLAGS\nLDFLAGS=\"$LDFLAGS -Wl,--build-id\"\nAC_LINK_IFELSE([AC_LANG_PROGRAM(,)],\n[libbacktrace_cv_ld_buildid=yes],\n[libbacktrace_cv_ld_buildid=no])\nLDFLAGS=$LDFLAGS_hold])\nAM_CONDITIONAL(HAVE_BUILDID, test \"$libbacktrace_cv_ld_buildid\" = yes)\n\ndnl Test whether the linker supports the --compress-debug-sections=zlib-gnu\ndnl option.\nAC_CACHE_CHECK([whether --compress-debug-sections=zlib-gnu is supported],\n[libgo_cv_ld_compress_zlib_gnu],\n[LDFLAGS_hold=$LDFLAGS\nLDFLAGS=\"$LDFLAGS -Wl,--compress-debug-sections=zlib-gnu\"\nAC_LINK_IFELSE([AC_LANG_PROGRAM(,)],\n[libgo_cv_ld_compress_zlib_gnu=yes],\n[libgo_cv_ld_compress_zlib_gnu=no])\nLDFLAGS=$LDFLAGS_hold])\nAM_CONDITIONAL(HAVE_COMPRESSED_DEBUG_ZLIB_GNU, test \"$libgo_cv_ld_compress_zlib_gnu\" = yes)\n\nAC_CACHE_CHECK([whether --compress-debug-sections=zlib-gabi is supported],\n[libgo_cv_ld_compress_zlib_gabi],\n[LDFLAGS_hold=$LDFLAGS\nLDFLAGS=\"$LDFLAGS -Wl,--compress-debug-sections=zlib-gabi\"\nAC_LINK_IFELSE([AC_LANG_PROGRAM(,)],\n[libgo_cv_ld_compress_zlib_gabi=yes],\n[libgo_cv_ld_compress_zlib_gabi=no])\nLDFLAGS=$LDFLAGS_hold])\nAM_CONDITIONAL(HAVE_COMPRESSED_DEBUG_ZLIB_GABI, test \"$libgo_cv_ld_compress_zlib_gabi\" = yes)\n\nAC_CHECK_LIB([zstd], [ZSTD_compress],\n    [AC_DEFINE(HAVE_ZSTD, 1, [Define if -lzstd is available.])])\nAM_CONDITIONAL(HAVE_ZSTD, test \"$ac_cv_lib_zstd_ZSTD_compress\" = yes)\n\ndnl Test whether the linker supports --compress-debug-sections=zstd option.\nAC_CACHE_CHECK([whether --compress-debug-sections=zstd is supported],\n[libgo_cv_ld_compress_zstd],\n[LDFLAGS_hold=$LDFLAGS\nLDFLAGS=\"$LDFLAGS -Wl,--compress-debug-sections=zstd\"\nAC_LINK_IFELSE([AC_LANG_PROGRAM(,)],\n[libgo_cv_ld_compress_zstd=yes],\n[libgo_cv_ld_compress_zstd=no])\nLDFLAGS=$LDFLAGS_hold])\nAM_CONDITIONAL(HAVE_COMPRESSED_DEBUG_ZSTD, test \"$libgo_cv_ld_compress_zstd\" = yes)\n\nAC_ARG_VAR(OBJCOPY, [location of objcopy])\nAC_CHECK_PROG(OBJCOPY, objcopy, objcopy,)\nAC_CHECK_PROG(READELF, readelf, readelf)\nAC_CACHE_CHECK([whether objcopy supports debuglink],\n[libbacktrace_cv_objcopy_debuglink],\n[if test -n \"${with_target_subdir}\"; then\n  libbacktrace_cv_objcopy_debuglink=no\nelif ! test -n \"${OBJCOPY}\"; then\n  libbacktrace_cv_objcopy_debuglink=no\nelif ${OBJCOPY} --help | grep add-gnu-debuglink >/dev/null 2>&1; then\n  libbacktrace_cv_objcopy_debuglink=yes\nelse\n  libbacktrace_cv_objcopy_debuglink=no\nfi])\nAM_CONDITIONAL(HAVE_OBJCOPY_DEBUGLINK, test \"$libbacktrace_cv_objcopy_debuglink\" = yes)\n\nAC_ARG_VAR(DSYMUTIL, [location of dsymutil])\nAC_CHECK_PROG(DSYMUTIL, dsymutil, dsymutil)\nAM_CONDITIONAL(USE_DSYMUTIL, test -n \"${DSYMUTIL}\" -a \"$FORMAT_FILE\" = \"macho.lo\")\n\nAC_ARG_VAR(NM, [location of nm])\nAC_CHECK_PROG(NM, nm, nm)\n\nAC_CHECK_PROG(XZ, xz, xz)\nAM_CONDITIONAL(HAVE_XZ, test \"$XZ\" != \"\")\nAC_CHECK_PROG(COMM, comm, comm)\nAM_CONDITIONAL(HAVE_COMM, test \"$COMM\" != \"\")\n\nAM_CONDITIONAL(HAVE_MINIDEBUG,\n  test \"${with_target_subdir}\" = \"\" -a \"$FORMAT_FILE\" = \"elf.lo\" -a \"${OBJCOPY}\" != \"\" -a \"${NM}\" != \"\" -a \"${XZ}\" != \"\" -a \"${COMM}\" != \"\")\n\nAC_CHECK_LIB([lzma], [lzma_auto_decoder],\n    [AC_DEFINE(HAVE_LIBLZMA, 1, [Define if -llzma is available.])])\nAM_CONDITIONAL(HAVE_LIBLZMA, test \"$ac_cv_lib_lzma_lzma_auto_decoder\" = yes)\n\nAC_CACHE_CHECK([whether tests can run],\n  [libbacktrace_cv_sys_native],\n  [AC_RUN_IFELSE([AC_LANG_PROGRAM([], [return 0;])],\n     [libbacktrace_cv_sys_native=yes],\n     [libbacktrace_cv_sys_native=no],\n     [libbacktrace_cv_sys_native=no])])\nAM_CONDITIONAL(NATIVE, test \"$libbacktrace_cv_sys_native\" = \"yes\")\n\nif test \"${multilib}\" = \"yes\"; then\n  multilib_arg=\"--enable-multilib\"\nelse\n  multilib_arg=\nfi\n\nAC_CONFIG_FILES(Makefile backtrace-supported.h)\nAC_CONFIG_FILES(install-debuginfo-for-buildid.sh, chmod +x install-debuginfo-for-buildid.sh)\n\n# We need multilib support, but only if configuring for the target.\nAC_CONFIG_COMMANDS([default],\n[if test -n \"$CONFIG_FILES\"; then\n   if test -n \"${with_target_subdir}\"; then\n     # Multilibs need MULTISUBDIR defined correctly in certain makefiles so\n     # that multilib installs will end up installed in the correct place.\n     # The testsuite needs it for multilib-aware ABI baseline files.\n     # To work around this not being passed down from config-ml.in ->\n     # srcdir/Makefile.am -> srcdir/{src,libsupc++,...}/Makefile.am, manually\n     # append it here.  Only modify Makefiles that have just been created.\n     #\n     # Also, get rid of this simulated-VPATH thing that automake does.\n     cat > vpsed << \\_EOF\n  s!`test -f '$<' || echo '$(srcdir)/'`!!\n_EOF\n     for i in $SUBDIRS; do\n      case $CONFIG_FILES in\n       *${i}/Makefile*)\n\t #echo \"Adding MULTISUBDIR to $i/Makefile\"\n\t sed -f vpsed $i/Makefile > tmp\n\t grep '^MULTISUBDIR =' Makefile >> tmp\n\t mv tmp $i/Makefile\n\t ;;\n      esac\n     done\n     rm vpsed\n   fi\n fi\n],\n[\n# Variables needed in config.status (file generation) which aren't already\n# passed by autoconf.\nSUBDIRS=\"$SUBDIRS\"\n])\n\nAC_OUTPUT\n"
  },
  {
    "path": "src/vendor/libbacktrace/debuginfod_support.h",
    "content": "/* External declarations for the libdebuginfod client library.\n   Copyright (C) 2019-2020 Red Hat, Inc.\n   This file is part of elfutils.\n\n   This file is free software; you can redistribute it and/or modify\n   it under the terms of either\n\n   * the GNU Lesser General Public License as published by the Free\n       Software Foundation; either version 3 of the License, or (at\n       your option) any later version\n\n   or\n\n   * the GNU General Public License as published by the Free\n       Software Foundation; either version 2 of the License, or (at\n       your option) any later version\n\n   or both in parallel, as here.\n\n   elfutils is distributed in the hope that it will be useful, but\n   WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   General Public License for more details.\n\n   You should have received copies of the GNU General Public License and\n   the GNU Lesser General Public License along with this program.  If\n   not, see <http://www.gnu.org/licenses/>.  */\n\n#ifndef _DEBUGINFOD_CLIENT_H\n#define _DEBUGINFOD_CLIENT_H 1\n\n/* Names of environment variables that control the client logic. */\n#define DEBUGINFOD_URLS_ENV_VAR \"DEBUGINFOD_URLS\"\n#define DEBUGINFOD_CACHE_PATH_ENV_VAR \"DEBUGINFOD_CACHE_PATH\"\n#define DEBUGINFOD_TIMEOUT_ENV_VAR \"DEBUGINFOD_TIMEOUT\"\n#define DEBUGINFOD_PROGRESS_ENV_VAR \"DEBUGINFOD_PROGRESS\"\n#define DEBUGINFOD_VERBOSE_ENV_VAR \"DEBUGINFOD_VERBOSE\"\n#define DEBUGINFOD_RETRY_LIMIT_ENV_VAR \"DEBUGINFOD_RETRY_LIMIT\"\n#define DEBUGINFOD_MAXSIZE_ENV_VAR \"DEBUGINFOD_MAXSIZE\"\n#define DEBUGINFOD_MAXTIME_ENV_VAR \"DEBUGINFOD_MAXTIME\"\n#define DEBUGINFOD_HEADERS_FILE_ENV_VAR \"DEBUGINFOD_HEADERS_FILE\"\n\n/* Handle for debuginfod-client connection.  */\ntypedef struct debuginfod_client debuginfod_client;\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* Create a handle for a new debuginfod-client session.  */\ndebuginfod_client *debuginfod_begin (void);\n\n/* Query the urls contained in $DEBUGINFOD_URLS for a file with\n   the specified type and build id.  If build_id_len == 0, the\n   build_id is supplied as a lowercase hexadecimal string; otherwise\n   it is a binary blob of given length.\n\n   If successful, return a file descriptor to the target, otherwise\n   return a posix error code.  If successful, set *path to a\n   strdup'd copy of the name of the same file in the cache.\n   Caller must free() it later. */\n\nint debuginfod_find_debuginfo (debuginfod_client *client,\n\t\t\t       const unsigned char *build_id,\n                               int build_id_len,\n                               char **path);\n\nint debuginfod_find_executable (debuginfod_client *client,\n\t\t\t\tconst unsigned char *build_id,\n                                int build_id_len,\n                                char **path);\n\nint debuginfod_find_source (debuginfod_client *client,\n\t\t\t    const unsigned char *build_id,\n                            int build_id_len,\n                            const char *filename,\n                            char **path);\n\nint debuginfod_find_section (debuginfod_client *client,\n\t\t\t     const unsigned char *build_id,\n\t\t\t     int build_id_len,\n\t\t\t     const char *section,\n\t\t\t     char **path);\n\ntypedef int (*debuginfod_progressfn_t)(debuginfod_client *c, long a, long b);\nvoid debuginfod_set_progressfn(debuginfod_client *c,\n\t\t\t       debuginfod_progressfn_t fn);\n\nvoid debuginfod_set_verbose_fd(debuginfod_client *c, int fd);\n\n/* Set the user parameter.  */\nvoid debuginfod_set_user_data (debuginfod_client *client, void *value);\n\n/* Get the user parameter.  */\nvoid* debuginfod_get_user_data (debuginfod_client *client);\n\n/* Get the current or last active URL, if known.  */\nconst char* debuginfod_get_url (debuginfod_client *client);\n\n/* Returns set of x-debuginfod* header lines received from current or\n   last active transfer, \\n separated, if known. */\nconst char* debuginfod_get_headers(debuginfod_client *client);\n\n/* Add an outgoing HTTP request  \"Header: Value\".  Copies string.  */\nint debuginfod_add_http_header (debuginfod_client *client, const char* header);\n\n/* Release debuginfod client connection context handle.  */\nvoid debuginfod_end (debuginfod_client *client);\n\n#ifdef __cplusplus\n}\n#endif\n\n\n#endif /* _DEBUGINFOD_CLIENT_H */\n"
  },
  {
    "path": "src/vendor/libbacktrace/dwarf.c",
    "content": "/* dwarf.c -- Get file/line information from DWARF for backtraces.\n   Copyright (C) 2012-2024 Free Software Foundation, Inc.\n   Written by Ian Lance Taylor, Google.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n    (1) Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n\n    (2) Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in\n    the documentation and/or other materials provided with the\n    distribution.\n\n    (3) The name of the author may not be used to\n    endorse or promote products derived from this software without\n    specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\nIMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,\nINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\nHOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\nIN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGE.  */\n\n#include \"config.h\"\n\n#include <errno.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/types.h>\n\n#include \"filenames.h\"\n\n#include \"backtrace.h\"\n#include \"internal.h\"\n\n/* DWARF constants.  */\n\nenum dwarf_tag {\n  DW_TAG_entry_point = 0x3,\n  DW_TAG_compile_unit = 0x11,\n  DW_TAG_inlined_subroutine = 0x1d,\n  DW_TAG_subprogram = 0x2e,\n  DW_TAG_skeleton_unit = 0x4a,\n};\n\nenum dwarf_form {\n  DW_FORM_addr = 0x01,\n  DW_FORM_block2 = 0x03,\n  DW_FORM_block4 = 0x04,\n  DW_FORM_data2 = 0x05,\n  DW_FORM_data4 = 0x06,\n  DW_FORM_data8 = 0x07,\n  DW_FORM_string = 0x08,\n  DW_FORM_block = 0x09,\n  DW_FORM_block1 = 0x0a,\n  DW_FORM_data1 = 0x0b,\n  DW_FORM_flag = 0x0c,\n  DW_FORM_sdata = 0x0d,\n  DW_FORM_strp = 0x0e,\n  DW_FORM_udata = 0x0f,\n  DW_FORM_ref_addr = 0x10,\n  DW_FORM_ref1 = 0x11,\n  DW_FORM_ref2 = 0x12,\n  DW_FORM_ref4 = 0x13,\n  DW_FORM_ref8 = 0x14,\n  DW_FORM_ref_udata = 0x15,\n  DW_FORM_indirect = 0x16,\n  DW_FORM_sec_offset = 0x17,\n  DW_FORM_exprloc = 0x18,\n  DW_FORM_flag_present = 0x19,\n  DW_FORM_ref_sig8 = 0x20,\n  DW_FORM_strx = 0x1a,\n  DW_FORM_addrx = 0x1b,\n  DW_FORM_ref_sup4 = 0x1c,\n  DW_FORM_strp_sup = 0x1d,\n  DW_FORM_data16 = 0x1e,\n  DW_FORM_line_strp = 0x1f,\n  DW_FORM_implicit_const = 0x21,\n  DW_FORM_loclistx = 0x22,\n  DW_FORM_rnglistx = 0x23,\n  DW_FORM_ref_sup8 = 0x24,\n  DW_FORM_strx1 = 0x25,\n  DW_FORM_strx2 = 0x26,\n  DW_FORM_strx3 = 0x27,\n  DW_FORM_strx4 = 0x28,\n  DW_FORM_addrx1 = 0x29,\n  DW_FORM_addrx2 = 0x2a,\n  DW_FORM_addrx3 = 0x2b,\n  DW_FORM_addrx4 = 0x2c,\n  DW_FORM_GNU_addr_index = 0x1f01,\n  DW_FORM_GNU_str_index = 0x1f02,\n  DW_FORM_GNU_ref_alt = 0x1f20,\n  DW_FORM_GNU_strp_alt = 0x1f21\n};\n\nenum dwarf_attribute {\n  DW_AT_sibling = 0x01,\n  DW_AT_location = 0x02,\n  DW_AT_name = 0x03,\n  DW_AT_ordering = 0x09,\n  DW_AT_subscr_data = 0x0a,\n  DW_AT_byte_size = 0x0b,\n  DW_AT_bit_offset = 0x0c,\n  DW_AT_bit_size = 0x0d,\n  DW_AT_element_list = 0x0f,\n  DW_AT_stmt_list = 0x10,\n  DW_AT_low_pc = 0x11,\n  DW_AT_high_pc = 0x12,\n  DW_AT_language = 0x13,\n  DW_AT_member = 0x14,\n  DW_AT_discr = 0x15,\n  DW_AT_discr_value = 0x16,\n  DW_AT_visibility = 0x17,\n  DW_AT_import = 0x18,\n  DW_AT_string_length = 0x19,\n  DW_AT_common_reference = 0x1a,\n  DW_AT_comp_dir = 0x1b,\n  DW_AT_const_value = 0x1c,\n  DW_AT_containing_type = 0x1d,\n  DW_AT_default_value = 0x1e,\n  DW_AT_inline = 0x20,\n  DW_AT_is_optional = 0x21,\n  DW_AT_lower_bound = 0x22,\n  DW_AT_producer = 0x25,\n  DW_AT_prototyped = 0x27,\n  DW_AT_return_addr = 0x2a,\n  DW_AT_start_scope = 0x2c,\n  DW_AT_bit_stride = 0x2e,\n  DW_AT_upper_bound = 0x2f,\n  DW_AT_abstract_origin = 0x31,\n  DW_AT_accessibility = 0x32,\n  DW_AT_address_class = 0x33,\n  DW_AT_artificial = 0x34,\n  DW_AT_base_types = 0x35,\n  DW_AT_calling_convention = 0x36,\n  DW_AT_count = 0x37,\n  DW_AT_data_member_location = 0x38,\n  DW_AT_decl_column = 0x39,\n  DW_AT_decl_file = 0x3a,\n  DW_AT_decl_line = 0x3b,\n  DW_AT_declaration = 0x3c,\n  DW_AT_discr_list = 0x3d,\n  DW_AT_encoding = 0x3e,\n  DW_AT_external = 0x3f,\n  DW_AT_frame_base = 0x40,\n  DW_AT_friend = 0x41,\n  DW_AT_identifier_case = 0x42,\n  DW_AT_macro_info = 0x43,\n  DW_AT_namelist_items = 0x44,\n  DW_AT_priority = 0x45,\n  DW_AT_segment = 0x46,\n  DW_AT_specification = 0x47,\n  DW_AT_static_link = 0x48,\n  DW_AT_type = 0x49,\n  DW_AT_use_location = 0x4a,\n  DW_AT_variable_parameter = 0x4b,\n  DW_AT_virtuality = 0x4c,\n  DW_AT_vtable_elem_location = 0x4d,\n  DW_AT_allocated = 0x4e,\n  DW_AT_associated = 0x4f,\n  DW_AT_data_location = 0x50,\n  DW_AT_byte_stride = 0x51,\n  DW_AT_entry_pc = 0x52,\n  DW_AT_use_UTF8 = 0x53,\n  DW_AT_extension = 0x54,\n  DW_AT_ranges = 0x55,\n  DW_AT_trampoline = 0x56,\n  DW_AT_call_column = 0x57,\n  DW_AT_call_file = 0x58,\n  DW_AT_call_line = 0x59,\n  DW_AT_description = 0x5a,\n  DW_AT_binary_scale = 0x5b,\n  DW_AT_decimal_scale = 0x5c,\n  DW_AT_small = 0x5d,\n  DW_AT_decimal_sign = 0x5e,\n  DW_AT_digit_count = 0x5f,\n  DW_AT_picture_string = 0x60,\n  DW_AT_mutable = 0x61,\n  DW_AT_threads_scaled = 0x62,\n  DW_AT_explicit = 0x63,\n  DW_AT_object_pointer = 0x64,\n  DW_AT_endianity = 0x65,\n  DW_AT_elemental = 0x66,\n  DW_AT_pure = 0x67,\n  DW_AT_recursive = 0x68,\n  DW_AT_signature = 0x69,\n  DW_AT_main_subprogram = 0x6a,\n  DW_AT_data_bit_offset = 0x6b,\n  DW_AT_const_expr = 0x6c,\n  DW_AT_enum_class = 0x6d,\n  DW_AT_linkage_name = 0x6e,\n  DW_AT_string_length_bit_size = 0x6f,\n  DW_AT_string_length_byte_size = 0x70,\n  DW_AT_rank = 0x71,\n  DW_AT_str_offsets_base = 0x72,\n  DW_AT_addr_base = 0x73,\n  DW_AT_rnglists_base = 0x74,\n  DW_AT_dwo_name = 0x76,\n  DW_AT_reference = 0x77,\n  DW_AT_rvalue_reference = 0x78,\n  DW_AT_macros = 0x79,\n  DW_AT_call_all_calls = 0x7a,\n  DW_AT_call_all_source_calls = 0x7b,\n  DW_AT_call_all_tail_calls = 0x7c,\n  DW_AT_call_return_pc = 0x7d,\n  DW_AT_call_value = 0x7e,\n  DW_AT_call_origin = 0x7f,\n  DW_AT_call_parameter = 0x80,\n  DW_AT_call_pc = 0x81,\n  DW_AT_call_tail_call = 0x82,\n  DW_AT_call_target = 0x83,\n  DW_AT_call_target_clobbered = 0x84,\n  DW_AT_call_data_location = 0x85,\n  DW_AT_call_data_value = 0x86,\n  DW_AT_noreturn = 0x87,\n  DW_AT_alignment = 0x88,\n  DW_AT_export_symbols = 0x89,\n  DW_AT_deleted = 0x8a,\n  DW_AT_defaulted = 0x8b,\n  DW_AT_loclists_base = 0x8c,\n  DW_AT_lo_user = 0x2000,\n  DW_AT_hi_user = 0x3fff,\n  DW_AT_MIPS_fde = 0x2001,\n  DW_AT_MIPS_loop_begin = 0x2002,\n  DW_AT_MIPS_tail_loop_begin = 0x2003,\n  DW_AT_MIPS_epilog_begin = 0x2004,\n  DW_AT_MIPS_loop_unroll_factor = 0x2005,\n  DW_AT_MIPS_software_pipeline_depth = 0x2006,\n  DW_AT_MIPS_linkage_name = 0x2007,\n  DW_AT_MIPS_stride = 0x2008,\n  DW_AT_MIPS_abstract_name = 0x2009,\n  DW_AT_MIPS_clone_origin = 0x200a,\n  DW_AT_MIPS_has_inlines = 0x200b,\n  DW_AT_HP_block_index = 0x2000,\n  DW_AT_HP_unmodifiable = 0x2001,\n  DW_AT_HP_prologue = 0x2005,\n  DW_AT_HP_epilogue = 0x2008,\n  DW_AT_HP_actuals_stmt_list = 0x2010,\n  DW_AT_HP_proc_per_section = 0x2011,\n  DW_AT_HP_raw_data_ptr = 0x2012,\n  DW_AT_HP_pass_by_reference = 0x2013,\n  DW_AT_HP_opt_level = 0x2014,\n  DW_AT_HP_prof_version_id = 0x2015,\n  DW_AT_HP_opt_flags = 0x2016,\n  DW_AT_HP_cold_region_low_pc = 0x2017,\n  DW_AT_HP_cold_region_high_pc = 0x2018,\n  DW_AT_HP_all_variables_modifiable = 0x2019,\n  DW_AT_HP_linkage_name = 0x201a,\n  DW_AT_HP_prof_flags = 0x201b,\n  DW_AT_HP_unit_name = 0x201f,\n  DW_AT_HP_unit_size = 0x2020,\n  DW_AT_HP_widened_byte_size = 0x2021,\n  DW_AT_HP_definition_points = 0x2022,\n  DW_AT_HP_default_location = 0x2023,\n  DW_AT_HP_is_result_param = 0x2029,\n  DW_AT_sf_names = 0x2101,\n  DW_AT_src_info = 0x2102,\n  DW_AT_mac_info = 0x2103,\n  DW_AT_src_coords = 0x2104,\n  DW_AT_body_begin = 0x2105,\n  DW_AT_body_end = 0x2106,\n  DW_AT_GNU_vector = 0x2107,\n  DW_AT_GNU_guarded_by = 0x2108,\n  DW_AT_GNU_pt_guarded_by = 0x2109,\n  DW_AT_GNU_guarded = 0x210a,\n  DW_AT_GNU_pt_guarded = 0x210b,\n  DW_AT_GNU_locks_excluded = 0x210c,\n  DW_AT_GNU_exclusive_locks_required = 0x210d,\n  DW_AT_GNU_shared_locks_required = 0x210e,\n  DW_AT_GNU_odr_signature = 0x210f,\n  DW_AT_GNU_template_name = 0x2110,\n  DW_AT_GNU_call_site_value = 0x2111,\n  DW_AT_GNU_call_site_data_value = 0x2112,\n  DW_AT_GNU_call_site_target = 0x2113,\n  DW_AT_GNU_call_site_target_clobbered = 0x2114,\n  DW_AT_GNU_tail_call = 0x2115,\n  DW_AT_GNU_all_tail_call_sites = 0x2116,\n  DW_AT_GNU_all_call_sites = 0x2117,\n  DW_AT_GNU_all_source_call_sites = 0x2118,\n  DW_AT_GNU_macros = 0x2119,\n  DW_AT_GNU_deleted = 0x211a,\n  DW_AT_GNU_dwo_name = 0x2130,\n  DW_AT_GNU_dwo_id = 0x2131,\n  DW_AT_GNU_ranges_base = 0x2132,\n  DW_AT_GNU_addr_base = 0x2133,\n  DW_AT_GNU_pubnames = 0x2134,\n  DW_AT_GNU_pubtypes = 0x2135,\n  DW_AT_GNU_discriminator = 0x2136,\n  DW_AT_GNU_locviews = 0x2137,\n  DW_AT_GNU_entry_view = 0x2138,\n  DW_AT_VMS_rtnbeg_pd_address = 0x2201,\n  DW_AT_use_GNAT_descriptive_type = 0x2301,\n  DW_AT_GNAT_descriptive_type = 0x2302,\n  DW_AT_GNU_numerator = 0x2303,\n  DW_AT_GNU_denominator = 0x2304,\n  DW_AT_GNU_bias = 0x2305,\n  DW_AT_upc_threads_scaled = 0x3210,\n  DW_AT_PGI_lbase = 0x3a00,\n  DW_AT_PGI_soffset = 0x3a01,\n  DW_AT_PGI_lstride = 0x3a02,\n  DW_AT_APPLE_optimized = 0x3fe1,\n  DW_AT_APPLE_flags = 0x3fe2,\n  DW_AT_APPLE_isa = 0x3fe3,\n  DW_AT_APPLE_block = 0x3fe4,\n  DW_AT_APPLE_major_runtime_vers = 0x3fe5,\n  DW_AT_APPLE_runtime_class = 0x3fe6,\n  DW_AT_APPLE_omit_frame_ptr = 0x3fe7,\n  DW_AT_APPLE_property_name = 0x3fe8,\n  DW_AT_APPLE_property_getter = 0x3fe9,\n  DW_AT_APPLE_property_setter = 0x3fea,\n  DW_AT_APPLE_property_attribute = 0x3feb,\n  DW_AT_APPLE_objc_complete_type = 0x3fec,\n  DW_AT_APPLE_property = 0x3fed\n};\n\nenum dwarf_line_number_op {\n  DW_LNS_extended_op = 0x0,\n  DW_LNS_copy = 0x1,\n  DW_LNS_advance_pc = 0x2,\n  DW_LNS_advance_line = 0x3,\n  DW_LNS_set_file = 0x4,\n  DW_LNS_set_column = 0x5,\n  DW_LNS_negate_stmt = 0x6,\n  DW_LNS_set_basic_block = 0x7,\n  DW_LNS_const_add_pc = 0x8,\n  DW_LNS_fixed_advance_pc = 0x9,\n  DW_LNS_set_prologue_end = 0xa,\n  DW_LNS_set_epilogue_begin = 0xb,\n  DW_LNS_set_isa = 0xc,\n};\n\nenum dwarf_extended_line_number_op {\n  DW_LNE_end_sequence = 0x1,\n  DW_LNE_set_address = 0x2,\n  DW_LNE_define_file = 0x3,\n  DW_LNE_set_discriminator = 0x4,\n};\n\nenum dwarf_line_number_content_type {\n  DW_LNCT_path = 0x1,\n  DW_LNCT_directory_index = 0x2,\n  DW_LNCT_timestamp = 0x3,\n  DW_LNCT_size = 0x4,\n  DW_LNCT_MD5 = 0x5,\n  DW_LNCT_lo_user = 0x2000,\n  DW_LNCT_hi_user = 0x3fff\n};\n\nenum dwarf_range_list_entry {\n  DW_RLE_end_of_list = 0x00,\n  DW_RLE_base_addressx = 0x01,\n  DW_RLE_startx_endx = 0x02,\n  DW_RLE_startx_length = 0x03,\n  DW_RLE_offset_pair = 0x04,\n  DW_RLE_base_address = 0x05,\n  DW_RLE_start_end = 0x06,\n  DW_RLE_start_length = 0x07\n};\n\nenum dwarf_unit_type {\n  DW_UT_compile = 0x01,\n  DW_UT_type = 0x02,\n  DW_UT_partial = 0x03,\n  DW_UT_skeleton = 0x04,\n  DW_UT_split_compile = 0x05,\n  DW_UT_split_type = 0x06,\n  DW_UT_lo_user = 0x80,\n  DW_UT_hi_user = 0xff\n};\n\n#if !defined(HAVE_DECL_STRNLEN) || !HAVE_DECL_STRNLEN\n\n/* If strnlen is not declared, provide our own version.  */\n\nstatic size_t\nxstrnlen (const char *s, size_t maxlen)\n{\n  size_t i;\n\n  for (i = 0; i < maxlen; ++i)\n    if (s[i] == '\\0')\n      break;\n  return i;\n}\n\n#define strnlen xstrnlen\n\n#endif\n\n/* A buffer to read DWARF info.  */\n\nstruct dwarf_buf\n{\n  /* Buffer name for error messages.  */\n  const char *name;\n  /* Start of the buffer.  */\n  const unsigned char *start;\n  /* Next byte to read.  */\n  const unsigned char *buf;\n  /* The number of bytes remaining.  */\n  size_t left;\n  /* Whether the data is big-endian.  */\n  int is_bigendian;\n  /* Error callback routine.  */\n  backtrace_error_callback error_callback;\n  /* Data for error_callback.  */\n  void *data;\n  /* Non-zero if we've reported an underflow error.  */\n  int reported_underflow;\n};\n\n/* A single attribute in a DWARF abbreviation.  */\n\nstruct attr\n{\n  /* The attribute name.  */\n  enum dwarf_attribute name;\n  /* The attribute form.  */\n  enum dwarf_form form;\n  /* The attribute value, for DW_FORM_implicit_const.  */\n  int64_t val;\n};\n\n/* A single DWARF abbreviation.  */\n\nstruct abbrev\n{\n  /* The abbrev code--the number used to refer to the abbrev.  */\n  uint64_t code;\n  /* The entry tag.  */\n  enum dwarf_tag tag;\n  /* Non-zero if this abbrev has child entries.  */\n  int has_children;\n  /* The number of attributes.  */\n  size_t num_attrs;\n  /* The attributes.  */\n  struct attr *attrs;\n};\n\n/* The DWARF abbreviations for a compilation unit.  This structure\n   only exists while reading the compilation unit.  Most DWARF readers\n   seem to a hash table to map abbrev ID's to abbrev entries.\n   However, we primarily care about GCC, and GCC simply issues ID's in\n   numerical order starting at 1.  So we simply keep a sorted vector,\n   and try to just look up the code.  */\n\nstruct abbrevs\n{\n  /* The number of abbrevs in the vector.  */\n  size_t num_abbrevs;\n  /* The abbrevs, sorted by the code field.  */\n  struct abbrev *abbrevs;\n};\n\n/* The different kinds of attribute values.  */\n\nenum attr_val_encoding\n{\n  /* No attribute value.  */\n  ATTR_VAL_NONE,\n  /* An address.  */\n  ATTR_VAL_ADDRESS,\n  /* An index into the .debug_addr section, whose value is relative to\n     the DW_AT_addr_base attribute of the compilation unit.  */\n  ATTR_VAL_ADDRESS_INDEX,\n  /* A unsigned integer.  */\n  ATTR_VAL_UINT,\n  /* A sigd integer.  */\n  ATTR_VAL_SINT,\n  /* A string.  */\n  ATTR_VAL_STRING,\n  /* An index into the .debug_str_offsets section.  */\n  ATTR_VAL_STRING_INDEX,\n  /* An offset to other data in the containing unit.  */\n  ATTR_VAL_REF_UNIT,\n  /* An offset to other data within the .debug_info section.  */\n  ATTR_VAL_REF_INFO,\n  /* An offset to other data within the alt .debug_info section.  */\n  ATTR_VAL_REF_ALT_INFO,\n  /* An offset to data in some other section.  */\n  ATTR_VAL_REF_SECTION,\n  /* A type signature.  */\n  ATTR_VAL_REF_TYPE,\n  /* An index into the .debug_rnglists section.  */\n  ATTR_VAL_RNGLISTS_INDEX,\n  /* A block of data (not represented).  */\n  ATTR_VAL_BLOCK,\n  /* An expression (not represented).  */\n  ATTR_VAL_EXPR,\n};\n\n/* An attribute value.  */\n\nstruct attr_val\n{\n  /* How the value is stored in the field u.  */\n  enum attr_val_encoding encoding;\n  union\n  {\n    /* ATTR_VAL_ADDRESS*, ATTR_VAL_UINT, ATTR_VAL_REF*.  */\n    uint64_t uint;\n    /* ATTR_VAL_SINT.  */\n    int64_t sint;\n    /* ATTR_VAL_STRING.  */\n    const char *string;\n    /* ATTR_VAL_BLOCK not stored.  */\n  } u;\n};\n\n/* The line number program header.  */\n\nstruct line_header\n{\n  /* The version of the line number information.  */\n  int version;\n  /* Address size.  */\n  int addrsize;\n  /* The minimum instruction length.  */\n  unsigned int min_insn_len;\n  /* The maximum number of ops per instruction.  */\n  unsigned int max_ops_per_insn;\n  /* The line base for special opcodes.  */\n  int line_base;\n  /* The line range for special opcodes.  */\n  unsigned int line_range;\n  /* The opcode base--the first special opcode.  */\n  unsigned int opcode_base;\n  /* Opcode lengths, indexed by opcode - 1.  */\n  const unsigned char *opcode_lengths;\n  /* The number of directory entries.  */\n  size_t dirs_count;\n  /* The directory entries.  */\n  const char **dirs;\n  /* The number of filenames.  */\n  size_t filenames_count;\n  /* The filenames.  */\n  const char **filenames;\n};\n\n/* A format description from a line header.  */\n\nstruct line_header_format\n{\n  int lnct;\t\t/* LNCT code.  */\n  enum dwarf_form form;\t/* Form of entry data.  */\n};\n\n/* Map a single PC value to a file/line.  We will keep a vector of\n   these sorted by PC value.  Each file/line will be correct from the\n   PC up to the PC of the next entry if there is one.  We allocate one\n   extra entry at the end so that we can use bsearch.  */\n\nstruct line\n{\n  /* PC.  */\n  uintptr_t pc;\n  /* File name.  Many entries in the array are expected to point to\n     the same file name.  */\n  const char *filename;\n  /* Line number.  */\n  int lineno;\n  /* Index of the object in the original array read from the DWARF\n     section, before it has been sorted.  The index makes it possible\n     to use Quicksort and maintain stability.  */\n  int idx;\n};\n\n/* A growable vector of line number information.  This is used while\n   reading the line numbers.  */\n\nstruct line_vector\n{\n  /* Memory.  This is an array of struct line.  */\n  struct backtrace_vector vec;\n  /* Number of valid mappings.  */\n  size_t count;\n};\n\n/* A function described in the debug info.  */\n\nstruct function\n{\n  /* The name of the function.  */\n  const char *name;\n  /* If this is an inlined function, the filename of the call\n     site.  */\n  const char *caller_filename;\n  /* If this is an inlined function, the line number of the call\n     site.  */\n  int caller_lineno;\n  /* Map PC ranges to inlined functions.  */\n  struct function_addrs *function_addrs;\n  size_t function_addrs_count;\n};\n\n/* An address range for a function.  This maps a PC value to a\n   specific function.  */\n\nstruct function_addrs\n{\n  /* Range is LOW <= PC < HIGH.  */\n  uintptr_t low;\n  uintptr_t high;\n  /* Function for this address range.  */\n  struct function *function;\n};\n\n/* A growable vector of function address ranges.  */\n\nstruct function_vector\n{\n  /* Memory.  This is an array of struct function_addrs.  */\n  struct backtrace_vector vec;\n  /* Number of address ranges present.  */\n  size_t count;\n};\n\n/* A DWARF compilation unit.  This only holds the information we need\n   to map a PC to a file and line.  */\n\nstruct unit\n{\n  /* The first entry for this compilation unit.  */\n  const unsigned char *unit_data;\n  /* The length of the data for this compilation unit.  */\n  size_t unit_data_len;\n  /* The offset of UNIT_DATA from the start of the information for\n     this compilation unit.  */\n  size_t unit_data_offset;\n  /* Offset of the start of the compilation unit from the start of the\n     .debug_info section.  */\n  size_t low_offset;\n  /* Offset of the end of the compilation unit from the start of the\n     .debug_info section.  */\n  size_t high_offset;\n  /* DWARF version.  */\n  int version;\n  /* Whether unit is DWARF64.  */\n  int is_dwarf64;\n  /* Address size.  */\n  int addrsize;\n  /* Offset into line number information.  */\n  off_t lineoff;\n  /* Offset of compilation unit in .debug_str_offsets.  */\n  uint64_t str_offsets_base;\n  /* Offset of compilation unit in .debug_addr.  */\n  uint64_t addr_base;\n  /* Offset of compilation unit in .debug_rnglists.  */\n  uint64_t rnglists_base;\n  /* Primary source file.  */\n  const char *filename;\n  /* Compilation command working directory.  */\n  const char *comp_dir;\n  /* Absolute file name, only set if needed.  */\n  const char *abs_filename;\n  /* The abbreviations for this unit.  */\n  struct abbrevs abbrevs;\n\n  /* The fields above this point are read in during initialization and\n     may be accessed freely.  The fields below this point are read in\n     as needed, and therefore require care, as different threads may\n     try to initialize them simultaneously.  */\n\n  /* PC to line number mapping.  This is NULL if the values have not\n     been read.  This is (struct line *) -1 if there was an error\n     reading the values.  */\n  struct line *lines;\n  /* Number of entries in lines.  */\n  size_t lines_count;\n  /* PC ranges to function.  */\n  struct function_addrs *function_addrs;\n  size_t function_addrs_count;\n};\n\n/* An address range for a compilation unit.  This maps a PC value to a\n   specific compilation unit.  Note that we invert the representation\n   in DWARF: instead of listing the units and attaching a list of\n   ranges, we list the ranges and have each one point to the unit.\n   This lets us do a binary search to find the unit.  */\n\nstruct unit_addrs\n{\n  /* Range is LOW <= PC < HIGH.  */\n  uintptr_t low;\n  uintptr_t high;\n  /* Compilation unit for this address range.  */\n  struct unit *u;\n};\n\n/* A growable vector of compilation unit address ranges.  */\n\nstruct unit_addrs_vector\n{\n  /* Memory.  This is an array of struct unit_addrs.  */\n  struct backtrace_vector vec;\n  /* Number of address ranges present.  */\n  size_t count;\n};\n\n/* A growable vector of compilation unit pointer.  */\n\nstruct unit_vector\n{\n  struct backtrace_vector vec;\n  size_t count;\n};\n\n/* The information we need to map a PC to a file and line.  */\n\nstruct dwarf_data\n{\n  /* The data for the next file we know about.  */\n  struct dwarf_data *next;\n  /* The data for .gnu_debugaltlink.  */\n  struct dwarf_data *altlink;\n  /* The base address mapping for this file.  */\n  struct libbacktrace_base_address base_address;\n  /* A sorted list of address ranges.  */\n  struct unit_addrs *addrs;\n  /* Number of address ranges in list.  */\n  size_t addrs_count;\n  /* A sorted list of units.  */\n  struct unit **units;\n  /* Number of units in the list.  */\n  size_t units_count;\n  /* The unparsed DWARF debug data.  */\n  struct dwarf_sections dwarf_sections;\n  /* Whether the data is big-endian or not.  */\n  int is_bigendian;\n  /* A vector used for function addresses.  We keep this here so that\n     we can grow the vector as we read more functions.  */\n  struct function_vector fvec;\n};\n\n/* Report an error for a DWARF buffer.  */\n\nstatic void\ndwarf_buf_error (struct dwarf_buf *buf, const char *msg, int errnum)\n{\n  char b[200];\n\n  snprintf (b, sizeof b, \"%s in %s at %d\",\n\t    msg, buf->name, (int) (buf->buf - buf->start));\n  buf->error_callback (buf->data, b, errnum);\n}\n\n/* Require at least COUNT bytes in BUF.  Return 1 if all is well, 0 on\n   error.  */\n\nstatic int\nrequire (struct dwarf_buf *buf, size_t count)\n{\n  if (buf->left >= count)\n    return 1;\n\n  if (!buf->reported_underflow)\n    {\n      dwarf_buf_error (buf, \"DWARF underflow\", 0);\n      buf->reported_underflow = 1;\n    }\n\n  return 0;\n}\n\n/* Advance COUNT bytes in BUF.  Return 1 if all is well, 0 on\n   error.  */\n\nstatic int\nadvance (struct dwarf_buf *buf, size_t count)\n{\n  if (!require (buf, count))\n    return 0;\n  buf->buf += count;\n  buf->left -= count;\n  return 1;\n}\n\n/* Read one zero-terminated string from BUF and advance past the string.  */\n\nstatic const char *\nread_string (struct dwarf_buf *buf)\n{\n  const char *p = (const char *)buf->buf;\n  size_t len = strnlen (p, buf->left);\n\n  /* - If len == left, we ran out of buffer before finding the zero terminator.\n       Generate an error by advancing len + 1.\n     - If len < left, advance by len + 1 to skip past the zero terminator.  */\n  size_t count = len + 1;\n\n  if (!advance (buf, count))\n    return NULL;\n\n  return p;\n}\n\n/* Read one byte from BUF and advance 1 byte.  */\n\nstatic unsigned char\nread_byte (struct dwarf_buf *buf)\n{\n  const unsigned char *p = buf->buf;\n\n  if (!advance (buf, 1))\n    return 0;\n  return p[0];\n}\n\n/* Read a signed char from BUF and advance 1 byte.  */\n\nstatic signed char\nread_sbyte (struct dwarf_buf *buf)\n{\n  const unsigned char *p = buf->buf;\n\n  if (!advance (buf, 1))\n    return 0;\n  return (*p ^ 0x80) - 0x80;\n}\n\n/* Read a uint16 from BUF and advance 2 bytes.  */\n\nstatic uint16_t\nread_uint16 (struct dwarf_buf *buf)\n{\n  const unsigned char *p = buf->buf;\n\n  if (!advance (buf, 2))\n    return 0;\n  if (buf->is_bigendian)\n    return ((uint16_t) p[0] << 8) | (uint16_t) p[1];\n  else\n    return ((uint16_t) p[1] << 8) | (uint16_t) p[0];\n}\n\n/* Read a 24 bit value from BUF and advance 3 bytes.  */\n\nstatic uint32_t\nread_uint24 (struct dwarf_buf *buf)\n{\n  const unsigned char *p = buf->buf;\n\n  if (!advance (buf, 3))\n    return 0;\n  if (buf->is_bigendian)\n    return (((uint32_t) p[0] << 16) | ((uint32_t) p[1] << 8)\n\t    | (uint32_t) p[2]);\n  else\n    return (((uint32_t) p[2] << 16) | ((uint32_t) p[1] << 8)\n\t    | (uint32_t) p[0]);\n}\n\n/* Read a uint32 from BUF and advance 4 bytes.  */\n\nstatic uint32_t\nread_uint32 (struct dwarf_buf *buf)\n{\n  const unsigned char *p = buf->buf;\n\n  if (!advance (buf, 4))\n    return 0;\n  if (buf->is_bigendian)\n    return (((uint32_t) p[0] << 24) | ((uint32_t) p[1] << 16)\n\t    | ((uint32_t) p[2] << 8) | (uint32_t) p[3]);\n  else\n    return (((uint32_t) p[3] << 24) | ((uint32_t) p[2] << 16)\n\t    | ((uint32_t) p[1] << 8) | (uint32_t) p[0]);\n}\n\n/* Read a uint64 from BUF and advance 8 bytes.  */\n\nstatic uint64_t\nread_uint64 (struct dwarf_buf *buf)\n{\n  const unsigned char *p = buf->buf;\n\n  if (!advance (buf, 8))\n    return 0;\n  if (buf->is_bigendian)\n    return (((uint64_t) p[0] << 56) | ((uint64_t) p[1] << 48)\n\t    | ((uint64_t) p[2] << 40) | ((uint64_t) p[3] << 32)\n\t    | ((uint64_t) p[4] << 24) | ((uint64_t) p[5] << 16)\n\t    | ((uint64_t) p[6] << 8) | (uint64_t) p[7]);\n  else\n    return (((uint64_t) p[7] << 56) | ((uint64_t) p[6] << 48)\n\t    | ((uint64_t) p[5] << 40) | ((uint64_t) p[4] << 32)\n\t    | ((uint64_t) p[3] << 24) | ((uint64_t) p[2] << 16)\n\t    | ((uint64_t) p[1] << 8) | (uint64_t) p[0]);\n}\n\n/* Read an offset from BUF and advance the appropriate number of\n   bytes.  */\n\nstatic uint64_t\nread_offset (struct dwarf_buf *buf, int is_dwarf64)\n{\n  if (is_dwarf64)\n    return read_uint64 (buf);\n  else\n    return read_uint32 (buf);\n}\n\n/* Read an address from BUF and advance the appropriate number of\n   bytes.  */\n\nstatic uint64_t\nread_address (struct dwarf_buf *buf, int addrsize)\n{\n  switch (addrsize)\n    {\n    case 1:\n      return read_byte (buf);\n    case 2:\n      return read_uint16 (buf);\n    case 4:\n      return read_uint32 (buf);\n    case 8:\n      return read_uint64 (buf);\n    default:\n      dwarf_buf_error (buf, \"unrecognized address size\", 0);\n      return 0;\n    }\n}\n\n/* Return whether a value is the highest possible address, given the\n   address size.  */\n\nstatic int\nis_highest_address (uint64_t address, int addrsize)\n{\n  switch (addrsize)\n    {\n    case 1:\n      return address == (unsigned char) -1;\n    case 2:\n      return address == (uint16_t) -1;\n    case 4:\n      return address == (uint32_t) -1;\n    case 8:\n      return address == (uint64_t) -1;\n    default:\n      return 0;\n    }\n}\n\n/* Read an unsigned LEB128 number.  */\n\nstatic uint64_t\nread_uleb128 (struct dwarf_buf *buf)\n{\n  uint64_t ret;\n  unsigned int shift;\n  int overflow;\n  unsigned char b;\n\n  ret = 0;\n  shift = 0;\n  overflow = 0;\n  do\n    {\n      const unsigned char *p;\n\n      p = buf->buf;\n      if (!advance (buf, 1))\n\treturn 0;\n      b = *p;\n      if (shift < 64)\n\tret |= ((uint64_t) (b & 0x7f)) << shift;\n      else if (!overflow)\n\t{\n\t  dwarf_buf_error (buf, \"LEB128 overflows uint64_t\", 0);\n\t  overflow = 1;\n\t}\n      shift += 7;\n    }\n  while ((b & 0x80) != 0);\n\n  return ret;\n}\n\n/* Read a signed LEB128 number.  */\n\nstatic int64_t\nread_sleb128 (struct dwarf_buf *buf)\n{\n  uint64_t val;\n  unsigned int shift;\n  int overflow;\n  unsigned char b;\n\n  val = 0;\n  shift = 0;\n  overflow = 0;\n  do\n    {\n      const unsigned char *p;\n\n      p = buf->buf;\n      if (!advance (buf, 1))\n\treturn 0;\n      b = *p;\n      if (shift < 64)\n\tval |= ((uint64_t) (b & 0x7f)) << shift;\n      else if (!overflow)\n\t{\n\t  dwarf_buf_error (buf, \"signed LEB128 overflows uint64_t\", 0);\n\t  overflow = 1;\n\t}\n      shift += 7;\n    }\n  while ((b & 0x80) != 0);\n\n  if ((b & 0x40) != 0 && shift < 64)\n    val |= ((uint64_t) -1) << shift;\n\n  return (int64_t) val;\n}\n\n/* Return the length of an LEB128 number.  */\n\nstatic size_t\nleb128_len (const unsigned char *p)\n{\n  size_t ret;\n\n  ret = 1;\n  while ((*p & 0x80) != 0)\n    {\n      ++p;\n      ++ret;\n    }\n  return ret;\n}\n\n/* Read initial_length from BUF and advance the appropriate number of bytes.  */\n\nstatic uint64_t\nread_initial_length (struct dwarf_buf *buf, int *is_dwarf64)\n{\n  uint64_t len;\n\n  len = read_uint32 (buf);\n  if (len == 0xffffffff)\n    {\n      len = read_uint64 (buf);\n      *is_dwarf64 = 1;\n    }\n  else\n    *is_dwarf64 = 0;\n\n  return len;\n}\n\n/* Free an abbreviations structure.  */\n\nstatic void\nfree_abbrevs (struct backtrace_state *state, struct abbrevs *abbrevs,\n\t      backtrace_error_callback error_callback, void *data)\n{\n  size_t i;\n\n  for (i = 0; i < abbrevs->num_abbrevs; ++i)\n    backtrace_free (state, abbrevs->abbrevs[i].attrs,\n\t\t    abbrevs->abbrevs[i].num_attrs * sizeof (struct attr),\n\t\t    error_callback, data);\n  backtrace_free (state, abbrevs->abbrevs,\n\t\t  abbrevs->num_abbrevs * sizeof (struct abbrev),\n\t\t  error_callback, data);\n  abbrevs->num_abbrevs = 0;\n  abbrevs->abbrevs = NULL;\n}\n\n/* Read an attribute value.  Returns 1 on success, 0 on failure.  If\n   the value can be represented as a uint64_t, sets *VAL and sets\n   *IS_VALID to 1.  We don't try to store the value of other attribute\n   forms, because we don't care about them.  */\n\nstatic int\nread_attribute (enum dwarf_form form, uint64_t implicit_val,\n\t\tstruct dwarf_buf *buf, int is_dwarf64, int version,\n\t\tint addrsize, const struct dwarf_sections *dwarf_sections,\n\t\tstruct dwarf_data *altlink, struct attr_val *val)\n{\n  /* Avoid warnings about val.u.FIELD may be used uninitialized if\n     this function is inlined.  The warnings aren't valid but can\n     occur because the different fields are set and used\n     conditionally.  */\n  memset (val, 0, sizeof *val);\n\n  switch (form)\n    {\n    case DW_FORM_addr:\n      val->encoding = ATTR_VAL_ADDRESS;\n      val->u.uint = read_address (buf, addrsize);\n      return 1;\n    case DW_FORM_block2:\n      val->encoding = ATTR_VAL_BLOCK;\n      return advance (buf, read_uint16 (buf));\n    case DW_FORM_block4:\n      val->encoding = ATTR_VAL_BLOCK;\n      return advance (buf, read_uint32 (buf));\n    case DW_FORM_data2:\n      val->encoding = ATTR_VAL_UINT;\n      val->u.uint = read_uint16 (buf);\n      return 1;\n    case DW_FORM_data4:\n      val->encoding = ATTR_VAL_UINT;\n      val->u.uint = read_uint32 (buf);\n      return 1;\n    case DW_FORM_data8:\n      val->encoding = ATTR_VAL_UINT;\n      val->u.uint = read_uint64 (buf);\n      return 1;\n    case DW_FORM_data16:\n      val->encoding = ATTR_VAL_BLOCK;\n      return advance (buf, 16);\n    case DW_FORM_string:\n      val->encoding = ATTR_VAL_STRING;\n      val->u.string = read_string (buf);\n      return val->u.string == NULL ? 0 : 1;\n    case DW_FORM_block:\n      val->encoding = ATTR_VAL_BLOCK;\n      return advance (buf, read_uleb128 (buf));\n    case DW_FORM_block1:\n      val->encoding = ATTR_VAL_BLOCK;\n      return advance (buf, read_byte (buf));\n    case DW_FORM_data1:\n      val->encoding = ATTR_VAL_UINT;\n      val->u.uint = read_byte (buf);\n      return 1;\n    case DW_FORM_flag:\n      val->encoding = ATTR_VAL_UINT;\n      val->u.uint = read_byte (buf);\n      return 1;\n    case DW_FORM_sdata:\n      val->encoding = ATTR_VAL_SINT;\n      val->u.sint = read_sleb128 (buf);\n      return 1;\n    case DW_FORM_strp:\n      {\n\tuint64_t offset;\n\n\toffset = read_offset (buf, is_dwarf64);\n\tif (offset >= dwarf_sections->size[DEBUG_STR])\n\t  {\n\t    dwarf_buf_error (buf, \"DW_FORM_strp out of range\", 0);\n\t    return 0;\n\t  }\n\tval->encoding = ATTR_VAL_STRING;\n\tval->u.string =\n\t  (const char *) dwarf_sections->data[DEBUG_STR] + offset;\n\treturn 1;\n      }\n    case DW_FORM_line_strp:\n      {\n\tuint64_t offset;\n\n\toffset = read_offset (buf, is_dwarf64);\n\tif (offset >= dwarf_sections->size[DEBUG_LINE_STR])\n\t  {\n\t    dwarf_buf_error (buf, \"DW_FORM_line_strp out of range\", 0);\n\t    return 0;\n\t  }\n\tval->encoding = ATTR_VAL_STRING;\n\tval->u.string =\n\t  (const char *) dwarf_sections->data[DEBUG_LINE_STR] + offset;\n\treturn 1;\n      }\n    case DW_FORM_udata:\n      val->encoding = ATTR_VAL_UINT;\n      val->u.uint = read_uleb128 (buf);\n      return 1;\n    case DW_FORM_ref_addr:\n      val->encoding = ATTR_VAL_REF_INFO;\n      if (version == 2)\n\tval->u.uint = read_address (buf, addrsize);\n      else\n\tval->u.uint = read_offset (buf, is_dwarf64);\n      return 1;\n    case DW_FORM_ref1:\n      val->encoding = ATTR_VAL_REF_UNIT;\n      val->u.uint = read_byte (buf);\n      return 1;\n    case DW_FORM_ref2:\n      val->encoding = ATTR_VAL_REF_UNIT;\n      val->u.uint = read_uint16 (buf);\n      return 1;\n    case DW_FORM_ref4:\n      val->encoding = ATTR_VAL_REF_UNIT;\n      val->u.uint = read_uint32 (buf);\n      return 1;\n    case DW_FORM_ref8:\n      val->encoding = ATTR_VAL_REF_UNIT;\n      val->u.uint = read_uint64 (buf);\n      return 1;\n    case DW_FORM_ref_udata:\n      val->encoding = ATTR_VAL_REF_UNIT;\n      val->u.uint = read_uleb128 (buf);\n      return 1;\n    case DW_FORM_indirect:\n      {\n\tuint64_t form;\n\n\tform = read_uleb128 (buf);\n\tif (form == DW_FORM_implicit_const)\n\t  {\n\t    dwarf_buf_error (buf,\n\t\t\t     \"DW_FORM_indirect to DW_FORM_implicit_const\",\n\t\t\t     0);\n\t    return 0;\n\t  }\n\treturn read_attribute ((enum dwarf_form) form, 0, buf, is_dwarf64,\n\t\t\t       version, addrsize, dwarf_sections, altlink,\n\t\t\t       val);\n      }\n    case DW_FORM_sec_offset:\n      val->encoding = ATTR_VAL_REF_SECTION;\n      val->u.uint = read_offset (buf, is_dwarf64);\n      return 1;\n    case DW_FORM_exprloc:\n      val->encoding = ATTR_VAL_EXPR;\n      return advance (buf, read_uleb128 (buf));\n    case DW_FORM_flag_present:\n      val->encoding = ATTR_VAL_UINT;\n      val->u.uint = 1;\n      return 1;\n    case DW_FORM_ref_sig8:\n      val->encoding = ATTR_VAL_REF_TYPE;\n      val->u.uint = read_uint64 (buf);\n      return 1;\n    case DW_FORM_strx: case DW_FORM_strx1: case DW_FORM_strx2:\n    case DW_FORM_strx3: case DW_FORM_strx4:\n      {\n\tuint64_t offset;\n\n\tswitch (form)\n\t  {\n\t  case DW_FORM_strx:\n\t    offset = read_uleb128 (buf);\n\t    break;\n\t  case DW_FORM_strx1:\n\t    offset = read_byte (buf);\n\t    break;\n\t  case DW_FORM_strx2:\n\t    offset = read_uint16 (buf);\n\t    break;\n\t  case DW_FORM_strx3:\n\t    offset = read_uint24 (buf);\n\t    break;\n\t  case DW_FORM_strx4:\n\t    offset = read_uint32 (buf);\n\t    break;\n\t  default:\n\t    /* This case can't happen.  */\n\t    return 0;\n\t  }\n\tval->encoding = ATTR_VAL_STRING_INDEX;\n\tval->u.uint = offset;\n\treturn 1;\n      }\n    case DW_FORM_addrx: case DW_FORM_addrx1: case DW_FORM_addrx2:\n    case DW_FORM_addrx3: case DW_FORM_addrx4:\n      {\n\tuint64_t offset;\n\n\tswitch (form)\n\t  {\n\t  case DW_FORM_addrx:\n\t    offset = read_uleb128 (buf);\n\t    break;\n\t  case DW_FORM_addrx1:\n\t    offset = read_byte (buf);\n\t    break;\n\t  case DW_FORM_addrx2:\n\t    offset = read_uint16 (buf);\n\t    break;\n\t  case DW_FORM_addrx3:\n\t    offset = read_uint24 (buf);\n\t    break;\n\t  case DW_FORM_addrx4:\n\t    offset = read_uint32 (buf);\n\t    break;\n\t  default:\n\t    /* This case can't happen.  */\n\t    return 0;\n\t  }\n\tval->encoding = ATTR_VAL_ADDRESS_INDEX;\n\tval->u.uint = offset;\n\treturn 1;\n      }\n    case DW_FORM_ref_sup4:\n      val->encoding = ATTR_VAL_REF_SECTION;\n      val->u.uint = read_uint32 (buf);\n      return 1;\n    case DW_FORM_ref_sup8:\n      val->encoding = ATTR_VAL_REF_SECTION;\n      val->u.uint = read_uint64 (buf);\n      return 1;\n    case DW_FORM_implicit_const:\n      val->encoding = ATTR_VAL_UINT;\n      val->u.uint = implicit_val;\n      return 1;\n    case DW_FORM_loclistx:\n      /* We don't distinguish this from DW_FORM_sec_offset.  It\n       * shouldn't matter since we don't care about loclists.  */\n      val->encoding = ATTR_VAL_REF_SECTION;\n      val->u.uint = read_uleb128 (buf);\n      return 1;\n    case DW_FORM_rnglistx:\n      val->encoding = ATTR_VAL_RNGLISTS_INDEX;\n      val->u.uint = read_uleb128 (buf);\n      return 1;\n    case DW_FORM_GNU_addr_index:\n      val->encoding = ATTR_VAL_REF_SECTION;\n      val->u.uint = read_uleb128 (buf);\n      return 1;\n    case DW_FORM_GNU_str_index:\n      val->encoding = ATTR_VAL_REF_SECTION;\n      val->u.uint = read_uleb128 (buf);\n      return 1;\n    case DW_FORM_GNU_ref_alt:\n      val->u.uint = read_offset (buf, is_dwarf64);\n      if (altlink == NULL)\n\t{\n\t  val->encoding = ATTR_VAL_NONE;\n\t  return 1;\n\t}\n      val->encoding = ATTR_VAL_REF_ALT_INFO;\n      return 1;\n    case DW_FORM_strp_sup: case DW_FORM_GNU_strp_alt:\n      {\n\tuint64_t offset;\n\n\toffset = read_offset (buf, is_dwarf64);\n\tif (altlink == NULL)\n\t  {\n\t    val->encoding = ATTR_VAL_NONE;\n\t    return 1;\n\t  }\n\tif (offset >= altlink->dwarf_sections.size[DEBUG_STR])\n\t  {\n\t    dwarf_buf_error (buf, \"DW_FORM_strp_sup out of range\", 0);\n\t    return 0;\n\t  }\n\tval->encoding = ATTR_VAL_STRING;\n\tval->u.string =\n\t  (const char *) altlink->dwarf_sections.data[DEBUG_STR] + offset;\n\treturn 1;\n      }\n    default:\n      dwarf_buf_error (buf, \"unrecognized DWARF form\", -1);\n      return 0;\n    }\n}\n\n/* If we can determine the value of a string attribute, set *STRING to\n   point to the string.  Return 1 on success, 0 on error.  If we don't\n   know the value, we consider that a success, and we don't change\n   *STRING.  An error is only reported for some sort of out of range\n   offset.  */\n\nstatic int\nresolve_string (const struct dwarf_sections *dwarf_sections, int is_dwarf64,\n\t\tint is_bigendian, uint64_t str_offsets_base,\n\t\tconst struct attr_val *val,\n\t\tbacktrace_error_callback error_callback, void *data,\n\t\tconst char **string)\n{\n  switch (val->encoding)\n    {\n    case ATTR_VAL_STRING:\n      *string = val->u.string;\n      return 1;\n\n    case ATTR_VAL_STRING_INDEX:\n      {\n\tuint64_t offset;\n\tstruct dwarf_buf offset_buf;\n\n\toffset = val->u.uint * (is_dwarf64 ? 8 : 4) + str_offsets_base;\n\tif (offset + (is_dwarf64 ? 8 : 4)\n\t    > dwarf_sections->size[DEBUG_STR_OFFSETS])\n\t  {\n\t    error_callback (data, \"DW_FORM_strx value out of range\", 0);\n\t    return 0;\n\t  }\n\n\toffset_buf.name = \".debug_str_offsets\";\n\toffset_buf.start = dwarf_sections->data[DEBUG_STR_OFFSETS];\n\toffset_buf.buf = dwarf_sections->data[DEBUG_STR_OFFSETS] + offset;\n\toffset_buf.left = dwarf_sections->size[DEBUG_STR_OFFSETS] - offset;\n\toffset_buf.is_bigendian = is_bigendian;\n\toffset_buf.error_callback = error_callback;\n\toffset_buf.data = data;\n\toffset_buf.reported_underflow = 0;\n\n\toffset = read_offset (&offset_buf, is_dwarf64);\n\tif (offset >= dwarf_sections->size[DEBUG_STR])\n\t  {\n\t    dwarf_buf_error (&offset_buf,\n\t\t\t     \"DW_FORM_strx offset out of range\",\n\t\t\t     0);\n\t    return 0;\n\t  }\n\t*string = (const char *) dwarf_sections->data[DEBUG_STR] + offset;\n\treturn 1;\n      }\n\n    default:\n      return 1;\n    }\n}\n\n/* Set *ADDRESS to the real address for a ATTR_VAL_ADDRESS_INDEX.\n   Return 1 on success, 0 on error.  */\n\nstatic int\nresolve_addr_index (const struct dwarf_sections *dwarf_sections,\n\t\t    uint64_t addr_base, int addrsize, int is_bigendian,\n\t\t    uint64_t addr_index,\n\t\t    backtrace_error_callback error_callback, void *data,\n\t\t    uintptr_t *address)\n{\n  uint64_t offset;\n  struct dwarf_buf addr_buf;\n\n  offset = addr_index * addrsize + addr_base;\n  if (offset + addrsize > dwarf_sections->size[DEBUG_ADDR])\n    {\n      error_callback (data, \"DW_FORM_addrx value out of range\", 0);\n      return 0;\n    }\n\n  addr_buf.name = \".debug_addr\";\n  addr_buf.start = dwarf_sections->data[DEBUG_ADDR];\n  addr_buf.buf = dwarf_sections->data[DEBUG_ADDR] + offset;\n  addr_buf.left = dwarf_sections->size[DEBUG_ADDR] - offset;\n  addr_buf.is_bigendian = is_bigendian;\n  addr_buf.error_callback = error_callback;\n  addr_buf.data = data;\n  addr_buf.reported_underflow = 0;\n\n  *address = (uintptr_t) read_address (&addr_buf, addrsize);\n  return 1;\n}\n\n/* Compare a unit offset against a unit for bsearch.  */\n\nstatic int\nunits_search (const void *vkey, const void *ventry)\n{\n  const size_t *key = (const size_t *) vkey;\n  const struct unit *entry = *((const struct unit *const *) ventry);\n  size_t offset;\n\n  offset = *key;\n  if (offset < entry->low_offset)\n    return -1;\n  else if (offset >= entry->high_offset)\n    return 1;\n  else\n    return 0;\n}\n\n/* Find a unit in PU containing OFFSET.  */\n\nstatic struct unit *\nfind_unit (struct unit **pu, size_t units_count, size_t offset)\n{\n  struct unit **u;\n  u = bsearch (&offset, pu, units_count, sizeof (struct unit *), units_search);\n  return u == NULL ? NULL : *u;\n}\n\n/* Compare function_addrs for qsort.  When ranges are nested, make the\n   smallest one sort last.  */\n\nstatic int\nfunction_addrs_compare (const void *v1, const void *v2)\n{\n  const struct function_addrs *a1 = (const struct function_addrs *) v1;\n  const struct function_addrs *a2 = (const struct function_addrs *) v2;\n\n  if (a1->low < a2->low)\n    return -1;\n  if (a1->low > a2->low)\n    return 1;\n  if (a1->high < a2->high)\n    return 1;\n  if (a1->high > a2->high)\n    return -1;\n  return strcmp (a1->function->name, a2->function->name);\n}\n\n/* Compare a PC against a function_addrs for bsearch.  We always\n   allocate an entra entry at the end of the vector, so that this\n   routine can safely look at the next entry.  Note that if there are\n   multiple ranges containing PC, which one will be returned is\n   unpredictable.  We compensate for that in dwarf_fileline.  */\n\nstatic int\nfunction_addrs_search (const void *vkey, const void *ventry)\n{\n  const uintptr_t *key = (const uintptr_t *) vkey;\n  const struct function_addrs *entry = (const struct function_addrs *) ventry;\n  uintptr_t pc;\n\n  pc = *key;\n  if (pc < entry->low)\n    return -1;\n  else if (pc > (entry + 1)->low)\n    return 1;\n  else\n    return 0;\n}\n\n/* Add a new compilation unit address range to a vector.  This is\n   called via add_ranges.  Returns 1 on success, 0 on failure.  */\n\nstatic int\nadd_unit_addr (struct backtrace_state *state, void *rdata,\n\t       uintptr_t lowpc, uintptr_t highpc,\n\t       backtrace_error_callback error_callback, void *data,\n\t       void *pvec)\n{\n  struct unit *u = (struct unit *) rdata;\n  struct unit_addrs_vector *vec = (struct unit_addrs_vector *) pvec;\n  struct unit_addrs *p;\n\n  /* Try to merge with the last entry.  */\n  if (vec->count > 0)\n    {\n      p = (struct unit_addrs *) vec->vec.base + (vec->count - 1);\n      if ((lowpc == p->high || lowpc == p->high + 1)\n\t  && u == p->u)\n\t{\n\t  if (highpc > p->high)\n\t    p->high = highpc;\n\t  return 1;\n\t}\n    }\n\n  p = ((struct unit_addrs *)\n       backtrace_vector_grow (state, sizeof (struct unit_addrs),\n\t\t\t      error_callback, data, &vec->vec));\n  if (p == NULL)\n    return 0;\n\n  p->low = lowpc;\n  p->high = highpc;\n  p->u = u;\n\n  ++vec->count;\n\n  return 1;\n}\n\n/* Compare unit_addrs for qsort.  When ranges are nested, make the\n   smallest one sort last.  */\n\nstatic int\nunit_addrs_compare (const void *v1, const void *v2)\n{\n  const struct unit_addrs *a1 = (const struct unit_addrs *) v1;\n  const struct unit_addrs *a2 = (const struct unit_addrs *) v2;\n\n  if (a1->low < a2->low)\n    return -1;\n  if (a1->low > a2->low)\n    return 1;\n  if (a1->high < a2->high)\n    return 1;\n  if (a1->high > a2->high)\n    return -1;\n  if (a1->u->lineoff < a2->u->lineoff)\n    return -1;\n  if (a1->u->lineoff > a2->u->lineoff)\n    return 1;\n  return 0;\n}\n\n/* Compare a PC against a unit_addrs for bsearch.  We always allocate\n   an entry entry at the end of the vector, so that this routine can\n   safely look at the next entry.  Note that if there are multiple\n   ranges containing PC, which one will be returned is unpredictable.\n   We compensate for that in dwarf_fileline.  */\n\nstatic int\nunit_addrs_search (const void *vkey, const void *ventry)\n{\n  const uintptr_t *key = (const uintptr_t *) vkey;\n  const struct unit_addrs *entry = (const struct unit_addrs *) ventry;\n  uintptr_t pc;\n\n  pc = *key;\n  if (pc < entry->low)\n    return -1;\n  else if (pc > (entry + 1)->low)\n    return 1;\n  else\n    return 0;\n}\n\n/* Sort the line vector by PC.  We want a stable sort here to maintain\n   the order of lines for the same PC values.  Since the sequence is\n   being sorted in place, their addresses cannot be relied on to\n   maintain stability.  That is the purpose of the index member.  */\n\nstatic int\nline_compare (const void *v1, const void *v2)\n{\n  const struct line *ln1 = (const struct line *) v1;\n  const struct line *ln2 = (const struct line *) v2;\n\n  if (ln1->pc < ln2->pc)\n    return -1;\n  else if (ln1->pc > ln2->pc)\n    return 1;\n  else if (ln1->idx < ln2->idx)\n    return -1;\n  else if (ln1->idx > ln2->idx)\n    return 1;\n  else\n    return 0;\n}\n\n/* Find a PC in a line vector.  We always allocate an extra entry at\n   the end of the lines vector, so that this routine can safely look\n   at the next entry.  Note that when there are multiple mappings for\n   the same PC value, this will return the last one.  */\n\nstatic int\nline_search (const void *vkey, const void *ventry)\n{\n  const uintptr_t *key = (const uintptr_t *) vkey;\n  const struct line *entry = (const struct line *) ventry;\n  uintptr_t pc;\n\n  pc = *key;\n  if (pc < entry->pc)\n    return -1;\n  else if (pc >= (entry + 1)->pc)\n    return 1;\n  else\n    return 0;\n}\n\n/* Sort the abbrevs by the abbrev code.  This function is passed to\n   both qsort and bsearch.  */\n\nstatic int\nabbrev_compare (const void *v1, const void *v2)\n{\n  const struct abbrev *a1 = (const struct abbrev *) v1;\n  const struct abbrev *a2 = (const struct abbrev *) v2;\n\n  if (a1->code < a2->code)\n    return -1;\n  else if (a1->code > a2->code)\n    return 1;\n  else\n    {\n      /* This really shouldn't happen.  It means there are two\n\t different abbrevs with the same code, and that means we don't\n\t know which one lookup_abbrev should return.  */\n      return 0;\n    }\n}\n\n/* Read the abbreviation table for a compilation unit.  Returns 1 on\n   success, 0 on failure.  */\n\nstatic int\nread_abbrevs (struct backtrace_state *state, uint64_t abbrev_offset,\n\t      const unsigned char *dwarf_abbrev, size_t dwarf_abbrev_size,\n\t      int is_bigendian, backtrace_error_callback error_callback,\n\t      void *data, struct abbrevs *abbrevs)\n{\n  struct dwarf_buf abbrev_buf;\n  struct dwarf_buf count_buf;\n  size_t num_abbrevs;\n\n  abbrevs->num_abbrevs = 0;\n  abbrevs->abbrevs = NULL;\n\n  if (abbrev_offset >= dwarf_abbrev_size)\n    {\n      error_callback (data, \"abbrev offset out of range\", 0);\n      return 0;\n    }\n\n  abbrev_buf.name = \".debug_abbrev\";\n  abbrev_buf.start = dwarf_abbrev;\n  abbrev_buf.buf = dwarf_abbrev + abbrev_offset;\n  abbrev_buf.left = dwarf_abbrev_size - abbrev_offset;\n  abbrev_buf.is_bigendian = is_bigendian;\n  abbrev_buf.error_callback = error_callback;\n  abbrev_buf.data = data;\n  abbrev_buf.reported_underflow = 0;\n\n  /* Count the number of abbrevs in this list.  */\n\n  count_buf = abbrev_buf;\n  num_abbrevs = 0;\n  while (read_uleb128 (&count_buf) != 0)\n    {\n      if (count_buf.reported_underflow)\n\treturn 0;\n      ++num_abbrevs;\n      // Skip tag.\n      read_uleb128 (&count_buf);\n      // Skip has_children.\n      read_byte (&count_buf);\n      // Skip attributes.\n      while (read_uleb128 (&count_buf) != 0)\n\t{\n\t  uint64_t form;\n\n\t  form = read_uleb128 (&count_buf);\n\t  if ((enum dwarf_form) form == DW_FORM_implicit_const)\n\t    read_sleb128 (&count_buf);\n\t}\n      // Skip form of last attribute.\n      read_uleb128 (&count_buf);\n    }\n\n  if (count_buf.reported_underflow)\n    return 0;\n\n  if (num_abbrevs == 0)\n    return 1;\n\n  abbrevs->abbrevs = ((struct abbrev *)\n\t\t      backtrace_alloc (state,\n\t\t\t\t       num_abbrevs * sizeof (struct abbrev),\n\t\t\t\t       error_callback, data));\n  if (abbrevs->abbrevs == NULL)\n    return 0;\n  abbrevs->num_abbrevs = num_abbrevs;\n  memset (abbrevs->abbrevs, 0, num_abbrevs * sizeof (struct abbrev));\n\n  num_abbrevs = 0;\n  while (1)\n    {\n      uint64_t code;\n      struct abbrev a;\n      size_t num_attrs;\n      struct attr *attrs;\n\n      if (abbrev_buf.reported_underflow)\n\tgoto fail;\n\n      code = read_uleb128 (&abbrev_buf);\n      if (code == 0)\n\tbreak;\n\n      a.code = code;\n      a.tag = (enum dwarf_tag) read_uleb128 (&abbrev_buf);\n      a.has_children = read_byte (&abbrev_buf);\n\n      count_buf = abbrev_buf;\n      num_attrs = 0;\n      while (read_uleb128 (&count_buf) != 0)\n\t{\n\t  uint64_t form;\n\n\t  ++num_attrs;\n\t  form = read_uleb128 (&count_buf);\n\t  if ((enum dwarf_form) form == DW_FORM_implicit_const)\n\t    read_sleb128 (&count_buf);\n\t}\n\n      if (num_attrs == 0)\n\t{\n\t  attrs = NULL;\n\t  read_uleb128 (&abbrev_buf);\n\t  read_uleb128 (&abbrev_buf);\n\t}\n      else\n\t{\n\t  attrs = ((struct attr *)\n\t\t   backtrace_alloc (state, num_attrs * sizeof *attrs,\n\t\t\t\t    error_callback, data));\n\t  if (attrs == NULL)\n\t    goto fail;\n\t  num_attrs = 0;\n\t  while (1)\n\t    {\n\t      uint64_t name;\n\t      uint64_t form;\n\n\t      name = read_uleb128 (&abbrev_buf);\n\t      form = read_uleb128 (&abbrev_buf);\n\t      if (name == 0)\n\t\tbreak;\n\t      attrs[num_attrs].name = (enum dwarf_attribute) name;\n\t      attrs[num_attrs].form = (enum dwarf_form) form;\n\t      if ((enum dwarf_form) form == DW_FORM_implicit_const)\n\t\tattrs[num_attrs].val = read_sleb128 (&abbrev_buf);\n\t      else\n\t\tattrs[num_attrs].val = 0;\n\t      ++num_attrs;\n\t    }\n\t}\n\n      a.num_attrs = num_attrs;\n      a.attrs = attrs;\n\n      abbrevs->abbrevs[num_abbrevs] = a;\n      ++num_abbrevs;\n    }\n\n  backtrace_qsort (abbrevs->abbrevs, abbrevs->num_abbrevs,\n\t\t   sizeof (struct abbrev), abbrev_compare);\n\n  return 1;\n\n fail:\n  free_abbrevs (state, abbrevs, error_callback, data);\n  return 0;\n}\n\n/* Return the abbrev information for an abbrev code.  */\n\nstatic const struct abbrev *\nlookup_abbrev (struct abbrevs *abbrevs, uint64_t code,\n\t       backtrace_error_callback error_callback, void *data)\n{\n  struct abbrev key;\n  void *p;\n\n  /* With GCC, where abbrevs are simply numbered in order, we should\n     be able to just look up the entry.  */\n  if (code - 1 < abbrevs->num_abbrevs\n      && abbrevs->abbrevs[code - 1].code == code)\n    return &abbrevs->abbrevs[code - 1];\n\n  /* Otherwise we have to search.  */\n  memset (&key, 0, sizeof key);\n  key.code = code;\n  p = bsearch (&key, abbrevs->abbrevs, abbrevs->num_abbrevs,\n\t       sizeof (struct abbrev), abbrev_compare);\n  if (p == NULL)\n    {\n      error_callback (data, \"invalid abbreviation code\", 0);\n      return NULL;\n    }\n  return (const struct abbrev *) p;\n}\n\n/* This struct is used to gather address range information while\n   reading attributes.  We use this while building a mapping from\n   address ranges to compilation units and then again while mapping\n   from address ranges to function entries.  Normally either\n   lowpc/highpc is set or ranges is set.  */\n\nstruct pcrange {\n  uintptr_t lowpc;             /* The low PC value.  */\n  int have_lowpc;\t\t/* Whether a low PC value was found.  */\n  int lowpc_is_addr_index;\t/* Whether lowpc is in .debug_addr.  */\n  uintptr_t highpc;            /* The high PC value.  */\n  int have_highpc;\t\t/* Whether a high PC value was found.  */\n  int highpc_is_relative;\t/* Whether highpc is relative to lowpc.  */\n  int highpc_is_addr_index;\t/* Whether highpc is in .debug_addr.  */\n  uint64_t ranges;\t\t/* Offset in ranges section.  */\n  int have_ranges;\t\t/* Whether ranges is valid.  */\n  int ranges_is_index;\t\t/* Whether ranges is DW_FORM_rnglistx.  */\n};\n\n/* Update PCRANGE from an attribute value.  */\n\nstatic void\nupdate_pcrange (const struct attr* attr, const struct attr_val* val,\n\t\tstruct pcrange *pcrange)\n{\n  switch (attr->name)\n    {\n    case DW_AT_low_pc:\n      if (val->encoding == ATTR_VAL_ADDRESS)\n\t{\n\t  pcrange->lowpc = (uintptr_t) val->u.uint;\n\t  pcrange->have_lowpc = 1;\n\t}\n      else if (val->encoding == ATTR_VAL_ADDRESS_INDEX)\n\t{\n\t  pcrange->lowpc = (uintptr_t) val->u.uint;\n\t  pcrange->have_lowpc = 1;\n\t  pcrange->lowpc_is_addr_index = 1;\n\t}\n      break;\n\n    case DW_AT_high_pc:\n      if (val->encoding == ATTR_VAL_ADDRESS)\n\t{\n\t  pcrange->highpc = (uintptr_t) val->u.uint;\n\t  pcrange->have_highpc = 1;\n\t}\n      else if (val->encoding == ATTR_VAL_UINT)\n\t{\n\t  pcrange->highpc = (uintptr_t) val->u.uint;\n\t  pcrange->have_highpc = 1;\n\t  pcrange->highpc_is_relative = 1;\n\t}\n      else if (val->encoding == ATTR_VAL_ADDRESS_INDEX)\n\t{\n\t  pcrange->highpc = (uintptr_t) val->u.uint;\n\t  pcrange->have_highpc = 1;\n\t  pcrange->highpc_is_addr_index = 1;\n\t}\n      break;\n\n    case DW_AT_ranges:\n      if (val->encoding == ATTR_VAL_UINT\n\t  || val->encoding == ATTR_VAL_REF_SECTION)\n\t{\n\t  pcrange->ranges = val->u.uint;\n\t  pcrange->have_ranges = 1;\n\t}\n      else if (val->encoding == ATTR_VAL_RNGLISTS_INDEX)\n\t{\n\t  pcrange->ranges = val->u.uint;\n\t  pcrange->have_ranges = 1;\n\t  pcrange->ranges_is_index = 1;\n\t}\n      break;\n\n    default:\n      break;\n    }\n}\n\n/* Call ADD_RANGE for a low/high PC pair.  Returns 1 on success, 0 on\n  error.  */\n\nstatic int\nadd_low_high_range (struct backtrace_state *state,\n\t\t    const struct dwarf_sections *dwarf_sections,\n\t\t    struct libbacktrace_base_address base_address,\n\t\t    int is_bigendian, struct unit *u,\n\t\t    const struct pcrange *pcrange,\n\t\t    int (*add_range) (struct backtrace_state *state,\n\t\t\t\t      void *rdata, uintptr_t lowpc,\n\t\t\t\t      uintptr_t highpc,\n\t\t\t\t      backtrace_error_callback error_callback,\n\t\t\t\t      void *data, void *vec),\n\t\t    void *rdata,\n\t\t    backtrace_error_callback error_callback, void *data,\n\t\t    void *vec)\n{\n  uintptr_t lowpc;\n  uintptr_t highpc;\n\n  lowpc = pcrange->lowpc;\n  if (pcrange->lowpc_is_addr_index)\n    {\n      if (!resolve_addr_index (dwarf_sections, u->addr_base, u->addrsize,\n\t\t\t       is_bigendian, lowpc, error_callback, data,\n\t\t\t       &lowpc))\n\treturn 0;\n    }\n\n  highpc = pcrange->highpc;\n  if (pcrange->highpc_is_addr_index)\n    {\n      if (!resolve_addr_index (dwarf_sections, u->addr_base, u->addrsize,\n\t\t\t       is_bigendian, highpc, error_callback, data,\n\t\t\t       &highpc))\n\treturn 0;\n    }\n  if (pcrange->highpc_is_relative)\n    highpc += lowpc;\n\n  /* Add in the base address of the module when recording PC values,\n     so that we can look up the PC directly.  */\n  lowpc = libbacktrace_add_base (lowpc, base_address);\n  highpc = libbacktrace_add_base (highpc, base_address);\n\n  return add_range (state, rdata, lowpc, highpc, error_callback, data, vec);\n}\n\n/* Call ADD_RANGE for each range read from .debug_ranges, as used in\n   DWARF versions 2 through 4.  */\n\nstatic int\nadd_ranges_from_ranges (\n    struct backtrace_state *state,\n    const struct dwarf_sections *dwarf_sections,\n    struct libbacktrace_base_address base_address, int is_bigendian,\n    struct unit *u, uintptr_t base,\n    const struct pcrange *pcrange,\n    int (*add_range) (struct backtrace_state *state, void *rdata,\n\t\t      uintptr_t lowpc, uintptr_t highpc,\n\t\t      backtrace_error_callback error_callback, void *data,\n\t\t      void *vec),\n    void *rdata,\n    backtrace_error_callback error_callback, void *data,\n    void *vec)\n{\n  struct dwarf_buf ranges_buf;\n\n  if (pcrange->ranges >= dwarf_sections->size[DEBUG_RANGES])\n    {\n      error_callback (data, \"ranges offset out of range\", 0);\n      return 0;\n    }\n\n  ranges_buf.name = \".debug_ranges\";\n  ranges_buf.start = dwarf_sections->data[DEBUG_RANGES];\n  ranges_buf.buf = dwarf_sections->data[DEBUG_RANGES] + pcrange->ranges;\n  ranges_buf.left = dwarf_sections->size[DEBUG_RANGES] - pcrange->ranges;\n  ranges_buf.is_bigendian = is_bigendian;\n  ranges_buf.error_callback = error_callback;\n  ranges_buf.data = data;\n  ranges_buf.reported_underflow = 0;\n\n  while (1)\n    {\n      uint64_t low;\n      uint64_t high;\n\n      if (ranges_buf.reported_underflow)\n\treturn 0;\n\n      low = read_address (&ranges_buf, u->addrsize);\n      high = read_address (&ranges_buf, u->addrsize);\n\n      if (low == 0 && high == 0)\n\tbreak;\n\n      if (is_highest_address (low, u->addrsize))\n\tbase = (uintptr_t) high;\n      else\n\t{\n\t  uintptr_t rl, rh;\n\n\t  rl = libbacktrace_add_base ((uintptr_t) low + base, base_address);\n\t  rh = libbacktrace_add_base ((uintptr_t) high + base, base_address);\n\t  if (!add_range (state, rdata, rl, rh, error_callback, data, vec))\n\t    return 0;\n\t}\n    }\n\n  if (ranges_buf.reported_underflow)\n    return 0;\n\n  return 1;\n}\n\n/* Call ADD_RANGE for each range read from .debug_rnglists, as used in\n   DWARF version 5.  */\n\nstatic int\nadd_ranges_from_rnglists (\n    struct backtrace_state *state,\n    const struct dwarf_sections *dwarf_sections,\n    struct libbacktrace_base_address base_address, int is_bigendian,\n    struct unit *u, uintptr_t base,\n    const struct pcrange *pcrange,\n    int (*add_range) (struct backtrace_state *state, void *rdata,\n\t\t      uintptr_t lowpc, uintptr_t highpc,\n\t\t      backtrace_error_callback error_callback, void *data,\n\t\t      void *vec),\n    void *rdata,\n    backtrace_error_callback error_callback, void *data,\n    void *vec)\n{\n  uint64_t offset;\n  struct dwarf_buf rnglists_buf;\n\n  if (!pcrange->ranges_is_index)\n    offset = pcrange->ranges;\n  else\n    offset = u->rnglists_base + pcrange->ranges * (u->is_dwarf64 ? 8 : 4);\n  if (offset >= dwarf_sections->size[DEBUG_RNGLISTS])\n    {\n      error_callback (data, \"rnglists offset out of range\", 0);\n      return 0;\n    }\n\n  rnglists_buf.name = \".debug_rnglists\";\n  rnglists_buf.start = dwarf_sections->data[DEBUG_RNGLISTS];\n  rnglists_buf.buf = dwarf_sections->data[DEBUG_RNGLISTS] + offset;\n  rnglists_buf.left = dwarf_sections->size[DEBUG_RNGLISTS] - offset;\n  rnglists_buf.is_bigendian = is_bigendian;\n  rnglists_buf.error_callback = error_callback;\n  rnglists_buf.data = data;\n  rnglists_buf.reported_underflow = 0;\n\n  if (pcrange->ranges_is_index)\n    {\n      offset = read_offset (&rnglists_buf, u->is_dwarf64);\n      offset += u->rnglists_base;\n      if (offset >= dwarf_sections->size[DEBUG_RNGLISTS])\n\t{\n\t  error_callback (data, \"rnglists index offset out of range\", 0);\n\t  return 0;\n\t}\n      rnglists_buf.buf = dwarf_sections->data[DEBUG_RNGLISTS] + offset;\n      rnglists_buf.left = dwarf_sections->size[DEBUG_RNGLISTS] - offset;\n    }\n\n  while (1)\n    {\n      unsigned char rle;\n\n      rle = read_byte (&rnglists_buf);\n      if (rle == DW_RLE_end_of_list)\n\tbreak;\n      switch (rle)\n\t{\n\tcase DW_RLE_base_addressx:\n\t  {\n\t    uint64_t index;\n\n\t    index = read_uleb128 (&rnglists_buf);\n\t    if (!resolve_addr_index (dwarf_sections, u->addr_base,\n\t\t\t\t     u->addrsize, is_bigendian, index,\n\t\t\t\t     error_callback, data, &base))\n\t      return 0;\n\t  }\n\t  break;\n\n\tcase DW_RLE_startx_endx:\n\t  {\n\t    uint64_t index;\n\t    uintptr_t low;\n\t    uintptr_t high;\n\n\t    index = read_uleb128 (&rnglists_buf);\n\t    if (!resolve_addr_index (dwarf_sections, u->addr_base,\n\t\t\t\t     u->addrsize, is_bigendian, index,\n\t\t\t\t     error_callback, data, &low))\n\t      return 0;\n\t    index = read_uleb128 (&rnglists_buf);\n\t    if (!resolve_addr_index (dwarf_sections, u->addr_base,\n\t\t\t\t     u->addrsize, is_bigendian, index,\n\t\t\t\t     error_callback, data, &high))\n\t      return 0;\n\t    if (!add_range (state, rdata,\n\t\t\t    libbacktrace_add_base (low, base_address),\n\t\t\t    libbacktrace_add_base (high, base_address),\n\t\t\t    error_callback, data, vec))\n\t      return 0;\n\t  }\n\t  break;\n\n\tcase DW_RLE_startx_length:\n\t  {\n\t    uint64_t index;\n\t    uintptr_t low;\n\t    uintptr_t length;\n\n\t    index = read_uleb128 (&rnglists_buf);\n\t    if (!resolve_addr_index (dwarf_sections, u->addr_base,\n\t\t\t\t     u->addrsize, is_bigendian, index,\n\t\t\t\t     error_callback, data, &low))\n\t      return 0;\n\t    length = read_uleb128 (&rnglists_buf);\n\t    low = libbacktrace_add_base (low, base_address);\n\t    if (!add_range (state, rdata, low, low + length,\n\t\t\t    error_callback, data, vec))\n\t      return 0;\n\t  }\n\t  break;\n\n\tcase DW_RLE_offset_pair:\n\t  {\n\t    uint64_t low;\n\t    uint64_t high;\n\n\t    low = read_uleb128 (&rnglists_buf);\n\t    high = read_uleb128 (&rnglists_buf);\n\t    if (!add_range (state, rdata,\n\t\t\t    libbacktrace_add_base (low + base, base_address),\n\t\t\t    libbacktrace_add_base (high + base, base_address),\n\t\t\t    error_callback, data, vec))\n\t      return 0;\n\t  }\n\t  break;\n\n\tcase DW_RLE_base_address:\n\t  base = (uintptr_t) read_address (&rnglists_buf, u->addrsize);\n\t  break;\n\n\tcase DW_RLE_start_end:\n\t  {\n\t    uintptr_t low;\n\t    uintptr_t high;\n\n\t    low = (uintptr_t) read_address (&rnglists_buf, u->addrsize);\n\t    high = (uintptr_t) read_address (&rnglists_buf, u->addrsize);\n\t    if (!add_range (state, rdata,\n\t\t\t    libbacktrace_add_base (low, base_address),\n\t\t\t    libbacktrace_add_base (high, base_address),\n\t\t\t    error_callback, data, vec))\n\t      return 0;\n\t  }\n\t  break;\n\n\tcase DW_RLE_start_length:\n\t  {\n\t    uintptr_t low;\n\t    uintptr_t length;\n\n\t    low = (uintptr_t) read_address (&rnglists_buf, u->addrsize);\n\t    length = (uintptr_t) read_uleb128 (&rnglists_buf);\n\t    low = libbacktrace_add_base (low, base_address);\n\t    if (!add_range (state, rdata, low, low + length,\n\t\t\t    error_callback, data, vec))\n\t      return 0;\n\t  }\n\t  break;\n\n\tdefault:\n\t  dwarf_buf_error (&rnglists_buf, \"unrecognized DW_RLE value\", -1);\n\t  return 0;\n\t}\n    }\n\n  if (rnglists_buf.reported_underflow)\n    return 0;\n\n  return 1;\n}\n\n/* Call ADD_RANGE for each lowpc/highpc pair in PCRANGE.  RDATA is\n   passed to ADD_RANGE, and is either a struct unit * or a struct\n   function *.  VEC is the vector we are adding ranges to, and is\n   either a struct unit_addrs_vector * or a struct function_vector *.\n   Returns 1 on success, 0 on error.  */\n\nstatic int\nadd_ranges (struct backtrace_state *state,\n\t    const struct dwarf_sections *dwarf_sections,\n\t    struct libbacktrace_base_address base_address, int is_bigendian,\n\t    struct unit *u, uintptr_t base, const struct pcrange *pcrange,\n\t    int (*add_range) (struct backtrace_state *state, void *rdata,\n\t\t\t      uintptr_t lowpc, uintptr_t highpc,\n\t\t\t      backtrace_error_callback error_callback,\n\t\t\t      void *data, void *vec),\n\t    void *rdata,\n\t    backtrace_error_callback error_callback, void *data,\n\t    void *vec)\n{\n  if (pcrange->have_lowpc && pcrange->have_highpc)\n    return add_low_high_range (state, dwarf_sections, base_address,\n\t\t\t       is_bigendian, u, pcrange, add_range, rdata,\n\t\t\t       error_callback, data, vec);\n\n  if (!pcrange->have_ranges)\n    {\n      /* Did not find any address ranges to add.  */\n      return 1;\n    }\n\n  if (u->version < 5)\n    return add_ranges_from_ranges (state, dwarf_sections, base_address,\n\t\t\t\t   is_bigendian, u, base, pcrange, add_range,\n\t\t\t\t   rdata, error_callback, data, vec);\n  else\n    return add_ranges_from_rnglists (state, dwarf_sections, base_address,\n\t\t\t\t     is_bigendian, u, base, pcrange, add_range,\n\t\t\t\t     rdata, error_callback, data, vec);\n}\n\n/* Find the address range covered by a compilation unit, reading from\n   UNIT_BUF and adding values to U.  Returns 1 if all data could be\n   read, 0 if there is some error.  */\n\nstatic int\nfind_address_ranges (struct backtrace_state *state,\n\t\t     struct libbacktrace_base_address base_address,\n\t\t     struct dwarf_buf *unit_buf,\n\t\t     const struct dwarf_sections *dwarf_sections,\n\t\t     int is_bigendian, struct dwarf_data *altlink,\n\t\t     backtrace_error_callback error_callback, void *data,\n\t\t     struct unit *u, struct unit_addrs_vector *addrs,\n\t\t     enum dwarf_tag *unit_tag)\n{\n  while (unit_buf->left > 0)\n    {\n      uint64_t code;\n      const struct abbrev *abbrev;\n      struct pcrange pcrange;\n      struct attr_val name_val;\n      int have_name_val;\n      struct attr_val comp_dir_val;\n      int have_comp_dir_val;\n      size_t i;\n\n      code = read_uleb128 (unit_buf);\n      if (code == 0)\n\treturn 1;\n\n      abbrev = lookup_abbrev (&u->abbrevs, code, error_callback, data);\n      if (abbrev == NULL)\n\treturn 0;\n\n      if (unit_tag != NULL)\n\t*unit_tag = abbrev->tag;\n\n      memset (&pcrange, 0, sizeof pcrange);\n      memset (&name_val, 0, sizeof name_val);\n      have_name_val = 0;\n      memset (&comp_dir_val, 0, sizeof comp_dir_val);\n      have_comp_dir_val = 0;\n      for (i = 0; i < abbrev->num_attrs; ++i)\n\t{\n\t  struct attr_val val;\n\n\t  if (!read_attribute (abbrev->attrs[i].form, abbrev->attrs[i].val,\n\t\t\t       unit_buf, u->is_dwarf64, u->version,\n\t\t\t       u->addrsize, dwarf_sections, altlink, &val))\n\t    return 0;\n\n\t  switch (abbrev->attrs[i].name)\n\t    {\n\t    case DW_AT_low_pc: case DW_AT_high_pc: case DW_AT_ranges:\n\t      update_pcrange (&abbrev->attrs[i], &val, &pcrange);\n\t      break;\n\n\t    case DW_AT_stmt_list:\n\t      if ((abbrev->tag == DW_TAG_compile_unit\n\t\t   || abbrev->tag == DW_TAG_skeleton_unit)\n\t\t  && (val.encoding == ATTR_VAL_UINT\n\t\t      || val.encoding == ATTR_VAL_REF_SECTION))\n\t\tu->lineoff = val.u.uint;\n\t      break;\n\n\t    case DW_AT_name:\n\t      if (abbrev->tag == DW_TAG_compile_unit\n\t\t  || abbrev->tag == DW_TAG_skeleton_unit)\n\t\t{\n\t\t  name_val = val;\n\t\t  have_name_val = 1;\n\t\t}\n\t      break;\n\n\t    case DW_AT_comp_dir:\n\t      if (abbrev->tag == DW_TAG_compile_unit\n\t\t  || abbrev->tag == DW_TAG_skeleton_unit)\n\t\t{\n\t\t  comp_dir_val = val;\n\t\t  have_comp_dir_val = 1;\n\t\t}\n\t      break;\n\n\t    case DW_AT_str_offsets_base:\n\t      if ((abbrev->tag == DW_TAG_compile_unit\n\t\t   || abbrev->tag == DW_TAG_skeleton_unit)\n\t\t  && val.encoding == ATTR_VAL_REF_SECTION)\n\t\tu->str_offsets_base = val.u.uint;\n\t      break;\n\n\t    case DW_AT_addr_base:\n\t      if ((abbrev->tag == DW_TAG_compile_unit\n\t\t   || abbrev->tag == DW_TAG_skeleton_unit)\n\t\t  && val.encoding == ATTR_VAL_REF_SECTION)\n\t\tu->addr_base = val.u.uint;\n\t      break;\n\n\t    case DW_AT_rnglists_base:\n\t      if ((abbrev->tag == DW_TAG_compile_unit\n\t\t   || abbrev->tag == DW_TAG_skeleton_unit)\n\t\t  && val.encoding == ATTR_VAL_REF_SECTION)\n\t\tu->rnglists_base = val.u.uint;\n\t      break;\n\n\t    default:\n\t      break;\n\t    }\n\t}\n\n      // Resolve strings after we're sure that we have seen\n      // DW_AT_str_offsets_base.\n      if (have_name_val)\n\t{\n\t  if (!resolve_string (dwarf_sections, u->is_dwarf64, is_bigendian,\n\t\t\t       u->str_offsets_base, &name_val,\n\t\t\t       error_callback, data, &u->filename))\n\t    return 0;\n\t}\n      if (have_comp_dir_val)\n\t{\n\t  if (!resolve_string (dwarf_sections, u->is_dwarf64, is_bigendian,\n\t\t\t       u->str_offsets_base, &comp_dir_val,\n\t\t\t       error_callback, data, &u->comp_dir))\n\t    return 0;\n\t}\n\n      if (abbrev->tag == DW_TAG_compile_unit\n\t  || abbrev->tag == DW_TAG_subprogram\n\t  || abbrev->tag == DW_TAG_skeleton_unit)\n\t{\n\t  if (!add_ranges (state, dwarf_sections, base_address,\n\t\t\t   is_bigendian, u, pcrange.lowpc, &pcrange,\n\t\t\t   add_unit_addr, (void *) u, error_callback, data,\n\t\t\t   (void *) addrs))\n\t    return 0;\n\n\t  /* If we found the PC range in the DW_TAG_compile_unit or\n\t     DW_TAG_skeleton_unit, we can stop now.  */\n\t  if ((abbrev->tag == DW_TAG_compile_unit\n\t       || abbrev->tag == DW_TAG_skeleton_unit)\n\t      && (pcrange.have_ranges\n\t\t  || (pcrange.have_lowpc && pcrange.have_highpc)))\n\t    return 1;\n\t}\n\n      if (abbrev->has_children)\n\t{\n\t  if (!find_address_ranges (state, base_address, unit_buf,\n\t\t\t\t    dwarf_sections, is_bigendian, altlink,\n\t\t\t\t    error_callback, data, u, addrs, NULL))\n\t    return 0;\n\t}\n    }\n\n  return 1;\n}\n\n/* Build a mapping from address ranges to the compilation units where\n   the line number information for that range can be found.  Returns 1\n   on success, 0 on failure.  */\n\nstatic int\nbuild_address_map (struct backtrace_state *state,\n\t\t   struct libbacktrace_base_address base_address,\n\t\t   const struct dwarf_sections *dwarf_sections,\n\t\t   int is_bigendian, struct dwarf_data *altlink,\n\t\t   backtrace_error_callback error_callback, void *data,\n\t\t   struct unit_addrs_vector *addrs,\n\t\t   struct unit_vector *unit_vec)\n{\n  struct dwarf_buf info;\n  struct backtrace_vector units;\n  size_t units_count;\n  size_t i;\n  struct unit **pu;\n  size_t unit_offset = 0;\n  struct unit_addrs *pa;\n\n  memset (&addrs->vec, 0, sizeof addrs->vec);\n  memset (&unit_vec->vec, 0, sizeof unit_vec->vec);\n  addrs->count = 0;\n  unit_vec->count = 0;\n\n  /* Read through the .debug_info section.  FIXME: Should we use the\n     .debug_aranges section?  gdb and addr2line don't use it, but I'm\n     not sure why.  */\n\n  info.name = \".debug_info\";\n  info.start = dwarf_sections->data[DEBUG_INFO];\n  info.buf = info.start;\n  info.left = dwarf_sections->size[DEBUG_INFO];\n  info.is_bigendian = is_bigendian;\n  info.error_callback = error_callback;\n  info.data = data;\n  info.reported_underflow = 0;\n\n  memset (&units, 0, sizeof units);\n  units_count = 0;\n\n  while (info.left > 0)\n    {\n      const unsigned char *unit_data_start;\n      uint64_t len;\n      int is_dwarf64;\n      struct dwarf_buf unit_buf;\n      int version;\n      int unit_type;\n      uint64_t abbrev_offset;\n      int addrsize;\n      struct unit *u;\n      enum dwarf_tag unit_tag;\n\n      if (info.reported_underflow)\n\tgoto fail;\n\n      unit_data_start = info.buf;\n\n      len = read_initial_length (&info, &is_dwarf64);\n      unit_buf = info;\n      unit_buf.left = len;\n\n      if (!advance (&info, len))\n\tgoto fail;\n\n      version = read_uint16 (&unit_buf);\n      if (version < 2 || version > 5)\n\t{\n\t  dwarf_buf_error (&unit_buf, \"unrecognized DWARF version\", -1);\n\t  goto fail;\n\t}\n\n      if (version < 5)\n\tunit_type = 0;\n      else\n\t{\n\t  unit_type = read_byte (&unit_buf);\n\t  if (unit_type == DW_UT_type || unit_type == DW_UT_split_type)\n\t    {\n\t      /* This unit doesn't have anything we need.  */\n\t      continue;\n\t    }\n\t}\n\n      pu = ((struct unit **)\n\t    backtrace_vector_grow (state, sizeof (struct unit *),\n\t\t\t\t   error_callback, data, &units));\n      if (pu == NULL)\n\t  goto fail;\n\n      u = ((struct unit *)\n\t   backtrace_alloc (state, sizeof *u, error_callback, data));\n      if (u == NULL)\n\tgoto fail;\n\n      *pu = u;\n      ++units_count;\n\n      if (version < 5)\n\taddrsize = 0; /* Set below.  */\n      else\n\taddrsize = read_byte (&unit_buf);\n\n      memset (&u->abbrevs, 0, sizeof u->abbrevs);\n      abbrev_offset = read_offset (&unit_buf, is_dwarf64);\n      if (!read_abbrevs (state, abbrev_offset,\n\t\t\t dwarf_sections->data[DEBUG_ABBREV],\n\t\t\t dwarf_sections->size[DEBUG_ABBREV],\n\t\t\t is_bigendian, error_callback, data, &u->abbrevs))\n\tgoto fail;\n\n      if (version < 5)\n\taddrsize = read_byte (&unit_buf);\n\n      switch (unit_type)\n\t{\n\tcase 0:\n\t  break;\n\tcase DW_UT_compile: case DW_UT_partial:\n\t  break;\n\tcase DW_UT_skeleton: case DW_UT_split_compile:\n\t  read_uint64 (&unit_buf); /* dwo_id */\n\t  break;\n\tdefault:\n\t  break;\n\t}\n\n      u->low_offset = unit_offset;\n      unit_offset += len + (is_dwarf64 ? 12 : 4);\n      u->high_offset = unit_offset;\n      u->unit_data = unit_buf.buf;\n      u->unit_data_len = unit_buf.left;\n      u->unit_data_offset = unit_buf.buf - unit_data_start;\n      u->version = version;\n      u->is_dwarf64 = is_dwarf64;\n      u->addrsize = addrsize;\n      u->filename = NULL;\n      u->comp_dir = NULL;\n      u->abs_filename = NULL;\n      u->lineoff = 0;\n      u->str_offsets_base = 0;\n      u->addr_base = 0;\n      u->rnglists_base = 0;\n\n      /* The actual line number mappings will be read as needed.  */\n      u->lines = NULL;\n      u->lines_count = 0;\n      u->function_addrs = NULL;\n      u->function_addrs_count = 0;\n\n      if (!find_address_ranges (state, base_address, &unit_buf, dwarf_sections,\n\t\t\t\tis_bigendian, altlink, error_callback, data,\n\t\t\t\tu, addrs, &unit_tag))\n\tgoto fail;\n\n      if (unit_buf.reported_underflow)\n\tgoto fail;\n    }\n  if (info.reported_underflow)\n    goto fail;\n\n  /* Add a trailing addrs entry, but don't include it in addrs->count.  */\n  pa = ((struct unit_addrs *)\n\tbacktrace_vector_grow (state, sizeof (struct unit_addrs),\n\t\t\t       error_callback, data, &addrs->vec));\n  if (pa == NULL)\n    goto fail;\n  pa->low = 0;\n  --pa->low;\n  pa->high = pa->low;\n  pa->u = NULL;\n\n  unit_vec->vec = units;\n  unit_vec->count = units_count;\n  return 1;\n\n fail:\n  if (units_count > 0)\n    {\n      pu = (struct unit **) units.base;\n      for (i = 0; i < units_count; i++)\n\t{\n\t  free_abbrevs (state, &pu[i]->abbrevs, error_callback, data);\n\t  backtrace_free (state, pu[i], sizeof **pu, error_callback, data);\n\t}\n      backtrace_vector_free (state, &units, error_callback, data);\n    }\n  if (addrs->count > 0)\n    {\n      backtrace_vector_free (state, &addrs->vec, error_callback, data);\n      addrs->count = 0;\n    }\n  return 0;\n}\n\n/* Add a new mapping to the vector of line mappings that we are\n   building.  Returns 1 on success, 0 on failure.  */\n\nstatic int\nadd_line (struct backtrace_state *state, struct dwarf_data *ddata,\n\t  uintptr_t pc, const char *filename, int lineno,\n\t  backtrace_error_callback error_callback, void *data,\n\t  struct line_vector *vec)\n{\n  struct line *ln;\n\n  /* If we are adding the same mapping, ignore it.  This can happen\n     when using discriminators.  */\n  if (vec->count > 0)\n    {\n      ln = (struct line *) vec->vec.base + (vec->count - 1);\n      if (pc == ln->pc && filename == ln->filename && lineno == ln->lineno)\n\treturn 1;\n    }\n\n  ln = ((struct line *)\n\tbacktrace_vector_grow (state, sizeof (struct line), error_callback,\n\t\t\t       data, &vec->vec));\n  if (ln == NULL)\n    return 0;\n\n  /* Add in the base address here, so that we can look up the PC\n     directly.  */\n  ln->pc = libbacktrace_add_base (pc, ddata->base_address);\n\n  ln->filename = filename;\n  ln->lineno = lineno;\n  ln->idx = vec->count;\n\n  ++vec->count;\n\n  return 1;\n}\n\n/* Free the line header information.  */\n\nstatic void\nfree_line_header (struct backtrace_state *state, struct line_header *hdr,\n\t\t  backtrace_error_callback error_callback, void *data)\n{\n  if (hdr->dirs_count != 0)\n    backtrace_free (state, hdr->dirs, hdr->dirs_count * sizeof (const char *),\n\t\t    error_callback, data);\n  backtrace_free (state, hdr->filenames,\n\t\t  hdr->filenames_count * sizeof (char *),\n\t\t  error_callback, data);\n}\n\n/* Read the directories and file names for a line header for version\n   2, setting fields in HDR.  Return 1 on success, 0 on failure.  */\n\nstatic int\nread_v2_paths (struct backtrace_state *state, struct unit *u,\n\t       struct dwarf_buf *hdr_buf, struct line_header *hdr)\n{\n  const unsigned char *p;\n  const unsigned char *pend;\n  size_t i;\n\n  /* Count the number of directory entries.  */\n  hdr->dirs_count = 0;\n  p = hdr_buf->buf;\n  pend = p + hdr_buf->left;\n  while (p < pend && *p != '\\0')\n    {\n      p += strnlen((const char *) p, pend - p) + 1;\n      ++hdr->dirs_count;\n    }\n\n  /* The index of the first entry in the list of directories is 1.  Index 0 is\n     used for the current directory of the compilation.  To simplify index\n     handling, we set entry 0 to the compilation unit directory.  */\n  ++hdr->dirs_count;\n  hdr->dirs = ((const char **)\n\t       backtrace_alloc (state,\n\t\t\t\thdr->dirs_count * sizeof (const char *),\n\t\t\t\thdr_buf->error_callback,\n\t\t\t\thdr_buf->data));\n  if (hdr->dirs == NULL)\n    return 0;\n\n  hdr->dirs[0] = u->comp_dir;\n  i = 1;\n  while (*hdr_buf->buf != '\\0')\n    {\n      if (hdr_buf->reported_underflow)\n\treturn 0;\n\n      hdr->dirs[i] = read_string (hdr_buf);\n      if (hdr->dirs[i] == NULL)\n\treturn 0;\n      ++i;\n    }\n  if (!advance (hdr_buf, 1))\n    return 0;\n\n  /* Count the number of file entries.  */\n  hdr->filenames_count = 0;\n  p = hdr_buf->buf;\n  pend = p + hdr_buf->left;\n  while (p < pend && *p != '\\0')\n    {\n      p += strnlen ((const char *) p, pend - p) + 1;\n      p += leb128_len (p);\n      p += leb128_len (p);\n      p += leb128_len (p);\n      ++hdr->filenames_count;\n    }\n\n  /* The index of the first entry in the list of file names is 1.  Index 0 is\n     used for the DW_AT_name of the compilation unit.  To simplify index\n     handling, we set entry 0 to the compilation unit file name.  */\n  ++hdr->filenames_count;\n  hdr->filenames = ((const char **)\n\t\t    backtrace_alloc (state,\n\t\t\t\t     hdr->filenames_count * sizeof (char *),\n\t\t\t\t     hdr_buf->error_callback,\n\t\t\t\t     hdr_buf->data));\n  if (hdr->filenames == NULL)\n    return 0;\n  hdr->filenames[0] = u->filename;\n  i = 1;\n  while (*hdr_buf->buf != '\\0')\n    {\n      const char *filename;\n      uint64_t dir_index;\n\n      if (hdr_buf->reported_underflow)\n\treturn 0;\n\n      filename = read_string (hdr_buf);\n      if (filename == NULL)\n\treturn 0;\n      dir_index = read_uleb128 (hdr_buf);\n      if (IS_ABSOLUTE_PATH (filename)\n\t  || (dir_index < hdr->dirs_count && hdr->dirs[dir_index] == NULL))\n\thdr->filenames[i] = filename;\n      else\n\t{\n\t  const char *dir;\n\t  size_t dir_len;\n\t  size_t filename_len;\n\t  char *s;\n\n\t  if (dir_index < hdr->dirs_count)\n\t    dir = hdr->dirs[dir_index];\n\t  else\n\t    {\n\t      dwarf_buf_error (hdr_buf,\n\t\t\t       (\"invalid directory index in \"\n\t\t\t\t\"line number program header\"),\n\t\t\t       0);\n\t      return 0;\n\t    }\n\t  dir_len = strlen (dir);\n\t  filename_len = strlen (filename);\n\t  s = ((char *) backtrace_alloc (state, dir_len + filename_len + 2,\n\t\t\t\t\t hdr_buf->error_callback,\n\t\t\t\t\t hdr_buf->data));\n\t  if (s == NULL)\n\t    return 0;\n\t  memcpy (s, dir, dir_len);\n\t  /* FIXME: If we are on a DOS-based file system, and the\n\t     directory or the file name use backslashes, then we\n\t     should use a backslash here.  */\n\t  s[dir_len] = '/';\n\t  memcpy (s + dir_len + 1, filename, filename_len + 1);\n\t  hdr->filenames[i] = s;\n\t}\n\n      /* Ignore the modification time and size.  */\n      read_uleb128 (hdr_buf);\n      read_uleb128 (hdr_buf);\n\n      ++i;\n    }\n\n  return 1;\n}\n\n/* Read a single version 5 LNCT entry for a directory or file name in a\n   line header.  Sets *STRING to the resulting name, ignoring other\n   data.  Return 1 on success, 0 on failure.  */\n\nstatic int\nread_lnct (struct backtrace_state *state, struct dwarf_data *ddata,\n\t   struct unit *u, struct dwarf_buf *hdr_buf,\n\t   const struct line_header *hdr, size_t formats_count,\n\t   const struct line_header_format *formats, const char **string)\n{\n  size_t i;\n  const char *dir;\n  const char *path;\n\n  dir = NULL;\n  path = NULL;\n  for (i = 0; i < formats_count; i++)\n    {\n      struct attr_val val;\n\n      if (!read_attribute (formats[i].form, 0, hdr_buf, u->is_dwarf64,\n\t\t\t   u->version, hdr->addrsize, &ddata->dwarf_sections,\n\t\t\t   ddata->altlink, &val))\n\treturn 0;\n      switch (formats[i].lnct)\n\t{\n\tcase DW_LNCT_path:\n\t  if (!resolve_string (&ddata->dwarf_sections, u->is_dwarf64,\n\t\t\t       ddata->is_bigendian, u->str_offsets_base,\n\t\t\t       &val, hdr_buf->error_callback, hdr_buf->data,\n\t\t\t       &path))\n\t    return 0;\n\t  break;\n\tcase DW_LNCT_directory_index:\n\t  if (val.encoding == ATTR_VAL_UINT)\n\t    {\n\t      if (val.u.uint >= hdr->dirs_count)\n\t\t{\n\t\t  dwarf_buf_error (hdr_buf,\n\t\t\t\t   (\"invalid directory index in \"\n\t\t\t\t    \"line number program header\"),\n\t\t\t\t   0);\n\t\t  return 0;\n\t\t}\n\t      dir = hdr->dirs[val.u.uint];\n\t    }\n\t  break;\n\tdefault:\n\t  /* We don't care about timestamps or sizes or hashes.  */\n\t  break;\n\t}\n    }\n\n  if (path == NULL)\n    {\n      dwarf_buf_error (hdr_buf,\n\t\t       \"missing file name in line number program header\",\n\t\t       0);\n      return 0;\n    }\n\n  if (dir == NULL)\n    *string = path;\n  else\n    {\n      size_t dir_len;\n      size_t path_len;\n      char *s;\n\n      dir_len = strlen (dir);\n      path_len = strlen (path);\n      s = (char *) backtrace_alloc (state, dir_len + path_len + 2,\n\t\t\t\t    hdr_buf->error_callback, hdr_buf->data);\n      if (s == NULL)\n\treturn 0;\n      memcpy (s, dir, dir_len);\n      /* FIXME: If we are on a DOS-based file system, and the\n\t directory or the path name use backslashes, then we should\n\t use a backslash here.  */\n      s[dir_len] = '/';\n      memcpy (s + dir_len + 1, path, path_len + 1);\n      *string = s;\n    }\n\n  return 1;\n}\n\n/* Read a set of DWARF 5 line header format entries, setting *PCOUNT\n   and *PPATHS.  Return 1 on success, 0 on failure.  */\n\nstatic int\nread_line_header_format_entries (struct backtrace_state *state,\n\t\t\t\t struct dwarf_data *ddata,\n\t\t\t\t struct unit *u,\n\t\t\t\t struct dwarf_buf *hdr_buf,\n\t\t\t\t struct line_header *hdr,\n\t\t\t\t size_t *pcount,\n\t\t\t\t const char ***ppaths)\n{\n  size_t formats_count;\n  struct line_header_format *formats;\n  size_t paths_count;\n  const char **paths;\n  size_t i;\n  int ret;\n\n  formats_count = read_byte (hdr_buf);\n  if (formats_count == 0)\n    formats = NULL;\n  else\n    {\n      formats = ((struct line_header_format *)\n\t\t backtrace_alloc (state,\n\t\t\t\t  (formats_count\n\t\t\t\t   * sizeof (struct line_header_format)),\n\t\t\t\t  hdr_buf->error_callback,\n\t\t\t\t  hdr_buf->data));\n      if (formats == NULL)\n\treturn 0;\n\n      for (i = 0; i < formats_count; i++)\n\t{\n\t  formats[i].lnct = (int) read_uleb128(hdr_buf);\n\t  formats[i].form = (enum dwarf_form) read_uleb128 (hdr_buf);\n\t}\n    }\n\n  paths_count = read_uleb128 (hdr_buf);\n  if (paths_count == 0)\n    {\n      *pcount = 0;\n      *ppaths = NULL;\n      ret = 1;\n      goto exit;\n    }\n\n  paths = ((const char **)\n\t   backtrace_alloc (state, paths_count * sizeof (const char *),\n\t\t\t    hdr_buf->error_callback, hdr_buf->data));\n  if (paths == NULL)\n    {\n      ret = 0;\n      goto exit;\n    }\n  for (i = 0; i < paths_count; i++)\n    {\n      if (!read_lnct (state, ddata, u, hdr_buf, hdr, formats_count,\n\t\t      formats, &paths[i]))\n\t{\n\t  backtrace_free (state, paths,\n\t\t\t  paths_count * sizeof (const char *),\n\t\t\t  hdr_buf->error_callback, hdr_buf->data);\n\t  ret = 0;\n\t  goto exit;\n\t}\n    }\n\n  *pcount = paths_count;\n  *ppaths = paths;\n\n  ret = 1;\n\n exit:\n  if (formats != NULL)\n    backtrace_free (state, formats,\n\t\t    formats_count * sizeof (struct line_header_format),\n\t\t    hdr_buf->error_callback, hdr_buf->data);\n\n  return  ret;\n}\n\n/* Read the line header.  Return 1 on success, 0 on failure.  */\n\nstatic int\nread_line_header (struct backtrace_state *state, struct dwarf_data *ddata,\n\t\t  struct unit *u, int is_dwarf64, struct dwarf_buf *line_buf,\n\t\t  struct line_header *hdr)\n{\n  uint64_t hdrlen;\n  struct dwarf_buf hdr_buf;\n\n  hdr->version = read_uint16 (line_buf);\n  if (hdr->version < 2 || hdr->version > 5)\n    {\n      dwarf_buf_error (line_buf, \"unsupported line number version\", -1);\n      return 0;\n    }\n\n  if (hdr->version < 5)\n    hdr->addrsize = u->addrsize;\n  else\n    {\n      hdr->addrsize = read_byte (line_buf);\n      /* We could support a non-zero segment_selector_size but I doubt\n\t we'll ever see it.  */\n      if (read_byte (line_buf) != 0)\n\t{\n\t  dwarf_buf_error (line_buf,\n\t\t\t   \"non-zero segment_selector_size not supported\",\n\t\t\t   -1);\n\t  return 0;\n\t}\n    }\n\n  hdrlen = read_offset (line_buf, is_dwarf64);\n\n  hdr_buf = *line_buf;\n  hdr_buf.left = hdrlen;\n\n  if (!advance (line_buf, hdrlen))\n    return 0;\n\n  hdr->min_insn_len = read_byte (&hdr_buf);\n  if (hdr->version < 4)\n    hdr->max_ops_per_insn = 1;\n  else\n    hdr->max_ops_per_insn = read_byte (&hdr_buf);\n\n  /* We don't care about default_is_stmt.  */\n  read_byte (&hdr_buf);\n\n  hdr->line_base = read_sbyte (&hdr_buf);\n  hdr->line_range = read_byte (&hdr_buf);\n\n  hdr->opcode_base = read_byte (&hdr_buf);\n  hdr->opcode_lengths = hdr_buf.buf;\n  if (!advance (&hdr_buf, hdr->opcode_base - 1))\n    return 0;\n\n  if (hdr->version < 5)\n    {\n      if (!read_v2_paths (state, u, &hdr_buf, hdr))\n\treturn 0;\n    }\n  else\n    {\n      if (!read_line_header_format_entries (state, ddata, u, &hdr_buf, hdr,\n\t\t\t\t\t    &hdr->dirs_count,\n\t\t\t\t\t    &hdr->dirs))\n\treturn 0;\n      if (!read_line_header_format_entries (state, ddata, u, &hdr_buf, hdr,\n\t\t\t\t\t    &hdr->filenames_count,\n\t\t\t\t\t    &hdr->filenames))\n\treturn 0;\n    }\n\n  if (hdr_buf.reported_underflow)\n    return 0;\n\n  return 1;\n}\n\n/* Read the line program, adding line mappings to VEC.  Return 1 on\n   success, 0 on failure.  */\n\nstatic int\nread_line_program (struct backtrace_state *state, struct dwarf_data *ddata,\n\t\t   const struct line_header *hdr, struct dwarf_buf *line_buf,\n\t\t   struct line_vector *vec)\n{\n  uint64_t address;\n  unsigned int op_index;\n  const char *reset_filename;\n  const char *filename;\n  int lineno;\n\n  address = 0;\n  op_index = 0;\n  if (hdr->filenames_count > 1)\n    reset_filename = hdr->filenames[1];\n  else\n    reset_filename = \"\";\n  filename = reset_filename;\n  lineno = 1;\n  while (line_buf->left > 0)\n    {\n      unsigned int op;\n\n      op = read_byte (line_buf);\n      if (op >= hdr->opcode_base)\n\t{\n\t  unsigned int advance;\n\n\t  /* Special opcode.  */\n\t  op -= hdr->opcode_base;\n\t  advance = op / hdr->line_range;\n\t  address += (hdr->min_insn_len * (op_index + advance)\n\t\t      / hdr->max_ops_per_insn);\n\t  op_index = (op_index + advance) % hdr->max_ops_per_insn;\n\t  lineno += hdr->line_base + (int) (op % hdr->line_range);\n\t  add_line (state, ddata, address, filename, lineno,\n\t\t    line_buf->error_callback, line_buf->data, vec);\n\t}\n      else if (op == DW_LNS_extended_op)\n\t{\n\t  uint64_t len;\n\n\t  len = read_uleb128 (line_buf);\n\t  op = read_byte (line_buf);\n\t  switch (op)\n\t    {\n\t    case DW_LNE_end_sequence:\n\t      /* FIXME: Should we mark the high PC here?  It seems\n\t\t that we already have that information from the\n\t\t compilation unit.  */\n\t      address = 0;\n\t      op_index = 0;\n\t      filename = reset_filename;\n\t      lineno = 1;\n\t      break;\n\t    case DW_LNE_set_address:\n\t      address = read_address (line_buf, hdr->addrsize);\n\t      break;\n\t    case DW_LNE_define_file:\n\t      {\n\t\tconst char *f;\n\t\tunsigned int dir_index;\n\n\t\tf = read_string (line_buf);\n\t\tif (f == NULL)\n\t\t  return 0;\n\t\tdir_index = read_uleb128 (line_buf);\n\t\t/* Ignore that time and length.  */\n\t\tread_uleb128 (line_buf);\n\t\tread_uleb128 (line_buf);\n\t\tif (IS_ABSOLUTE_PATH (f))\n\t\t  filename = f;\n\t\telse\n\t\t  {\n\t\t    const char *dir;\n\t\t    size_t dir_len;\n\t\t    size_t f_len;\n\t\t    char *p;\n\n\t\t    if (dir_index < hdr->dirs_count)\n\t\t      dir = hdr->dirs[dir_index];\n\t\t    else\n\t\t      {\n\t\t\tdwarf_buf_error (line_buf,\n\t\t\t\t\t (\"invalid directory index \"\n\t\t\t\t\t  \"in line number program\"),\n\t\t\t\t\t 0);\n\t\t\treturn 0;\n\t\t      }\n\t\t    dir_len = strlen (dir);\n\t\t    f_len = strlen (f);\n\t\t    p = ((char *)\n\t\t\t backtrace_alloc (state, dir_len + f_len + 2,\n\t\t\t\t\t  line_buf->error_callback,\n\t\t\t\t\t  line_buf->data));\n\t\t    if (p == NULL)\n\t\t      return 0;\n\t\t    memcpy (p, dir, dir_len);\n\t\t    /* FIXME: If we are on a DOS-based file system,\n\t\t       and the directory or the file name use\n\t\t       backslashes, then we should use a backslash\n\t\t       here.  */\n\t\t    p[dir_len] = '/';\n\t\t    memcpy (p + dir_len + 1, f, f_len + 1);\n\t\t    filename = p;\n\t\t  }\n\t      }\n\t      break;\n\t    case DW_LNE_set_discriminator:\n\t      /* We don't care about discriminators.  */\n\t      read_uleb128 (line_buf);\n\t      break;\n\t    default:\n\t      if (!advance (line_buf, len - 1))\n\t\treturn 0;\n\t      break;\n\t    }\n\t}\n      else\n\t{\n\t  switch (op)\n\t    {\n\t    case DW_LNS_copy:\n\t      add_line (state, ddata, address, filename, lineno,\n\t\t\tline_buf->error_callback, line_buf->data, vec);\n\t      break;\n\t    case DW_LNS_advance_pc:\n\t      {\n\t\tuint64_t advance;\n\n\t\tadvance = read_uleb128 (line_buf);\n\t\taddress += (hdr->min_insn_len * (op_index + advance)\n\t\t\t    / hdr->max_ops_per_insn);\n\t\top_index = (op_index + advance) % hdr->max_ops_per_insn;\n\t      }\n\t      break;\n\t    case DW_LNS_advance_line:\n\t      lineno += (int) read_sleb128 (line_buf);\n\t      break;\n\t    case DW_LNS_set_file:\n\t      {\n\t\tuint64_t fileno;\n\n\t\tfileno = read_uleb128 (line_buf);\n\t\tif (fileno >= hdr->filenames_count)\n\t\t  {\n\t\t    dwarf_buf_error (line_buf,\n\t\t\t\t     (\"invalid file number in \"\n\t\t\t\t      \"line number program\"),\n\t\t\t\t     0);\n\t\t    return 0;\n\t\t  }\n\t\tfilename = hdr->filenames[fileno];\n\t      }\n\t      break;\n\t    case DW_LNS_set_column:\n\t      read_uleb128 (line_buf);\n\t      break;\n\t    case DW_LNS_negate_stmt:\n\t      break;\n\t    case DW_LNS_set_basic_block:\n\t      break;\n\t    case DW_LNS_const_add_pc:\n\t      {\n\t\tunsigned int advance;\n\n\t\top = 255 - hdr->opcode_base;\n\t\tadvance = op / hdr->line_range;\n\t\taddress += (hdr->min_insn_len * (op_index + advance)\n\t\t\t    / hdr->max_ops_per_insn);\n\t\top_index = (op_index + advance) % hdr->max_ops_per_insn;\n\t      }\n\t      break;\n\t    case DW_LNS_fixed_advance_pc:\n\t      address += read_uint16 (line_buf);\n\t      op_index = 0;\n\t      break;\n\t    case DW_LNS_set_prologue_end:\n\t      break;\n\t    case DW_LNS_set_epilogue_begin:\n\t      break;\n\t    case DW_LNS_set_isa:\n\t      read_uleb128 (line_buf);\n\t      break;\n\t    default:\n\t      {\n\t\tunsigned int i;\n\n\t\tfor (i = hdr->opcode_lengths[op - 1]; i > 0; --i)\n\t\t  read_uleb128 (line_buf);\n\t      }\n\t      break;\n\t    }\n\t}\n    }\n\n  return 1;\n}\n\n/* Read the line number information for a compilation unit.  Returns 1\n   on success, 0 on failure.  */\n\nstatic int\nread_line_info (struct backtrace_state *state, struct dwarf_data *ddata,\n\t\tbacktrace_error_callback error_callback, void *data,\n\t\tstruct unit *u, struct line_header *hdr, struct line **lines,\n\t\tsize_t *lines_count)\n{\n  struct line_vector vec;\n  struct dwarf_buf line_buf;\n  uint64_t len;\n  int is_dwarf64;\n  struct line *ln;\n\n  memset (&vec.vec, 0, sizeof vec.vec);\n  vec.count = 0;\n\n  memset (hdr, 0, sizeof *hdr);\n\n  if (u->lineoff != (off_t) (size_t) u->lineoff\n      || (size_t) u->lineoff >= ddata->dwarf_sections.size[DEBUG_LINE])\n    {\n      error_callback (data, \"unit line offset out of range\", 0);\n      goto fail;\n    }\n\n  line_buf.name = \".debug_line\";\n  line_buf.start = ddata->dwarf_sections.data[DEBUG_LINE];\n  line_buf.buf = ddata->dwarf_sections.data[DEBUG_LINE] + u->lineoff;\n  line_buf.left = ddata->dwarf_sections.size[DEBUG_LINE] - u->lineoff;\n  line_buf.is_bigendian = ddata->is_bigendian;\n  line_buf.error_callback = error_callback;\n  line_buf.data = data;\n  line_buf.reported_underflow = 0;\n\n  len = read_initial_length (&line_buf, &is_dwarf64);\n  line_buf.left = len;\n\n  if (!read_line_header (state, ddata, u, is_dwarf64, &line_buf, hdr))\n    goto fail;\n\n  if (!read_line_program (state, ddata, hdr, &line_buf, &vec))\n    goto fail;\n\n  if (line_buf.reported_underflow)\n    goto fail;\n\n  if (vec.count == 0)\n    {\n      /* This is not a failure in the sense of a generating an error,\n\t but it is a failure in that sense that we have no useful\n\t information.  */\n      goto fail;\n    }\n\n  /* Allocate one extra entry at the end.  */\n  ln = ((struct line *)\n\tbacktrace_vector_grow (state, sizeof (struct line), error_callback,\n\t\t\t       data, &vec.vec));\n  if (ln == NULL)\n    goto fail;\n  ln->pc = (uintptr_t) -1;\n  ln->filename = NULL;\n  ln->lineno = 0;\n  ln->idx = 0;\n\n  if (!backtrace_vector_release (state, &vec.vec, error_callback, data))\n    goto fail;\n\n  ln = (struct line *) vec.vec.base;\n  backtrace_qsort (ln, vec.count, sizeof (struct line), line_compare);\n\n  *lines = ln;\n  *lines_count = vec.count;\n\n  return 1;\n\n fail:\n  backtrace_vector_free (state, &vec.vec, error_callback, data);\n  free_line_header (state, hdr, error_callback, data);\n  *lines = (struct line *) (uintptr_t) -1;\n  *lines_count = 0;\n  return 0;\n}\n\nstatic const char *read_referenced_name (struct dwarf_data *, struct unit *,\n\t\t\t\t\t uint64_t, backtrace_error_callback,\n\t\t\t\t\t void *);\n\n/* Read the name of a function from a DIE referenced by ATTR with VAL.  */\n\nstatic const char *\nread_referenced_name_from_attr (struct dwarf_data *ddata, struct unit *u,\n\t\t\t\tstruct attr *attr, struct attr_val *val,\n\t\t\t\tbacktrace_error_callback error_callback,\n\t\t\t\tvoid *data)\n{\n  switch (attr->name)\n    {\n    case DW_AT_abstract_origin:\n    case DW_AT_specification:\n      break;\n    default:\n      return NULL;\n    }\n\n  if (attr->form == DW_FORM_ref_sig8)\n    return NULL;\n\n  if (val->encoding == ATTR_VAL_REF_INFO)\n    {\n      struct unit *unit\n\t= find_unit (ddata->units, ddata->units_count,\n\t\t     val->u.uint);\n      if (unit == NULL)\n\treturn NULL;\n\n      uint64_t offset = val->u.uint - unit->low_offset;\n      return read_referenced_name (ddata, unit, offset, error_callback, data);\n    }\n\n  if (val->encoding == ATTR_VAL_UINT\n      || val->encoding == ATTR_VAL_REF_UNIT)\n    return read_referenced_name (ddata, u, val->u.uint, error_callback, data);\n\n  if (val->encoding == ATTR_VAL_REF_ALT_INFO)\n    {\n      struct unit *alt_unit\n\t= find_unit (ddata->altlink->units, ddata->altlink->units_count,\n\t\t     val->u.uint);\n      if (alt_unit == NULL)\n\treturn NULL;\n\n      uint64_t offset = val->u.uint - alt_unit->low_offset;\n      return read_referenced_name (ddata->altlink, alt_unit, offset,\n\t\t\t\t   error_callback, data);\n    }\n\n  return NULL;\n}\n\n/* Read the name of a function from a DIE referenced by a\n   DW_AT_abstract_origin or DW_AT_specification tag.  OFFSET is within\n   the same compilation unit.  */\n\nstatic const char *\nread_referenced_name (struct dwarf_data *ddata, struct unit *u,\n\t\t      uint64_t offset, backtrace_error_callback error_callback,\n\t\t      void *data)\n{\n  struct dwarf_buf unit_buf;\n  uint64_t code;\n  const struct abbrev *abbrev;\n  const char *ret;\n  size_t i;\n\n  /* OFFSET is from the start of the data for this compilation unit.\n     U->unit_data is the data, but it starts U->unit_data_offset bytes\n     from the beginning.  */\n\n  if (offset < u->unit_data_offset\n      || offset - u->unit_data_offset >= u->unit_data_len)\n    {\n      error_callback (data,\n\t\t      \"abstract origin or specification out of range\",\n\t\t      0);\n      return NULL;\n    }\n\n  offset -= u->unit_data_offset;\n\n  unit_buf.name = \".debug_info\";\n  unit_buf.start = ddata->dwarf_sections.data[DEBUG_INFO];\n  unit_buf.buf = u->unit_data + offset;\n  unit_buf.left = u->unit_data_len - offset;\n  unit_buf.is_bigendian = ddata->is_bigendian;\n  unit_buf.error_callback = error_callback;\n  unit_buf.data = data;\n  unit_buf.reported_underflow = 0;\n\n  code = read_uleb128 (&unit_buf);\n  if (code == 0)\n    {\n      dwarf_buf_error (&unit_buf,\n\t\t       \"invalid abstract origin or specification\",\n\t\t       0);\n      return NULL;\n    }\n\n  abbrev = lookup_abbrev (&u->abbrevs, code, error_callback, data);\n  if (abbrev == NULL)\n    return NULL;\n\n  ret = NULL;\n  for (i = 0; i < abbrev->num_attrs; ++i)\n    {\n      struct attr_val val;\n\n      if (!read_attribute (abbrev->attrs[i].form, abbrev->attrs[i].val,\n\t\t\t   &unit_buf, u->is_dwarf64, u->version, u->addrsize,\n\t\t\t   &ddata->dwarf_sections, ddata->altlink, &val))\n\treturn NULL;\n\n      switch (abbrev->attrs[i].name)\n\t{\n\tcase DW_AT_name:\n\t  /* Third name preference: don't override.  A name we found in some\n\t     other way, will normally be more useful -- e.g., this name is\n\t     normally not mangled.  */\n\t  if (ret != NULL)\n\t    break;\n\t  if (!resolve_string (&ddata->dwarf_sections, u->is_dwarf64,\n\t\t\t       ddata->is_bigendian, u->str_offsets_base,\n\t\t\t       &val, error_callback, data, &ret))\n\t    return NULL;\n\t  break;\n\n\tcase DW_AT_linkage_name:\n\tcase DW_AT_MIPS_linkage_name:\n\t  /* First name preference: override all.  */\n\t  {\n\t    const char *s;\n\n\t    s = NULL;\n\t    if (!resolve_string (&ddata->dwarf_sections, u->is_dwarf64,\n\t\t\t\t ddata->is_bigendian, u->str_offsets_base,\n\t\t\t\t &val, error_callback, data, &s))\n\t      return NULL;\n\t    if (s != NULL)\n\t      return s;\n\t  }\n\t  break;\n\n\tcase DW_AT_specification:\n\t  /* Second name preference: override DW_AT_name, don't override\n\t     DW_AT_linkage_name.  */\n\t  {\n\t    const char *name;\n\n\t    name = read_referenced_name_from_attr (ddata, u, &abbrev->attrs[i],\n\t\t\t\t\t\t   &val, error_callback, data);\n\t    if (name != NULL)\n\t      ret = name;\n\t  }\n\t  break;\n\n\tdefault:\n\t  break;\n\t}\n    }\n\n  return ret;\n}\n\n/* Add a range to a unit that maps to a function.  This is called via\n   add_ranges.  Returns 1 on success, 0 on error.  */\n\nstatic int\nadd_function_range (struct backtrace_state *state, void *rdata,\n\t\t    uintptr_t lowpc, uintptr_t highpc,\n\t\t    backtrace_error_callback error_callback, void *data,\n\t\t    void *pvec)\n{\n  struct function *function = (struct function *) rdata;\n  struct function_vector *vec = (struct function_vector *) pvec;\n  struct function_addrs *p;\n\n  if (vec->count > 0)\n    {\n      p = (struct function_addrs *) vec->vec.base + (vec->count - 1);\n      if ((lowpc == p->high || lowpc == p->high + 1)\n\t  && function == p->function)\n\t{\n\t  if (highpc > p->high)\n\t    p->high = highpc;\n\t  return 1;\n\t}\n    }\n\n  p = ((struct function_addrs *)\n       backtrace_vector_grow (state, sizeof (struct function_addrs),\n\t\t\t      error_callback, data, &vec->vec));\n  if (p == NULL)\n    return 0;\n\n  p->low = lowpc;\n  p->high = highpc;\n  p->function = function;\n\n  ++vec->count;\n\n  return 1;\n}\n\n/* Read one entry plus all its children.  Add function addresses to\n   VEC.  Returns 1 on success, 0 on error.  */\n\nstatic int\nread_function_entry (struct backtrace_state *state, struct dwarf_data *ddata,\n\t\t     struct unit *u, uintptr_t base, struct dwarf_buf *unit_buf,\n\t\t     const struct line_header *lhdr,\n\t\t     backtrace_error_callback error_callback, void *data,\n\t\t     struct function_vector *vec_function,\n\t\t     struct function_vector *vec_inlined)\n{\n  while (unit_buf->left > 0)\n    {\n      uint64_t code;\n      const struct abbrev *abbrev;\n      int is_function;\n      struct function *function;\n      struct function_vector *vec;\n      size_t i;\n      struct pcrange pcrange;\n      int have_linkage_name;\n\n      code = read_uleb128 (unit_buf);\n      if (code == 0)\n\treturn 1;\n\n      abbrev = lookup_abbrev (&u->abbrevs, code, error_callback, data);\n      if (abbrev == NULL)\n\treturn 0;\n\n      is_function = (abbrev->tag == DW_TAG_subprogram\n\t\t     || abbrev->tag == DW_TAG_entry_point\n\t\t     || abbrev->tag == DW_TAG_inlined_subroutine);\n\n      if (abbrev->tag == DW_TAG_inlined_subroutine)\n\tvec = vec_inlined;\n      else\n\tvec = vec_function;\n\n      function = NULL;\n      if (is_function)\n\t{\n\t  function = ((struct function *)\n\t\t      backtrace_alloc (state, sizeof *function,\n\t\t\t\t       error_callback, data));\n\t  if (function == NULL)\n\t    return 0;\n\t  memset (function, 0, sizeof *function);\n\t}\n\n      memset (&pcrange, 0, sizeof pcrange);\n      have_linkage_name = 0;\n      for (i = 0; i < abbrev->num_attrs; ++i)\n\t{\n\t  struct attr_val val;\n\n\t  if (!read_attribute (abbrev->attrs[i].form, abbrev->attrs[i].val,\n\t\t\t       unit_buf, u->is_dwarf64, u->version,\n\t\t\t       u->addrsize, &ddata->dwarf_sections,\n\t\t\t       ddata->altlink, &val))\n\t    return 0;\n\n\t  /* The compile unit sets the base address for any address\n\t     ranges in the function entries.  */\n\t  if ((abbrev->tag == DW_TAG_compile_unit\n\t       || abbrev->tag == DW_TAG_skeleton_unit)\n\t      && abbrev->attrs[i].name == DW_AT_low_pc)\n\t    {\n\t      if (val.encoding == ATTR_VAL_ADDRESS)\n\t\tbase = (uintptr_t) val.u.uint;\n\t      else if (val.encoding == ATTR_VAL_ADDRESS_INDEX)\n\t\t{\n\t\t  if (!resolve_addr_index (&ddata->dwarf_sections,\n\t\t\t\t\t   u->addr_base, u->addrsize,\n\t\t\t\t\t   ddata->is_bigendian, val.u.uint,\n\t\t\t\t\t   error_callback, data, &base))\n\t\t    return 0;\n\t\t}\n\t    }\n\n\t  if (is_function)\n\t    {\n\t      switch (abbrev->attrs[i].name)\n\t\t{\n\t\tcase DW_AT_call_file:\n\t\t  if (val.encoding == ATTR_VAL_UINT)\n\t\t    {\n\t\t      if (val.u.uint >= lhdr->filenames_count)\n\t\t\t{\n\t\t\t  dwarf_buf_error (unit_buf,\n\t\t\t\t\t   (\"invalid file number in \"\n\t\t\t\t\t    \"DW_AT_call_file attribute\"),\n\t\t\t\t\t   0);\n\t\t\t  return 0;\n\t\t\t}\n\t\t      function->caller_filename = lhdr->filenames[val.u.uint];\n\t\t    }\n\t\t  break;\n\n\t\tcase DW_AT_call_line:\n\t\t  if (val.encoding == ATTR_VAL_UINT)\n\t\t    function->caller_lineno = val.u.uint;\n\t\t  break;\n\n\t\tcase DW_AT_abstract_origin:\n\t\tcase DW_AT_specification:\n\t\t  /* Second name preference: override DW_AT_name, don't override\n\t\t     DW_AT_linkage_name.  */\n\t\t  if (have_linkage_name)\n\t\t    break;\n\t\t  {\n\t\t    const char *name;\n\n\t\t    name\n\t\t      = read_referenced_name_from_attr (ddata, u,\n\t\t\t\t\t\t\t&abbrev->attrs[i], &val,\n\t\t\t\t\t\t\terror_callback, data);\n\t\t    if (name != NULL)\n\t\t      function->name = name;\n\t\t  }\n\t\t  break;\n\n\t\tcase DW_AT_name:\n\t\t  /* Third name preference: don't override.  */\n\t\t  if (function->name != NULL)\n\t\t    break;\n\t\t  if (!resolve_string (&ddata->dwarf_sections, u->is_dwarf64,\n\t\t\t\t       ddata->is_bigendian,\n\t\t\t\t       u->str_offsets_base, &val,\n\t\t\t\t       error_callback, data, &function->name))\n\t\t    return 0;\n\t\t  break;\n\n\t\tcase DW_AT_linkage_name:\n\t\tcase DW_AT_MIPS_linkage_name:\n\t\t  /* First name preference: override all.  */\n\t\t  {\n\t\t    const char *s;\n\n\t\t    s = NULL;\n\t\t    if (!resolve_string (&ddata->dwarf_sections, u->is_dwarf64,\n\t\t\t\t\t ddata->is_bigendian,\n\t\t\t\t\t u->str_offsets_base, &val,\n\t\t\t\t\t error_callback, data, &s))\n\t\t      return 0;\n\t\t    if (s != NULL)\n\t\t      {\n\t\t\tfunction->name = s;\n\t\t\thave_linkage_name = 1;\n\t\t      }\n\t\t  }\n\t\t  break;\n\n\t\tcase DW_AT_low_pc: case DW_AT_high_pc: case DW_AT_ranges:\n\t\t  update_pcrange (&abbrev->attrs[i], &val, &pcrange);\n\t\t  break;\n\n\t\tdefault:\n\t\t  break;\n\t\t}\n\t    }\n\t}\n\n      /* If we couldn't find a name for the function, we have no use\n\t for it.  */\n      if (is_function && function->name == NULL)\n\t{\n\t  backtrace_free (state, function, sizeof *function,\n\t\t\t  error_callback, data);\n\t  is_function = 0;\n\t}\n\n      if (is_function)\n\t{\n\t  if (pcrange.have_ranges\n\t      || (pcrange.have_lowpc && pcrange.have_highpc))\n\t    {\n\t      if (!add_ranges (state, &ddata->dwarf_sections,\n\t\t\t       ddata->base_address, ddata->is_bigendian,\n\t\t\t       u, base, &pcrange, add_function_range,\n\t\t\t       (void *) function, error_callback, data,\n\t\t\t       (void *) vec))\n\t\treturn 0;\n\t    }\n\t  else\n\t    {\n\t      backtrace_free (state, function, sizeof *function,\n\t\t\t      error_callback, data);\n\t      is_function = 0;\n\t    }\n\t}\n\n      if (abbrev->has_children)\n\t{\n\t  if (!is_function)\n\t    {\n\t      if (!read_function_entry (state, ddata, u, base, unit_buf, lhdr,\n\t\t\t\t\terror_callback, data, vec_function,\n\t\t\t\t\tvec_inlined))\n\t\treturn 0;\n\t    }\n\t  else\n\t    {\n\t      struct function_vector fvec;\n\n\t      /* Gather any information for inlined functions in\n\t\t FVEC.  */\n\n\t      memset (&fvec, 0, sizeof fvec);\n\n\t      if (!read_function_entry (state, ddata, u, base, unit_buf, lhdr,\n\t\t\t\t\terror_callback, data, vec_function,\n\t\t\t\t\t&fvec))\n\t\treturn 0;\n\n\t      if (fvec.count > 0)\n\t\t{\n\t\t  struct function_addrs *p;\n\t\t  struct function_addrs *faddrs;\n\n\t\t  /* Allocate a trailing entry, but don't include it\n\t\t     in fvec.count.  */\n\t\t  p = ((struct function_addrs *)\n\t\t       backtrace_vector_grow (state,\n\t\t\t\t\t      sizeof (struct function_addrs),\n\t\t\t\t\t      error_callback, data,\n\t\t\t\t\t      &fvec.vec));\n\t\t  if (p == NULL)\n\t\t    return 0;\n\t\t  p->low = 0;\n\t\t  --p->low;\n\t\t  p->high = p->low;\n\t\t  p->function = NULL;\n\n\t\t  if (!backtrace_vector_release (state, &fvec.vec,\n\t\t\t\t\t\t error_callback, data))\n\t\t    return 0;\n\n\t\t  faddrs = (struct function_addrs *) fvec.vec.base;\n\t\t  backtrace_qsort (faddrs, fvec.count,\n\t\t\t\t   sizeof (struct function_addrs),\n\t\t\t\t   function_addrs_compare);\n\n\t\t  function->function_addrs = faddrs;\n\t\t  function->function_addrs_count = fvec.count;\n\t\t}\n\t    }\n\t}\n    }\n\n  return 1;\n}\n\n/* Read function name information for a compilation unit.  We look\n   through the whole unit looking for function tags.  */\n\nstatic void\nread_function_info (struct backtrace_state *state, struct dwarf_data *ddata,\n\t\t    const struct line_header *lhdr,\n\t\t    backtrace_error_callback error_callback, void *data,\n\t\t    struct unit *u, struct function_vector *fvec,\n\t\t    struct function_addrs **ret_addrs,\n\t\t    size_t *ret_addrs_count)\n{\n  struct function_vector lvec;\n  struct function_vector *pfvec;\n  struct dwarf_buf unit_buf;\n  struct function_addrs *p;\n  struct function_addrs *addrs;\n  size_t addrs_count;\n\n  /* Use FVEC if it is not NULL.  Otherwise use our own vector.  */\n  if (fvec != NULL)\n    pfvec = fvec;\n  else\n    {\n      memset (&lvec, 0, sizeof lvec);\n      pfvec = &lvec;\n    }\n\n  unit_buf.name = \".debug_info\";\n  unit_buf.start = ddata->dwarf_sections.data[DEBUG_INFO];\n  unit_buf.buf = u->unit_data;\n  unit_buf.left = u->unit_data_len;\n  unit_buf.is_bigendian = ddata->is_bigendian;\n  unit_buf.error_callback = error_callback;\n  unit_buf.data = data;\n  unit_buf.reported_underflow = 0;\n\n  while (unit_buf.left > 0)\n    {\n      if (!read_function_entry (state, ddata, u, 0, &unit_buf, lhdr,\n\t\t\t\terror_callback, data, pfvec, pfvec))\n\treturn;\n    }\n\n  if (pfvec->count == 0)\n    return;\n\n  /* Allocate a trailing entry, but don't include it in\n     pfvec->count.  */\n  p = ((struct function_addrs *)\n       backtrace_vector_grow (state, sizeof (struct function_addrs),\n\t\t\t      error_callback, data, &pfvec->vec));\n  if (p == NULL)\n    return;\n  p->low = 0;\n  --p->low;\n  p->high = p->low;\n  p->function = NULL;\n\n  addrs_count = pfvec->count;\n\n  if (fvec == NULL)\n    {\n      if (!backtrace_vector_release (state, &lvec.vec, error_callback, data))\n\treturn;\n      addrs = (struct function_addrs *) pfvec->vec.base;\n    }\n  else\n    {\n      /* Finish this list of addresses, but leave the remaining space in\n\t the vector available for the next function unit.  */\n      addrs = ((struct function_addrs *)\n\t       backtrace_vector_finish (state, &fvec->vec,\n\t\t\t\t\terror_callback, data));\n      if (addrs == NULL)\n\treturn;\n      fvec->count = 0;\n    }\n\n  backtrace_qsort (addrs, addrs_count, sizeof (struct function_addrs),\n\t\t   function_addrs_compare);\n\n  *ret_addrs = addrs;\n  *ret_addrs_count = addrs_count;\n}\n\n/* See if PC is inlined in FUNCTION.  If it is, print out the inlined\n   information, and update FILENAME and LINENO for the caller.\n   Returns whatever CALLBACK returns, or 0 to keep going.  */\n\nstatic int\nreport_inlined_functions (uintptr_t pc, struct function *function,\n\t\t\t  backtrace_full_callback callback, void *data,\n\t\t\t  const char **filename, int *lineno)\n{\n  struct function_addrs *p;\n  struct function_addrs *match;\n  struct function *inlined;\n  int ret;\n\n  if (function->function_addrs_count == 0)\n    return 0;\n\n  /* Our search isn't safe if pc == -1, as that is the sentinel\n     value.  */\n  if (pc + 1 == 0)\n    return 0;\n\n  p = ((struct function_addrs *)\n       bsearch (&pc, function->function_addrs,\n\t\tfunction->function_addrs_count,\n\t\tsizeof (struct function_addrs),\n\t\tfunction_addrs_search));\n  if (p == NULL)\n    return 0;\n\n  /* Here pc >= p->low && pc < (p + 1)->low.  The function_addrs are\n     sorted by low, so if pc > p->low we are at the end of a range of\n     function_addrs with the same low value.  If pc == p->low walk\n     forward to the end of the range with that low value.  Then walk\n     backward and use the first range that includes pc.  */\n  while (pc == (p + 1)->low)\n    ++p;\n  match = NULL;\n  while (1)\n    {\n      if (pc < p->high)\n\t{\n\t  match = p;\n\t  break;\n\t}\n      if (p == function->function_addrs)\n\tbreak;\n      if ((p - 1)->low < p->low)\n\tbreak;\n      --p;\n    }\n  if (match == NULL)\n    return 0;\n\n  /* We found an inlined call.  */\n\n  inlined = match->function;\n\n  /* Report any calls inlined into this one.  */\n  ret = report_inlined_functions (pc, inlined, callback, data,\n\t\t\t\t  filename, lineno);\n  if (ret != 0)\n    return ret;\n\n  /* Report this inlined call.  */\n  ret = callback (data, pc, *filename, *lineno, inlined->name);\n  if (ret != 0)\n    return ret;\n\n  /* Our caller will report the caller of the inlined function; tell\n     it the appropriate filename and line number.  */\n  *filename = inlined->caller_filename;\n  *lineno = inlined->caller_lineno;\n\n  return 0;\n}\n\n/* Look for a PC in the DWARF mapping for one module.  On success,\n   call CALLBACK and return whatever it returns.  On error, call\n   ERROR_CALLBACK and return 0.  Sets *FOUND to 1 if the PC is found,\n   0 if not.  */\n\nstatic int\ndwarf_lookup_pc (struct backtrace_state *state, struct dwarf_data *ddata,\n\t\t uintptr_t pc, backtrace_full_callback callback,\n\t\t backtrace_error_callback error_callback, void *data,\n\t\t int *found)\n{\n  struct unit_addrs *entry;\n  int found_entry;\n  struct unit *u;\n  int new_data;\n  struct line *lines;\n  struct line *ln;\n  struct function_addrs *p;\n  struct function_addrs *fmatch;\n  struct function *function;\n  const char *filename;\n  int lineno;\n  int ret;\n\n  *found = 1;\n\n  /* Find an address range that includes PC.  Our search isn't safe if\n     PC == -1, as we use that as a sentinel value, so skip the search\n     in that case.  */\n  entry = (ddata->addrs_count == 0 || pc + 1 == 0\n\t   ? NULL\n\t   : bsearch (&pc, ddata->addrs, ddata->addrs_count,\n\t\t      sizeof (struct unit_addrs), unit_addrs_search));\n\n  if (entry == NULL)\n    {\n      *found = 0;\n      return 0;\n    }\n\n  /* Here pc >= entry->low && pc < (entry + 1)->low.  The unit_addrs\n     are sorted by low, so if pc > p->low we are at the end of a range\n     of unit_addrs with the same low value.  If pc == p->low walk\n     forward to the end of the range with that low value.  Then walk\n     backward and use the first range that includes pc.  */\n  while (pc == (entry + 1)->low)\n    ++entry;\n  found_entry = 0;\n  while (1)\n    {\n      if (pc < entry->high)\n\t{\n\t  found_entry = 1;\n\t  break;\n\t}\n      if (entry == ddata->addrs)\n\tbreak;\n      if ((entry - 1)->low < entry->low)\n\tbreak;\n      --entry;\n    }\n  if (!found_entry)\n    {\n      *found = 0;\n      return 0;\n    }\n\n  /* We need the lines, lines_count, function_addrs,\n     function_addrs_count fields of u.  If they are not set, we need\n     to set them.  When running in threaded mode, we need to allow for\n     the possibility that some other thread is setting them\n     simultaneously.  */\n\n  u = entry->u;\n  lines = u->lines;\n\n  /* Skip units with no useful line number information by walking\n     backward.  Useless line number information is marked by setting\n     lines == -1.  */\n  while (entry > ddata->addrs\n\t && pc >= (entry - 1)->low\n\t && pc < (entry - 1)->high)\n    {\n      if (state->threaded)\n\tlines = (struct line *) backtrace_atomic_load_pointer (&u->lines);\n\n      if (lines != (struct line *) (uintptr_t) -1)\n\tbreak;\n\n      --entry;\n\n      u = entry->u;\n      lines = u->lines;\n    }\n\n  if (state->threaded)\n    lines = backtrace_atomic_load_pointer (&u->lines);\n\n  new_data = 0;\n  if (lines == NULL)\n    {\n      struct function_addrs *function_addrs;\n      size_t function_addrs_count;\n      struct line_header lhdr;\n      size_t count;\n\n      /* We have never read the line information for this unit.  Read\n\t it now.  */\n\n      function_addrs = NULL;\n      function_addrs_count = 0;\n      if (read_line_info (state, ddata, error_callback, data, entry->u, &lhdr,\n\t\t\t  &lines, &count))\n\t{\n\t  struct function_vector *pfvec;\n\n\t  /* If not threaded, reuse DDATA->FVEC for better memory\n\t     consumption.  */\n\t  if (state->threaded)\n\t    pfvec = NULL;\n\t  else\n\t    pfvec = &ddata->fvec;\n\t  read_function_info (state, ddata, &lhdr, error_callback, data,\n\t\t\t      entry->u, pfvec, &function_addrs,\n\t\t\t      &function_addrs_count);\n\t  free_line_header (state, &lhdr, error_callback, data);\n\t  new_data = 1;\n\t}\n\n      /* Atomically store the information we just read into the unit.\n\t If another thread is simultaneously writing, it presumably\n\t read the same information, and we don't care which one we\n\t wind up with; we just leak the other one.  We do have to\n\t write the lines field last, so that the acquire-loads above\n\t ensure that the other fields are set.  */\n\n      if (!state->threaded)\n\t{\n\t  u->lines_count = count;\n\t  u->function_addrs = function_addrs;\n\t  u->function_addrs_count = function_addrs_count;\n\t  u->lines = lines;\n\t}\n      else\n\t{\n\t  backtrace_atomic_store_size_t (&u->lines_count, count);\n\t  backtrace_atomic_store_pointer (&u->function_addrs, function_addrs);\n\t  backtrace_atomic_store_size_t (&u->function_addrs_count,\n\t\t\t\t\t function_addrs_count);\n\t  backtrace_atomic_store_pointer (&u->lines, lines);\n\t}\n    }\n\n  /* Now all fields of U have been initialized.  */\n\n  if (lines == (struct line *) (uintptr_t) -1)\n    {\n      /* If reading the line number information failed in some way,\n\t try again to see if there is a better compilation unit for\n\t this PC.  */\n      if (new_data)\n\treturn dwarf_lookup_pc (state, ddata, pc, callback, error_callback,\n\t\t\t\tdata, found);\n      return callback (data, pc, NULL, 0, NULL);\n    }\n\n  /* Search for PC within this unit.  */\n\n  ln = (struct line *) bsearch (&pc, lines, entry->u->lines_count,\n\t\t\t\tsizeof (struct line), line_search);\n  if (ln == NULL)\n    {\n      /* The PC is between the low_pc and high_pc attributes of the\n\t compilation unit, but no entry in the line table covers it.\n\t This implies that the start of the compilation unit has no\n\t line number information.  */\n\n      if (entry->u->abs_filename == NULL)\n\t{\n\t  const char *filename;\n\n\t  filename = entry->u->filename;\n\t  if (filename != NULL\n\t      && !IS_ABSOLUTE_PATH (filename)\n\t      && entry->u->comp_dir != NULL)\n\t    {\n\t      size_t filename_len;\n\t      const char *dir;\n\t      size_t dir_len;\n\t      char *s;\n\n\t      filename_len = strlen (filename);\n\t      dir = entry->u->comp_dir;\n\t      dir_len = strlen (dir);\n\t      s = (char *) backtrace_alloc (state, dir_len + filename_len + 2,\n\t\t\t\t\t    error_callback, data);\n\t      if (s == NULL)\n\t\t{\n\t\t  *found = 0;\n\t\t  return 0;\n\t\t}\n\t      memcpy (s, dir, dir_len);\n\t      /* FIXME: Should use backslash if DOS file system.  */\n\t      s[dir_len] = '/';\n\t      memcpy (s + dir_len + 1, filename, filename_len + 1);\n\t      filename = s;\n\t    }\n\t  entry->u->abs_filename = filename;\n\t}\n\n      return callback (data, pc, entry->u->abs_filename, 0, NULL);\n    }\n\n  /* Search for function name within this unit.  */\n\n  if (entry->u->function_addrs_count == 0)\n    return callback (data, pc, ln->filename, ln->lineno, NULL);\n\n  p = ((struct function_addrs *)\n       bsearch (&pc, entry->u->function_addrs,\n\t\tentry->u->function_addrs_count,\n\t\tsizeof (struct function_addrs),\n\t\tfunction_addrs_search));\n  if (p == NULL)\n    return callback (data, pc, ln->filename, ln->lineno, NULL);\n\n  /* Here pc >= p->low && pc < (p + 1)->low.  The function_addrs are\n     sorted by low, so if pc > p->low we are at the end of a range of\n     function_addrs with the same low value.  If pc == p->low walk\n     forward to the end of the range with that low value.  Then walk\n     backward and use the first range that includes pc.  */\n  while (pc == (p + 1)->low)\n    ++p;\n  fmatch = NULL;\n  while (1)\n    {\n      if (pc < p->high)\n\t{\n\t  fmatch = p;\n\t  break;\n\t}\n      if (p == entry->u->function_addrs)\n\tbreak;\n      if ((p - 1)->low < p->low)\n\tbreak;\n      --p;\n    }\n  if (fmatch == NULL)\n    return callback (data, pc, ln->filename, ln->lineno, NULL);\n\n  function = fmatch->function;\n\n  filename = ln->filename;\n  lineno = ln->lineno;\n\n  ret = report_inlined_functions (pc, function, callback, data,\n\t\t\t\t  &filename, &lineno);\n  if (ret != 0)\n    return ret;\n\n  return callback (data, pc, filename, lineno, function->name);\n}\n\n\n/* Return the file/line information for a PC using the DWARF mapping\n   we built earlier.  */\n\nstatic int\ndwarf_fileline (struct backtrace_state *state, uintptr_t pc,\n\t\tbacktrace_full_callback callback,\n\t\tbacktrace_error_callback error_callback, void *data)\n{\n  struct dwarf_data *ddata;\n  int found;\n  int ret;\n\n  if (!state->threaded)\n    {\n      for (ddata = (struct dwarf_data *) state->fileline_data;\n\t   ddata != NULL;\n\t   ddata = ddata->next)\n\t{\n\t  ret = dwarf_lookup_pc (state, ddata, pc, callback, error_callback,\n\t\t\t\t data, &found);\n\t  if (ret != 0 || found)\n\t    return ret;\n\t}\n    }\n  else\n    {\n      struct dwarf_data **pp;\n\n      pp = (struct dwarf_data **) (void *) &state->fileline_data;\n      while (1)\n\t{\n\t  ddata = backtrace_atomic_load_pointer (pp);\n\t  if (ddata == NULL)\n\t    break;\n\n\t  ret = dwarf_lookup_pc (state, ddata, pc, callback, error_callback,\n\t\t\t\t data, &found);\n\t  if (ret != 0 || found)\n\t    return ret;\n\n\t  pp = &ddata->next;\n\t}\n    }\n\n  /* FIXME: See if any libraries have been dlopen'ed.  */\n\n  return callback (data, pc, NULL, 0, NULL);\n}\n\n/* Initialize our data structures from the DWARF debug info for a\n   file.  Return NULL on failure.  */\n\nstatic struct dwarf_data *\nbuild_dwarf_data (struct backtrace_state *state,\n\t\t  struct libbacktrace_base_address base_address,\n\t\t  const struct dwarf_sections *dwarf_sections,\n\t\t  int is_bigendian,\n\t\t  struct dwarf_data *altlink,\n\t\t  backtrace_error_callback error_callback,\n\t\t  void *data)\n{\n  struct unit_addrs_vector addrs_vec;\n  struct unit_addrs *addrs;\n  size_t addrs_count;\n  struct unit_vector units_vec;\n  struct unit **units;\n  size_t units_count;\n  struct dwarf_data *fdata;\n\n  if (!build_address_map (state, base_address, dwarf_sections, is_bigendian,\n\t\t\t  altlink, error_callback, data, &addrs_vec,\n\t\t\t  &units_vec))\n    return NULL;\n\n  if (!backtrace_vector_release (state, &addrs_vec.vec, error_callback, data))\n    return NULL;\n  if (!backtrace_vector_release (state, &units_vec.vec, error_callback, data))\n    return NULL;\n  addrs = (struct unit_addrs *) addrs_vec.vec.base;\n  units = (struct unit **) units_vec.vec.base;\n  addrs_count = addrs_vec.count;\n  units_count = units_vec.count;\n  backtrace_qsort (addrs, addrs_count, sizeof (struct unit_addrs),\n\t\t   unit_addrs_compare);\n  /* No qsort for units required, already sorted.  */\n\n  fdata = ((struct dwarf_data *)\n\t   backtrace_alloc (state, sizeof (struct dwarf_data),\n\t\t\t    error_callback, data));\n  if (fdata == NULL)\n    return NULL;\n\n  fdata->next = NULL;\n  fdata->altlink = altlink;\n  fdata->base_address = base_address;\n  fdata->addrs = addrs;\n  fdata->addrs_count = addrs_count;\n  fdata->units = units;\n  fdata->units_count = units_count;\n  fdata->dwarf_sections = *dwarf_sections;\n  fdata->is_bigendian = is_bigendian;\n  memset (&fdata->fvec, 0, sizeof fdata->fvec);\n\n  return fdata;\n}\n\n/* Build our data structures from the DWARF sections for a module.\n   Set FILELINE_FN and STATE->FILELINE_DATA.  Return 1 on success, 0\n   on failure.  */\n\nint\nbacktrace_dwarf_add (struct backtrace_state *state,\n\t\t     struct libbacktrace_base_address base_address,\n\t\t     const struct dwarf_sections *dwarf_sections,\n\t\t     int is_bigendian,\n\t\t     struct dwarf_data *fileline_altlink,\n\t\t     backtrace_error_callback error_callback,\n\t\t     void *data, fileline *fileline_fn,\n\t\t     struct dwarf_data **fileline_entry)\n{\n  struct dwarf_data *fdata;\n\n  fdata = build_dwarf_data (state, base_address, dwarf_sections, is_bigendian,\n\t\t\t    fileline_altlink, error_callback, data);\n  if (fdata == NULL)\n    return 0;\n\n  if (fileline_entry != NULL)\n    *fileline_entry = fdata;\n\n  if (!state->threaded)\n    {\n      struct dwarf_data **pp;\n\n      for (pp = (struct dwarf_data **) (void *) &state->fileline_data;\n\t   *pp != NULL;\n\t   pp = &(*pp)->next)\n\t;\n      *pp = fdata;\n    }\n  else\n    {\n      while (1)\n\t{\n\t  struct dwarf_data **pp;\n\n\t  pp = (struct dwarf_data **) (void *) &state->fileline_data;\n\n\t  while (1)\n\t    {\n\t      struct dwarf_data *p;\n\n\t      p = backtrace_atomic_load_pointer (pp);\n\n\t      if (p == NULL)\n\t\tbreak;\n\n\t      pp = &p->next;\n\t    }\n\n\t  if (__sync_bool_compare_and_swap (pp, NULL, fdata))\n\t    break;\n\t}\n    }\n\n  *fileline_fn = dwarf_fileline;\n\n  return 1;\n}\n"
  },
  {
    "path": "src/vendor/libbacktrace/edtest.c",
    "content": "/* edtest.c -- Test for libbacktrace storage allocation stress handling\n   Copyright (C) 2017-2024 Free Software Foundation, Inc.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n    (1) Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n\n    (2) Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in\n    the documentation and/or other materials provided with the\n    distribution.\n\n    (3) The name of the author may not be used to\n    endorse or promote products derived from this software without\n    specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\nIMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,\nINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\nHOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\nIN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGE.  */\n\n#include \"config.h\"\n\n#include <assert.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/types.h>\n\n#include \"backtrace.h\"\n#include \"backtrace-supported.h\"\n#include \"internal.h\"\n\n#include \"testlib.h\"\n\nstatic int test1 (void) __attribute__ ((noinline, noclone, optnone, unused));\nextern int f2 (int);\nextern int f3 (int, int);\n\nstatic int\ntest1 (void)\n{\n  /* Returning a value here and elsewhere avoids a tailcall which\n     would mess up the backtrace.  */\n  return f2 (__LINE__) + 1;\n}\n\nint\nf3 (int f1line, int f2line)\n{\n  struct info all[20];\n  struct bdata data;\n  int f3line;\n  int i;\n\n  data.all = &all[0];\n  data.index = 0;\n  data.max = 20;\n  data.failed = 0;\n\n  f3line = __LINE__ + 1;\n  i = backtrace_full (state, 0, callback_one, error_callback_one, &data);\n\n  if (i != 0)\n    {\n      fprintf (stderr, \"test1: unexpected return value %d\\n\", i);\n      data.failed = 1;\n    }\n\n  if (data.index < 3)\n    {\n      fprintf (stderr,\n               \"test1: not enough frames; got %zu, expected at least 3\\n\",\n               data.index);\n      data.failed = 1;\n    }\n\n  check (\"test1\", 0, all, f3line, \"f3\", \"edtest.c\", &data.failed);\n  check (\"test1\", 1, all, f2line, \"f2\", \"edtest2_build.c\", &data.failed);\n  check (\"test1\", 2, all, f1line, \"test1\", \"edtest.c\", &data.failed);\n\n  printf (\"%s: backtrace_full alloc stress\\n\", data.failed ? \"FAIL\" : \"PASS\");\n\n  if (data.failed)\n    ++failures;\n\n  return failures;\n}\n\nint\nmain (int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)\n{\n  state = backtrace_create_state (argv[0], BACKTRACE_SUPPORTS_THREADS,\n                                  error_callback_create, NULL);\n\n  // Grab the storage allocation lock prior to doing anything interesting.\n  // The intent here is to insure that the backtrace_alloc code is forced\n  // to always call mmap() for new memory as opposed to reusing previously\n  // allocated memory from the free list. Doing things this way helps\n  // simulate what you might see in a multithreaded program in which there\n  // are racing calls to the allocator.\n  struct backtrace_state *state_internal =\n      (struct backtrace_state *) state;\n  state_internal->lock_alloc = 1;\n\n  // Kick off the test\n  test1();\n\n  exit (failures > 0 ? EXIT_FAILURE : EXIT_SUCCESS);\n}\n"
  },
  {
    "path": "src/vendor/libbacktrace/edtest2.c",
    "content": "/* edtest2.c -- Test for libbacktrace storage allocation stress handling (p2)\n   Copyright (C) 2017-2024 Free Software Foundation, Inc.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n    (1) Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n\n    (2) Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in\n    the documentation and/or other materials provided with the\n    distribution.\n\n    (3) The name of the author may not be used to\n    endorse or promote products derived from this software without\n    specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\nIMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,\nINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\nHOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\nIN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGE.  */\n\n/* This file intentionally written without any #include's\n */\n\nextern int f3(int, int);\nextern int f2(int);\n\nint f2(int x)\n{\n  /* Returning a value here and elsewhere avoids a tailcall which\n     would mess up the backtrace.  */\n  return f3(x, __LINE__) + 3;\n}\n"
  },
  {
    "path": "src/vendor/libbacktrace/elf.c",
    "content": "/* elf.c -- Get debug data from an ELF file for backtraces.\n   Copyright (C) 2012-2024 Free Software Foundation, Inc.\n   Written by Ian Lance Taylor, Google.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n    (1) Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n\n    (2) Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in\n    the documentation and/or other materials provided with the\n    distribution.\n\n    (3) The name of the author may not be used to\n    endorse or promote products derived from this software without\n    specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\nIMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,\nINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\nHOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\nIN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGE.  */\n\n#include \"config.h\"\n\n#include <errno.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/types.h>\n#include <sys/stat.h>\n#include <unistd.h>\n#include <dlfcn.h>\n\n#ifdef HAVE_DL_ITERATE_PHDR\n #ifdef HAVE_LINK_H\n  #include <link.h>\n #endif\n #ifdef HAVE_SYS_LINK_H\n  #include <sys/link.h>\n #endif\n#endif\n\n#include \"backtrace.h\"\n#include \"internal.h\"\n#include \"debuginfod_support.h\"\n\n#ifndef S_ISLNK\n #ifndef S_IFLNK\n  #define S_IFLNK 0120000\n #endif\n #ifndef S_IFMT\n  #define S_IFMT 0170000\n #endif\n #define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)\n#endif\n\n#ifndef __GNUC__\n#define __builtin_prefetch(p, r, l)\n#define unlikely(x) (x)\n#else\n#define unlikely(x) __builtin_expect(!!(x), 0)\n#endif\n\n#if !defined(HAVE_DECL_STRNLEN) || !HAVE_DECL_STRNLEN\n\n/* If strnlen is not declared, provide our own version.  */\n\nstatic size_t\nxstrnlen (const char *s, size_t maxlen)\n{\n  size_t i;\n\n  for (i = 0; i < maxlen; ++i)\n    if (s[i] == '\\0')\n      break;\n  return i;\n}\n\n#define strnlen xstrnlen\n\n#endif\n\n#ifndef HAVE_LSTAT\n\n/* Dummy version of lstat for systems that don't have it.  */\n\nstatic int\nxlstat (const char *path ATTRIBUTE_UNUSED, struct stat *st ATTRIBUTE_UNUSED)\n{\n  return -1;\n}\n\n#define lstat xlstat\n\n#endif\n\n#ifndef HAVE_READLINK\n\n/* Dummy version of readlink for systems that don't have it.  */\n\nstatic ssize_t\nxreadlink (const char *path ATTRIBUTE_UNUSED, char *buf ATTRIBUTE_UNUSED,\n\t   size_t bufsz ATTRIBUTE_UNUSED)\n{\n  return -1;\n}\n\n#define readlink xreadlink\n\n#endif\n\n#ifndef HAVE_DL_ITERATE_PHDR\n\n/* Dummy version of dl_iterate_phdr for systems that don't have it.  */\n\n#define dl_phdr_info x_dl_phdr_info\n#define dl_iterate_phdr x_dl_iterate_phdr\n\nstruct dl_phdr_info\n{\n  uintptr_t dlpi_addr;\n  const char *dlpi_name;\n};\n\nstatic int\ndl_iterate_phdr (int (*callback) (struct dl_phdr_info *,\n\t\t\t\t  size_t, void *) ATTRIBUTE_UNUSED,\n\t\t void *data ATTRIBUTE_UNUSED)\n{\n  return 0;\n}\n\n#endif /* ! defined (HAVE_DL_ITERATE_PHDR) */\n\n/* The configure script must tell us whether we are 32-bit or 64-bit\n   ELF.  We could make this code test and support either possibility,\n   but there is no point.  This code only works for the currently\n   running executable, which means that we know the ELF mode at\n   configure time.  */\n\n#if BACKTRACE_ELF_SIZE != 32 && BACKTRACE_ELF_SIZE != 64\n#error \"Unknown BACKTRACE_ELF_SIZE\"\n#endif\n\n/* <link.h> might #include <elf.h> which might define our constants\n   with slightly different values.  Undefine them to be safe.  */\n\n#undef EI_NIDENT\n#undef EI_MAG0\n#undef EI_MAG1\n#undef EI_MAG2\n#undef EI_MAG3\n#undef EI_CLASS\n#undef EI_DATA\n#undef EI_VERSION\n#undef ELF_MAG0\n#undef ELF_MAG1\n#undef ELF_MAG2\n#undef ELF_MAG3\n#undef ELFCLASS32\n#undef ELFCLASS64\n#undef ELFDATA2LSB\n#undef ELFDATA2MSB\n#undef EV_CURRENT\n#undef ET_DYN\n#undef EM_PPC64\n#undef EF_PPC64_ABI\n#undef SHN_LORESERVE\n#undef SHN_XINDEX\n#undef SHN_UNDEF\n#undef SHT_PROGBITS\n#undef SHT_SYMTAB\n#undef SHT_STRTAB\n#undef SHT_DYNSYM\n#undef SHF_COMPRESSED\n#undef STT_OBJECT\n#undef STT_FUNC\n#undef NT_GNU_BUILD_ID\n#undef ELFCOMPRESS_ZLIB\n#undef ELFCOMPRESS_ZSTD\n\n/* Basic types.  */\n\ntypedef uint16_t b_elf_half;    /* Elf_Half.  */\ntypedef uint32_t b_elf_word;    /* Elf_Word.  */\ntypedef int32_t  b_elf_sword;   /* Elf_Sword.  */\n\n#if BACKTRACE_ELF_SIZE == 32\n\ntypedef uint32_t b_elf_addr;    /* Elf_Addr.  */\ntypedef uint32_t b_elf_off;     /* Elf_Off.  */\n\ntypedef uint32_t b_elf_wxword;  /* 32-bit Elf_Word, 64-bit ELF_Xword.  */\n\n#else\n\ntypedef uint64_t b_elf_addr;    /* Elf_Addr.  */\ntypedef uint64_t b_elf_off;     /* Elf_Off.  */\ntypedef uint64_t b_elf_xword;   /* Elf_Xword.  */\ntypedef int64_t  b_elf_sxword;  /* Elf_Sxword.  */\n\ntypedef uint64_t b_elf_wxword;  /* 32-bit Elf_Word, 64-bit ELF_Xword.  */\n\n#endif\n\n/* Data structures and associated constants.  */\n\n#define EI_NIDENT 16\n\ntypedef struct {\n  unsigned char\te_ident[EI_NIDENT];\t/* ELF \"magic number\" */\n  b_elf_half\te_type;\t\t\t/* Identifies object file type */\n  b_elf_half\te_machine;\t\t/* Specifies required architecture */\n  b_elf_word\te_version;\t\t/* Identifies object file version */\n  b_elf_addr\te_entry;\t\t/* Entry point virtual address */\n  b_elf_off\te_phoff;\t\t/* Program header table file offset */\n  b_elf_off\te_shoff;\t\t/* Section header table file offset */\n  b_elf_word\te_flags;\t\t/* Processor-specific flags */\n  b_elf_half\te_ehsize;\t\t/* ELF header size in bytes */\n  b_elf_half\te_phentsize;\t\t/* Program header table entry size */\n  b_elf_half\te_phnum;\t\t/* Program header table entry count */\n  b_elf_half\te_shentsize;\t\t/* Section header table entry size */\n  b_elf_half\te_shnum;\t\t/* Section header table entry count */\n  b_elf_half\te_shstrndx;\t\t/* Section header string table index */\n} b_elf_ehdr;  /* Elf_Ehdr.  */\n\n#define EI_MAG0 0\n#define EI_MAG1 1\n#define EI_MAG2 2\n#define EI_MAG3 3\n#define EI_CLASS 4\n#define EI_DATA 5\n#define EI_VERSION 6\n\n#define ELFMAG0 0x7f\n#define ELFMAG1 'E'\n#define ELFMAG2 'L'\n#define ELFMAG3 'F'\n\n#define ELFCLASS32 1\n#define ELFCLASS64 2\n\n#define ELFDATA2LSB 1\n#define ELFDATA2MSB 2\n\n#define EV_CURRENT 1\n\n#define ET_DYN 3\n\n#define EM_PPC64 21\n#define EF_PPC64_ABI 3\n\ntypedef struct {\n  b_elf_word\tsh_name;\t\t/* Section name, index in string tbl */\n  b_elf_word\tsh_type;\t\t/* Type of section */\n  b_elf_wxword\tsh_flags;\t\t/* Miscellaneous section attributes */\n  b_elf_addr\tsh_addr;\t\t/* Section virtual addr at execution */\n  b_elf_off\tsh_offset;\t\t/* Section file offset */\n  b_elf_wxword\tsh_size;\t\t/* Size of section in bytes */\n  b_elf_word\tsh_link;\t\t/* Index of another section */\n  b_elf_word\tsh_info;\t\t/* Additional section information */\n  b_elf_wxword\tsh_addralign;\t\t/* Section alignment */\n  b_elf_wxword\tsh_entsize;\t\t/* Entry size if section holds table */\n} b_elf_shdr;  /* Elf_Shdr.  */\n\n#define SHN_UNDEF\t0x0000\t\t/* Undefined section */\n#define SHN_LORESERVE\t0xFF00\t\t/* Begin range of reserved indices */\n#define SHN_XINDEX\t0xFFFF\t\t/* Section index is held elsewhere */\n\n#define SHT_PROGBITS 1\n#define SHT_SYMTAB 2\n#define SHT_STRTAB 3\n#define SHT_DYNSYM 11\n\n#define SHF_COMPRESSED 0x800\n\n#if BACKTRACE_ELF_SIZE == 32\n\ntypedef struct\n{\n  b_elf_word\tst_name;\t\t/* Symbol name, index in string tbl */\n  b_elf_addr\tst_value;\t\t/* Symbol value */\n  b_elf_word\tst_size;\t\t/* Symbol size */\n  unsigned char\tst_info;\t\t/* Symbol binding and type */\n  unsigned char\tst_other;\t\t/* Visibility and other data */\n  b_elf_half\tst_shndx;\t\t/* Symbol section index */\n} b_elf_sym;  /* Elf_Sym.  */\n\n#else /* BACKTRACE_ELF_SIZE != 32 */\n\ntypedef struct\n{\n  b_elf_word\tst_name;\t\t/* Symbol name, index in string tbl */\n  unsigned char\tst_info;\t\t/* Symbol binding and type */\n  unsigned char\tst_other;\t\t/* Visibility and other data */\n  b_elf_half\tst_shndx;\t\t/* Symbol section index */\n  b_elf_addr\tst_value;\t\t/* Symbol value */\n  b_elf_xword\tst_size;\t\t/* Symbol size */\n} b_elf_sym;  /* Elf_Sym.  */\n\n#endif /* BACKTRACE_ELF_SIZE != 32 */\n\n#define STT_OBJECT 1\n#define STT_FUNC 2\n\ntypedef struct\n{\n  uint32_t namesz;\n  uint32_t descsz;\n  uint32_t type;\n  char name[1];\n} b_elf_note;\n\n#define NT_GNU_BUILD_ID 3\n\n#if BACKTRACE_ELF_SIZE == 32\n\ntypedef struct\n{\n  b_elf_word\tch_type;\t\t/* Compresstion algorithm */\n  b_elf_word\tch_size;\t\t/* Uncompressed size */\n  b_elf_word\tch_addralign;\t\t/* Alignment for uncompressed data */\n} b_elf_chdr;  /* Elf_Chdr */\n\n#else /* BACKTRACE_ELF_SIZE != 32 */\n\ntypedef struct\n{\n  b_elf_word\tch_type;\t\t/* Compression algorithm */\n  b_elf_word\tch_reserved;\t\t/* Reserved */\n  b_elf_xword\tch_size;\t\t/* Uncompressed size */\n  b_elf_xword\tch_addralign;\t\t/* Alignment for uncompressed data */\n} b_elf_chdr;  /* Elf_Chdr */\n\n#endif /* BACKTRACE_ELF_SIZE != 32 */\n\n#define ELFCOMPRESS_ZLIB 1\n#define ELFCOMPRESS_ZSTD 2\n\n/* Names of sections, indexed by enum dwarf_section in internal.h.  */\n\nstatic const char * const dwarf_section_names[DEBUG_MAX] =\n{\n  \".debug_info\",\n  \".debug_line\",\n  \".debug_abbrev\",\n  \".debug_ranges\",\n  \".debug_str\",\n  \".debug_addr\",\n  \".debug_str_offsets\",\n  \".debug_line_str\",\n  \".debug_rnglists\"\n};\n\n/* Information we gather for the sections we care about.  */\n\nstruct debug_section_info\n{\n  /* Section file offset.  */\n  off_t offset;\n  /* Section size.  */\n  size_t size;\n  /* Section contents, after read from file.  */\n  const unsigned char *data;\n  /* Whether the SHF_COMPRESSED flag is set for the section.  */\n  int compressed;\n};\n\n/* Information we keep for an ELF symbol.  */\n\nstruct elf_symbol\n{\n  /* The name of the symbol.  */\n  const char *name;\n  /* The address of the symbol.  */\n  uintptr_t address;\n  /* The size of the symbol.  */\n  size_t size;\n};\n\n/* Information to pass to elf_syminfo.  */\n\nstruct elf_syminfo_data\n{\n  /* Symbols for the next module.  */\n  struct elf_syminfo_data *next;\n  /* The ELF symbols, sorted by address.  */\n  struct elf_symbol *symbols;\n  /* The number of symbols.  */\n  size_t count;\n};\n\n/* A view that works for either a file or memory.  */\n\nstruct elf_view\n{\n  struct backtrace_view view;\n  int release; /* If non-zero, must call backtrace_release_view.  */\n};\n\n/* Information about PowerPC64 ELFv1 .opd section.  */\n\nstruct elf_ppc64_opd_data\n{\n  /* Address of the .opd section.  */\n  b_elf_addr addr;\n  /* Section data.  */\n  const char *data;\n  /* Size of the .opd section.  */\n  size_t size;\n  /* Corresponding section view.  */\n  struct elf_view view;\n};\n\n/* Create a view of SIZE bytes from DESCRIPTOR/MEMORY at OFFSET.  */\n\nstatic int\nelf_get_view (struct backtrace_state *state, int descriptor,\n\t      const unsigned char *memory, size_t memory_size, off_t offset,\n\t      uint64_t size, backtrace_error_callback error_callback,\n\t      void *data, struct elf_view *view)\n{\n  if (memory == NULL)\n    {\n      view->release = 1;\n      return backtrace_get_view (state, descriptor, offset, size,\n\t\t\t\t error_callback, data, &view->view);\n    }\n  else\n    {\n      if ((uint64_t) offset + size > (uint64_t) memory_size)\n\t{\n\t  error_callback (data, \"out of range for in-memory file\", 0);\n\t  return 0;\n\t}\n      view->view.data = (const void *) (memory + offset);\n      view->view.base = NULL;\n      view->view.len = size;\n      view->release = 0;\n      return 1;\n    }\n}\n\n/* Release a view read by elf_get_view.  */\n\nstatic void\nelf_release_view (struct backtrace_state *state, struct elf_view *view,\n\t\t  backtrace_error_callback error_callback, void *data)\n{\n  if (view->release)\n    backtrace_release_view (state, &view->view, error_callback, data);\n}\n\n/* Compute the CRC-32 of BUF/LEN.  This uses the CRC used for\n   .gnu_debuglink files.  */\n\nstatic uint32_t\nelf_crc32 (uint32_t crc, const unsigned char *buf, size_t len)\n{\n  static const uint32_t crc32_table[256] =\n    {\n      0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,\n      0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,\n      0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,\n      0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,\n      0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,\n      0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,\n      0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,\n      0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,\n      0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,\n      0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,\n      0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,\n      0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,\n      0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,\n      0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,\n      0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,\n      0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,\n      0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,\n      0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,\n      0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,\n      0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,\n      0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,\n      0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,\n      0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,\n      0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,\n      0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,\n      0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,\n      0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,\n      0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,\n      0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,\n      0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,\n      0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,\n      0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,\n      0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,\n      0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,\n      0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,\n      0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,\n      0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,\n      0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,\n      0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,\n      0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,\n      0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,\n      0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,\n      0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,\n      0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,\n      0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,\n      0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,\n      0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,\n      0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,\n      0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,\n      0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,\n      0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,\n      0x2d02ef8d\n    };\n  const unsigned char *end;\n\n  crc = ~crc;\n  for (end = buf + len; buf < end; ++ buf)\n    crc = crc32_table[(crc ^ *buf) & 0xff] ^ (crc >> 8);\n  return ~crc;\n}\n\n/* Return the CRC-32 of the entire file open at DESCRIPTOR.  */\n\nstatic uint32_t\nelf_crc32_file (struct backtrace_state *state, int descriptor,\n\t\tbacktrace_error_callback error_callback, void *data)\n{\n  struct stat st;\n  struct backtrace_view file_view;\n  uint32_t ret;\n\n  if (fstat (descriptor, &st) < 0)\n    {\n      error_callback (data, \"fstat\", errno);\n      return 0;\n    }\n\n  if (!backtrace_get_view (state, descriptor, 0, st.st_size, error_callback,\n\t\t\t   data, &file_view))\n    return 0;\n\n  ret = elf_crc32 (0, (const unsigned char *) file_view.data, st.st_size);\n\n  backtrace_release_view (state, &file_view, error_callback, data);\n\n  return ret;\n}\n\n/* A dummy callback function used when we can't find a symbol\n   table.  */\n\nvoid\nelf_nosyms (struct backtrace_state *state ATTRIBUTE_UNUSED,\n\t    uintptr_t addr ATTRIBUTE_UNUSED,\n\t    backtrace_syminfo_callback callback ATTRIBUTE_UNUSED,\n\t    backtrace_error_callback error_callback, void *data)\n{\n  error_callback (data, \"no symbol table in ELF executable\", -1);\n}\n\n/* A callback function used when we can't find any debug info.  */\n\nstatic int\nelf_nodebug (struct backtrace_state *state, uintptr_t pc,\n\t     backtrace_full_callback callback,\n\t     backtrace_error_callback error_callback, void *data)\n{\n  if (state->syminfo_fn != NULL && state->syminfo_fn != elf_nosyms)\n    {\n      struct backtrace_call_full bdata;\n\n      /* Fetch symbol information so that we can least get the\n\t function name.  */\n\n      bdata.full_callback = callback;\n      bdata.full_error_callback = error_callback;\n      bdata.full_data = data;\n      bdata.ret = 0;\n      state->syminfo_fn (state, pc, backtrace_syminfo_to_full_callback,\n\t\t\t backtrace_syminfo_to_full_error_callback, &bdata);\n      return bdata.ret;\n    }\n\n  error_callback (data, \"no debug info in ELF executable (make sure to compile with -g)\", -1);\n  return 0;\n}\n\n/* Compare struct elf_symbol for qsort.  */\n\nstatic int\nelf_symbol_compare (const void *v1, const void *v2)\n{\n  const struct elf_symbol *e1 = (const struct elf_symbol *) v1;\n  const struct elf_symbol *e2 = (const struct elf_symbol *) v2;\n\n  if (e1->address < e2->address)\n    return -1;\n  else if (e1->address > e2->address)\n    return 1;\n  else\n    return 0;\n}\n\n/* Compare an ADDR against an elf_symbol for bsearch.  We allocate one\n   extra entry in the array so that this can look safely at the next\n   entry.  */\n\nstatic int\nelf_symbol_search (const void *vkey, const void *ventry)\n{\n  const uintptr_t *key = (const uintptr_t *) vkey;\n  const struct elf_symbol *entry = (const struct elf_symbol *) ventry;\n  uintptr_t addr;\n\n  addr = *key;\n  if (addr < entry->address)\n    return -1;\n  else if (addr >= entry->address + entry->size)\n    return 1;\n  else\n    return 0;\n}\n\n/* Initialize the symbol table info for elf_syminfo.  */\n\nint\nelf_initialize_syminfo (struct backtrace_state *state,\n\t\t\tstruct libbacktrace_base_address base_address,\n\t\t\tconst unsigned char *symtab_data, size_t symtab_size,\n\t\t\tconst unsigned char *strtab, size_t strtab_size,\n\t\t\tbacktrace_error_callback error_callback,\n\t\t\tvoid *data, struct elf_syminfo_data *sdata,\n\t\t\tstruct elf_ppc64_opd_data *opd)\n{\n  size_t sym_count;\n  const b_elf_sym *sym;\n  size_t elf_symbol_count;\n  size_t elf_symbol_size;\n  struct elf_symbol *elf_symbols;\n  size_t i;\n  unsigned int j;\n\n  sym_count = symtab_size / sizeof (b_elf_sym);\n\n  /* We only care about function symbols.  Count them.  */\n  sym = (const b_elf_sym *) symtab_data;\n  elf_symbol_count = 0;\n  for (i = 0; i < sym_count; ++i, ++sym)\n    {\n      int info;\n\n      info = sym->st_info & 0xf;\n      if ((info == STT_FUNC || info == STT_OBJECT)\n\t  && sym->st_shndx != SHN_UNDEF)\n\t++elf_symbol_count;\n    }\n\n  elf_symbol_size = elf_symbol_count * sizeof (struct elf_symbol);\n  elf_symbols = ((struct elf_symbol *)\n\t\t backtrace_alloc (state, elf_symbol_size, error_callback,\n\t\t\t\t  data));\n  if (elf_symbols == NULL)\n    return 0;\n\n  sym = (const b_elf_sym *) symtab_data;\n  j = 0;\n  for (i = 0; i < sym_count; ++i, ++sym)\n    {\n      int info;\n\n      info = sym->st_info & 0xf;\n      if (info != STT_FUNC && info != STT_OBJECT)\n\tcontinue;\n      if (sym->st_shndx == SHN_UNDEF)\n\tcontinue;\n      if (sym->st_name >= strtab_size)\n\t{\n\t  error_callback (data, \"symbol string index out of range\", 0);\n\t  backtrace_free (state, elf_symbols, elf_symbol_size, error_callback,\n\t\t\t  data);\n\t  return 0;\n\t}\n      elf_symbols[j].name = (const char *) strtab + sym->st_name;\n      /* Special case PowerPC64 ELFv1 symbols in .opd section, if the symbol\n\t is a function descriptor, read the actual code address from the\n\t descriptor.  */\n      if (opd\n\t  && sym->st_value >= opd->addr\n\t  && sym->st_value < opd->addr + opd->size)\n\telf_symbols[j].address\n\t  = *(const b_elf_addr *) (opd->data + (sym->st_value - opd->addr));\n      else\n\telf_symbols[j].address = sym->st_value;\n      elf_symbols[j].address =\n\tlibbacktrace_add_base (elf_symbols[j].address, base_address);\n      elf_symbols[j].size = sym->st_size;\n      ++j;\n    }\n\n  backtrace_qsort (elf_symbols, elf_symbol_count, sizeof (struct elf_symbol),\n\t\t   elf_symbol_compare);\n\n  sdata->next = NULL;\n  sdata->symbols = elf_symbols;\n  sdata->count = elf_symbol_count;\n\n  return 1;\n}\n\n/* Add EDATA to the list in STATE.  */\n\nstatic void\nelf_add_syminfo_data (struct backtrace_state *state,\n\t\t      struct elf_syminfo_data *edata)\n{\n  if (!state->threaded)\n    {\n      struct elf_syminfo_data **pp;\n\n      for (pp = (struct elf_syminfo_data **) (void *) &state->syminfo_data;\n\t   *pp != NULL;\n\t   pp = &(*pp)->next)\n\t;\n      *pp = edata;\n    }\n  else\n    {\n      while (1)\n\t{\n\t  struct elf_syminfo_data **pp;\n\n\t  pp = (struct elf_syminfo_data **) (void *) &state->syminfo_data;\n\n\t  while (1)\n\t    {\n\t      struct elf_syminfo_data *p;\n\n\t      p = backtrace_atomic_load_pointer (pp);\n\n\t      if (p == NULL)\n\t\tbreak;\n\n\t      pp = &p->next;\n\t    }\n\n\t  if (__sync_bool_compare_and_swap (pp, NULL, edata))\n\t    break;\n\t}\n    }\n}\n\n/* Return the symbol name and value for an ADDR.  */\n\nvoid\nelf_syminfo (struct backtrace_state *state, uintptr_t addr,\n\t     backtrace_syminfo_callback callback,\n\t     backtrace_error_callback error_callback ATTRIBUTE_UNUSED,\n\t     void *data)\n{\n  struct elf_syminfo_data *edata;\n  struct elf_symbol *sym = NULL;\n\n  if (!state->threaded)\n    {\n      for (edata = (struct elf_syminfo_data *) state->syminfo_data;\n\t   edata != NULL;\n\t   edata = edata->next)\n\t{\n\t  sym = ((struct elf_symbol *)\n\t\t bsearch (&addr, edata->symbols, edata->count,\n\t\t\t  sizeof (struct elf_symbol), elf_symbol_search));\n\t  if (sym != NULL)\n\t    break;\n\t}\n    }\n  else\n    {\n      struct elf_syminfo_data **pp;\n\n      pp = (struct elf_syminfo_data **) (void *) &state->syminfo_data;\n      while (1)\n\t{\n\t  edata = backtrace_atomic_load_pointer (pp);\n\t  if (edata == NULL)\n\t    break;\n\n\t  sym = ((struct elf_symbol *)\n\t\t bsearch (&addr, edata->symbols, edata->count,\n\t\t\t  sizeof (struct elf_symbol), elf_symbol_search));\n\t  if (sym != NULL)\n\t    break;\n\n\t  pp = &edata->next;\n\t}\n    }\n\n  if (sym == NULL)\n    callback (data, addr, NULL, 0, 0);\n  else\n    callback (data, addr, sym->name, sym->address, sym->size);\n}\n\n/* Return whether FILENAME is a symlink.  */\n\nstatic int\nelf_is_symlink (const char *filename)\n{\n  struct stat st;\n\n  if (lstat (filename, &st) < 0)\n    return 0;\n  return S_ISLNK (st.st_mode);\n}\n\n/* Return the results of reading the symlink FILENAME in a buffer\n   allocated by backtrace_alloc.  Return the length of the buffer in\n   *LEN.  */\n\nstatic char *\nelf_readlink (struct backtrace_state *state, const char *filename,\n\t      backtrace_error_callback error_callback, void *data,\n\t      size_t *plen)\n{\n  size_t len;\n  char *buf;\n\n  len = 128;\n  while (1)\n    {\n      ssize_t rl;\n\n      buf = backtrace_alloc (state, len, error_callback, data);\n      if (buf == NULL)\n\treturn NULL;\n      rl = readlink (filename, buf, len);\n      if (rl < 0)\n\t{\n\t  backtrace_free (state, buf, len, error_callback, data);\n\t  return NULL;\n\t}\n      if ((size_t) rl < len - 1)\n\t{\n\t  buf[rl] = '\\0';\n\t  *plen = len;\n\t  return buf;\n\t}\n      backtrace_free (state, buf, len, error_callback, data);\n      len *= 2;\n    }\n}\n\n#define SYSTEM_BUILD_ID_DIR \"/usr/lib/debug/.build-id/\"\n\nstatic int debuginfod_guard = 0;\n\nstatic int\nelf_open_debugfile_by_debuginfod (const char *buildid_data,\n\t\t\t       size_t buildid_size,\n\t\t\t       backtrace_error_callback error_callback,\n\t\t\t       void *data)\n{\n  char* path = NULL;\n  const unsigned char* bi = (const unsigned char*)buildid_data;\n\n  debuginfod_client* client = debuginfod_begin();\n  if (!client) {\n    return -1;\n  }\n\n  const int fd = debuginfod_find_debuginfo(client, bi, buildid_size, &path);\n\n  debuginfod_end(client);\n\n  if (!path || fd <= 0) {\n    return -1;\n  }\n\n  const int ret = backtrace_open (path, error_callback, data, NULL);\n\n  free(path);\n  close(fd);\n\n  return ret;\n}\n\n\n/* Open a separate debug info file, using the build ID to find it.\n   Returns an open file descriptor, or -1.\n\n   The GDB manual says that the only place gdb looks for a debug file\n   when the build ID is known is in /usr/lib/debug/.build-id.  */\n\nstatic int\nelf_open_debugfile_by_buildid (struct backtrace_state *state,\n\t\t\t       const char *buildid_data, size_t buildid_size,\n\t\t\t       backtrace_error_callback error_callback,\n\t\t\t       void *data)\n{\n  const char * const prefix = SYSTEM_BUILD_ID_DIR;\n  const size_t prefix_len = strlen (prefix);\n  const char * const suffix = \".debug\";\n  const size_t suffix_len = strlen (suffix);\n  size_t len;\n  char *bd_filename;\n  char *t;\n  size_t i;\n  int ret;\n  int does_not_exist;\n\n  len = prefix_len + buildid_size * 2 + suffix_len + 2;\n  bd_filename = backtrace_alloc (state, len, error_callback, data);\n  if (bd_filename == NULL)\n    return -1;\n\n  t = bd_filename;\n  memcpy (t, prefix, prefix_len);\n  t += prefix_len;\n  for (i = 0; i < buildid_size; i++)\n    {\n      unsigned char b;\n      unsigned char nib;\n\n      b = (unsigned char) buildid_data[i];\n      nib = (b & 0xf0) >> 4;\n      *t++ = nib < 10 ? '0' + nib : 'a' + nib - 10;\n      nib = b & 0x0f;\n      *t++ = nib < 10 ? '0' + nib : 'a' + nib - 10;\n      if (i == 0)\n\t*t++ = '/';\n    }\n  memcpy (t, suffix, suffix_len);\n  t[suffix_len] = '\\0';\n\n  ret = backtrace_open (bd_filename, error_callback, data, &does_not_exist);\n\n  backtrace_free (state, bd_filename, len, error_callback, data);\n\n  /* gdb checks that the debuginfo file has the same build ID note.\n     That seems kind of pointless to me--why would it have the right\n     name but not the right build ID?--so skipping the check.  */\n\n  return ret;\n}\n\n/* Try to open a file whose name is PREFIX (length PREFIX_LEN)\n   concatenated with PREFIX2 (length PREFIX2_LEN) concatenated with\n   DEBUGLINK_NAME.  Returns an open file descriptor, or -1.  */\n\nstatic int\nelf_try_debugfile (struct backtrace_state *state, const char *prefix,\n\t\t   size_t prefix_len, const char *prefix2, size_t prefix2_len,\n\t\t   const char *debuglink_name,\n\t\t   backtrace_error_callback error_callback, void *data)\n{\n  size_t debuglink_len;\n  size_t try_len;\n  char *try;\n  int does_not_exist;\n  int ret;\n\n  debuglink_len = strlen (debuglink_name);\n  try_len = prefix_len + prefix2_len + debuglink_len + 1;\n  try = backtrace_alloc (state, try_len, error_callback, data);\n  if (try == NULL)\n    return -1;\n\n  memcpy (try, prefix, prefix_len);\n  memcpy (try + prefix_len, prefix2, prefix2_len);\n  memcpy (try + prefix_len + prefix2_len, debuglink_name, debuglink_len);\n  try[prefix_len + prefix2_len + debuglink_len] = '\\0';\n\n  ret = backtrace_open (try, error_callback, data, &does_not_exist);\n\n  backtrace_free (state, try, try_len, error_callback, data);\n\n  return ret;\n}\n\n/* Find a separate debug info file, using the debuglink section data\n   to find it.  Returns an open file descriptor, or -1.  */\n\nstatic int\nelf_find_debugfile_by_debuglink (struct backtrace_state *state,\n\t\t\t\t const char *filename,\n\t\t\t\t const char *debuglink_name,\n\t\t\t\t backtrace_error_callback error_callback,\n\t\t\t\t void *data)\n{\n  int ret;\n  char *alc;\n  size_t alc_len;\n  const char *slash;\n  int ddescriptor;\n  const char *prefix;\n  size_t prefix_len;\n\n  /* Resolve symlinks in FILENAME.  Since FILENAME is fairly likely to\n     be /proc/self/exe, symlinks are common.  We don't try to resolve\n     the whole path name, just the base name.  */\n  ret = -1;\n  alc = NULL;\n  alc_len = 0;\n  while (elf_is_symlink (filename))\n    {\n      char *new_buf;\n      size_t new_len;\n\n      new_buf = elf_readlink (state, filename, error_callback, data, &new_len);\n      if (new_buf == NULL)\n\tbreak;\n\n      if (new_buf[0] == '/')\n\tfilename = new_buf;\n      else\n\t{\n\t  slash = strrchr (filename, '/');\n\t  if (slash == NULL)\n\t    filename = new_buf;\n\t  else\n\t    {\n\t      size_t clen;\n\t      char *c;\n\n\t      slash++;\n\t      clen = slash - filename + strlen (new_buf) + 1;\n\t      c = backtrace_alloc (state, clen, error_callback, data);\n\t      if (c == NULL)\n\t\tgoto done;\n\n\t      memcpy (c, filename, slash - filename);\n\t      memcpy (c + (slash - filename), new_buf, strlen (new_buf));\n\t      c[slash - filename + strlen (new_buf)] = '\\0';\n\t      backtrace_free (state, new_buf, new_len, error_callback, data);\n\t      filename = c;\n\t      new_buf = c;\n\t      new_len = clen;\n\t    }\n\t}\n\n      if (alc != NULL)\n\tbacktrace_free (state, alc, alc_len, error_callback, data);\n      alc = new_buf;\n      alc_len = new_len;\n    }\n\n  /* Look for DEBUGLINK_NAME in the same directory as FILENAME.  */\n\n  slash = strrchr (filename, '/');\n  if (slash == NULL)\n    {\n      prefix = \"\";\n      prefix_len = 0;\n    }\n  else\n    {\n      slash++;\n      prefix = filename;\n      prefix_len = slash - filename;\n    }\n\n  ddescriptor = elf_try_debugfile (state, prefix, prefix_len, \"\", 0,\n\t\t\t\t   debuglink_name, error_callback, data);\n  if (ddescriptor >= 0)\n    {\n      ret = ddescriptor;\n      goto done;\n    }\n\n  /* Look for DEBUGLINK_NAME in a .debug subdirectory of FILENAME.  */\n\n  ddescriptor = elf_try_debugfile (state, prefix, prefix_len, \".debug/\",\n\t\t\t\t   strlen (\".debug/\"), debuglink_name,\n\t\t\t\t   error_callback, data);\n  if (ddescriptor >= 0)\n    {\n      ret = ddescriptor;\n      goto done;\n    }\n\n  /* Look for DEBUGLINK_NAME in /usr/lib/debug.  */\n\n  ddescriptor = elf_try_debugfile (state, \"/usr/lib/debug/\",\n\t\t\t\t   strlen (\"/usr/lib/debug/\"), prefix,\n\t\t\t\t   prefix_len, debuglink_name,\n\t\t\t\t   error_callback, data);\n  if (ddescriptor >= 0)\n    ret = ddescriptor;\n\n done:\n  if (alc != NULL && alc_len > 0)\n    backtrace_free (state, alc, alc_len, error_callback, data);\n  return ret;\n}\n\n/* Open a separate debug info file, using the debuglink section data\n   to find it.  Returns an open file descriptor, or -1.  */\n\nstatic int\nelf_open_debugfile_by_debuglink (struct backtrace_state *state,\n\t\t\t\t const char *filename,\n\t\t\t\t const char *debuglink_name,\n\t\t\t\t uint32_t debuglink_crc,\n\t\t\t\t backtrace_error_callback error_callback,\n\t\t\t\t void *data)\n{\n  int ddescriptor;\n\n  ddescriptor = elf_find_debugfile_by_debuglink (state, filename,\n\t\t\t\t\t\t debuglink_name,\n\t\t\t\t\t\t error_callback, data);\n  if (ddescriptor < 0)\n    return -1;\n\n  if (debuglink_crc != 0)\n    {\n      uint32_t got_crc;\n\n      got_crc = debuglink_crc ? elf_crc32_file (state, ddescriptor, error_callback, data) : 0;\n      if (got_crc != debuglink_crc)\n\t{\n\t  backtrace_close (ddescriptor, error_callback, data);\n\t  return -1;\n\t}\n    }\n\n  return ddescriptor;\n}\n\n/* A function useful for setting a breakpoint for an inflation failure\n   when this code is compiled with -g.  */\n\nstatic void\nelf_uncompress_failed(void)\n{\n}\n\n/* *PVAL is the current value being read from the stream, and *PBITS\n   is the number of valid bits.  Ensure that *PVAL holds at least 15\n   bits by reading additional bits from *PPIN, up to PINEND, as\n   needed.  Updates *PPIN, *PVAL and *PBITS.  Returns 1 on success, 0\n   on error.  */\n\nstatic int\nelf_fetch_bits (const unsigned char **ppin, const unsigned char *pinend,\n\t\tuint64_t *pval, unsigned int *pbits)\n{\n  unsigned int bits;\n  const unsigned char *pin;\n  uint64_t val;\n  uint32_t next;\n\n  bits = *pbits;\n  if (bits >= 15)\n    return 1;\n  pin = *ppin;\n  val = *pval;\n\n  if (unlikely (pinend - pin < 4))\n    {\n      elf_uncompress_failed ();\n      return 0;\n    }\n\n#if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) \\\n    && defined(__ORDER_BIG_ENDIAN__) \\\n    && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ \\\n        || __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)\n  /* We've ensured that PIN is aligned.  */\n  next = *(const uint32_t *)pin;\n\n#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__\n  next = __builtin_bswap32 (next);\n#endif\n#else\n  next = pin[0] | (pin[1] << 8) | (pin[2] << 16) | (pin[3] << 24);\n#endif\n\n  val |= (uint64_t)next << bits;\n  bits += 32;\n  pin += 4;\n\n  /* We will need the next four bytes soon.  */\n  __builtin_prefetch (pin, 0, 0);\n\n  *ppin = pin;\n  *pval = val;\n  *pbits = bits;\n  return 1;\n}\n\n/* This is like elf_fetch_bits, but it fetchs the bits backward, and ensures at\n   least 16 bits.  This is for zstd.  */\n\nstatic int\nelf_fetch_bits_backward (const unsigned char **ppin,\n\t\t\t const unsigned char *pinend,\n\t\t\t uint64_t *pval, unsigned int *pbits)\n{\n  unsigned int bits;\n  const unsigned char *pin;\n  uint64_t val;\n  uint32_t next;\n\n  bits = *pbits;\n  if (bits >= 16)\n    return 1;\n  pin = *ppin;\n  val = *pval;\n\n  if (unlikely (pin <= pinend))\n    return 1;\n\n  pin -= 4;\n\n#if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) \\\n  && defined(__ORDER_BIG_ENDIAN__)\t\t\t\t\\\n  && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__\t\t\t\\\n      || __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)\n  /* We've ensured that PIN is aligned.  */\n  next = *(const uint32_t *)pin;\n\n#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__\n  next = __builtin_bswap32 (next);\n#endif\n#else\n  next = pin[0] | (pin[1] << 8) | (pin[2] << 16) | (pin[3] << 24);\n#endif\n\n  val <<= 32;\n  val |= next;\n  bits += 32;\n\n  if (unlikely (pin < pinend))\n    {\n      val >>= (pinend - pin) * 8;\n      bits -= (pinend - pin) * 8;\n    }\n\n  *ppin = pin;\n  *pval = val;\n  *pbits = bits;\n  return 1;\n}\n\n/* Initialize backward fetching when the bitstream starts with a 1 bit in the\n   last byte in memory (which is the first one that we read).  This is used by\n   zstd decompression.  Returns 1 on success, 0 on error.  */\n\nstatic int\nelf_fetch_backward_init (const unsigned char **ppin,\n\t\t\t const unsigned char *pinend,\n\t\t\t uint64_t *pval, unsigned int *pbits)\n{\n  const unsigned char *pin;\n  unsigned int stream_start;\n  uint64_t val;\n  unsigned int bits;\n\n  pin = *ppin;\n  stream_start = (unsigned int)*pin;\n  if (unlikely (stream_start == 0))\n    {\n      elf_uncompress_failed ();\n      return 0;\n    }\n  val = 0;\n  bits = 0;\n\n  /* Align to a 32-bit boundary.  */\n  while ((((uintptr_t)pin) & 3) != 0)\n    {\n      val <<= 8;\n      val |= (uint64_t)*pin;\n      bits += 8;\n      --pin;\n    }\n\n  val <<= 8;\n  val |= (uint64_t)*pin;\n  bits += 8;\n\n  *ppin = pin;\n  *pval = val;\n  *pbits = bits;\n  if (!elf_fetch_bits_backward (ppin, pinend, pval, pbits))\n    return 0;\n\n  *pbits -= __builtin_clz (stream_start) - (sizeof (unsigned int) - 1) * 8 + 1;\n\n  if (!elf_fetch_bits_backward (ppin, pinend, pval, pbits))\n    return 0;\n\n  return 1;\n}\n\n/* Huffman code tables, like the rest of the zlib format, are defined\n   by RFC 1951.  We store a Huffman code table as a series of tables\n   stored sequentially in memory.  Each entry in a table is 16 bits.\n   The first, main, table has 256 entries.  It is followed by a set of\n   secondary tables of length 2 to 128 entries.  The maximum length of\n   a code sequence in the deflate format is 15 bits, so that is all we\n   need.  Each secondary table has an index, which is the offset of\n   the table in the overall memory storage.\n\n   The deflate format says that all codes of a given bit length are\n   lexicographically consecutive.  Perhaps we could have 130 values\n   that require a 15-bit code, perhaps requiring three secondary\n   tables of size 128.  I don't know if this is actually possible, but\n   it suggests that the maximum size required for secondary tables is\n   3 * 128 + 3 * 64 ... == 768.  The zlib enough program reports 660\n   as the maximum.  We permit 768, since in addition to the 256 for\n   the primary table, with two bytes per entry, and with the two\n   tables we need, that gives us a page.\n\n   A single table entry needs to store a value or (for the main table\n   only) the index and size of a secondary table.  Values range from 0\n   to 285, inclusive.  Secondary table indexes, per above, range from\n   0 to 510.  For a value we need to store the number of bits we need\n   to determine that value (one value may appear multiple times in the\n   table), which is 1 to 8.  For a secondary table we need to store\n   the number of bits used to index into the table, which is 1 to 7.\n   And of course we need 1 bit to decide whether we have a value or a\n   secondary table index.  So each entry needs 9 bits for value/table\n   index, 3 bits for size, 1 bit what it is.  For simplicity we use 16\n   bits per entry.  */\n\n/* Number of entries we allocate to for one code table.  We get a page\n   for the two code tables we need.  */\n\n#define ZLIB_HUFFMAN_TABLE_SIZE (1024)\n\n/* Bit masks and shifts for the values in the table.  */\n\n#define ZLIB_HUFFMAN_VALUE_MASK 0x01ff\n#define ZLIB_HUFFMAN_BITS_SHIFT 9\n#define ZLIB_HUFFMAN_BITS_MASK 0x7\n#define ZLIB_HUFFMAN_SECONDARY_SHIFT 12\n\n/* For working memory while inflating we need two code tables, we need\n   an array of code lengths (max value 15, so we use unsigned char),\n   and an array of unsigned shorts used while building a table.  The\n   latter two arrays must be large enough to hold the maximum number\n   of code lengths, which RFC 1951 defines as 286 + 30.  */\n\n#define ZLIB_TABLE_SIZE \\\n  (2 * ZLIB_HUFFMAN_TABLE_SIZE * sizeof (uint16_t) \\\n   + (286 + 30) * sizeof (uint16_t)\t      \\\n   + (286 + 30) * sizeof (unsigned char))\n\n#define ZLIB_TABLE_CODELEN_OFFSET \\\n  (2 * ZLIB_HUFFMAN_TABLE_SIZE * sizeof (uint16_t) \\\n   + (286 + 30) * sizeof (uint16_t))\n\n#define ZLIB_TABLE_WORK_OFFSET \\\n  (2 * ZLIB_HUFFMAN_TABLE_SIZE * sizeof (uint16_t))\n\n#ifdef BACKTRACE_GENERATE_FIXED_HUFFMAN_TABLE\n\n/* Used by the main function that generates the fixed table to learn\n   the table size.  */\nstatic size_t final_next_secondary;\n\n#endif\n\n/* Build a Huffman code table from an array of lengths in CODES of\n   length CODES_LEN.  The table is stored into *TABLE.  ZDEBUG_TABLE\n   is the same as for elf_zlib_inflate, used to find some work space.\n   Returns 1 on success, 0 on error.  */\n\nstatic int\nelf_zlib_inflate_table (unsigned char *codes, size_t codes_len,\n\t\t\tuint16_t *zdebug_table, uint16_t *table)\n{\n  uint16_t count[16];\n  uint16_t start[16];\n  uint16_t prev[16];\n  uint16_t firstcode[7];\n  uint16_t *next;\n  size_t i;\n  size_t j;\n  unsigned int code;\n  size_t next_secondary;\n\n  /* Count the number of code of each length.  Set NEXT[val] to be the\n     next value after VAL with the same bit length.  */\n\n  next = (uint16_t *) (((unsigned char *) zdebug_table)\n\t\t       + ZLIB_TABLE_WORK_OFFSET);\n\n  memset (&count[0], 0, 16 * sizeof (uint16_t));\n  for (i = 0; i < codes_len; ++i)\n    {\n      if (unlikely (codes[i] >= 16))\n\t{\n\t  elf_uncompress_failed ();\n\t  return 0;\n\t}\n\n      if (count[codes[i]] == 0)\n\t{\n\t  start[codes[i]] = i;\n\t  prev[codes[i]] = i;\n\t}\n      else\n\t{\n\t  next[prev[codes[i]]] = i;\n\t  prev[codes[i]] = i;\n\t}\n\n      ++count[codes[i]];\n    }\n\n  /* For each length, fill in the table for the codes of that\n     length.  */\n\n  memset (table, 0, ZLIB_HUFFMAN_TABLE_SIZE * sizeof (uint16_t));\n\n  /* Handle the values that do not require a secondary table.  */\n\n  code = 0;\n  for (j = 1; j <= 8; ++j)\n    {\n      unsigned int jcnt;\n      unsigned int val;\n\n      jcnt = count[j];\n      if (jcnt == 0)\n\tcontinue;\n\n      if (unlikely (jcnt > (1U << j)))\n\t{\n\t  elf_uncompress_failed ();\n\t  return 0;\n\t}\n\n      /* There are JCNT values that have this length, the values\n\t starting from START[j] continuing through NEXT[VAL].  Those\n\t values are assigned consecutive values starting at CODE.  */\n\n      val = start[j];\n      for (i = 0; i < jcnt; ++i)\n\t{\n\t  uint16_t tval;\n\t  size_t ind;\n\t  unsigned int incr;\n\n\t  /* In the compressed bit stream, the value VAL is encoded as\n\t     J bits with the value C.  */\n\n\t  if (unlikely ((val & ~ZLIB_HUFFMAN_VALUE_MASK) != 0))\n\t    {\n\t      elf_uncompress_failed ();\n\t      return 0;\n\t    }\n\n\t  tval = val | ((j - 1) << ZLIB_HUFFMAN_BITS_SHIFT);\n\n\t  /* The table lookup uses 8 bits.  If J is less than 8, we\n\t     don't know what the other bits will be.  We need to fill\n\t     in all possibilities in the table.  Since the Huffman\n\t     code is unambiguous, those entries can't be used for any\n\t     other code.  */\n\n\t  for (ind = code; ind < 0x100; ind += 1 << j)\n\t    {\n\t      if (unlikely (table[ind] != 0))\n\t\t{\n\t\t  elf_uncompress_failed ();\n\t\t  return 0;\n\t\t}\n\t      table[ind] = tval;\n\t    }\n\n\t  /* Advance to the next value with this length.  */\n\t  if (i + 1 < jcnt)\n\t    val = next[val];\n\n\t  /* The Huffman codes are stored in the bitstream with the\n\t     most significant bit first, as is required to make them\n\t     unambiguous.  The effect is that when we read them from\n\t     the bitstream we see the bit sequence in reverse order:\n\t     the most significant bit of the Huffman code is the least\n\t     significant bit of the value we read from the bitstream.\n\t     That means that to make our table lookups work, we need\n\t     to reverse the bits of CODE.  Since reversing bits is\n\t     tedious and in general requires using a table, we instead\n\t     increment CODE in reverse order.  That is, if the number\n\t     of bits we are currently using, here named J, is 3, we\n\t     count as 000, 100, 010, 110, 001, 101, 011, 111, which is\n\t     to say the numbers from 0 to 7 but with the bits\n\t     reversed.  Going to more bits, aka incrementing J,\n\t     effectively just adds more zero bits as the beginning,\n\t     and as such does not change the numeric value of CODE.\n\n\t     To increment CODE of length J in reverse order, find the\n\t     most significant zero bit and set it to one while\n\t     clearing all higher bits.  In other words, add 1 modulo\n\t     2^J, only reversed.  */\n\n\t  incr = 1U << (j - 1);\n\t  while ((code & incr) != 0)\n\t    incr >>= 1;\n\t  if (incr == 0)\n\t    code = 0;\n\t  else\n\t    {\n\t      code &= incr - 1;\n\t      code += incr;\n\t    }\n\t}\n    }\n\n  /* Handle the values that require a secondary table.  */\n\n  /* Set FIRSTCODE, the number at which the codes start, for each\n     length.  */\n\n  for (j = 9; j < 16; j++)\n    {\n      unsigned int jcnt;\n      unsigned int k;\n\n      jcnt = count[j];\n      if (jcnt == 0)\n\tcontinue;\n\n      /* There are JCNT values that have this length, the values\n\t starting from START[j].  Those values are assigned\n\t consecutive values starting at CODE.  */\n\n      firstcode[j - 9] = code;\n\n      /* Reverse add JCNT to CODE modulo 2^J.  */\n      for (k = 0; k < j; ++k)\n\t{\n\t  if ((jcnt & (1U << k)) != 0)\n\t    {\n\t      unsigned int m;\n\t      unsigned int bit;\n\n\t      bit = 1U << (j - k - 1);\n\t      for (m = 0; m < j - k; ++m, bit >>= 1)\n\t\t{\n\t\t  if ((code & bit) == 0)\n\t\t    {\n\t\t      code += bit;\n\t\t      break;\n\t\t    }\n\t\t  code &= ~bit;\n\t\t}\n\t      jcnt &= ~(1U << k);\n\t    }\n\t}\n      if (unlikely (jcnt != 0))\n\t{\n\t  elf_uncompress_failed ();\n\t  return 0;\n\t}\n    }\n\n  /* For J from 9 to 15, inclusive, we store COUNT[J] consecutive\n     values starting at START[J] with consecutive codes starting at\n     FIRSTCODE[J - 9].  In the primary table we need to point to the\n     secondary table, and the secondary table will be indexed by J - 9\n     bits.  We count down from 15 so that we install the larger\n     secondary tables first, as the smaller ones may be embedded in\n     the larger ones.  */\n\n  next_secondary = 0; /* Index of next secondary table (after primary).  */\n  for (j = 15; j >= 9; j--)\n    {\n      unsigned int jcnt;\n      unsigned int val;\n      size_t primary; /* Current primary index.  */\n      size_t secondary; /* Offset to current secondary table.  */\n      size_t secondary_bits; /* Bit size of current secondary table.  */\n\n      jcnt = count[j];\n      if (jcnt == 0)\n\tcontinue;\n\n      val = start[j];\n      code = firstcode[j - 9];\n      primary = 0x100;\n      secondary = 0;\n      secondary_bits = 0;\n      for (i = 0; i < jcnt; ++i)\n\t{\n\t  uint16_t tval;\n\t  size_t ind;\n\t  unsigned int incr;\n\n\t  if ((code & 0xff) != primary)\n\t    {\n\t      uint16_t tprimary;\n\n\t      /* Fill in a new primary table entry.  */\n\n\t      primary = code & 0xff;\n\n\t      tprimary = table[primary];\n\t      if (tprimary == 0)\n\t\t{\n\t\t  /* Start a new secondary table.  */\n\n\t\t  if (unlikely ((next_secondary & ZLIB_HUFFMAN_VALUE_MASK)\n\t\t\t\t!= next_secondary))\n\t\t    {\n\t\t      elf_uncompress_failed ();\n\t\t      return 0;\n\t\t    }\n\n\t\t  secondary = next_secondary;\n\t\t  secondary_bits = j - 8;\n\t\t  next_secondary += 1 << secondary_bits;\n\t\t  table[primary] = (secondary\n\t\t\t\t    + ((j - 8) << ZLIB_HUFFMAN_BITS_SHIFT)\n\t\t\t\t    + (1U << ZLIB_HUFFMAN_SECONDARY_SHIFT));\n\t\t}\n\t      else\n\t\t{\n\t\t  /* There is an existing entry.  It had better be a\n\t\t     secondary table with enough bits.  */\n\t\t  if (unlikely ((tprimary\n\t\t\t\t & (1U << ZLIB_HUFFMAN_SECONDARY_SHIFT))\n\t\t\t\t== 0))\n\t\t    {\n\t\t      elf_uncompress_failed ();\n\t\t      return 0;\n\t\t    }\n\t\t  secondary = tprimary & ZLIB_HUFFMAN_VALUE_MASK;\n\t\t  secondary_bits = ((tprimary >> ZLIB_HUFFMAN_BITS_SHIFT)\n\t\t\t\t    & ZLIB_HUFFMAN_BITS_MASK);\n\t\t  if (unlikely (secondary_bits < j - 8))\n\t\t    {\n\t\t      elf_uncompress_failed ();\n\t\t      return 0;\n\t\t    }\n\t\t}\n\t    }\n\n\t  /* Fill in secondary table entries.  */\n\n\t  tval = val | ((j - 8) << ZLIB_HUFFMAN_BITS_SHIFT);\n\n\t  for (ind = code >> 8;\n\t       ind < (1U << secondary_bits);\n\t       ind += 1U << (j - 8))\n\t    {\n\t      if (unlikely (table[secondary + 0x100 + ind] != 0))\n\t\t{\n\t\t  elf_uncompress_failed ();\n\t\t  return 0;\n\t\t}\n\t      table[secondary + 0x100 + ind] = tval;\n\t    }\n\n\t  if (i + 1 < jcnt)\n\t    val = next[val];\n\n\t  incr = 1U << (j - 1);\n\t  while ((code & incr) != 0)\n\t    incr >>= 1;\n\t  if (incr == 0)\n\t    code = 0;\n\t  else\n\t    {\n\t      code &= incr - 1;\n\t      code += incr;\n\t    }\n\t}\n    }\n\n#ifdef BACKTRACE_GENERATE_FIXED_HUFFMAN_TABLE\n  final_next_secondary = next_secondary;\n#endif\n\n  return 1;\n}\n\n#ifdef BACKTRACE_GENERATE_FIXED_HUFFMAN_TABLE\n\n/* Used to generate the fixed Huffman table for block type 1.  */\n\n#include <stdio.h>\n\nstatic uint16_t table[ZLIB_TABLE_SIZE];\nstatic unsigned char codes[288];\n\nint\nmain ()\n{\n  size_t i;\n\n  for (i = 0; i <= 143; ++i)\n    codes[i] = 8;\n  for (i = 144; i <= 255; ++i)\n    codes[i] = 9;\n  for (i = 256; i <= 279; ++i)\n    codes[i] = 7;\n  for (i = 280; i <= 287; ++i)\n    codes[i] = 8;\n  if (!elf_zlib_inflate_table (&codes[0], 288, &table[0], &table[0]))\n    {\n      fprintf (stderr, \"elf_zlib_inflate_table failed\\n\");\n      exit (EXIT_FAILURE);\n    }\n\n  printf (\"static const uint16_t elf_zlib_default_table[%#zx] =\\n\",\n\t  final_next_secondary + 0x100);\n  printf (\"{\\n\");\n  for (i = 0; i < final_next_secondary + 0x100; i += 8)\n    {\n      size_t j;\n\n      printf (\" \");\n      for (j = i; j < final_next_secondary + 0x100 && j < i + 8; ++j)\n\tprintf (\" %#x,\", table[j]);\n      printf (\"\\n\");\n    }\n  printf (\"};\\n\");\n  printf (\"\\n\");\n\n  for (i = 0; i < 32; ++i)\n    codes[i] = 5;\n  if (!elf_zlib_inflate_table (&codes[0], 32, &table[0], &table[0]))\n    {\n      fprintf (stderr, \"elf_zlib_inflate_table failed\\n\");\n      exit (EXIT_FAILURE);\n    }\n\n  printf (\"static const uint16_t elf_zlib_default_dist_table[%#zx] =\\n\",\n\t  final_next_secondary + 0x100);\n  printf (\"{\\n\");\n  for (i = 0; i < final_next_secondary + 0x100; i += 8)\n    {\n      size_t j;\n\n      printf (\" \");\n      for (j = i; j < final_next_secondary + 0x100 && j < i + 8; ++j)\n\tprintf (\" %#x,\", table[j]);\n      printf (\"\\n\");\n    }\n  printf (\"};\\n\");\n\n  return 0;\n}\n\n#endif\n\n/* The fixed tables generated by the #ifdef'ed out main function\n   above.  */\n\nstatic const uint16_t elf_zlib_default_table[0x170] =\n{\n  0xd00, 0xe50, 0xe10, 0xf18, 0xd10, 0xe70, 0xe30, 0x1230,\n  0xd08, 0xe60, 0xe20, 0x1210, 0xe00, 0xe80, 0xe40, 0x1250,\n  0xd04, 0xe58, 0xe18, 0x1200, 0xd14, 0xe78, 0xe38, 0x1240,\n  0xd0c, 0xe68, 0xe28, 0x1220, 0xe08, 0xe88, 0xe48, 0x1260,\n  0xd02, 0xe54, 0xe14, 0xf1c, 0xd12, 0xe74, 0xe34, 0x1238,\n  0xd0a, 0xe64, 0xe24, 0x1218, 0xe04, 0xe84, 0xe44, 0x1258,\n  0xd06, 0xe5c, 0xe1c, 0x1208, 0xd16, 0xe7c, 0xe3c, 0x1248,\n  0xd0e, 0xe6c, 0xe2c, 0x1228, 0xe0c, 0xe8c, 0xe4c, 0x1268,\n  0xd01, 0xe52, 0xe12, 0xf1a, 0xd11, 0xe72, 0xe32, 0x1234,\n  0xd09, 0xe62, 0xe22, 0x1214, 0xe02, 0xe82, 0xe42, 0x1254,\n  0xd05, 0xe5a, 0xe1a, 0x1204, 0xd15, 0xe7a, 0xe3a, 0x1244,\n  0xd0d, 0xe6a, 0xe2a, 0x1224, 0xe0a, 0xe8a, 0xe4a, 0x1264,\n  0xd03, 0xe56, 0xe16, 0xf1e, 0xd13, 0xe76, 0xe36, 0x123c,\n  0xd0b, 0xe66, 0xe26, 0x121c, 0xe06, 0xe86, 0xe46, 0x125c,\n  0xd07, 0xe5e, 0xe1e, 0x120c, 0xd17, 0xe7e, 0xe3e, 0x124c,\n  0xd0f, 0xe6e, 0xe2e, 0x122c, 0xe0e, 0xe8e, 0xe4e, 0x126c,\n  0xd00, 0xe51, 0xe11, 0xf19, 0xd10, 0xe71, 0xe31, 0x1232,\n  0xd08, 0xe61, 0xe21, 0x1212, 0xe01, 0xe81, 0xe41, 0x1252,\n  0xd04, 0xe59, 0xe19, 0x1202, 0xd14, 0xe79, 0xe39, 0x1242,\n  0xd0c, 0xe69, 0xe29, 0x1222, 0xe09, 0xe89, 0xe49, 0x1262,\n  0xd02, 0xe55, 0xe15, 0xf1d, 0xd12, 0xe75, 0xe35, 0x123a,\n  0xd0a, 0xe65, 0xe25, 0x121a, 0xe05, 0xe85, 0xe45, 0x125a,\n  0xd06, 0xe5d, 0xe1d, 0x120a, 0xd16, 0xe7d, 0xe3d, 0x124a,\n  0xd0e, 0xe6d, 0xe2d, 0x122a, 0xe0d, 0xe8d, 0xe4d, 0x126a,\n  0xd01, 0xe53, 0xe13, 0xf1b, 0xd11, 0xe73, 0xe33, 0x1236,\n  0xd09, 0xe63, 0xe23, 0x1216, 0xe03, 0xe83, 0xe43, 0x1256,\n  0xd05, 0xe5b, 0xe1b, 0x1206, 0xd15, 0xe7b, 0xe3b, 0x1246,\n  0xd0d, 0xe6b, 0xe2b, 0x1226, 0xe0b, 0xe8b, 0xe4b, 0x1266,\n  0xd03, 0xe57, 0xe17, 0xf1f, 0xd13, 0xe77, 0xe37, 0x123e,\n  0xd0b, 0xe67, 0xe27, 0x121e, 0xe07, 0xe87, 0xe47, 0x125e,\n  0xd07, 0xe5f, 0xe1f, 0x120e, 0xd17, 0xe7f, 0xe3f, 0x124e,\n  0xd0f, 0xe6f, 0xe2f, 0x122e, 0xe0f, 0xe8f, 0xe4f, 0x126e,\n  0x290, 0x291, 0x292, 0x293, 0x294, 0x295, 0x296, 0x297,\n  0x298, 0x299, 0x29a, 0x29b, 0x29c, 0x29d, 0x29e, 0x29f,\n  0x2a0, 0x2a1, 0x2a2, 0x2a3, 0x2a4, 0x2a5, 0x2a6, 0x2a7,\n  0x2a8, 0x2a9, 0x2aa, 0x2ab, 0x2ac, 0x2ad, 0x2ae, 0x2af,\n  0x2b0, 0x2b1, 0x2b2, 0x2b3, 0x2b4, 0x2b5, 0x2b6, 0x2b7,\n  0x2b8, 0x2b9, 0x2ba, 0x2bb, 0x2bc, 0x2bd, 0x2be, 0x2bf,\n  0x2c0, 0x2c1, 0x2c2, 0x2c3, 0x2c4, 0x2c5, 0x2c6, 0x2c7,\n  0x2c8, 0x2c9, 0x2ca, 0x2cb, 0x2cc, 0x2cd, 0x2ce, 0x2cf,\n  0x2d0, 0x2d1, 0x2d2, 0x2d3, 0x2d4, 0x2d5, 0x2d6, 0x2d7,\n  0x2d8, 0x2d9, 0x2da, 0x2db, 0x2dc, 0x2dd, 0x2de, 0x2df,\n  0x2e0, 0x2e1, 0x2e2, 0x2e3, 0x2e4, 0x2e5, 0x2e6, 0x2e7,\n  0x2e8, 0x2e9, 0x2ea, 0x2eb, 0x2ec, 0x2ed, 0x2ee, 0x2ef,\n  0x2f0, 0x2f1, 0x2f2, 0x2f3, 0x2f4, 0x2f5, 0x2f6, 0x2f7,\n  0x2f8, 0x2f9, 0x2fa, 0x2fb, 0x2fc, 0x2fd, 0x2fe, 0x2ff,\n};\n\nstatic const uint16_t elf_zlib_default_dist_table[0x100] =\n{\n  0x800, 0x810, 0x808, 0x818, 0x804, 0x814, 0x80c, 0x81c,\n  0x802, 0x812, 0x80a, 0x81a, 0x806, 0x816, 0x80e, 0x81e,\n  0x801, 0x811, 0x809, 0x819, 0x805, 0x815, 0x80d, 0x81d,\n  0x803, 0x813, 0x80b, 0x81b, 0x807, 0x817, 0x80f, 0x81f,\n  0x800, 0x810, 0x808, 0x818, 0x804, 0x814, 0x80c, 0x81c,\n  0x802, 0x812, 0x80a, 0x81a, 0x806, 0x816, 0x80e, 0x81e,\n  0x801, 0x811, 0x809, 0x819, 0x805, 0x815, 0x80d, 0x81d,\n  0x803, 0x813, 0x80b, 0x81b, 0x807, 0x817, 0x80f, 0x81f,\n  0x800, 0x810, 0x808, 0x818, 0x804, 0x814, 0x80c, 0x81c,\n  0x802, 0x812, 0x80a, 0x81a, 0x806, 0x816, 0x80e, 0x81e,\n  0x801, 0x811, 0x809, 0x819, 0x805, 0x815, 0x80d, 0x81d,\n  0x803, 0x813, 0x80b, 0x81b, 0x807, 0x817, 0x80f, 0x81f,\n  0x800, 0x810, 0x808, 0x818, 0x804, 0x814, 0x80c, 0x81c,\n  0x802, 0x812, 0x80a, 0x81a, 0x806, 0x816, 0x80e, 0x81e,\n  0x801, 0x811, 0x809, 0x819, 0x805, 0x815, 0x80d, 0x81d,\n  0x803, 0x813, 0x80b, 0x81b, 0x807, 0x817, 0x80f, 0x81f,\n  0x800, 0x810, 0x808, 0x818, 0x804, 0x814, 0x80c, 0x81c,\n  0x802, 0x812, 0x80a, 0x81a, 0x806, 0x816, 0x80e, 0x81e,\n  0x801, 0x811, 0x809, 0x819, 0x805, 0x815, 0x80d, 0x81d,\n  0x803, 0x813, 0x80b, 0x81b, 0x807, 0x817, 0x80f, 0x81f,\n  0x800, 0x810, 0x808, 0x818, 0x804, 0x814, 0x80c, 0x81c,\n  0x802, 0x812, 0x80a, 0x81a, 0x806, 0x816, 0x80e, 0x81e,\n  0x801, 0x811, 0x809, 0x819, 0x805, 0x815, 0x80d, 0x81d,\n  0x803, 0x813, 0x80b, 0x81b, 0x807, 0x817, 0x80f, 0x81f,\n  0x800, 0x810, 0x808, 0x818, 0x804, 0x814, 0x80c, 0x81c,\n  0x802, 0x812, 0x80a, 0x81a, 0x806, 0x816, 0x80e, 0x81e,\n  0x801, 0x811, 0x809, 0x819, 0x805, 0x815, 0x80d, 0x81d,\n  0x803, 0x813, 0x80b, 0x81b, 0x807, 0x817, 0x80f, 0x81f,\n  0x800, 0x810, 0x808, 0x818, 0x804, 0x814, 0x80c, 0x81c,\n  0x802, 0x812, 0x80a, 0x81a, 0x806, 0x816, 0x80e, 0x81e,\n  0x801, 0x811, 0x809, 0x819, 0x805, 0x815, 0x80d, 0x81d,\n  0x803, 0x813, 0x80b, 0x81b, 0x807, 0x817, 0x80f, 0x81f,\n};\n\n/* Inflate a zlib stream from PIN/SIN to POUT/SOUT.  Return 1 on\n   success, 0 on some error parsing the stream.  */\n\nstatic int\nelf_zlib_inflate (const unsigned char *pin, size_t sin, uint16_t *zdebug_table,\n\t\t  unsigned char *pout, size_t sout)\n{\n  unsigned char *porigout;\n  const unsigned char *pinend;\n  unsigned char *poutend;\n\n  /* We can apparently see multiple zlib streams concatenated\n     together, so keep going as long as there is something to read.\n     The last 4 bytes are the checksum.  */\n  porigout = pout;\n  pinend = pin + sin;\n  poutend = pout + sout;\n  while ((pinend - pin) > 4)\n    {\n      uint64_t val;\n      unsigned int bits;\n      int last;\n\n      /* Read the two byte zlib header.  */\n\n      if (unlikely ((pin[0] & 0xf) != 8)) /* 8 is zlib encoding.  */\n\t{\n\t  /* Unknown compression method.  */\n\t  elf_uncompress_failed ();\n\t  return 0;\n\t}\n      if (unlikely ((pin[0] >> 4) > 7))\n\t{\n\t  /* Window size too large.  Other than this check, we don't\n\t     care about the window size.  */\n\t  elf_uncompress_failed ();\n\t  return 0;\n\t}\n      if (unlikely ((pin[1] & 0x20) != 0))\n\t{\n\t  /* Stream expects a predefined dictionary, but we have no\n\t     dictionary.  */\n\t  elf_uncompress_failed ();\n\t  return 0;\n\t}\n      val = (pin[0] << 8) | pin[1];\n      if (unlikely (val % 31 != 0))\n\t{\n\t  /* Header check failure.  */\n\t  elf_uncompress_failed ();\n\t  return 0;\n\t}\n      pin += 2;\n\n      /* Align PIN to a 32-bit boundary.  */\n\n      val = 0;\n      bits = 0;\n      while ((((uintptr_t) pin) & 3) != 0)\n\t{\n\t  val |= (uint64_t)*pin << bits;\n\t  bits += 8;\n\t  ++pin;\n\t}\n\n      /* Read blocks until one is marked last.  */\n\n      last = 0;\n\n      while (!last)\n\t{\n\t  unsigned int type;\n\t  const uint16_t *tlit;\n\t  const uint16_t *tdist;\n\n\t  if (!elf_fetch_bits (&pin, pinend, &val, &bits))\n\t    return 0;\n\n\t  last = val & 1;\n\t  type = (val >> 1) & 3;\n\t  val >>= 3;\n\t  bits -= 3;\n\n\t  if (unlikely (type == 3))\n\t    {\n\t      /* Invalid block type.  */\n\t      elf_uncompress_failed ();\n\t      return 0;\n\t    }\n\n\t  if (type == 0)\n\t    {\n\t      uint16_t len;\n\t      uint16_t lenc;\n\n\t      /* An uncompressed block.  */\n\n\t      /* If we've read ahead more than a byte, back up.  */\n\t      while (bits >= 8)\n\t\t{\n\t\t  --pin;\n\t\t  bits -= 8;\n\t\t}\n\n\t      val = 0;\n\t      bits = 0;\n\t      if (unlikely ((pinend - pin) < 4))\n\t\t{\n\t\t  /* Missing length.  */\n\t\t  elf_uncompress_failed ();\n\t\t  return 0;\n\t\t}\n\t      len = pin[0] | (pin[1] << 8);\n\t      lenc = pin[2] | (pin[3] << 8);\n\t      pin += 4;\n\t      lenc = ~lenc;\n\t      if (unlikely (len != lenc))\n\t\t{\n\t\t  /* Corrupt data.  */\n\t\t  elf_uncompress_failed ();\n\t\t  return 0;\n\t\t}\n\t      if (unlikely (len > (unsigned int) (pinend - pin)\n\t\t\t    || len > (unsigned int) (poutend - pout)))\n\t\t{\n\t\t  /* Not enough space in buffers.  */\n\t\t  elf_uncompress_failed ();\n\t\t  return 0;\n\t\t}\n\t      memcpy (pout, pin, len);\n\t      pout += len;\n\t      pin += len;\n\n\t      /* Align PIN.  */\n\t      while ((((uintptr_t) pin) & 3) != 0)\n\t\t{\n\t\t  val |= (uint64_t)*pin << bits;\n\t\t  bits += 8;\n\t\t  ++pin;\n\t\t}\n\n\t      /* Go around to read the next block.  */\n\t      continue;\n\t    }\n\n\t  if (type == 1)\n\t    {\n\t      tlit = elf_zlib_default_table;\n\t      tdist = elf_zlib_default_dist_table;\n\t    }\n\t  else\n\t    {\n\t      unsigned int nlit;\n\t      unsigned int ndist;\n\t      unsigned int nclen;\n\t      unsigned char codebits[19];\n\t      unsigned char *plenbase;\n\t      unsigned char *plen;\n\t      unsigned char *plenend;\n\n\t      /* Read a Huffman encoding table.  The various magic\n\t\t numbers here are from RFC 1951.  */\n\n\t      if (!elf_fetch_bits (&pin, pinend, &val, &bits))\n\t\treturn 0;\n\n\t      nlit = (val & 0x1f) + 257;\n\t      val >>= 5;\n\t      ndist = (val & 0x1f) + 1;\n\t      val >>= 5;\n\t      nclen = (val & 0xf) + 4;\n\t      val >>= 4;\n\t      bits -= 14;\n\t      if (unlikely (nlit > 286 || ndist > 30))\n\t\t{\n\t\t  /* Values out of range.  */\n\t\t  elf_uncompress_failed ();\n\t\t  return 0;\n\t\t}\n\n\t      /* Read and build the table used to compress the\n\t\t literal, length, and distance codes.  */\n\n\t      memset(&codebits[0], 0, 19);\n\n\t      /* There are always at least 4 elements in the\n\t\t table.  */\n\n\t      if (!elf_fetch_bits (&pin, pinend, &val, &bits))\n\t\treturn 0;\n\n\t      codebits[16] = val & 7;\n\t      codebits[17] = (val >> 3) & 7;\n\t      codebits[18] = (val >> 6) & 7;\n\t      codebits[0] = (val >> 9) & 7;\n\t      val >>= 12;\n\t      bits -= 12;\n\n\t      if (nclen == 4)\n\t\tgoto codebitsdone;\n\n\t      codebits[8] = val & 7;\n\t      val >>= 3;\n\t      bits -= 3;\n\n\t      if (nclen == 5)\n\t\tgoto codebitsdone;\n\n\t      if (!elf_fetch_bits (&pin, pinend, &val, &bits))\n\t\treturn 0;\n\n\t      codebits[7] = val & 7;\n\t      val >>= 3;\n\t      bits -= 3;\n\n\t      if (nclen == 6)\n\t\tgoto codebitsdone;\n\n\t      codebits[9] = val & 7;\n\t      val >>= 3;\n\t      bits -= 3;\n\n\t      if (nclen == 7)\n\t\tgoto codebitsdone;\n\n\t      codebits[6] = val & 7;\n\t      val >>= 3;\n\t      bits -= 3;\n\n\t      if (nclen == 8)\n\t\tgoto codebitsdone;\n\n\t      codebits[10] = val & 7;\n\t      val >>= 3;\n\t      bits -= 3;\n\n\t      if (nclen == 9)\n\t\tgoto codebitsdone;\n\n\t      codebits[5] = val & 7;\n\t      val >>= 3;\n\t      bits -= 3;\n\n\t      if (nclen == 10)\n\t\tgoto codebitsdone;\n\n\t      if (!elf_fetch_bits (&pin, pinend, &val, &bits))\n\t\treturn 0;\n\n\t      codebits[11] = val & 7;\n\t      val >>= 3;\n\t      bits -= 3;\n\n\t      if (nclen == 11)\n\t\tgoto codebitsdone;\n\n\t      codebits[4] = val & 7;\n\t      val >>= 3;\n\t      bits -= 3;\n\n\t      if (nclen == 12)\n\t\tgoto codebitsdone;\n\n\t      codebits[12] = val & 7;\n\t      val >>= 3;\n\t      bits -= 3;\n\n\t      if (nclen == 13)\n\t\tgoto codebitsdone;\n\n\t      codebits[3] = val & 7;\n\t      val >>= 3;\n\t      bits -= 3;\n\n\t      if (nclen == 14)\n\t\tgoto codebitsdone;\n\n\t      codebits[13] = val & 7;\n\t      val >>= 3;\n\t      bits -= 3;\n\n\t      if (nclen == 15)\n\t\tgoto codebitsdone;\n\n\t      if (!elf_fetch_bits (&pin, pinend, &val, &bits))\n\t\treturn 0;\n\n\t      codebits[2] = val & 7;\n\t      val >>= 3;\n\t      bits -= 3;\n\n\t      if (nclen == 16)\n\t\tgoto codebitsdone;\n\n\t      codebits[14] = val & 7;\n\t      val >>= 3;\n\t      bits -= 3;\n\n\t      if (nclen == 17)\n\t\tgoto codebitsdone;\n\n\t      codebits[1] = val & 7;\n\t      val >>= 3;\n\t      bits -= 3;\n\n\t      if (nclen == 18)\n\t\tgoto codebitsdone;\n\n\t      codebits[15] = val & 7;\n\t      val >>= 3;\n\t      bits -= 3;\n\n\t    codebitsdone:\n\n\t      if (!elf_zlib_inflate_table (codebits, 19, zdebug_table,\n\t\t\t\t\t   zdebug_table))\n\t\treturn 0;\n\n\t      /* Read the compressed bit lengths of the literal,\n\t\t length, and distance codes.  We have allocated space\n\t\t at the end of zdebug_table to hold them.  */\n\n\t      plenbase = (((unsigned char *) zdebug_table)\n\t\t\t  + ZLIB_TABLE_CODELEN_OFFSET);\n\t      plen = plenbase;\n\t      plenend = plen + nlit + ndist;\n\t      while (plen < plenend)\n\t\t{\n\t\t  uint16_t t;\n\t\t  unsigned int b;\n\t\t  uint16_t v;\n\n\t\t  if (!elf_fetch_bits (&pin, pinend, &val, &bits))\n\t\t    return 0;\n\n\t\t  t = zdebug_table[val & 0xff];\n\n\t\t  /* The compression here uses bit lengths up to 7, so\n\t\t     a secondary table is never necessary.  */\n\t\t  if (unlikely ((t & (1U << ZLIB_HUFFMAN_SECONDARY_SHIFT))\n\t\t\t\t!= 0))\n\t\t    {\n\t\t      elf_uncompress_failed ();\n\t\t      return 0;\n\t\t    }\n\n\t\t  b = (t >> ZLIB_HUFFMAN_BITS_SHIFT) & ZLIB_HUFFMAN_BITS_MASK;\n\t\t  val >>= b + 1;\n\t\t  bits -= b + 1;\n\n\t\t  v = t & ZLIB_HUFFMAN_VALUE_MASK;\n\t\t  if (v < 16)\n\t\t    *plen++ = v;\n\t\t  else if (v == 16)\n\t\t    {\n\t\t      unsigned int c;\n\t\t      unsigned int prev;\n\n\t\t      /* Copy previous entry 3 to 6 times.  */\n\n\t\t      if (unlikely (plen == plenbase))\n\t\t\t{\n\t\t\t  elf_uncompress_failed ();\n\t\t\t  return 0;\n\t\t\t}\n\n\t\t      /* We used up to 7 bits since the last\n\t\t\t elf_fetch_bits, so we have at least 8 bits\n\t\t\t available here.  */\n\n\t\t      c = 3 + (val & 0x3);\n\t\t      val >>= 2;\n\t\t      bits -= 2;\n\t\t      if (unlikely ((unsigned int) (plenend - plen) < c))\n\t\t\t{\n\t\t\t  elf_uncompress_failed ();\n\t\t\t  return 0;\n\t\t\t}\n\n\t\t      prev = plen[-1];\n\t\t      switch (c)\n\t\t\t{\n\t\t\tcase 6:\n\t\t\t  *plen++ = prev;\n\t\t\t  ATTRIBUTE_FALLTHROUGH;\n\t\t\tcase 5:\n\t\t\t  *plen++ = prev;\n\t\t\t  ATTRIBUTE_FALLTHROUGH;\n\t\t\tcase 4:\n\t\t\t  *plen++ = prev;\n\t\t\t}\n\t\t      *plen++ = prev;\n\t\t      *plen++ = prev;\n\t\t      *plen++ = prev;\n\t\t    }\n\t\t  else if (v == 17)\n\t\t    {\n\t\t      unsigned int c;\n\n\t\t      /* Store zero 3 to 10 times.  */\n\n\t\t      /* We used up to 7 bits since the last\n\t\t\t elf_fetch_bits, so we have at least 8 bits\n\t\t\t available here.  */\n\n\t\t      c = 3 + (val & 0x7);\n\t\t      val >>= 3;\n\t\t      bits -= 3;\n\t\t      if (unlikely ((unsigned int) (plenend - plen) < c))\n\t\t\t{\n\t\t\t  elf_uncompress_failed ();\n\t\t\t  return 0;\n\t\t\t}\n\n\t\t      switch (c)\n\t\t\t{\n\t\t\tcase 10:\n\t\t\t  *plen++ = 0;\n\t\t\t  ATTRIBUTE_FALLTHROUGH;\n\t\t\tcase 9:\n\t\t\t  *plen++ = 0;\n\t\t\t  ATTRIBUTE_FALLTHROUGH;\n\t\t\tcase 8:\n\t\t\t  *plen++ = 0;\n\t\t\t  ATTRIBUTE_FALLTHROUGH;\n\t\t\tcase 7:\n\t\t\t  *plen++ = 0;\n\t\t\t  ATTRIBUTE_FALLTHROUGH;\n\t\t\tcase 6:\n\t\t\t  *plen++ = 0;\n\t\t\t  ATTRIBUTE_FALLTHROUGH;\n\t\t\tcase 5:\n\t\t\t  *plen++ = 0;\n\t\t\t  ATTRIBUTE_FALLTHROUGH;\n\t\t\tcase 4:\n\t\t\t  *plen++ = 0;\n\t\t\t}\n\t\t      *plen++ = 0;\n\t\t      *plen++ = 0;\n\t\t      *plen++ = 0;\n\t\t    }\n\t\t  else if (v == 18)\n\t\t    {\n\t\t      unsigned int c;\n\n\t\t      /* Store zero 11 to 138 times.  */\n\n\t\t      /* We used up to 7 bits since the last\n\t\t\t elf_fetch_bits, so we have at least 8 bits\n\t\t\t available here.  */\n\n\t\t      c = 11 + (val & 0x7f);\n\t\t      val >>= 7;\n\t\t      bits -= 7;\n\t\t      if (unlikely ((unsigned int) (plenend - plen) < c))\n\t\t\t{\n\t\t\t  elf_uncompress_failed ();\n\t\t\t  return 0;\n\t\t\t}\n\n\t\t      memset (plen, 0, c);\n\t\t      plen += c;\n\t\t    }\n\t\t  else\n\t\t    {\n\t\t      elf_uncompress_failed ();\n\t\t      return 0;\n\t\t    }\n\t\t}\n\n\t      /* Make sure that the stop code can appear.  */\n\n\t      plen = plenbase;\n\t      if (unlikely (plen[256] == 0))\n\t\t{\n\t\t  elf_uncompress_failed ();\n\t\t  return 0;\n\t\t}\n\n\t      /* Build the decompression tables.  */\n\n\t      if (!elf_zlib_inflate_table (plen, nlit, zdebug_table,\n\t\t\t\t\t   zdebug_table))\n\t\treturn 0;\n\t      if (!elf_zlib_inflate_table (plen + nlit, ndist, zdebug_table,\n\t\t\t\t\t   (zdebug_table\n\t\t\t\t\t    + ZLIB_HUFFMAN_TABLE_SIZE)))\n\t\treturn 0;\n\t      tlit = zdebug_table;\n\t      tdist = zdebug_table + ZLIB_HUFFMAN_TABLE_SIZE;\n\t    }\n\n\t  /* Inflate values until the end of the block.  This is the\n\t     main loop of the inflation code.  */\n\n\t  while (1)\n\t    {\n\t      uint16_t t;\n\t      unsigned int b;\n\t      uint16_t v;\n\t      unsigned int lit;\n\n\t      if (!elf_fetch_bits (&pin, pinend, &val, &bits))\n\t\treturn 0;\n\n\t      t = tlit[val & 0xff];\n\t      b = (t >> ZLIB_HUFFMAN_BITS_SHIFT) & ZLIB_HUFFMAN_BITS_MASK;\n\t      v = t & ZLIB_HUFFMAN_VALUE_MASK;\n\n\t      if ((t & (1U << ZLIB_HUFFMAN_SECONDARY_SHIFT)) == 0)\n\t\t{\n\t\t  lit = v;\n\t\t  val >>= b + 1;\n\t\t  bits -= b + 1;\n\t\t}\n\t      else\n\t\t{\n\t\t  t = tlit[v + 0x100 + ((val >> 8) & ((1U << b) - 1))];\n\t\t  b = (t >> ZLIB_HUFFMAN_BITS_SHIFT) & ZLIB_HUFFMAN_BITS_MASK;\n\t\t  lit = t & ZLIB_HUFFMAN_VALUE_MASK;\n\t\t  val >>= b + 8;\n\t\t  bits -= b + 8;\n\t\t}\n\n\t      if (lit < 256)\n\t\t{\n\t\t  if (unlikely (pout == poutend))\n\t\t    {\n\t\t      elf_uncompress_failed ();\n\t\t      return 0;\n\t\t    }\n\n\t\t  *pout++ = lit;\n\n\t\t  /* We will need to write the next byte soon.  We ask\n\t\t     for high temporal locality because we will write\n\t\t     to the whole cache line soon.  */\n\t\t  __builtin_prefetch (pout, 1, 3);\n\t\t}\n\t      else if (lit == 256)\n\t\t{\n\t\t  /* The end of the block.  */\n\t\t  break;\n\t\t}\n\t      else\n\t\t{\n\t\t  unsigned int dist;\n\t\t  unsigned int len;\n\n\t\t  /* Convert lit into a length.  */\n\n\t\t  if (lit < 265)\n\t\t    len = lit - 257 + 3;\n\t\t  else if (lit == 285)\n\t\t    len = 258;\n\t\t  else if (unlikely (lit > 285))\n\t\t    {\n\t\t      elf_uncompress_failed ();\n\t\t      return 0;\n\t\t    }\n\t\t  else\n\t\t    {\n\t\t      unsigned int extra;\n\n\t\t      if (!elf_fetch_bits (&pin, pinend, &val, &bits))\n\t\t\treturn 0;\n\n\t\t      /* This is an expression for the table of length\n\t\t\t codes in RFC 1951 3.2.5.  */\n\t\t      lit -= 265;\n\t\t      extra = (lit >> 2) + 1;\n\t\t      len = (lit & 3) << extra;\n\t\t      len += 11;\n\t\t      len += ((1U << (extra - 1)) - 1) << 3;\n\t\t      len += val & ((1U << extra) - 1);\n\t\t      val >>= extra;\n\t\t      bits -= extra;\n\t\t    }\n\n\t\t  if (!elf_fetch_bits (&pin, pinend, &val, &bits))\n\t\t    return 0;\n\n\t\t  t = tdist[val & 0xff];\n\t\t  b = (t >> ZLIB_HUFFMAN_BITS_SHIFT) & ZLIB_HUFFMAN_BITS_MASK;\n\t\t  v = t & ZLIB_HUFFMAN_VALUE_MASK;\n\n\t\t  if ((t & (1U << ZLIB_HUFFMAN_SECONDARY_SHIFT)) == 0)\n\t\t    {\n\t\t      dist = v;\n\t\t      val >>= b + 1;\n\t\t      bits -= b + 1;\n\t\t    }\n\t\t  else\n\t\t    {\n\t\t      t = tdist[v + 0x100 + ((val >> 8) & ((1U << b) - 1))];\n\t\t      b = ((t >> ZLIB_HUFFMAN_BITS_SHIFT)\n\t\t\t   & ZLIB_HUFFMAN_BITS_MASK);\n\t\t      dist = t & ZLIB_HUFFMAN_VALUE_MASK;\n\t\t      val >>= b + 8;\n\t\t      bits -= b + 8;\n\t\t    }\n\n\t\t  /* Convert dist to a distance.  */\n\n\t\t  if (dist == 0)\n\t\t    {\n\t\t      /* A distance of 1.  A common case, meaning\n\t\t\t repeat the last character LEN times.  */\n\n\t\t      if (unlikely (pout == porigout))\n\t\t\t{\n\t\t\t  elf_uncompress_failed ();\n\t\t\t  return 0;\n\t\t\t}\n\n\t\t      if (unlikely ((unsigned int) (poutend - pout) < len))\n\t\t\t{\n\t\t\t  elf_uncompress_failed ();\n\t\t\t  return 0;\n\t\t\t}\n\n\t\t      memset (pout, pout[-1], len);\n\t\t      pout += len;\n\t\t    }\n\t\t  else if (unlikely (dist > 29))\n\t\t    {\n\t\t      elf_uncompress_failed ();\n\t\t      return 0;\n\t\t    }\n\t\t  else\n\t\t    {\n\t\t      if (dist < 4)\n\t\t\tdist = dist + 1;\n\t\t      else\n\t\t\t{\n\t\t\t  unsigned int extra;\n\n\t\t\t  if (!elf_fetch_bits (&pin, pinend, &val, &bits))\n\t\t\t    return 0;\n\n\t\t\t  /* This is an expression for the table of\n\t\t\t     distance codes in RFC 1951 3.2.5.  */\n\t\t\t  dist -= 4;\n\t\t\t  extra = (dist >> 1) + 1;\n\t\t\t  dist = (dist & 1) << extra;\n\t\t\t  dist += 5;\n\t\t\t  dist += ((1U << (extra - 1)) - 1) << 2;\n\t\t\t  dist += val & ((1U << extra) - 1);\n\t\t\t  val >>= extra;\n\t\t\t  bits -= extra;\n\t\t\t}\n\n\t\t      /* Go back dist bytes, and copy len bytes from\n\t\t\t there.  */\n\n\t\t      if (unlikely ((unsigned int) (pout - porigout) < dist))\n\t\t\t{\n\t\t\t  elf_uncompress_failed ();\n\t\t\t  return 0;\n\t\t\t}\n\n\t\t      if (unlikely ((unsigned int) (poutend - pout) < len))\n\t\t\t{\n\t\t\t  elf_uncompress_failed ();\n\t\t\t  return 0;\n\t\t\t}\n\n\t\t      if (dist >= len)\n\t\t\t{\n\t\t\t  memcpy (pout, pout - dist, len);\n\t\t\t  pout += len;\n\t\t\t}\n\t\t      else\n\t\t\t{\n\t\t\t  while (len > 0)\n\t\t\t    {\n\t\t\t      unsigned int copy;\n\n\t\t\t      copy = len < dist ? len : dist;\n\t\t\t      memcpy (pout, pout - dist, copy);\n\t\t\t      len -= copy;\n\t\t\t      pout += copy;\n\t\t\t    }\n\t\t\t}\n\t\t    }\n\t\t}\n\t    }\n\t}\n    }\n\n  /* We should have filled the output buffer.  */\n  if (unlikely (pout != poutend))\n    {\n      elf_uncompress_failed ();\n      return 0;\n    }\n\n  return 1;\n}\n\n/* Verify the zlib checksum.  The checksum is in the 4 bytes at\n   CHECKBYTES, and the uncompressed data is at UNCOMPRESSED /\n   UNCOMPRESSED_SIZE.  Returns 1 on success, 0 on failure.  */\n\nstatic int\nelf_zlib_verify_checksum (const unsigned char *checkbytes,\n\t\t\t  const unsigned char *uncompressed,\n\t\t\t  size_t uncompressed_size)\n{\n  unsigned int i;\n  unsigned int cksum;\n  const unsigned char *p;\n  uint32_t s1;\n  uint32_t s2;\n  size_t hsz;\n\n  cksum = 0;\n  for (i = 0; i < 4; i++)\n    cksum = (cksum << 8) | checkbytes[i];\n\n  s1 = 1;\n  s2 = 0;\n\n  /* Minimize modulo operations.  */\n\n  p = uncompressed;\n  hsz = uncompressed_size;\n  while (hsz >= 5552)\n    {\n      for (i = 0; i < 5552; i += 16)\n\t{\n\t  /* Manually unroll loop 16 times.  */\n\t  s1 = s1 + *p++;\n\t  s2 = s2 + s1;\n\t  s1 = s1 + *p++;\n\t  s2 = s2 + s1;\n\t  s1 = s1 + *p++;\n\t  s2 = s2 + s1;\n\t  s1 = s1 + *p++;\n\t  s2 = s2 + s1;\n\t  s1 = s1 + *p++;\n\t  s2 = s2 + s1;\n\t  s1 = s1 + *p++;\n\t  s2 = s2 + s1;\n\t  s1 = s1 + *p++;\n\t  s2 = s2 + s1;\n\t  s1 = s1 + *p++;\n\t  s2 = s2 + s1;\n\t  s1 = s1 + *p++;\n\t  s2 = s2 + s1;\n\t  s1 = s1 + *p++;\n\t  s2 = s2 + s1;\n\t  s1 = s1 + *p++;\n\t  s2 = s2 + s1;\n\t  s1 = s1 + *p++;\n\t  s2 = s2 + s1;\n\t  s1 = s1 + *p++;\n\t  s2 = s2 + s1;\n\t  s1 = s1 + *p++;\n\t  s2 = s2 + s1;\n\t  s1 = s1 + *p++;\n\t  s2 = s2 + s1;\n\t  s1 = s1 + *p++;\n\t  s2 = s2 + s1;\n\t}\n      hsz -= 5552;\n      s1 %= 65521;\n      s2 %= 65521;\n    }\n\n  while (hsz >= 16)\n    {\n      /* Manually unroll loop 16 times.  */\n      s1 = s1 + *p++;\n      s2 = s2 + s1;\n      s1 = s1 + *p++;\n      s2 = s2 + s1;\n      s1 = s1 + *p++;\n      s2 = s2 + s1;\n      s1 = s1 + *p++;\n      s2 = s2 + s1;\n      s1 = s1 + *p++;\n      s2 = s2 + s1;\n      s1 = s1 + *p++;\n      s2 = s2 + s1;\n      s1 = s1 + *p++;\n      s2 = s2 + s1;\n      s1 = s1 + *p++;\n      s2 = s2 + s1;\n      s1 = s1 + *p++;\n      s2 = s2 + s1;\n      s1 = s1 + *p++;\n      s2 = s2 + s1;\n      s1 = s1 + *p++;\n      s2 = s2 + s1;\n      s1 = s1 + *p++;\n      s2 = s2 + s1;\n      s1 = s1 + *p++;\n      s2 = s2 + s1;\n      s1 = s1 + *p++;\n      s2 = s2 + s1;\n      s1 = s1 + *p++;\n      s2 = s2 + s1;\n      s1 = s1 + *p++;\n      s2 = s2 + s1;\n\n      hsz -= 16;\n    }\n\n  for (i = 0; i < hsz; ++i)\n    {\n      s1 = s1 + *p++;\n      s2 = s2 + s1;\n    }\n\n  s1 %= 65521;\n  s2 %= 65521;\n\n  if (unlikely ((s2 << 16) + s1 != cksum))\n    {\n      elf_uncompress_failed ();\n      return 0;\n    }\n\n  return 1;\n}\n\n/* Inflate a zlib stream from PIN/SIN to POUT/SOUT, and verify the\n   checksum.  Return 1 on success, 0 on error.  */\n\nstatic int\nelf_zlib_inflate_and_verify (const unsigned char *pin, size_t sin,\n\t\t\t     uint16_t *zdebug_table, unsigned char *pout,\n\t\t\t     size_t sout)\n{\n  if (!elf_zlib_inflate (pin, sin, zdebug_table, pout, sout))\n    return 0;\n  if (!elf_zlib_verify_checksum (pin + sin - 4, pout, sout))\n    return 0;\n  return 1;\n}\n\n/* For working memory during zstd compression, we need\n   - a literal length FSE table: 512 64-bit values == 4096 bytes\n   - a match length FSE table: 512 64-bit values == 4096 bytes\n   - a offset FSE table: 256 64-bit values == 2048 bytes\n   - a Huffman tree: 2048 uint16_t values == 4096 bytes\n   - scratch space, one of\n     - to build an FSE table: 512 uint16_t values == 1024 bytes\n     - to build a Huffman tree: 512 uint16_t + 256 uint32_t == 2048 bytes\n*/\n\n#define ZSTD_TABLE_SIZE\t\t\t\t\t\\\n  (2 * 512 * sizeof (struct elf_zstd_fse_baseline_entry)\t\\\n   + 256 * sizeof (struct elf_zstd_fse_baseline_entry)\t\t\\\n   + 2048 * sizeof (uint16_t)\t\t\t\t\t\\\n   + 512 * sizeof (uint16_t) + 256 * sizeof (uint32_t))\n\n#define ZSTD_TABLE_LITERAL_FSE_OFFSET (0)\n\n#define ZSTD_TABLE_MATCH_FSE_OFFSET\t\t\t\\\n  (512 * sizeof (struct elf_zstd_fse_baseline_entry))\n\n#define ZSTD_TABLE_OFFSET_FSE_OFFSET\t\t\t\\\n  (ZSTD_TABLE_MATCH_FSE_OFFSET\t\t\t\t\\\n   + 512 * sizeof (struct elf_zstd_fse_baseline_entry))\n\n#define ZSTD_TABLE_HUFFMAN_OFFSET\t\t\t\t\t\\\n  (ZSTD_TABLE_OFFSET_FSE_OFFSET\t\t\t\t\t\t\\\n   + 256 * sizeof (struct elf_zstd_fse_baseline_entry))\n\n#define ZSTD_TABLE_WORK_OFFSET \\\n  (ZSTD_TABLE_HUFFMAN_OFFSET + 2048 * sizeof (uint16_t))\n\n/* An entry in a zstd FSE table.  */\n\nstruct elf_zstd_fse_entry\n{\n  /* The value that this FSE entry represents.  */\n  unsigned char symbol;\n  /* The number of bits to read to determine the next state.  */\n  unsigned char bits;\n  /* Add the bits to this base to get the next state.  */\n  uint16_t base;\n};\n\nstatic int\nelf_zstd_build_fse (const int16_t *, int, uint16_t *, int,\n\t\t    struct elf_zstd_fse_entry *);\n\n/* Read a zstd FSE table and build the decoding table in *TABLE, updating *PPIN\n   as it reads.  ZDEBUG_TABLE is scratch space; it must be enough for 512\n   uint16_t values (1024 bytes).  MAXIDX is the maximum number of symbols\n   permitted. *TABLE_BITS is the maximum number of bits for symbols in the\n   table: the size of *TABLE is at least 1 << *TABLE_BITS.  This updates\n   *TABLE_BITS to the actual number of bits.  Returns 1 on success, 0 on\n   error.  */\n\nstatic int\nelf_zstd_read_fse (const unsigned char **ppin, const unsigned char *pinend,\n\t\t   uint16_t *zdebug_table, int maxidx,\n\t\t   struct elf_zstd_fse_entry *table, int *table_bits)\n{\n  const unsigned char *pin;\n  int16_t *norm;\n  uint16_t *next;\n  uint64_t val;\n  unsigned int bits;\n  int accuracy_log;\n  uint32_t remaining;\n  uint32_t threshold;\n  int bits_needed;\n  int idx;\n  int prev0;\n\n  pin = *ppin;\n\n  norm = (int16_t *) zdebug_table;\n  next = zdebug_table + 256;\n\n  if (unlikely (pin + 3 >= pinend))\n    {\n      elf_uncompress_failed ();\n      return 0;\n    }\n\n  /* Align PIN to a 32-bit boundary.  */\n\n  val = 0;\n  bits = 0;\n  while ((((uintptr_t) pin) & 3) != 0)\n    {\n      val |= (uint64_t)*pin << bits;\n      bits += 8;\n      ++pin;\n    }\n\n  if (!elf_fetch_bits (&pin, pinend, &val, &bits))\n    return 0;\n\n  accuracy_log = (val & 0xf) + 5;\n  if (accuracy_log > *table_bits)\n    {\n      elf_uncompress_failed ();\n      return 0;\n    }\n  *table_bits = accuracy_log;\n  val >>= 4;\n  bits -= 4;\n\n  /* This code is mostly copied from the reference implementation.  */\n\n  /* The number of remaining probabilities, plus 1.  This sets the number of\n     bits that need to be read for the next value.  */\n  remaining = (1 << accuracy_log) + 1;\n\n  /* The current difference between small and large values, which depends on\n     the number of remaining values.  Small values use one less bit.  */\n  threshold = 1 << accuracy_log;\n\n  /* The number of bits used to compute threshold.  */\n  bits_needed = accuracy_log + 1;\n\n  /* The next character value.  */\n  idx = 0;\n\n  /* Whether the last count was 0.  */\n  prev0 = 0;\n\n  while (remaining > 1 && idx <= maxidx)\n    {\n      uint32_t max;\n      int32_t count;\n\n      if (!elf_fetch_bits (&pin, pinend, &val, &bits))\n\treturn 0;\n\n      if (prev0)\n\t{\n\t  int zidx;\n\n\t  /* Previous count was 0, so there is a 2-bit repeat flag.  If the\n\t     2-bit flag is 0b11, it adds 3 and then there is another repeat\n\t     flag.  */\n\t  zidx = idx;\n\t  while ((val & 0xfff) == 0xfff)\n\t    {\n\t      zidx += 3 * 6;\n\t      val >>= 12;\n\t      bits -= 12;\n\t      if  (!elf_fetch_bits (&pin, pinend, &val, &bits))\n\t\treturn 0;\n\t    }\n\t  while ((val & 3) == 3)\n\t    {\n\t      zidx += 3;\n\t      val >>= 2;\n\t      bits -= 2;\n\t      if (!elf_fetch_bits (&pin, pinend, &val, &bits))\n\t\treturn 0;\n\t    }\n\t  /* We have at least 13 bits here, don't need to fetch.  */\n\t  zidx += val & 3;\n\t  val >>= 2;\n\t  bits -= 2;\n\n\t  if (unlikely (zidx > maxidx))\n\t    {\n\t      elf_uncompress_failed ();\n\t      return 0;\n\t    }\n\n\t  for (; idx < zidx; idx++)\n\t    norm[idx] = 0;\n\n\t  prev0 = 0;\n\t  continue;\n\t}\n\n      max = (2 * threshold - 1) - remaining;\n      if ((val & (threshold - 1)) < max)\n\t{\n\t  /* A small value.  */\n\t  count = (int32_t) ((uint32_t) val & (threshold - 1));\n\t  val >>= bits_needed - 1;\n\t  bits -= bits_needed - 1;\n\t}\n      else\n\t{\n\t  /* A large value.  */\n\t  count = (int32_t) ((uint32_t) val & (2 * threshold - 1));\n\t  if (count >= (int32_t) threshold)\n\t    count -= (int32_t) max;\n\t  val >>= bits_needed;\n\t  bits -= bits_needed;\n\t}\n\n      count--;\n      if (count >= 0)\n\tremaining -= count;\n      else\n\tremaining--;\n      if (unlikely (idx >= 256))\n\t{\n\t  elf_uncompress_failed ();\n\t  return 0;\n\t}\n      norm[idx] = (int16_t) count;\n      ++idx;\n\n      prev0 = count == 0;\n\n      while (remaining < threshold)\n\t{\n\t  bits_needed--;\n\t  threshold >>= 1;\n\t}\n    }\n\n  if (unlikely (remaining != 1))\n    {\n      elf_uncompress_failed ();\n      return 0;\n    }\n\n  /* If we've read ahead more than a byte, back up.  */\n  while (bits >= 8)\n    {\n      --pin;\n      bits -= 8;\n    }\n\n  *ppin = pin;\n\n  for (; idx <= maxidx; idx++)\n    norm[idx] = 0;\n\n  return elf_zstd_build_fse (norm, idx, next, *table_bits, table);\n}\n\n/* Build the FSE decoding table from a list of probabilities.  This reads from\n   NORM of length IDX, uses NEXT as scratch space, and writes to *TABLE, whose\n   size is TABLE_BITS.  */\n\nstatic int\nelf_zstd_build_fse (const int16_t *norm, int idx, uint16_t *next,\n\t\t    int table_bits, struct elf_zstd_fse_entry *table)\n{\n  int table_size;\n  int high_threshold;\n  int i;\n  int pos;\n  int step;\n  int mask;\n\n  table_size = 1 << table_bits;\n  high_threshold = table_size - 1;\n  for (i = 0; i < idx; i++)\n    {\n      int16_t n;\n\n      n = norm[i];\n      if (n >= 0)\n\tnext[i] = (uint16_t) n;\n      else\n\t{\n\t  table[high_threshold].symbol = (unsigned char) i;\n\t  high_threshold--;\n\t  next[i] = 1;\n\t}\n    }\n\n  pos = 0;\n  step = (table_size >> 1) + (table_size >> 3) + 3;\n  mask = table_size - 1;\n  for (i = 0; i < idx; i++)\n    {\n      int n;\n      int j;\n\n      n = (int) norm[i];\n      for (j = 0; j < n; j++)\n\t{\n\t  table[pos].symbol = (unsigned char) i;\n\t  pos = (pos + step) & mask;\n\t  while (unlikely (pos > high_threshold))\n\t    pos = (pos + step) & mask;\n\t}\n    }\n  if (unlikely (pos != 0))\n    {\n      elf_uncompress_failed ();\n      return 0;\n    }\n\n  for (i = 0; i < table_size; i++)\n    {\n      unsigned char sym;\n      uint16_t next_state;\n      int high_bit;\n      int bits;\n\n      sym = table[i].symbol;\n      next_state = next[sym];\n      ++next[sym];\n\n      if (next_state == 0)\n\t{\n\t  elf_uncompress_failed ();\n\t  return 0;\n\t}\n      high_bit = 31 - __builtin_clz (next_state);\n\n      bits = table_bits - high_bit;\n      table[i].bits = (unsigned char) bits;\n      table[i].base = (uint16_t) ((next_state << bits) - table_size);\n    }\n\n  return 1;\n}\n\n/* Encode the baseline and bits into a single 32-bit value.  */\n\n#define ZSTD_ENCODE_BASELINE_BITS(baseline, basebits)\t\\\n  ((uint32_t)(baseline) | ((uint32_t)(basebits) << 24))\n\n#define ZSTD_DECODE_BASELINE(baseline_basebits)\t\\\n  ((uint32_t)(baseline_basebits) & 0xffffff)\n\n#define ZSTD_DECODE_BASEBITS(baseline_basebits)\t\\\n  ((uint32_t)(baseline_basebits) >> 24)\n\n/* Given a literal length code, we need to read a number of bits and add that\n   to a baseline.  For states 0 to 15 the baseline is the state and the number\n   of bits is zero.  */\n\n#define ZSTD_LITERAL_LENGTH_BASELINE_OFFSET (16)\n\nstatic const uint32_t elf_zstd_literal_length_base[] =\n{\n  ZSTD_ENCODE_BASELINE_BITS(16, 1),\n  ZSTD_ENCODE_BASELINE_BITS(18, 1),\n  ZSTD_ENCODE_BASELINE_BITS(20, 1),\n  ZSTD_ENCODE_BASELINE_BITS(22, 1),\n  ZSTD_ENCODE_BASELINE_BITS(24, 2),\n  ZSTD_ENCODE_BASELINE_BITS(28, 2),\n  ZSTD_ENCODE_BASELINE_BITS(32, 3),\n  ZSTD_ENCODE_BASELINE_BITS(40, 3),\n  ZSTD_ENCODE_BASELINE_BITS(48, 4),\n  ZSTD_ENCODE_BASELINE_BITS(64, 6),\n  ZSTD_ENCODE_BASELINE_BITS(128, 7),\n  ZSTD_ENCODE_BASELINE_BITS(256, 8),\n  ZSTD_ENCODE_BASELINE_BITS(512, 9),\n  ZSTD_ENCODE_BASELINE_BITS(1024, 10),\n  ZSTD_ENCODE_BASELINE_BITS(2048, 11),\n  ZSTD_ENCODE_BASELINE_BITS(4096, 12),\n  ZSTD_ENCODE_BASELINE_BITS(8192, 13),\n  ZSTD_ENCODE_BASELINE_BITS(16384, 14),\n  ZSTD_ENCODE_BASELINE_BITS(32768, 15),\n  ZSTD_ENCODE_BASELINE_BITS(65536, 16)\n};\n\n/* The same applies to match length codes.  For states 0 to 31 the baseline is\n   the state + 3 and the number of bits is zero.  */\n\n#define ZSTD_MATCH_LENGTH_BASELINE_OFFSET (32)\n\nstatic const uint32_t elf_zstd_match_length_base[] =\n{\n  ZSTD_ENCODE_BASELINE_BITS(35, 1),\n  ZSTD_ENCODE_BASELINE_BITS(37, 1),\n  ZSTD_ENCODE_BASELINE_BITS(39, 1),\n  ZSTD_ENCODE_BASELINE_BITS(41, 1),\n  ZSTD_ENCODE_BASELINE_BITS(43, 2),\n  ZSTD_ENCODE_BASELINE_BITS(47, 2),\n  ZSTD_ENCODE_BASELINE_BITS(51, 3),\n  ZSTD_ENCODE_BASELINE_BITS(59, 3),\n  ZSTD_ENCODE_BASELINE_BITS(67, 4),\n  ZSTD_ENCODE_BASELINE_BITS(83, 4),\n  ZSTD_ENCODE_BASELINE_BITS(99, 5),\n  ZSTD_ENCODE_BASELINE_BITS(131, 7),\n  ZSTD_ENCODE_BASELINE_BITS(259, 8),\n  ZSTD_ENCODE_BASELINE_BITS(515, 9),\n  ZSTD_ENCODE_BASELINE_BITS(1027, 10),\n  ZSTD_ENCODE_BASELINE_BITS(2051, 11),\n  ZSTD_ENCODE_BASELINE_BITS(4099, 12),\n  ZSTD_ENCODE_BASELINE_BITS(8195, 13),\n  ZSTD_ENCODE_BASELINE_BITS(16387, 14),\n  ZSTD_ENCODE_BASELINE_BITS(32771, 15),\n  ZSTD_ENCODE_BASELINE_BITS(65539, 16)\n};\n\n/* An entry in an FSE table used for literal/match/length values.  For these we\n   have to map the symbol to a baseline value, and we have to read zero or more\n   bits and add that value to the baseline value.  Rather than look the values\n   up in a separate table, we grow the FSE table so that we get better memory\n   caching.  */\n\nstruct elf_zstd_fse_baseline_entry\n{\n  /* The baseline for the value that this FSE entry represents..  */\n  uint32_t baseline;\n  /* The number of bits to read to add to the baseline.  */\n  unsigned char basebits;\n  /* The number of bits to read to determine the next state.  */\n  unsigned char bits;\n  /* Add the bits to this base to get the next state.  */\n  uint16_t base;\n};\n\n/* Convert the literal length FSE table FSE_TABLE to an FSE baseline table at\n   BASELINE_TABLE.  Note that FSE_TABLE and BASELINE_TABLE will overlap.  */\n\nstatic int\nelf_zstd_make_literal_baseline_fse (\n    const struct elf_zstd_fse_entry *fse_table,\n    int table_bits,\n    struct elf_zstd_fse_baseline_entry *baseline_table)\n{\n  size_t count;\n  const struct elf_zstd_fse_entry *pfse;\n  struct elf_zstd_fse_baseline_entry *pbaseline;\n\n  /* Convert backward to avoid overlap.  */\n\n  count = 1U << table_bits;\n  pfse = fse_table + count;\n  pbaseline = baseline_table + count;\n  while (pfse > fse_table)\n    {\n      unsigned char symbol;\n      unsigned char bits;\n      uint16_t base;\n\n      --pfse;\n      --pbaseline;\n      symbol = pfse->symbol;\n      bits = pfse->bits;\n      base = pfse->base;\n      if (symbol < ZSTD_LITERAL_LENGTH_BASELINE_OFFSET)\n\t{\n\t  pbaseline->baseline = (uint32_t)symbol;\n\t  pbaseline->basebits = 0;\n\t}\n      else\n\t{\n\t  unsigned int idx;\n\t  uint32_t basebits;\n\n\t  if (unlikely (symbol > 35))\n\t    {\n\t      elf_uncompress_failed ();\n\t      return 0;\n\t    }\n\t  idx = symbol - ZSTD_LITERAL_LENGTH_BASELINE_OFFSET;\n\t  basebits = elf_zstd_literal_length_base[idx];\n\t  pbaseline->baseline = ZSTD_DECODE_BASELINE(basebits);\n\t  pbaseline->basebits = ZSTD_DECODE_BASEBITS(basebits);\n\t}\n      pbaseline->bits = bits;\n      pbaseline->base = base;\n    }\n\n  return 1;\n}\n\n/* Convert the offset length FSE table FSE_TABLE to an FSE baseline table at\n   BASELINE_TABLE.  Note that FSE_TABLE and BASELINE_TABLE will overlap.  */\n\nstatic int\nelf_zstd_make_offset_baseline_fse (\n    const struct elf_zstd_fse_entry *fse_table,\n    int table_bits,\n    struct elf_zstd_fse_baseline_entry *baseline_table)\n{\n  size_t count;\n  const struct elf_zstd_fse_entry *pfse;\n  struct elf_zstd_fse_baseline_entry *pbaseline;\n\n  /* Convert backward to avoid overlap.  */\n\n  count = 1U << table_bits;\n  pfse = fse_table + count;\n  pbaseline = baseline_table + count;\n  while (pfse > fse_table)\n    {\n      unsigned char symbol;\n      unsigned char bits;\n      uint16_t base;\n\n      --pfse;\n      --pbaseline;\n      symbol = pfse->symbol;\n      bits = pfse->bits;\n      base = pfse->base;\n      if (unlikely (symbol > 31))\n\t{\n\t  elf_uncompress_failed ();\n\t  return 0;\n\t}\n\n      /* The simple way to write this is\n\n\t   pbaseline->baseline = (uint32_t)1 << symbol;\n\t   pbaseline->basebits = symbol;\n\n\t That will give us an offset value that corresponds to the one\n\t described in the RFC.  However, for offset values > 3, we have to\n\t subtract 3.  And for offset values 1, 2, 3 we use a repeated offset.\n\t The baseline is always a power of 2, and is never 0, so for these low\n\t values we will see one entry that is baseline 1, basebits 0, and one\n\t entry that is baseline 2, basebits 1.  All other entries will have\n\t baseline >= 4 and basebits >= 2.\n\n\t So we can check for RFC offset <= 3 by checking for basebits <= 1.\n\t And that means that we can subtract 3 here and not worry about doing\n\t it in the hot loop.  */\n\n      pbaseline->baseline = (uint32_t)1 << symbol;\n      if (symbol >= 2)\n\tpbaseline->baseline -= 3;\n      pbaseline->basebits = symbol;\n      pbaseline->bits = bits;\n      pbaseline->base = base;\n    }\n\n  return 1;\n}\n\n/* Convert the match length FSE table FSE_TABLE to an FSE baseline table at\n   BASELINE_TABLE.  Note that FSE_TABLE and BASELINE_TABLE will overlap.  */\n\nstatic int\nelf_zstd_make_match_baseline_fse (\n    const struct elf_zstd_fse_entry *fse_table,\n    int table_bits,\n    struct elf_zstd_fse_baseline_entry *baseline_table)\n{\n  size_t count;\n  const struct elf_zstd_fse_entry *pfse;\n  struct elf_zstd_fse_baseline_entry *pbaseline;\n\n  /* Convert backward to avoid overlap.  */\n\n  count = 1U << table_bits;\n  pfse = fse_table + count;\n  pbaseline = baseline_table + count;\n  while (pfse > fse_table)\n    {\n      unsigned char symbol;\n      unsigned char bits;\n      uint16_t base;\n\n      --pfse;\n      --pbaseline;\n      symbol = pfse->symbol;\n      bits = pfse->bits;\n      base = pfse->base;\n      if (symbol < ZSTD_MATCH_LENGTH_BASELINE_OFFSET)\n\t{\n\t  pbaseline->baseline = (uint32_t)symbol + 3;\n\t  pbaseline->basebits = 0;\n\t}\n      else\n\t{\n\t  unsigned int idx;\n\t  uint32_t basebits;\n\n\t  if (unlikely (symbol > 52))\n\t    {\n\t      elf_uncompress_failed ();\n\t      return 0;\n\t    }\n\t  idx = symbol - ZSTD_MATCH_LENGTH_BASELINE_OFFSET;\n\t  basebits = elf_zstd_match_length_base[idx];\n\t  pbaseline->baseline = ZSTD_DECODE_BASELINE(basebits);\n\t  pbaseline->basebits = ZSTD_DECODE_BASEBITS(basebits);\n\t}\n      pbaseline->bits = bits;\n      pbaseline->base = base;\n    }\n\n  return 1;\n}\n\n#ifdef BACKTRACE_GENERATE_ZSTD_FSE_TABLES\n\n/* Used to generate the predefined FSE decoding tables for zstd.  */\n\n#include <stdio.h>\n\n/* These values are straight from RFC 8878.  */\n\nstatic int16_t lit[36] =\n{\n   4, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1,\n   2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 1, 1, 1, 1, 1,\n  -1,-1,-1,-1\n};\n\nstatic int16_t match[53] =\n{\n   1, 4, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1,\n   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,-1,-1,\n  -1,-1,-1,-1,-1\n};\n\nstatic int16_t offset[29] =\n{\n  1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1,\n  1, 1, 1, 1, 1, 1, 1, 1,-1,-1,-1,-1,-1\n};\n\nstatic uint16_t next[256];\n\nstatic void\nprint_table (const struct elf_zstd_fse_baseline_entry *table, size_t size)\n{\n  size_t i;\n\n  printf (\"{\\n\");\n  for (i = 0; i < size; i += 3)\n    {\n      int j;\n\n      printf (\" \");\n      for (j = 0; j < 3 && i + j < size; ++j)\n\tprintf (\" { %u, %d, %d, %d },\", table[i + j].baseline,\n\t\ttable[i + j].basebits, table[i + j].bits,\n\t\ttable[i + j].base);\n      printf (\"\\n\");\n    }\n  printf (\"};\\n\");\n}\n\nint\nmain ()\n{\n  struct elf_zstd_fse_entry lit_table[64];\n  struct elf_zstd_fse_baseline_entry lit_baseline[64];\n  struct elf_zstd_fse_entry match_table[64];\n  struct elf_zstd_fse_baseline_entry match_baseline[64];\n  struct elf_zstd_fse_entry offset_table[32];\n  struct elf_zstd_fse_baseline_entry offset_baseline[32];\n\n  if (!elf_zstd_build_fse (lit, sizeof lit / sizeof lit[0], next,\n\t\t\t   6, lit_table))\n    {\n      fprintf (stderr, \"elf_zstd_build_fse failed\\n\");\n      exit (EXIT_FAILURE);\n    }\n\n  if (!elf_zstd_make_literal_baseline_fse (lit_table, 6, lit_baseline))\n    {\n      fprintf (stderr, \"elf_zstd_make_literal_baseline_fse failed\\n\");\n      exit (EXIT_FAILURE);\n    }\n\n  printf (\"static const struct elf_zstd_fse_baseline_entry \"\n\t  \"elf_zstd_lit_table[64] =\\n\");\n  print_table (lit_baseline,\n\t       sizeof lit_baseline / sizeof lit_baseline[0]);\n  printf (\"\\n\");\n\n  if (!elf_zstd_build_fse (match, sizeof match / sizeof match[0], next,\n\t\t\t   6, match_table))\n    {\n      fprintf (stderr, \"elf_zstd_build_fse failed\\n\");\n      exit (EXIT_FAILURE);\n    }\n\n  if (!elf_zstd_make_match_baseline_fse (match_table, 6, match_baseline))\n    {\n      fprintf (stderr, \"elf_zstd_make_match_baseline_fse failed\\n\");\n      exit (EXIT_FAILURE);\n    }\n\n  printf (\"static const struct elf_zstd_fse_baseline_entry \"\n\t  \"elf_zstd_match_table[64] =\\n\");\n  print_table (match_baseline,\n\t       sizeof match_baseline / sizeof match_baseline[0]);\n  printf (\"\\n\");\n\n  if (!elf_zstd_build_fse (offset, sizeof offset / sizeof offset[0], next,\n\t\t\t   5, offset_table))\n    {\n      fprintf (stderr, \"elf_zstd_build_fse failed\\n\");\n      exit (EXIT_FAILURE);\n    }\n\n  if (!elf_zstd_make_offset_baseline_fse (offset_table, 5, offset_baseline))\n    {\n      fprintf (stderr, \"elf_zstd_make_offset_baseline_fse failed\\n\");\n      exit (EXIT_FAILURE);\n    }\n\n  printf (\"static const struct elf_zstd_fse_baseline_entry \"\n\t  \"elf_zstd_offset_table[32] =\\n\");\n  print_table (offset_baseline,\n\t       sizeof offset_baseline / sizeof offset_baseline[0]);\n  printf (\"\\n\");\n\n  return 0;\n}\n\n#endif\n\n/* The fixed tables generated by the #ifdef'ed out main function\n   above.  */\n\nstatic const struct elf_zstd_fse_baseline_entry elf_zstd_lit_table[64] =\n{\n  { 0, 0, 4, 0 }, { 0, 0, 4, 16 }, { 1, 0, 5, 32 },\n  { 3, 0, 5, 0 }, { 4, 0, 5, 0 }, { 6, 0, 5, 0 },\n  { 7, 0, 5, 0 }, { 9, 0, 5, 0 }, { 10, 0, 5, 0 },\n  { 12, 0, 5, 0 }, { 14, 0, 6, 0 }, { 16, 1, 5, 0 },\n  { 20, 1, 5, 0 }, { 22, 1, 5, 0 }, { 28, 2, 5, 0 },\n  { 32, 3, 5, 0 }, { 48, 4, 5, 0 }, { 64, 6, 5, 32 },\n  { 128, 7, 5, 0 }, { 256, 8, 6, 0 }, { 1024, 10, 6, 0 },\n  { 4096, 12, 6, 0 }, { 0, 0, 4, 32 }, { 1, 0, 4, 0 },\n  { 2, 0, 5, 0 }, { 4, 0, 5, 32 }, { 5, 0, 5, 0 },\n  { 7, 0, 5, 32 }, { 8, 0, 5, 0 }, { 10, 0, 5, 32 },\n  { 11, 0, 5, 0 }, { 13, 0, 6, 0 }, { 16, 1, 5, 32 },\n  { 18, 1, 5, 0 }, { 22, 1, 5, 32 }, { 24, 2, 5, 0 },\n  { 32, 3, 5, 32 }, { 40, 3, 5, 0 }, { 64, 6, 4, 0 },\n  { 64, 6, 4, 16 }, { 128, 7, 5, 32 }, { 512, 9, 6, 0 },\n  { 2048, 11, 6, 0 }, { 0, 0, 4, 48 }, { 1, 0, 4, 16 },\n  { 2, 0, 5, 32 }, { 3, 0, 5, 32 }, { 5, 0, 5, 32 },\n  { 6, 0, 5, 32 }, { 8, 0, 5, 32 }, { 9, 0, 5, 32 },\n  { 11, 0, 5, 32 }, { 12, 0, 5, 32 }, { 15, 0, 6, 0 },\n  { 18, 1, 5, 32 }, { 20, 1, 5, 32 }, { 24, 2, 5, 32 },\n  { 28, 2, 5, 32 }, { 40, 3, 5, 32 }, { 48, 4, 5, 32 },\n  { 65536, 16, 6, 0 }, { 32768, 15, 6, 0 }, { 16384, 14, 6, 0 },\n  { 8192, 13, 6, 0 },\n};\n\nstatic const struct elf_zstd_fse_baseline_entry elf_zstd_match_table[64] =\n{\n  { 3, 0, 6, 0 }, { 4, 0, 4, 0 }, { 5, 0, 5, 32 },\n  { 6, 0, 5, 0 }, { 8, 0, 5, 0 }, { 9, 0, 5, 0 },\n  { 11, 0, 5, 0 }, { 13, 0, 6, 0 }, { 16, 0, 6, 0 },\n  { 19, 0, 6, 0 }, { 22, 0, 6, 0 }, { 25, 0, 6, 0 },\n  { 28, 0, 6, 0 }, { 31, 0, 6, 0 }, { 34, 0, 6, 0 },\n  { 37, 1, 6, 0 }, { 41, 1, 6, 0 }, { 47, 2, 6, 0 },\n  { 59, 3, 6, 0 }, { 83, 4, 6, 0 }, { 131, 7, 6, 0 },\n  { 515, 9, 6, 0 }, { 4, 0, 4, 16 }, { 5, 0, 4, 0 },\n  { 6, 0, 5, 32 }, { 7, 0, 5, 0 }, { 9, 0, 5, 32 },\n  { 10, 0, 5, 0 }, { 12, 0, 6, 0 }, { 15, 0, 6, 0 },\n  { 18, 0, 6, 0 }, { 21, 0, 6, 0 }, { 24, 0, 6, 0 },\n  { 27, 0, 6, 0 }, { 30, 0, 6, 0 }, { 33, 0, 6, 0 },\n  { 35, 1, 6, 0 }, { 39, 1, 6, 0 }, { 43, 2, 6, 0 },\n  { 51, 3, 6, 0 }, { 67, 4, 6, 0 }, { 99, 5, 6, 0 },\n  { 259, 8, 6, 0 }, { 4, 0, 4, 32 }, { 4, 0, 4, 48 },\n  { 5, 0, 4, 16 }, { 7, 0, 5, 32 }, { 8, 0, 5, 32 },\n  { 10, 0, 5, 32 }, { 11, 0, 5, 32 }, { 14, 0, 6, 0 },\n  { 17, 0, 6, 0 }, { 20, 0, 6, 0 }, { 23, 0, 6, 0 },\n  { 26, 0, 6, 0 }, { 29, 0, 6, 0 }, { 32, 0, 6, 0 },\n  { 65539, 16, 6, 0 }, { 32771, 15, 6, 0 }, { 16387, 14, 6, 0 },\n  { 8195, 13, 6, 0 }, { 4099, 12, 6, 0 }, { 2051, 11, 6, 0 },\n  { 1027, 10, 6, 0 },\n};\n\nstatic const struct elf_zstd_fse_baseline_entry elf_zstd_offset_table[32] =\n{\n  { 1, 0, 5, 0 }, { 61, 6, 4, 0 }, { 509, 9, 5, 0 },\n  { 32765, 15, 5, 0 }, { 2097149, 21, 5, 0 }, { 5, 3, 5, 0 },\n  { 125, 7, 4, 0 }, { 4093, 12, 5, 0 }, { 262141, 18, 5, 0 },\n  { 8388605, 23, 5, 0 }, { 29, 5, 5, 0 }, { 253, 8, 4, 0 },\n  { 16381, 14, 5, 0 }, { 1048573, 20, 5, 0 }, { 1, 2, 5, 0 },\n  { 125, 7, 4, 16 }, { 2045, 11, 5, 0 }, { 131069, 17, 5, 0 },\n  { 4194301, 22, 5, 0 }, { 13, 4, 5, 0 }, { 253, 8, 4, 16 },\n  { 8189, 13, 5, 0 }, { 524285, 19, 5, 0 }, { 2, 1, 5, 0 },\n  { 61, 6, 4, 16 }, { 1021, 10, 5, 0 }, { 65533, 16, 5, 0 },\n  { 268435453, 28, 5, 0 }, { 134217725, 27, 5, 0 }, { 67108861, 26, 5, 0 },\n  { 33554429, 25, 5, 0 }, { 16777213, 24, 5, 0 },\n};\n\n/* Read a zstd Huffman table and build the decoding table in *TABLE, reading\n   and updating *PPIN.  This sets *PTABLE_BITS to the number of bits of the\n   table, such that the table length is 1 << *TABLE_BITS.  ZDEBUG_TABLE is\n   scratch space; it must be enough for 512 uint16_t values + 256 32-bit values\n   (2048 bytes).  Returns 1 on success, 0 on error.  */\n\nstatic int\nelf_zstd_read_huff (const unsigned char **ppin, const unsigned char *pinend,\n\t\t    uint16_t *zdebug_table, uint16_t *table, int *ptable_bits)\n{\n  const unsigned char *pin;\n  unsigned char hdr;\n  unsigned char *weights;\n  size_t count;\n  uint32_t *weight_mark;\n  size_t i;\n  uint32_t weight_mask;\n  size_t table_bits;\n\n  pin = *ppin;\n  if (unlikely (pin >= pinend))\n    {\n      elf_uncompress_failed ();\n      return 0;\n    }\n  hdr = *pin;\n  ++pin;\n\n  weights = (unsigned char *) zdebug_table;\n\n  if (hdr < 128)\n    {\n      /* Table is compressed using FSE.  */\n\n      struct elf_zstd_fse_entry *fse_table;\n      int fse_table_bits;\n      uint16_t *scratch;\n      const unsigned char *pfse;\n      const unsigned char *pback;\n      uint64_t val;\n      unsigned int bits;\n      unsigned int state1, state2;\n\n      /* SCRATCH is used temporarily by elf_zstd_read_fse.  It overlaps\n\t WEIGHTS.  */\n      scratch = zdebug_table;\n      fse_table = (struct elf_zstd_fse_entry *) (scratch + 512);\n      fse_table_bits = 6;\n\n      pfse = pin;\n      if (!elf_zstd_read_fse (&pfse, pinend, scratch, 255, fse_table,\n\t\t\t      &fse_table_bits))\n\treturn 0;\n\n      if (unlikely (pin + hdr > pinend))\n\t{\n\t  elf_uncompress_failed ();\n\t  return 0;\n\t}\n\n      /* We no longer need SCRATCH.  Start recording weights.  We need up to\n\t 256 bytes of weights and 64 bytes of rank counts, so it won't overlap\n\t FSE_TABLE.  */\n\n      pback = pin + hdr - 1;\n\n      if (!elf_fetch_backward_init (&pback, pfse, &val, &bits))\n\treturn 0;\n\n      bits -= fse_table_bits;\n      state1 = (val >> bits) & ((1U << fse_table_bits) - 1);\n      bits -= fse_table_bits;\n      state2 = (val >> bits) & ((1U << fse_table_bits) - 1);\n\n      /* There are two independent FSE streams, tracked by STATE1 and STATE2.\n\t We decode them alternately.  */\n\n      count = 0;\n      while (1)\n\t{\n\t  struct elf_zstd_fse_entry *pt;\n\t  uint64_t v;\n\n\t  pt = &fse_table[state1];\n\n\t  if (unlikely (pin < pinend) && bits < pt->bits)\n\t    {\n\t      if (unlikely (count >= 254))\n\t\t{\n\t\t  elf_uncompress_failed ();\n\t\t  return 0;\n\t\t}\n\t      weights[count] = (unsigned char) pt->symbol;\n\t      weights[count + 1] = (unsigned char) fse_table[state2].symbol;\n\t      count += 2;\n\t      break;\n\t    }\n\n\t  if (unlikely (pt->bits == 0))\n\t    v = 0;\n\t  else\n\t    {\n\t      if (!elf_fetch_bits_backward (&pback, pfse, &val, &bits))\n\t\treturn 0;\n\n\t      bits -= pt->bits;\n\t      v = (val >> bits) & (((uint64_t)1 << pt->bits) - 1);\n\t    }\n\n\t  state1 = pt->base + v;\n\n\t  if (unlikely (count >= 255))\n\t    {\n\t      elf_uncompress_failed ();\n\t      return 0;\n\t    }\n\n\t  weights[count] = pt->symbol;\n\t  ++count;\n\n\t  pt = &fse_table[state2];\n\n\t  if (unlikely (pin < pinend && bits < pt->bits))\n\t    {\n\t      if (unlikely (count >= 254))\n\t\t{\n\t\t  elf_uncompress_failed ();\n\t\t  return 0;\n\t\t}\n\t      weights[count] = (unsigned char) pt->symbol;\n\t      weights[count + 1] = (unsigned char) fse_table[state1].symbol;\n\t      count += 2;\n\t      break;\n\t    }\n\n\t  if (unlikely (pt->bits == 0))\n\t    v = 0;\n\t  else\n\t    {\n\t      if (!elf_fetch_bits_backward (&pback, pfse, &val, &bits))\n\t\treturn 0;\n\n\t      bits -= pt->bits;\n\t      v = (val >> bits) & (((uint64_t)1 << pt->bits) - 1);\n\t    }\n\n\t  state2 = pt->base + v;\n\n\t  if (unlikely (count >= 255))\n\t    {\n\t      elf_uncompress_failed ();\n\t      return 0;\n\t    }\n\n\t  weights[count] = pt->symbol;\n\t  ++count;\n\t}\n\n      pin += hdr;\n    }\n  else\n    {\n      /* Table is not compressed.  Each weight is 4 bits.  */\n\n      count = hdr - 127;\n      if (unlikely (pin + ((count + 1) / 2) >= pinend))\n\t{\n\t  elf_uncompress_failed ();\n\t  return 0;\n\t}\n      for (i = 0; i < count; i += 2)\n\t{\n\t  unsigned char b;\n\n\t  b = *pin;\n\t  ++pin;\n\t  weights[i] = b >> 4;\n\t  weights[i + 1] = b & 0xf;\n\t}\n    }\n\n  weight_mark = (uint32_t *) (weights + 256);\n  memset (weight_mark, 0, 13 * sizeof (uint32_t));\n  weight_mask = 0;\n  for (i = 0; i < count; ++i)\n    {\n      unsigned char w;\n\n      w = weights[i];\n      if (unlikely (w > 12))\n\t{\n\t  elf_uncompress_failed ();\n\t  return 0;\n\t}\n      ++weight_mark[w];\n      if (w > 0)\n\tweight_mask += 1U << (w - 1);\n    }\n  if (unlikely (weight_mask == 0))\n    {\n      elf_uncompress_failed ();\n      return 0;\n    }\n\n  table_bits = 32 - __builtin_clz (weight_mask);\n  if (unlikely (table_bits > 11))\n    {\n      elf_uncompress_failed ();\n      return 0;\n    }\n\n  /* Work out the last weight value, which is omitted because the weights must\n     sum to a power of two.  */\n  {\n    uint32_t left;\n    uint32_t high_bit;\n\n    left = ((uint32_t)1 << table_bits) - weight_mask;\n    if (left == 0)\n      {\n\telf_uncompress_failed ();\n\treturn 0;\n      }\n    high_bit = 31 - __builtin_clz (left);\n    if (((uint32_t)1 << high_bit) != left)\n      {\n\telf_uncompress_failed ();\n\treturn 0;\n      }\n\n    if (unlikely (count >= 256))\n      {\n\telf_uncompress_failed ();\n\treturn 0;\n      }\n\n    weights[count] = high_bit + 1;\n    ++count;\n    ++weight_mark[high_bit + 1];\n  }\n\n  if (weight_mark[1] < 2 || (weight_mark[1] & 1) != 0)\n    {\n      elf_uncompress_failed ();\n      return 0;\n    }\n\n  /* Change WEIGHT_MARK from a count of weights to the index of the first\n     symbol for that weight.  We shift the indexes to also store how many we\n     have seen so far, below.  */\n  {\n    uint32_t next;\n\n    next = 0;\n    for (i = 0; i < table_bits; ++i)\n      {\n\tuint32_t cur;\n\n\tcur = next;\n\tnext += weight_mark[i + 1] << i;\n\tweight_mark[i + 1] = cur;\n      }\n  }\n\n  for (i = 0; i < count; ++i)\n    {\n      unsigned char weight;\n      uint32_t length;\n      uint16_t tval;\n      size_t start;\n      uint32_t j;\n\n      weight = weights[i];\n      if (weight == 0)\n\tcontinue;\n\n      length = 1U << (weight - 1);\n      tval = (i << 8) | (table_bits + 1 - weight);\n      start = weight_mark[weight];\n      for (j = 0; j < length; ++j)\n\ttable[start + j] = tval;\n      weight_mark[weight] += length;\n    }\n\n  *ppin = pin;\n  *ptable_bits = (int)table_bits;\n\n  return 1;\n}\n\n/* Read and decompress the literals and store them ending at POUTEND.  This\n   works because we are going to use all the literals in the output, so they\n   must fit into the output buffer.  HUFFMAN_TABLE, and PHUFFMAN_TABLE_BITS\n   store the Huffman table across calls.  SCRATCH is used to read a Huffman\n   table.  Store the start of the decompressed literals in *PPLIT.  Update\n   *PPIN.  Return 1 on success, 0 on error.  */\n\nstatic int\nelf_zstd_read_literals (const unsigned char **ppin,\n\t\t\tconst unsigned char *pinend,\n\t\t\tunsigned char *pout,\n\t\t\tunsigned char *poutend,\n\t\t\tuint16_t *scratch,\n\t\t\tuint16_t *huffman_table,\n\t\t\tint *phuffman_table_bits,\n\t\t\tunsigned char **pplit)\n{\n  const unsigned char *pin;\n  unsigned char *plit;\n  unsigned char hdr;\n  uint32_t regenerated_size;\n  uint32_t compressed_size;\n  int streams;\n  uint32_t total_streams_size;\n  unsigned int huffman_table_bits;\n  uint64_t huffman_mask;\n\n  pin = *ppin;\n  if (unlikely (pin >= pinend))\n    {\n      elf_uncompress_failed ();\n      return 0;\n    }\n  hdr = *pin;\n  ++pin;\n\n  if ((hdr & 3) == 0 || (hdr & 3) == 1)\n    {\n      int raw;\n\n      /* Raw_Literals_Block or RLE_Literals_Block */\n\n      raw = (hdr & 3) == 0;\n\n      switch ((hdr >> 2) & 3)\n\t{\n\tcase 0: case 2:\n\t  regenerated_size = hdr >> 3;\n\t  break;\n\tcase 1:\n\t  if (unlikely (pin >= pinend))\n\t    {\n\t      elf_uncompress_failed ();\n\t      return 0;\n\t    }\n\t  regenerated_size = (hdr >> 4) + ((uint32_t)(*pin) << 4);\n\t  ++pin;\n\t  break;\n\tcase 3:\n\t  if (unlikely (pin + 1 >= pinend))\n\t    {\n\t      elf_uncompress_failed ();\n\t      return 0;\n\t    }\n\t  regenerated_size = ((hdr >> 4)\n\t\t\t      + ((uint32_t)*pin << 4)\n\t\t\t      + ((uint32_t)pin[1] << 12));\n\t  pin += 2;\n\t  break;\n\tdefault:\n\t  elf_uncompress_failed ();\n\t  return 0;\n\t}\n\n      if (unlikely ((size_t)(poutend - pout) < regenerated_size))\n\t{\n\t  elf_uncompress_failed ();\n\t  return 0;\n\t}\n\n      plit = poutend - regenerated_size;\n\n      if (raw)\n\t{\n\t  if (unlikely (pin + regenerated_size >= pinend))\n\t    {\n\t      elf_uncompress_failed ();\n\t      return 0;\n\t    }\n\t  memcpy (plit, pin, regenerated_size);\n\t  pin += regenerated_size;\n\t}\n      else\n\t{\n\t  if (pin >= pinend)\n\t    {\n\t      elf_uncompress_failed ();\n\t      return 0;\n\t    }\n\t  memset (plit, *pin, regenerated_size);\n\t  ++pin;\n\t}\n\n      *ppin = pin;\n      *pplit = plit;\n\n      return 1;\n    }\n\n  /* Compressed_Literals_Block or Treeless_Literals_Block */\n\n  switch ((hdr >> 2) & 3)\n    {\n    case 0: case 1:\n      if (unlikely (pin + 1 >= pinend))\n\t{\n\t  elf_uncompress_failed ();\n\t  return 0;\n\t}\n      regenerated_size = (hdr >> 4) | ((uint32_t)(*pin & 0x3f) << 4);\n      compressed_size = (uint32_t)*pin >> 6 | ((uint32_t)pin[1] << 2);\n      pin += 2;\n      streams = ((hdr >> 2) & 3) == 0 ? 1 : 4;\n      break;\n    case 2:\n      if (unlikely (pin + 2 >= pinend))\n\t{\n\t  elf_uncompress_failed ();\n\t  return 0;\n\t}\n      regenerated_size = (((uint32_t)hdr >> 4)\n\t\t\t  | ((uint32_t)*pin << 4)\n\t\t\t  | (((uint32_t)pin[1] & 3) << 12));\n      compressed_size = (((uint32_t)pin[1] >> 2)\n\t\t\t | ((uint32_t)pin[2] << 6));\n      pin += 3;\n      streams = 4;\n      break;\n    case 3:\n      if (unlikely (pin + 3 >= pinend))\n\t{\n\t  elf_uncompress_failed ();\n\t  return 0;\n\t}\n      regenerated_size = (((uint32_t)hdr >> 4)\n\t\t\t  | ((uint32_t)*pin << 4)\n\t\t\t  | (((uint32_t)pin[1] & 0x3f) << 12));\n      compressed_size = (((uint32_t)pin[1] >> 6)\n\t\t\t | ((uint32_t)pin[2] << 2)\n\t\t\t | ((uint32_t)pin[3] << 10));\n      pin += 4;\n      streams = 4;\n      break;\n    default:\n      elf_uncompress_failed ();\n      return 0;\n    }\n\n  if (unlikely (pin + compressed_size > pinend))\n    {\n      elf_uncompress_failed ();\n      return 0;\n    }\n\n  pinend = pin + compressed_size;\n  *ppin = pinend;\n\n  if (unlikely ((size_t)(poutend - pout) < regenerated_size))\n    {\n      elf_uncompress_failed ();\n      return 0;\n    }\n\n  plit = poutend - regenerated_size;\n\n  *pplit = plit;\n\n  total_streams_size = compressed_size;\n  if ((hdr & 3) == 2)\n    {\n      const unsigned char *ptable;\n\n      /* Compressed_Literals_Block.  Read Huffman tree.  */\n\n      ptable = pin;\n      if (!elf_zstd_read_huff (&ptable, pinend, scratch, huffman_table,\n\t\t\t       phuffman_table_bits))\n\treturn 0;\n\n      if (unlikely (total_streams_size < (size_t)(ptable - pin)))\n\t{\n\t  elf_uncompress_failed ();\n\t  return 0;\n\t}\n\n      total_streams_size -= ptable - pin;\n      pin = ptable;\n    }\n  else\n    {\n      /* Treeless_Literals_Block.  Reuse previous Huffman tree.  */\n      if (unlikely (*phuffman_table_bits == 0))\n\t{\n\t  elf_uncompress_failed ();\n\t  return 0;\n\t}\n    }\n\n  /* Decompress COMPRESSED_SIZE bytes of data at PIN using the huffman table,\n     storing REGENERATED_SIZE bytes of decompressed data at PLIT.  */\n\n  huffman_table_bits = (unsigned int)*phuffman_table_bits;\n  huffman_mask = ((uint64_t)1 << huffman_table_bits) - 1;\n\n  if (streams == 1)\n    {\n      const unsigned char *pback;\n      const unsigned char *pbackend;\n      uint64_t val;\n      unsigned int bits;\n      uint32_t i;\n\n      pback = pin + total_streams_size - 1;\n      pbackend = pin;\n      if (!elf_fetch_backward_init (&pback, pbackend, &val, &bits))\n\treturn 0;\n\n      /* This is one of the inner loops of the decompression algorithm, so we\n\t put some effort into optimization.  We can't get more than 64 bytes\n\t from a single call to elf_fetch_bits_backward, and we can't subtract\n\t more than 11 bits at a time.  */\n\n      if (regenerated_size >= 64)\n\t{\n\t  unsigned char *plitstart;\n\t  unsigned char *plitstop;\n\n\t  plitstart = plit;\n\t  plitstop = plit + regenerated_size - 64;\n\t  while (plit < plitstop)\n\t    {\n\t      uint16_t t;\n\n\t      if (!elf_fetch_bits_backward (&pback, pbackend, &val, &bits))\n\t\treturn 0;\n\n\t      if (bits < 16)\n\t\tbreak;\n\n\t      while (bits >= 33)\n\t\t{\n\t\t  t = huffman_table[(val >> (bits - huffman_table_bits))\n\t\t\t\t    & huffman_mask];\n\t\t  *plit = t >> 8;\n\t\t  ++plit;\n\t\t  bits -= t & 0xff;\n\n\t\t  t = huffman_table[(val >> (bits - huffman_table_bits))\n\t\t\t\t    & huffman_mask];\n\t\t  *plit = t >> 8;\n\t\t  ++plit;\n\t\t  bits -= t & 0xff;\n\n\t\t  t = huffman_table[(val >> (bits - huffman_table_bits))\n\t\t\t\t    & huffman_mask];\n\t\t  *plit = t >> 8;\n\t\t  ++plit;\n\t\t  bits -= t & 0xff;\n\t\t}\n\n\t      while (bits > 11)\n\t\t{\n\t\t  t = huffman_table[(val >> (bits - huffman_table_bits))\n\t\t\t\t    & huffman_mask];\n\t\t  *plit = t >> 8;\n\t\t  ++plit;\n\t\t  bits -= t & 0xff;\n\t\t}\n\t    }\n\n\t  regenerated_size -= plit - plitstart;\n\t}\n\n      for (i = 0; i < regenerated_size; ++i)\n\t{\n\t  uint16_t t;\n\n\t  if (!elf_fetch_bits_backward (&pback, pbackend, &val, &bits))\n\t    return 0;\n\n\t  if (unlikely (bits < huffman_table_bits))\n\t    {\n\t      t = huffman_table[(val << (huffman_table_bits - bits))\n\t\t\t\t& huffman_mask];\n\t      if (unlikely (bits < (t & 0xff)))\n\t\t{\n\t\t  elf_uncompress_failed ();\n\t\t  return 0;\n\t\t}\n\t    }\n\t  else\n\t    t = huffman_table[(val >> (bits - huffman_table_bits))\n\t\t\t      & huffman_mask];\n\n\t  *plit = t >> 8;\n\t  ++plit;\n\t  bits -= t & 0xff;\n\t}\n\n      return 1;\n    }\n\n  {\n    uint32_t stream_size1, stream_size2, stream_size3, stream_size4;\n    uint32_t tot;\n    const unsigned char *pback1, *pback2, *pback3, *pback4;\n    const unsigned char *pbackend1, *pbackend2, *pbackend3, *pbackend4;\n    uint64_t val1, val2, val3, val4;\n    unsigned int bits1, bits2, bits3, bits4;\n    unsigned char *plit1, *plit2, *plit3, *plit4;\n    uint32_t regenerated_stream_size;\n    uint32_t regenerated_stream_size4;\n    uint16_t t1, t2, t3, t4;\n    uint32_t i;\n    uint32_t limit;\n\n    /* Read jump table.  */\n    if (unlikely (pin + 5 >= pinend))\n      {\n\telf_uncompress_failed ();\n\treturn 0;\n      }\n    stream_size1 = (uint32_t)*pin | ((uint32_t)pin[1] << 8);\n    pin += 2;\n    stream_size2 = (uint32_t)*pin | ((uint32_t)pin[1] << 8);\n    pin += 2;\n    stream_size3 = (uint32_t)*pin | ((uint32_t)pin[1] << 8);\n    pin += 2;\n    tot = stream_size1 + stream_size2 + stream_size3;\n    if (unlikely (tot > total_streams_size - 6))\n      {\n\telf_uncompress_failed ();\n\treturn 0;\n      }\n    stream_size4 = total_streams_size - 6 - tot;\n\n    pback1 = pin + stream_size1 - 1;\n    pbackend1 = pin;\n\n    pback2 = pback1 + stream_size2;\n    pbackend2 = pback1 + 1;\n\n    pback3 = pback2 + stream_size3;\n    pbackend3 = pback2 + 1;\n\n    pback4 = pback3 + stream_size4;\n    pbackend4 = pback3 + 1;\n\n    if (!elf_fetch_backward_init (&pback1, pbackend1, &val1, &bits1))\n      return 0;\n    if (!elf_fetch_backward_init (&pback2, pbackend2, &val2, &bits2))\n      return 0;\n    if (!elf_fetch_backward_init (&pback3, pbackend3, &val3, &bits3))\n      return 0;\n    if (!elf_fetch_backward_init (&pback4, pbackend4, &val4, &bits4))\n      return 0;\n\n    regenerated_stream_size = (regenerated_size + 3) / 4;\n\n    plit1 = plit;\n    plit2 = plit1 + regenerated_stream_size;\n    plit3 = plit2 + regenerated_stream_size;\n    plit4 = plit3 + regenerated_stream_size;\n\n    regenerated_stream_size4 = regenerated_size - regenerated_stream_size * 3;\n\n    /* We can't get more than 64 literal bytes from a single call to\n       elf_fetch_bits_backward.  The fourth stream can be up to 3 bytes less,\n       so use as the limit.  */\n\n    limit = regenerated_stream_size4 <= 64 ? 0 : regenerated_stream_size4 - 64;\n    i = 0;\n    while (i < limit)\n      {\n\tif (!elf_fetch_bits_backward (&pback1, pbackend1, &val1, &bits1))\n\t  return 0;\n\tif (!elf_fetch_bits_backward (&pback2, pbackend2, &val2, &bits2))\n\t  return 0;\n\tif (!elf_fetch_bits_backward (&pback3, pbackend3, &val3, &bits3))\n\t  return 0;\n\tif (!elf_fetch_bits_backward (&pback4, pbackend4, &val4, &bits4))\n\t  return 0;\n\n\t/* We can't subtract more than 11 bits at a time.  */\n\n\tdo\n\t  {\n\t    t1 = huffman_table[(val1 >> (bits1 - huffman_table_bits))\n\t\t\t       & huffman_mask];\n\t    t2 = huffman_table[(val2 >> (bits2 - huffman_table_bits))\n\t\t\t       & huffman_mask];\n\t    t3 = huffman_table[(val3 >> (bits3 - huffman_table_bits))\n\t\t\t       & huffman_mask];\n\t    t4 = huffman_table[(val4 >> (bits4 - huffman_table_bits))\n\t\t\t       & huffman_mask];\n\n\t    *plit1 = t1 >> 8;\n\t    ++plit1;\n\t    bits1 -= t1 & 0xff;\n\n\t    *plit2 = t2 >> 8;\n\t    ++plit2;\n\t    bits2 -= t2 & 0xff;\n\n\t    *plit3 = t3 >> 8;\n\t    ++plit3;\n\t    bits3 -= t3 & 0xff;\n\n\t    *plit4 = t4 >> 8;\n\t    ++plit4;\n\t    bits4 -= t4 & 0xff;\n\n\t    ++i;\n\t  }\n\twhile (bits1 > 11 && bits2 > 11 && bits3 > 11 && bits4 > 11);\n      }\n\n    while (i < regenerated_stream_size)\n      {\n\tint use4;\n\n\tuse4 = i < regenerated_stream_size4;\n\n\tif (!elf_fetch_bits_backward (&pback1, pbackend1, &val1, &bits1))\n\t  return 0;\n\tif (!elf_fetch_bits_backward (&pback2, pbackend2, &val2, &bits2))\n\t  return 0;\n\tif (!elf_fetch_bits_backward (&pback3, pbackend3, &val3, &bits3))\n\t  return 0;\n\tif (use4)\n\t  {\n\t    if (!elf_fetch_bits_backward (&pback4, pbackend4, &val4, &bits4))\n\t      return 0;\n\t  }\n\n\tif (unlikely (bits1 < huffman_table_bits))\n\t  {\n\t    t1 = huffman_table[(val1 << (huffman_table_bits - bits1))\n\t\t\t       & huffman_mask];\n\t    if (unlikely (bits1 < (t1 & 0xff)))\n\t      {\n\t\telf_uncompress_failed ();\n\t\treturn 0;\n\t      }\n\t  }\n\telse\n\t  t1 = huffman_table[(val1 >> (bits1 - huffman_table_bits))\n\t\t\t     & huffman_mask];\n\n\tif (unlikely (bits2 < huffman_table_bits))\n\t  {\n\t    t2 = huffman_table[(val2 << (huffman_table_bits - bits2))\n\t\t\t       & huffman_mask];\n\t    if (unlikely (bits2 < (t2 & 0xff)))\n\t      {\n\t\telf_uncompress_failed ();\n\t\treturn 0;\n\t      }\n\t  }\n\telse\n\t  t2 = huffman_table[(val2 >> (bits2 - huffman_table_bits))\n\t\t\t     & huffman_mask];\n\n\tif (unlikely (bits3 < huffman_table_bits))\n\t  {\n\t    t3 = huffman_table[(val3 << (huffman_table_bits - bits3))\n\t\t\t       & huffman_mask];\n\t    if (unlikely (bits3 < (t3 & 0xff)))\n\t      {\n\t\telf_uncompress_failed ();\n\t\treturn 0;\n\t      }\n\t  }\n\telse\n\t  t3 = huffman_table[(val3 >> (bits3 - huffman_table_bits))\n\t\t\t     & huffman_mask];\n\n\tif (use4)\n\t  {\n\t    if (unlikely (bits4 < huffman_table_bits))\n\t      {\n\t\tt4 = huffman_table[(val4 << (huffman_table_bits - bits4))\n\t\t\t\t   & huffman_mask];\n\t\tif (unlikely (bits4 < (t4 & 0xff)))\n\t\t  {\n\t\t    elf_uncompress_failed ();\n\t\t    return 0;\n\t\t  }\n\t      }\n\t    else\n\t      t4 = huffman_table[(val4 >> (bits4 - huffman_table_bits))\n\t\t\t\t & huffman_mask];\n\n\t    *plit4 = t4 >> 8;\n\t    ++plit4;\n\t    bits4 -= t4 & 0xff;\n\t  }\n\n\t*plit1 = t1 >> 8;\n\t++plit1;\n\tbits1 -= t1 & 0xff;\n\n\t*plit2 = t2 >> 8;\n\t++plit2;\n\tbits2 -= t2 & 0xff;\n\n\t*plit3 = t3 >> 8;\n\t++plit3;\n\tbits3 -= t3 & 0xff;\n\n\t++i;\n      }\n  }\n\n  return 1;\n}\n\n/* The information used to decompress a sequence code, which can be a literal\n   length, an offset, or a match length.  */\n\nstruct elf_zstd_seq_decode\n{\n  const struct elf_zstd_fse_baseline_entry *table;\n  int table_bits;\n};\n\n/* Unpack a sequence code compression mode.  */\n\nstatic int\nelf_zstd_unpack_seq_decode (int mode,\n\t\t\t    const unsigned char **ppin,\n\t\t\t    const unsigned char *pinend,\n\t\t\t    const struct elf_zstd_fse_baseline_entry *predef,\n\t\t\t    int predef_bits,\n\t\t\t    uint16_t *scratch,\n\t\t\t    int maxidx,\n\t\t\t    struct elf_zstd_fse_baseline_entry *table,\n\t\t\t    int table_bits,\n\t\t\t    int (*conv)(const struct elf_zstd_fse_entry *,\n\t\t\t\t\tint,\n\t\t\t\t\tstruct elf_zstd_fse_baseline_entry *),\n\t\t\t    struct elf_zstd_seq_decode *decode)\n{\n  switch (mode)\n    {\n    case 0:\n      decode->table = predef;\n      decode->table_bits = predef_bits;\n      break;\n\n    case 1:\n      {\n\tstruct elf_zstd_fse_entry entry;\n\n\tif (unlikely (*ppin >= pinend))\n\t  {\n\t    elf_uncompress_failed ();\n\t    return 0;\n\t  }\n\tentry.symbol = **ppin;\n\t++*ppin;\n\tentry.bits = 0;\n\tentry.base = 0;\n\tdecode->table_bits = 0;\n\tif (!conv (&entry, 0, table))\n\t  return 0;\n      }\n      break;\n\n    case 2:\n      {\n\tstruct elf_zstd_fse_entry *fse_table;\n\n\t/* We use the same space for the simple FSE table and the baseline\n\t   table.  */\n\tfse_table = (struct elf_zstd_fse_entry *)table;\n\tdecode->table_bits = table_bits;\n\tif (!elf_zstd_read_fse (ppin, pinend, scratch, maxidx, fse_table,\n\t\t\t\t&decode->table_bits))\n\t  return 0;\n\tif (!conv (fse_table, decode->table_bits, table))\n\t  return 0;\n\tdecode->table = table;\n      }\n      break;\n\n    case 3:\n      if (unlikely (decode->table_bits == -1))\n\t{\n\t  elf_uncompress_failed ();\n\t  return 0;\n\t}\n      break;\n\n    default:\n      elf_uncompress_failed ();\n      return 0;\n    }\n\n  return 1;\n}\n\n/* Decompress a zstd stream from PIN/SIN to POUT/SOUT.  Code based on RFC 8878.\n   Return 1 on success, 0 on error.  */\n\nstatic int\nelf_zstd_decompress (const unsigned char *pin, size_t sin,\n\t\t     unsigned char *zdebug_table, unsigned char *pout,\n\t\t     size_t sout)\n{\n  const unsigned char *pinend;\n  unsigned char *poutstart;\n  unsigned char *poutend;\n  struct elf_zstd_seq_decode literal_decode;\n  struct elf_zstd_fse_baseline_entry *literal_fse_table;\n  struct elf_zstd_seq_decode match_decode;\n  struct elf_zstd_fse_baseline_entry *match_fse_table;\n  struct elf_zstd_seq_decode offset_decode;\n  struct elf_zstd_fse_baseline_entry *offset_fse_table;\n  uint16_t *huffman_table;\n  int huffman_table_bits;\n  uint32_t repeated_offset1;\n  uint32_t repeated_offset2;\n  uint32_t repeated_offset3;\n  uint16_t *scratch;\n  unsigned char hdr;\n  int has_checksum;\n  uint64_t content_size;\n  int last_block;\n\n  pinend = pin + sin;\n  poutstart = pout;\n  poutend = pout + sout;\n\n  literal_decode.table = NULL;\n  literal_decode.table_bits = -1;\n  literal_fse_table = ((struct elf_zstd_fse_baseline_entry *)\n\t\t       (zdebug_table + ZSTD_TABLE_LITERAL_FSE_OFFSET));\n\n  match_decode.table = NULL;\n  match_decode.table_bits = -1;\n  match_fse_table = ((struct elf_zstd_fse_baseline_entry *)\n\t\t     (zdebug_table + ZSTD_TABLE_MATCH_FSE_OFFSET));\n\n  offset_decode.table = NULL;\n  offset_decode.table_bits = -1;\n  offset_fse_table = ((struct elf_zstd_fse_baseline_entry *)\n\t\t      (zdebug_table + ZSTD_TABLE_OFFSET_FSE_OFFSET));\n  huffman_table = ((uint16_t *)\n\t\t   (zdebug_table + ZSTD_TABLE_HUFFMAN_OFFSET));\n  huffman_table_bits = 0;\n  scratch = ((uint16_t *)\n\t     (zdebug_table + ZSTD_TABLE_WORK_OFFSET));\n\n  repeated_offset1 = 1;\n  repeated_offset2 = 4;\n  repeated_offset3 = 8;\n\n  if (unlikely (sin < 4))\n    {\n      elf_uncompress_failed ();\n      return 0;\n    }\n\n  /* These values are the zstd magic number.  */\n  if (unlikely (pin[0] != 0x28\n\t\t|| pin[1] != 0xb5\n\t\t|| pin[2] != 0x2f\n\t\t|| pin[3] != 0xfd))\n    {\n      elf_uncompress_failed ();\n      return 0;\n    }\n\n  pin += 4;\n\n  if (unlikely (pin >= pinend))\n    {\n      elf_uncompress_failed ();\n      return 0;\n    }\n\n  hdr = *pin++;\n\n  /* We expect a single frame.  */\n  if (unlikely ((hdr & (1 << 5)) == 0))\n    {\n      elf_uncompress_failed ();\n      return 0;\n    }\n  /* Reserved bit must be zero.  */\n  if (unlikely ((hdr & (1 << 3)) != 0))\n    {\n      elf_uncompress_failed ();\n      return 0;\n    }\n  /* We do not expect a dictionary.  */\n  if (unlikely ((hdr & 3) != 0))\n    {\n      elf_uncompress_failed ();\n      return 0;\n    }\n  has_checksum = (hdr & (1 << 2)) != 0;\n  switch (hdr >> 6)\n    {\n    case 0:\n      if (unlikely (pin >= pinend))\n\t{\n\t  elf_uncompress_failed ();\n\t  return 0;\n\t}\n      content_size = (uint64_t) *pin++;\n      break;\n    case 1:\n      if (unlikely (pin + 1 >= pinend))\n\t{\n\t  elf_uncompress_failed ();\n\t  return 0;\n\t}\n      content_size = (((uint64_t) pin[0]) | (((uint64_t) pin[1]) << 8)) + 256;\n      pin += 2;\n      break;\n    case 2:\n      if (unlikely (pin + 3 >= pinend))\n\t{\n\t  elf_uncompress_failed ();\n\t  return 0;\n\t}\n      content_size = ((uint64_t) pin[0]\n\t\t      | (((uint64_t) pin[1]) << 8)\n\t\t      | (((uint64_t) pin[2]) << 16)\n\t\t      | (((uint64_t) pin[3]) << 24));\n      pin += 4;\n      break;\n    case 3:\n      if (unlikely (pin + 7 >= pinend))\n\t{\n\t  elf_uncompress_failed ();\n\t  return 0;\n\t}\n      content_size = ((uint64_t) pin[0]\n\t\t      | (((uint64_t) pin[1]) << 8)\n\t\t      | (((uint64_t) pin[2]) << 16)\n\t\t      | (((uint64_t) pin[3]) << 24)\n\t\t      | (((uint64_t) pin[4]) << 32)\n\t\t      | (((uint64_t) pin[5]) << 40)\n\t\t      | (((uint64_t) pin[6]) << 48)\n\t\t      | (((uint64_t) pin[7]) << 56));\n      pin += 8;\n      break;\n    default:\n      elf_uncompress_failed ();\n      return 0;\n    }\n\n  if (unlikely (content_size != (size_t) content_size\n\t\t|| (size_t) content_size != sout))\n    {\n      elf_uncompress_failed ();\n      return 0;\n    }\n\n  last_block = 0;\n  while (!last_block)\n    {\n      uint32_t block_hdr;\n      int block_type;\n      uint32_t block_size;\n\n      if (unlikely (pin + 2 >= pinend))\n\t{\n\t  elf_uncompress_failed ();\n\t  return 0;\n\t}\n      block_hdr = ((uint32_t) pin[0]\n\t\t   | (((uint32_t) pin[1]) << 8)\n\t\t   | (((uint32_t) pin[2]) << 16));\n      pin += 3;\n\n      last_block = block_hdr & 1;\n      block_type = (block_hdr >> 1) & 3;\n      block_size = block_hdr >> 3;\n\n      switch (block_type)\n\t{\n\tcase 0:\n\t  /* Raw_Block */\n\t  if (unlikely ((size_t) block_size > (size_t) (pinend - pin)))\n\t    {\n\t      elf_uncompress_failed ();\n\t      return 0;\n\t    }\n\t  if (unlikely ((size_t) block_size > (size_t) (poutend - pout)))\n\t    {\n\t      elf_uncompress_failed ();\n\t      return 0;\n\t    }\n\t  memcpy (pout, pin, block_size);\n\t  pout += block_size;\n\t  pin += block_size;\n\t  break;\n\n\tcase 1:\n\t  /* RLE_Block */\n\t  if (unlikely (pin >= pinend))\n\t    {\n\t      elf_uncompress_failed ();\n\t      return 0;\n\t    }\n\t  if (unlikely ((size_t) block_size > (size_t) (poutend - pout)))\n\t    {\n\t      elf_uncompress_failed ();\n\t      return 0;\n\t    }\n\t  memset (pout, *pin, block_size);\n\t  pout += block_size;\n\t  pin++;\n\t  break;\n\n\tcase 2:\n\t  {\n\t    const unsigned char *pblockend;\n\t    unsigned char *plitstack;\n\t    unsigned char *plit;\n\t    uint32_t literal_count;\n\t    unsigned char seq_hdr;\n\t    size_t seq_count;\n\t    size_t seq;\n\t    const unsigned char *pback;\n\t    uint64_t val;\n\t    unsigned int bits;\n\t    unsigned int literal_state;\n\t    unsigned int offset_state;\n\t    unsigned int match_state;\n\n\t    /* Compressed_Block */\n\t    if (unlikely ((size_t) block_size > (size_t) (pinend - pin)))\n\t      {\n\t\telf_uncompress_failed ();\n\t\treturn 0;\n\t      }\n\n\t    pblockend = pin + block_size;\n\n\t    /* Read the literals into the end of the output space, and leave\n\t       PLIT pointing at them.  */\n\n\t    if (!elf_zstd_read_literals (&pin, pblockend, pout, poutend,\n\t\t\t\t\t scratch, huffman_table,\n\t\t\t\t\t &huffman_table_bits,\n\t\t\t\t\t &plitstack))\n\t      return 0;\n\t    plit = plitstack;\n\t    literal_count = poutend - plit;\n\n\t    seq_hdr = *pin;\n\t    pin++;\n\t    if (seq_hdr < 128)\n\t      seq_count = seq_hdr;\n\t    else if (seq_hdr < 255)\n\t      {\n\t\tif (unlikely (pin >= pinend))\n\t\t  {\n\t\t    elf_uncompress_failed ();\n\t\t    return 0;\n\t\t  }\n\t\tseq_count = ((seq_hdr - 128) << 8) + *pin;\n\t\tpin++;\n\t      }\n\t    else\n\t      {\n\t\tif (unlikely (pin + 1 >= pinend))\n\t\t  {\n\t\t    elf_uncompress_failed ();\n\t\t    return 0;\n\t\t  }\n\t\tseq_count = *pin + (pin[1] << 8) + 0x7f00;\n\t\tpin += 2;\n\t      }\n\n\t    if (seq_count > 0)\n\t      {\n\t\tint (*pfn)(const struct elf_zstd_fse_entry *,\n\t\t\t   int, struct elf_zstd_fse_baseline_entry *);\n\n\t\tif (unlikely (pin >= pinend))\n\t\t  {\n\t\t    elf_uncompress_failed ();\n\t\t    return 0;\n\t\t  }\n\t\tseq_hdr = *pin;\n\t\t++pin;\n\n\t\tpfn = elf_zstd_make_literal_baseline_fse;\n\t\tif (!elf_zstd_unpack_seq_decode ((seq_hdr >> 6) & 3,\n\t\t\t\t\t\t &pin, pinend,\n\t\t\t\t\t\t &elf_zstd_lit_table[0], 6,\n\t\t\t\t\t\t scratch, 35,\n\t\t\t\t\t\t literal_fse_table, 9, pfn,\n\t\t\t\t\t\t &literal_decode))\n\t\t  return 0;\n\n\t\tpfn = elf_zstd_make_offset_baseline_fse;\n\t\tif (!elf_zstd_unpack_seq_decode ((seq_hdr >> 4) & 3,\n\t\t\t\t\t\t &pin, pinend,\n\t\t\t\t\t\t &elf_zstd_offset_table[0], 5,\n\t\t\t\t\t\t scratch, 31,\n\t\t\t\t\t\t offset_fse_table, 8, pfn,\n\t\t\t\t\t\t &offset_decode))\n\t\t  return 0;\n\n\t\tpfn = elf_zstd_make_match_baseline_fse;\n\t\tif (!elf_zstd_unpack_seq_decode ((seq_hdr >> 2) & 3,\n\t\t\t\t\t\t &pin, pinend,\n\t\t\t\t\t\t &elf_zstd_match_table[0], 6,\n\t\t\t\t\t\t scratch, 52,\n\t\t\t\t\t\t match_fse_table, 9, pfn,\n\t\t\t\t\t\t &match_decode))\n\t\t  return 0;\n\t      }\n\n\t    pback = pblockend - 1;\n\t    if (!elf_fetch_backward_init (&pback, pin, &val, &bits))\n\t      return 0;\n\n\t    bits -= literal_decode.table_bits;\n\t    literal_state = ((val >> bits)\n\t\t\t     & ((1U << literal_decode.table_bits) - 1));\n\n\t    if (!elf_fetch_bits_backward (&pback, pin, &val, &bits))\n\t      return 0;\n\t    bits -= offset_decode.table_bits;\n\t    offset_state = ((val >> bits)\n\t\t\t    & ((1U << offset_decode.table_bits) - 1));\n\n\t    if (!elf_fetch_bits_backward (&pback, pin, &val, &bits))\n\t      return 0;\n\t    bits -= match_decode.table_bits;\n\t    match_state = ((val >> bits)\n\t\t\t   & ((1U << match_decode.table_bits) - 1));\n\n\t    seq = 0;\n\t    while (1)\n\t      {\n\t\tconst struct elf_zstd_fse_baseline_entry *pt;\n\t\tuint32_t offset_basebits;\n\t\tuint32_t offset_baseline;\n\t\tuint32_t offset_bits;\n\t\tuint32_t offset_base;\n\t\tuint32_t offset;\n\t\tuint32_t match_baseline;\n\t\tuint32_t match_bits;\n\t\tuint32_t match_base;\n\t\tuint32_t match;\n\t\tuint32_t literal_baseline;\n\t\tuint32_t literal_bits;\n\t\tuint32_t literal_base;\n\t\tuint32_t literal;\n\t\tuint32_t need;\n\t\tuint32_t add;\n\n\t\tpt = &offset_decode.table[offset_state];\n\t\toffset_basebits = pt->basebits;\n\t\toffset_baseline = pt->baseline;\n\t\toffset_bits = pt->bits;\n\t\toffset_base = pt->base;\n\n\t\t/* This case can be more than 16 bits, which is all that\n\t\t   elf_fetch_bits_backward promises.  */\n\t\tneed = offset_basebits;\n\t\tadd = 0;\n\t\tif (unlikely (need > 16))\n\t\t  {\n\t\t    if (!elf_fetch_bits_backward (&pback, pin, &val, &bits))\n\t\t      return 0;\n\t\t    bits -= 16;\n\t\t    add = (val >> bits) & ((1U << 16) - 1);\n\t\t    need -= 16;\n\t\t    add <<= need;\n\t\t  }\n\t\tif (need > 0)\n\t\t  {\n\t\t    if (!elf_fetch_bits_backward (&pback, pin, &val, &bits))\n\t\t      return 0;\n\t\t    bits -= need;\n\t\t    add += (val >> bits) & ((1U << need) - 1);\n\t\t  }\n\n\t\toffset = offset_baseline + add;\n\n\t\tpt = &match_decode.table[match_state];\n\t\tneed = pt->basebits;\n\t\tmatch_baseline = pt->baseline;\n\t\tmatch_bits = pt->bits;\n\t\tmatch_base = pt->base;\n\n\t\tadd = 0;\n\t\tif (need > 0)\n\t\t  {\n\t\t    if (!elf_fetch_bits_backward (&pback, pin, &val, &bits))\n\t\t      return 0;\n\t\t    bits -= need;\n\t\t    add = (val >> bits) & ((1U << need) - 1);\n\t\t  }\n\n\t\tmatch = match_baseline + add;\n\n\t\tpt = &literal_decode.table[literal_state];\n\t\tneed = pt->basebits;\n\t\tliteral_baseline = pt->baseline;\n\t\tliteral_bits = pt->bits;\n\t\tliteral_base = pt->base;\n\n\t\tadd = 0;\n\t\tif (need > 0)\n\t\t  {\n\t\t    if (!elf_fetch_bits_backward (&pback, pin, &val, &bits))\n\t\t      return 0;\n\t\t    bits -= need;\n\t\t    add = (val >> bits) & ((1U << need) - 1);\n\t\t  }\n\n\t\tliteral = literal_baseline + add;\n\n\t\t/* See the comment in elf_zstd_make_offset_baseline_fse.  */\n\t\tif (offset_basebits > 1)\n\t\t  {\n\t\t    repeated_offset3 = repeated_offset2;\n\t\t    repeated_offset2 = repeated_offset1;\n\t\t    repeated_offset1 = offset;\n\t\t  }\n\t\telse\n\t\t  {\n\t\t    if (unlikely (literal == 0))\n\t\t      ++offset;\n\t\t    switch (offset)\n\t\t      {\n\t\t      case 1:\n\t\t\toffset = repeated_offset1;\n\t\t\tbreak;\n\t\t      case 2:\n\t\t\toffset = repeated_offset2;\n\t\t\trepeated_offset2 = repeated_offset1;\n\t\t\trepeated_offset1 = offset;\n\t\t\tbreak;\n\t\t      case 3:\n\t\t\toffset = repeated_offset3;\n\t\t\trepeated_offset3 = repeated_offset2;\n\t\t\trepeated_offset2 = repeated_offset1;\n\t\t\trepeated_offset1 = offset;\n\t\t\tbreak;\n\t\t      case 4:\n\t\t\toffset = repeated_offset1 - 1;\n\t\t\trepeated_offset3 = repeated_offset2;\n\t\t\trepeated_offset2 = repeated_offset1;\n\t\t\trepeated_offset1 = offset;\n\t\t\tbreak;\n\t\t      }\n\t\t  }\n\n\t\t++seq;\n\t\tif (seq < seq_count)\n\t\t  {\n\t\t    uint32_t v;\n\n\t\t    /* Update the three states.  */\n\n\t\t    if (!elf_fetch_bits_backward (&pback, pin, &val, &bits))\n\t\t      return 0;\n\n\t\t    need = literal_bits;\n\t\t    bits -= need;\n\t\t    v = (val >> bits) & (((uint32_t)1 << need) - 1);\n\n\t\t    literal_state = literal_base + v;\n\n\t\t    if (!elf_fetch_bits_backward (&pback, pin, &val, &bits))\n\t\t      return 0;\n\n\t\t    need = match_bits;\n\t\t    bits -= need;\n\t\t    v = (val >> bits) & (((uint32_t)1 << need) - 1);\n\n\t\t    match_state = match_base + v;\n\n\t\t    if (!elf_fetch_bits_backward (&pback, pin, &val, &bits))\n\t\t      return 0;\n\n\t\t    need = offset_bits;\n\t\t    bits -= need;\n\t\t    v = (val >> bits) & (((uint32_t)1 << need) - 1);\n\n\t\t    offset_state = offset_base + v;\n\t\t  }\n\n\t\t/* The next sequence is now in LITERAL, OFFSET, MATCH.  */\n\n\t\t/* Copy LITERAL bytes from the literals.  */\n\n\t\tif (unlikely ((size_t)(poutend - pout) < literal))\n\t\t  {\n\t\t    elf_uncompress_failed ();\n\t\t    return 0;\n\t\t  }\n\n\t\tif (unlikely (literal_count < literal))\n\t\t  {\n\t\t    elf_uncompress_failed ();\n\t\t    return 0;\n\t\t  }\n\n\t\tliteral_count -= literal;\n\n\t\t/* Often LITERAL is small, so handle small cases quickly.  */\n\t\tswitch (literal)\n\t\t  {\n\t\t  case 8:\n\t\t    *pout++ = *plit++;\n\t\t    ATTRIBUTE_FALLTHROUGH;\n\t\t  case 7:\n\t\t    *pout++ = *plit++;\n\t\t    ATTRIBUTE_FALLTHROUGH;\n\t\t  case 6:\n\t\t    *pout++ = *plit++;\n\t\t    ATTRIBUTE_FALLTHROUGH;\n\t\t  case 5:\n\t\t    *pout++ = *plit++;\n\t\t    ATTRIBUTE_FALLTHROUGH;\n\t\t  case 4:\n\t\t    *pout++ = *plit++;\n\t\t    ATTRIBUTE_FALLTHROUGH;\n\t\t  case 3:\n\t\t    *pout++ = *plit++;\n\t\t    ATTRIBUTE_FALLTHROUGH;\n\t\t  case 2:\n\t\t    *pout++ = *plit++;\n\t\t    ATTRIBUTE_FALLTHROUGH;\n\t\t  case 1:\n\t\t    *pout++ = *plit++;\n\t\t    break;\n\n\t\t  case 0:\n\t\t    break;\n\n\t\t  default:\n\t\t    if (unlikely ((size_t)(plit - pout) < literal))\n\t\t      {\n\t\t\tuint32_t move;\n\n\t\t\tmove = plit - pout;\n\t\t\twhile (literal > move)\n\t\t\t  {\n\t\t\t    memcpy (pout, plit, move);\n\t\t\t    pout += move;\n\t\t\t    plit += move;\n\t\t\t    literal -= move;\n\t\t\t  }\n\t\t      }\n\n\t\t    memcpy (pout, plit, literal);\n\t\t    pout += literal;\n\t\t    plit += literal;\n\t\t  }\n\n\t\tif (match > 0)\n\t\t  {\n\t\t    /* Copy MATCH bytes from the decoded output at OFFSET.  */\n\n\t\t    if (unlikely ((size_t)(poutend - pout) < match))\n\t\t      {\n\t\t\telf_uncompress_failed ();\n\t\t\treturn 0;\n\t\t      }\n\n\t\t    if (unlikely ((size_t)(pout - poutstart) < offset))\n\t\t      {\n\t\t\telf_uncompress_failed ();\n\t\t\treturn 0;\n\t\t      }\n\n\t\t    if (offset >= match)\n\t\t      {\n\t\t\tmemcpy (pout, pout - offset, match);\n\t\t\tpout += match;\n\t\t      }\n\t\t    else\n\t\t      {\n\t\t\twhile (match > 0)\n\t\t\t  {\n\t\t\t    uint32_t copy;\n\n\t\t\t    copy = match < offset ? match : offset;\n\t\t\t    memcpy (pout, pout - offset, copy);\n\t\t\t    match -= copy;\n\t\t\t    pout += copy;\n\t\t\t  }\n\t\t      }\n\t\t  }\n\n\t\tif (unlikely (seq >= seq_count))\n\t\t  {\n\t\t    /* Copy remaining literals.  */\n\t\t    if (literal_count > 0 && plit != pout)\n\t\t      {\n\t\t\tif (unlikely ((size_t)(poutend - pout)\n\t\t\t\t      < literal_count))\n\t\t\t  {\n\t\t\t    elf_uncompress_failed ();\n\t\t\t    return 0;\n\t\t\t  }\n\n\t\t\tif ((size_t)(plit - pout) < literal_count)\n\t\t\t  {\n\t\t\t    uint32_t move;\n\n\t\t\t    move = plit - pout;\n\t\t\t    while (literal_count > move)\n\t\t\t      {\n\t\t\t\tmemcpy (pout, plit, move);\n\t\t\t\tpout += move;\n\t\t\t\tplit += move;\n\t\t\t\tliteral_count -= move;\n\t\t\t      }\n\t\t\t  }\n\n\t\t\tmemcpy (pout, plit, literal_count);\n\t\t      }\n\n\t\t    pout += literal_count;\n\n\t\t    break;\n\t\t  }\n\t      }\n\n\t    pin = pblockend;\n\t  }\n\t  break;\n\n\tcase 3:\n\tdefault:\n\t  elf_uncompress_failed ();\n\t  return 0;\n\t}\n    }\n\n  if (has_checksum)\n    {\n      if (unlikely (pin + 4 > pinend))\n\t{\n\t  elf_uncompress_failed ();\n\t  return 0;\n\t}\n\n      /* We don't currently verify the checksum.  Currently running GNU ld with\n\t --compress-debug-sections=zstd does not seem to generate a\n\t checksum.  */\n\n      pin += 4;\n    }\n\n  if (pin != pinend)\n    {\n      elf_uncompress_failed ();\n      return 0;\n    }\n\n  return 1;\n}\n\n#define ZDEBUG_TABLE_SIZE \\\n  (ZLIB_TABLE_SIZE > ZSTD_TABLE_SIZE ? ZLIB_TABLE_SIZE : ZSTD_TABLE_SIZE)\n\n/* Uncompress the old compressed debug format, the one emitted by\n   --compress-debug-sections=zlib-gnu.  The compressed data is in\n   COMPRESSED / COMPRESSED_SIZE, and the function writes to\n   *UNCOMPRESSED / *UNCOMPRESSED_SIZE.  ZDEBUG_TABLE is work space to\n   hold Huffman tables.  Returns 0 on error, 1 on successful\n   decompression or if something goes wrong.  In general we try to\n   carry on, by returning 1, even if we can't decompress.  */\n\nstatic int\nelf_uncompress_zdebug (struct backtrace_state *state,\n\t\t       const unsigned char *compressed, size_t compressed_size,\n\t\t       uint16_t *zdebug_table,\n\t\t       backtrace_error_callback error_callback, void *data,\n\t\t       unsigned char **uncompressed, size_t *uncompressed_size)\n{\n  size_t sz;\n  size_t i;\n  unsigned char *po;\n\n  *uncompressed = NULL;\n  *uncompressed_size = 0;\n\n  /* The format starts with the four bytes ZLIB, followed by the 8\n     byte length of the uncompressed data in big-endian order,\n     followed by a zlib stream.  */\n\n  if (compressed_size < 12 || memcmp (compressed, \"ZLIB\", 4) != 0)\n    return 1;\n\n  sz = 0;\n  for (i = 0; i < 8; i++)\n    sz = (sz << 8) | compressed[i + 4];\n\n  if (*uncompressed != NULL && *uncompressed_size >= sz)\n    po = *uncompressed;\n  else\n    {\n      po = (unsigned char *) backtrace_alloc (state, sz, error_callback, data);\n      if (po == NULL)\n\treturn 0;\n    }\n\n  if (!elf_zlib_inflate_and_verify (compressed + 12, compressed_size - 12,\n\t\t\t\t    zdebug_table, po, sz))\n    return 1;\n\n  *uncompressed = po;\n  *uncompressed_size = sz;\n\n  return 1;\n}\n\n/* Uncompress the new compressed debug format, the official standard\n   ELF approach emitted by --compress-debug-sections=zlib-gabi.  The\n   compressed data is in COMPRESSED / COMPRESSED_SIZE, and the\n   function writes to *UNCOMPRESSED / *UNCOMPRESSED_SIZE.\n   ZDEBUG_TABLE is work space as for elf_uncompress_zdebug.  Returns 0\n   on error, 1 on successful decompression or if something goes wrong.\n   In general we try to carry on, by returning 1, even if we can't\n   decompress.  */\n\nstatic int\nelf_uncompress_chdr (struct backtrace_state *state,\n\t\t     const unsigned char *compressed, size_t compressed_size,\n\t\t     uint16_t *zdebug_table,\n\t\t     backtrace_error_callback error_callback, void *data,\n\t\t     unsigned char **uncompressed, size_t *uncompressed_size)\n{\n  b_elf_chdr chdr;\n  char *alc;\n  size_t alc_len;\n  unsigned char *po;\n\n  *uncompressed = NULL;\n  *uncompressed_size = 0;\n\n  /* The format starts with an ELF compression header.  */\n  if (compressed_size < sizeof (b_elf_chdr))\n    return 1;\n\n  /* The lld linker can misalign a compressed section, so we can't safely read\n     the fields directly as we can for other ELF sections.  See\n     https://github.com/ianlancetaylor/libbacktrace/pull/120.  */\n  memcpy (&chdr, compressed, sizeof (b_elf_chdr));\n\n  alc = NULL;\n  alc_len = 0;\n  if (*uncompressed != NULL && *uncompressed_size >= chdr.ch_size)\n    po = *uncompressed;\n  else\n    {\n      alc_len = chdr.ch_size;\n      alc = backtrace_alloc (state, alc_len, error_callback, data);\n      if (alc == NULL)\n\treturn 0;\n      po = (unsigned char *) alc;\n    }\n\n  switch (chdr.ch_type)\n    {\n    case ELFCOMPRESS_ZLIB:\n      if (!elf_zlib_inflate_and_verify (compressed + sizeof (b_elf_chdr),\n\t\t\t\t\tcompressed_size - sizeof (b_elf_chdr),\n\t\t\t\t\tzdebug_table, po, chdr.ch_size))\n\tgoto skip;\n      break;\n\n    case ELFCOMPRESS_ZSTD:\n      if (!elf_zstd_decompress (compressed + sizeof (b_elf_chdr),\n\t\t\t\tcompressed_size - sizeof (b_elf_chdr),\n\t\t\t\t(unsigned char *)zdebug_table, po,\n\t\t\t\tchdr.ch_size))\n\tgoto skip;\n      break;\n\n    default:\n      /* Unsupported compression algorithm.  */\n      goto skip;\n    }\n\n  *uncompressed = po;\n  *uncompressed_size = chdr.ch_size;\n\n  return 1;\n\n skip:\n  if (alc != NULL && alc_len > 0)\n    backtrace_free (state, alc, alc_len, error_callback, data);\n  return 1;\n}\n\n/* This function is a hook for testing the zlib support.  It is only\n   used by tests.  */\n\nint\nbacktrace_uncompress_zdebug (struct backtrace_state *state,\n\t\t\t     const unsigned char *compressed,\n\t\t\t     size_t compressed_size,\n\t\t\t     backtrace_error_callback error_callback,\n\t\t\t     void *data, unsigned char **uncompressed,\n\t\t\t     size_t *uncompressed_size)\n{\n  uint16_t *zdebug_table;\n  int ret;\n\n  zdebug_table = ((uint16_t *) backtrace_alloc (state, ZDEBUG_TABLE_SIZE,\n\t\t\t\t\t\terror_callback, data));\n  if (zdebug_table == NULL)\n    return 0;\n  ret = elf_uncompress_zdebug (state, compressed, compressed_size,\n\t\t\t       zdebug_table, error_callback, data,\n\t\t\t       uncompressed, uncompressed_size);\n  backtrace_free (state, zdebug_table, ZDEBUG_TABLE_SIZE,\n\t\t  error_callback, data);\n  return ret;\n}\n\n/* This function is a hook for testing the zstd support.  It is only used by\n   tests.  */\n\nint\nbacktrace_uncompress_zstd (struct backtrace_state *state,\n\t\t\t   const unsigned char *compressed,\n\t\t\t   size_t compressed_size,\n\t\t\t   backtrace_error_callback error_callback,\n\t\t\t   void *data, unsigned char *uncompressed,\n\t\t\t   size_t uncompressed_size)\n{\n  unsigned char *zdebug_table;\n  int ret;\n\n  zdebug_table = ((unsigned char *) backtrace_alloc (state, ZDEBUG_TABLE_SIZE,\n\t\t\t\t\t\t     error_callback, data));\n  if (zdebug_table == NULL)\n    return 0;\n  ret = elf_zstd_decompress (compressed, compressed_size,\n\t\t\t     zdebug_table, uncompressed, uncompressed_size);\n  backtrace_free (state, zdebug_table, ZDEBUG_TABLE_SIZE,\n\t\t  error_callback, data);\n  return ret;\n}\n\n/* Number of LZMA states.  */\n#define LZMA_STATES (12)\n\n/* Number of LZMA position states.  The pb value of the property byte\n   is the number of bits to include in these states, and the maximum\n   value of pb is 4.  */\n#define LZMA_POS_STATES (16)\n\n/* Number of LZMA distance states.  These are used match distances\n   with a short match length: up to 4 bytes.  */\n#define LZMA_DIST_STATES (4)\n\n/* Number of LZMA distance slots.  LZMA uses six bits to encode larger\n   match lengths, so 1 << 6 possible probabilities.  */\n#define LZMA_DIST_SLOTS (64)\n\n/* LZMA distances 0 to 3 are encoded directly, larger values use a\n   probability model.  */\n#define LZMA_DIST_MODEL_START (4)\n\n/* The LZMA probability model ends at 14.  */\n#define LZMA_DIST_MODEL_END (14)\n\n/* LZMA distance slots for distances less than 127.  */\n#define LZMA_FULL_DISTANCES (128)\n\n/* LZMA uses four alignment bits.  */\n#define LZMA_ALIGN_SIZE (16)\n\n/* LZMA match length is encoded with 4, 5, or 10 bits, some of which\n   are already known.  */\n#define LZMA_LEN_LOW_SYMBOLS (8)\n#define LZMA_LEN_MID_SYMBOLS (8)\n#define LZMA_LEN_HIGH_SYMBOLS (256)\n\n/* LZMA literal encoding.  */\n#define LZMA_LITERAL_CODERS_MAX (16)\n#define LZMA_LITERAL_CODER_SIZE (0x300)\n\n/* LZMA is based on a large set of probabilities, each managed\n   independently.  Each probability is an 11 bit number that we store\n   in a uint16_t.  We use a single large array of probabilities.  */\n\n/* Lengths of entries in the LZMA probabilities array.  The names used\n   here are copied from the Linux kernel implementation.  */\n\n#define LZMA_PROB_IS_MATCH_LEN (LZMA_STATES * LZMA_POS_STATES)\n#define LZMA_PROB_IS_REP_LEN LZMA_STATES\n#define LZMA_PROB_IS_REP0_LEN LZMA_STATES\n#define LZMA_PROB_IS_REP1_LEN LZMA_STATES\n#define LZMA_PROB_IS_REP2_LEN LZMA_STATES\n#define LZMA_PROB_IS_REP0_LONG_LEN (LZMA_STATES * LZMA_POS_STATES)\n#define LZMA_PROB_DIST_SLOT_LEN (LZMA_DIST_STATES * LZMA_DIST_SLOTS)\n#define LZMA_PROB_DIST_SPECIAL_LEN (LZMA_FULL_DISTANCES - LZMA_DIST_MODEL_END)\n#define LZMA_PROB_DIST_ALIGN_LEN LZMA_ALIGN_SIZE\n#define LZMA_PROB_MATCH_LEN_CHOICE_LEN 1\n#define LZMA_PROB_MATCH_LEN_CHOICE2_LEN 1\n#define LZMA_PROB_MATCH_LEN_LOW_LEN (LZMA_POS_STATES * LZMA_LEN_LOW_SYMBOLS)\n#define LZMA_PROB_MATCH_LEN_MID_LEN (LZMA_POS_STATES * LZMA_LEN_MID_SYMBOLS)\n#define LZMA_PROB_MATCH_LEN_HIGH_LEN LZMA_LEN_HIGH_SYMBOLS\n#define LZMA_PROB_REP_LEN_CHOICE_LEN 1\n#define LZMA_PROB_REP_LEN_CHOICE2_LEN 1\n#define LZMA_PROB_REP_LEN_LOW_LEN (LZMA_POS_STATES * LZMA_LEN_LOW_SYMBOLS)\n#define LZMA_PROB_REP_LEN_MID_LEN (LZMA_POS_STATES * LZMA_LEN_MID_SYMBOLS)\n#define LZMA_PROB_REP_LEN_HIGH_LEN LZMA_LEN_HIGH_SYMBOLS\n#define LZMA_PROB_LITERAL_LEN \\\n  (LZMA_LITERAL_CODERS_MAX * LZMA_LITERAL_CODER_SIZE)\n\n/* Offsets into the LZMA probabilities array.  This is mechanically\n   generated from the above lengths.  */\n\n#define LZMA_PROB_IS_MATCH_OFFSET 0\n#define LZMA_PROB_IS_REP_OFFSET \\\n  (LZMA_PROB_IS_MATCH_OFFSET + LZMA_PROB_IS_MATCH_LEN)\n#define LZMA_PROB_IS_REP0_OFFSET \\\n  (LZMA_PROB_IS_REP_OFFSET + LZMA_PROB_IS_REP_LEN)\n#define LZMA_PROB_IS_REP1_OFFSET \\\n  (LZMA_PROB_IS_REP0_OFFSET + LZMA_PROB_IS_REP0_LEN)\n#define LZMA_PROB_IS_REP2_OFFSET \\\n  (LZMA_PROB_IS_REP1_OFFSET + LZMA_PROB_IS_REP1_LEN)\n#define LZMA_PROB_IS_REP0_LONG_OFFSET \\\n  (LZMA_PROB_IS_REP2_OFFSET + LZMA_PROB_IS_REP2_LEN)\n#define LZMA_PROB_DIST_SLOT_OFFSET \\\n  (LZMA_PROB_IS_REP0_LONG_OFFSET + LZMA_PROB_IS_REP0_LONG_LEN)\n#define LZMA_PROB_DIST_SPECIAL_OFFSET \\\n  (LZMA_PROB_DIST_SLOT_OFFSET + LZMA_PROB_DIST_SLOT_LEN)\n#define LZMA_PROB_DIST_ALIGN_OFFSET \\\n  (LZMA_PROB_DIST_SPECIAL_OFFSET + LZMA_PROB_DIST_SPECIAL_LEN)\n#define LZMA_PROB_MATCH_LEN_CHOICE_OFFSET \\\n  (LZMA_PROB_DIST_ALIGN_OFFSET + LZMA_PROB_DIST_ALIGN_LEN)\n#define LZMA_PROB_MATCH_LEN_CHOICE2_OFFSET \\\n  (LZMA_PROB_MATCH_LEN_CHOICE_OFFSET + LZMA_PROB_MATCH_LEN_CHOICE_LEN)\n#define LZMA_PROB_MATCH_LEN_LOW_OFFSET \\\n  (LZMA_PROB_MATCH_LEN_CHOICE2_OFFSET + LZMA_PROB_MATCH_LEN_CHOICE2_LEN)\n#define LZMA_PROB_MATCH_LEN_MID_OFFSET \\\n  (LZMA_PROB_MATCH_LEN_LOW_OFFSET + LZMA_PROB_MATCH_LEN_LOW_LEN)\n#define LZMA_PROB_MATCH_LEN_HIGH_OFFSET \\\n  (LZMA_PROB_MATCH_LEN_MID_OFFSET + LZMA_PROB_MATCH_LEN_MID_LEN)\n#define LZMA_PROB_REP_LEN_CHOICE_OFFSET \\\n  (LZMA_PROB_MATCH_LEN_HIGH_OFFSET + LZMA_PROB_MATCH_LEN_HIGH_LEN)\n#define LZMA_PROB_REP_LEN_CHOICE2_OFFSET \\\n  (LZMA_PROB_REP_LEN_CHOICE_OFFSET + LZMA_PROB_REP_LEN_CHOICE_LEN)\n#define LZMA_PROB_REP_LEN_LOW_OFFSET \\\n  (LZMA_PROB_REP_LEN_CHOICE2_OFFSET + LZMA_PROB_REP_LEN_CHOICE2_LEN)\n#define LZMA_PROB_REP_LEN_MID_OFFSET \\\n  (LZMA_PROB_REP_LEN_LOW_OFFSET + LZMA_PROB_REP_LEN_LOW_LEN)\n#define LZMA_PROB_REP_LEN_HIGH_OFFSET \\\n  (LZMA_PROB_REP_LEN_MID_OFFSET + LZMA_PROB_REP_LEN_MID_LEN)\n#define LZMA_PROB_LITERAL_OFFSET \\\n  (LZMA_PROB_REP_LEN_HIGH_OFFSET + LZMA_PROB_REP_LEN_HIGH_LEN)\n\n#define LZMA_PROB_TOTAL_COUNT \\\n  (LZMA_PROB_LITERAL_OFFSET + LZMA_PROB_LITERAL_LEN)\n\n/* Check that the number of LZMA probabilities is the same as the\n   Linux kernel implementation.  */\n\n#if LZMA_PROB_TOTAL_COUNT != 1846 + (1 << 4) * 0x300\n #error Wrong number of LZMA probabilities\n#endif\n\n/* Expressions for the offset in the LZMA probabilities array of a\n   specific probability.  */\n\n#define LZMA_IS_MATCH(state, pos) \\\n  (LZMA_PROB_IS_MATCH_OFFSET + (state) * LZMA_POS_STATES + (pos))\n#define LZMA_IS_REP(state) \\\n  (LZMA_PROB_IS_REP_OFFSET + (state))\n#define LZMA_IS_REP0(state) \\\n  (LZMA_PROB_IS_REP0_OFFSET + (state))\n#define LZMA_IS_REP1(state) \\\n  (LZMA_PROB_IS_REP1_OFFSET + (state))\n#define LZMA_IS_REP2(state) \\\n  (LZMA_PROB_IS_REP2_OFFSET + (state))\n#define LZMA_IS_REP0_LONG(state, pos) \\\n  (LZMA_PROB_IS_REP0_LONG_OFFSET + (state) * LZMA_POS_STATES + (pos))\n#define LZMA_DIST_SLOT(dist, slot) \\\n  (LZMA_PROB_DIST_SLOT_OFFSET + (dist) * LZMA_DIST_SLOTS + (slot))\n#define LZMA_DIST_SPECIAL(dist) \\\n  (LZMA_PROB_DIST_SPECIAL_OFFSET + (dist))\n#define LZMA_DIST_ALIGN(dist) \\\n  (LZMA_PROB_DIST_ALIGN_OFFSET + (dist))\n#define LZMA_MATCH_LEN_CHOICE \\\n  LZMA_PROB_MATCH_LEN_CHOICE_OFFSET\n#define LZMA_MATCH_LEN_CHOICE2 \\\n  LZMA_PROB_MATCH_LEN_CHOICE2_OFFSET\n#define LZMA_MATCH_LEN_LOW(pos, sym) \\\n  (LZMA_PROB_MATCH_LEN_LOW_OFFSET + (pos) * LZMA_LEN_LOW_SYMBOLS + (sym))\n#define LZMA_MATCH_LEN_MID(pos, sym) \\\n  (LZMA_PROB_MATCH_LEN_MID_OFFSET + (pos) * LZMA_LEN_MID_SYMBOLS + (sym))\n#define LZMA_MATCH_LEN_HIGH(sym) \\\n  (LZMA_PROB_MATCH_LEN_HIGH_OFFSET + (sym))\n#define LZMA_REP_LEN_CHOICE \\\n  LZMA_PROB_REP_LEN_CHOICE_OFFSET\n#define LZMA_REP_LEN_CHOICE2 \\\n  LZMA_PROB_REP_LEN_CHOICE2_OFFSET\n#define LZMA_REP_LEN_LOW(pos, sym) \\\n  (LZMA_PROB_REP_LEN_LOW_OFFSET + (pos) * LZMA_LEN_LOW_SYMBOLS + (sym))\n#define LZMA_REP_LEN_MID(pos, sym) \\\n  (LZMA_PROB_REP_LEN_MID_OFFSET + (pos) * LZMA_LEN_MID_SYMBOLS + (sym))\n#define LZMA_REP_LEN_HIGH(sym) \\\n  (LZMA_PROB_REP_LEN_HIGH_OFFSET + (sym))\n#define LZMA_LITERAL(code, size) \\\n  (LZMA_PROB_LITERAL_OFFSET + (code) * LZMA_LITERAL_CODER_SIZE + (size))\n\n/* Read an LZMA varint from BUF, reading and updating *POFFSET,\n   setting *VAL.  Returns 0 on error, 1 on success.  */\n\nstatic int\nelf_lzma_varint (const unsigned char *compressed, size_t compressed_size,\n\t\t size_t *poffset, uint64_t *val)\n{\n  size_t off;\n  int i;\n  uint64_t v;\n  unsigned char b;\n\n  off = *poffset;\n  i = 0;\n  v = 0;\n  while (1)\n    {\n      if (unlikely (off >= compressed_size))\n\t{\n\t  elf_uncompress_failed ();\n\t  return 0;\n\t}\n      b = compressed[off];\n      v |= (b & 0x7f) << (i * 7);\n      ++off;\n      if ((b & 0x80) == 0)\n\t{\n\t  *poffset = off;\n\t  *val = v;\n\t  return 1;\n\t}\n      ++i;\n      if (unlikely (i >= 9))\n\t{\n\t  elf_uncompress_failed ();\n\t  return 0;\n\t}\n    }\n}\n\n/* Normalize the LZMA range decoder, pulling in an extra input byte if\n   needed.  */\n\nstatic void\nelf_lzma_range_normalize (const unsigned char *compressed,\n\t\t\t  size_t compressed_size, size_t *poffset,\n\t\t\t  uint32_t *prange, uint32_t *pcode)\n{\n  if (*prange < (1U << 24))\n    {\n      if (unlikely (*poffset >= compressed_size))\n\t{\n\t  /* We assume this will be caught elsewhere.  */\n\t  elf_uncompress_failed ();\n\t  return;\n\t}\n      *prange <<= 8;\n      *pcode <<= 8;\n      *pcode += compressed[*poffset];\n      ++*poffset;\n    }\n}\n\n/* Read and return a single bit from the LZMA stream, reading and\n   updating *PROB.  Each bit comes from the range coder.  */\n\nstatic int\nelf_lzma_bit (const unsigned char *compressed, size_t compressed_size,\n\t      uint16_t *prob, size_t *poffset, uint32_t *prange,\n\t      uint32_t *pcode)\n{\n  uint32_t bound;\n\n  elf_lzma_range_normalize (compressed, compressed_size, poffset,\n\t\t\t    prange, pcode);\n  bound = (*prange >> 11) * (uint32_t) *prob;\n  if (*pcode < bound)\n    {\n      *prange = bound;\n      *prob += ((1U << 11) - *prob) >> 5;\n      return 0;\n    }\n  else\n    {\n      *prange -= bound;\n      *pcode -= bound;\n      *prob -= *prob >> 5;\n      return 1;\n    }\n}\n\n/* Read an integer of size BITS from the LZMA stream, most significant\n   bit first.  The bits are predicted using PROBS.  */\n\nstatic uint32_t\nelf_lzma_integer (const unsigned char *compressed, size_t compressed_size,\n\t\t  uint16_t *probs, uint32_t bits, size_t *poffset,\n\t\t  uint32_t *prange, uint32_t *pcode)\n{\n  uint32_t sym;\n  uint32_t i;\n\n  sym = 1;\n  for (i = 0; i < bits; i++)\n    {\n      int bit;\n\n      bit = elf_lzma_bit (compressed, compressed_size, probs + sym, poffset,\n\t\t\t  prange, pcode);\n      sym <<= 1;\n      sym += bit;\n    }\n  return sym - (1 << bits);\n}\n\n/* Read an integer of size BITS from the LZMA stream, least\n   significant bit first.  The bits are predicted using PROBS.  */\n\nstatic uint32_t\nelf_lzma_reverse_integer (const unsigned char *compressed,\n\t\t\t  size_t compressed_size, uint16_t *probs,\n\t\t\t  uint32_t bits, size_t *poffset, uint32_t *prange,\n\t\t\t  uint32_t *pcode)\n{\n  uint32_t sym;\n  uint32_t val;\n  uint32_t i;\n\n  sym = 1;\n  val = 0;\n  for (i = 0; i < bits; i++)\n    {\n      int bit;\n\n      bit = elf_lzma_bit (compressed, compressed_size, probs + sym, poffset,\n\t\t\t  prange, pcode);\n      sym <<= 1;\n      sym += bit;\n      val += bit << i;\n    }\n  return val;\n}\n\n/* Read a length from the LZMA stream.  IS_REP picks either LZMA_MATCH\n   or LZMA_REP probabilities.  */\n\nstatic uint32_t\nelf_lzma_len (const unsigned char *compressed, size_t compressed_size,\n\t      uint16_t *probs, int is_rep, unsigned int pos_state,\n\t      size_t *poffset, uint32_t *prange, uint32_t *pcode)\n{\n  uint16_t *probs_choice;\n  uint16_t *probs_sym;\n  uint32_t bits;\n  uint32_t len;\n\n  probs_choice = probs + (is_rep\n\t\t\t  ? LZMA_REP_LEN_CHOICE\n\t\t\t  : LZMA_MATCH_LEN_CHOICE);\n  if (elf_lzma_bit (compressed, compressed_size, probs_choice, poffset,\n\t\t    prange, pcode))\n    {\n      probs_choice = probs + (is_rep\n\t\t\t      ? LZMA_REP_LEN_CHOICE2\n\t\t\t      : LZMA_MATCH_LEN_CHOICE2);\n      if (elf_lzma_bit (compressed, compressed_size, probs_choice,\n\t\t\tpoffset, prange, pcode))\n\t{\n\t  probs_sym = probs + (is_rep\n\t\t\t       ? LZMA_REP_LEN_HIGH (0)\n\t\t\t       : LZMA_MATCH_LEN_HIGH (0));\n\t  bits = 8;\n\t  len = 2 + 8 + 8;\n\t}\n      else\n\t{\n\t  probs_sym = probs + (is_rep\n\t\t\t       ? LZMA_REP_LEN_MID (pos_state, 0)\n\t\t\t       : LZMA_MATCH_LEN_MID (pos_state, 0));\n\t  bits = 3;\n\t  len = 2 + 8;\n\t}\n    }\n  else\n    {\n      probs_sym = probs + (is_rep\n\t\t\t   ? LZMA_REP_LEN_LOW (pos_state, 0)\n\t\t\t   : LZMA_MATCH_LEN_LOW (pos_state, 0));\n      bits = 3;\n      len = 2;\n    }\n\n  len += elf_lzma_integer (compressed, compressed_size, probs_sym, bits,\n\t\t\t   poffset, prange, pcode);\n  return len;\n}\n\n/* Uncompress one LZMA block from a minidebug file.  The compressed\n   data is at COMPRESSED + *POFFSET.  Update *POFFSET.  Store the data\n   into the memory at UNCOMPRESSED, size UNCOMPRESSED_SIZE.  CHECK is\n   the stream flag from the xz header.  Return 1 on successful\n   decompression.  */\n\nstatic int\nelf_uncompress_lzma_block (const unsigned char *compressed,\n\t\t\t   size_t compressed_size, unsigned char check,\n\t\t\t   uint16_t *probs, unsigned char *uncompressed,\n\t\t\t   size_t uncompressed_size, size_t *poffset)\n{\n  size_t off;\n  size_t block_header_offset;\n  size_t block_header_size;\n  unsigned char block_flags;\n  uint64_t header_compressed_size;\n  uint64_t header_uncompressed_size;\n  unsigned char lzma2_properties;\n  size_t crc_offset;\n  uint32_t computed_crc;\n  uint32_t stream_crc;\n  size_t uncompressed_offset;\n  size_t dict_start_offset;\n  unsigned int lc;\n  unsigned int lp;\n  unsigned int pb;\n  uint32_t range;\n  uint32_t code;\n  uint32_t lstate;\n  uint32_t dist[4];\n\n  off = *poffset;\n  block_header_offset = off;\n\n  /* Block header size is a single byte.  */\n  if (unlikely (off >= compressed_size))\n    {\n      elf_uncompress_failed ();\n      return 0;\n    }\n  block_header_size = (compressed[off] + 1) * 4;\n  if (unlikely (off + block_header_size > compressed_size))\n    {\n      elf_uncompress_failed ();\n      return 0;\n    }\n\n  /* Block flags.  */\n  block_flags = compressed[off + 1];\n  if (unlikely ((block_flags & 0x3c) != 0))\n    {\n      elf_uncompress_failed ();\n      return 0;\n    }\n\n  off += 2;\n\n  /* Optional compressed size.  */\n  header_compressed_size = 0;\n  if ((block_flags & 0x40) != 0)\n    {\n      *poffset = off;\n      if (!elf_lzma_varint (compressed, compressed_size, poffset,\n\t\t\t    &header_compressed_size))\n\treturn 0;\n      off = *poffset;\n    }\n\n  /* Optional uncompressed size.  */\n  header_uncompressed_size = 0;\n  if ((block_flags & 0x80) != 0)\n    {\n      *poffset = off;\n      if (!elf_lzma_varint (compressed, compressed_size, poffset,\n\t\t\t    &header_uncompressed_size))\n\treturn 0;\n      off = *poffset;\n    }\n\n  /* The recipe for creating a minidebug file is to run the xz program\n     with no arguments, so we expect exactly one filter: lzma2.  */\n\n  if (unlikely ((block_flags & 0x3) != 0))\n    {\n      elf_uncompress_failed ();\n      return 0;\n    }\n\n  if (unlikely (off + 2 >= block_header_offset + block_header_size))\n    {\n      elf_uncompress_failed ();\n      return 0;\n    }\n\n  /* The filter ID for LZMA2 is 0x21.  */\n  if (unlikely (compressed[off] != 0x21))\n    {\n      elf_uncompress_failed ();\n      return 0;\n    }\n  ++off;\n\n  /* The size of the filter properties for LZMA2 is 1.  */\n  if (unlikely (compressed[off] != 1))\n    {\n      elf_uncompress_failed ();\n      return 0;\n    }\n  ++off;\n\n  lzma2_properties = compressed[off];\n  ++off;\n\n  if (unlikely (lzma2_properties > 40))\n    {\n      elf_uncompress_failed ();\n      return 0;\n    }\n\n  /* The properties describe the dictionary size, but we don't care\n     what that is.  */\n\n  /* Skip to just before CRC, verifying zero bytes in between.  */\n  crc_offset = block_header_offset + block_header_size - 4;\n  if (unlikely (crc_offset + 4 > compressed_size))\n    {\n      elf_uncompress_failed ();\n      return 0;\n    }\n  for (; off < crc_offset; off++)\n    {\n      if (compressed[off] != 0)\n\t{\n\t  elf_uncompress_failed ();\n\t  return 0;\n\t}\n    }\n\n  /* Block header CRC.  */\n  computed_crc = elf_crc32 (0, compressed + block_header_offset,\n\t\t\t    block_header_size - 4);\n  stream_crc = ((uint32_t)compressed[off]\n\t\t| ((uint32_t)compressed[off + 1] << 8)\n\t\t| ((uint32_t)compressed[off + 2] << 16)\n\t\t| ((uint32_t)compressed[off + 3] << 24));\n  if (unlikely (computed_crc != stream_crc))\n    {\n      elf_uncompress_failed ();\n      return 0;\n    }\n  off += 4;\n\n  /* Read a sequence of LZMA2 packets.  */\n\n  uncompressed_offset = 0;\n  dict_start_offset = 0;\n  lc = 0;\n  lp = 0;\n  pb = 0;\n  lstate = 0;\n  while (off < compressed_size)\n    {\n      unsigned char control;\n\n      range = 0xffffffff;\n      code = 0;\n\n      control = compressed[off];\n      ++off;\n      if (unlikely (control == 0))\n\t{\n\t  /* End of packets.  */\n\t  break;\n\t}\n\n      if (control == 1 || control >= 0xe0)\n\t{\n\t  /* Reset dictionary to empty.  */\n\t  dict_start_offset = uncompressed_offset;\n\t}\n\n      if (control < 0x80)\n\t{\n\t  size_t chunk_size;\n\n\t  /* The only valid values here are 1 or 2.  A 1 means to\n\t     reset the dictionary (done above).  Then we see an\n\t     uncompressed chunk.  */\n\n\t  if (unlikely (control > 2))\n\t    {\n\t      elf_uncompress_failed ();\n\t      return 0;\n\t    }\n\n\t  /* An uncompressed chunk is a two byte size followed by\n\t     data.  */\n\n\t  if (unlikely (off + 2 > compressed_size))\n\t    {\n\t      elf_uncompress_failed ();\n\t      return 0;\n\t    }\n\n\t  chunk_size = compressed[off] << 8;\n\t  chunk_size += compressed[off + 1];\n\t  ++chunk_size;\n\n\t  off += 2;\n\n\t  if (unlikely (off + chunk_size > compressed_size))\n\t    {\n\t      elf_uncompress_failed ();\n\t      return 0;\n\t    }\n\t  if (unlikely (uncompressed_offset + chunk_size > uncompressed_size))\n\t    {\n\t      elf_uncompress_failed ();\n\t      return 0;\n\t    }\n\n\t  memcpy (uncompressed + uncompressed_offset, compressed + off,\n\t\t  chunk_size);\n\t  uncompressed_offset += chunk_size;\n\t  off += chunk_size;\n\t}\n      else\n\t{\n\t  size_t uncompressed_chunk_start;\n\t  size_t uncompressed_chunk_size;\n\t  size_t compressed_chunk_size;\n\t  size_t limit;\n\n\t  /* An LZMA chunk.  This starts with an uncompressed size and\n\t     a compressed size.  */\n\n\t  if (unlikely (off + 4 >= compressed_size))\n\t    {\n\t      elf_uncompress_failed ();\n\t      return 0;\n\t    }\n\n\t  uncompressed_chunk_start = uncompressed_offset;\n\n\t  uncompressed_chunk_size = (control & 0x1f) << 16;\n\t  uncompressed_chunk_size += compressed[off] << 8;\n\t  uncompressed_chunk_size += compressed[off + 1];\n\t  ++uncompressed_chunk_size;\n\n\t  compressed_chunk_size = compressed[off + 2] << 8;\n\t  compressed_chunk_size += compressed[off + 3];\n\t  ++compressed_chunk_size;\n\n\t  off += 4;\n\n\t  /* Bit 7 (0x80) is set.\n\t     Bits 6 and 5 (0x40 and 0x20) are as follows:\n\t     0: don't reset anything\n\t     1: reset state\n\t     2: reset state, read properties\n\t     3: reset state, read properties, reset dictionary (done above) */\n\n\t  if (control >= 0xc0)\n\t    {\n\t      unsigned char props;\n\n\t      /* Bit 6 is set, read properties.  */\n\n\t      if (unlikely (off >= compressed_size))\n\t\t{\n\t\t  elf_uncompress_failed ();\n\t\t  return 0;\n\t\t}\n\t      props = compressed[off];\n\t      ++off;\n\t      if (unlikely (props > (4 * 5 + 4) * 9 + 8))\n\t\t{\n\t\t  elf_uncompress_failed ();\n\t\t  return 0;\n\t\t}\n\t      pb = 0;\n\t      while (props >= 9 * 5)\n\t\t{\n\t\t  props -= 9 * 5;\n\t\t  ++pb;\n\t\t}\n\t      lp = 0;\n\t      while (props > 9)\n\t\t{\n\t\t  props -= 9;\n\t\t  ++lp;\n\t\t}\n\t      lc = props;\n\t      if (unlikely (lc + lp > 4))\n\t\t{\n\t\t  elf_uncompress_failed ();\n\t\t  return 0;\n\t\t}\n\t    }\n\n\t  if (control >= 0xa0)\n\t    {\n\t      size_t i;\n\n\t      /* Bit 5 or 6 is set, reset LZMA state.  */\n\n\t      lstate = 0;\n\t      memset (&dist, 0, sizeof dist);\n\t      for (i = 0; i < LZMA_PROB_TOTAL_COUNT; i++)\n\t\tprobs[i] = 1 << 10;\n\t      range = 0xffffffff;\n\t      code = 0;\n\t    }\n\n\t  /* Read the range code.  */\n\n\t  if (unlikely (off + 5 > compressed_size))\n\t    {\n\t      elf_uncompress_failed ();\n\t      return 0;\n\t    }\n\n\t  /* The byte at compressed[off] is ignored for some\n\t     reason.  */\n\n\t  code = ((compressed[off + 1] << 24)\n\t\t  + (compressed[off + 2] << 16)\n\t\t  + (compressed[off + 3] << 8)\n\t\t  + compressed[off + 4]);\n\t  off += 5;\n\n\t  /* This is the main LZMA decode loop.  */\n\n\t  limit = off + compressed_chunk_size;\n\t  *poffset = off;\n\t  while (*poffset < limit)\n\t    {\n\t      unsigned int pos_state;\n\n\t      if (unlikely (uncompressed_offset\n\t\t\t    == (uncompressed_chunk_start\n\t\t\t\t+ uncompressed_chunk_size)))\n\t\t{\n\t\t  /* We've decompressed all the expected bytes.  */\n\t\t  break;\n\t\t}\n\n\t      pos_state = ((uncompressed_offset - dict_start_offset)\n\t\t\t   & ((1 << pb) - 1));\n\n\t      if (elf_lzma_bit (compressed, compressed_size,\n\t\t\t\tprobs + LZMA_IS_MATCH (lstate, pos_state),\n\t\t\t\tpoffset, &range, &code))\n\t\t{\n\t\t  uint32_t len;\n\n\t\t  if (elf_lzma_bit (compressed, compressed_size,\n\t\t\t\t    probs + LZMA_IS_REP (lstate),\n\t\t\t\t    poffset, &range, &code))\n\t\t    {\n\t\t      int short_rep;\n\t\t      uint32_t next_dist;\n\n\t\t      /* Repeated match.  */\n\n\t\t      short_rep = 0;\n\t\t      if (elf_lzma_bit (compressed, compressed_size,\n\t\t\t\t\tprobs + LZMA_IS_REP0 (lstate),\n\t\t\t\t\tpoffset, &range, &code))\n\t\t\t{\n\t\t\t  if (elf_lzma_bit (compressed, compressed_size,\n\t\t\t\t\t    probs + LZMA_IS_REP1 (lstate),\n\t\t\t\t\t    poffset, &range, &code))\n\t\t\t    {\n\t\t\t      if (elf_lzma_bit (compressed, compressed_size,\n\t\t\t\t\t\tprobs + LZMA_IS_REP2 (lstate),\n\t\t\t\t\t\tpoffset, &range, &code))\n\t\t\t\t{\n\t\t\t\t  next_dist = dist[3];\n\t\t\t\t  dist[3] = dist[2];\n\t\t\t\t}\n\t\t\t      else\n\t\t\t\t{\n\t\t\t\t  next_dist = dist[2];\n\t\t\t\t}\n\t\t\t      dist[2] = dist[1];\n\t\t\t    }\n\t\t\t  else\n\t\t\t    {\n\t\t\t      next_dist = dist[1];\n\t\t\t    }\n\n\t\t\t  dist[1] = dist[0];\n\t\t\t  dist[0] = next_dist;\n\t\t\t}\n\t\t      else\n\t\t\t{\n\t\t\t  if (!elf_lzma_bit (compressed, compressed_size,\n\t\t\t\t\t    (probs\n\t\t\t\t\t     + LZMA_IS_REP0_LONG (lstate,\n\t\t\t\t\t\t\t\t  pos_state)),\n\t\t\t\t\t    poffset, &range, &code))\n\t\t\t    short_rep = 1;\n\t\t\t}\n\n\t\t      if (lstate < 7)\n\t\t\tlstate = short_rep ? 9 : 8;\n\t\t      else\n\t\t\tlstate = 11;\n\n\t\t      if (short_rep)\n\t\t\tlen = 1;\n\t\t      else\n\t\t\tlen = elf_lzma_len (compressed, compressed_size,\n\t\t\t\t\t    probs, 1, pos_state, poffset,\n\t\t\t\t\t    &range, &code);\n\t\t    }\n\t\t  else\n\t\t    {\n\t\t      uint32_t dist_state;\n\t\t      uint32_t dist_slot;\n\t\t      uint16_t *probs_dist;\n\n\t\t      /* Match.  */\n\n\t\t      if (lstate < 7)\n\t\t\tlstate = 7;\n\t\t      else\n\t\t\tlstate = 10;\n\t\t      dist[3] = dist[2];\n\t\t      dist[2] = dist[1];\n\t\t      dist[1] = dist[0];\n\t\t      len = elf_lzma_len (compressed, compressed_size,\n\t\t\t\t\t  probs, 0, pos_state, poffset,\n\t\t\t\t\t  &range, &code);\n\n\t\t      if (len < 4 + 2)\n\t\t\tdist_state = len - 2;\n\t\t      else\n\t\t\tdist_state = 3;\n\t\t      probs_dist = probs + LZMA_DIST_SLOT (dist_state, 0);\n\t\t      dist_slot = elf_lzma_integer (compressed,\n\t\t\t\t\t\t    compressed_size,\n\t\t\t\t\t\t    probs_dist, 6,\n\t\t\t\t\t\t    poffset, &range,\n\t\t\t\t\t\t    &code);\n\t\t      if (dist_slot < LZMA_DIST_MODEL_START)\n\t\t\tdist[0] = dist_slot;\n\t\t      else\n\t\t\t{\n\t\t\t  uint32_t limit;\n\n\t\t\t  limit = (dist_slot >> 1) - 1;\n\t\t\t  dist[0] = 2 + (dist_slot & 1);\n\t\t\t  if (dist_slot < LZMA_DIST_MODEL_END)\n\t\t\t    {\n\t\t\t      dist[0] <<= limit;\n\t\t\t      probs_dist = (probs\n\t\t\t\t\t    + LZMA_DIST_SPECIAL(dist[0]\n\t\t\t\t\t\t\t\t- dist_slot\n\t\t\t\t\t\t\t\t- 1));\n\t\t\t      dist[0] +=\n\t\t\t\telf_lzma_reverse_integer (compressed,\n\t\t\t\t\t\t\t  compressed_size,\n\t\t\t\t\t\t\t  probs_dist,\n\t\t\t\t\t\t\t  limit, poffset,\n\t\t\t\t\t\t\t  &range, &code);\n\t\t\t    }\n\t\t\t  else\n\t\t\t    {\n\t\t\t      uint32_t dist0;\n\t\t\t      uint32_t i;\n\n\t\t\t      dist0 = dist[0];\n\t\t\t      for (i = 0; i < limit - 4; i++)\n\t\t\t\t{\n\t\t\t\t  uint32_t mask;\n\n\t\t\t\t  elf_lzma_range_normalize (compressed,\n\t\t\t\t\t\t\t    compressed_size,\n\t\t\t\t\t\t\t    poffset,\n\t\t\t\t\t\t\t    &range, &code);\n\t\t\t\t  range >>= 1;\n\t\t\t\t  code -= range;\n\t\t\t\t  mask = -(code >> 31);\n\t\t\t\t  code += range & mask;\n\t\t\t\t  dist0 <<= 1;\n\t\t\t\t  dist0 += mask + 1;\n\t\t\t\t}\n\t\t\t      dist0 <<= 4;\n\t\t\t      probs_dist = probs + LZMA_DIST_ALIGN (0);\n\t\t\t      dist0 +=\n\t\t\t\telf_lzma_reverse_integer (compressed,\n\t\t\t\t\t\t\t  compressed_size,\n\t\t\t\t\t\t\t  probs_dist, 4,\n\t\t\t\t\t\t\t  poffset,\n\t\t\t\t\t\t\t  &range, &code);\n\t\t\t      dist[0] = dist0;\n\t\t\t    }\n\t\t\t}\n\t\t    }\n\n\t\t  if (unlikely (uncompressed_offset\n\t\t\t\t- dict_start_offset < dist[0] + 1))\n\t\t    {\n\t\t      elf_uncompress_failed ();\n\t\t      return 0;\n\t\t    }\n\t\t  if (unlikely (uncompressed_offset + len > uncompressed_size))\n\t\t    {\n\t\t      elf_uncompress_failed ();\n\t\t      return 0;\n\t\t    }\n\n\t\t  if (dist[0] == 0)\n\t\t    {\n\t\t      /* A common case, meaning repeat the last\n\t\t\t character LEN times.  */\n\t\t      memset (uncompressed + uncompressed_offset,\n\t\t\t      uncompressed[uncompressed_offset - 1],\n\t\t\t      len);\n\t\t      uncompressed_offset += len;\n\t\t    }\n\t\t  else if (dist[0] + 1 >= len)\n\t\t    {\n\t\t      memcpy (uncompressed + uncompressed_offset,\n\t\t\t      uncompressed + uncompressed_offset - dist[0] - 1,\n\t\t\t      len);\n\t\t      uncompressed_offset += len;\n\t\t    }\n\t\t  else\n\t\t    {\n\t\t      while (len > 0)\n\t\t\t{\n\t\t\t  uint32_t copy;\n\n\t\t\t  copy = len < dist[0] + 1 ? len : dist[0] + 1;\n\t\t\t  memcpy (uncompressed + uncompressed_offset,\n\t\t\t\t  (uncompressed + uncompressed_offset\n\t\t\t\t   - dist[0] - 1),\n\t\t\t\t  copy);\n\t\t\t  len -= copy;\n\t\t\t  uncompressed_offset += copy;\n\t\t\t}\n\t\t    }\n\t\t}\n\t      else\n\t\t{\n\t\t  unsigned char prev;\n\t\t  unsigned char low;\n\t\t  size_t high;\n\t\t  uint16_t *lit_probs;\n\t\t  unsigned int sym;\n\n\t\t  /* Literal value.  */\n\n\t\t  if (uncompressed_offset > 0)\n\t\t    prev = uncompressed[uncompressed_offset - 1];\n\t\t  else\n\t\t    prev = 0;\n\t\t  low = prev >> (8 - lc);\n\t\t  high = (((uncompressed_offset - dict_start_offset)\n\t\t\t   & ((1 << lp) - 1))\n\t\t\t  << lc);\n\t\t  lit_probs = probs + LZMA_LITERAL (low + high, 0);\n\t\t  if (lstate < 7)\n\t\t    sym = elf_lzma_integer (compressed, compressed_size,\n\t\t\t\t\t    lit_probs, 8, poffset, &range,\n\t\t\t\t\t    &code);\n\t\t  else\n\t\t    {\n\t\t      unsigned int match;\n\t\t      unsigned int bit;\n\t\t      unsigned int match_bit;\n\t\t      unsigned int idx;\n\n\t\t      sym = 1;\n\t\t      if (uncompressed_offset >= dist[0] + 1)\n\t\t\tmatch = uncompressed[uncompressed_offset - dist[0] - 1];\n\t\t      else\n\t\t\tmatch = 0;\n\t\t      match <<= 1;\n\t\t      bit = 0x100;\n\t\t      do\n\t\t\t{\n\t\t\t  match_bit = match & bit;\n\t\t\t  match <<= 1;\n\t\t\t  idx = bit + match_bit + sym;\n\t\t\t  sym <<= 1;\n\t\t\t  if (elf_lzma_bit (compressed, compressed_size,\n\t\t\t\t\t    lit_probs + idx, poffset,\n\t\t\t\t\t    &range, &code))\n\t\t\t    {\n\t\t\t      ++sym;\n\t\t\t      bit &= match_bit;\n\t\t\t    }\n\t\t\t  else\n\t\t\t    {\n\t\t\t      bit &= ~ match_bit;\n\t\t\t    }\n\t\t\t}\n\t\t      while (sym < 0x100);\n\t\t    }\n\n\t\t  if (unlikely (uncompressed_offset >= uncompressed_size))\n\t\t    {\n\t\t      elf_uncompress_failed ();\n\t\t      return 0;\n\t\t    }\n\n\t\t  uncompressed[uncompressed_offset] = (unsigned char) sym;\n\t\t  ++uncompressed_offset;\n\t\t  if (lstate <= 3)\n\t\t    lstate = 0;\n\t\t  else if (lstate <= 9)\n\t\t    lstate -= 3;\n\t\t  else\n\t\t    lstate -= 6;\n\t\t}\n\t    }\n\n\t  elf_lzma_range_normalize (compressed, compressed_size, poffset,\n\t\t\t\t    &range, &code);\n\n\t  off = *poffset;\n\t}\n    }\n\n  /* We have reached the end of the block.  Pad to four byte\n     boundary.  */\n  off = (off + 3) &~ (size_t) 3;\n  if (unlikely (off > compressed_size))\n    {\n      elf_uncompress_failed ();\n      return 0;\n    }\n\n  switch (check)\n    {\n    case 0:\n      /* No check.  */\n      break;\n\n    case 1:\n      /* CRC32 */\n      if (unlikely (off + 4 > compressed_size))\n\t{\n\t  elf_uncompress_failed ();\n\t  return 0;\n\t}\n      computed_crc = elf_crc32 (0, uncompressed, uncompressed_offset);\n      stream_crc = (compressed[off]\n\t\t    | (compressed[off + 1] << 8)\n\t\t    | (compressed[off + 2] << 16)\n\t\t    | (compressed[off + 3] << 24));\n      if (computed_crc != stream_crc)\n\t{\n\t  elf_uncompress_failed ();\n\t  return 0;\n\t}\n      off += 4;\n      break;\n\n    case 4:\n      /* CRC64.  We don't bother computing a CRC64 checksum.  */\n      if (unlikely (off + 8 > compressed_size))\n\t{\n\t  elf_uncompress_failed ();\n\t  return 0;\n\t}\n      off += 8;\n      break;\n\n    case 10:\n      /* SHA.  We don't bother computing a SHA checksum.  */\n      if (unlikely (off + 32 > compressed_size))\n\t{\n\t  elf_uncompress_failed ();\n\t  return 0;\n\t}\n      off += 32;\n      break;\n\n    default:\n      elf_uncompress_failed ();\n      return 0;\n    }\n\n  *poffset = off;\n\n  return 1;\n}\n\n/* Uncompress LZMA data found in a minidebug file.  The minidebug\n   format is described at\n   https://sourceware.org/gdb/current/onlinedocs/gdb/MiniDebugInfo.html.\n   Returns 0 on error, 1 on successful decompression.  For this\n   function we return 0 on failure to decompress, as the calling code\n   will carry on in that case.  */\n\nstatic int\nelf_uncompress_lzma (struct backtrace_state *state,\n\t\t     const unsigned char *compressed, size_t compressed_size,\n\t\t     backtrace_error_callback error_callback, void *data,\n\t\t     unsigned char **uncompressed, size_t *uncompressed_size)\n{\n  size_t header_size;\n  size_t footer_size;\n  unsigned char check;\n  uint32_t computed_crc;\n  uint32_t stream_crc;\n  size_t offset;\n  size_t index_size;\n  size_t footer_offset;\n  size_t index_offset;\n  uint64_t index_compressed_size;\n  uint64_t index_uncompressed_size;\n  unsigned char *mem;\n  uint16_t *probs;\n  size_t compressed_block_size;\n\n  /* The format starts with a stream header and ends with a stream\n     footer.  */\n  header_size = 12;\n  footer_size = 12;\n  if (unlikely (compressed_size < header_size + footer_size))\n    {\n      elf_uncompress_failed ();\n      return 0;\n    }\n\n  /* The stream header starts with a magic string.  */\n  if (unlikely (memcmp (compressed, \"\\375\" \"7zXZ\\0\", 6) != 0))\n    {\n      elf_uncompress_failed ();\n      return 0;\n    }\n\n  /* Next come stream flags.  The first byte is zero, the second byte\n     is the check.  */\n  if (unlikely (compressed[6] != 0))\n    {\n      elf_uncompress_failed ();\n      return 0;\n    }\n  check = compressed[7];\n  if (unlikely ((check & 0xf8) != 0))\n    {\n      elf_uncompress_failed ();\n      return 0;\n    }\n\n  /* Next comes a CRC of the stream flags.  */\n  computed_crc = elf_crc32 (0, compressed + 6, 2);\n  stream_crc = ((uint32_t)compressed[8]\n\t\t| ((uint32_t)compressed[9] << 8)\n\t\t| ((uint32_t)compressed[10] << 16)\n\t\t| ((uint32_t)compressed[11] << 24));\n  if (unlikely (computed_crc != stream_crc))\n    {\n      elf_uncompress_failed ();\n      return 0;\n    }\n\n  /* Now that we've parsed the header, parse the footer, so that we\n     can get the uncompressed size.  */\n\n  /* The footer ends with two magic bytes.  */\n\n  offset = compressed_size;\n  if (unlikely (memcmp (compressed + offset - 2, \"YZ\", 2) != 0))\n    {\n      elf_uncompress_failed ();\n      return 0;\n    }\n  offset -= 2;\n\n  /* Before that are the stream flags, which should be the same as the\n     flags in the header.  */\n  if (unlikely (compressed[offset - 2] != 0\n\t\t|| compressed[offset - 1] != check))\n    {\n      elf_uncompress_failed ();\n      return 0;\n    }\n  offset -= 2;\n\n  /* Before that is the size of the index field, which precedes the\n     footer.  */\n  index_size = (compressed[offset - 4]\n\t\t| (compressed[offset - 3] << 8)\n\t\t| (compressed[offset - 2] << 16)\n\t\t| (compressed[offset - 1] << 24));\n  index_size = (index_size + 1) * 4;\n  offset -= 4;\n\n  /* Before that is a footer CRC.  */\n  computed_crc = elf_crc32 (0, compressed + offset, 6);\n  stream_crc = ((uint32_t)compressed[offset - 4]\n\t\t| ((uint32_t)compressed[offset - 3] << 8)\n\t\t| ((uint32_t)compressed[offset - 2] << 16)\n\t\t| ((uint32_t)compressed[offset - 1] << 24));\n  if (unlikely (computed_crc != stream_crc))\n    {\n      elf_uncompress_failed ();\n      return 0;\n    }\n  offset -= 4;\n\n  /* The index comes just before the footer.  */\n  if (unlikely (offset < index_size + header_size))\n    {\n      elf_uncompress_failed ();\n      return 0;\n    }\n\n  footer_offset = offset;\n  offset -= index_size;\n  index_offset = offset;\n\n  /* The index starts with a zero byte.  */\n  if (unlikely (compressed[offset] != 0))\n    {\n      elf_uncompress_failed ();\n      return 0;\n    }\n  ++offset;\n\n  /* Next is the number of blocks.  We expect zero blocks for an empty\n     stream, and otherwise a single block.  */\n  if (unlikely (compressed[offset] == 0))\n    {\n      *uncompressed = NULL;\n      *uncompressed_size = 0;\n      return 1;\n    }\n  if (unlikely (compressed[offset] != 1))\n    {\n      elf_uncompress_failed ();\n      return 0;\n    }\n  ++offset;\n\n  /* Next is the compressed size and the uncompressed size.  */\n  if (!elf_lzma_varint (compressed, compressed_size, &offset,\n\t\t\t&index_compressed_size))\n    return 0;\n  if (!elf_lzma_varint (compressed, compressed_size, &offset,\n\t\t\t&index_uncompressed_size))\n    return 0;\n\n  /* Pad to a four byte boundary.  */\n  offset = (offset + 3) &~ (size_t) 3;\n\n  /* Next is a CRC of the index.  */\n  computed_crc = elf_crc32 (0, compressed + index_offset,\n\t\t\t    offset - index_offset);\n  stream_crc = ((uint32_t)compressed[offset]\n\t\t| ((uint32_t)compressed[offset + 1] << 8)\n\t\t| ((uint32_t)compressed[offset + 2] << 16)\n\t\t| ((uint32_t)compressed[offset + 3] << 24));\n  if (unlikely (computed_crc != stream_crc))\n    {\n      elf_uncompress_failed ();\n      return 0;\n    }\n  offset += 4;\n\n  /* We should now be back at the footer.  */\n  if (unlikely (offset != footer_offset))\n    {\n      elf_uncompress_failed ();\n      return 0;\n    }\n\n  /* Allocate space to hold the uncompressed data.  If we succeed in\n     uncompressing the LZMA data, we never free this memory.  */\n  mem = (unsigned char *) backtrace_alloc (state, index_uncompressed_size,\n\t\t\t\t\t   error_callback, data);\n  if (unlikely (mem == NULL))\n    return 0;\n  *uncompressed = mem;\n  *uncompressed_size = index_uncompressed_size;\n\n  /* Allocate space for probabilities.  */\n  probs = ((uint16_t *)\n\t   backtrace_alloc (state,\n\t\t\t    LZMA_PROB_TOTAL_COUNT * sizeof (uint16_t),\n\t\t\t    error_callback, data));\n  if (unlikely (probs == NULL))\n    {\n      backtrace_free (state, mem, index_uncompressed_size, error_callback,\n\t\t      data);\n      return 0;\n    }\n\n  /* Uncompress the block, which follows the header.  */\n  offset = 12;\n  if (!elf_uncompress_lzma_block (compressed, compressed_size, check, probs,\n\t\t\t\t  mem, index_uncompressed_size, &offset))\n    {\n      backtrace_free (state, mem, index_uncompressed_size, error_callback,\n\t\t      data);\n      return 0;\n    }\n\n  compressed_block_size = offset - 12;\n  if (unlikely (compressed_block_size\n\t\t!= ((index_compressed_size + 3) &~ (size_t) 3)))\n    {\n      elf_uncompress_failed ();\n      backtrace_free (state, mem, index_uncompressed_size, error_callback,\n\t\t      data);\n      return 0;\n    }\n\n  offset = (offset + 3) &~ (size_t) 3;\n  if (unlikely (offset != index_offset))\n    {\n      elf_uncompress_failed ();\n      backtrace_free (state, mem, index_uncompressed_size, error_callback,\n\t\t      data);\n      return 0;\n    }\n\n  return 1;\n}\n\n/* This function is a hook for testing the LZMA support.  It is only\n   used by tests.  */\n\nint\nbacktrace_uncompress_lzma (struct backtrace_state *state,\n\t\t\t   const unsigned char *compressed,\n\t\t\t   size_t compressed_size,\n\t\t\t   backtrace_error_callback error_callback,\n\t\t\t   void *data, unsigned char **uncompressed,\n\t\t\t   size_t *uncompressed_size)\n{\n  return elf_uncompress_lzma (state, compressed, compressed_size,\n\t\t\t      error_callback, data, uncompressed,\n\t\t\t      uncompressed_size);\n}\n\n/* Add the backtrace data for one ELF file.  Returns 1 on success,\n   0 on failure (in both cases descriptor is closed) or -1 if exe\n   is non-zero and the ELF file is ET_DYN, which tells the caller that\n   elf_add will need to be called on the descriptor again after\n   base_address is determined.  */\n\nint\nelf_add (struct backtrace_state *state, const char *filename, int descriptor,\n\t const unsigned char *memory, size_t memory_size,\n\t struct libbacktrace_base_address base_address,\n\t struct elf_ppc64_opd_data *caller_opd,\n\t backtrace_error_callback error_callback, void *data,\n\t fileline *fileline_fn, int *found_sym, int *found_dwarf,\n\t struct dwarf_data **fileline_entry, int exe, int debuginfo,\n\t const char *with_buildid_data, uint32_t with_buildid_size)\n{\n  struct elf_view ehdr_view;\n  b_elf_ehdr ehdr;\n  off_t shoff;\n  unsigned int shnum;\n  unsigned int shstrndx;\n  struct elf_view shdrs_view;\n  int shdrs_view_valid;\n  const b_elf_shdr *shdrs;\n  const b_elf_shdr *shstrhdr;\n  size_t shstr_size;\n  off_t shstr_off;\n  struct elf_view names_view;\n  int names_view_valid;\n  const char *names;\n  unsigned int symtab_shndx;\n  unsigned int dynsym_shndx;\n  unsigned int i;\n  struct debug_section_info sections[DEBUG_MAX];\n  struct debug_section_info zsections[DEBUG_MAX];\n  struct elf_view symtab_view;\n  int symtab_view_valid;\n  struct elf_view strtab_view;\n  int strtab_view_valid;\n  struct elf_view buildid_view;\n  int buildid_view_valid;\n  const char *buildid_data;\n  uint32_t buildid_size;\n  struct elf_view debuglink_view;\n  int debuglink_view_valid;\n  const char *debuglink_name;\n  uint32_t debuglink_crc;\n  struct elf_view debugaltlink_view;\n  int debugaltlink_view_valid;\n  const char *debugaltlink_name;\n  const char *debugaltlink_buildid_data;\n  uint32_t debugaltlink_buildid_size;\n  struct elf_view gnu_debugdata_view;\n  int gnu_debugdata_view_valid;\n  size_t gnu_debugdata_size;\n  unsigned char *gnu_debugdata_uncompressed;\n  size_t gnu_debugdata_uncompressed_size;\n  off_t min_offset;\n  off_t max_offset;\n  off_t debug_size;\n  struct elf_view debug_view;\n  int debug_view_valid;\n  unsigned int using_debug_view;\n  uint16_t *zdebug_table;\n  struct elf_view split_debug_view[DEBUG_MAX];\n  unsigned char split_debug_view_valid[DEBUG_MAX];\n  struct elf_ppc64_opd_data opd_data, *opd;\n  int opd_view_valid;\n  struct dwarf_sections dwarf_sections;\n\n  if (!debuginfo)\n    {\n      *found_sym = 0;\n      *found_dwarf = 0;\n    }\n\n  shdrs_view_valid = 0;\n  names_view_valid = 0;\n  symtab_view_valid = 0;\n  strtab_view_valid = 0;\n  buildid_view_valid = 0;\n  buildid_data = NULL;\n  buildid_size = 0;\n  debuglink_view_valid = 0;\n  debuglink_name = NULL;\n  debuglink_crc = 0;\n  debugaltlink_view_valid = 0;\n  debugaltlink_name = NULL;\n  debugaltlink_buildid_data = NULL;\n  debugaltlink_buildid_size = 0;\n  gnu_debugdata_view_valid = 0;\n  gnu_debugdata_size = 0;\n  debug_view_valid = 0;\n  memset (&split_debug_view_valid[0], 0, sizeof split_debug_view_valid);\n  opd = NULL;\n  opd_view_valid = 0;\n\n  if (!elf_get_view (state, descriptor, memory, memory_size, 0, sizeof ehdr,\n\t\t     error_callback, data, &ehdr_view))\n    goto fail;\n\n  memcpy (&ehdr, ehdr_view.view.data, sizeof ehdr);\n\n  elf_release_view (state, &ehdr_view, error_callback, data);\n\n  if (ehdr.e_ident[EI_MAG0] != ELFMAG0\n      || ehdr.e_ident[EI_MAG1] != ELFMAG1\n      || ehdr.e_ident[EI_MAG2] != ELFMAG2\n      || ehdr.e_ident[EI_MAG3] != ELFMAG3)\n    {\n      error_callback (data, \"executable file is not ELF\", 0);\n      goto fail;\n    }\n  if (ehdr.e_ident[EI_VERSION] != EV_CURRENT)\n    {\n      error_callback (data, \"executable file is unrecognized ELF version\", 0);\n      goto fail;\n    }\n\n#if BACKTRACE_ELF_SIZE == 32\n#define BACKTRACE_ELFCLASS ELFCLASS32\n#else\n#define BACKTRACE_ELFCLASS ELFCLASS64\n#endif\n\n  if (ehdr.e_ident[EI_CLASS] != BACKTRACE_ELFCLASS)\n    {\n      error_callback (data, \"executable file is unexpected ELF class\", 0);\n      goto fail;\n    }\n\n  if (ehdr.e_ident[EI_DATA] != ELFDATA2LSB\n      && ehdr.e_ident[EI_DATA] != ELFDATA2MSB)\n    {\n      error_callback (data, \"executable file has unknown endianness\", 0);\n      goto fail;\n    }\n\n  /* If the executable is ET_DYN, it is either a PIE, or we are running\n     directly a shared library with .interp.  We need to wait for\n     dl_iterate_phdr in that case to determine the actual base_address.  */\n  if (exe && ehdr.e_type == ET_DYN)\n    return -1;\n\n  shoff = ehdr.e_shoff;\n  shnum = ehdr.e_shnum;\n  shstrndx = ehdr.e_shstrndx;\n\n  if ((shnum == 0 || shstrndx == SHN_XINDEX)\n      && shoff != 0)\n    {\n      struct elf_view shdr_view;\n      const b_elf_shdr *shdr;\n\n      if (!elf_get_view (state, descriptor, memory, memory_size, shoff,\n\t\t\t sizeof shdr, error_callback, data, &shdr_view))\n\tgoto fail;\n\n      shdr = (const b_elf_shdr *) shdr_view.view.data;\n\n      if (shnum == 0)\n\tshnum = shdr->sh_size;\n\n      if (shstrndx == SHN_XINDEX)\n\t{\n\t  shstrndx = shdr->sh_link;\n\n\t  /* Versions of the GNU binutils between 2.12 and 2.18 did\n\t     not handle objects with more than SHN_LORESERVE sections\n\t     correctly.  All large section indexes were offset by\n\t     0x100.  There is more information at\n\t     http://sourceware.org/bugzilla/show_bug.cgi?id-5900 .\n\t     Fortunately these object files are easy to detect, as the\n\t     GNU binutils always put the section header string table\n\t     near the end of the list of sections.  Thus if the\n\t     section header string table index is larger than the\n\t     number of sections, then we know we have to subtract\n\t     0x100 to get the real section index.  */\n\t  if (shstrndx >= shnum && shstrndx >= SHN_LORESERVE + 0x100)\n\t    shstrndx -= 0x100;\n\t}\n\n      elf_release_view (state, &shdr_view, error_callback, data);\n    }\n\n  if (shnum == 0 || shstrndx == 0)\n    goto fail;\n\n  /* To translate PC to file/line when using DWARF, we need to find\n     the .debug_info and .debug_line sections.  */\n\n  /* Read the section headers, skipping the first one.  */\n\n  if (!elf_get_view (state, descriptor, memory, memory_size,\n\t\t     shoff + sizeof (b_elf_shdr),\n\t\t     (shnum - 1) * sizeof (b_elf_shdr),\n\t\t     error_callback, data, &shdrs_view))\n    goto fail;\n  shdrs_view_valid = 1;\n  shdrs = (const b_elf_shdr *) shdrs_view.view.data;\n\n  /* Read the section names.  */\n\n  shstrhdr = &shdrs[shstrndx - 1];\n  shstr_size = shstrhdr->sh_size;\n  shstr_off = shstrhdr->sh_offset;\n\n  if (!elf_get_view (state, descriptor, memory, memory_size, shstr_off,\n\t\t     shstrhdr->sh_size, error_callback, data, &names_view))\n    goto fail;\n  names_view_valid = 1;\n  names = (const char *) names_view.view.data;\n\n  symtab_shndx = 0;\n  dynsym_shndx = 0;\n\n  memset (sections, 0, sizeof sections);\n  memset (zsections, 0, sizeof zsections);\n\n  /* Look for the symbol table.  */\n  for (i = 1; i < shnum; ++i)\n    {\n      const b_elf_shdr *shdr;\n      unsigned int sh_name;\n      const char *name;\n      int j;\n\n      shdr = &shdrs[i - 1];\n\n      if (shdr->sh_type == SHT_SYMTAB)\n\tsymtab_shndx = i;\n      else if (shdr->sh_type == SHT_DYNSYM)\n\tdynsym_shndx = i;\n\n      sh_name = shdr->sh_name;\n      if (sh_name >= shstr_size)\n\t{\n\t  error_callback (data, \"ELF section name out of range\", 0);\n\t  goto fail;\n\t}\n\n      name = names + sh_name;\n\n      for (j = 0; j < (int) DEBUG_MAX; ++j)\n\t{\n\t  if (strcmp (name, dwarf_section_names[j]) == 0)\n\t    {\n\t      sections[j].offset = shdr->sh_offset;\n\t      sections[j].size = shdr->sh_size;\n\t      sections[j].compressed = (shdr->sh_flags & SHF_COMPRESSED) != 0;\n\t      break;\n\t    }\n\t}\n\n      if (name[0] == '.' && name[1] == 'z')\n\t{\n\t  for (j = 0; j < (int) DEBUG_MAX; ++j)\n\t    {\n\t      if (strcmp (name + 2, dwarf_section_names[j] + 1) == 0)\n\t\t{\n\t\t  zsections[j].offset = shdr->sh_offset;\n\t\t  zsections[j].size = shdr->sh_size;\n\t\t  break;\n\t\t}\n\t    }\n\t}\n\n      /* Read the build ID if present.  This could check for any\n\t SHT_NOTE section with the right note name and type, but gdb\n\t looks for a specific section name.  */\n      if ((!debuginfo || with_buildid_data != NULL)\n\t  && !buildid_view_valid\n\t  && strcmp (name, \".note.gnu.build-id\") == 0)\n\t{\n\t  const b_elf_note *note;\n\n\t  if (!elf_get_view (state, descriptor, memory, memory_size,\n\t\t\t     shdr->sh_offset, shdr->sh_size, error_callback,\n\t\t\t     data, &buildid_view))\n\t    goto fail;\n\n\t  buildid_view_valid = 1;\n\t  note = (const b_elf_note *) buildid_view.view.data;\n\t  if (note->type == NT_GNU_BUILD_ID\n\t      && note->namesz == 4\n\t      && strncmp (note->name, \"GNU\", 4) == 0\n\t      && shdr->sh_size <= 12 + ((note->namesz + 3) & ~ 3) + note->descsz)\n\t    {\n\t      buildid_data = &note->name[0] + ((note->namesz + 3) & ~ 3);\n\t      buildid_size = note->descsz;\n\t    }\n\n\t  if (with_buildid_size != 0)\n\t    {\n\t      if (buildid_size != with_buildid_size)\n\t\tgoto fail;\n\n\t      if (memcmp (buildid_data, with_buildid_data, buildid_size) != 0)\n\t\tgoto fail;\n\t    }\n\t}\n\n      /* Read the debuglink file if present.  */\n      if (!debuginfo\n\t  && !debuglink_view_valid\n\t  && strcmp (name, \".gnu_debuglink\") == 0)\n\t{\n\t  const char *debuglink_data;\n\t  size_t crc_offset;\n\n\t  if (!elf_get_view (state, descriptor, memory, memory_size,\n\t\t\t     shdr->sh_offset, shdr->sh_size, error_callback,\n\t\t\t     data, &debuglink_view))\n\t    goto fail;\n\n\t  debuglink_view_valid = 1;\n\t  debuglink_data = (const char *) debuglink_view.view.data;\n\t  crc_offset = strnlen (debuglink_data, shdr->sh_size);\n\t  crc_offset = (crc_offset + 3) & ~3;\n\t  if (crc_offset + 4 <= shdr->sh_size)\n\t    {\n\t      debuglink_name = debuglink_data;\n\t      debuglink_crc = *(const uint32_t*)(debuglink_data + crc_offset);\n\t    }\n\t}\n\n      if (!debugaltlink_view_valid\n\t  && strcmp (name, \".gnu_debugaltlink\") == 0)\n\t{\n\t  const char *debugaltlink_data;\n\t  size_t debugaltlink_name_len;\n\n\t  if (!elf_get_view (state, descriptor, memory, memory_size,\n\t\t\t     shdr->sh_offset, shdr->sh_size, error_callback,\n\t\t\t     data, &debugaltlink_view))\n\t    goto fail;\n\n\t  debugaltlink_view_valid = 1;\n\t  debugaltlink_data = (const char *) debugaltlink_view.view.data;\n\t  debugaltlink_name = debugaltlink_data;\n\t  debugaltlink_name_len = strnlen (debugaltlink_data, shdr->sh_size);\n\t  if (debugaltlink_name_len < shdr->sh_size)\n\t    {\n\t      /* Include terminating zero.  */\n\t      debugaltlink_name_len += 1;\n\n\t      debugaltlink_buildid_data\n\t\t= debugaltlink_data + debugaltlink_name_len;\n\t      debugaltlink_buildid_size = shdr->sh_size - debugaltlink_name_len;\n\t    }\n\t}\n\n      if (!debuginfo\n\t  && !gnu_debugdata_view_valid\n\t  && strcmp (name, \".gnu_debugdata\") == 0)\n\t{\n\t  if (!elf_get_view (state, descriptor, memory, memory_size,\n\t\t\t     shdr->sh_offset, shdr->sh_size, error_callback,\n\t\t\t     data, &gnu_debugdata_view))\n\t    goto fail;\n\n\t  gnu_debugdata_size = shdr->sh_size;\n\t  gnu_debugdata_view_valid = 1;\n\t}\n\n      /* Read the .opd section on PowerPC64 ELFv1.  */\n      if (ehdr.e_machine == EM_PPC64\n\t  && (ehdr.e_flags & EF_PPC64_ABI) < 2\n\t  && shdr->sh_type == SHT_PROGBITS\n\t  && strcmp (name, \".opd\") == 0)\n\t{\n\t  if (!elf_get_view (state, descriptor, memory, memory_size,\n\t\t\t     shdr->sh_offset, shdr->sh_size, error_callback,\n\t\t\t     data, &opd_data.view))\n\t    goto fail;\n\n\t  opd = &opd_data;\n\t  opd->addr = shdr->sh_addr;\n\t  opd->data = (const char *) opd_data.view.view.data;\n\t  opd->size = shdr->sh_size;\n\t  opd_view_valid = 1;\n\t}\n    }\n\n  /* A debuginfo file may not have a useful .opd section, but we can use the\n     one from the original executable.  */\n  if (opd == NULL)\n    opd = caller_opd;\n\n  if (symtab_shndx == 0)\n    symtab_shndx = dynsym_shndx;\n  if (symtab_shndx != 0)\n    {\n      const b_elf_shdr *symtab_shdr;\n      unsigned int strtab_shndx;\n      const b_elf_shdr *strtab_shdr;\n      struct elf_syminfo_data *sdata;\n\n      symtab_shdr = &shdrs[symtab_shndx - 1];\n      strtab_shndx = symtab_shdr->sh_link;\n      if (strtab_shndx >= shnum)\n\t{\n\t  error_callback (data,\n\t\t\t  \"ELF symbol table strtab link out of range\", 0);\n\t  goto fail;\n\t}\n      strtab_shdr = &shdrs[strtab_shndx - 1];\n\n      if (!elf_get_view (state, descriptor, memory, memory_size,\n\t\t\t symtab_shdr->sh_offset, symtab_shdr->sh_size,\n\t\t\t error_callback, data, &symtab_view))\n\tgoto fail;\n      symtab_view_valid = 1;\n\n      if (!elf_get_view (state, descriptor, memory, memory_size,\n\t\t\t strtab_shdr->sh_offset, strtab_shdr->sh_size,\n\t\t\t error_callback, data, &strtab_view))\n\tgoto fail;\n      strtab_view_valid = 1;\n\n      sdata = ((struct elf_syminfo_data *)\n\t       backtrace_alloc (state, sizeof *sdata, error_callback, data));\n      if (sdata == NULL)\n\tgoto fail;\n\n      if (!elf_initialize_syminfo (state, base_address,\n\t\t\t\t   symtab_view.view.data, symtab_shdr->sh_size,\n\t\t\t\t   strtab_view.view.data, strtab_shdr->sh_size,\n\t\t\t\t   error_callback, data, sdata, opd))\n\t{\n\t  backtrace_free (state, sdata, sizeof *sdata, error_callback, data);\n\t  goto fail;\n\t}\n\n      /* We no longer need the symbol table, but we hold on to the\n\t string table permanently.  */\n      elf_release_view (state, &symtab_view, error_callback, data);\n      symtab_view_valid = 0;\n      strtab_view_valid = 0;\n\n      *found_sym = 1;\n\n      elf_add_syminfo_data (state, sdata);\n    }\n\n  elf_release_view (state, &shdrs_view, error_callback, data);\n  shdrs_view_valid = 0;\n  elf_release_view (state, &names_view, error_callback, data);\n  names_view_valid = 0;\n\n  /* If the debug info is in a separate file, read that one instead.  */\n\n  if (buildid_data != NULL)\n    {\n      int d;\n\n      d = elf_open_debugfile_by_buildid (state, buildid_data, buildid_size,\n\t\t\t\t\t error_callback, data);\n      if (d < 0 && !debuginfod_guard) {\n          char* env = getenv(DEBUGINFOD_PROGRESS_ENV_VAR);\n          if (env) {\n            fprintf(stderr, \"Trying to download debuginfo for %s\\n\", filename);\n          }\n          d = elf_open_debugfile_by_debuginfod(buildid_data, buildid_size,\n                                               error_callback, data);\n      }\n      if (d >= 0)\n\t{\n\t  int ret;\n\n\t  elf_release_view (state, &buildid_view, error_callback, data);\n\t  if (debuglink_view_valid)\n\t    elf_release_view (state, &debuglink_view, error_callback, data);\n\t  if (debugaltlink_view_valid)\n\t    elf_release_view (state, &debugaltlink_view, error_callback, data);\n\t  ret = elf_add (state, \"\", d, NULL, 0, base_address, opd,\n\t\t\t error_callback, data, fileline_fn, found_sym,\n\t\t\t found_dwarf, NULL, 0, 1, NULL, 0);\n\t  if (ret < 0)\n\t    backtrace_close (d, error_callback, data);\n\t  else if (descriptor >= 0)\n\t    backtrace_close (descriptor, error_callback, data);\n\t  return ret;\n\t}\n    }\n\n  if (buildid_view_valid)\n    {\n      elf_release_view (state, &buildid_view, error_callback, data);\n      buildid_view_valid = 0;\n    }\n\n  if (debuglink_name != NULL)\n    {\n      int d;\n\n      d = elf_open_debugfile_by_debuglink (state, filename, debuglink_name,\n\t\t\t\t\t   debuglink_crc, error_callback,\n\t\t\t\t\t   data);\n      if (d >= 0)\n\t{\n\t  int ret;\n\n\t  elf_release_view (state, &debuglink_view, error_callback, data);\n\t  if (debugaltlink_view_valid)\n\t    elf_release_view (state, &debugaltlink_view, error_callback, data);\n\t  ret = elf_add (state, \"\", d, NULL, 0, base_address, opd,\n\t\t\t error_callback, data, fileline_fn, found_sym,\n\t\t\t found_dwarf, NULL, 0, 1, NULL, 0);\n\t  if (ret < 0)\n\t    backtrace_close (d, error_callback, data);\n\t  else if (descriptor >= 0)\n\t    backtrace_close(descriptor, error_callback, data);\n\t  return ret;\n\t}\n    }\n\n  if (debuglink_view_valid)\n    {\n      elf_release_view (state, &debuglink_view, error_callback, data);\n      debuglink_view_valid = 0;\n    }\n\n  struct dwarf_data *fileline_altlink = NULL;\n  if (debugaltlink_name != NULL)\n    {\n      int d;\n\n      d = elf_open_debugfile_by_debuglink (state, filename, debugaltlink_name,\n\t\t\t\t\t   0, error_callback, data);\n      if (d >= 0)\n\t{\n\t  int ret;\n\n\t  ret = elf_add (state, filename, d, NULL, 0, base_address, opd,\n\t\t\t error_callback, data, fileline_fn, found_sym,\n\t\t\t found_dwarf, &fileline_altlink, 0, 1,\n\t\t\t debugaltlink_buildid_data, debugaltlink_buildid_size);\n\t  elf_release_view (state, &debugaltlink_view, error_callback, data);\n\t  debugaltlink_view_valid = 0;\n\t  if (ret < 0)\n\t    {\n\t      backtrace_close (d, error_callback, data);\n\t      return ret;\n\t    }\n\t}\n    }\n\n  if (debugaltlink_view_valid)\n    {\n      elf_release_view (state, &debugaltlink_view, error_callback, data);\n      debugaltlink_view_valid = 0;\n    }\n\n  if (gnu_debugdata_view_valid)\n    {\n      int ret;\n\n      ret = elf_uncompress_lzma (state,\n\t\t\t\t ((const unsigned char *)\n\t\t\t\t  gnu_debugdata_view.view.data),\n\t\t\t\t gnu_debugdata_size, error_callback, data,\n\t\t\t\t &gnu_debugdata_uncompressed,\n\t\t\t\t &gnu_debugdata_uncompressed_size);\n\n      elf_release_view (state, &gnu_debugdata_view, error_callback, data);\n      gnu_debugdata_view_valid = 0;\n\n      if (ret)\n\t{\n\t  ret = elf_add (state, filename, -1, gnu_debugdata_uncompressed,\n\t\t\t gnu_debugdata_uncompressed_size, base_address, opd,\n\t\t\t error_callback, data, fileline_fn, found_sym,\n\t\t\t found_dwarf, NULL, 0, 0, NULL, 0);\n\t  if (ret >= 0 && descriptor >= 0)\n\t    backtrace_close(descriptor, error_callback, data);\n\t  return ret;\n\t}\n    }\n\n  if (opd_view_valid)\n    {\n      elf_release_view (state, &opd->view, error_callback, data);\n      opd_view_valid = 0;\n      opd = NULL;\n    }\n\n  /* Read all the debug sections in a single view, since they are\n     probably adjacent in the file.  If any of sections are\n     uncompressed, we never release this view.  */\n\n  min_offset = 0;\n  max_offset = 0;\n  debug_size = 0;\n  for (i = 0; i < (int) DEBUG_MAX; ++i)\n    {\n      off_t end;\n\n      if (sections[i].size != 0)\n\t{\n\t  if (min_offset == 0 || sections[i].offset < min_offset)\n\t    min_offset = sections[i].offset;\n\t  end = sections[i].offset + sections[i].size;\n\t  if (end > max_offset)\n\t    max_offset = end;\n\t  debug_size += sections[i].size;\n\t}\n      if (zsections[i].size != 0)\n\t{\n\t  if (min_offset == 0 || zsections[i].offset < min_offset)\n\t    min_offset = zsections[i].offset;\n\t  end = zsections[i].offset + zsections[i].size;\n\t  if (end > max_offset)\n\t    max_offset = end;\n\t  debug_size += zsections[i].size;\n\t}\n    }\n  if (min_offset == 0 || max_offset == 0)\n    {\n      if (descriptor >= 0)\n\t{\n\t  if (!backtrace_close (descriptor, error_callback, data))\n\t    goto fail;\n\t}\n      return 1;\n    }\n\n  /* If the total debug section size is large, assume that there are\n     gaps between the sections, and read them individually.  */\n\n  if (max_offset - min_offset < 0x20000000\n      || max_offset - min_offset < debug_size + 0x10000)\n    {\n      if (!elf_get_view (state, descriptor, memory, memory_size, min_offset,\n\t\t\t max_offset - min_offset, error_callback, data,\n\t\t\t &debug_view))\n\tgoto fail;\n      debug_view_valid = 1;\n    }\n  else\n    {\n      memset (&split_debug_view[0], 0, sizeof split_debug_view);\n      for (i = 0; i < (int) DEBUG_MAX; ++i)\n\t{\n\t  struct debug_section_info *dsec;\n\n\t  if (sections[i].size != 0)\n\t    dsec = &sections[i];\n\t  else if (zsections[i].size != 0)\n\t    dsec = &zsections[i];\n\t  else\n\t    continue;\n\n\t  if (!elf_get_view (state, descriptor, memory, memory_size,\n\t\t\t     dsec->offset, dsec->size, error_callback, data,\n\t\t\t     &split_debug_view[i]))\n\t    goto fail;\n\t  split_debug_view_valid[i] = 1;\n\n\t  if (sections[i].size != 0)\n\t    sections[i].data = ((const unsigned char *)\n\t\t\t\tsplit_debug_view[i].view.data);\n\t  else\n\t    zsections[i].data = ((const unsigned char *)\n\t\t\t\t split_debug_view[i].view.data);\n\t}\n    }\n\n  /* We've read all we need from the executable.  */\n  if (descriptor >= 0)\n    {\n      if (!backtrace_close (descriptor, error_callback, data))\n\tgoto fail;\n      descriptor = -1;\n    }\n\n  using_debug_view = 0;\n  if (debug_view_valid)\n    {\n      for (i = 0; i < (int) DEBUG_MAX; ++i)\n\t{\n\t  if (sections[i].size == 0)\n\t    sections[i].data = NULL;\n\t  else\n\t    {\n\t      sections[i].data = ((const unsigned char *) debug_view.view.data\n\t\t\t\t  + (sections[i].offset - min_offset));\n\t      ++using_debug_view;\n\t    }\n\n\t  if (zsections[i].size == 0)\n\t    zsections[i].data = NULL;\n\t  else\n\t    zsections[i].data = ((const unsigned char *) debug_view.view.data\n\t\t\t\t + (zsections[i].offset - min_offset));\n\t}\n    }\n\n  /* Uncompress the old format (--compress-debug-sections=zlib-gnu).  */\n\n  zdebug_table = NULL;\n  for (i = 0; i < (int) DEBUG_MAX; ++i)\n    {\n      if (sections[i].size == 0 && zsections[i].size > 0)\n\t{\n\t  unsigned char *uncompressed_data;\n\t  size_t uncompressed_size;\n\n\t  if (zdebug_table == NULL)\n\t    {\n\t      zdebug_table = ((uint16_t *)\n\t\t\t      backtrace_alloc (state, ZLIB_TABLE_SIZE,\n\t\t\t\t\t       error_callback, data));\n\t      if (zdebug_table == NULL)\n\t\tgoto fail;\n\t    }\n\n\t  uncompressed_data = NULL;\n\t  uncompressed_size = 0;\n\t  if (!elf_uncompress_zdebug (state, zsections[i].data,\n\t\t\t\t      zsections[i].size, zdebug_table,\n\t\t\t\t      error_callback, data,\n\t\t\t\t      &uncompressed_data, &uncompressed_size))\n\t    goto fail;\n\t  sections[i].data = uncompressed_data;\n\t  sections[i].size = uncompressed_size;\n\t  sections[i].compressed = 0;\n\n\t  if (split_debug_view_valid[i])\n\t    {\n\t      elf_release_view (state, &split_debug_view[i],\n\t\t\t\terror_callback, data);\n\t      split_debug_view_valid[i] = 0;\n\t    }\n\t}\n    }\n\n  if (zdebug_table != NULL)\n    {\n      backtrace_free (state, zdebug_table, ZLIB_TABLE_SIZE,\n\t\t      error_callback, data);\n      zdebug_table = NULL;\n    }\n\n  /* Uncompress the official ELF format\n     (--compress-debug-sections=zlib-gabi, --compress-debug-sections=zstd).  */\n  for (i = 0; i < (int) DEBUG_MAX; ++i)\n    {\n      unsigned char *uncompressed_data;\n      size_t uncompressed_size;\n\n      if (sections[i].size == 0 || !sections[i].compressed)\n\tcontinue;\n\n      if (zdebug_table == NULL)\n\t{\n\t  zdebug_table = ((uint16_t *)\n\t\t\t  backtrace_alloc (state, ZDEBUG_TABLE_SIZE,\n\t\t\t\t\t   error_callback, data));\n\t  if (zdebug_table == NULL)\n\t    goto fail;\n\t}\n\n      uncompressed_data = NULL;\n      uncompressed_size = 0;\n      if (!elf_uncompress_chdr (state, sections[i].data, sections[i].size,\n\t\t\t\tzdebug_table, error_callback, data,\n\t\t\t\t&uncompressed_data, &uncompressed_size))\n\tgoto fail;\n      sections[i].data = uncompressed_data;\n      sections[i].size = uncompressed_size;\n      sections[i].compressed = 0;\n\n      if (debug_view_valid)\n\t--using_debug_view;\n      else if (split_debug_view_valid[i])\n\t{\n\t  elf_release_view (state, &split_debug_view[i], error_callback, data);\n\t  split_debug_view_valid[i] = 0;\n\t}\n    }\n\n  if (zdebug_table != NULL)\n    backtrace_free (state, zdebug_table, ZDEBUG_TABLE_SIZE,\n\t\t    error_callback, data);\n\n  if (debug_view_valid && using_debug_view == 0)\n    {\n      elf_release_view (state, &debug_view, error_callback, data);\n      debug_view_valid = 0;\n    }\n\n  for (i = 0; i < (int) DEBUG_MAX; ++i)\n    {\n      dwarf_sections.data[i] = sections[i].data;\n      dwarf_sections.size[i] = sections[i].size;\n    }\n\n  if (!backtrace_dwarf_add (state, base_address, &dwarf_sections,\n\t\t\t    ehdr.e_ident[EI_DATA] == ELFDATA2MSB,\n\t\t\t    fileline_altlink,\n\t\t\t    error_callback, data, fileline_fn,\n\t\t\t    fileline_entry))\n    goto fail;\n\n  *found_dwarf = 1;\n\n  return 1;\n\n fail:\n  if (shdrs_view_valid)\n    elf_release_view (state, &shdrs_view, error_callback, data);\n  if (names_view_valid)\n    elf_release_view (state, &names_view, error_callback, data);\n  if (symtab_view_valid)\n    elf_release_view (state, &symtab_view, error_callback, data);\n  if (strtab_view_valid)\n    elf_release_view (state, &strtab_view, error_callback, data);\n  if (debuglink_view_valid)\n    elf_release_view (state, &debuglink_view, error_callback, data);\n  if (debugaltlink_view_valid)\n    elf_release_view (state, &debugaltlink_view, error_callback, data);\n  if (gnu_debugdata_view_valid)\n    elf_release_view (state, &gnu_debugdata_view, error_callback, data);\n  if (buildid_view_valid)\n    elf_release_view (state, &buildid_view, error_callback, data);\n  if (debug_view_valid)\n    elf_release_view (state, &debug_view, error_callback, data);\n  for (i = 0; i < (int) DEBUG_MAX; ++i)\n    {\n      if (split_debug_view_valid[i])\n\telf_release_view (state, &split_debug_view[i], error_callback, data);\n    }\n  if (opd_view_valid)\n    elf_release_view (state, &opd->view, error_callback, data);\n  if (descriptor >= 0)\n    backtrace_close (descriptor, error_callback, data);\n  return 0;\n}\n\n/* Data passed to phdr_callback.  */\n\nstruct phdr_data\n{\n  struct backtrace_state *state;\n  backtrace_error_callback error_callback;\n  void *data;\n  fileline *fileline_fn;\n  int *found_sym;\n  int *found_dwarf;\n  const char *exe_filename;\n  int exe_descriptor;\n};\n\n/* Callback passed to dl_iterate_phdr.  Load debug info from shared\n   libraries.  */\n\nstatic int\n#ifdef __i386__\n__attribute__ ((__force_align_arg_pointer__))\n#endif\nphdr_callback (struct dl_phdr_info *info, size_t size ATTRIBUTE_UNUSED,\n\t       void *pdata)\n{\n  struct phdr_data *pd = (struct phdr_data *) pdata;\n  const char *filename;\n  int descriptor;\n  int does_not_exist;\n  struct libbacktrace_base_address base_address;\n  fileline elf_fileline_fn;\n  int found_dwarf;\n\n  /* There is not much we can do if we don't have the module name,\n     unless executable is ET_DYN, where we expect the very first\n     phdr_callback to be for the PIE.  */\n  if (info->dlpi_name == NULL || info->dlpi_name[0] == '\\0')\n    {\n      if (pd->exe_descriptor == -1)\n\treturn 0;\n      filename = pd->exe_filename;\n      descriptor = pd->exe_descriptor;\n      pd->exe_descriptor = -1;\n    }\n  else\n    {\n      if (pd->exe_descriptor != -1)\n\t{\n\t  backtrace_close (pd->exe_descriptor, pd->error_callback, pd->data);\n\t  pd->exe_descriptor = -1;\n\t}\n\n      filename = info->dlpi_name;\n      descriptor = backtrace_open (info->dlpi_name, pd->error_callback,\n\t\t\t\t   pd->data, &does_not_exist);\n      if (descriptor < 0)\n\treturn 0;\n    }\n\n  base_address.m = info->dlpi_addr;\n  if (elf_add (pd->state, filename, descriptor, NULL, 0, base_address, NULL,\n\t       pd->error_callback, pd->data, &elf_fileline_fn, pd->found_sym,\n\t       &found_dwarf, NULL, 0, 0, NULL, 0))\n    {\n      if (found_dwarf)\n\t{\n\t  *pd->found_dwarf = 1;\n\t  *pd->fileline_fn = elf_fileline_fn;\n\t}\n    }\n\n  return 0;\n}\n\n/* Initialize the backtrace data we need from an ELF executable.  At\n   the ELF level, all we need to do is find the debug info\n   sections.  */\n\nint\nbacktrace_initialize (struct backtrace_state *state, const char *filename,\n\t\t      int descriptor, backtrace_error_callback error_callback,\n\t\t      void *data, fileline *fileline_fn)\n{\n  int ret;\n  int found_sym;\n  int found_dwarf;\n  fileline elf_fileline_fn = elf_nodebug;\n  struct phdr_data pd;\n\n  /* When using fdpic we must use dl_iterate_phdr for all modules, including\n     the main executable, so that we can get the right base address\n     mapping.  */\n  if (!libbacktrace_using_fdpic ())\n    {\n      struct libbacktrace_base_address zero_base_address;\n\n      memset (&zero_base_address, 0, sizeof zero_base_address);\n      ret = elf_add (state, filename, descriptor, NULL, 0, zero_base_address,\n\t\t     NULL, error_callback, data, &elf_fileline_fn, &found_sym,\n\t\t     &found_dwarf, NULL, 1, 0, NULL, 0);\n      if (!ret)\n\treturn 0;\n    }\n\n  pd.state = state;\n  pd.error_callback = error_callback;\n  pd.data = data;\n  pd.fileline_fn = &elf_fileline_fn;\n  pd.found_sym = &found_sym;\n  pd.found_dwarf = &found_dwarf;\n  pd.exe_filename = filename;\n  pd.exe_descriptor = ret < 0 ? descriptor : -1;\n\n  /* Here, There Be Dragons: we are about to call dl_iterate_phdr,\n     which is a glibc-internal function that holds a libc internal\n     lock. As this function needs to iterate over all the loaded\n     modules, this lock is shared by dlopen so no new modules can be\n     loaded while is iterating. This is a problem for us, as the\n     debuginfod client will use libcurl to spawn threads to download\n     debuginfo files, and libcurl uses dlopen to load a bunch of stuff\n     for its backend in some versions. This can cause a deadlock because\n     the debuginfod client will wait until the libcurl threads finish but\n     they will never finish because they are waiting for the dlopen lock\n     to be released, which will not happen until the call to dl_iterate_phdr\n     finishes.\n\n     To avoid this, we use a global variable to detect if we are already\n     iterating over the modules, and if so, we skip the query to debuginfod\n     and just try with the other default methods.\n\n     Note this ONLY affects the symbol resolution when retrieving a backtrace,\n     and it doesn't affect offline symbolication.  */\n  debuginfod_guard++;\n  dl_iterate_phdr (phdr_callback, (void *) &pd);\n  debuginfod_guard--;\n\n  if (!state->threaded)\n    {\n      if (found_sym)\n\tstate->syminfo_fn = elf_syminfo;\n      else if (state->syminfo_fn == NULL)\n\tstate->syminfo_fn = elf_nosyms;\n    }\n  else\n    {\n      if (found_sym)\n\tbacktrace_atomic_store_pointer (&state->syminfo_fn, elf_syminfo);\n      else\n\t(void) __sync_bool_compare_and_swap (&state->syminfo_fn, NULL,\n\t\t\t\t\t     elf_nosyms);\n    }\n\n  if (!state->threaded)\n    *fileline_fn = state->fileline_fn;\n  else\n    *fileline_fn = backtrace_atomic_load_pointer (&state->fileline_fn);\n\n  if (*fileline_fn == NULL || *fileline_fn == elf_nodebug)\n    *fileline_fn = elf_fileline_fn;\n\n  return 1;\n}\n"
  },
  {
    "path": "src/vendor/libbacktrace/fileline.c",
    "content": "/* fileline.c -- Get file and line number information in a backtrace.\n   Copyright (C) 2012-2024 Free Software Foundation, Inc.\n   Written by Ian Lance Taylor, Google.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n    (1) Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n\n    (2) Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in\n    the documentation and/or other materials provided with the\n    distribution.\n\n    (3) The name of the author may not be used to\n    endorse or promote products derived from this software without\n    specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\nIMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,\nINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\nHOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\nIN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGE.  */\n\n#include \"config.h\"\n\n#include <sys/types.h>\n#include <sys/stat.h>\n#include <errno.h>\n#include <fcntl.h>\n#include <stdlib.h>\n#include <unistd.h>\n\n#if defined (HAVE_KERN_PROC_ARGS) || defined (HAVE_KERN_PROC)\n#include <sys/sysctl.h>\n#endif\n\n#ifdef HAVE_MACH_O_DYLD_H\n#include <mach-o/dyld.h>\n#endif\n\n#ifdef HAVE_WINDOWS_H\n#ifndef WIN32_MEAN_AND_LEAN\n#define WIN32_MEAN_AND_LEAN\n#endif\n\n#ifndef NOMINMAX\n#define NOMINMAX\n#endif\n\n#include <windows.h>\n#endif\n\n#include \"backtrace.h\"\n#include \"internal.h\"\n\n#ifndef HAVE_GETEXECNAME\n#define getexecname() NULL\n#endif\n\n#if !defined (HAVE_KERN_PROC_ARGS) && !defined (HAVE_KERN_PROC)\n\n#define sysctl_exec_name1(state, error_callback, data) NULL\n#define sysctl_exec_name2(state, error_callback, data) NULL\n\n#else /* defined (HAVE_KERN_PROC_ARGS) || |defined (HAVE_KERN_PROC) */\n\nstatic char *\nsysctl_exec_name (struct backtrace_state *state,\n\t\t  int mib0, int mib1, int mib2, int mib3,\n\t\t  backtrace_error_callback error_callback, void *data)\n{\n  int mib[4];\n  size_t len;\n  char *name;\n  size_t rlen;\n\n  mib[0] = mib0;\n  mib[1] = mib1;\n  mib[2] = mib2;\n  mib[3] = mib3;\n\n  if (sysctl (mib, 4, NULL, &len, NULL, 0) < 0)\n    return NULL;\n  name = (char *) backtrace_alloc (state, len, error_callback, data);\n  if (name == NULL)\n    return NULL;\n  rlen = len;\n  if (sysctl (mib, 4, name, &rlen, NULL, 0) < 0)\n    {\n      backtrace_free (state, name, len, error_callback, data);\n      return NULL;\n    }\n  return name;\n}\n\n#ifdef HAVE_KERN_PROC_ARGS\n\nstatic char *\nsysctl_exec_name1 (struct backtrace_state *state,\n\t\t   backtrace_error_callback error_callback, void *data)\n{\n  /* This variant is used on NetBSD.  */\n  return sysctl_exec_name (state, CTL_KERN, KERN_PROC_ARGS, -1,\n\t\t\t   KERN_PROC_PATHNAME, error_callback, data);\n}\n\n#else\n\n#define sysctl_exec_name1(state, error_callback, data) NULL\n\n#endif\n\n#ifdef HAVE_KERN_PROC\n\nstatic char *\nsysctl_exec_name2 (struct backtrace_state *state,\n\t\t   backtrace_error_callback error_callback, void *data)\n{\n  /* This variant is used on FreeBSD.  */\n  return sysctl_exec_name (state, CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1,\n\t\t\t   error_callback, data);\n}\n\n#else\n\n#define sysctl_exec_name2(state, error_callback, data) NULL\n\n#endif\n\n#endif /* defined (HAVE_KERN_PROC_ARGS) || |defined (HAVE_KERN_PROC) */\n\n#ifdef HAVE_MACH_O_DYLD_H\n\nstatic char *\nmacho_get_executable_path (struct backtrace_state *state,\n\t\t\t   backtrace_error_callback error_callback, void *data)\n{\n  uint32_t len;\n  char *name;\n\n  len = 0;\n  if (_NSGetExecutablePath (NULL, &len) == 0)\n    return NULL;\n  name = (char *) backtrace_alloc (state, len, error_callback, data);\n  if (name == NULL)\n    return NULL;\n  if (_NSGetExecutablePath (name, &len) != 0)\n    {\n      backtrace_free (state, name, len, error_callback, data);\n      return NULL;\n    }\n  return name;\n}\n\n#else /* !defined (HAVE_MACH_O_DYLD_H) */\n\n#define macho_get_executable_path(state, error_callback, data) NULL\n\n#endif /* !defined (HAVE_MACH_O_DYLD_H) */\n\n#if HAVE_DECL__PGMPTR\n\n#define windows_executable_filename() _pgmptr\n\n#else /* !HAVE_DECL__PGMPTR */\n\n#define windows_executable_filename() NULL\n\n#endif /* !HAVE_DECL__PGMPTR */\n\n#ifdef HAVE_WINDOWS_H\n\n#define FILENAME_BUF_SIZE (MAX_PATH)\n\nstatic char *\nwindows_get_executable_path (char *buf, backtrace_error_callback error_callback,\n\t\t\t     void *data)\n{\n  size_t got;\n  int error;\n\n  got = GetModuleFileNameA (NULL, buf, FILENAME_BUF_SIZE - 1);\n  error = GetLastError ();\n  if (got == 0\n      || (got == FILENAME_BUF_SIZE - 1 && error == ERROR_INSUFFICIENT_BUFFER))\n    {\n      error_callback (data,\n\t\t      \"could not get the filename of the current executable\",\n\t\t      error);\n      return NULL;\n    }\n  return buf;\n}\n\n#else /* !defined (HAVE_WINDOWS_H) */\n\n#define windows_get_executable_path(buf, error_callback, data) NULL\n#define FILENAME_BUF_SIZE 64\n\n#endif /* !defined (HAVE_WINDOWS_H) */\n\n/* Initialize the fileline information from the executable.  Returns 1\n   on success, 0 on failure.  */\n\nstatic int\nfileline_initialize (struct backtrace_state *state,\n\t\t     backtrace_error_callback error_callback, void *data)\n{\n  int failed;\n  fileline fileline_fn;\n  int pass;\n  int called_error_callback;\n  int descriptor;\n  const char *filename;\n  char buf[FILENAME_BUF_SIZE];\n\n  if (!state->threaded)\n    failed = state->fileline_initialization_failed;\n  else\n    failed = backtrace_atomic_load_int (&state->fileline_initialization_failed);\n\n  if (failed)\n    {\n      error_callback (data, \"failed to read executable information\", -1);\n      return 0;\n    }\n\n  if (!state->threaded)\n    fileline_fn = state->fileline_fn;\n  else\n    fileline_fn = backtrace_atomic_load_pointer (&state->fileline_fn);\n  if (fileline_fn != NULL)\n    return 1;\n\n  /* We have not initialized the information.  Do it now.  */\n\n  descriptor = -1;\n  called_error_callback = 0;\n  for (pass = 0; pass < 10; ++pass)\n    {\n      int does_not_exist;\n\n      switch (pass)\n\t{\n\tcase 0:\n\t  filename = state->filename;\n\t  break;\n\tcase 1:\n\t  filename = getexecname ();\n\t  break;\n\tcase 2:\n\t  /* Test this before /proc/self/exe, as the latter exists but points\n\t     to the wine binary (and thus doesn't work).  */\n\t  filename = windows_executable_filename ();\n\t  break;\n\tcase 3:\n\t  filename = \"/proc/self/exe\";\n\t  break;\n\tcase 4:\n\t  filename = \"/proc/curproc/file\";\n\t  break;\n\tcase 5:\n\t  snprintf (buf, sizeof (buf), \"/proc/%ld/object/a.out\",\n\t\t    (long) getpid ());\n\t  filename = buf;\n\t  break;\n\tcase 6:\n\t  filename = sysctl_exec_name1 (state, error_callback, data);\n\t  break;\n\tcase 7:\n\t  filename = sysctl_exec_name2 (state, error_callback, data);\n\t  break;\n\tcase 8:\n\t  filename = macho_get_executable_path (state, error_callback, data);\n\t  break;\n\tcase 9:\n\t  filename = windows_get_executable_path (buf, error_callback, data);\n\t  break;\n\tdefault:\n\t  abort ();\n\t}\n\n      if (filename == NULL)\n\tcontinue;\n\n      descriptor = backtrace_open (filename, error_callback, data,\n\t\t\t\t   &does_not_exist);\n      if (descriptor < 0 && !does_not_exist)\n\t{\n\t  called_error_callback = 1;\n\t  break;\n\t}\n      if (descriptor >= 0)\n\tbreak;\n    }\n\n  if (descriptor < 0)\n    {\n      if (!called_error_callback)\n\t{\n\t  if (state->filename != NULL)\n\t    error_callback (data, state->filename, ENOENT);\n\t  else\n\t    error_callback (data,\n\t\t\t    \"libbacktrace could not find executable to open\",\n\t\t\t    0);\n\t}\n      failed = 1;\n    }\n\n  if (!failed)\n    {\n      if (!backtrace_initialize (state, filename, descriptor, error_callback,\n\t\t\t\t data, &fileline_fn))\n\tfailed = 1;\n    }\n\n  if (failed)\n    {\n      if (!state->threaded)\n\tstate->fileline_initialization_failed = 1;\n      else\n\tbacktrace_atomic_store_int (&state->fileline_initialization_failed, 1);\n      return 0;\n    }\n\n  if (!state->threaded)\n    state->fileline_fn = fileline_fn;\n  else\n    {\n      backtrace_atomic_store_pointer (&state->fileline_fn, fileline_fn);\n\n      /* Note that if two threads initialize at once, one of the data\n\t sets may be leaked.  */\n    }\n\n  return 1;\n}\n\n/* Given a PC, find the file name, line number, and function name.  */\n\nint\nbacktrace_pcinfo (struct backtrace_state *state, uintptr_t pc,\n\t\t  backtrace_full_callback callback,\n\t\t  backtrace_error_callback error_callback, void *data)\n{\n  if (!fileline_initialize (state, error_callback, data))\n    return 0;\n\n  if (state->fileline_initialization_failed)\n    return 0;\n\n  return state->fileline_fn (state, pc, callback, error_callback, data);\n}\n\n/* Given a PC, find the symbol for it, and its value.  */\n\nint\nbacktrace_syminfo (struct backtrace_state *state, uintptr_t pc,\n\t\t   backtrace_syminfo_callback callback,\n\t\t   backtrace_error_callback error_callback, void *data)\n{\n  if (!fileline_initialize (state, error_callback, data))\n    return 0;\n\n  if (state->fileline_initialization_failed)\n    return 0;\n\n  state->syminfo_fn (state, pc, callback, error_callback, data);\n  return 1;\n}\n\n/* A backtrace_syminfo_callback that can call into a\n   backtrace_full_callback, used when we have a symbol table but no\n   debug info.  */\n\nvoid\nbacktrace_syminfo_to_full_callback (void *data, uintptr_t pc,\n\t\t\t\t    const char *symname,\n\t\t\t\t    uintptr_t symval ATTRIBUTE_UNUSED,\n\t\t\t\t    uintptr_t symsize ATTRIBUTE_UNUSED)\n{\n  struct backtrace_call_full *bdata = (struct backtrace_call_full *) data;\n\n  bdata->ret = bdata->full_callback (bdata->full_data, pc, NULL, 0, symname);\n}\n\n/* An error callback that corresponds to\n   backtrace_syminfo_to_full_callback.  */\n\nvoid\nbacktrace_syminfo_to_full_error_callback (void *data, const char *msg,\n\t\t\t\t\t  int errnum)\n{\n  struct backtrace_call_full *bdata = (struct backtrace_call_full *) data;\n\n  bdata->full_error_callback (bdata->full_data, msg, errnum);\n}\n"
  },
  {
    "path": "src/vendor/libbacktrace/filenames.h",
    "content": "/* btest.c -- Filename header for libbacktrace library\n   Copyright (C) 2012-2018 Free Software Foundation, Inc.\n   Written by Ian Lance Taylor, Google.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n    (1) Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n\n    (2) Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in\n    the documentation and/or other materials provided with the\n    distribution.\n\n    (3) The name of the author may not be used to\n    endorse or promote products derived from this software without\n    specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\nIMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,\nINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\nHOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\nIN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGE.  */\n\n#ifndef GCC_VERSION\n# define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__)\n#endif\n\n#if (GCC_VERSION < 2007)\n# define __attribute__(x)\n#endif\n\n#ifndef ATTRIBUTE_UNUSED\n# define ATTRIBUTE_UNUSED __attribute__ ((__unused__))\n#endif\n\n#if defined(__MSDOS__) || defined(_WIN32) || defined(__OS2__) || defined (__CYGWIN__)\n# define IS_DIR_SEPARATOR(c) ((c) == '/' || (c) == '\\\\')\n# define HAS_DRIVE_SPEC(f) ((f)[0] != '\\0' && (f)[1] == ':')\n# define IS_ABSOLUTE_PATH(f) (IS_DIR_SEPARATOR((f)[0]) || HAS_DRIVE_SPEC(f))\n#else\n# define IS_DIR_SEPARATOR(c) ((c) == '/')\n# define IS_ABSOLUTE_PATH(f) (IS_DIR_SEPARATOR((f)[0]))\n#endif\n"
  },
  {
    "path": "src/vendor/libbacktrace/filetype.awk",
    "content": "# An awk script to determine the type of a file.\n/^\\177ELF\\001/      { if (NR == 1) { print \"elf32\"; exit } }\n/^\\177ELF\\002/      { if (NR == 1) { print \"elf64\"; exit } }\n/^\\114\\001/         { if (NR == 1) { print \"pecoff\"; exit } }\n/^\\144\\206/         { if (NR == 1) { print \"pecoff\"; exit } }\n/^\\001\\337/         { if (NR == 1) { print \"xcoff32\"; exit } }\n/^\\001\\367/         { if (NR == 1) { print \"xcoff64\"; exit } }\n/^\\376\\355\\372\\316/ { if (NR == 1) { print \"macho\"; exit } }\n/^\\316\\372\\355\\376/ { if (NR == 1) { print \"macho\"; exit } }\n/^\\376\\355\\372\\317/ { if (NR == 1) { print \"macho\"; exit } }\n/^\\317\\372\\355\\376/ { if (NR == 1) { print \"macho\"; exit } }\n/^\\312\\376\\272\\276/ { if (NR == 1) { print \"macho\"; exit } }\n/^\\276\\272\\376\\312/ { if (NR == 1) { print \"macho\"; exit } }\n"
  },
  {
    "path": "src/vendor/libbacktrace/install-debuginfo-for-buildid.sh.in",
    "content": "#!/bin/sh\n\n# install-debug-info-for-buildid.sh -- Helper script for libbacktrace library\n# testing.\n# Copyright (C) 2019-2024 Free Software Foundation, Inc.\n\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions are\n# met:\n\n#     (1) Redistributions of source code must retain the above copyright\n#     notice, this list of conditions and the following disclaimer.\n\n#     (2) Redistributions in binary form must reproduce the above copyright\n#     notice, this list of conditions and the following disclaimer in\n#     the documentation and/or other materials provided with the\n#     distribution.\n\n#     (3) The name of the author may not be used to\n#     endorse or promote products derived from this software without\n#     specific prior written permission.\n\n# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n# DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,\n# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\n# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n# POSSIBILITY OF SUCH DAMAGE.\n\n# Extract build-id from src, and copy debug info of src to\n# $build_id_dir/aa/bb...zz.debug.\n\nset -e\n\nsed=@SED@\nawk=@AWK@\ngrep=@GREP@\nobjcopy=@OBJCOPY@\nreadelf=@READELF@\nmkdir_p=\"@MKDIR_P@\"\n\nbuild_id_dir=\"$1\"\nsrc=\"$2\"\n\nbuildid=$(LANG=C $readelf -n $src \\\n\t      | $grep \"Build ID\" \\\n\t      | $awk '{print $3}')\n\nprefix=$(echo $buildid \\\n\t     | $sed 's/^\\(.\\{2\\}\\).*/\\1/')\n\nremainder=$(echo $buildid \\\n\t\t| $sed 's/^.\\{2\\}//')\n\ndir=$build_id_dir/$prefix\ndst=$dir/$remainder.debug\n\n$mkdir_p $dir\n\n$objcopy --only-keep-debug $src $dst\n"
  },
  {
    "path": "src/vendor/libbacktrace/install-sh",
    "content": "#!/bin/sh\n# install - install a program, script, or datafile\n\nscriptversion=2013-12-25.23; # UTC\n\n# This originates from X11R5 (mit/util/scripts/install.sh), which was\n# later released in X11R6 (xc/config/util/install.sh) with the\n# following copyright and license.\n#\n# Copyright (C) 1994 X Consortium\n#\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documentation files (the \"Software\"), to\n# deal in the Software without restriction, including without limitation the\n# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n# sell copies of the Software, and to permit persons to whom the Software is\n# furnished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE\n# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN\n# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-\n# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n#\n# Except as contained in this notice, the name of the X Consortium shall not\n# be used in advertising or otherwise to promote the sale, use or other deal-\n# ings in this Software without prior written authorization from the X Consor-\n# tium.\n#\n#\n# FSF changes to this file are in the public domain.\n#\n# Calling this script install-sh is preferred over install.sh, to prevent\n# 'make' implicit rules from creating a file called install from it\n# when there is no Makefile.\n#\n# This script is compatible with the BSD install script, but was written\n# from scratch.\n\ntab='\t'\nnl='\n'\nIFS=\" $tab$nl\"\n\n# Set DOITPROG to \"echo\" to test this script.\n\ndoit=${DOITPROG-}\ndoit_exec=${doit:-exec}\n\n# Put in absolute file names if you don't have them in your path;\n# or use environment vars.\n\nchgrpprog=${CHGRPPROG-chgrp}\nchmodprog=${CHMODPROG-chmod}\nchownprog=${CHOWNPROG-chown}\ncmpprog=${CMPPROG-cmp}\ncpprog=${CPPROG-cp}\nmkdirprog=${MKDIRPROG-mkdir}\nmvprog=${MVPROG-mv}\nrmprog=${RMPROG-rm}\nstripprog=${STRIPPROG-strip}\n\nposix_mkdir=\n\n# Desired mode of installed file.\nmode=0755\n\nchgrpcmd=\nchmodcmd=$chmodprog\nchowncmd=\nmvcmd=$mvprog\nrmcmd=\"$rmprog -f\"\nstripcmd=\n\nsrc=\ndst=\ndir_arg=\ndst_arg=\n\ncopy_on_change=false\nis_target_a_directory=possibly\n\nusage=\"\\\nUsage: $0 [OPTION]... [-T] SRCFILE DSTFILE\n   or: $0 [OPTION]... SRCFILES... DIRECTORY\n   or: $0 [OPTION]... -t DIRECTORY SRCFILES...\n   or: $0 [OPTION]... -d DIRECTORIES...\n\nIn the 1st form, copy SRCFILE to DSTFILE.\nIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY.\nIn the 4th, create DIRECTORIES.\n\nOptions:\n     --help     display this help and exit.\n     --version  display version info and exit.\n\n  -c            (ignored)\n  -C            install only if different (preserve the last data modification time)\n  -d            create directories instead of installing files.\n  -g GROUP      $chgrpprog installed files to GROUP.\n  -m MODE       $chmodprog installed files to MODE.\n  -o USER       $chownprog installed files to USER.\n  -s            $stripprog installed files.\n  -t DIRECTORY  install into DIRECTORY.\n  -T            report an error if DSTFILE is a directory.\n\nEnvironment variables override the default commands:\n  CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG\n  RMPROG STRIPPROG\n\"\n\nwhile test $# -ne 0; do\n  case $1 in\n    -c) ;;\n\n    -C) copy_on_change=true;;\n\n    -d) dir_arg=true;;\n\n    -g) chgrpcmd=\"$chgrpprog $2\"\n        shift;;\n\n    --help) echo \"$usage\"; exit $?;;\n\n    -m) mode=$2\n        case $mode in\n          *' '* | *\"$tab\"* | *\"$nl\"* | *'*'* | *'?'* | *'['*)\n            echo \"$0: invalid mode: $mode\" >&2\n            exit 1;;\n        esac\n        shift;;\n\n    -o) chowncmd=\"$chownprog $2\"\n        shift;;\n\n    -s) stripcmd=$stripprog;;\n\n    -t)\n        is_target_a_directory=always\n        dst_arg=$2\n        # Protect names problematic for 'test' and other utilities.\n        case $dst_arg in\n          -* | [=\\(\\)!]) dst_arg=./$dst_arg;;\n        esac\n        shift;;\n\n    -T) is_target_a_directory=never;;\n\n    --version) echo \"$0 $scriptversion\"; exit $?;;\n\n    --) shift\n        break;;\n\n    -*) echo \"$0: invalid option: $1\" >&2\n        exit 1;;\n\n    *)  break;;\n  esac\n  shift\ndone\n\n# We allow the use of options -d and -T together, by making -d\n# take the precedence; this is for compatibility with GNU install.\n\nif test -n \"$dir_arg\"; then\n  if test -n \"$dst_arg\"; then\n    echo \"$0: target directory not allowed when installing a directory.\" >&2\n    exit 1\n  fi\nfi\n\nif test $# -ne 0 && test -z \"$dir_arg$dst_arg\"; then\n  # When -d is used, all remaining arguments are directories to create.\n  # When -t is used, the destination is already specified.\n  # Otherwise, the last argument is the destination.  Remove it from $@.\n  for arg\n  do\n    if test -n \"$dst_arg\"; then\n      # $@ is not empty: it contains at least $arg.\n      set fnord \"$@\" \"$dst_arg\"\n      shift # fnord\n    fi\n    shift # arg\n    dst_arg=$arg\n    # Protect names problematic for 'test' and other utilities.\n    case $dst_arg in\n      -* | [=\\(\\)!]) dst_arg=./$dst_arg;;\n    esac\n  done\nfi\n\nif test $# -eq 0; then\n  if test -z \"$dir_arg\"; then\n    echo \"$0: no input file specified.\" >&2\n    exit 1\n  fi\n  # It's OK to call 'install-sh -d' without argument.\n  # This can happen when creating conditional directories.\n  exit 0\nfi\n\nif test -z \"$dir_arg\"; then\n  if test $# -gt 1 || test \"$is_target_a_directory\" = always; then\n    if test ! -d \"$dst_arg\"; then\n      echo \"$0: $dst_arg: Is not a directory.\" >&2\n      exit 1\n    fi\n  fi\nfi\n\nif test -z \"$dir_arg\"; then\n  do_exit='(exit $ret); exit $ret'\n  trap \"ret=129; $do_exit\" 1\n  trap \"ret=130; $do_exit\" 2\n  trap \"ret=141; $do_exit\" 13\n  trap \"ret=143; $do_exit\" 15\n\n  # Set umask so as not to create temps with too-generous modes.\n  # However, 'strip' requires both read and write access to temps.\n  case $mode in\n    # Optimize common cases.\n    *644) cp_umask=133;;\n    *755) cp_umask=22;;\n\n    *[0-7])\n      if test -z \"$stripcmd\"; then\n        u_plus_rw=\n      else\n        u_plus_rw='% 200'\n      fi\n      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;\n    *)\n      if test -z \"$stripcmd\"; then\n        u_plus_rw=\n      else\n        u_plus_rw=,u+rw\n      fi\n      cp_umask=$mode$u_plus_rw;;\n  esac\nfi\n\nfor src\ndo\n  # Protect names problematic for 'test' and other utilities.\n  case $src in\n    -* | [=\\(\\)!]) src=./$src;;\n  esac\n\n  if test -n \"$dir_arg\"; then\n    dst=$src\n    dstdir=$dst\n    test -d \"$dstdir\"\n    dstdir_status=$?\n  else\n\n    # Waiting for this to be detected by the \"$cpprog $src $dsttmp\" command\n    # might cause directories to be created, which would be especially bad\n    # if $src (and thus $dsttmp) contains '*'.\n    if test ! -f \"$src\" && test ! -d \"$src\"; then\n      echo \"$0: $src does not exist.\" >&2\n      exit 1\n    fi\n\n    if test -z \"$dst_arg\"; then\n      echo \"$0: no destination specified.\" >&2\n      exit 1\n    fi\n    dst=$dst_arg\n\n    # If destination is a directory, append the input filename; won't work\n    # if double slashes aren't ignored.\n    if test -d \"$dst\"; then\n      if test \"$is_target_a_directory\" = never; then\n        echo \"$0: $dst_arg: Is a directory\" >&2\n        exit 1\n      fi\n      dstdir=$dst\n      dst=$dstdir/`basename \"$src\"`\n      dstdir_status=0\n    else\n      dstdir=`dirname \"$dst\"`\n      test -d \"$dstdir\"\n      dstdir_status=$?\n    fi\n  fi\n\n  obsolete_mkdir_used=false\n\n  if test $dstdir_status != 0; then\n    case $posix_mkdir in\n      '')\n        # Create intermediate dirs using mode 755 as modified by the umask.\n        # This is like FreeBSD 'install' as of 1997-10-28.\n        umask=`umask`\n        case $stripcmd.$umask in\n          # Optimize common cases.\n          *[2367][2367]) mkdir_umask=$umask;;\n          .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;\n\n          *[0-7])\n            mkdir_umask=`expr $umask + 22 \\\n              - $umask % 100 % 40 + $umask % 20 \\\n              - $umask % 10 % 4 + $umask % 2\n            `;;\n          *) mkdir_umask=$umask,go-w;;\n        esac\n\n        # With -d, create the new directory with the user-specified mode.\n        # Otherwise, rely on $mkdir_umask.\n        if test -n \"$dir_arg\"; then\n          mkdir_mode=-m$mode\n        else\n          mkdir_mode=\n        fi\n\n        posix_mkdir=false\n        case $umask in\n          *[123567][0-7][0-7])\n            # POSIX mkdir -p sets u+wx bits regardless of umask, which\n            # is incompatible with FreeBSD 'install' when (umask & 300) != 0.\n            ;;\n          *)\n            tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$\n            trap 'ret=$?; rmdir \"$tmpdir/d\" \"$tmpdir\" 2>/dev/null; exit $ret' 0\n\n            if (umask $mkdir_umask &&\n                exec $mkdirprog $mkdir_mode -p -- \"$tmpdir/d\") >/dev/null 2>&1\n            then\n              if test -z \"$dir_arg\" || {\n                   # Check for POSIX incompatibilities with -m.\n                   # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or\n                   # other-writable bit of parent directory when it shouldn't.\n                   # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.\n                   ls_ld_tmpdir=`ls -ld \"$tmpdir\"`\n                   case $ls_ld_tmpdir in\n                     d????-?r-*) different_mode=700;;\n                     d????-?--*) different_mode=755;;\n                     *) false;;\n                   esac &&\n                   $mkdirprog -m$different_mode -p -- \"$tmpdir\" && {\n                     ls_ld_tmpdir_1=`ls -ld \"$tmpdir\"`\n                     test \"$ls_ld_tmpdir\" = \"$ls_ld_tmpdir_1\"\n                   }\n                 }\n              then posix_mkdir=:\n              fi\n              rmdir \"$tmpdir/d\" \"$tmpdir\"\n            else\n              # Remove any dirs left behind by ancient mkdir implementations.\n              rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null\n            fi\n            trap '' 0;;\n        esac;;\n    esac\n\n    if\n      $posix_mkdir && (\n        umask $mkdir_umask &&\n        $doit_exec $mkdirprog $mkdir_mode -p -- \"$dstdir\"\n      )\n    then :\n    else\n\n      # The umask is ridiculous, or mkdir does not conform to POSIX,\n      # or it failed possibly due to a race condition.  Create the\n      # directory the slow way, step by step, checking for races as we go.\n\n      case $dstdir in\n        /*) prefix='/';;\n        [-=\\(\\)!]*) prefix='./';;\n        *)  prefix='';;\n      esac\n\n      oIFS=$IFS\n      IFS=/\n      set -f\n      set fnord $dstdir\n      shift\n      set +f\n      IFS=$oIFS\n\n      prefixes=\n\n      for d\n      do\n        test X\"$d\" = X && continue\n\n        prefix=$prefix$d\n        if test -d \"$prefix\"; then\n          prefixes=\n        else\n          if $posix_mkdir; then\n            (umask=$mkdir_umask &&\n             $doit_exec $mkdirprog $mkdir_mode -p -- \"$dstdir\") && break\n            # Don't fail if two instances are running concurrently.\n            test -d \"$prefix\" || exit 1\n          else\n            case $prefix in\n              *\\'*) qprefix=`echo \"$prefix\" | sed \"s/'/'\\\\\\\\\\\\\\\\''/g\"`;;\n              *) qprefix=$prefix;;\n            esac\n            prefixes=\"$prefixes '$qprefix'\"\n          fi\n        fi\n        prefix=$prefix/\n      done\n\n      if test -n \"$prefixes\"; then\n        # Don't fail if two instances are running concurrently.\n        (umask $mkdir_umask &&\n         eval \"\\$doit_exec \\$mkdirprog $prefixes\") ||\n          test -d \"$dstdir\" || exit 1\n        obsolete_mkdir_used=true\n      fi\n    fi\n  fi\n\n  if test -n \"$dir_arg\"; then\n    { test -z \"$chowncmd\" || $doit $chowncmd \"$dst\"; } &&\n    { test -z \"$chgrpcmd\" || $doit $chgrpcmd \"$dst\"; } &&\n    { test \"$obsolete_mkdir_used$chowncmd$chgrpcmd\" = false ||\n      test -z \"$chmodcmd\" || $doit $chmodcmd $mode \"$dst\"; } || exit 1\n  else\n\n    # Make a couple of temp file names in the proper directory.\n    dsttmp=$dstdir/_inst.$$_\n    rmtmp=$dstdir/_rm.$$_\n\n    # Trap to clean up those temp files at exit.\n    trap 'ret=$?; rm -f \"$dsttmp\" \"$rmtmp\" && exit $ret' 0\n\n    # Copy the file name to the temp name.\n    (umask $cp_umask && $doit_exec $cpprog \"$src\" \"$dsttmp\") &&\n\n    # and set any options; do chmod last to preserve setuid bits.\n    #\n    # If any of these fail, we abort the whole thing.  If we want to\n    # ignore errors from any of these, just make sure not to ignore\n    # errors from the above \"$doit $cpprog $src $dsttmp\" command.\n    #\n    { test -z \"$chowncmd\" || $doit $chowncmd \"$dsttmp\"; } &&\n    { test -z \"$chgrpcmd\" || $doit $chgrpcmd \"$dsttmp\"; } &&\n    { test -z \"$stripcmd\" || $doit $stripcmd \"$dsttmp\"; } &&\n    { test -z \"$chmodcmd\" || $doit $chmodcmd $mode \"$dsttmp\"; } &&\n\n    # If -C, don't bother to copy if it wouldn't change the file.\n    if $copy_on_change &&\n       old=`LC_ALL=C ls -dlL \"$dst\"     2>/dev/null` &&\n       new=`LC_ALL=C ls -dlL \"$dsttmp\"  2>/dev/null` &&\n       set -f &&\n       set X $old && old=:$2:$4:$5:$6 &&\n       set X $new && new=:$2:$4:$5:$6 &&\n       set +f &&\n       test \"$old\" = \"$new\" &&\n       $cmpprog \"$dst\" \"$dsttmp\" >/dev/null 2>&1\n    then\n      rm -f \"$dsttmp\"\n    else\n      # Rename the file to the real destination.\n      $doit $mvcmd -f \"$dsttmp\" \"$dst\" 2>/dev/null ||\n\n      # The rename failed, perhaps because mv can't rename something else\n      # to itself, or perhaps because mv is so ancient that it does not\n      # support -f.\n      {\n        # Now remove or move aside any old file at destination location.\n        # We try this two ways since rm can't unlink itself on some\n        # systems and the destination file might be busy for other\n        # reasons.  In this case, the final cleanup might fail but the new\n        # file should still install successfully.\n        {\n          test ! -f \"$dst\" ||\n          $doit $rmcmd -f \"$dst\" 2>/dev/null ||\n          { $doit $mvcmd -f \"$dst\" \"$rmtmp\" 2>/dev/null &&\n            { $doit $rmcmd -f \"$rmtmp\" 2>/dev/null; :; }\n          } ||\n          { echo \"$0: cannot unlink or rename $dst\" >&2\n            (exit 1); exit 1\n          }\n        } &&\n\n        # Now rename the file to the real destination.\n        $doit $mvcmd \"$dsttmp\" \"$dst\"\n      }\n    fi || exit 1\n\n    trap '' 0\n  fi\ndone\n\n# Local variables:\n# eval: (add-hook 'write-file-hooks 'time-stamp)\n# time-stamp-start: \"scriptversion=\"\n# time-stamp-format: \"%:y-%02m-%02d.%02H\"\n# time-stamp-time-zone: \"UTC\"\n# time-stamp-end: \"; # UTC\"\n# End:\n"
  },
  {
    "path": "src/vendor/libbacktrace/instrumented_alloc.c",
    "content": "/* instrumented_alloc.c -- Memory allocation instrumented to fail when\n   requested, for testing purposes.\n   Copyright (C) 2018-2024 Free Software Foundation, Inc.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n    (1) Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n\n    (2) Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in\n    the documentation and/or other materials provided with the\n    distribution.\n\n    (3) The name of the author may not be used to\n    endorse or promote products derived from this software without\n    specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\nIMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,\nINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\nHOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\nIN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGE.  */\n\n/* Include all the header files of alloc here, to make sure they're not\n   processed when including alloc.c below, such that the redefinitions of malloc\n   and realloc are only effective in alloc.c itself.  This does not work for\n   config.h, because it's not wrapped in \"#ifndef CONFIG_H\\n#define CONFIG_H\"\n   and \"#endif\" but that does not seem to be harmful.  */\n\n#include \"config.h\"\n\n#include <errno.h>\n#include <stdlib.h>\n#include <sys/types.h>\n#include <inttypes.h>\n\n#include \"backtrace.h\"\n#include \"internal.h\"\n\nextern void *instrumented_malloc (size_t size);\nextern void *instrumented_realloc (void *ptr, size_t size);\n\n#define malloc instrumented_malloc\n#define realloc instrumented_realloc\n#include \"alloc.c\"\n#undef malloc\n#undef realloc\n\nstatic uint64_t nr_allocs = 0;\nstatic uint64_t fail_at_alloc = 0;\n\nextern int at_fail_alloc_p (void);\nextern uint64_t get_nr_allocs (void);\nextern void set_fail_at_alloc (uint64_t);\n\nvoid *\ninstrumented_malloc (size_t size)\n{\n  void *res;\n\n  if (at_fail_alloc_p ())\n    return NULL;\n\n  res = malloc (size);\n  if (res != NULL)\n    nr_allocs++;\n\n  return res;\n}\n\nvoid *\ninstrumented_realloc (void *ptr, size_t size)\n{\n  void *res;\n\n  if (size != 0)\n    {\n      if (at_fail_alloc_p ())\n\treturn NULL;\n    }\n\n  res = realloc (ptr, size);\n  if (res != NULL)\n    nr_allocs++;\n\n  return res;\n}\n\nint\nat_fail_alloc_p (void)\n{\n  return fail_at_alloc == nr_allocs + 1;\n}\n\nuint64_t\nget_nr_allocs (void)\n{\n  return nr_allocs;\n}\n\nvoid\nset_fail_at_alloc (uint64_t nr)\n{\n  fail_at_alloc = nr;\n}\n"
  },
  {
    "path": "src/vendor/libbacktrace/internal.h",
    "content": "/* internal.h -- Internal header file for stack backtrace library.\n   Copyright (C) 2012-2024 Free Software Foundation, Inc.\n   Written by Ian Lance Taylor, Google.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n    (1) Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n\n    (2) Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in\n    the documentation and/or other materials provided with the\n    distribution.\n\n    (3) The name of the author may not be used to\n    endorse or promote products derived from this software without\n    specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\nIMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,\nINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\nHOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\nIN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGE.  */\n\n#ifndef BACKTRACE_INTERNAL_H\n#define BACKTRACE_INTERNAL_H\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* We assume that <sys/types.h> and \"backtrace.h\" have already been\n   included.  */\n\n#ifndef GCC_VERSION\n# define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__)\n#endif\n\n#if (GCC_VERSION < 2007)\n# define __attribute__(x)\n#endif\n\n#ifndef ATTRIBUTE_UNUSED\n# define ATTRIBUTE_UNUSED __attribute__ ((__unused__))\n#endif\n\n#ifndef ATTRIBUTE_MALLOC\n# if (GCC_VERSION >= 2096)\n#  define ATTRIBUTE_MALLOC __attribute__ ((__malloc__))\n# else\n#  define ATTRIBUTE_MALLOC\n# endif\n#endif\n\n#ifdef __has_attribute\n# if __has_attribute(fallthrough)\n#  define ATTRIBUTE_FALLTHROUGH __attribute__ ((fallthrough))\n# endif\n#endif\n#ifndef ATTRIBUTE_FALLTHROUGH\n# if (GCC_VERSION >= 7000)\n#  define ATTRIBUTE_FALLTHROUGH __attribute__ ((__fallthrough__))\n# else\n#  define ATTRIBUTE_FALLTHROUGH\n# endif\n#endif\n\n#ifndef HAVE_SYNC_FUNCTIONS\n\n/* Define out the sync functions.  These should never be called if\n   they are not available.  */\n\n#define __sync_bool_compare_and_swap(A, B, C) (abort(), 1)\n#define __sync_lock_test_and_set(A, B) (abort(), 0)\n#define __sync_lock_release(A) abort()\n\n#endif /* !defined (HAVE_SYNC_FUNCTIONS) */\n\n#ifdef HAVE_ATOMIC_FUNCTIONS\n\n/* We have the atomic builtin functions.  */\n\n#define backtrace_atomic_load_pointer(p) \\\n    __atomic_load_n ((p), __ATOMIC_ACQUIRE)\n#define backtrace_atomic_load_int(p) \\\n    __atomic_load_n ((p), __ATOMIC_ACQUIRE)\n#define backtrace_atomic_store_pointer(p, v) \\\n    __atomic_store_n ((p), (v), __ATOMIC_RELEASE)\n#define backtrace_atomic_store_size_t(p, v) \\\n    __atomic_store_n ((p), (v), __ATOMIC_RELEASE)\n#define backtrace_atomic_store_int(p, v) \\\n    __atomic_store_n ((p), (v), __ATOMIC_RELEASE)\n\n#else /* !defined (HAVE_ATOMIC_FUNCTIONS) */\n#ifdef HAVE_SYNC_FUNCTIONS\n\n/* We have the sync functions but not the atomic functions.  Define\n   the atomic ones in terms of the sync ones.  */\n\nextern void *backtrace_atomic_load_pointer (void *);\nextern int backtrace_atomic_load_int (int *);\nextern void backtrace_atomic_store_pointer (void *, void *);\nextern void backtrace_atomic_store_size_t (size_t *, size_t);\nextern void backtrace_atomic_store_int (int *, int);\n\n#else /* !defined (HAVE_SYNC_FUNCTIONS) */\n\n/* We have neither the sync nor the atomic functions.  These will\n   never be called.  */\n\n#define backtrace_atomic_load_pointer(p) (abort(), (void *) NULL)\n#define backtrace_atomic_load_int(p) (abort(), 0)\n#define backtrace_atomic_store_pointer(p, v) abort()\n#define backtrace_atomic_store_size_t(p, v) abort()\n#define backtrace_atomic_store_int(p, v) abort()\n\n#endif /* !defined (HAVE_SYNC_FUNCTIONS) */\n#endif /* !defined (HAVE_ATOMIC_FUNCTIONS) */\n\n/* The type of the function that collects file/line information.  This\n   is like backtrace_pcinfo.  */\n\ntypedef int (*fileline) (struct backtrace_state *state, uintptr_t pc,\n\t\t\t backtrace_full_callback callback,\n\t\t\t backtrace_error_callback error_callback, void *data);\n\n/* The type of the function that collects symbol information.  This is\n   like backtrace_syminfo.  */\n\ntypedef void (*syminfo) (struct backtrace_state *state, uintptr_t pc,\n\t\t\t backtrace_syminfo_callback callback,\n\t\t\t backtrace_error_callback error_callback, void *data);\n\n/* What the backtrace state pointer points to.  */\n\nstruct backtrace_state\n{\n  /* The name of the executable.  */\n  const char *filename;\n  /* Non-zero if threaded.  */\n  int threaded;\n  /* The master lock for fileline_fn, fileline_data, syminfo_fn,\n     syminfo_data, fileline_initialization_failed and everything the\n     data pointers point to.  */\n  void *lock;\n  /* The function that returns file/line information.  */\n  fileline fileline_fn;\n  /* The data to pass to FILELINE_FN.  */\n  void *fileline_data;\n  /* The function that returns symbol information.  */\n  syminfo syminfo_fn;\n  /* The data to pass to SYMINFO_FN.  */\n  void *syminfo_data;\n  /* Whether initializing the file/line information failed.  */\n  int fileline_initialization_failed;\n  /* The lock for the freelist.  */\n  int lock_alloc;\n  /* The freelist when using mmap.  */\n  struct backtrace_freelist_struct *freelist;\n};\n\n/* Open a file for reading.  Returns -1 on error.  If DOES_NOT_EXIST\n   is not NULL, *DOES_NOT_EXIST will be set to 0 normally and set to 1\n   if the file does not exist.  If the file does not exist and\n   DOES_NOT_EXIST is not NULL, the function will return -1 and will\n   not call ERROR_CALLBACK.  On other errors, or if DOES_NOT_EXIST is\n   NULL, the function will call ERROR_CALLBACK before returning.  */\nextern int backtrace_open (const char *filename,\n\t\t\t   backtrace_error_callback error_callback,\n\t\t\t   void *data,\n\t\t\t   int *does_not_exist);\n\n/* A view of the contents of a file.  This supports mmap when\n   available.  A view will remain in memory even after backtrace_close\n   is called on the file descriptor from which the view was\n   obtained.  */\n\nstruct backtrace_view\n{\n  /* The data that the caller requested.  */\n  const void *data;\n  /* The base of the view.  */\n  void *base;\n  /* The total length of the view.  */\n  size_t len;\n};\n\n/* Create a view of SIZE bytes from DESCRIPTOR at OFFSET.  Store the\n   result in *VIEW.  Returns 1 on success, 0 on error.  */\nextern int backtrace_get_view (struct backtrace_state *state, int descriptor,\n\t\t\t       off_t offset, uint64_t size,\n\t\t\t       backtrace_error_callback error_callback,\n\t\t\t       void *data, struct backtrace_view *view);\n\n/* Release a view created by backtrace_get_view.  */\nextern void backtrace_release_view (struct backtrace_state *state,\n\t\t\t\t    struct backtrace_view *view,\n\t\t\t\t    backtrace_error_callback error_callback,\n\t\t\t\t    void *data);\n\n/* Close a file opened by backtrace_open.  Returns 1 on success, 0 on\n   error.  */\n\nextern int backtrace_close (int descriptor,\n\t\t\t    backtrace_error_callback error_callback,\n\t\t\t    void *data);\n\n/* Sort without using memory.  */\n\nextern void backtrace_qsort (void *base, size_t count, size_t size,\n\t\t\t     int (*compar) (const void *, const void *));\n\n/* Allocate memory.  This is like malloc.  If ERROR_CALLBACK is NULL,\n   this does not report an error, it just returns NULL.  */\n\nextern void *backtrace_alloc (struct backtrace_state *state, size_t size,\n\t\t\t      backtrace_error_callback error_callback,\n\t\t\t      void *data) ATTRIBUTE_MALLOC;\n\n/* Free memory allocated by backtrace_alloc.  If ERROR_CALLBACK is\n   NULL, this does not report an error.  */\n\nextern void backtrace_free (struct backtrace_state *state, void *mem,\n\t\t\t    size_t size,\n\t\t\t    backtrace_error_callback error_callback,\n\t\t\t    void *data);\n\n/* A growable vector of some struct.  This is used for more efficient\n   allocation when we don't know the final size of some group of data\n   that we want to represent as an array.  */\n\nstruct backtrace_vector\n{\n  /* The base of the vector.  */\n  void *base;\n  /* The number of bytes in the vector.  */\n  size_t size;\n  /* The number of bytes available at the current allocation.  */\n  size_t alc;\n};\n\n/* Grow VEC by SIZE bytes.  Return a pointer to the newly allocated\n   bytes.  Note that this may move the entire vector to a new memory\n   location.  Returns NULL on failure.  */\n\nextern void *backtrace_vector_grow (struct backtrace_state *state, size_t size,\n\t\t\t\t    backtrace_error_callback error_callback,\n\t\t\t\t    void *data,\n\t\t\t\t    struct backtrace_vector *vec);\n\n/* Finish the current allocation on VEC.  Prepare to start a new\n   allocation.  The finished allocation will never be freed.  Returns\n   a pointer to the base of the finished entries, or NULL on\n   failure.  */\n\nextern void* backtrace_vector_finish (struct backtrace_state *state,\n\t\t\t\t      struct backtrace_vector *vec,\n\t\t\t\t      backtrace_error_callback error_callback,\n\t\t\t\t      void *data);\n\n/* Release any extra space allocated for VEC.  This may change\n   VEC->base.  Returns 1 on success, 0 on failure.  */\n\nextern int backtrace_vector_release (struct backtrace_state *state,\n\t\t\t\t     struct backtrace_vector *vec,\n\t\t\t\t     backtrace_error_callback error_callback,\n\t\t\t\t     void *data);\n\n/* Free the space managed by VEC.  This will reset VEC.  */\n\nstatic inline void\nbacktrace_vector_free (struct backtrace_state *state,\n\t\t       struct backtrace_vector *vec,\n\t\t       backtrace_error_callback error_callback, void *data)\n{\n  vec->alc += vec->size;\n  vec->size = 0;\n  backtrace_vector_release (state, vec, error_callback, data);\n}\n\n/* Read initial debug data from a descriptor, and set the\n   fileline_data, syminfo_fn, and syminfo_data fields of STATE.\n   Return the fileln_fn field in *FILELN_FN--this is done this way so\n   that the synchronization code is only implemented once.  This is\n   called after the descriptor has first been opened.  It will close\n   the descriptor if it is no longer needed.  Returns 1 on success, 0\n   on error.  There will be multiple implementations of this function,\n   for different file formats.  Each system will compile the\n   appropriate one.  */\n\nextern int backtrace_initialize (struct backtrace_state *state,\n\t\t\t\t const char *filename,\n\t\t\t\t int descriptor,\n\t\t\t\t backtrace_error_callback error_callback,\n\t\t\t\t void *data,\n\t\t\t\t fileline *fileline_fn);\n\n/* An enum for the DWARF sections we care about.  */\n\nenum dwarf_section\n{\n  DEBUG_INFO,\n  DEBUG_LINE,\n  DEBUG_ABBREV,\n  DEBUG_RANGES,\n  DEBUG_STR,\n  DEBUG_ADDR,\n  DEBUG_STR_OFFSETS,\n  DEBUG_LINE_STR,\n  DEBUG_RNGLISTS,\n\n  DEBUG_MAX\n};\n\n/* Data for the DWARF sections we care about.  */\n\nstruct dwarf_sections\n{\n  const unsigned char *data[DEBUG_MAX];\n  size_t size[DEBUG_MAX];\n};\n\n/* DWARF data read from a file, used for .gnu_debugaltlink.  */\n\nstruct dwarf_data;\n\n/* The load address mapping.  */\n\n#if defined(__FDPIC__) && defined(HAVE_DL_ITERATE_PHDR) && (defined(HAVE_LINK_H) || defined(HAVE_SYS_LINK_H))\n\n#ifdef HAVE_LINK_H\n #include <link.h>\n#endif\n#ifdef HAVE_SYS_LINK_H\n #include <sys/link.h>\n#endif\n\n#define libbacktrace_using_fdpic() (1)\n\nstruct libbacktrace_base_address\n{\n  struct elf32_fdpic_loadaddr m;\n};\n\n#define libbacktrace_add_base(pc, base) \\\n  ((uintptr_t) (__RELOC_POINTER ((pc), (base).m)))\n\n#else /* not _FDPIC__ */\n\n#define libbacktrace_using_fdpic() (0)\n\nstruct libbacktrace_base_address\n{\n  uintptr_t m;\n};\n\n#define libbacktrace_add_base(pc, base) ((pc) + (base).m)\n\n#endif /* not _FDPIC__ */\n\n/* Add file/line information for a DWARF module.  */\n\nextern int backtrace_dwarf_add (struct backtrace_state *state,\n\t\t\t\tstruct libbacktrace_base_address base_address,\n\t\t\t\tconst struct dwarf_sections *dwarf_sections,\n\t\t\t\tint is_bigendian,\n\t\t\t\tstruct dwarf_data *fileline_altlink,\n\t\t\t\tbacktrace_error_callback error_callback,\n\t\t\t\tvoid *data, fileline *fileline_fn,\n\t\t\t\tstruct dwarf_data **fileline_entry);\n\n/* A data structure to pass to backtrace_syminfo_to_full.  */\n\nstruct backtrace_call_full\n{\n  backtrace_full_callback full_callback;\n  backtrace_error_callback full_error_callback;\n  void *full_data;\n  int ret;\n};\n\n/* A backtrace_syminfo_callback that can call into a\n   backtrace_full_callback, used when we have a symbol table but no\n   debug info.  */\n\nextern void backtrace_syminfo_to_full_callback (void *data, uintptr_t pc,\n\t\t\t\t\t\tconst char *symname,\n\t\t\t\t\t\tuintptr_t symval,\n\t\t\t\t\t\tuintptr_t symsize);\n\n/* An error callback that corresponds to\n   backtrace_syminfo_to_full_callback.  */\n\nextern void backtrace_syminfo_to_full_error_callback (void *, const char *,\n\t\t\t\t\t\t      int);\n\n/* A test-only hook for elf_uncompress_zdebug.  */\n\nextern int backtrace_uncompress_zdebug (struct backtrace_state *,\n\t\t\t\t\tconst unsigned char *compressed,\n\t\t\t\t\tsize_t compressed_size,\n\t\t\t\t\tbacktrace_error_callback, void *data,\n\t\t\t\t\tunsigned char **uncompressed,\n\t\t\t\t\tsize_t *uncompressed_size);\n\n/* A test-only hook for elf_zstd_decompress.  */\n\nextern int backtrace_uncompress_zstd (struct backtrace_state *,\n\t\t\t\t      const unsigned char *compressed,\n\t\t\t\t      size_t compressed_size,\n\t\t\t\t      backtrace_error_callback, void *data,\n\t\t\t\t      unsigned char *uncompressed,\n\t\t\t\t      size_t uncompressed_size);\n\n/* A test-only hook for elf_uncompress_lzma.  */\n\nextern int backtrace_uncompress_lzma (struct backtrace_state *,\n\t\t\t\t      const unsigned char *compressed,\n\t\t\t\t      size_t compressed_size,\n\t\t\t\t      backtrace_error_callback, void *data,\n\t\t\t\t      unsigned char **uncompressed,\n\t\t\t\t      size_t *uncompressed_size);\n\nstruct elf_ppc64_opd_data;\nextern int elf_add (struct backtrace_state *state, const char *filename, int descriptor,\n\t const unsigned char *memory, size_t memory_size,\n\t struct libbacktrace_base_address base_address,\n\t struct elf_ppc64_opd_data *caller_opd,\n\t backtrace_error_callback error_callback, void *data,\n\t fileline *fileline_fn, int *found_sym, int *found_dwarf,\n\t struct dwarf_data **fileline_entry, int exe, int debuginfo,\n\t const char *with_buildid_data, uint32_t with_buildid_size);\nextern void elf_syminfo (struct backtrace_state *state, uintptr_t addr,\n\t     backtrace_syminfo_callback callback,\n\t     backtrace_error_callback error_callback ATTRIBUTE_UNUSED,\n\t     void *data);\nextern void elf_nosyms (struct backtrace_state *state ATTRIBUTE_UNUSED,\n\t    uintptr_t addr ATTRIBUTE_UNUSED,\n\t    backtrace_syminfo_callback callback ATTRIBUTE_UNUSED,\n\t    backtrace_error_callback error_callback, void *data);\n\nextern int macho_add (struct backtrace_state *state, const char *filename, int descriptor,\n\t   off_t offset, const unsigned char *match_uuid,\n\t   struct libbacktrace_base_address base_address, int skip_symtab,\n\t   backtrace_error_callback error_callback, void *data,\n\t   fileline *fileline_fn, int *found_sym);\nextern void macho_syminfo (struct backtrace_state *state, uintptr_t addr,\n\t       backtrace_syminfo_callback callback,\n\t       backtrace_error_callback error_callback ATTRIBUTE_UNUSED,\n\t       void *data);\nextern void macho_nosyms (struct backtrace_state *state ATTRIBUTE_UNUSED,\n\t      uintptr_t addr ATTRIBUTE_UNUSED,\n\t      backtrace_syminfo_callback callback ATTRIBUTE_UNUSED,\n\t      backtrace_error_callback error_callback, void *data);\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "src/vendor/libbacktrace/ltmain.sh",
    "content": "# Generated from ltmain.m4sh.\n\n# libtool (GNU libtool 1.3134 2009-11-29) 2.2.7a\n# Written by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996\n\n# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006,\n# 2007, 2008, 2009 Free Software Foundation, Inc.\n# This is free software; see the source for copying conditions.  There is NO\n# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n# GNU Libtool is free software; you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation; either version 2 of the License, or\n# (at your option) any later version.\n#\n# As a special exception to the GNU General Public License,\n# if you distribute this file as part of a program or library that\n# is built using GNU Libtool, you may include this file under the\n# same distribution terms that you use for the rest of that program.\n#\n# GNU Libtool is distributed in the hope that it will be useful, but\n# WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n# General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with GNU Libtool; see the file COPYING.  If not, a copy\n# can be downloaded from http://www.gnu.org/licenses/gpl.html,\n# or obtained by writing to the Free Software Foundation, Inc.,\n# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n\n# Usage: $progname [OPTION]... [MODE-ARG]...\n#\n# Provide generalized library-building support services.\n#\n#       --config             show all configuration variables\n#       --debug              enable verbose shell tracing\n#   -n, --dry-run            display commands without modifying any files\n#       --features           display basic configuration information and exit\n#       --mode=MODE          use operation mode MODE\n#       --no-finish          let install mode avoid finish commands\n#       --preserve-dup-deps  don't remove duplicate dependency libraries\n#       --quiet, --silent    don't print informational messages\n#       --no-quiet, --no-silent\n#                            print informational messages (default)\n#       --tag=TAG            use configuration variables from tag TAG\n#   -v, --verbose            print more informational messages than default\n#       --no-verbose         don't print the extra informational messages\n#       --version            print version information\n#   -h, --help, --help-all   print short, long, or detailed help message\n#\n# MODE must be one of the following:\n#\n#         clean              remove files from the build directory\n#         compile            compile a source file into a libtool object\n#         execute            automatically set library path, then run a program\n#         finish             complete the installation of libtool libraries\n#         install            install libraries or executables\n#         link               create a library or an executable\n#         uninstall          remove libraries from an installed directory\n#\n# MODE-ARGS vary depending on the MODE.  When passed as first option,\n# `--mode=MODE' may be abbreviated as `MODE' or a unique abbreviation of that.\n# Try `$progname --help --mode=MODE' for a more detailed description of MODE.\n#\n# When reporting a bug, please describe a test case to reproduce it and\n# include the following information:\n#\n#         host-triplet:\t$host\n#         shell:\t\t$SHELL\n#         compiler:\t\t$LTCC\n#         compiler flags:\t\t$LTCFLAGS\n#         linker:\t\t$LD (gnu? $with_gnu_ld)\n#         $progname:\t(GNU libtool 1.3134 2009-11-29) 2.2.7a\n#         automake:\t$automake_version\n#         autoconf:\t$autoconf_version\n#\n# Report bugs to <bug-libtool@gnu.org>.\n\nPROGRAM=libtool\nPACKAGE=libtool\nVERSION=2.2.7a\nTIMESTAMP=\" 1.3134 2009-11-29\"\npackage_revision=1.3134\n\n# Be Bourne compatible\nif test -n \"${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then\n  emulate sh\n  NULLCMD=:\n  # Zsh 3.x and 4.x performs word splitting on ${1+\"$@\"}, which\n  # is contrary to our usage.  Disable this feature.\n  alias -g '${1+\"$@\"}'='\"$@\"'\n  setopt NO_GLOB_SUBST\nelse\n  case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac\nfi\nBIN_SH=xpg4; export BIN_SH # for Tru64\nDUALCASE=1; export DUALCASE # for MKS sh\n\n# A function that is used when there is no print builtin or printf.\nfunc_fallback_echo ()\n{\n  eval 'cat <<_LTECHO_EOF\n$1\n_LTECHO_EOF'\n}\n\n# NLS nuisances: We save the old values to restore during execute mode.\n# Only set LANG and LC_ALL to C if already set.\n# These must not be set unconditionally because not all systems understand\n# e.g. LANG=C (notably SCO).\nlt_user_locale=\nlt_safe_locale=\nfor lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES\ndo\n  eval \"if test \\\"\\${$lt_var+set}\\\" = set; then\n          save_$lt_var=\\$$lt_var\n          $lt_var=C\n\t  export $lt_var\n\t  lt_user_locale=\\\"$lt_var=\\\\\\$save_\\$lt_var; \\$lt_user_locale\\\"\n\t  lt_safe_locale=\\\"$lt_var=C; \\$lt_safe_locale\\\"\n\tfi\"\ndone\n\n$lt_unset CDPATH\n\n\n\n\n\n\n\n# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh\n# is ksh but when the shell is invoked as \"sh\" and the current value of\n# the _XPG environment variable is not equal to 1 (one), the special\n# positional parameter $0, within a function call, is the name of the\n# function.\nprogpath=\"$0\"\n\n\n\n: ${CP=\"cp -f\"}\n: ${ECHO=$as_echo}\n: ${EGREP=\"/bin/grep -E\"}\n: ${FGREP=\"/bin/grep -F\"}\n: ${GREP=\"/bin/grep\"}\n: ${LN_S=\"ln -s\"}\n: ${MAKE=\"make\"}\n: ${MKDIR=\"mkdir\"}\n: ${MV=\"mv -f\"}\n: ${RM=\"rm -f\"}\n: ${SED=\"/mount/endor/wildenhu/local-x86_64/bin/sed\"}\n: ${SHELL=\"${CONFIG_SHELL-/bin/sh}\"}\n: ${Xsed=\"$SED -e 1s/^X//\"}\n\n# Global variables:\nEXIT_SUCCESS=0\nEXIT_FAILURE=1\nEXIT_MISMATCH=63  # $? = 63 is used to indicate version mismatch to missing.\nEXIT_SKIP=77\t  # $? = 77 is used to indicate a skipped test to automake.\n\nexit_status=$EXIT_SUCCESS\n\n# Make sure IFS has a sensible default\nlt_nl='\n'\nIFS=\" \t$lt_nl\"\n\ndirname=\"s,/[^/]*$,,\"\nbasename=\"s,^.*/,,\"\n\n# func_dirname_and_basename file append nondir_replacement\n# perform func_basename and func_dirname in a single function\n# call:\n#   dirname:  Compute the dirname of FILE.  If nonempty,\n#             add APPEND to the result, otherwise set result\n#             to NONDIR_REPLACEMENT.\n#             value returned in \"$func_dirname_result\"\n#   basename: Compute filename of FILE.\n#             value retuned in \"$func_basename_result\"\n# Implementation must be kept synchronized with func_dirname\n# and func_basename. For efficiency, we do not delegate to\n# those functions but instead duplicate the functionality here.\nfunc_dirname_and_basename ()\n{\n  # Extract subdirectory from the argument.\n  func_dirname_result=`$ECHO \"${1}\" | $SED -e \"$dirname\"`\n  if test \"X$func_dirname_result\" = \"X${1}\"; then\n    func_dirname_result=\"${3}\"\n  else\n    func_dirname_result=\"$func_dirname_result${2}\"\n  fi\n  func_basename_result=`$ECHO \"${1}\" | $SED -e \"$basename\"`\n}\n\n# Generated shell functions inserted here.\n\n# These SED scripts presuppose an absolute path with a trailing slash.\npathcar='s,^/\\([^/]*\\).*$,\\1,'\npathcdr='s,^/[^/]*,,'\nremovedotparts=':dotsl\n\t\ts@/\\./@/@g\n\t\tt dotsl\n\t\ts,/\\.$,/,'\ncollapseslashes='s@/\\{1,\\}@/@g'\nfinalslash='s,/*$,/,'\n\n# func_normal_abspath PATH\n# Remove doubled-up and trailing slashes, \".\" path components,\n# and cancel out any \"..\" path components in PATH after making\n# it an absolute path.\n#             value returned in \"$func_normal_abspath_result\"\nfunc_normal_abspath ()\n{\n  # Start from root dir and reassemble the path.\n  func_normal_abspath_result=\n  func_normal_abspath_tpath=$1\n  func_normal_abspath_altnamespace=\n  case $func_normal_abspath_tpath in\n    \"\")\n      # Empty path, that just means $cwd.\n      func_stripname '' '/' \"`pwd`\"\n      func_normal_abspath_result=$func_stripname_result\n      return\n    ;;\n    # The next three entries are used to spot a run of precisely\n    # two leading slashes without using negated character classes;\n    # we take advantage of case's first-match behaviour.\n    ///*)\n      # Unusual form of absolute path, do nothing.\n    ;;\n    //*)\n      # Not necessarily an ordinary path; POSIX reserves leading '//'\n      # and for example Cygwin uses it to access remote file shares\n      # over CIFS/SMB, so we conserve a leading double slash if found.\n      func_normal_abspath_altnamespace=/\n    ;;\n    /*)\n      # Absolute path, do nothing.\n    ;;\n    *)\n      # Relative path, prepend $cwd.\n      func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath\n    ;;\n  esac\n  # Cancel out all the simple stuff to save iterations.  We also want\n  # the path to end with a slash for ease of parsing, so make sure\n  # there is one (and only one) here.\n  func_normal_abspath_tpath=`$ECHO \"$func_normal_abspath_tpath\" | $SED \\\n        -e \"$removedotparts\" -e \"$collapseslashes\" -e \"$finalslash\"`\n  while :; do\n    # Processed it all yet?\n    if test \"$func_normal_abspath_tpath\" = / ; then\n      # If we ascended to the root using \"..\" the result may be empty now.\n      if test -z \"$func_normal_abspath_result\" ; then\n        func_normal_abspath_result=/\n      fi\n      break\n    fi\n    func_normal_abspath_tcomponent=`$ECHO \"$func_normal_abspath_tpath\" | $SED \\\n        -e \"$pathcar\"`\n    func_normal_abspath_tpath=`$ECHO \"$func_normal_abspath_tpath\" | $SED \\\n        -e \"$pathcdr\"`\n    # Figure out what to do with it\n    case $func_normal_abspath_tcomponent in\n      \"\")\n        # Trailing empty path component, ignore it.\n      ;;\n      ..)\n        # Parent dir; strip last assembled component from result.\n        func_dirname \"$func_normal_abspath_result\"\n        func_normal_abspath_result=$func_dirname_result\n      ;;\n      *)\n        # Actual path component, append it.\n        func_normal_abspath_result=$func_normal_abspath_result/$func_normal_abspath_tcomponent\n      ;;\n    esac\n  done\n  # Restore leading double-slash if one was found on entry.\n  func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result\n}\n\n# func_relative_path SRCDIR DSTDIR\n# generates a relative path from SRCDIR to DSTDIR, with a trailing\n# slash if non-empty, suitable for immediately appending a filename\n# without needing to append a separator.\n#             value returned in \"$func_relative_path_result\"\nfunc_relative_path ()\n{\n  func_relative_path_result=\n  func_normal_abspath \"$1\"\n  func_relative_path_tlibdir=$func_normal_abspath_result\n  func_normal_abspath \"$2\"\n  func_relative_path_tbindir=$func_normal_abspath_result\n\n  # Ascend the tree starting from libdir\n  while :; do\n    # check if we have found a prefix of bindir\n    case $func_relative_path_tbindir in\n      $func_relative_path_tlibdir)\n        # found an exact match\n        func_relative_path_tcancelled=\n        break\n        ;;\n      $func_relative_path_tlibdir*)\n        # found a matching prefix\n        func_stripname \"$func_relative_path_tlibdir\" '' \"$func_relative_path_tbindir\"\n        func_relative_path_tcancelled=$func_stripname_result\n        if test -z \"$func_relative_path_result\"; then\n          func_relative_path_result=.\n        fi\n        break\n        ;;\n      *)\n        func_dirname $func_relative_path_tlibdir\n        func_relative_path_tlibdir=${func_dirname_result}\n        if test \"x$func_relative_path_tlibdir\" = x ; then\n          # Have to descend all the way to the root!\n          func_relative_path_result=../$func_relative_path_result\n          func_relative_path_tcancelled=$func_relative_path_tbindir\n          break\n        fi\n        func_relative_path_result=../$func_relative_path_result\n        ;;\n    esac\n  done\n\n  # Now calculate path; take care to avoid doubling-up slashes.\n  func_stripname '' '/' \"$func_relative_path_result\"\n  func_relative_path_result=$func_stripname_result\n  func_stripname '/' '/' \"$func_relative_path_tcancelled\"\n  if test \"x$func_stripname_result\" != x ; then\n    func_relative_path_result=${func_relative_path_result}/${func_stripname_result}\n  fi\n\n  # Normalisation. If bindir is libdir, return empty string,\n  # else relative path ending with a slash; either way, target\n  # file name can be directly appended.\n  if test ! -z \"$func_relative_path_result\"; then\n    func_stripname './' '' \"$func_relative_path_result/\"\n    func_relative_path_result=$func_stripname_result\n  fi\n}\n\n# The name of this program:\nfunc_dirname_and_basename \"$progpath\"\nprogname=$func_basename_result\n\n# Make sure we have an absolute path for reexecution:\ncase $progpath in\n  [\\\\/]*|[A-Za-z]:\\\\*) ;;\n  *[\\\\/]*)\n     progdir=$func_dirname_result\n     progdir=`cd \"$progdir\" && pwd`\n     progpath=\"$progdir/$progname\"\n     ;;\n  *)\n     save_IFS=\"$IFS\"\n     IFS=:\n     for progdir in $PATH; do\n       IFS=\"$save_IFS\"\n       test -x \"$progdir/$progname\" && break\n     done\n     IFS=\"$save_IFS\"\n     test -n \"$progdir\" || progdir=`pwd`\n     progpath=\"$progdir/$progname\"\n     ;;\nesac\n\n# Sed substitution that helps us do robust quoting.  It backslashifies\n# metacharacters that are still active within double-quoted strings.\nXsed=\"${SED}\"' -e 1s/^X//'\nsed_quote_subst='s/\\([`\"$\\\\]\\)/\\\\\\1/g'\n\n# Same as above, but do not quote variable references.\ndouble_quote_subst='s/\\([\"`\\\\]\\)/\\\\\\1/g'\n\n# Re-`\\' parameter expansions in output of double_quote_subst that were\n# `\\'-ed in input to the same.  If an odd number of `\\' preceded a '$'\n# in input to double_quote_subst, that '$' was protected from expansion.\n# Since each input `\\' is now two `\\'s, look for any number of runs of\n# four `\\'s followed by two `\\'s and then a '$'.  `\\' that '$'.\nbs='\\\\'\nbs2='\\\\\\\\'\nbs4='\\\\\\\\\\\\\\\\'\ndollar='\\$'\nsed_double_backslash=\"\\\n  s/$bs4/&\\\\\n/g\n  s/^$bs2$dollar/$bs&/\n  s/\\\\([^$bs]\\\\)$bs2$dollar/\\\\1$bs2$bs$dollar/g\n  s/\\n//g\"\n\n# Standard options:\nopt_dry_run=false\nopt_help=false\nopt_quiet=false\nopt_verbose=false\nopt_warning=:\n\n# func_echo arg...\n# Echo program name prefixed message, along with the current mode\n# name if it has been set yet.\nfunc_echo ()\n{\n    $ECHO \"$progname${mode+: }$mode: $*\"\n}\n\n# func_verbose arg...\n# Echo program name prefixed message in verbose mode only.\nfunc_verbose ()\n{\n    $opt_verbose && func_echo ${1+\"$@\"}\n\n    # A bug in bash halts the script if the last line of a function\n    # fails when set -e is in force, so we need another command to\n    # work around that:\n    :\n}\n\n# func_echo_all arg...\n# Invoke $ECHO with all args, space-separated.\nfunc_echo_all ()\n{\n    $ECHO \"$*\"\n}\n\n# func_error arg...\n# Echo program name prefixed message to standard error.\nfunc_error ()\n{\n    $ECHO \"$progname${mode+: }$mode: \"${1+\"$@\"} 1>&2\n}\n\n# func_warning arg...\n# Echo program name prefixed warning message to standard error.\nfunc_warning ()\n{\n    $opt_warning && $ECHO \"$progname${mode+: }$mode: warning: \"${1+\"$@\"} 1>&2\n\n    # bash bug again:\n    :\n}\n\n# func_fatal_error arg...\n# Echo program name prefixed message to standard error, and exit.\nfunc_fatal_error ()\n{\n    func_error ${1+\"$@\"}\n    exit $EXIT_FAILURE\n}\n\n# func_fatal_help arg...\n# Echo program name prefixed message to standard error, followed by\n# a help hint, and exit.\nfunc_fatal_help ()\n{\n    func_error ${1+\"$@\"}\n    func_fatal_error \"$help\"\n}\nhelp=\"Try \\`$progname --help' for more information.\"  ## default\n\n\n# func_grep expression filename\n# Check whether EXPRESSION matches any line of FILENAME, without output.\nfunc_grep ()\n{\n    $GREP \"$1\" \"$2\" >/dev/null 2>&1\n}\n\n\n# func_mkdir_p directory-path\n# Make sure the entire path to DIRECTORY-PATH is available.\nfunc_mkdir_p ()\n{\n    my_directory_path=\"$1\"\n    my_dir_list=\n\n    if test -n \"$my_directory_path\" && test \"$opt_dry_run\" != \":\"; then\n\n      # Protect directory names starting with `-'\n      case $my_directory_path in\n        -*) my_directory_path=\"./$my_directory_path\" ;;\n      esac\n\n      # While some portion of DIR does not yet exist...\n      while test ! -d \"$my_directory_path\"; do\n        # ...make a list in topmost first order.  Use a colon delimited\n\t# list incase some portion of path contains whitespace.\n        my_dir_list=\"$my_directory_path:$my_dir_list\"\n\n        # If the last portion added has no slash in it, the list is done\n        case $my_directory_path in */*) ;; *) break ;; esac\n\n        # ...otherwise throw away the child directory and loop\n        my_directory_path=`$ECHO \"$my_directory_path\" | $SED -e \"$dirname\"`\n      done\n      my_dir_list=`$ECHO \"$my_dir_list\" | $SED 's,:*$,,'`\n\n      save_mkdir_p_IFS=\"$IFS\"; IFS=':'\n      for my_dir in $my_dir_list; do\n\tIFS=\"$save_mkdir_p_IFS\"\n        # mkdir can fail with a `File exist' error if two processes\n        # try to create one of the directories concurrently.  Don't\n        # stop in that case!\n        $MKDIR \"$my_dir\" 2>/dev/null || :\n      done\n      IFS=\"$save_mkdir_p_IFS\"\n\n      # Bail out if we (or some other process) failed to create a directory.\n      test -d \"$my_directory_path\" || \\\n        func_fatal_error \"Failed to create \\`$1'\"\n    fi\n}\n\n\n# func_mktempdir [string]\n# Make a temporary directory that won't clash with other running\n# libtool processes, and avoids race conditions if possible.  If\n# given, STRING is the basename for that directory.\nfunc_mktempdir ()\n{\n    my_template=\"${TMPDIR-/tmp}/${1-$progname}\"\n\n    if test \"$opt_dry_run\" = \":\"; then\n      # Return a directory name, but don't create it in dry-run mode\n      my_tmpdir=\"${my_template}-$$\"\n    else\n\n      # If mktemp works, use that first and foremost\n      my_tmpdir=`mktemp -d \"${my_template}-XXXXXXXX\" 2>/dev/null`\n\n      if test ! -d \"$my_tmpdir\"; then\n        # Failing that, at least try and use $RANDOM to avoid a race\n        my_tmpdir=\"${my_template}-${RANDOM-0}$$\"\n\n        save_mktempdir_umask=`umask`\n        umask 0077\n        $MKDIR \"$my_tmpdir\"\n        umask $save_mktempdir_umask\n      fi\n\n      # If we're not in dry-run mode, bomb out on failure\n      test -d \"$my_tmpdir\" || \\\n        func_fatal_error \"cannot create temporary directory \\`$my_tmpdir'\"\n    fi\n\n    $ECHO \"$my_tmpdir\"\n}\n\n\n# func_quote_for_eval arg\n# Aesthetically quote ARG to be evaled later.\n# This function returns two values: FUNC_QUOTE_FOR_EVAL_RESULT\n# is double-quoted, suitable for a subsequent eval, whereas\n# FUNC_QUOTE_FOR_EVAL_UNQUOTED_RESULT has merely all characters\n# which are still active within double quotes backslashified.\nfunc_quote_for_eval ()\n{\n    case $1 in\n      *[\\\\\\`\\\"\\$]*)\n\tfunc_quote_for_eval_unquoted_result=`$ECHO \"$1\" | $SED \"$sed_quote_subst\"` ;;\n      *)\n        func_quote_for_eval_unquoted_result=\"$1\" ;;\n    esac\n\n    case $func_quote_for_eval_unquoted_result in\n      # Double-quote args containing shell metacharacters to delay\n      # word splitting, command substitution and and variable\n      # expansion for a subsequent eval.\n      # Many Bourne shells cannot handle close brackets correctly\n      # in scan sets, so we specify it separately.\n      *[\\[\\~\\#\\^\\&\\*\\(\\)\\{\\}\\|\\;\\<\\>\\?\\'\\ \\\t]*|*]*|\"\")\n        func_quote_for_eval_result=\"\\\"$func_quote_for_eval_unquoted_result\\\"\"\n        ;;\n      *)\n        func_quote_for_eval_result=\"$func_quote_for_eval_unquoted_result\"\n    esac\n}\n\n\n# func_quote_for_expand arg\n# Aesthetically quote ARG to be evaled later; same as above,\n# but do not quote variable references.\nfunc_quote_for_expand ()\n{\n    case $1 in\n      *[\\\\\\`\\\"]*)\n\tmy_arg=`$ECHO \"$1\" | $SED \\\n\t    -e \"$double_quote_subst\" -e \"$sed_double_backslash\"` ;;\n      *)\n        my_arg=\"$1\" ;;\n    esac\n\n    case $my_arg in\n      # Double-quote args containing shell metacharacters to delay\n      # word splitting and command substitution for a subsequent eval.\n      # Many Bourne shells cannot handle close brackets correctly\n      # in scan sets, so we specify it separately.\n      *[\\[\\~\\#\\^\\&\\*\\(\\)\\{\\}\\|\\;\\<\\>\\?\\'\\ \\\t]*|*]*|\"\")\n        my_arg=\"\\\"$my_arg\\\"\"\n        ;;\n    esac\n\n    func_quote_for_expand_result=\"$my_arg\"\n}\n\n\n# func_show_eval cmd [fail_exp]\n# Unless opt_silent is true, then output CMD.  Then, if opt_dryrun is\n# not true, evaluate CMD.  If the evaluation of CMD fails, and FAIL_EXP\n# is given, then evaluate it.\nfunc_show_eval ()\n{\n    my_cmd=\"$1\"\n    my_fail_exp=\"${2-:}\"\n\n    ${opt_silent-false} || {\n      func_quote_for_expand \"$my_cmd\"\n      eval \"func_echo $func_quote_for_expand_result\"\n    }\n\n    if ${opt_dry_run-false}; then :; else\n      eval \"$my_cmd\"\n      my_status=$?\n      if test \"$my_status\" -eq 0; then :; else\n\teval \"(exit $my_status); $my_fail_exp\"\n      fi\n    fi\n}\n\n\n# func_show_eval_locale cmd [fail_exp]\n# Unless opt_silent is true, then output CMD.  Then, if opt_dryrun is\n# not true, evaluate CMD.  If the evaluation of CMD fails, and FAIL_EXP\n# is given, then evaluate it.  Use the saved locale for evaluation.\nfunc_show_eval_locale ()\n{\n    my_cmd=\"$1\"\n    my_fail_exp=\"${2-:}\"\n\n    ${opt_silent-false} || {\n      func_quote_for_expand \"$my_cmd\"\n      eval \"func_echo $func_quote_for_expand_result\"\n    }\n\n    if ${opt_dry_run-false}; then :; else\n      eval \"$lt_user_locale\n\t    $my_cmd\"\n      my_status=$?\n      eval \"$lt_safe_locale\"\n      if test \"$my_status\" -eq 0; then :; else\n\teval \"(exit $my_status); $my_fail_exp\"\n      fi\n    fi\n}\n\n\n\n\n\n# func_version\n# Echo version message to standard output and exit.\nfunc_version ()\n{\n    $SED -n '/(C)/!b go\n\t:more\n\t/\\./!{\n\t  N\n\t  s/\\n# //\n\t  b more\n\t}\n\t:go\n\t/^# '$PROGRAM' (GNU /,/# warranty; / {\n        s/^# //\n\ts/^# *$//\n        s/\\((C)\\)[ 0-9,-]*\\( [1-9][0-9]*\\)/\\1\\2/\n        p\n     }' < \"$progpath\"\n     exit $?\n}\n\n# func_usage\n# Echo short help message to standard output and exit.\nfunc_usage ()\n{\n    $SED -n '/^# Usage:/,/^#  *-h/ {\n        s/^# //\n\ts/^# *$//\n\ts/\\$progname/'$progname'/\n\tp\n    }' < \"$progpath\"\n    echo\n    $ECHO \"run \\`$progname --help | more' for full usage\"\n    exit $?\n}\n\n# func_help [NOEXIT]\n# Echo long help message to standard output and exit,\n# unless 'noexit' is passed as argument.\nfunc_help ()\n{\n    $SED -n '/^# Usage:/,/# Report bugs to/ {\n        s/^# //\n\ts/^# *$//\n\ts*\\$progname*'$progname'*\n\ts*\\$host*'\"$host\"'*\n\ts*\\$SHELL*'\"$SHELL\"'*\n\ts*\\$LTCC*'\"$LTCC\"'*\n\ts*\\$LTCFLAGS*'\"$LTCFLAGS\"'*\n\ts*\\$LD*'\"$LD\"'*\n\ts/\\$with_gnu_ld/'\"$with_gnu_ld\"'/\n\ts/\\$automake_version/'\"`(automake --version) 2>/dev/null |$SED 1q`\"'/\n\ts/\\$autoconf_version/'\"`(autoconf --version) 2>/dev/null |$SED 1q`\"'/\n\tp\n     }' < \"$progpath\"\n    ret=$?\n    if test -z \"$1\"; then\n      exit $ret\n    fi\n}\n\n# func_missing_arg argname\n# Echo program name prefixed message to standard error and set global\n# exit_cmd.\nfunc_missing_arg ()\n{\n    func_error \"missing argument for $1\"\n    exit_cmd=exit\n}\n\nexit_cmd=:\n\n\n\n\n\n\nmagic=\"%%%MAGIC variable%%%\"\nmagic_exe=\"%%%MAGIC EXE variable%%%\"\n\n# Global variables.\n# $mode is unset\nnonopt=\nexecute_dlfiles=\npreserve_args=\nlo2o=\"s/\\\\.lo\\$/.${objext}/\"\no2lo=\"s/\\\\.${objext}\\$/.lo/\"\nextracted_archives=\nextracted_serial=0\n\nopt_dry_run=false\nopt_finish=:\nopt_duplicate_deps=false\nopt_silent=false\nopt_debug=:\n\n# If this variable is set in any of the actions, the command in it\n# will be execed at the end.  This prevents here-documents from being\n# left over by shells.\nexec_cmd=\n\n# func_fatal_configuration arg...\n# Echo program name prefixed message to standard error, followed by\n# a configuration failure hint, and exit.\nfunc_fatal_configuration ()\n{\n    func_error ${1+\"$@\"}\n    func_error \"See the $PACKAGE documentation for more information.\"\n    func_fatal_error \"Fatal configuration error.\"\n}\n\n\n# func_config\n# Display the configuration for all the tags in this script.\nfunc_config ()\n{\n    re_begincf='^# ### BEGIN LIBTOOL'\n    re_endcf='^# ### END LIBTOOL'\n\n    # Default configuration.\n    $SED \"1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\\$d\" < \"$progpath\"\n\n    # Now print the configurations for the tags.\n    for tagname in $taglist; do\n      $SED -n \"/$re_begincf TAG CONFIG: $tagname\\$/,/$re_endcf TAG CONFIG: $tagname\\$/p\" < \"$progpath\"\n    done\n\n    exit $?\n}\n\n# func_features\n# Display the features supported by this script.\nfunc_features ()\n{\n    echo \"host: $host\"\n    if test \"$build_libtool_libs\" = yes; then\n      echo \"enable shared libraries\"\n    else\n      echo \"disable shared libraries\"\n    fi\n    if test \"$build_old_libs\" = yes; then\n      echo \"enable static libraries\"\n    else\n      echo \"disable static libraries\"\n    fi\n\n    exit $?\n}\n\n# func_enable_tag tagname\n# Verify that TAGNAME is valid, and either flag an error and exit, or\n# enable the TAGNAME tag.  We also add TAGNAME to the global $taglist\n# variable here.\nfunc_enable_tag ()\n{\n  # Global variable:\n  tagname=\"$1\"\n\n  re_begincf=\"^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\\$\"\n  re_endcf=\"^# ### END LIBTOOL TAG CONFIG: $tagname\\$\"\n  sed_extractcf=\"/$re_begincf/,/$re_endcf/p\"\n\n  # Validate tagname.\n  case $tagname in\n    *[!-_A-Za-z0-9,/]*)\n      func_fatal_error \"invalid tag name: $tagname\"\n      ;;\n  esac\n\n  # Don't test for the \"default\" C tag, as we know it's\n  # there but not specially marked.\n  case $tagname in\n    CC) ;;\n    *)\n      if $GREP \"$re_begincf\" \"$progpath\" >/dev/null 2>&1; then\n\ttaglist=\"$taglist $tagname\"\n\n\t# Evaluate the configuration.  Be careful to quote the path\n\t# and the sed script, to avoid splitting on whitespace, but\n\t# also don't use non-portable quotes within backquotes within\n\t# quotes we have to do it in 2 steps:\n\textractedcf=`$SED -n -e \"$sed_extractcf\" < \"$progpath\"`\n\teval \"$extractedcf\"\n      else\n\tfunc_error \"ignoring unknown tag $tagname\"\n      fi\n      ;;\n  esac\n}\n\n# Parse options once, thoroughly.  This comes as soon as possible in\n# the script to make things like `libtool --version' happen quickly.\n{\n\n  # Shorthand for --mode=foo, only valid as the first argument\n  case $1 in\n  clean|clea|cle|cl)\n    shift; set dummy --mode clean ${1+\"$@\"}; shift\n    ;;\n  compile|compil|compi|comp|com|co|c)\n    shift; set dummy --mode compile ${1+\"$@\"}; shift\n    ;;\n  execute|execut|execu|exec|exe|ex|e)\n    shift; set dummy --mode execute ${1+\"$@\"}; shift\n    ;;\n  finish|finis|fini|fin|fi|f)\n    shift; set dummy --mode finish ${1+\"$@\"}; shift\n    ;;\n  install|instal|insta|inst|ins|in|i)\n    shift; set dummy --mode install ${1+\"$@\"}; shift\n    ;;\n  link|lin|li|l)\n    shift; set dummy --mode link ${1+\"$@\"}; shift\n    ;;\n  uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u)\n    shift; set dummy --mode uninstall ${1+\"$@\"}; shift\n    ;;\n  esac\n\n  # Parse non-mode specific arguments:\n  while test \"$#\" -gt 0; do\n    opt=\"$1\"\n    shift\n\n    case $opt in\n      --config)\t\tfunc_config\t\t\t\t\t;;\n\n      --debug)\t\tpreserve_args=\"$preserve_args $opt\"\n\t\t\tfunc_echo \"enabling shell trace mode\"\n\t\t\topt_debug='set -x'\n\t\t\t$opt_debug\n\t\t\t;;\n\n      -dlopen)\t\ttest \"$#\" -eq 0 && func_missing_arg \"$opt\" && break\n\t\t\texecute_dlfiles=\"$execute_dlfiles $1\"\n\t\t\tshift\n\t\t\t;;\n\n      --dry-run | -n)\topt_dry_run=:\t\t\t\t\t;;\n      --features)       func_features\t\t\t\t\t;;\n      --finish)\t\tmode=\"finish\"\t\t\t\t\t;;\n      --no-finish)\topt_finish=false\t\t\t\t;;\n\n      --mode)\t\ttest \"$#\" -eq 0 && func_missing_arg \"$opt\" && break\n\t\t\tcase $1 in\n\t\t\t  # Valid mode arguments:\n\t\t\t  clean)\t;;\n\t\t\t  compile)\t;;\n\t\t\t  execute)\t;;\n\t\t\t  finish)\t;;\n\t\t\t  install)\t;;\n\t\t\t  link)\t\t;;\n\t\t\t  relink)\t;;\n\t\t\t  uninstall)\t;;\n\n\t\t\t  # Catch anything else as an error\n\t\t\t  *) func_error \"invalid argument for $opt\"\n\t\t\t     exit_cmd=exit\n\t\t\t     break\n\t\t\t     ;;\n\t\t        esac\n\n\t\t\tmode=\"$1\"\n\t\t\tshift\n\t\t\t;;\n\n      --preserve-dup-deps)\n\t\t\topt_duplicate_deps=:\t\t\t\t;;\n\n      --quiet|--silent)\tpreserve_args=\"$preserve_args $opt\"\n\t\t\topt_silent=:\n\t\t\topt_verbose=false\n\t\t\t;;\n\n      --no-quiet|--no-silent)\n\t\t\tpreserve_args=\"$preserve_args $opt\"\n\t\t\topt_silent=false\n\t\t\t;;\n\n      --verbose| -v)\tpreserve_args=\"$preserve_args $opt\"\n\t\t\topt_silent=false\n\t\t\topt_verbose=:\n\t\t\t;;\n\n      --no-verbose)\tpreserve_args=\"$preserve_args $opt\"\n\t\t\topt_verbose=false\n\t\t\t;;\n\n      --tag)\t\ttest \"$#\" -eq 0 && func_missing_arg \"$opt\" && break\n\t\t\tpreserve_args=\"$preserve_args $opt $1\"\n\t\t\tfunc_enable_tag \"$1\"\t# tagname is set here\n\t\t\tshift\n\t\t\t;;\n\n      # Separate optargs to long options:\n      -dlopen=*|--mode=*|--tag=*)\n\t\t\tfunc_opt_split \"$opt\"\n\t\t\tset dummy \"$func_opt_split_opt\" \"$func_opt_split_arg\" ${1+\"$@\"}\n\t\t\tshift\n\t\t\t;;\n\n      -\\?|-h)\t\tfunc_usage\t\t\t\t\t;;\n      --help)\t\topt_help=:\t\t\t\t\t;;\n      --help-all)\topt_help=': help-all'\t\t\t\t;;\n      --version)\tfunc_version\t\t\t\t\t;;\n\n      -*)\t\tfunc_fatal_help \"unrecognized option \\`$opt'\"\t;;\n\n      *)\t\tnonopt=\"$opt\"\n\t\t\tbreak\n\t\t\t;;\n    esac\n  done\n\n\n  case $host in\n    *cygwin* | *mingw* | *pw32* | *cegcc* | *solaris2* )\n      # don't eliminate duplications in $postdeps and $predeps\n      opt_duplicate_compiler_generated_deps=:\n      ;;\n    *)\n      opt_duplicate_compiler_generated_deps=$opt_duplicate_deps\n      ;;\n  esac\n\n  # Having warned about all mis-specified options, bail out if\n  # anything was wrong.\n  $exit_cmd $EXIT_FAILURE\n}\n\n# func_check_version_match\n# Ensure that we are using m4 macros, and libtool script from the same\n# release of libtool.\nfunc_check_version_match ()\n{\n  if test \"$package_revision\" != \"$macro_revision\"; then\n    if test \"$VERSION\" != \"$macro_version\"; then\n      if test -z \"$macro_version\"; then\n        cat >&2 <<_LT_EOF\n$progname: Version mismatch error.  This is $PACKAGE $VERSION, but the\n$progname: definition of this LT_INIT comes from an older release.\n$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION\n$progname: and run autoconf again.\n_LT_EOF\n      else\n        cat >&2 <<_LT_EOF\n$progname: Version mismatch error.  This is $PACKAGE $VERSION, but the\n$progname: definition of this LT_INIT comes from $PACKAGE $macro_version.\n$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION\n$progname: and run autoconf again.\n_LT_EOF\n      fi\n    else\n      cat >&2 <<_LT_EOF\n$progname: Version mismatch error.  This is $PACKAGE $VERSION, revision $package_revision,\n$progname: but the definition of this LT_INIT comes from revision $macro_revision.\n$progname: You should recreate aclocal.m4 with macros from revision $package_revision\n$progname: of $PACKAGE $VERSION and run autoconf again.\n_LT_EOF\n    fi\n\n    exit $EXIT_MISMATCH\n  fi\n}\n\n\n## ----------- ##\n##    Main.    ##\n## ----------- ##\n\n$opt_help || {\n  # Sanity checks first:\n  func_check_version_match\n\n  if test \"$build_libtool_libs\" != yes && test \"$build_old_libs\" != yes; then\n    func_fatal_configuration \"not configured to build any kind of library\"\n  fi\n\n  test -z \"$mode\" && func_fatal_error \"error: you must specify a MODE.\"\n\n\n  # Darwin sucks\n  eval \"std_shrext=\\\"$shrext_cmds\\\"\"\n\n\n  # Only execute mode is allowed to have -dlopen flags.\n  if test -n \"$execute_dlfiles\" && test \"$mode\" != execute; then\n    func_error \"unrecognized option \\`-dlopen'\"\n    $ECHO \"$help\" 1>&2\n    exit $EXIT_FAILURE\n  fi\n\n  # Change the help message to a mode-specific one.\n  generic_help=\"$help\"\n  help=\"Try \\`$progname --help --mode=$mode' for more information.\"\n}\n\n\n# func_lalib_p file\n# True iff FILE is a libtool `.la' library or `.lo' object file.\n# This function is only a basic sanity check; it will hardly flush out\n# determined imposters.\nfunc_lalib_p ()\n{\n    test -f \"$1\" &&\n      $SED -e 4q \"$1\" 2>/dev/null \\\n        | $GREP \"^# Generated by .*$PACKAGE\" > /dev/null 2>&1\n}\n\n# func_lalib_unsafe_p file\n# True iff FILE is a libtool `.la' library or `.lo' object file.\n# This function implements the same check as func_lalib_p without\n# resorting to external programs.  To this end, it redirects stdin and\n# closes it afterwards, without saving the original file descriptor.\n# As a safety measure, use it only where a negative result would be\n# fatal anyway.  Works if `file' does not exist.\nfunc_lalib_unsafe_p ()\n{\n    lalib_p=no\n    if test -f \"$1\" && test -r \"$1\" && exec 5<&0 <\"$1\"; then\n\tfor lalib_p_l in 1 2 3 4\n\tdo\n\t    read lalib_p_line\n\t    case \"$lalib_p_line\" in\n\t\t\\#\\ Generated\\ by\\ *$PACKAGE* ) lalib_p=yes; break;;\n\t    esac\n\tdone\n\texec 0<&5 5<&-\n    fi\n    test \"$lalib_p\" = yes\n}\n\n# func_ltwrapper_script_p file\n# True iff FILE is a libtool wrapper script\n# This function is only a basic sanity check; it will hardly flush out\n# determined imposters.\nfunc_ltwrapper_script_p ()\n{\n    func_lalib_p \"$1\"\n}\n\n# func_ltwrapper_executable_p file\n# True iff FILE is a libtool wrapper executable\n# This function is only a basic sanity check; it will hardly flush out\n# determined imposters.\nfunc_ltwrapper_executable_p ()\n{\n    func_ltwrapper_exec_suffix=\n    case $1 in\n    *.exe) ;;\n    *) func_ltwrapper_exec_suffix=.exe ;;\n    esac\n    $GREP \"$magic_exe\" \"$1$func_ltwrapper_exec_suffix\" >/dev/null 2>&1\n}\n\n# func_ltwrapper_scriptname file\n# Assumes file is an ltwrapper_executable\n# uses $file to determine the appropriate filename for a\n# temporary ltwrapper_script.\nfunc_ltwrapper_scriptname ()\n{\n    func_ltwrapper_scriptname_result=\"\"\n    if func_ltwrapper_executable_p \"$1\"; then\n\tfunc_dirname_and_basename \"$1\" \"\" \".\"\n\tfunc_stripname '' '.exe' \"$func_basename_result\"\n\tfunc_ltwrapper_scriptname_result=\"$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper\"\n    fi\n}\n\n# func_ltwrapper_p file\n# True iff FILE is a libtool wrapper script or wrapper executable\n# This function is only a basic sanity check; it will hardly flush out\n# determined imposters.\nfunc_ltwrapper_p ()\n{\n    func_ltwrapper_script_p \"$1\" || func_ltwrapper_executable_p \"$1\"\n}\n\n\n# func_execute_cmds commands fail_cmd\n# Execute tilde-delimited COMMANDS.\n# If FAIL_CMD is given, eval that upon failure.\n# FAIL_CMD may read-access the current command in variable CMD!\nfunc_execute_cmds ()\n{\n    $opt_debug\n    save_ifs=$IFS; IFS='~'\n    for cmd in $1; do\n      IFS=$save_ifs\n      eval \"cmd=\\\"$cmd\\\"\"\n      func_show_eval \"$cmd\" \"${2-:}\"\n    done\n    IFS=$save_ifs\n}\n\n\n# func_source file\n# Source FILE, adding directory component if necessary.\n# Note that it is not necessary on cygwin/mingw to append a dot to\n# FILE even if both FILE and FILE.exe exist: automatic-append-.exe\n# behavior happens only for exec(3), not for open(2)!  Also, sourcing\n# `FILE.' does not work on cygwin managed mounts.\nfunc_source ()\n{\n    $opt_debug\n    case $1 in\n    */* | *\\\\*)\t. \"$1\" ;;\n    *)\t\t. \"./$1\" ;;\n    esac\n}\n\n\n# func_infer_tag arg\n# Infer tagged configuration to use if any are available and\n# if one wasn't chosen via the \"--tag\" command line option.\n# Only attempt this if the compiler in the base compile\n# command doesn't match the default compiler.\n# arg is usually of the form 'gcc ...'\nfunc_infer_tag ()\n{\n    $opt_debug\n    if test -n \"$available_tags\" && test -z \"$tagname\"; then\n      CC_quoted=\n      for arg in $CC; do\n        func_quote_for_eval \"$arg\"\n\tCC_quoted=\"$CC_quoted $func_quote_for_eval_result\"\n      done\n      CC_expanded=`func_echo_all $CC`\n      CC_quoted_expanded=`func_echo_all $CC_quoted`\n      case $@ in\n      # Blanks in the command may have been stripped by the calling shell,\n      # but not from the CC environment variable when configure was run.\n      \" $CC \"* | \"$CC \"* | \" $CC_expanded \"* | \"$CC_expanded \"* | \\\n      \" $CC_quoted\"* | \"$CC_quoted \"* | \" $CC_quoted_expanded \"* | \"$CC_quoted_expanded \"*) ;;\n      # Blanks at the start of $base_compile will cause this to fail\n      # if we don't check for them as well.\n      *)\n\tfor z in $available_tags; do\n\t  if $GREP \"^# ### BEGIN LIBTOOL TAG CONFIG: $z$\" < \"$progpath\" > /dev/null; then\n\t    # Evaluate the configuration.\n\t    eval \"`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`\"\n\t    CC_quoted=\n\t    for arg in $CC; do\n\t      # Double-quote args containing other shell metacharacters.\n\t      func_quote_for_eval \"$arg\"\n\t      CC_quoted=\"$CC_quoted $func_quote_for_eval_result\"\n\t    done\n\t    CC_expanded=`func_echo_all $CC`\n\t    CC_quoted_expanded=`func_echo_all $CC_quoted`\n\t    case \"$@ \" in\n\t    \" $CC \"* | \"$CC \"* | \" $CC_expanded \"* | \"$CC_expanded \"* | \\\n\t    \" $CC_quoted\"* | \"$CC_quoted \"* | \" $CC_quoted_expanded \"* | \"$CC_quoted_expanded \"*)\n\t      # The compiler in the base compile command matches\n\t      # the one in the tagged configuration.\n\t      # Assume this is the tagged configuration we want.\n\t      tagname=$z\n\t      break\n\t      ;;\n\t    esac\n\t  fi\n\tdone\n\t# If $tagname still isn't set, then no tagged configuration\n\t# was found and let the user know that the \"--tag\" command\n\t# line option must be used.\n\tif test -z \"$tagname\"; then\n\t  func_echo \"unable to infer tagged configuration\"\n\t  func_fatal_error \"specify a tag with \\`--tag'\"\n#\telse\n#\t  func_verbose \"using $tagname tagged configuration\"\n\tfi\n\t;;\n      esac\n    fi\n}\n\n\n\n# func_write_libtool_object output_name pic_name nonpic_name\n# Create a libtool object file (analogous to a \".la\" file),\n# but don't create it if we're doing a dry run.\nfunc_write_libtool_object ()\n{\n    write_libobj=${1}\n    if test \"$build_libtool_libs\" = yes; then\n      write_lobj=\\'${2}\\'\n    else\n      write_lobj=none\n    fi\n\n    if test \"$build_old_libs\" = yes; then\n      write_oldobj=\\'${3}\\'\n    else\n      write_oldobj=none\n    fi\n\n    $opt_dry_run || {\n      cat >${write_libobj}T <<EOF\n# $write_libobj - a libtool object file\n# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION\n#\n# Please DO NOT delete this file!\n# It is necessary for linking the library.\n\n# Name of the PIC object.\npic_object=$write_lobj\n\n# Name of the non-PIC object\nnon_pic_object=$write_oldobj\n\nEOF\n      $MV \"${write_libobj}T\" \"${write_libobj}\"\n    }\n}\n\n# func_mode_compile arg...\nfunc_mode_compile ()\n{\n    $opt_debug\n    # Get the compilation command and the source file.\n    base_compile=\n    srcfile=\"$nonopt\"  #  always keep a non-empty value in \"srcfile\"\n    suppress_opt=yes\n    suppress_output=\n    arg_mode=normal\n    libobj=\n    later=\n    pie_flag=\n\n    for arg\n    do\n      case $arg_mode in\n      arg  )\n\t# do not \"continue\".  Instead, add this to base_compile\n\tlastarg=\"$arg\"\n\targ_mode=normal\n\t;;\n\n      target )\n\tlibobj=\"$arg\"\n\targ_mode=normal\n\tcontinue\n\t;;\n\n      normal )\n\t# Accept any command-line options.\n\tcase $arg in\n\t-o)\n\t  test -n \"$libobj\" && \\\n\t    func_fatal_error \"you cannot specify \\`-o' more than once\"\n\t  arg_mode=target\n\t  continue\n\t  ;;\n\n\t-pie | -fpie | -fPIE)\n          pie_flag=\"$pie_flag $arg\"\n\t  continue\n\t  ;;\n\n\t-shared | -static | -prefer-pic | -prefer-non-pic)\n\t  later=\"$later $arg\"\n\t  continue\n\t  ;;\n\n\t-no-suppress)\n\t  suppress_opt=no\n\t  continue\n\t  ;;\n\n\t-Xcompiler)\n\t  arg_mode=arg  #  the next one goes into the \"base_compile\" arg list\n\t  continue      #  The current \"srcfile\" will either be retained or\n\t  ;;            #  replaced later.  I would guess that would be a bug.\n\n\t-Wc,*)\n\t  func_stripname '-Wc,' '' \"$arg\"\n\t  args=$func_stripname_result\n\t  lastarg=\n\t  save_ifs=\"$IFS\"; IFS=','\n\t  for arg in $args; do\n\t    IFS=\"$save_ifs\"\n\t    func_quote_for_eval \"$arg\"\n\t    lastarg=\"$lastarg $func_quote_for_eval_result\"\n\t  done\n\t  IFS=\"$save_ifs\"\n\t  func_stripname ' ' '' \"$lastarg\"\n\t  lastarg=$func_stripname_result\n\n\t  # Add the arguments to base_compile.\n\t  base_compile=\"$base_compile $lastarg\"\n\t  continue\n\t  ;;\n\n\t*)\n\t  # Accept the current argument as the source file.\n\t  # The previous \"srcfile\" becomes the current argument.\n\t  #\n\t  lastarg=\"$srcfile\"\n\t  srcfile=\"$arg\"\n\t  ;;\n\tesac  #  case $arg\n\t;;\n      esac    #  case $arg_mode\n\n      # Aesthetically quote the previous argument.\n      func_quote_for_eval \"$lastarg\"\n      base_compile=\"$base_compile $func_quote_for_eval_result\"\n    done # for arg\n\n    case $arg_mode in\n    arg)\n      func_fatal_error \"you must specify an argument for -Xcompile\"\n      ;;\n    target)\n      func_fatal_error \"you must specify a target with \\`-o'\"\n      ;;\n    *)\n      # Get the name of the library object.\n      test -z \"$libobj\" && {\n\tfunc_basename \"$srcfile\"\n\tlibobj=\"$func_basename_result\"\n      }\n      ;;\n    esac\n\n    # Recognize several different file suffixes.\n    # If the user specifies -o file.o, it is replaced with file.lo\n    case $libobj in\n    *.[cCFSifmso] | \\\n    *.ada | *.adb | *.ads | *.asm | \\\n    *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \\\n    *.[fF][09]? | *.for | *.java | *.obj | *.sx | *.cu | *.cup)\n      func_xform \"$libobj\"\n      libobj=$func_xform_result\n      ;;\n    esac\n\n    case $libobj in\n    *.lo) func_lo2o \"$libobj\"; obj=$func_lo2o_result ;;\n    *)\n      func_fatal_error \"cannot determine name of library object from \\`$libobj'\"\n      ;;\n    esac\n\n    func_infer_tag $base_compile\n\n    for arg in $later; do\n      case $arg in\n      -shared)\n\ttest \"$build_libtool_libs\" != yes && \\\n\t  func_fatal_configuration \"can not build a shared library\"\n\tbuild_old_libs=no\n\tcontinue\n\t;;\n\n      -static)\n\tbuild_libtool_libs=no\n\tbuild_old_libs=yes\n\tcontinue\n\t;;\n\n      -prefer-pic)\n\tpic_mode=yes\n\tcontinue\n\t;;\n\n      -prefer-non-pic)\n\tpic_mode=no\n\tcontinue\n\t;;\n      esac\n    done\n\n    func_quote_for_eval \"$libobj\"\n    test \"X$libobj\" != \"X$func_quote_for_eval_result\" \\\n      && $ECHO \"X$libobj\" | $GREP '[]~#^*{};<>?\"'\"'\"'\t &()|`$[]' \\\n      && func_warning \"libobj name \\`$libobj' may not contain shell special characters.\"\n    func_dirname_and_basename \"$obj\" \"/\" \"\"\n    objname=\"$func_basename_result\"\n    xdir=\"$func_dirname_result\"\n    lobj=${xdir}$objdir/$objname\n\n    test -z \"$base_compile\" && \\\n      func_fatal_help \"you must specify a compilation command\"\n\n    # Delete any leftover library objects.\n    if test \"$build_old_libs\" = yes; then\n      removelist=\"$obj $lobj $libobj ${libobj}T\"\n    else\n      removelist=\"$lobj $libobj ${libobj}T\"\n    fi\n\n    # On Cygwin there's no \"real\" PIC flag so we must build both object types\n    case $host_os in\n    cygwin* | mingw* | pw32* | os2* | cegcc*)\n      pic_mode=default\n      ;;\n    esac\n    if test \"$pic_mode\" = no && test \"$deplibs_check_method\" != pass_all; then\n      # non-PIC code in shared libraries is not supported\n      pic_mode=default\n    fi\n\n    # Calculate the filename of the output object if compiler does\n    # not support -o with -c\n    if test \"$compiler_c_o\" = no; then\n      output_obj=`$ECHO \"$srcfile\" | $SED 's%^.*/%%; s%\\.[^.]*$%%'`.${objext}\n      lockfile=\"$output_obj.lock\"\n    else\n      output_obj=\n      need_locks=no\n      lockfile=\n    fi\n\n    # Lock this critical section if it is needed\n    # We use this script file to make the link, it avoids creating a new file\n    if test \"$need_locks\" = yes; then\n      until $opt_dry_run || ln \"$progpath\" \"$lockfile\" 2>/dev/null; do\n\tfunc_echo \"Waiting for $lockfile to be removed\"\n\tsleep 2\n      done\n    elif test \"$need_locks\" = warn; then\n      if test -f \"$lockfile\"; then\n\t$ECHO \"\\\n*** ERROR, $lockfile exists and contains:\n`cat $lockfile 2>/dev/null`\n\nThis indicates that another process is trying to use the same\ntemporary object file, and libtool could not work around it because\nyour compiler does not support \\`-c' and \\`-o' together.  If you\nrepeat this compilation, it may succeed, by chance, but you had better\navoid parallel builds (make -j) in this platform, or get a better\ncompiler.\"\n\n\t$opt_dry_run || $RM $removelist\n\texit $EXIT_FAILURE\n      fi\n      removelist=\"$removelist $output_obj\"\n      $ECHO \"$srcfile\" > \"$lockfile\"\n    fi\n\n    $opt_dry_run || $RM $removelist\n    removelist=\"$removelist $lockfile\"\n    trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15\n\n    if test -n \"$fix_srcfile_path\"; then\n      eval \"srcfile=\\\"$fix_srcfile_path\\\"\"\n    fi\n    func_quote_for_eval \"$srcfile\"\n    qsrcfile=$func_quote_for_eval_result\n\n    # Only build a PIC object if we are building libtool libraries.\n    if test \"$build_libtool_libs\" = yes; then\n      # Without this assignment, base_compile gets emptied.\n      fbsd_hideous_sh_bug=$base_compile\n\n      if test \"$pic_mode\" != no; then\n\tcommand=\"$base_compile $qsrcfile $pic_flag\"\n      else\n\t# Don't build PIC code\n\tcommand=\"$base_compile $qsrcfile\"\n      fi\n\n      func_mkdir_p \"$xdir$objdir\"\n\n      if test -z \"$output_obj\"; then\n\t# Place PIC objects in $objdir\n\tcommand=\"$command -o $lobj\"\n      fi\n\n      func_show_eval_locale \"$command\"\t\\\n          'test -n \"$output_obj\" && $RM $removelist; exit $EXIT_FAILURE'\n\n      if test \"$need_locks\" = warn &&\n\t test \"X`cat $lockfile 2>/dev/null`\" != \"X$srcfile\"; then\n\t$ECHO \"\\\n*** ERROR, $lockfile contains:\n`cat $lockfile 2>/dev/null`\n\nbut it should contain:\n$srcfile\n\nThis indicates that another process is trying to use the same\ntemporary object file, and libtool could not work around it because\nyour compiler does not support \\`-c' and \\`-o' together.  If you\nrepeat this compilation, it may succeed, by chance, but you had better\navoid parallel builds (make -j) in this platform, or get a better\ncompiler.\"\n\n\t$opt_dry_run || $RM $removelist\n\texit $EXIT_FAILURE\n      fi\n\n      # Just move the object if needed, then go on to compile the next one\n      if test -n \"$output_obj\" && test \"X$output_obj\" != \"X$lobj\"; then\n\tfunc_show_eval '$MV \"$output_obj\" \"$lobj\"' \\\n\t  'error=$?; $opt_dry_run || $RM $removelist; exit $error'\n      fi\n\n      # Allow error messages only from the first compilation.\n      if test \"$suppress_opt\" = yes; then\n\tsuppress_output=' >/dev/null 2>&1'\n      fi\n    fi\n\n    # Only build a position-dependent object if we build old libraries.\n    if test \"$build_old_libs\" = yes; then\n      if test \"$pic_mode\" != yes; then\n\t# Don't build PIC code\n\tcommand=\"$base_compile $qsrcfile$pie_flag\"\n      else\n\tcommand=\"$base_compile $qsrcfile $pic_flag\"\n      fi\n      if test \"$compiler_c_o\" = yes; then\n\tcommand=\"$command -o $obj\"\n      fi\n\n      # Suppress compiler output if we already did a PIC compilation.\n      command=\"$command$suppress_output\"\n      func_show_eval_locale \"$command\" \\\n        '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE'\n\n      if test \"$need_locks\" = warn &&\n\t test \"X`cat $lockfile 2>/dev/null`\" != \"X$srcfile\"; then\n\t$ECHO \"\\\n*** ERROR, $lockfile contains:\n`cat $lockfile 2>/dev/null`\n\nbut it should contain:\n$srcfile\n\nThis indicates that another process is trying to use the same\ntemporary object file, and libtool could not work around it because\nyour compiler does not support \\`-c' and \\`-o' together.  If you\nrepeat this compilation, it may succeed, by chance, but you had better\navoid parallel builds (make -j) in this platform, or get a better\ncompiler.\"\n\n\t$opt_dry_run || $RM $removelist\n\texit $EXIT_FAILURE\n      fi\n\n      # Just move the object if needed\n      if test -n \"$output_obj\" && test \"X$output_obj\" != \"X$obj\"; then\n\tfunc_show_eval '$MV \"$output_obj\" \"$obj\"' \\\n\t  'error=$?; $opt_dry_run || $RM $removelist; exit $error'\n      fi\n    fi\n\n    $opt_dry_run || {\n      func_write_libtool_object \"$libobj\" \"$objdir/$objname\" \"$objname\"\n\n      # Unlock the critical section if it was locked\n      if test \"$need_locks\" != no; then\n\tremovelist=$lockfile\n        $RM \"$lockfile\"\n      fi\n    }\n\n    exit $EXIT_SUCCESS\n}\n\n$opt_help || {\n  test \"$mode\" = compile && func_mode_compile ${1+\"$@\"}\n}\n\nfunc_mode_help ()\n{\n    # We need to display help for each of the modes.\n    case $mode in\n      \"\")\n        # Generic help is extracted from the usage comments\n        # at the start of this file.\n        func_help\n        ;;\n\n      clean)\n        $ECHO \\\n\"Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE...\n\nRemove files from the build directory.\n\nRM is the name of the program to use to delete files associated with each FILE\n(typically \\`/bin/rm').  RM-OPTIONS are options (such as \\`-f') to be passed\nto RM.\n\nIf FILE is a libtool library, object or program, all the files associated\nwith it are deleted. Otherwise, only FILE itself is deleted using RM.\"\n        ;;\n\n      compile)\n      $ECHO \\\n\"Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE\n\nCompile a source file into a libtool library object.\n\nThis mode accepts the following additional options:\n\n  -o OUTPUT-FILE    set the output file name to OUTPUT-FILE\n  -no-suppress      do not suppress compiler output for multiple passes\n  -prefer-pic       try to building PIC objects only\n  -prefer-non-pic   try to building non-PIC objects only\n  -shared           do not build a \\`.o' file suitable for static linking\n  -static           only build a \\`.o' file suitable for static linking\n  -Wc,FLAG          pass FLAG directly to the compiler\n\nCOMPILE-COMMAND is a command to be used in creating a \\`standard' object file\nfrom the given SOURCEFILE.\n\nThe output file name is determined by removing the directory component from\nSOURCEFILE, then substituting the C source code suffix \\`.c' with the\nlibrary object suffix, \\`.lo'.\"\n        ;;\n\n      execute)\n        $ECHO \\\n\"Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]...\n\nAutomatically set library path, then run a program.\n\nThis mode accepts the following additional options:\n\n  -dlopen FILE      add the directory containing FILE to the library path\n\nThis mode sets the library path environment variable according to \\`-dlopen'\nflags.\n\nIf any of the ARGS are libtool executable wrappers, then they are translated\ninto their corresponding uninstalled binary, and any of their required library\ndirectories are added to the library path.\n\nThen, COMMAND is executed, with ARGS as arguments.\"\n        ;;\n\n      finish)\n        $ECHO \\\n\"Usage: $progname [OPTION]... --mode=finish [LIBDIR]...\n\nComplete the installation of libtool libraries.\n\nEach LIBDIR is a directory that contains libtool libraries.\n\nThe commands that this mode executes may require superuser privileges.  Use\nthe \\`--dry-run' option if you just want to see what would be executed.\"\n        ;;\n\n      install)\n        $ECHO \\\n\"Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND...\n\nInstall executables or libraries.\n\nINSTALL-COMMAND is the installation command.  The first component should be\neither the \\`install' or \\`cp' program.\n\nThe following components of INSTALL-COMMAND are treated specially:\n\n  -inst-prefix-dir PREFIX-DIR  Use PREFIX-DIR as a staging area for installation\n\nThe rest of the components are interpreted as arguments to that command (only\nBSD-compatible install options are recognized).\"\n        ;;\n\n      link)\n        $ECHO \\\n\"Usage: $progname [OPTION]... --mode=link LINK-COMMAND...\n\nLink object files or libraries together to form another library, or to\ncreate an executable program.\n\nLINK-COMMAND is a command using the C compiler that you would use to create\na program from several object files.\n\nThe following components of LINK-COMMAND are treated specially:\n\n  -all-static       do not do any dynamic linking at all\n  -avoid-version    do not add a version suffix if possible\n  -bindir BINDIR    specify path to binaries directory (for systems where\n                    libraries must be found in the PATH setting at runtime)\n  -dlopen FILE      \\`-dlpreopen' FILE if it cannot be dlopened at runtime\n  -dlpreopen FILE   link in FILE and add its symbols to lt_preloaded_symbols\n  -export-dynamic   allow symbols from OUTPUT-FILE to be resolved with dlsym(3)\n  -export-symbols SYMFILE\n                    try to export only the symbols listed in SYMFILE\n  -export-symbols-regex REGEX\n                    try to export only the symbols matching REGEX\n  -LLIBDIR          search LIBDIR for required installed libraries\n  -lNAME            OUTPUT-FILE requires the installed library libNAME\n  -module           build a library that can dlopened\n  -no-fast-install  disable the fast-install mode\n  -no-install       link a not-installable executable\n  -no-undefined     declare that a library does not refer to external symbols\n  -o OUTPUT-FILE    create OUTPUT-FILE from the specified objects\n  -objectlist FILE  Use a list of object files found in FILE to specify objects\n  -precious-files-regex REGEX\n                    don't remove output files matching REGEX\n  -release RELEASE  specify package release information\n  -rpath LIBDIR     the created library will eventually be installed in LIBDIR\n  -R[ ]LIBDIR       add LIBDIR to the runtime path of programs and libraries\n  -shared           only do dynamic linking of libtool libraries\n  -shrext SUFFIX    override the standard shared library file extension\n  -static           do not do any dynamic linking of uninstalled libtool libraries\n  -static-libtool-libs\n                    do not do any dynamic linking of libtool libraries\n  -version-info CURRENT[:REVISION[:AGE]]\n                    specify library version info [each variable defaults to 0]\n  -weak LIBNAME     declare that the target provides the LIBNAME interface\n  -Wc,FLAG\n  -Xcompiler FLAG   pass linker-specific FLAG directly to the compiler\n  -Wl,FLAG\n  -Xlinker FLAG     pass linker-specific FLAG directly to the linker\n  -XCClinker FLAG   pass link-specific FLAG to the compiler driver (CC)\n\nAll other options (arguments beginning with \\`-') are ignored.\n\nEvery other argument is treated as a filename.  Files ending in \\`.la' are\ntreated as uninstalled libtool libraries, other files are standard or library\nobject files.\n\nIf the OUTPUT-FILE ends in \\`.la', then a libtool library is created,\nonly library objects (\\`.lo' files) may be specified, and \\`-rpath' is\nrequired, except when creating a convenience library.\n\nIf OUTPUT-FILE ends in \\`.a' or \\`.lib', then a standard library is created\nusing \\`ar' and \\`ranlib', or on Windows using \\`lib'.\n\nIf OUTPUT-FILE ends in \\`.lo' or \\`.${objext}', then a reloadable object file\nis created, otherwise an executable program is created.\"\n        ;;\n\n      uninstall)\n        $ECHO \\\n\"Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE...\n\nRemove libraries from an installation directory.\n\nRM is the name of the program to use to delete files associated with each FILE\n(typically \\`/bin/rm').  RM-OPTIONS are options (such as \\`-f') to be passed\nto RM.\n\nIf FILE is a libtool library, all the files associated with it are deleted.\nOtherwise, only FILE itself is deleted using RM.\"\n        ;;\n\n      *)\n        func_fatal_help \"invalid operation mode \\`$mode'\"\n        ;;\n    esac\n\n    echo\n    $ECHO \"Try \\`$progname --help' for more information about other modes.\"\n}\n\n# Now that we've collected a possible --mode arg, show help if necessary\nif $opt_help; then\n  if test \"$opt_help\" = :; then\n    func_mode_help\n  else\n    {\n      func_help noexit\n      for mode in compile link execute install finish uninstall clean; do\n\tfunc_mode_help\n      done\n    } | sed -n '1p; 2,$s/^Usage:/  or: /p'\n    {\n      func_help noexit\n      for mode in compile link execute install finish uninstall clean; do\n\techo\n\tfunc_mode_help\n      done\n    } |\n    sed '1d\n      /^When reporting/,/^Report/{\n\tH\n\td\n      }\n      $x\n      /information about other modes/d\n      /more detailed .*MODE/d\n      s/^Usage:.*--mode=\\([^ ]*\\) .*/Description of \\1 mode:/'\n  fi\n  exit $?\nfi\n\n\n# func_mode_execute arg...\nfunc_mode_execute ()\n{\n    $opt_debug\n    # The first argument is the command name.\n    cmd=\"$nonopt\"\n    test -z \"$cmd\" && \\\n      func_fatal_help \"you must specify a COMMAND\"\n\n    # Handle -dlopen flags immediately.\n    for file in $execute_dlfiles; do\n      test -f \"$file\" \\\n\t|| func_fatal_help \"\\`$file' is not a file\"\n\n      dir=\n      case $file in\n      *.la)\n\t# Check to see that this really is a libtool archive.\n\tfunc_lalib_unsafe_p \"$file\" \\\n\t  || func_fatal_help \"\\`$lib' is not a valid libtool archive\"\n\n\t# Read the libtool library.\n\tdlname=\n\tlibrary_names=\n\tfunc_source \"$file\"\n\n\t# Skip this library if it cannot be dlopened.\n\tif test -z \"$dlname\"; then\n\t  # Warn if it was a shared library.\n\t  test -n \"$library_names\" && \\\n\t    func_warning \"\\`$file' was not linked with \\`-export-dynamic'\"\n\t  continue\n\tfi\n\n\tfunc_dirname \"$file\" \"\" \".\"\n\tdir=\"$func_dirname_result\"\n\n\tif test -f \"$dir/$objdir/$dlname\"; then\n\t  dir=\"$dir/$objdir\"\n\telse\n\t  if test ! -f \"$dir/$dlname\"; then\n\t    func_fatal_error \"cannot find \\`$dlname' in \\`$dir' or \\`$dir/$objdir'\"\n\t  fi\n\tfi\n\t;;\n\n      *.lo)\n\t# Just add the directory containing the .lo file.\n\tfunc_dirname \"$file\" \"\" \".\"\n\tdir=\"$func_dirname_result\"\n\t;;\n\n      *)\n\tfunc_warning \"\\`-dlopen' is ignored for non-libtool libraries and objects\"\n\tcontinue\n\t;;\n      esac\n\n      # Get the absolute pathname.\n      absdir=`cd \"$dir\" && pwd`\n      test -n \"$absdir\" && dir=\"$absdir\"\n\n      # Now add the directory to shlibpath_var.\n      if eval test -z \\\"\\$$shlibpath_var\\\"; then\n\teval $shlibpath_var=\\$dir\n      else\n\teval $shlibpath_var=\\$dir:\\$$shlibpath_var\n      fi\n    done\n\n    # This variable tells wrapper scripts just to set shlibpath_var\n    # rather than running their programs.\n    libtool_execute_magic=\"$magic\"\n\n    # Check if any of the arguments is a wrapper script.\n    args=\n    for file\n    do\n      case $file in\n      -* | *.la | *.lo ) ;;\n      *)\n\t# Do a test to see if this is really a libtool program.\n\tif func_ltwrapper_script_p \"$file\"; then\n\t  func_source \"$file\"\n\t  # Transform arg to wrapped name.\n\t  file=\"$progdir/$program\"\n\telif func_ltwrapper_executable_p \"$file\"; then\n\t  func_ltwrapper_scriptname \"$file\"\n\t  func_source \"$func_ltwrapper_scriptname_result\"\n\t  # Transform arg to wrapped name.\n\t  file=\"$progdir/$program\"\n\tfi\n\t;;\n      esac\n      # Quote arguments (to preserve shell metacharacters).\n      func_quote_for_eval \"$file\"\n      args=\"$args $func_quote_for_eval_result\"\n    done\n\n    if test \"X$opt_dry_run\" = Xfalse; then\n      if test -n \"$shlibpath_var\"; then\n\t# Export the shlibpath_var.\n\teval \"export $shlibpath_var\"\n      fi\n\n      # Restore saved environment variables\n      for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES\n      do\n\teval \"if test \\\"\\${save_$lt_var+set}\\\" = set; then\n                $lt_var=\\$save_$lt_var; export $lt_var\n\t      else\n\t\t$lt_unset $lt_var\n\t      fi\"\n      done\n\n      # Now prepare to actually exec the command.\n      exec_cmd=\"\\$cmd$args\"\n    else\n      # Display what would be done.\n      if test -n \"$shlibpath_var\"; then\n\teval \"\\$ECHO \\\"\\$shlibpath_var=\\$$shlibpath_var\\\"\"\n\techo \"export $shlibpath_var\"\n      fi\n      $ECHO \"$cmd$args\"\n      exit $EXIT_SUCCESS\n    fi\n}\n\ntest \"$mode\" = execute && func_mode_execute ${1+\"$@\"}\n\n\n# func_mode_finish arg...\nfunc_mode_finish ()\n{\n    $opt_debug\n    libdirs=\"$nonopt\"\n    admincmds=\n\n    if test -n \"$finish_cmds$finish_eval\" && test -n \"$libdirs\"; then\n      for dir\n      do\n\tlibdirs=\"$libdirs $dir\"\n      done\n\n      for libdir in $libdirs; do\n\tif test -n \"$finish_cmds\"; then\n\t  # Do each command in the finish commands.\n\t  func_execute_cmds \"$finish_cmds\" 'admincmds=\"$admincmds\n'\"$cmd\"'\"'\n\tfi\n\tif test -n \"$finish_eval\"; then\n\t  # Do the single finish_eval.\n\t  eval cmds=\\\"$finish_eval\\\"\n\t  $opt_dry_run || eval \"$cmds\" || admincmds=\"$admincmds\n       $cmds\"\n\tfi\n      done\n    fi\n\n    # Exit here if they wanted silent mode.\n    $opt_silent && exit $EXIT_SUCCESS\n\n    echo \"----------------------------------------------------------------------\"\n    echo \"Libraries have been installed in:\"\n    for libdir in $libdirs; do\n      $ECHO \"   $libdir\"\n    done\n    echo\n    echo \"If you ever happen to want to link against installed libraries\"\n    echo \"in a given directory, LIBDIR, you must either use libtool, and\"\n    echo \"specify the full pathname of the library, or use the \\`-LLIBDIR'\"\n    echo \"flag during linking and do at least one of the following:\"\n    if test -n \"$shlibpath_var\"; then\n      echo \"   - add LIBDIR to the \\`$shlibpath_var' environment variable\"\n      echo \"     during execution\"\n    fi\n    if test -n \"$runpath_var\"; then\n      echo \"   - add LIBDIR to the \\`$runpath_var' environment variable\"\n      echo \"     during linking\"\n    fi\n    if test -n \"$hardcode_libdir_flag_spec\"; then\n      libdir=LIBDIR\n      eval \"flag=\\\"$hardcode_libdir_flag_spec\\\"\"\n\n      $ECHO \"   - use the \\`$flag' linker flag\"\n    fi\n    if test -n \"$admincmds\"; then\n      $ECHO \"   - have your system administrator run these commands:$admincmds\"\n    fi\n    if test -f /etc/ld.so.conf; then\n      echo \"   - have your system administrator add LIBDIR to \\`/etc/ld.so.conf'\"\n    fi\n    echo\n\n    echo \"See any operating system documentation about shared libraries for\"\n    case $host in\n      solaris2.[6789]|solaris2.1[0-9])\n        echo \"more information, such as the ld(1), crle(1) and ld.so(8) manual\"\n\techo \"pages.\"\n\t;;\n      *)\n        echo \"more information, such as the ld(1) and ld.so(8) manual pages.\"\n        ;;\n    esac\n    echo \"----------------------------------------------------------------------\"\n    exit $EXIT_SUCCESS\n}\n\ntest \"$mode\" = finish && func_mode_finish ${1+\"$@\"}\n\n\n# func_mode_install arg...\nfunc_mode_install ()\n{\n    $opt_debug\n    # There may be an optional sh(1) argument at the beginning of\n    # install_prog (especially on Windows NT).\n    if test \"$nonopt\" = \"$SHELL\" || test \"$nonopt\" = /bin/sh ||\n       # Allow the use of GNU shtool's install command.\n       case $nonopt in *shtool*) :;; *) false;; esac; then\n      # Aesthetically quote it.\n      func_quote_for_eval \"$nonopt\"\n      install_prog=\"$func_quote_for_eval_result \"\n      arg=$1\n      shift\n    else\n      install_prog=\n      arg=$nonopt\n    fi\n\n    # The real first argument should be the name of the installation program.\n    # Aesthetically quote it.\n    func_quote_for_eval \"$arg\"\n    install_prog=\"$install_prog$func_quote_for_eval_result\"\n    install_shared_prog=$install_prog\n    case \" $install_prog \" in\n      *[\\\\\\ /]cp\\ *) install_cp=: ;;\n      *) install_cp=false ;;\n    esac\n\n    # We need to accept at least all the BSD install flags.\n    dest=\n    files=\n    opts=\n    prev=\n    install_type=\n    isdir=no\n    stripme=\n    no_mode=:\n    for arg\n    do\n      arg2=\n      if test -n \"$dest\"; then\n\tfiles=\"$files $dest\"\n\tdest=$arg\n\tcontinue\n      fi\n\n      case $arg in\n      -d) isdir=yes ;;\n      -f)\n\tif $install_cp; then :; else\n\t  prev=$arg\n\tfi\n\t;;\n      -g | -m | -o)\n\tprev=$arg\n\t;;\n      -s)\n\tstripme=\" -s\"\n\tcontinue\n\t;;\n      -*)\n\t;;\n      *)\n\t# If the previous option needed an argument, then skip it.\n\tif test -n \"$prev\"; then\n\t  if test \"x$prev\" = x-m && test -n \"$install_override_mode\"; then\n\t    arg2=$install_override_mode\n\t    no_mode=false\n\t  fi\n\t  prev=\n\telse\n\t  dest=$arg\n\t  continue\n\tfi\n\t;;\n      esac\n\n      # Aesthetically quote the argument.\n      func_quote_for_eval \"$arg\"\n      install_prog=\"$install_prog $func_quote_for_eval_result\"\n      if test -n \"$arg2\"; then\n\tfunc_quote_for_eval \"$arg2\"\n      fi\n      install_shared_prog=\"$install_shared_prog $func_quote_for_eval_result\"\n    done\n\n    test -z \"$install_prog\" && \\\n      func_fatal_help \"you must specify an install program\"\n\n    test -n \"$prev\" && \\\n      func_fatal_help \"the \\`$prev' option requires an argument\"\n\n    if test -n \"$install_override_mode\" && $no_mode; then\n      if $install_cp; then :; else\n\tfunc_quote_for_eval \"$install_override_mode\"\n\tinstall_shared_prog=\"$install_shared_prog -m $func_quote_for_eval_result\"\n      fi\n    fi\n\n    if test -z \"$files\"; then\n      if test -z \"$dest\"; then\n\tfunc_fatal_help \"no file or destination specified\"\n      else\n\tfunc_fatal_help \"you must specify a destination\"\n      fi\n    fi\n\n    # Strip any trailing slash from the destination.\n    func_stripname '' '/' \"$dest\"\n    dest=$func_stripname_result\n\n    # Check to see that the destination is a directory.\n    test -d \"$dest\" && isdir=yes\n    if test \"$isdir\" = yes; then\n      destdir=\"$dest\"\n      destname=\n    else\n      func_dirname_and_basename \"$dest\" \"\" \".\"\n      destdir=\"$func_dirname_result\"\n      destname=\"$func_basename_result\"\n\n      # Not a directory, so check to see that there is only one file specified.\n      set dummy $files; shift\n      test \"$#\" -gt 1 && \\\n\tfunc_fatal_help \"\\`$dest' is not a directory\"\n    fi\n    case $destdir in\n    [\\\\/]* | [A-Za-z]:[\\\\/]*) ;;\n    *)\n      for file in $files; do\n\tcase $file in\n\t*.lo) ;;\n\t*)\n\t  func_fatal_help \"\\`$destdir' must be an absolute directory name\"\n\t  ;;\n\tesac\n      done\n      ;;\n    esac\n\n    # This variable tells wrapper scripts just to set variables rather\n    # than running their programs.\n    libtool_install_magic=\"$magic\"\n\n    staticlibs=\n    future_libdirs=\n    current_libdirs=\n    for file in $files; do\n\n      # Do each installation.\n      case $file in\n      *.$libext)\n\t# Do the static libraries later.\n\tstaticlibs=\"$staticlibs $file\"\n\t;;\n\n      *.la)\n\t# Check to see that this really is a libtool archive.\n\tfunc_lalib_unsafe_p \"$file\" \\\n\t  || func_fatal_help \"\\`$file' is not a valid libtool archive\"\n\n\tlibrary_names=\n\told_library=\n\trelink_command=\n\tfunc_source \"$file\"\n\n\t# Add the libdir to current_libdirs if it is the destination.\n\tif test \"X$destdir\" = \"X$libdir\"; then\n\t  case \"$current_libdirs \" in\n\t  *\" $libdir \"*) ;;\n\t  *) current_libdirs=\"$current_libdirs $libdir\" ;;\n\t  esac\n\telse\n\t  # Note the libdir as a future libdir.\n\t  case \"$future_libdirs \" in\n\t  *\" $libdir \"*) ;;\n\t  *) future_libdirs=\"$future_libdirs $libdir\" ;;\n\t  esac\n\tfi\n\n\tfunc_dirname \"$file\" \"/\" \"\"\n\tdir=\"$func_dirname_result\"\n\tdir=\"$dir$objdir\"\n\n\tif test -n \"$relink_command\"; then\n\t  # Determine the prefix the user has applied to our future dir.\n\t  inst_prefix_dir=`$ECHO \"$destdir\" | $SED -e \"s%$libdir\\$%%\"`\n\n\t  # Don't allow the user to place us outside of our expected\n\t  # location b/c this prevents finding dependent libraries that\n\t  # are installed to the same prefix.\n\t  # At present, this check doesn't affect windows .dll's that\n\t  # are installed into $libdir/../bin (currently, that works fine)\n\t  # but it's something to keep an eye on.\n\t  test \"$inst_prefix_dir\" = \"$destdir\" && \\\n\t    func_fatal_error \"error: cannot install \\`$file' to a directory not ending in $libdir\"\n\n\t  if test -n \"$inst_prefix_dir\"; then\n\t    # Stick the inst_prefix_dir data into the link command.\n\t    relink_command=`$ECHO \"$relink_command\" | $SED \"s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%\"`\n\t  else\n\t    relink_command=`$ECHO \"$relink_command\" | $SED \"s%@inst_prefix_dir@%%\"`\n\t  fi\n\n\t  func_warning \"relinking \\`$file'\"\n\t  func_show_eval \"$relink_command\" \\\n\t    'func_fatal_error \"error: relink \\`$file'\\'' with the above command before installing it\"'\n\tfi\n\n\t# See the names of the shared library.\n\tset dummy $library_names; shift\n\tif test -n \"$1\"; then\n\t  realname=\"$1\"\n\t  shift\n\n\t  srcname=\"$realname\"\n\t  test -n \"$relink_command\" && srcname=\"$realname\"T\n\n\t  # Install the shared library and build the symlinks.\n\t  func_show_eval \"$install_shared_prog $dir/$srcname $destdir/$realname\" \\\n\t      'exit $?'\n\t  tstripme=\"$stripme\"\n\t  case $host_os in\n\t  cygwin* | mingw* | pw32* | cegcc*)\n\t    case $realname in\n\t    *.dll.a)\n\t      tstripme=\"\"\n\t      ;;\n\t    esac\n\t    ;;\n\t  esac\n\t  if test -n \"$tstripme\" && test -n \"$striplib\"; then\n\t    func_show_eval \"$striplib $destdir/$realname\" 'exit $?'\n\t  fi\n\n\t  if test \"$#\" -gt 0; then\n\t    # Delete the old symlinks, and create new ones.\n\t    # Try `ln -sf' first, because the `ln' binary might depend on\n\t    # the symlink we replace!  Solaris /bin/ln does not understand -f,\n\t    # so we also need to try rm && ln -s.\n\t    for linkname\n\t    do\n\t      test \"$linkname\" != \"$realname\" \\\n\t\t&& func_show_eval \"(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })\"\n\t    done\n\t  fi\n\n\t  # Do each command in the postinstall commands.\n\t  lib=\"$destdir/$realname\"\n\t  func_execute_cmds \"$postinstall_cmds\" 'exit $?'\n\tfi\n\n\t# Install the pseudo-library for information purposes.\n\tfunc_basename \"$file\"\n\tname=\"$func_basename_result\"\n\tinstname=\"$dir/$name\"i\n\tfunc_show_eval \"$install_prog $instname $destdir/$name\" 'exit $?'\n\n\t# Maybe install the static library, too.\n\ttest -n \"$old_library\" && staticlibs=\"$staticlibs $dir/$old_library\"\n\t;;\n\n      *.lo)\n\t# Install (i.e. copy) a libtool object.\n\n\t# Figure out destination file name, if it wasn't already specified.\n\tif test -n \"$destname\"; then\n\t  destfile=\"$destdir/$destname\"\n\telse\n\t  func_basename \"$file\"\n\t  destfile=\"$func_basename_result\"\n\t  destfile=\"$destdir/$destfile\"\n\tfi\n\n\t# Deduce the name of the destination old-style object file.\n\tcase $destfile in\n\t*.lo)\n\t  func_lo2o \"$destfile\"\n\t  staticdest=$func_lo2o_result\n\t  ;;\n\t*.$objext)\n\t  staticdest=\"$destfile\"\n\t  destfile=\n\t  ;;\n\t*)\n\t  func_fatal_help \"cannot copy a libtool object to \\`$destfile'\"\n\t  ;;\n\tesac\n\n\t# Install the libtool object if requested.\n\ttest -n \"$destfile\" && \\\n\t  func_show_eval \"$install_prog $file $destfile\" 'exit $?'\n\n\t# Install the old object if enabled.\n\tif test \"$build_old_libs\" = yes; then\n\t  # Deduce the name of the old-style object file.\n\t  func_lo2o \"$file\"\n\t  staticobj=$func_lo2o_result\n\t  func_show_eval \"$install_prog \\$staticobj \\$staticdest\" 'exit $?'\n\tfi\n\texit $EXIT_SUCCESS\n\t;;\n\n      *)\n\t# Figure out destination file name, if it wasn't already specified.\n\tif test -n \"$destname\"; then\n\t  destfile=\"$destdir/$destname\"\n\telse\n\t  func_basename \"$file\"\n\t  destfile=\"$func_basename_result\"\n\t  destfile=\"$destdir/$destfile\"\n\tfi\n\n\t# If the file is missing, and there is a .exe on the end, strip it\n\t# because it is most likely a libtool script we actually want to\n\t# install\n\tstripped_ext=\"\"\n\tcase $file in\n\t  *.exe)\n\t    if test ! -f \"$file\"; then\n\t      func_stripname '' '.exe' \"$file\"\n\t      file=$func_stripname_result\n\t      stripped_ext=\".exe\"\n\t    fi\n\t    ;;\n\tesac\n\n\t# Do a test to see if this is really a libtool program.\n\tcase $host in\n\t*cygwin* | *mingw*)\n\t    if func_ltwrapper_executable_p \"$file\"; then\n\t      func_ltwrapper_scriptname \"$file\"\n\t      wrapper=$func_ltwrapper_scriptname_result\n\t    else\n\t      func_stripname '' '.exe' \"$file\"\n\t      wrapper=$func_stripname_result\n\t    fi\n\t    ;;\n\t*)\n\t    wrapper=$file\n\t    ;;\n\tesac\n\tif func_ltwrapper_script_p \"$wrapper\"; then\n\t  notinst_deplibs=\n\t  relink_command=\n\n\t  func_source \"$wrapper\"\n\n\t  # Check the variables that should have been set.\n\t  test -z \"$generated_by_libtool_version\" && \\\n\t    func_fatal_error \"invalid libtool wrapper script \\`$wrapper'\"\n\n\t  finalize=yes\n\t  for lib in $notinst_deplibs; do\n\t    # Check to see that each library is installed.\n\t    libdir=\n\t    if test -f \"$lib\"; then\n\t      func_source \"$lib\"\n\t    fi\n\t    libfile=\"$libdir/\"`$ECHO \"$lib\" | $SED 's%^.*/%%g'` ### testsuite: skip nested quoting test\n\t    if test -n \"$libdir\" && test ! -f \"$libfile\"; then\n\t      func_warning \"\\`$lib' has not been installed in \\`$libdir'\"\n\t      finalize=no\n\t    fi\n\t  done\n\n\t  relink_command=\n\t  func_source \"$wrapper\"\n\n\t  outputname=\n\t  if test \"$fast_install\" = no && test -n \"$relink_command\"; then\n\t    $opt_dry_run || {\n\t      if test \"$finalize\" = yes; then\n\t        tmpdir=`func_mktempdir`\n\t\tfunc_basename \"$file$stripped_ext\"\n\t\tfile=\"$func_basename_result\"\n\t        outputname=\"$tmpdir/$file\"\n\t        # Replace the output file specification.\n\t        relink_command=`$ECHO \"$relink_command\" | $SED 's%@OUTPUT@%'\"$outputname\"'%g'`\n\n\t        $opt_silent || {\n\t          func_quote_for_expand \"$relink_command\"\n\t\t  eval \"func_echo $func_quote_for_expand_result\"\n\t        }\n\t        if eval \"$relink_command\"; then :\n\t          else\n\t\t  func_error \"error: relink \\`$file' with the above command before installing it\"\n\t\t  $opt_dry_run || ${RM}r \"$tmpdir\"\n\t\t  continue\n\t        fi\n\t        file=\"$outputname\"\n\t      else\n\t        func_warning \"cannot relink \\`$file'\"\n\t      fi\n\t    }\n\t  else\n\t    # Install the binary that we compiled earlier.\n\t    file=`$ECHO \"$file$stripped_ext\" | $SED \"s%\\([^/]*\\)$%$objdir/\\1%\"`\n\t  fi\n\tfi\n\n\t# remove .exe since cygwin /usr/bin/install will append another\n\t# one anyway\n\tcase $install_prog,$host in\n\t*/usr/bin/install*,*cygwin*)\n\t  case $file:$destfile in\n\t  *.exe:*.exe)\n\t    # this is ok\n\t    ;;\n\t  *.exe:*)\n\t    destfile=$destfile.exe\n\t    ;;\n\t  *:*.exe)\n\t    func_stripname '' '.exe' \"$destfile\"\n\t    destfile=$func_stripname_result\n\t    ;;\n\t  esac\n\t  ;;\n\tesac\n\tfunc_show_eval \"$install_prog\\$stripme \\$file \\$destfile\" 'exit $?'\n\t$opt_dry_run || if test -n \"$outputname\"; then\n\t  ${RM}r \"$tmpdir\"\n\tfi\n\t;;\n      esac\n    done\n\n    for file in $staticlibs; do\n      func_basename \"$file\"\n      name=\"$func_basename_result\"\n\n      # Set up the ranlib parameters.\n      oldlib=\"$destdir/$name\"\n\n      func_show_eval \"$install_prog \\$file \\$oldlib\" 'exit $?'\n\n      if test -n \"$stripme\" && test -n \"$old_striplib\"; then\n\tfunc_show_eval \"$old_striplib $oldlib\" 'exit $?'\n      fi\n\n      # Do each command in the postinstall commands.\n      func_execute_cmds \"$old_postinstall_cmds\" 'exit $?'\n    done\n\n    test -n \"$future_libdirs\" && \\\n      func_warning \"remember to run \\`$progname --finish$future_libdirs'\"\n\n    if test -n \"$current_libdirs\" && $opt_finish; then\n      # Maybe just do a dry run.\n      $opt_dry_run && current_libdirs=\" -n$current_libdirs\"\n      exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs'\n    else\n      exit $EXIT_SUCCESS\n    fi\n}\n\ntest \"$mode\" = install && func_mode_install ${1+\"$@\"}\n\n\n# func_generate_dlsyms outputname originator pic_p\n# Extract symbols from dlprefiles and create ${outputname}S.o with\n# a dlpreopen symbol table.\nfunc_generate_dlsyms ()\n{\n    $opt_debug\n    my_outputname=\"$1\"\n    my_originator=\"$2\"\n    my_pic_p=\"${3-no}\"\n    my_prefix=`$ECHO \"$my_originator\" | sed 's%[^a-zA-Z0-9]%_%g'`\n    my_dlsyms=\n\n    if test -n \"$dlfiles$dlprefiles\" || test \"$dlself\" != no; then\n      if test -n \"$NM\" && test -n \"$global_symbol_pipe\"; then\n\tmy_dlsyms=\"${my_outputname}S.c\"\n      else\n\tfunc_error \"not configured to extract global symbols from dlpreopened files\"\n      fi\n    fi\n\n    if test -n \"$my_dlsyms\"; then\n      case $my_dlsyms in\n      \"\") ;;\n      *.c)\n\t# Discover the nlist of each of the dlfiles.\n\tnlist=\"$output_objdir/${my_outputname}.nm\"\n\n\tfunc_show_eval \"$RM $nlist ${nlist}S ${nlist}T\"\n\n\t# Parse the name list into a source file.\n\tfunc_verbose \"creating $output_objdir/$my_dlsyms\"\n\n\t$opt_dry_run || $ECHO > \"$output_objdir/$my_dlsyms\" \"\\\n/* $my_dlsyms - symbol resolution table for \\`$my_outputname' dlsym emulation. */\n/* Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION */\n\n#ifdef __cplusplus\nextern \\\"C\\\" {\n#endif\n\n#if defined(__GNUC__) && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4))\n#pragma GCC diagnostic ignored \\\"-Wstrict-prototypes\\\"\n#endif\n\n/* External symbol declarations for the compiler. */\\\n\"\n\n\tif test \"$dlself\" = yes; then\n\t  func_verbose \"generating symbol list for \\`$output'\"\n\n\t  $opt_dry_run || echo ': @PROGRAM@ ' > \"$nlist\"\n\n\t  # Add our own program objects to the symbol list.\n\t  progfiles=`$ECHO \"$objs$old_deplibs\" | $SP2NL | $SED \"$lo2o\" | $NL2SP`\n\t  for progfile in $progfiles; do\n\t    func_verbose \"extracting global C symbols from \\`$progfile'\"\n\t    $opt_dry_run || eval \"$NM $progfile | $global_symbol_pipe >> '$nlist'\"\n\t  done\n\n\t  if test -n \"$exclude_expsyms\"; then\n\t    $opt_dry_run || {\n\t      $EGREP -v \" ($exclude_expsyms)$\" \"$nlist\" > \"$nlist\"T\n\t      $MV \"$nlist\"T \"$nlist\"\n\t    }\n\t  fi\n\n\t  if test -n \"$export_symbols_regex\"; then\n\t    $opt_dry_run || {\n\t      $EGREP -e \"$export_symbols_regex\" \"$nlist\" > \"$nlist\"T\n\t      $MV \"$nlist\"T \"$nlist\"\n\t    }\n\t  fi\n\n\t  # Prepare the list of exported symbols\n\t  if test -z \"$export_symbols\"; then\n\t    export_symbols=\"$output_objdir/$outputname.exp\"\n\t    $opt_dry_run || {\n\t      $RM $export_symbols\n\t      ${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \\(.*\\)$/\\1/p' < \"$nlist\" > \"$export_symbols\"\n\t      case $host in\n\t      *cygwin* | *mingw* | *cegcc* )\n                echo EXPORTS > \"$output_objdir/$outputname.def\"\n                cat \"$export_symbols\" >> \"$output_objdir/$outputname.def\"\n\t        ;;\n\t      esac\n\t    }\n\t  else\n\t    $opt_dry_run || {\n\t      ${SED} -e 's/\\([].[*^$]\\)/\\\\\\1/g' -e 's/^/ /' -e 's/$/$/' < \"$export_symbols\" > \"$output_objdir/$outputname.exp\"\n\t      $GREP -f \"$output_objdir/$outputname.exp\" < \"$nlist\" > \"$nlist\"T\n\t      $MV \"$nlist\"T \"$nlist\"\n\t      case $host in\n\t        *cygwin* | *mingw* | *cegcc* )\n\t          echo EXPORTS > \"$output_objdir/$outputname.def\"\n\t          cat \"$nlist\" >> \"$output_objdir/$outputname.def\"\n\t          ;;\n\t      esac\n\t    }\n\t  fi\n\tfi\n\n\tfor dlprefile in $dlprefiles; do\n\t  func_verbose \"extracting global C symbols from \\`$dlprefile'\"\n\t  func_basename \"$dlprefile\"\n\t  name=\"$func_basename_result\"\n\t  $opt_dry_run || {\n\t    $ECHO \": $name \" >> \"$nlist\"\n\t    eval \"$NM $dlprefile 2>/dev/null | $global_symbol_pipe >> '$nlist'\"\n\t  }\n\tdone\n\n\t$opt_dry_run || {\n\t  # Make sure we have at least an empty file.\n\t  test -f \"$nlist\" || : > \"$nlist\"\n\n\t  if test -n \"$exclude_expsyms\"; then\n\t    $EGREP -v \" ($exclude_expsyms)$\" \"$nlist\" > \"$nlist\"T\n\t    $MV \"$nlist\"T \"$nlist\"\n\t  fi\n\n\t  # Try sorting and uniquifying the output.\n\t  if $GREP -v \"^: \" < \"$nlist\" |\n\t      if sort -k 3 </dev/null >/dev/null 2>&1; then\n\t\tsort -k 3\n\t      else\n\t\tsort +2\n\t      fi |\n\t      uniq > \"$nlist\"S; then\n\t    :\n\t  else\n\t    $GREP -v \"^: \" < \"$nlist\" > \"$nlist\"S\n\t  fi\n\n\t  if test -f \"$nlist\"S; then\n\t    eval \"$global_symbol_to_cdecl\"' < \"$nlist\"S >> \"$output_objdir/$my_dlsyms\"'\n\t  else\n\t    echo '/* NONE */' >> \"$output_objdir/$my_dlsyms\"\n\t  fi\n\n\t  echo >> \"$output_objdir/$my_dlsyms\" \"\\\n\n/* The mapping between symbol names and symbols.  */\ntypedef struct {\n  const char *name;\n  void *address;\n} lt_dlsymlist;\n\"\n\t  case $host in\n\t  *cygwin* | *mingw* | *cegcc* )\n\t    echo >> \"$output_objdir/$my_dlsyms\" \"\\\n/* DATA imports from DLLs on WIN32 con't be const, because\n   runtime relocations are performed -- see ld's documentation\n   on pseudo-relocs.  */\"\n\t    lt_dlsym_const= ;;\n\t  *osf5*)\n\t    echo >> \"$output_objdir/$my_dlsyms\" \"\\\n/* This system does not cope well with relocations in const data */\"\n\t    lt_dlsym_const= ;;\n\t  *)\n\t    lt_dlsym_const=const ;;\n\t  esac\n\n\t  echo >> \"$output_objdir/$my_dlsyms\" \"\\\nextern $lt_dlsym_const lt_dlsymlist\nlt_${my_prefix}_LTX_preloaded_symbols[];\n$lt_dlsym_const lt_dlsymlist\nlt_${my_prefix}_LTX_preloaded_symbols[] =\n{\\\n  { \\\"$my_originator\\\", (void *) 0 },\"\n\n\t  case $need_lib_prefix in\n\t  no)\n\t    eval \"$global_symbol_to_c_name_address\" < \"$nlist\" >> \"$output_objdir/$my_dlsyms\"\n\t    ;;\n\t  *)\n\t    eval \"$global_symbol_to_c_name_address_lib_prefix\" < \"$nlist\" >> \"$output_objdir/$my_dlsyms\"\n\t    ;;\n\t  esac\n\t  echo >> \"$output_objdir/$my_dlsyms\" \"\\\n  {0, (void *) 0}\n};\n\n/* This works around a problem in FreeBSD linker */\n#ifdef FREEBSD_WORKAROUND\nstatic const void *lt_preloaded_setup() {\n  return lt_${my_prefix}_LTX_preloaded_symbols;\n}\n#endif\n\n#ifdef __cplusplus\n}\n#endif\\\n\"\n\t} # !$opt_dry_run\n\n\tpic_flag_for_symtable=\n\tcase \"$compile_command \" in\n\t*\" -static \"*) ;;\n\t*)\n\t  case $host in\n\t  # compiling the symbol table file with pic_flag works around\n\t  # a FreeBSD bug that causes programs to crash when -lm is\n\t  # linked before any other PIC object.  But we must not use\n\t  # pic_flag when linking with -static.  The problem exists in\n\t  # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1.\n\t  *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*)\n\t    pic_flag_for_symtable=\" $pic_flag -DFREEBSD_WORKAROUND\" ;;\n\t  *-*-hpux*)\n\t    pic_flag_for_symtable=\" $pic_flag\"  ;;\n\t  *)\n\t    if test \"X$my_pic_p\" != Xno; then\n\t      pic_flag_for_symtable=\" $pic_flag\"\n\t    fi\n\t    ;;\n\t  esac\n\t  ;;\n\tesac\n\tsymtab_cflags=\n\tfor arg in $LTCFLAGS; do\n\t  case $arg in\n\t  -pie | -fpie | -fPIE) ;;\n\t  *) symtab_cflags=\"$symtab_cflags $arg\" ;;\n\t  esac\n\tdone\n\n\t# Now compile the dynamic symbol file.\n\tfunc_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable \"$my_dlsyms\")' 'exit $?'\n\n\t# Clean up the generated files.\n\tfunc_show_eval '$RM \"$output_objdir/$my_dlsyms\" \"$nlist\" \"${nlist}S\" \"${nlist}T\"'\n\n\t# Transform the symbol file into the correct name.\n\tsymfileobj=\"$output_objdir/${my_outputname}S.$objext\"\n\tcase $host in\n\t*cygwin* | *mingw* | *cegcc* )\n\t  if test -f \"$output_objdir/$my_outputname.def\"; then\n\t    compile_command=`$ECHO \"$compile_command\" | $SED \"s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%\"`\n\t    finalize_command=`$ECHO \"$finalize_command\" | $SED \"s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%\"`\n\t  else\n\t    compile_command=`$ECHO \"$compile_command\" | $SED \"s%@SYMFILE@%$symfileobj%\"`\n\t    finalize_command=`$ECHO \"$finalize_command\" | $SED \"s%@SYMFILE@%$symfileobj%\"`\n\t  fi\n\t  ;;\n\t*)\n\t  compile_command=`$ECHO \"$compile_command\" | $SED \"s%@SYMFILE@%$symfileobj%\"`\n\t  finalize_command=`$ECHO \"$finalize_command\" | $SED \"s%@SYMFILE@%$symfileobj%\"`\n\t  ;;\n\tesac\n\t;;\n      *)\n\tfunc_fatal_error \"unknown suffix for \\`$my_dlsyms'\"\n\t;;\n      esac\n    else\n      # We keep going just in case the user didn't refer to\n      # lt_preloaded_symbols.  The linker will fail if global_symbol_pipe\n      # really was required.\n\n      # Nullify the symbol file.\n      compile_command=`$ECHO \"$compile_command\" | $SED \"s% @SYMFILE@%%\"`\n      finalize_command=`$ECHO \"$finalize_command\" | $SED \"s% @SYMFILE@%%\"`\n    fi\n}\n\n# func_win32_libid arg\n# return the library type of file 'arg'\n#\n# Need a lot of goo to handle *both* DLLs and import libs\n# Has to be a shell function in order to 'eat' the argument\n# that is supplied when $file_magic_command is called.\n# Despite the name, also deal with 64 bit binaries.\nfunc_win32_libid ()\n{\n  $opt_debug\n  win32_libid_type=\"unknown\"\n  win32_fileres=`file -L $1 2>/dev/null`\n  case $win32_fileres in\n  *ar\\ archive\\ import\\ library*) # definitely import\n    win32_libid_type=\"x86 archive import\"\n    ;;\n  *ar\\ archive*) # could be an import, or static\n    if $OBJDUMP -f \"$1\" | $SED -e '10q' 2>/dev/null |\n       $EGREP 'file format (pe-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then\n      win32_nmres=`$NM -f posix -A \"$1\" |\n\t$SED -n -e '\n\t    1,100{\n\t\t/ I /{\n\t\t    s,.*,import,\n\t\t    p\n\t\t    q\n\t\t}\n\t    }'`\n      case $win32_nmres in\n      import*)  win32_libid_type=\"x86 archive import\";;\n      *)        win32_libid_type=\"x86 archive static\";;\n      esac\n    fi\n    ;;\n  *DLL*)\n    win32_libid_type=\"x86 DLL\"\n    ;;\n  *executable*) # but shell scripts are \"executable\" too...\n    case $win32_fileres in\n    *MS\\ Windows\\ PE\\ Intel*)\n      win32_libid_type=\"x86 DLL\"\n      ;;\n    esac\n    ;;\n  esac\n  $ECHO \"$win32_libid_type\"\n}\n\n\n\n# func_extract_an_archive dir oldlib\nfunc_extract_an_archive ()\n{\n    $opt_debug\n    f_ex_an_ar_dir=\"$1\"; shift\n    f_ex_an_ar_oldlib=\"$1\"\n    if test \"$lock_old_archive_extraction\" = yes; then\n      lockfile=$f_ex_an_ar_oldlib.lock\n      until $opt_dry_run || ln \"$progpath\" \"$lockfile\" 2>/dev/null; do\n\tfunc_echo \"Waiting for $lockfile to be removed\"\n\tsleep 2\n      done\n    fi\n    func_show_eval \"(cd \\$f_ex_an_ar_dir && $AR x \\\"\\$f_ex_an_ar_oldlib\\\")\" \\\n\t\t   'stat=$?; rm -f \"$lockfile\"; exit $stat'\n    if test \"$lock_old_archive_extraction\" = yes; then\n      $opt_dry_run || rm -f \"$lockfile\"\n    fi\n    if ($AR t \"$f_ex_an_ar_oldlib\" | sort | sort -uc >/dev/null 2>&1); then\n     :\n    else\n      func_fatal_error \"object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib\"\n    fi\n}\n\n\n# func_extract_archives gentop oldlib ...\nfunc_extract_archives ()\n{\n    $opt_debug\n    my_gentop=\"$1\"; shift\n    my_oldlibs=${1+\"$@\"}\n    my_oldobjs=\"\"\n    my_xlib=\"\"\n    my_xabs=\"\"\n    my_xdir=\"\"\n\n    for my_xlib in $my_oldlibs; do\n      # Extract the objects.\n      case $my_xlib in\n\t[\\\\/]* | [A-Za-z]:[\\\\/]*) my_xabs=\"$my_xlib\" ;;\n\t*) my_xabs=`pwd`\"/$my_xlib\" ;;\n      esac\n      func_basename \"$my_xlib\"\n      my_xlib=\"$func_basename_result\"\n      my_xlib_u=$my_xlib\n      while :; do\n        case \" $extracted_archives \" in\n\t*\" $my_xlib_u \"*)\n\t  func_arith $extracted_serial + 1\n\t  extracted_serial=$func_arith_result\n\t  my_xlib_u=lt$extracted_serial-$my_xlib ;;\n\t*) break ;;\n\tesac\n      done\n      extracted_archives=\"$extracted_archives $my_xlib_u\"\n      my_xdir=\"$my_gentop/$my_xlib_u\"\n\n      func_mkdir_p \"$my_xdir\"\n\n      case $host in\n      *-darwin*)\n\tfunc_verbose \"Extracting $my_xabs\"\n\t# Do not bother doing anything if just a dry run\n\t$opt_dry_run || {\n\t  darwin_orig_dir=`pwd`\n\t  cd $my_xdir || exit $?\n\t  darwin_archive=$my_xabs\n\t  darwin_curdir=`pwd`\n\t  darwin_base_archive=`basename \"$darwin_archive\"`\n\t  darwin_arches=`$LIPO -info \"$darwin_archive\" 2>/dev/null | $GREP Architectures 2>/dev/null || true`\n\t  if test -n \"$darwin_arches\"; then\n\t    darwin_arches=`$ECHO \"$darwin_arches\" | $SED -e 's/.*are://'`\n\t    darwin_arch=\n\t    func_verbose \"$darwin_base_archive has multiple architectures $darwin_arches\"\n\t    for darwin_arch in  $darwin_arches ; do\n\t      func_mkdir_p \"unfat-$$/${darwin_base_archive}-${darwin_arch}\"\n\t      $LIPO -thin $darwin_arch -output \"unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}\" \"${darwin_archive}\"\n\t      cd \"unfat-$$/${darwin_base_archive}-${darwin_arch}\"\n\t      func_extract_an_archive \"`pwd`\" \"${darwin_base_archive}\"\n\t      cd \"$darwin_curdir\"\n\t      $RM \"unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}\"\n\t    done # $darwin_arches\n            ## Okay now we've a bunch of thin objects, gotta fatten them up :)\n\t    darwin_filelist=`find unfat-$$ -type f -name \\*.o -print -o -name \\*.lo -print | $SED -e \"$basename\" | sort -u`\n\t    darwin_file=\n\t    darwin_files=\n\t    for darwin_file in $darwin_filelist; do\n\t      darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP`\n\t      $LIPO -create -output \"$darwin_file\" $darwin_files\n\t    done # $darwin_filelist\n\t    $RM -rf unfat-$$\n\t    cd \"$darwin_orig_dir\"\n\t  else\n\t    cd $darwin_orig_dir\n\t    func_extract_an_archive \"$my_xdir\" \"$my_xabs\"\n\t  fi # $darwin_arches\n\t} # !$opt_dry_run\n\t;;\n      *)\n        func_extract_an_archive \"$my_xdir\" \"$my_xabs\"\n\t;;\n      esac\n      my_oldobjs=\"$my_oldobjs \"`find $my_xdir -name \\*.$objext -print -o -name \\*.lo -print | sort | $NL2SP`\n    done\n\n    func_extract_archives_result=\"$my_oldobjs\"\n}\n\n\n# func_emit_wrapper [arg=no]\n#\n# Emit a libtool wrapper script on stdout.\n# Don't directly open a file because we may want to\n# incorporate the script contents within a cygwin/mingw\n# wrapper executable.  Must ONLY be called from within\n# func_mode_link because it depends on a number of variables\n# set therein.\n#\n# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\n# variable will take.  If 'yes', then the emitted script\n# will assume that the directory in which it is stored is\n# the $objdir directory.  This is a cygwin/mingw-specific\n# behavior.\nfunc_emit_wrapper ()\n{\n\tfunc_emit_wrapper_arg1=${1-no}\n\n\t$ECHO \"\\\n#! $SHELL\n\n# $output - temporary wrapper script for $objdir/$outputname\n# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION\n#\n# The $output program cannot be directly executed until all the libtool\n# libraries that it depends on are installed.\n#\n# This wrapper script should never be moved out of the build directory.\n# If it is, it will not operate correctly.\n\n# Sed substitution that helps us do robust quoting.  It backslashifies\n# metacharacters that are still active within double-quoted strings.\nsed_quote_subst='$sed_quote_subst'\n\n# Be Bourne compatible\nif test -n \\\"\\${ZSH_VERSION+set}\\\" && (emulate sh) >/dev/null 2>&1; then\n  emulate sh\n  NULLCMD=:\n  # Zsh 3.x and 4.x performs word splitting on \\${1+\\\"\\$@\\\"}, which\n  # is contrary to our usage.  Disable this feature.\n  alias -g '\\${1+\\\"\\$@\\\"}'='\\\"\\$@\\\"'\n  setopt NO_GLOB_SUBST\nelse\n  case \\`(set -o) 2>/dev/null\\` in *posix*) set -o posix;; esac\nfi\nBIN_SH=xpg4; export BIN_SH # for Tru64\nDUALCASE=1; export DUALCASE # for MKS sh\n\n# The HP-UX ksh and POSIX shell print the target directory to stdout\n# if CDPATH is set.\n(unset CDPATH) >/dev/null 2>&1 && unset CDPATH\n\nrelink_command=\\\"$relink_command\\\"\n\n# This environment variable determines our operation mode.\nif test \\\"\\$libtool_install_magic\\\" = \\\"$magic\\\"; then\n  # install mode needs the following variables:\n  generated_by_libtool_version='$macro_version'\n  notinst_deplibs='$notinst_deplibs'\nelse\n  # When we are sourced in execute mode, \\$file and \\$ECHO are already set.\n  if test \\\"\\$libtool_execute_magic\\\" != \\\"$magic\\\"; then\n    file=\\\"\\$0\\\"\"\n\n    qECHO=`$ECHO \"$ECHO\" | $SED \"$sed_quote_subst\"`\n    $ECHO \"\\\n\n# A function that is used when there is no print builtin or printf.\nfunc_fallback_echo ()\n{\n  eval 'cat <<_LTECHO_EOF\n\\$1\n_LTECHO_EOF'\n}\n    ECHO=\\\"$qECHO\\\"\n  fi\\\n\n  # Find the directory that this script lives in.\n  thisdir=\\`\\$ECHO \\\"\\$file\\\" | $SED 's%/[^/]*$%%'\\`\n  test \\\"x\\$thisdir\\\" = \\\"x\\$file\\\" && thisdir=.\n\n  # Follow symbolic links until we get to the real thisdir.\n  file=\\`ls -ld \\\"\\$file\\\" | $SED -n 's/.*-> //p'\\`\n  while test -n \\\"\\$file\\\"; do\n    destdir=\\`\\$ECHO \\\"\\$file\\\" | $SED 's%/[^/]*\\$%%'\\`\n\n    # If there was a directory component, then change thisdir.\n    if test \\\"x\\$destdir\\\" != \\\"x\\$file\\\"; then\n      case \\\"\\$destdir\\\" in\n      [\\\\\\\\/]* | [A-Za-z]:[\\\\\\\\/]*) thisdir=\\\"\\$destdir\\\" ;;\n      *) thisdir=\\\"\\$thisdir/\\$destdir\\\" ;;\n      esac\n    fi\n\n    file=\\`\\$ECHO \\\"\\$file\\\" | $SED 's%^.*/%%'\\`\n    file=\\`ls -ld \\\"\\$thisdir/\\$file\\\" | $SED -n 's/.*-> //p'\\`\n  done\n\n  # Usually 'no', except on cygwin/mingw when embedded into\n  # the cwrapper.\n  WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1\n  if test \\\"\\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\\\" = \\\"yes\\\"; then\n    # special case for '.'\n    if test \\\"\\$thisdir\\\" = \\\".\\\"; then\n      thisdir=\\`pwd\\`\n    fi\n    # remove .libs from thisdir\n    case \\\"\\$thisdir\\\" in\n    *[\\\\\\\\/]$objdir ) thisdir=\\`\\$ECHO \\\"\\$thisdir\\\" | $SED 's%[\\\\\\\\/][^\\\\\\\\/]*$%%'\\` ;;\n    $objdir )   thisdir=. ;;\n    esac\n  fi\n\n  # Try to get the absolute directory name.\n  absdir=\\`cd \\\"\\$thisdir\\\" && pwd\\`\n  test -n \\\"\\$absdir\\\" && thisdir=\\\"\\$absdir\\\"\n\"\n\n\tif test \"$fast_install\" = yes; then\n\t  $ECHO \"\\\n  program=lt-'$outputname'$exeext\n  progdir=\\\"\\$thisdir/$objdir\\\"\n\n  if test ! -f \\\"\\$progdir/\\$program\\\" ||\n     { file=\\`ls -1dt \\\"\\$progdir/\\$program\\\" \\\"\\$progdir/../\\$program\\\" 2>/dev/null | ${SED} 1q\\`; \\\\\n       test \\\"X\\$file\\\" != \\\"X\\$progdir/\\$program\\\"; }; then\n\n    file=\\\"\\$\\$-\\$program\\\"\n\n    if test ! -d \\\"\\$progdir\\\"; then\n      $MKDIR \\\"\\$progdir\\\"\n    else\n      $RM \\\"\\$progdir/\\$file\\\"\n    fi\"\n\n\t  $ECHO \"\\\n\n    # relink executable if necessary\n    if test -n \\\"\\$relink_command\\\"; then\n      if relink_command_output=\\`eval \\\"\\$relink_command\\\" 2>&1\\`; then :\n      else\n\t$ECHO \\\"\\$relink_command_output\\\" >&2\n\t$RM \\\"\\$progdir/\\$file\\\"\n\texit 1\n      fi\n    fi\n\n    $MV \\\"\\$progdir/\\$file\\\" \\\"\\$progdir/\\$program\\\" 2>/dev/null ||\n    { $RM \\\"\\$progdir/\\$program\\\";\n      $MV \\\"\\$progdir/\\$file\\\" \\\"\\$progdir/\\$program\\\"; }\n    $RM \\\"\\$progdir/\\$file\\\"\n  fi\"\n\telse\n\t  $ECHO \"\\\n  program='$outputname'\n  progdir=\\\"\\$thisdir/$objdir\\\"\n\"\n\tfi\n\n\t$ECHO \"\\\n\n  if test -f \\\"\\$progdir/\\$program\\\"; then\"\n\n\t# Export our shlibpath_var if we have one.\n\tif test \"$shlibpath_overrides_runpath\" = yes && test -n \"$shlibpath_var\" && test -n \"$temp_rpath\"; then\n\t  $ECHO \"\\\n    # Add our own library path to $shlibpath_var\n    $shlibpath_var=\\\"$temp_rpath\\$$shlibpath_var\\\"\n\n    # Some systems cannot cope with colon-terminated $shlibpath_var\n    # The second colon is a workaround for a bug in BeOS R4 sed\n    $shlibpath_var=\\`\\$ECHO \\\"\\$$shlibpath_var\\\" | $SED 's/::*\\$//'\\`\n\n    export $shlibpath_var\n\"\n\tfi\n\n\t# fixup the dll searchpath if we need to.\n\tif test -n \"$dllsearchpath\"; then\n\t  $ECHO \"\\\n    # Add the dll search path components to the executable PATH\n    PATH=$dllsearchpath:\\$PATH\n\"\n\tfi\n\n\t$ECHO \"\\\n    if test \\\"\\$libtool_execute_magic\\\" != \\\"$magic\\\"; then\n      # Run the actual program with our arguments.\n\"\n\tcase $host in\n\t# Backslashes separate directories on plain windows\n\t*-*-mingw | *-*-os2* | *-cegcc*)\n\t  $ECHO \"\\\n      exec \\\"\\$progdir\\\\\\\\\\$program\\\" \\${1+\\\"\\$@\\\"}\n\"\n\t  ;;\n\n\t*)\n\t  $ECHO \"\\\n      exec \\\"\\$progdir/\\$program\\\" \\${1+\\\"\\$@\\\"}\n\"\n\t  ;;\n\tesac\n\t$ECHO \"\\\n      \\$ECHO \\\"\\$0: cannot exec \\$program \\$*\\\" 1>&2\n      exit 1\n    fi\n  else\n    # The program doesn't exist.\n    \\$ECHO \\\"\\$0: error: \\\\\\`\\$progdir/\\$program' does not exist\\\" 1>&2\n    \\$ECHO \\\"This script is just a wrapper for \\$program.\\\" 1>&2\n    \\$ECHO \\\"See the $PACKAGE documentation for more information.\\\" 1>&2\n    exit 1\n  fi\nfi\\\n\"\n}\n\n\n# func_to_host_path arg\n#\n# Convert paths to host format when used with build tools.\n# Intended for use with \"native\" mingw (where libtool itself\n# is running under the msys shell), or in the following cross-\n# build environments:\n#    $build          $host\n#    mingw (msys)    mingw  [e.g. native]\n#    cygwin          mingw\n#    *nix + wine     mingw\n# where wine is equipped with the `winepath' executable.\n# In the native mingw case, the (msys) shell automatically\n# converts paths for any non-msys applications it launches,\n# but that facility isn't available from inside the cwrapper.\n# Similar accommodations are necessary for $host mingw and\n# $build cygwin.  Calling this function does no harm for other\n# $host/$build combinations not listed above.\n#\n# ARG is the path (on $build) that should be converted to\n# the proper representation for $host. The result is stored\n# in $func_to_host_path_result.\nfunc_to_host_path ()\n{\n  func_to_host_path_result=\"$1\"\n  if test -n \"$1\"; then\n    case $host in\n      *mingw* )\n        lt_sed_naive_backslashify='s|\\\\\\\\*|\\\\|g;s|/|\\\\|g;s|\\\\|\\\\\\\\|g'\n        case $build in\n          *mingw* ) # actually, msys\n            # awkward: cmd appends spaces to result\n            func_to_host_path_result=`( cmd //c echo \"$1\" ) 2>/dev/null |\n              $SED -e 's/[ ]*$//' -e \"$lt_sed_naive_backslashify\"`\n            ;;\n          *cygwin* )\n            func_to_host_path_result=`cygpath -w \"$1\" |\n\t      $SED -e \"$lt_sed_naive_backslashify\"`\n            ;;\n          * )\n            # Unfortunately, winepath does not exit with a non-zero\n            # error code, so we are forced to check the contents of\n            # stdout. On the other hand, if the command is not\n            # found, the shell will set an exit code of 127 and print\n            # *an error message* to stdout. So we must check for both\n            # error code of zero AND non-empty stdout, which explains\n            # the odd construction:\n            func_to_host_path_tmp1=`winepath -w \"$1\" 2>/dev/null`\n            if test \"$?\" -eq 0 && test -n \"${func_to_host_path_tmp1}\"; then\n              func_to_host_path_result=`$ECHO \"$func_to_host_path_tmp1\" |\n                $SED -e \"$lt_sed_naive_backslashify\"`\n            else\n              # Allow warning below.\n              func_to_host_path_result=\n            fi\n            ;;\n        esac\n        if test -z \"$func_to_host_path_result\" ; then\n          func_error \"Could not determine host path corresponding to\"\n          func_error \"  \\`$1'\"\n          func_error \"Continuing, but uninstalled executables may not work.\"\n          # Fallback:\n          func_to_host_path_result=\"$1\"\n        fi\n        ;;\n    esac\n  fi\n}\n# end: func_to_host_path\n\n# func_to_host_pathlist arg\n#\n# Convert pathlists to host format when used with build tools.\n# See func_to_host_path(), above. This function supports the\n# following $build/$host combinations (but does no harm for\n# combinations not listed here):\n#    $build          $host\n#    mingw (msys)    mingw  [e.g. native]\n#    cygwin          mingw\n#    *nix + wine     mingw\n#\n# Path separators are also converted from $build format to\n# $host format. If ARG begins or ends with a path separator\n# character, it is preserved (but converted to $host format)\n# on output.\n#\n# ARG is a pathlist (on $build) that should be converted to\n# the proper representation on $host. The result is stored\n# in $func_to_host_pathlist_result.\nfunc_to_host_pathlist ()\n{\n  func_to_host_pathlist_result=\"$1\"\n  if test -n \"$1\"; then\n    case $host in\n      *mingw* )\n        lt_sed_naive_backslashify='s|\\\\\\\\*|\\\\|g;s|/|\\\\|g;s|\\\\|\\\\\\\\|g'\n        # Remove leading and trailing path separator characters from\n        # ARG. msys behavior is inconsistent here, cygpath turns them\n        # into '.;' and ';.', and winepath ignores them completely.\n\tfunc_stripname : : \"$1\"\n        func_to_host_pathlist_tmp1=$func_stripname_result\n        case $build in\n          *mingw* ) # Actually, msys.\n            # Awkward: cmd appends spaces to result.\n            func_to_host_pathlist_result=`\n\t      ( cmd //c echo \"$func_to_host_pathlist_tmp1\" ) 2>/dev/null |\n\t      $SED -e 's/[ ]*$//' -e \"$lt_sed_naive_backslashify\"`\n            ;;\n          *cygwin* )\n            func_to_host_pathlist_result=`cygpath -w -p \"$func_to_host_pathlist_tmp1\" |\n              $SED -e \"$lt_sed_naive_backslashify\"`\n            ;;\n          * )\n            # unfortunately, winepath doesn't convert pathlists\n            func_to_host_pathlist_result=\"\"\n            func_to_host_pathlist_oldIFS=$IFS\n            IFS=:\n            for func_to_host_pathlist_f in $func_to_host_pathlist_tmp1 ; do\n              IFS=$func_to_host_pathlist_oldIFS\n              if test -n \"$func_to_host_pathlist_f\" ; then\n                func_to_host_path \"$func_to_host_pathlist_f\"\n                if test -n \"$func_to_host_path_result\" ; then\n                  if test -z \"$func_to_host_pathlist_result\" ; then\n                    func_to_host_pathlist_result=\"$func_to_host_path_result\"\n                  else\n                    func_append func_to_host_pathlist_result \";$func_to_host_path_result\"\n                  fi\n                fi\n              fi\n            done\n            IFS=$func_to_host_pathlist_oldIFS\n            ;;\n        esac\n        if test -z \"$func_to_host_pathlist_result\"; then\n          func_error \"Could not determine the host path(s) corresponding to\"\n          func_error \"  \\`$1'\"\n          func_error \"Continuing, but uninstalled executables may not work.\"\n          # Fallback. This may break if $1 contains DOS-style drive\n          # specifications. The fix is not to complicate the expression\n          # below, but for the user to provide a working wine installation\n          # with winepath so that path translation in the cross-to-mingw\n          # case works properly.\n          lt_replace_pathsep_nix_to_dos=\"s|:|;|g\"\n          func_to_host_pathlist_result=`echo \"$func_to_host_pathlist_tmp1\" |\\\n            $SED -e \"$lt_replace_pathsep_nix_to_dos\"`\n        fi\n        # Now, add the leading and trailing path separators back\n        case \"$1\" in\n          :* ) func_to_host_pathlist_result=\";$func_to_host_pathlist_result\"\n            ;;\n        esac\n        case \"$1\" in\n          *: ) func_append func_to_host_pathlist_result \";\"\n            ;;\n        esac\n        ;;\n    esac\n  fi\n}\n# end: func_to_host_pathlist\n\n# func_emit_cwrapperexe_src\n# emit the source code for a wrapper executable on stdout\n# Must ONLY be called from within func_mode_link because\n# it depends on a number of variable set therein.\nfunc_emit_cwrapperexe_src ()\n{\n\tcat <<EOF\n\n/* $cwrappersource - temporary wrapper executable for $objdir/$outputname\n   Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION\n\n   The $output program cannot be directly executed until all the libtool\n   libraries that it depends on are installed.\n\n   This wrapper executable should never be moved out of the build directory.\n   If it is, it will not operate correctly.\n\n   Currently, it simply execs the wrapper *script* \"$SHELL $output\",\n   but could eventually absorb all of the scripts functionality and\n   exec $objdir/$outputname directly.\n*/\nEOF\n\t    cat <<\"EOF\"\n#ifdef _MSC_VER\n# define _CRT_SECURE_NO_DEPRECATE 1\n#endif\n#include <stdio.h>\n#include <stdlib.h>\n#ifdef _MSC_VER\n# include <direct.h>\n# include <process.h>\n# include <io.h>\n#else\n# include <unistd.h>\n# include <stdint.h>\n# ifdef __CYGWIN__\n#  include <io.h>\n# endif\n#endif\n#include <malloc.h>\n#include <stdarg.h>\n#include <assert.h>\n#include <string.h>\n#include <ctype.h>\n#include <errno.h>\n#include <fcntl.h>\n#include <sys/stat.h>\n\n/* declarations of non-ANSI functions */\n#if defined(__MINGW32__)\n# ifdef __STRICT_ANSI__\nint _putenv (const char *);\n# endif\n#elif defined(__CYGWIN__)\n# ifdef __STRICT_ANSI__\nchar *realpath (const char *, char *);\nint putenv (char *);\nint setenv (const char *, const char *, int);\n# endif\n/* #elif defined (other platforms) ... */\n#endif\n\n/* portability defines, excluding path handling macros */\n#if defined(_MSC_VER)\n# define setmode _setmode\n# define stat    _stat\n# define chmod   _chmod\n# define getcwd  _getcwd\n# define putenv  _putenv\n# define S_IXUSR _S_IEXEC\n# ifndef _INTPTR_T_DEFINED\n#  define _INTPTR_T_DEFINED\n#  define intptr_t int\n# endif\n#elif defined(__MINGW32__)\n# define setmode _setmode\n# define stat    _stat\n# define chmod   _chmod\n# define getcwd  _getcwd\n# define putenv  _putenv\n#elif defined(__CYGWIN__)\n# define HAVE_SETENV\n# define FOPEN_WB \"wb\"\n/* #elif defined (other platforms) ... */\n#endif\n\n#if defined(PATH_MAX)\n# define LT_PATHMAX PATH_MAX\n#elif defined(MAXPATHLEN)\n# define LT_PATHMAX MAXPATHLEN\n#else\n# define LT_PATHMAX 1024\n#endif\n\n#ifndef S_IXOTH\n# define S_IXOTH 0\n#endif\n#ifndef S_IXGRP\n# define S_IXGRP 0\n#endif\n\n/* path handling portability macros */\n#ifndef DIR_SEPARATOR\n# define DIR_SEPARATOR '/'\n# define PATH_SEPARATOR ':'\n#endif\n\n#if (defined (_WIN32) && ! defined(__CYGWIN__)) || defined (__MSDOS__) || \\\n  defined (__DJGPP__) || defined (__OS2__)\n# define HAVE_DOS_BASED_FILE_SYSTEM\n# define FOPEN_WB \"wb\"\n# ifndef DIR_SEPARATOR_2\n#  define DIR_SEPARATOR_2 '\\\\'\n# endif\n# ifndef PATH_SEPARATOR_2\n#  define PATH_SEPARATOR_2 ';'\n# endif\n#endif\n\n#ifndef DIR_SEPARATOR_2\n# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR)\n#else /* DIR_SEPARATOR_2 */\n# define IS_DIR_SEPARATOR(ch) \\\n\t(((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2))\n#endif /* DIR_SEPARATOR_2 */\n\n#ifndef PATH_SEPARATOR_2\n# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR)\n#else /* PATH_SEPARATOR_2 */\n# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2)\n#endif /* PATH_SEPARATOR_2 */\n\n#ifndef FOPEN_WB\n# define FOPEN_WB \"w\"\n#endif\n#ifndef _O_BINARY\n# define _O_BINARY 0\n#endif\n\n#define XMALLOC(type, num)      ((type *) xmalloc ((num) * sizeof(type)))\n#define XFREE(stale) do { \\\n  if (stale) { free ((void *) stale); stale = 0; } \\\n} while (0)\n\n#undef LTWRAPPER_DEBUGPRINTF\n#if defined LT_DEBUGWRAPPER\n# define LTWRAPPER_DEBUGPRINTF(args) ltwrapper_debugprintf args\nstatic void\nltwrapper_debugprintf (const char *fmt, ...)\n{\n    va_list args;\n    va_start (args, fmt);\n    (void) vfprintf (stderr, fmt, args);\n    va_end (args);\n}\n#else\n# define LTWRAPPER_DEBUGPRINTF(args)\n#endif\n\nconst char *program_name = NULL;\n\nvoid *xmalloc (size_t num);\nchar *xstrdup (const char *string);\nconst char *base_name (const char *name);\nchar *find_executable (const char *wrapper);\nchar *chase_symlinks (const char *pathspec);\nint make_executable (const char *path);\nint check_executable (const char *path);\nchar *strendzap (char *str, const char *pat);\nvoid lt_fatal (const char *message, ...);\nvoid lt_setenv (const char *name, const char *value);\nchar *lt_extend_str (const char *orig_value, const char *add, int to_end);\nvoid lt_update_exe_path (const char *name, const char *value);\nvoid lt_update_lib_path (const char *name, const char *value);\nchar **prepare_spawn (char **argv);\nvoid lt_dump_script (FILE *f);\nEOF\n\n\t    cat <<EOF\nconst char * MAGIC_EXE = \"$magic_exe\";\nconst char * LIB_PATH_VARNAME = \"$shlibpath_var\";\nEOF\n\n\t    if test \"$shlibpath_overrides_runpath\" = yes && test -n \"$shlibpath_var\" && test -n \"$temp_rpath\"; then\n              func_to_host_pathlist \"$temp_rpath\"\n\t      cat <<EOF\nconst char * LIB_PATH_VALUE   = \"$func_to_host_pathlist_result\";\nEOF\n\t    else\n\t      cat <<\"EOF\"\nconst char * LIB_PATH_VALUE   = \"\";\nEOF\n\t    fi\n\n\t    if test -n \"$dllsearchpath\"; then\n              func_to_host_pathlist \"$dllsearchpath:\"\n\t      cat <<EOF\nconst char * EXE_PATH_VARNAME = \"PATH\";\nconst char * EXE_PATH_VALUE   = \"$func_to_host_pathlist_result\";\nEOF\n\t    else\n\t      cat <<\"EOF\"\nconst char * EXE_PATH_VARNAME = \"\";\nconst char * EXE_PATH_VALUE   = \"\";\nEOF\n\t    fi\n\n\t    if test \"$fast_install\" = yes; then\n\t      cat <<EOF\nconst char * TARGET_PROGRAM_NAME = \"lt-$outputname\"; /* hopefully, no .exe */\nEOF\n\t    else\n\t      cat <<EOF\nconst char * TARGET_PROGRAM_NAME = \"$outputname\"; /* hopefully, no .exe */\nEOF\n\t    fi\n\n\n\t    cat <<\"EOF\"\n\n#define LTWRAPPER_OPTION_PREFIX         \"--lt-\"\n#define LTWRAPPER_OPTION_PREFIX_LENGTH  5\n\nstatic const size_t opt_prefix_len         = LTWRAPPER_OPTION_PREFIX_LENGTH;\nstatic const char *ltwrapper_option_prefix = LTWRAPPER_OPTION_PREFIX;\n\nstatic const char *dumpscript_opt       = LTWRAPPER_OPTION_PREFIX \"dump-script\";\n\nint\nmain (int argc, char *argv[])\n{\n  char **newargz;\n  int  newargc;\n  char *tmp_pathspec;\n  char *actual_cwrapper_path;\n  char *actual_cwrapper_name;\n  char *target_name;\n  char *lt_argv_zero;\n  intptr_t rval = 127;\n\n  int i;\n\n  program_name = (char *) xstrdup (base_name (argv[0]));\n  LTWRAPPER_DEBUGPRINTF ((\"(main) argv[0]      : %s\\n\", argv[0]));\n  LTWRAPPER_DEBUGPRINTF ((\"(main) program_name : %s\\n\", program_name));\n\n  /* very simple arg parsing; don't want to rely on getopt */\n  for (i = 1; i < argc; i++)\n    {\n      if (strcmp (argv[i], dumpscript_opt) == 0)\n\t{\nEOF\n\t    case \"$host\" in\n\t      *mingw* | *cygwin* )\n\t\t# make stdout use \"unix\" line endings\n\t\techo \"          setmode(1,_O_BINARY);\"\n\t\t;;\n\t      esac\n\n\t    cat <<\"EOF\"\n\t  lt_dump_script (stdout);\n\t  return 0;\n\t}\n    }\n\n  newargz = XMALLOC (char *, argc + 1);\n  tmp_pathspec = find_executable (argv[0]);\n  if (tmp_pathspec == NULL)\n    lt_fatal (\"Couldn't find %s\", argv[0]);\n  LTWRAPPER_DEBUGPRINTF ((\"(main) found exe (before symlink chase) at : %s\\n\",\n\t\t\t  tmp_pathspec));\n\n  actual_cwrapper_path = chase_symlinks (tmp_pathspec);\n  LTWRAPPER_DEBUGPRINTF ((\"(main) found exe (after symlink chase) at : %s\\n\",\n\t\t\t  actual_cwrapper_path));\n  XFREE (tmp_pathspec);\n\n  actual_cwrapper_name = xstrdup( base_name (actual_cwrapper_path));\n  strendzap (actual_cwrapper_path, actual_cwrapper_name);\n\n  /* wrapper name transforms */\n  strendzap (actual_cwrapper_name, \".exe\");\n  tmp_pathspec = lt_extend_str (actual_cwrapper_name, \".exe\", 1);\n  XFREE (actual_cwrapper_name);\n  actual_cwrapper_name = tmp_pathspec;\n  tmp_pathspec = 0;\n\n  /* target_name transforms -- use actual target program name; might have lt- prefix */\n  target_name = xstrdup (base_name (TARGET_PROGRAM_NAME));\n  strendzap (target_name, \".exe\");\n  tmp_pathspec = lt_extend_str (target_name, \".exe\", 1);\n  XFREE (target_name);\n  target_name = tmp_pathspec;\n  tmp_pathspec = 0;\n\n  LTWRAPPER_DEBUGPRINTF ((\"(main) libtool target name: %s\\n\",\n\t\t\t  target_name));\nEOF\n\n\t    cat <<EOF\n  newargz[0] =\n    XMALLOC (char, (strlen (actual_cwrapper_path) +\n\t\t    strlen (\"$objdir\") + 1 + strlen (actual_cwrapper_name) + 1));\n  strcpy (newargz[0], actual_cwrapper_path);\n  strcat (newargz[0], \"$objdir\");\n  strcat (newargz[0], \"/\");\nEOF\n\n\t    cat <<\"EOF\"\n  /* stop here, and copy so we don't have to do this twice */\n  tmp_pathspec = xstrdup (newargz[0]);\n\n  /* do NOT want the lt- prefix here, so use actual_cwrapper_name */\n  strcat (newargz[0], actual_cwrapper_name);\n\n  /* DO want the lt- prefix here if it exists, so use target_name */\n  lt_argv_zero = lt_extend_str (tmp_pathspec, target_name, 1);\n  XFREE (tmp_pathspec);\n  tmp_pathspec = NULL;\nEOF\n\n\t    case $host_os in\n\t      mingw*)\n\t    cat <<\"EOF\"\n  {\n    char* p;\n    while ((p = strchr (newargz[0], '\\\\')) != NULL)\n      {\n\t*p = '/';\n      }\n    while ((p = strchr (lt_argv_zero, '\\\\')) != NULL)\n      {\n\t*p = '/';\n      }\n  }\nEOF\n\t    ;;\n\t    esac\n\n\t    cat <<\"EOF\"\n  XFREE (target_name);\n  XFREE (actual_cwrapper_path);\n  XFREE (actual_cwrapper_name);\n\n  lt_setenv (\"BIN_SH\", \"xpg4\"); /* for Tru64 */\n  lt_setenv (\"DUALCASE\", \"1\");  /* for MSK sh */\n  lt_update_lib_path (LIB_PATH_VARNAME, LIB_PATH_VALUE);\n  lt_update_exe_path (EXE_PATH_VARNAME, EXE_PATH_VALUE);\n\n  newargc=0;\n  for (i = 1; i < argc; i++)\n    {\n      if (strncmp (argv[i], ltwrapper_option_prefix, opt_prefix_len) == 0)\n        {\n          /* however, if there is an option in the LTWRAPPER_OPTION_PREFIX\n             namespace, but it is not one of the ones we know about and\n             have already dealt with, above (inluding dump-script), then\n             report an error. Otherwise, targets might begin to believe\n             they are allowed to use options in the LTWRAPPER_OPTION_PREFIX\n             namespace. The first time any user complains about this, we'll\n             need to make LTWRAPPER_OPTION_PREFIX a configure-time option\n             or a configure.ac-settable value.\n           */\n          lt_fatal (\"Unrecognized option in %s namespace: '%s'\",\n                    ltwrapper_option_prefix, argv[i]);\n        }\n      /* otherwise ... */\n      newargz[++newargc] = xstrdup (argv[i]);\n    }\n  newargz[++newargc] = NULL;\n\n  LTWRAPPER_DEBUGPRINTF     ((\"(main) lt_argv_zero : %s\\n\", (lt_argv_zero ? lt_argv_zero : \"<NULL>\")));\n  for (i = 0; i < newargc; i++)\n    {\n      LTWRAPPER_DEBUGPRINTF ((\"(main) newargz[%d]   : %s\\n\", i, (newargz[i] ? newargz[i] : \"<NULL>\")));\n    }\n\nEOF\n\n\t    case $host_os in\n\t      mingw*)\n\t\tcat <<\"EOF\"\n  /* execv doesn't actually work on mingw as expected on unix */\n  newargz = prepare_spawn (newargz);\n  rval = _spawnv (_P_WAIT, lt_argv_zero, (const char * const *) newargz);\n  if (rval == -1)\n    {\n      /* failed to start process */\n      LTWRAPPER_DEBUGPRINTF ((\"(main) failed to launch target \\\"%s\\\": errno = %d\\n\", lt_argv_zero, errno));\n      return 127;\n    }\n  return rval;\nEOF\n\t\t;;\n\t      *)\n\t\tcat <<\"EOF\"\n  execv (lt_argv_zero, newargz);\n  return rval; /* =127, but avoids unused variable warning */\nEOF\n\t\t;;\n\t    esac\n\n\t    cat <<\"EOF\"\n}\n\nvoid *\nxmalloc (size_t num)\n{\n  void *p = (void *) malloc (num);\n  if (!p)\n    lt_fatal (\"Memory exhausted\");\n\n  return p;\n}\n\nchar *\nxstrdup (const char *string)\n{\n  return string ? strcpy ((char *) xmalloc (strlen (string) + 1),\n\t\t\t  string) : NULL;\n}\n\nconst char *\nbase_name (const char *name)\n{\n  const char *base;\n\n#if defined (HAVE_DOS_BASED_FILE_SYSTEM)\n  /* Skip over the disk name in MSDOS pathnames. */\n  if (isalpha ((unsigned char) name[0]) && name[1] == ':')\n    name += 2;\n#endif\n\n  for (base = name; *name; name++)\n    if (IS_DIR_SEPARATOR (*name))\n      base = name + 1;\n  return base;\n}\n\nint\ncheck_executable (const char *path)\n{\n  struct stat st;\n\n  LTWRAPPER_DEBUGPRINTF ((\"(check_executable)  : %s\\n\",\n\t\t\t  path ? (*path ? path : \"EMPTY!\") : \"NULL!\"));\n  if ((!path) || (!*path))\n    return 0;\n\n  if ((stat (path, &st) >= 0)\n      && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)))\n    return 1;\n  else\n    return 0;\n}\n\nint\nmake_executable (const char *path)\n{\n  int rval = 0;\n  struct stat st;\n\n  LTWRAPPER_DEBUGPRINTF ((\"(make_executable)   : %s\\n\",\n\t\t\t  path ? (*path ? path : \"EMPTY!\") : \"NULL!\"));\n  if ((!path) || (!*path))\n    return 0;\n\n  if (stat (path, &st) >= 0)\n    {\n      rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR);\n    }\n  return rval;\n}\n\n/* Searches for the full path of the wrapper.  Returns\n   newly allocated full path name if found, NULL otherwise\n   Does not chase symlinks, even on platforms that support them.\n*/\nchar *\nfind_executable (const char *wrapper)\n{\n  int has_slash = 0;\n  const char *p;\n  const char *p_next;\n  /* static buffer for getcwd */\n  char tmp[LT_PATHMAX + 1];\n  int tmp_len;\n  char *concat_name;\n\n  LTWRAPPER_DEBUGPRINTF ((\"(find_executable)   : %s\\n\",\n\t\t\t  wrapper ? (*wrapper ? wrapper : \"EMPTY!\") : \"NULL!\"));\n\n  if ((wrapper == NULL) || (*wrapper == '\\0'))\n    return NULL;\n\n  /* Absolute path? */\n#if defined (HAVE_DOS_BASED_FILE_SYSTEM)\n  if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':')\n    {\n      concat_name = xstrdup (wrapper);\n      if (check_executable (concat_name))\n\treturn concat_name;\n      XFREE (concat_name);\n    }\n  else\n    {\n#endif\n      if (IS_DIR_SEPARATOR (wrapper[0]))\n\t{\n\t  concat_name = xstrdup (wrapper);\n\t  if (check_executable (concat_name))\n\t    return concat_name;\n\t  XFREE (concat_name);\n\t}\n#if defined (HAVE_DOS_BASED_FILE_SYSTEM)\n    }\n#endif\n\n  for (p = wrapper; *p; p++)\n    if (*p == '/')\n      {\n\thas_slash = 1;\n\tbreak;\n      }\n  if (!has_slash)\n    {\n      /* no slashes; search PATH */\n      const char *path = getenv (\"PATH\");\n      if (path != NULL)\n\t{\n\t  for (p = path; *p; p = p_next)\n\t    {\n\t      const char *q;\n\t      size_t p_len;\n\t      for (q = p; *q; q++)\n\t\tif (IS_PATH_SEPARATOR (*q))\n\t\t  break;\n\t      p_len = q - p;\n\t      p_next = (*q == '\\0' ? q : q + 1);\n\t      if (p_len == 0)\n\t\t{\n\t\t  /* empty path: current directory */\n\t\t  if (getcwd (tmp, LT_PATHMAX) == NULL)\n\t\t    lt_fatal (\"getcwd failed\");\n\t\t  tmp_len = strlen (tmp);\n\t\t  concat_name =\n\t\t    XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1);\n\t\t  memcpy (concat_name, tmp, tmp_len);\n\t\t  concat_name[tmp_len] = '/';\n\t\t  strcpy (concat_name + tmp_len + 1, wrapper);\n\t\t}\n\t      else\n\t\t{\n\t\t  concat_name =\n\t\t    XMALLOC (char, p_len + 1 + strlen (wrapper) + 1);\n\t\t  memcpy (concat_name, p, p_len);\n\t\t  concat_name[p_len] = '/';\n\t\t  strcpy (concat_name + p_len + 1, wrapper);\n\t\t}\n\t      if (check_executable (concat_name))\n\t\treturn concat_name;\n\t      XFREE (concat_name);\n\t    }\n\t}\n      /* not found in PATH; assume curdir */\n    }\n  /* Relative path | not found in path: prepend cwd */\n  if (getcwd (tmp, LT_PATHMAX) == NULL)\n    lt_fatal (\"getcwd failed\");\n  tmp_len = strlen (tmp);\n  concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1);\n  memcpy (concat_name, tmp, tmp_len);\n  concat_name[tmp_len] = '/';\n  strcpy (concat_name + tmp_len + 1, wrapper);\n\n  if (check_executable (concat_name))\n    return concat_name;\n  XFREE (concat_name);\n  return NULL;\n}\n\nchar *\nchase_symlinks (const char *pathspec)\n{\n#ifndef S_ISLNK\n  return xstrdup (pathspec);\n#else\n  char buf[LT_PATHMAX];\n  struct stat s;\n  char *tmp_pathspec = xstrdup (pathspec);\n  char *p;\n  int has_symlinks = 0;\n  while (strlen (tmp_pathspec) && !has_symlinks)\n    {\n      LTWRAPPER_DEBUGPRINTF ((\"checking path component for symlinks: %s\\n\",\n\t\t\t      tmp_pathspec));\n      if (lstat (tmp_pathspec, &s) == 0)\n\t{\n\t  if (S_ISLNK (s.st_mode) != 0)\n\t    {\n\t      has_symlinks = 1;\n\t      break;\n\t    }\n\n\t  /* search backwards for last DIR_SEPARATOR */\n\t  p = tmp_pathspec + strlen (tmp_pathspec) - 1;\n\t  while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p)))\n\t    p--;\n\t  if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p)))\n\t    {\n\t      /* no more DIR_SEPARATORS left */\n\t      break;\n\t    }\n\t  *p = '\\0';\n\t}\n      else\n\t{\n\t  char *errstr = strerror (errno);\n\t  lt_fatal (\"Error accessing file %s (%s)\", tmp_pathspec, errstr);\n\t}\n    }\n  XFREE (tmp_pathspec);\n\n  if (!has_symlinks)\n    {\n      return xstrdup (pathspec);\n    }\n\n  tmp_pathspec = realpath (pathspec, buf);\n  if (tmp_pathspec == 0)\n    {\n      lt_fatal (\"Could not follow symlinks for %s\", pathspec);\n    }\n  return xstrdup (tmp_pathspec);\n#endif\n}\n\nchar *\nstrendzap (char *str, const char *pat)\n{\n  size_t len, patlen;\n\n  assert (str != NULL);\n  assert (pat != NULL);\n\n  len = strlen (str);\n  patlen = strlen (pat);\n\n  if (patlen <= len)\n    {\n      str += len - patlen;\n      if (strcmp (str, pat) == 0)\n\t*str = '\\0';\n    }\n  return str;\n}\n\nstatic void\nlt_error_core (int exit_status, const char *mode,\n\t       const char *message, va_list ap)\n{\n  fprintf (stderr, \"%s: %s: \", program_name, mode);\n  vfprintf (stderr, message, ap);\n  fprintf (stderr, \".\\n\");\n\n  if (exit_status >= 0)\n    exit (exit_status);\n}\n\nvoid\nlt_fatal (const char *message, ...)\n{\n  va_list ap;\n  va_start (ap, message);\n  lt_error_core (EXIT_FAILURE, \"FATAL\", message, ap);\n  va_end (ap);\n}\n\nvoid\nlt_setenv (const char *name, const char *value)\n{\n  LTWRAPPER_DEBUGPRINTF ((\"(lt_setenv) setting '%s' to '%s'\\n\",\n                          (name ? name : \"<NULL>\"),\n                          (value ? value : \"<NULL>\")));\n  {\n#ifdef HAVE_SETENV\n    /* always make a copy, for consistency with !HAVE_SETENV */\n    char *str = xstrdup (value);\n    setenv (name, str, 1);\n#else\n    int len = strlen (name) + 1 + strlen (value) + 1;\n    char *str = XMALLOC (char, len);\n    sprintf (str, \"%s=%s\", name, value);\n    if (putenv (str) != EXIT_SUCCESS)\n      {\n        XFREE (str);\n      }\n#endif\n  }\n}\n\nchar *\nlt_extend_str (const char *orig_value, const char *add, int to_end)\n{\n  char *new_value;\n  if (orig_value && *orig_value)\n    {\n      int orig_value_len = strlen (orig_value);\n      int add_len = strlen (add);\n      new_value = XMALLOC (char, add_len + orig_value_len + 1);\n      if (to_end)\n        {\n          strcpy (new_value, orig_value);\n          strcpy (new_value + orig_value_len, add);\n        }\n      else\n        {\n          strcpy (new_value, add);\n          strcpy (new_value + add_len, orig_value);\n        }\n    }\n  else\n    {\n      new_value = xstrdup (add);\n    }\n  return new_value;\n}\n\nvoid\nlt_update_exe_path (const char *name, const char *value)\n{\n  LTWRAPPER_DEBUGPRINTF ((\"(lt_update_exe_path) modifying '%s' by prepending '%s'\\n\",\n                          (name ? name : \"<NULL>\"),\n                          (value ? value : \"<NULL>\")));\n\n  if (name && *name && value && *value)\n    {\n      char *new_value = lt_extend_str (getenv (name), value, 0);\n      /* some systems can't cope with a ':'-terminated path #' */\n      int len = strlen (new_value);\n      while (((len = strlen (new_value)) > 0) && IS_PATH_SEPARATOR (new_value[len-1]))\n        {\n          new_value[len-1] = '\\0';\n        }\n      lt_setenv (name, new_value);\n      XFREE (new_value);\n    }\n}\n\nvoid\nlt_update_lib_path (const char *name, const char *value)\n{\n  LTWRAPPER_DEBUGPRINTF ((\"(lt_update_lib_path) modifying '%s' by prepending '%s'\\n\",\n                          (name ? name : \"<NULL>\"),\n                          (value ? value : \"<NULL>\")));\n\n  if (name && *name && value && *value)\n    {\n      char *new_value = lt_extend_str (getenv (name), value, 0);\n      lt_setenv (name, new_value);\n      XFREE (new_value);\n    }\n}\n\nEOF\n\t    case $host_os in\n\t      mingw*)\n\t\tcat <<\"EOF\"\n\n/* Prepares an argument vector before calling spawn().\n   Note that spawn() does not by itself call the command interpreter\n     (getenv (\"COMSPEC\") != NULL ? getenv (\"COMSPEC\") :\n      ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);\n         GetVersionEx(&v);\n         v.dwPlatformId == VER_PLATFORM_WIN32_NT;\n      }) ? \"cmd.exe\" : \"command.com\").\n   Instead it simply concatenates the arguments, separated by ' ', and calls\n   CreateProcess().  We must quote the arguments since Win32 CreateProcess()\n   interprets characters like ' ', '\\t', '\\\\', '\"' (but not '<' and '>') in a\n   special way:\n   - Space and tab are interpreted as delimiters. They are not treated as\n     delimiters if they are surrounded by double quotes: \"...\".\n   - Unescaped double quotes are removed from the input. Their only effect is\n     that within double quotes, space and tab are treated like normal\n     characters.\n   - Backslashes not followed by double quotes are not special.\n   - But 2*n+1 backslashes followed by a double quote become\n     n backslashes followed by a double quote (n >= 0):\n       \\\" -> \"\n       \\\\\\\" -> \\\"\n       \\\\\\\\\\\" -> \\\\\"\n */\n#define SHELL_SPECIAL_CHARS \"\\\"\\\\ \\001\\002\\003\\004\\005\\006\\007\\010\\011\\012\\013\\014\\015\\016\\017\\020\\021\\022\\023\\024\\025\\026\\027\\030\\031\\032\\033\\034\\035\\036\\037\"\n#define SHELL_SPACE_CHARS \" \\001\\002\\003\\004\\005\\006\\007\\010\\011\\012\\013\\014\\015\\016\\017\\020\\021\\022\\023\\024\\025\\026\\027\\030\\031\\032\\033\\034\\035\\036\\037\"\nchar **\nprepare_spawn (char **argv)\n{\n  size_t argc;\n  char **new_argv;\n  size_t i;\n\n  /* Count number of arguments.  */\n  for (argc = 0; argv[argc] != NULL; argc++)\n    ;\n\n  /* Allocate new argument vector.  */\n  new_argv = XMALLOC (char *, argc + 1);\n\n  /* Put quoted arguments into the new argument vector.  */\n  for (i = 0; i < argc; i++)\n    {\n      const char *string = argv[i];\n\n      if (string[0] == '\\0')\n\tnew_argv[i] = xstrdup (\"\\\"\\\"\");\n      else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL)\n\t{\n\t  int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL);\n\t  size_t length;\n\t  unsigned int backslashes;\n\t  const char *s;\n\t  char *quoted_string;\n\t  char *p;\n\n\t  length = 0;\n\t  backslashes = 0;\n\t  if (quote_around)\n\t    length++;\n\t  for (s = string; *s != '\\0'; s++)\n\t    {\n\t      char c = *s;\n\t      if (c == '\"')\n\t\tlength += backslashes + 1;\n\t      length++;\n\t      if (c == '\\\\')\n\t\tbackslashes++;\n\t      else\n\t\tbackslashes = 0;\n\t    }\n\t  if (quote_around)\n\t    length += backslashes + 1;\n\n\t  quoted_string = XMALLOC (char, length + 1);\n\n\t  p = quoted_string;\n\t  backslashes = 0;\n\t  if (quote_around)\n\t    *p++ = '\"';\n\t  for (s = string; *s != '\\0'; s++)\n\t    {\n\t      char c = *s;\n\t      if (c == '\"')\n\t\t{\n\t\t  unsigned int j;\n\t\t  for (j = backslashes + 1; j > 0; j--)\n\t\t    *p++ = '\\\\';\n\t\t}\n\t      *p++ = c;\n\t      if (c == '\\\\')\n\t\tbackslashes++;\n\t      else\n\t\tbackslashes = 0;\n\t    }\n\t  if (quote_around)\n\t    {\n\t      unsigned int j;\n\t      for (j = backslashes; j > 0; j--)\n\t\t*p++ = '\\\\';\n\t      *p++ = '\"';\n\t    }\n\t  *p = '\\0';\n\n\t  new_argv[i] = quoted_string;\n\t}\n      else\n\tnew_argv[i] = (char *) string;\n    }\n  new_argv[argc] = NULL;\n\n  return new_argv;\n}\nEOF\n\t\t;;\n\t    esac\n\n            cat <<\"EOF\"\nvoid lt_dump_script (FILE* f)\n{\nEOF\n\t    func_emit_wrapper yes |\n              $SED -e 's/\\([\\\\\"]\\)/\\\\\\1/g' \\\n\t           -e 's/^/  fputs (\"/' -e 's/$/\\\\n\", f);/'\n\n            cat <<\"EOF\"\n}\nEOF\n}\n# end: func_emit_cwrapperexe_src\n\n# func_win32_import_lib_p ARG\n# True if ARG is an import lib, as indicated by $file_magic_cmd\nfunc_win32_import_lib_p ()\n{\n    $opt_debug\n    case `eval \"$file_magic_cmd \\\"\\$1\\\" 2>/dev/null\" | $SED -e 10q` in\n    *import*) : ;;\n    *) false ;;\n    esac\n}\n\n# func_mode_link arg...\nfunc_mode_link ()\n{\n    $opt_debug\n    case $host in\n    *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*)\n      # It is impossible to link a dll without this setting, and\n      # we shouldn't force the makefile maintainer to figure out\n      # which system we are compiling for in order to pass an extra\n      # flag for every libtool invocation.\n      # allow_undefined=no\n\n      # FIXME: Unfortunately, there are problems with the above when trying\n      # to make a dll which has undefined symbols, in which case not\n      # even a static library is built.  For now, we need to specify\n      # -no-undefined on the libtool link line when we can be certain\n      # that all symbols are satisfied, otherwise we get a static library.\n      allow_undefined=yes\n      ;;\n    *)\n      allow_undefined=yes\n      ;;\n    esac\n    libtool_args=$nonopt\n    base_compile=\"$nonopt $@\"\n    compile_command=$nonopt\n    finalize_command=$nonopt\n\n    compile_rpath=\n    finalize_rpath=\n    compile_shlibpath=\n    finalize_shlibpath=\n    convenience=\n    old_convenience=\n    deplibs=\n    old_deplibs=\n    compiler_flags=\n    linker_flags=\n    dllsearchpath=\n    lib_search_path=`pwd`\n    inst_prefix_dir=\n    new_inherited_linker_flags=\n\n    avoid_version=no\n    bindir=\n    dlfiles=\n    dlprefiles=\n    dlself=no\n    export_dynamic=no\n    export_symbols=\n    export_symbols_regex=\n    generated=\n    libobjs=\n    ltlibs=\n    module=no\n    no_install=no\n    objs=\n    non_pic_objects=\n    precious_files_regex=\n    prefer_static_libs=no\n    preload=no\n    prev=\n    prevarg=\n    release=\n    rpath=\n    xrpath=\n    perm_rpath=\n    temp_rpath=\n    thread_safe=no\n    vinfo=\n    vinfo_number=no\n    weak_libs=\n    single_module=\"${wl}-single_module\"\n    func_infer_tag $base_compile\n\n    # We need to know -static, to get the right output filenames.\n    for arg\n    do\n      case $arg in\n      -shared)\n\ttest \"$build_libtool_libs\" != yes && \\\n\t  func_fatal_configuration \"can not build a shared library\"\n\tbuild_old_libs=no\n\tbreak\n\t;;\n      -all-static | -static | -static-libtool-libs)\n\tcase $arg in\n\t-all-static)\n\t  if test \"$build_libtool_libs\" = yes && test -z \"$link_static_flag\"; then\n\t    func_warning \"complete static linking is impossible in this configuration\"\n\t  fi\n\t  if test -n \"$link_static_flag\"; then\n\t    dlopen_self=$dlopen_self_static\n\t  fi\n\t  prefer_static_libs=yes\n\t  ;;\n\t-static)\n\t  if test -z \"$pic_flag\" && test -n \"$link_static_flag\"; then\n\t    dlopen_self=$dlopen_self_static\n\t  fi\n\t  prefer_static_libs=built\n\t  ;;\n\t-static-libtool-libs)\n\t  if test -z \"$pic_flag\" && test -n \"$link_static_flag\"; then\n\t    dlopen_self=$dlopen_self_static\n\t  fi\n\t  prefer_static_libs=yes\n\t  ;;\n\tesac\n\tbuild_libtool_libs=no\n\tbuild_old_libs=yes\n\tbreak\n\t;;\n      esac\n    done\n\n    # See if our shared archives depend on static archives.\n    test -n \"$old_archive_from_new_cmds\" && build_old_libs=yes\n\n    # Go through the arguments, transforming them on the way.\n    while test \"$#\" -gt 0; do\n      arg=\"$1\"\n      shift\n      func_quote_for_eval \"$arg\"\n      qarg=$func_quote_for_eval_unquoted_result\n      func_append libtool_args \" $func_quote_for_eval_result\"\n\n      # If the previous option needs an argument, assign it.\n      if test -n \"$prev\"; then\n\tcase $prev in\n\toutput)\n\t  func_append compile_command \" @OUTPUT@\"\n\t  func_append finalize_command \" @OUTPUT@\"\n\t  ;;\n\tesac\n\n\tcase $prev in\n\tbindir)\n\t  bindir=\"$arg\"\n\t  prev=\n\t  continue\n\t  ;;\n\tdlfiles|dlprefiles)\n\t  if test \"$preload\" = no; then\n\t    # Add the symbol object into the linking commands.\n\t    func_append compile_command \" @SYMFILE@\"\n\t    func_append finalize_command \" @SYMFILE@\"\n\t    preload=yes\n\t  fi\n\t  case $arg in\n\t  *.la | *.lo) ;;  # We handle these cases below.\n\t  force)\n\t    if test \"$dlself\" = no; then\n\t      dlself=needless\n\t      export_dynamic=yes\n\t    fi\n\t    prev=\n\t    continue\n\t    ;;\n\t  self)\n\t    if test \"$prev\" = dlprefiles; then\n\t      dlself=yes\n\t    elif test \"$prev\" = dlfiles && test \"$dlopen_self\" != yes; then\n\t      dlself=yes\n\t    else\n\t      dlself=needless\n\t      export_dynamic=yes\n\t    fi\n\t    prev=\n\t    continue\n\t    ;;\n\t  *)\n\t    if test \"$prev\" = dlfiles; then\n\t      dlfiles=\"$dlfiles $arg\"\n\t    else\n\t      dlprefiles=\"$dlprefiles $arg\"\n\t    fi\n\t    prev=\n\t    continue\n\t    ;;\n\t  esac\n\t  ;;\n\texpsyms)\n\t  export_symbols=\"$arg\"\n\t  test -f \"$arg\" \\\n\t    || func_fatal_error \"symbol file \\`$arg' does not exist\"\n\t  prev=\n\t  continue\n\t  ;;\n\texpsyms_regex)\n\t  export_symbols_regex=\"$arg\"\n\t  prev=\n\t  continue\n\t  ;;\n\tframework)\n\t  case $host in\n\t    *-*-darwin*)\n\t      case \"$deplibs \" in\n\t\t*\" $qarg.ltframework \"*) ;;\n\t\t*) deplibs=\"$deplibs $qarg.ltframework\" # this is fixed later\n\t\t   ;;\n\t      esac\n\t      ;;\n\t  esac\n\t  prev=\n\t  continue\n\t  ;;\n\tinst_prefix)\n\t  inst_prefix_dir=\"$arg\"\n\t  prev=\n\t  continue\n\t  ;;\n\tobjectlist)\n\t  if test -f \"$arg\"; then\n\t    save_arg=$arg\n\t    moreargs=\n\t    for fil in `cat \"$save_arg\"`\n\t    do\n#\t      moreargs=\"$moreargs $fil\"\n\t      arg=$fil\n\t      # A libtool-controlled object.\n\n\t      # Check to see that this really is a libtool object.\n\t      if func_lalib_unsafe_p \"$arg\"; then\n\t\tpic_object=\n\t\tnon_pic_object=\n\n\t\t# Read the .lo file\n\t\tfunc_source \"$arg\"\n\n\t\tif test -z \"$pic_object\" ||\n\t\t   test -z \"$non_pic_object\" ||\n\t\t   test \"$pic_object\" = none &&\n\t\t   test \"$non_pic_object\" = none; then\n\t\t  func_fatal_error \"cannot find name of object for \\`$arg'\"\n\t\tfi\n\n\t\t# Extract subdirectory from the argument.\n\t\tfunc_dirname \"$arg\" \"/\" \"\"\n\t\txdir=\"$func_dirname_result\"\n\n\t\tif test \"$pic_object\" != none; then\n\t\t  # Prepend the subdirectory the object is found in.\n\t\t  pic_object=\"$xdir$pic_object\"\n\n\t\t  if test \"$prev\" = dlfiles; then\n\t\t    if test \"$build_libtool_libs\" = yes && test \"$dlopen_support\" = yes; then\n\t\t      dlfiles=\"$dlfiles $pic_object\"\n\t\t      prev=\n\t\t      continue\n\t\t    else\n\t\t      # If libtool objects are unsupported, then we need to preload.\n\t\t      prev=dlprefiles\n\t\t    fi\n\t\t  fi\n\n\t\t  # CHECK ME:  I think I busted this.  -Ossama\n\t\t  if test \"$prev\" = dlprefiles; then\n\t\t    # Preload the old-style object.\n\t\t    dlprefiles=\"$dlprefiles $pic_object\"\n\t\t    prev=\n\t\t  fi\n\n\t\t  # A PIC object.\n\t\t  func_append libobjs \" $pic_object\"\n\t\t  arg=\"$pic_object\"\n\t\tfi\n\n\t\t# Non-PIC object.\n\t\tif test \"$non_pic_object\" != none; then\n\t\t  # Prepend the subdirectory the object is found in.\n\t\t  non_pic_object=\"$xdir$non_pic_object\"\n\n\t\t  # A standard non-PIC object\n\t\t  func_append non_pic_objects \" $non_pic_object\"\n\t\t  if test -z \"$pic_object\" || test \"$pic_object\" = none ; then\n\t\t    arg=\"$non_pic_object\"\n\t\t  fi\n\t\telse\n\t\t  # If the PIC object exists, use it instead.\n\t\t  # $xdir was prepended to $pic_object above.\n\t\t  non_pic_object=\"$pic_object\"\n\t\t  func_append non_pic_objects \" $non_pic_object\"\n\t\tfi\n\t      else\n\t\t# Only an error if not doing a dry-run.\n\t\tif $opt_dry_run; then\n\t\t  # Extract subdirectory from the argument.\n\t\t  func_dirname \"$arg\" \"/\" \"\"\n\t\t  xdir=\"$func_dirname_result\"\n\n\t\t  func_lo2o \"$arg\"\n\t\t  pic_object=$xdir$objdir/$func_lo2o_result\n\t\t  non_pic_object=$xdir$func_lo2o_result\n\t\t  func_append libobjs \" $pic_object\"\n\t\t  func_append non_pic_objects \" $non_pic_object\"\n\t        else\n\t\t  func_fatal_error \"\\`$arg' is not a valid libtool object\"\n\t\tfi\n\t      fi\n\t    done\n\t  else\n\t    func_fatal_error \"link input file \\`$arg' does not exist\"\n\t  fi\n\t  arg=$save_arg\n\t  prev=\n\t  continue\n\t  ;;\n\tprecious_regex)\n\t  precious_files_regex=\"$arg\"\n\t  prev=\n\t  continue\n\t  ;;\n\trelease)\n\t  release=\"-$arg\"\n\t  prev=\n\t  continue\n\t  ;;\n\trpath | xrpath)\n\t  # We need an absolute path.\n\t  case $arg in\n\t  [\\\\/]* | [A-Za-z]:[\\\\/]*) ;;\n\t  *)\n\t    func_fatal_error \"only absolute run-paths are allowed\"\n\t    ;;\n\t  esac\n\t  if test \"$prev\" = rpath; then\n\t    case \"$rpath \" in\n\t    *\" $arg \"*) ;;\n\t    *) rpath=\"$rpath $arg\" ;;\n\t    esac\n\t  else\n\t    case \"$xrpath \" in\n\t    *\" $arg \"*) ;;\n\t    *) xrpath=\"$xrpath $arg\" ;;\n\t    esac\n\t  fi\n\t  prev=\n\t  continue\n\t  ;;\n\tshrext)\n\t  shrext_cmds=\"$arg\"\n\t  prev=\n\t  continue\n\t  ;;\n\tweak)\n\t  weak_libs=\"$weak_libs $arg\"\n\t  prev=\n\t  continue\n\t  ;;\n\txcclinker)\n\t  linker_flags=\"$linker_flags $qarg\"\n\t  compiler_flags=\"$compiler_flags $qarg\"\n\t  prev=\n\t  func_append compile_command \" $qarg\"\n\t  func_append finalize_command \" $qarg\"\n\t  continue\n\t  ;;\n\txcompiler)\n\t  compiler_flags=\"$compiler_flags $qarg\"\n\t  prev=\n\t  func_append compile_command \" $qarg\"\n\t  func_append finalize_command \" $qarg\"\n\t  continue\n\t  ;;\n\txlinker)\n\t  linker_flags=\"$linker_flags $qarg\"\n\t  compiler_flags=\"$compiler_flags $wl$qarg\"\n\t  prev=\n\t  func_append compile_command \" $wl$qarg\"\n\t  func_append finalize_command \" $wl$qarg\"\n\t  continue\n\t  ;;\n\t*)\n\t  eval \"$prev=\\\"\\$arg\\\"\"\n\t  prev=\n\t  continue\n\t  ;;\n\tesac\n      fi # test -n \"$prev\"\n\n      prevarg=\"$arg\"\n\n      case $arg in\n      -all-static)\n\tif test -n \"$link_static_flag\"; then\n\t  # See comment for -static flag below, for more details.\n\t  func_append compile_command \" $link_static_flag\"\n\t  func_append finalize_command \" $link_static_flag\"\n\tfi\n\tcontinue\n\t;;\n\n      -allow-undefined)\n\t# FIXME: remove this flag sometime in the future.\n\tfunc_fatal_error \"\\`-allow-undefined' must not be used because it is the default\"\n\t;;\n\n      -avoid-version)\n\tavoid_version=yes\n\tcontinue\n\t;;\n\n      -bindir)\n\tprev=bindir\n\tcontinue\n\t;;\n\n      -dlopen)\n\tprev=dlfiles\n\tcontinue\n\t;;\n\n      -dlpreopen)\n\tprev=dlprefiles\n\tcontinue\n\t;;\n\n      -export-dynamic)\n\texport_dynamic=yes\n\tcontinue\n\t;;\n\n      -export-symbols | -export-symbols-regex)\n\tif test -n \"$export_symbols\" || test -n \"$export_symbols_regex\"; then\n\t  func_fatal_error \"more than one -exported-symbols argument is not allowed\"\n\tfi\n\tif test \"X$arg\" = \"X-export-symbols\"; then\n\t  prev=expsyms\n\telse\n\t  prev=expsyms_regex\n\tfi\n\tcontinue\n\t;;\n\n      -framework)\n\tprev=framework\n\tcontinue\n\t;;\n\n      -inst-prefix-dir)\n\tprev=inst_prefix\n\tcontinue\n\t;;\n\n      # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:*\n      # so, if we see these flags be careful not to treat them like -L\n      -L[A-Z][A-Z]*:*)\n\tcase $with_gcc/$host in\n\tno/*-*-irix* | /*-*-irix*)\n\t  func_append compile_command \" $arg\"\n\t  func_append finalize_command \" $arg\"\n\t  ;;\n\tesac\n\tcontinue\n\t;;\n\n      -L*)\n\tfunc_stripname '-L' '' \"$arg\"\n\tdir=$func_stripname_result\n\tif test -z \"$dir\"; then\n\t  if test \"$#\" -gt 0; then\n\t    func_fatal_error \"require no space between \\`-L' and \\`$1'\"\n\t  else\n\t    func_fatal_error \"need path for \\`-L' option\"\n\t  fi\n\tfi\n\t# We need an absolute path.\n\tcase $dir in\n\t[\\\\/]* | [A-Za-z]:[\\\\/]*) ;;\n\t*)\n\t  absdir=`cd \"$dir\" && pwd`\n\t  test -z \"$absdir\" && \\\n\t    func_fatal_error \"cannot determine absolute directory name of \\`$dir'\"\n\t  dir=\"$absdir\"\n\t  ;;\n\tesac\n\tcase \"$deplibs \" in\n\t*\" -L$dir \"*) ;;\n\t*)\n\t  deplibs=\"$deplibs -L$dir\"\n\t  lib_search_path=\"$lib_search_path $dir\"\n\t  ;;\n\tesac\n\tcase $host in\n\t*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*)\n\t  testbindir=`$ECHO \"$dir\" | $SED 's*/lib$*/bin*'`\n\t  case :$dllsearchpath: in\n\t  *\":$dir:\"*) ;;\n\t  ::) dllsearchpath=$dir;;\n\t  *) dllsearchpath=\"$dllsearchpath:$dir\";;\n\t  esac\n\t  case :$dllsearchpath: in\n\t  *\":$testbindir:\"*) ;;\n\t  ::) dllsearchpath=$testbindir;;\n\t  *) dllsearchpath=\"$dllsearchpath:$testbindir\";;\n\t  esac\n\t  ;;\n\tesac\n\tcontinue\n\t;;\n\n      -l*)\n\tif test \"X$arg\" = \"X-lc\" || test \"X$arg\" = \"X-lm\"; then\n\t  case $host in\n\t  *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*)\n\t    # These systems don't actually have a C or math library (as such)\n\t    continue\n\t    ;;\n\t  *-*-os2*)\n\t    # These systems don't actually have a C library (as such)\n\t    test \"X$arg\" = \"X-lc\" && continue\n\t    ;;\n\t  *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)\n\t    # Do not include libc due to us having libc/libc_r.\n\t    test \"X$arg\" = \"X-lc\" && continue\n\t    ;;\n\t  *-*-rhapsody* | *-*-darwin1.[012])\n\t    # Rhapsody C and math libraries are in the System framework\n\t    deplibs=\"$deplibs System.ltframework\"\n\t    continue\n\t    ;;\n\t  *-*-sco3.2v5* | *-*-sco5v6*)\n\t    # Causes problems with __ctype\n\t    test \"X$arg\" = \"X-lc\" && continue\n\t    ;;\n\t  *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)\n\t    # Compiler inserts libc in the correct place for threads to work\n\t    test \"X$arg\" = \"X-lc\" && continue\n\t    ;;\n\t  *-*-linux*)\n\t    test \"X$arg\" = \"X-lc\" && continue\n\t    ;;\n\t  esac\n\telif test \"X$arg\" = \"X-lc_r\"; then\n\t case $host in\n\t *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)\n\t   # Do not include libc_r directly, use -pthread flag.\n\t   continue\n\t   ;;\n\t esac\n\tfi\n\tdeplibs=\"$deplibs $arg\"\n\tcontinue\n\t;;\n\n      -module)\n\tmodule=yes\n\tcontinue\n\t;;\n\n      # Tru64 UNIX uses -model [arg] to determine the layout of C++\n      # classes, name mangling, and exception handling.\n      # Darwin uses the -arch flag to determine output architecture.\n      -model|-arch|-isysroot)\n\tcompiler_flags=\"$compiler_flags $arg\"\n\tfunc_append compile_command \" $arg\"\n\tfunc_append finalize_command \" $arg\"\n\tprev=xcompiler\n\tcontinue\n\t;;\n\n      -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads)\n\tcompiler_flags=\"$compiler_flags $arg\"\n\tfunc_append compile_command \" $arg\"\n\tfunc_append finalize_command \" $arg\"\n\tcase \"$new_inherited_linker_flags \" in\n\t    *\" $arg \"*) ;;\n\t    * ) new_inherited_linker_flags=\"$new_inherited_linker_flags $arg\" ;;\n\tesac\n\tcontinue\n\t;;\n\n      -multi_module)\n\tsingle_module=\"${wl}-multi_module\"\n\tcontinue\n\t;;\n\n      -no-fast-install)\n\tfast_install=no\n\tcontinue\n\t;;\n\n      -no-install)\n\tcase $host in\n\t*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*)\n\t  # The PATH hackery in wrapper scripts is required on Windows\n\t  # and Darwin in order for the loader to find any dlls it needs.\n\t  func_warning \"\\`-no-install' is ignored for $host\"\n\t  func_warning \"assuming \\`-no-fast-install' instead\"\n\t  fast_install=no\n\t  ;;\n\t*) no_install=yes ;;\n\tesac\n\tcontinue\n\t;;\n\n      -no-undefined)\n\tallow_undefined=no\n\tcontinue\n\t;;\n\n      -objectlist)\n\tprev=objectlist\n\tcontinue\n\t;;\n\n      -o) prev=output ;;\n\n      -precious-files-regex)\n\tprev=precious_regex\n\tcontinue\n\t;;\n\n      -release)\n\tprev=release\n\tcontinue\n\t;;\n\n      -rpath)\n\tprev=rpath\n\tcontinue\n\t;;\n\n      -R)\n\tprev=xrpath\n\tcontinue\n\t;;\n\n      -R*)\n\tfunc_stripname '-R' '' \"$arg\"\n\tdir=$func_stripname_result\n\t# We need an absolute path.\n\tcase $dir in\n\t[\\\\/]* | [A-Za-z]:[\\\\/]*) ;;\n\t*)\n\t  func_fatal_error \"only absolute run-paths are allowed\"\n\t  ;;\n\tesac\n\tcase \"$xrpath \" in\n\t*\" $dir \"*) ;;\n\t*) xrpath=\"$xrpath $dir\" ;;\n\tesac\n\tcontinue\n\t;;\n\n      -shared)\n\t# The effects of -shared are defined in a previous loop.\n\tcontinue\n\t;;\n\n      -shrext)\n\tprev=shrext\n\tcontinue\n\t;;\n\n      -static | -static-libtool-libs)\n\t# The effects of -static are defined in a previous loop.\n\t# We used to do the same as -all-static on platforms that\n\t# didn't have a PIC flag, but the assumption that the effects\n\t# would be equivalent was wrong.  It would break on at least\n\t# Digital Unix and AIX.\n\tcontinue\n\t;;\n\n      -thread-safe)\n\tthread_safe=yes\n\tcontinue\n\t;;\n\n      -version-info)\n\tprev=vinfo\n\tcontinue\n\t;;\n\n      -version-number)\n\tprev=vinfo\n\tvinfo_number=yes\n\tcontinue\n\t;;\n\n      -weak)\n        prev=weak\n\tcontinue\n\t;;\n\n      -Wc,*)\n\tfunc_stripname '-Wc,' '' \"$arg\"\n\targs=$func_stripname_result\n\targ=\n\tsave_ifs=\"$IFS\"; IFS=','\n\tfor flag in $args; do\n\t  IFS=\"$save_ifs\"\n          func_quote_for_eval \"$flag\"\n\t  arg=\"$arg $func_quote_for_eval_result\"\n\t  compiler_flags=\"$compiler_flags $func_quote_for_eval_result\"\n\tdone\n\tIFS=\"$save_ifs\"\n\tfunc_stripname ' ' '' \"$arg\"\n\targ=$func_stripname_result\n\t;;\n\n      -Wl,*)\n\tfunc_stripname '-Wl,' '' \"$arg\"\n\targs=$func_stripname_result\n\targ=\n\tsave_ifs=\"$IFS\"; IFS=','\n\tfor flag in $args; do\n\t  IFS=\"$save_ifs\"\n          func_quote_for_eval \"$flag\"\n\t  arg=\"$arg $wl$func_quote_for_eval_result\"\n\t  compiler_flags=\"$compiler_flags $wl$func_quote_for_eval_result\"\n\t  linker_flags=\"$linker_flags $func_quote_for_eval_result\"\n\tdone\n\tIFS=\"$save_ifs\"\n\tfunc_stripname ' ' '' \"$arg\"\n\targ=$func_stripname_result\n\t;;\n\n      -Xcompiler)\n\tprev=xcompiler\n\tcontinue\n\t;;\n\n      -Xlinker)\n\tprev=xlinker\n\tcontinue\n\t;;\n\n      -XCClinker)\n\tprev=xcclinker\n\tcontinue\n\t;;\n\n      # -msg_* for osf cc\n      -msg_*)\n\tfunc_quote_for_eval \"$arg\"\n\targ=\"$func_quote_for_eval_result\"\n\t;;\n\n      # -64, -mips[0-9] enable 64-bit mode on the SGI compiler\n      # -r[0-9][0-9]* specifies the processor on the SGI compiler\n      # -xarch=*, -xtarget=* enable 64-bit mode on the Sun compiler\n      # +DA*, +DD* enable 64-bit mode on the HP compiler\n      # -q* pass through compiler args for the IBM compiler\n      # -m*, -t[45]*, -txscale* pass through architecture-specific\n      # compiler args for GCC\n      # -F/path gives path to uninstalled frameworks, gcc on darwin\n      # -p, -pg, --coverage, -fprofile-* pass through profiling flag for GCC\n      # @file GCC response files\n      # -tp=* Portland pgcc target processor selection\n      -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \\\n      -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*)\n        func_quote_for_eval \"$arg\"\n\targ=\"$func_quote_for_eval_result\"\n        func_append compile_command \" $arg\"\n        func_append finalize_command \" $arg\"\n        compiler_flags=\"$compiler_flags $arg\"\n        continue\n        ;;\n\n      # Some other compiler flag.\n      -* | +*)\n        func_quote_for_eval \"$arg\"\n\targ=\"$func_quote_for_eval_result\"\n\t;;\n\n      *.$objext)\n\t# A standard object.\n\tobjs=\"$objs $arg\"\n\t;;\n\n      *.lo)\n\t# A libtool-controlled object.\n\n\t# Check to see that this really is a libtool object.\n\tif func_lalib_unsafe_p \"$arg\"; then\n\t  pic_object=\n\t  non_pic_object=\n\n\t  # Read the .lo file\n\t  func_source \"$arg\"\n\n\t  if test -z \"$pic_object\" ||\n\t     test -z \"$non_pic_object\" ||\n\t     test \"$pic_object\" = none &&\n\t     test \"$non_pic_object\" = none; then\n\t    func_fatal_error \"cannot find name of object for \\`$arg'\"\n\t  fi\n\n\t  # Extract subdirectory from the argument.\n\t  func_dirname \"$arg\" \"/\" \"\"\n\t  xdir=\"$func_dirname_result\"\n\n\t  if test \"$pic_object\" != none; then\n\t    # Prepend the subdirectory the object is found in.\n\t    pic_object=\"$xdir$pic_object\"\n\n\t    if test \"$prev\" = dlfiles; then\n\t      if test \"$build_libtool_libs\" = yes && test \"$dlopen_support\" = yes; then\n\t\tdlfiles=\"$dlfiles $pic_object\"\n\t\tprev=\n\t\tcontinue\n\t      else\n\t\t# If libtool objects are unsupported, then we need to preload.\n\t\tprev=dlprefiles\n\t      fi\n\t    fi\n\n\t    # CHECK ME:  I think I busted this.  -Ossama\n\t    if test \"$prev\" = dlprefiles; then\n\t      # Preload the old-style object.\n\t      dlprefiles=\"$dlprefiles $pic_object\"\n\t      prev=\n\t    fi\n\n\t    # A PIC object.\n\t    func_append libobjs \" $pic_object\"\n\t    arg=\"$pic_object\"\n\t  fi\n\n\t  # Non-PIC object.\n\t  if test \"$non_pic_object\" != none; then\n\t    # Prepend the subdirectory the object is found in.\n\t    non_pic_object=\"$xdir$non_pic_object\"\n\n\t    # A standard non-PIC object\n\t    func_append non_pic_objects \" $non_pic_object\"\n\t    if test -z \"$pic_object\" || test \"$pic_object\" = none ; then\n\t      arg=\"$non_pic_object\"\n\t    fi\n\t  else\n\t    # If the PIC object exists, use it instead.\n\t    # $xdir was prepended to $pic_object above.\n\t    non_pic_object=\"$pic_object\"\n\t    func_append non_pic_objects \" $non_pic_object\"\n\t  fi\n\telse\n\t  # Only an error if not doing a dry-run.\n\t  if $opt_dry_run; then\n\t    # Extract subdirectory from the argument.\n\t    func_dirname \"$arg\" \"/\" \"\"\n\t    xdir=\"$func_dirname_result\"\n\n\t    func_lo2o \"$arg\"\n\t    pic_object=$xdir$objdir/$func_lo2o_result\n\t    non_pic_object=$xdir$func_lo2o_result\n\t    func_append libobjs \" $pic_object\"\n\t    func_append non_pic_objects \" $non_pic_object\"\n\t  else\n\t    func_fatal_error \"\\`$arg' is not a valid libtool object\"\n\t  fi\n\tfi\n\t;;\n\n      *.$libext)\n\t# An archive.\n\tdeplibs=\"$deplibs $arg\"\n\told_deplibs=\"$old_deplibs $arg\"\n\tcontinue\n\t;;\n\n      *.la)\n\t# A libtool-controlled library.\n\n\tif test \"$prev\" = dlfiles; then\n\t  # This library was specified with -dlopen.\n\t  dlfiles=\"$dlfiles $arg\"\n\t  prev=\n\telif test \"$prev\" = dlprefiles; then\n\t  # The library was specified with -dlpreopen.\n\t  dlprefiles=\"$dlprefiles $arg\"\n\t  prev=\n\telse\n\t  deplibs=\"$deplibs $arg\"\n\tfi\n\tcontinue\n\t;;\n\n      # Some other compiler argument.\n      *)\n\t# Unknown arguments in both finalize_command and compile_command need\n\t# to be aesthetically quoted because they are evaled later.\n\tfunc_quote_for_eval \"$arg\"\n\targ=\"$func_quote_for_eval_result\"\n\t;;\n      esac # arg\n\n      # Now actually substitute the argument into the commands.\n      if test -n \"$arg\"; then\n\tfunc_append compile_command \" $arg\"\n\tfunc_append finalize_command \" $arg\"\n      fi\n    done # argument parsing loop\n\n    test -n \"$prev\" && \\\n      func_fatal_help \"the \\`$prevarg' option requires an argument\"\n\n    if test \"$export_dynamic\" = yes && test -n \"$export_dynamic_flag_spec\"; then\n      eval \"arg=\\\"$export_dynamic_flag_spec\\\"\"\n      func_append compile_command \" $arg\"\n      func_append finalize_command \" $arg\"\n    fi\n\n    oldlibs=\n    # calculate the name of the file, without its directory\n    func_basename \"$output\"\n    outputname=\"$func_basename_result\"\n    libobjs_save=\"$libobjs\"\n\n    if test -n \"$shlibpath_var\"; then\n      # get the directories listed in $shlibpath_var\n      eval shlib_search_path=\\`\\$ECHO \\\"\\${$shlibpath_var}\\\" \\| \\$SED \\'s/:/ /g\\'\\`\n    else\n      shlib_search_path=\n    fi\n    eval \"sys_lib_search_path=\\\"$sys_lib_search_path_spec\\\"\"\n    eval \"sys_lib_dlsearch_path=\\\"$sys_lib_dlsearch_path_spec\\\"\"\n\n    func_dirname \"$output\" \"/\" \"\"\n    output_objdir=\"$func_dirname_result$objdir\"\n    # Create the object directory.\n    func_mkdir_p \"$output_objdir\"\n\n    # Determine the type of output\n    case $output in\n    \"\")\n      func_fatal_help \"you must specify an output file\"\n      ;;\n    *.$libext) linkmode=oldlib ;;\n    *.lo | *.$objext) linkmode=obj ;;\n    *.la) linkmode=lib ;;\n    *) linkmode=prog ;; # Anything else should be a program.\n    esac\n\n    specialdeplibs=\n\n    libs=\n    # Find all interdependent deplibs by searching for libraries\n    # that are linked more than once (e.g. -la -lb -la)\n    for deplib in $deplibs; do\n      if $opt_duplicate_deps ; then\n\tcase \"$libs \" in\n\t*\" $deplib \"*) specialdeplibs=\"$specialdeplibs $deplib\" ;;\n\tesac\n      fi\n      libs=\"$libs $deplib\"\n    done\n\n    if test \"$linkmode\" = lib; then\n      libs=\"$predeps $libs $compiler_lib_search_path $postdeps\"\n\n      # Compute libraries that are listed more than once in $predeps\n      # $postdeps and mark them as special (i.e., whose duplicates are\n      # not to be eliminated).\n      pre_post_deps=\n      if $opt_duplicate_compiler_generated_deps; then\n\tfor pre_post_dep in $predeps $postdeps; do\n\t  case \"$pre_post_deps \" in\n\t  *\" $pre_post_dep \"*) specialdeplibs=\"$specialdeplibs $pre_post_deps\" ;;\n\t  esac\n\t  pre_post_deps=\"$pre_post_deps $pre_post_dep\"\n\tdone\n      fi\n      pre_post_deps=\n    fi\n\n    deplibs=\n    newdependency_libs=\n    newlib_search_path=\n    need_relink=no # whether we're linking any uninstalled libtool libraries\n    notinst_deplibs= # not-installed libtool libraries\n    notinst_path= # paths that contain not-installed libtool libraries\n\n    case $linkmode in\n    lib)\n\tpasses=\"conv dlpreopen link\"\n\tfor file in $dlfiles $dlprefiles; do\n\t  case $file in\n\t  *.la) ;;\n\t  *)\n\t    func_fatal_help \"libraries can \\`-dlopen' only libtool libraries: $file\"\n\t    ;;\n\t  esac\n\tdone\n\t;;\n    prog)\n\tcompile_deplibs=\n\tfinalize_deplibs=\n\talldeplibs=no\n\tnewdlfiles=\n\tnewdlprefiles=\n\tpasses=\"conv scan dlopen dlpreopen link\"\n\t;;\n    *)  passes=\"conv\"\n\t;;\n    esac\n\n    for pass in $passes; do\n      # The preopen pass in lib mode reverses $deplibs; put it back here\n      # so that -L comes before libs that need it for instance...\n      if test \"$linkmode,$pass\" = \"lib,link\"; then\n\t## FIXME: Find the place where the list is rebuilt in the wrong\n\t##        order, and fix it there properly\n        tmp_deplibs=\n\tfor deplib in $deplibs; do\n\t  tmp_deplibs=\"$deplib $tmp_deplibs\"\n\tdone\n\tdeplibs=\"$tmp_deplibs\"\n      fi\n\n      if test \"$linkmode,$pass\" = \"lib,link\" ||\n\t test \"$linkmode,$pass\" = \"prog,scan\"; then\n\tlibs=\"$deplibs\"\n\tdeplibs=\n      fi\n      if test \"$linkmode\" = prog; then\n\tcase $pass in\n\tdlopen) libs=\"$dlfiles\" ;;\n\tdlpreopen) libs=\"$dlprefiles\" ;;\n\tlink) libs=\"$deplibs %DEPLIBS% $dependency_libs\" ;;\n\tesac\n      fi\n      if test \"$linkmode,$pass\" = \"lib,dlpreopen\"; then\n\t# Collect and forward deplibs of preopened libtool libs\n\tfor lib in $dlprefiles; do\n\t  # Ignore non-libtool-libs\n\t  dependency_libs=\n\t  case $lib in\n\t  *.la)\tfunc_source \"$lib\" ;;\n\t  esac\n\n\t  # Collect preopened libtool deplibs, except any this library\n\t  # has declared as weak libs\n\t  for deplib in $dependency_libs; do\n\t    func_basename \"$deplib\"\n            deplib_base=$func_basename_result\n\t    case \" $weak_libs \" in\n\t    *\" $deplib_base \"*) ;;\n\t    *) deplibs=\"$deplibs $deplib\" ;;\n\t    esac\n\t  done\n\tdone\n\tlibs=\"$dlprefiles\"\n      fi\n      if test \"$pass\" = dlopen; then\n\t# Collect dlpreopened libraries\n\tsave_deplibs=\"$deplibs\"\n\tdeplibs=\n      fi\n\n      for deplib in $libs; do\n\tlib=\n\tfound=no\n\tcase $deplib in\n\t-mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads)\n\t  if test \"$linkmode,$pass\" = \"prog,link\"; then\n\t    compile_deplibs=\"$deplib $compile_deplibs\"\n\t    finalize_deplibs=\"$deplib $finalize_deplibs\"\n\t  else\n\t    compiler_flags=\"$compiler_flags $deplib\"\n\t    if test \"$linkmode\" = lib ; then\n\t\tcase \"$new_inherited_linker_flags \" in\n\t\t    *\" $deplib \"*) ;;\n\t\t    * ) new_inherited_linker_flags=\"$new_inherited_linker_flags $deplib\" ;;\n\t\tesac\n\t    fi\n\t  fi\n\t  continue\n\t  ;;\n\t-l*)\n\t  if test \"$linkmode\" != lib && test \"$linkmode\" != prog; then\n\t    func_warning \"\\`-l' is ignored for archives/objects\"\n\t    continue\n\t  fi\n\t  func_stripname '-l' '' \"$deplib\"\n\t  name=$func_stripname_result\n\t  if test \"$linkmode\" = lib; then\n\t    searchdirs=\"$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path\"\n\t  else\n\t    searchdirs=\"$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path\"\n\t  fi\n\t  for searchdir in $searchdirs; do\n\t    for search_ext in .la $std_shrext .so .a; do\n\t      # Search the libtool library\n\t      lib=\"$searchdir/lib${name}${search_ext}\"\n\t      if test -f \"$lib\"; then\n\t\tif test \"$search_ext\" = \".la\"; then\n\t\t  found=yes\n\t\telse\n\t\t  found=no\n\t\tfi\n\t\tbreak 2\n\t      fi\n\t    done\n\t  done\n\t  if test \"$found\" != yes; then\n\t    # deplib doesn't seem to be a libtool library\n\t    if test \"$linkmode,$pass\" = \"prog,link\"; then\n\t      compile_deplibs=\"$deplib $compile_deplibs\"\n\t      finalize_deplibs=\"$deplib $finalize_deplibs\"\n\t    else\n\t      deplibs=\"$deplib $deplibs\"\n\t      test \"$linkmode\" = lib && newdependency_libs=\"$deplib $newdependency_libs\"\n\t    fi\n\t    continue\n\t  else # deplib is a libtool library\n\t    # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib,\n\t    # We need to do some special things here, and not later.\n\t    if test \"X$allow_libtool_libs_with_static_runtimes\" = \"Xyes\" ; then\n\t      case \" $predeps $postdeps \" in\n\t      *\" $deplib \"*)\n\t\tif func_lalib_p \"$lib\"; then\n\t\t  library_names=\n\t\t  old_library=\n\t\t  func_source \"$lib\"\n\t\t  for l in $old_library $library_names; do\n\t\t    ll=\"$l\"\n\t\t  done\n\t\t  if test \"X$ll\" = \"X$old_library\" ; then # only static version available\n\t\t    found=no\n\t\t    func_dirname \"$lib\" \"\" \".\"\n\t\t    ladir=\"$func_dirname_result\"\n\t\t    lib=$ladir/$old_library\n\t\t    if test \"$linkmode,$pass\" = \"prog,link\"; then\n\t\t      compile_deplibs=\"$deplib $compile_deplibs\"\n\t\t      finalize_deplibs=\"$deplib $finalize_deplibs\"\n\t\t    else\n\t\t      deplibs=\"$deplib $deplibs\"\n\t\t      test \"$linkmode\" = lib && newdependency_libs=\"$deplib $newdependency_libs\"\n\t\t    fi\n\t\t    continue\n\t\t  fi\n\t\tfi\n\t\t;;\n\t      *) ;;\n\t      esac\n\t    fi\n\t  fi\n\t  ;; # -l\n\t*.ltframework)\n\t  if test \"$linkmode,$pass\" = \"prog,link\"; then\n\t    compile_deplibs=\"$deplib $compile_deplibs\"\n\t    finalize_deplibs=\"$deplib $finalize_deplibs\"\n\t  else\n\t    deplibs=\"$deplib $deplibs\"\n\t    if test \"$linkmode\" = lib ; then\n\t\tcase \"$new_inherited_linker_flags \" in\n\t\t    *\" $deplib \"*) ;;\n\t\t    * ) new_inherited_linker_flags=\"$new_inherited_linker_flags $deplib\" ;;\n\t\tesac\n\t    fi\n\t  fi\n\t  continue\n\t  ;;\n\t-L*)\n\t  case $linkmode in\n\t  lib)\n\t    deplibs=\"$deplib $deplibs\"\n\t    test \"$pass\" = conv && continue\n\t    newdependency_libs=\"$deplib $newdependency_libs\"\n\t    func_stripname '-L' '' \"$deplib\"\n\t    newlib_search_path=\"$newlib_search_path $func_stripname_result\"\n\t    ;;\n\t  prog)\n\t    if test \"$pass\" = conv; then\n\t      deplibs=\"$deplib $deplibs\"\n\t      continue\n\t    fi\n\t    if test \"$pass\" = scan; then\n\t      deplibs=\"$deplib $deplibs\"\n\t    else\n\t      compile_deplibs=\"$deplib $compile_deplibs\"\n\t      finalize_deplibs=\"$deplib $finalize_deplibs\"\n\t    fi\n\t    func_stripname '-L' '' \"$deplib\"\n\t    newlib_search_path=\"$newlib_search_path $func_stripname_result\"\n\t    ;;\n\t  *)\n\t    func_warning \"\\`-L' is ignored for archives/objects\"\n\t    ;;\n\t  esac # linkmode\n\t  continue\n\t  ;; # -L\n\t-R*)\n\t  if test \"$pass\" = link; then\n\t    func_stripname '-R' '' \"$deplib\"\n\t    dir=$func_stripname_result\n\t    # Make sure the xrpath contains only unique directories.\n\t    case \"$xrpath \" in\n\t    *\" $dir \"*) ;;\n\t    *) xrpath=\"$xrpath $dir\" ;;\n\t    esac\n\t  fi\n\t  deplibs=\"$deplib $deplibs\"\n\t  continue\n\t  ;;\n\t*.la) lib=\"$deplib\" ;;\n\t*.$libext)\n\t  if test \"$pass\" = conv; then\n\t    deplibs=\"$deplib $deplibs\"\n\t    continue\n\t  fi\n\t  case $linkmode in\n\t  lib)\n\t    # Linking convenience modules into shared libraries is allowed,\n\t    # but linking other static libraries is non-portable.\n\t    case \" $dlpreconveniencelibs \" in\n\t    *\" $deplib \"*) ;;\n\t    *)\n\t      valid_a_lib=no\n\t      case $deplibs_check_method in\n\t\tmatch_pattern*)\n\t\t  set dummy $deplibs_check_method; shift\n\t\t  match_pattern_regex=`expr \"$deplibs_check_method\" : \"$1 \\(.*\\)\"`\n\t\t  if eval \"\\$ECHO \\\"$deplib\\\"\" 2>/dev/null | $SED 10q \\\n\t\t    | $EGREP \"$match_pattern_regex\" > /dev/null; then\n\t\t    valid_a_lib=yes\n\t\t  fi\n\t\t;;\n\t\tpass_all)\n\t\t  valid_a_lib=yes\n\t\t;;\n\t      esac\n\t      if test \"$valid_a_lib\" != yes; then\n\t\techo\n\t\t$ECHO \"*** Warning: Trying to link with static lib archive $deplib.\"\n\t\techo \"*** I have the capability to make that library automatically link in when\"\n\t\techo \"*** you link to this library.  But I can only do this if you have a\"\n\t\techo \"*** shared version of the library, which you do not appear to have\"\n\t\techo \"*** because the file extensions .$libext of this argument makes me believe\"\n\t\techo \"*** that it is just a static archive that I should not use here.\"\n\t      else\n\t\techo\n\t\t$ECHO \"*** Warning: Linking the shared library $output against the\"\n\t\t$ECHO \"*** static library $deplib is not portable!\"\n\t\tdeplibs=\"$deplib $deplibs\"\n\t      fi\n\t      ;;\n\t    esac\n\t    continue\n\t    ;;\n\t  prog)\n\t    if test \"$pass\" != link; then\n\t      deplibs=\"$deplib $deplibs\"\n\t    else\n\t      compile_deplibs=\"$deplib $compile_deplibs\"\n\t      finalize_deplibs=\"$deplib $finalize_deplibs\"\n\t    fi\n\t    continue\n\t    ;;\n\t  esac # linkmode\n\t  ;; # *.$libext\n\t*.lo | *.$objext)\n\t  if test \"$pass\" = conv; then\n\t    deplibs=\"$deplib $deplibs\"\n\t  elif test \"$linkmode\" = prog; then\n\t    if test \"$pass\" = dlpreopen || test \"$dlopen_support\" != yes || test \"$build_libtool_libs\" = no; then\n\t      # If there is no dlopen support or we're linking statically,\n\t      # we need to preload.\n\t      newdlprefiles=\"$newdlprefiles $deplib\"\n\t      compile_deplibs=\"$deplib $compile_deplibs\"\n\t      finalize_deplibs=\"$deplib $finalize_deplibs\"\n\t    else\n\t      newdlfiles=\"$newdlfiles $deplib\"\n\t    fi\n\t  fi\n\t  continue\n\t  ;;\n\t%DEPLIBS%)\n\t  alldeplibs=yes\n\t  continue\n\t  ;;\n\tesac # case $deplib\n\n\tif test \"$found\" = yes || test -f \"$lib\"; then :\n\telse\n\t  func_fatal_error \"cannot find the library \\`$lib' or unhandled argument \\`$deplib'\"\n\tfi\n\n\t# Check to see that this really is a libtool archive.\n\tfunc_lalib_unsafe_p \"$lib\" \\\n\t  || func_fatal_error \"\\`$lib' is not a valid libtool archive\"\n\n\tfunc_dirname \"$lib\" \"\" \".\"\n\tladir=\"$func_dirname_result\"\n\n\tdlname=\n\tdlopen=\n\tdlpreopen=\n\tlibdir=\n\tlibrary_names=\n\told_library=\n\tinherited_linker_flags=\n\t# If the library was installed with an old release of libtool,\n\t# it will not redefine variables installed, or shouldnotlink\n\tinstalled=yes\n\tshouldnotlink=no\n\tavoidtemprpath=\n\n\n\t# Read the .la file\n\tfunc_source \"$lib\"\n\n\t# Convert \"-framework foo\" to \"foo.ltframework\"\n\tif test -n \"$inherited_linker_flags\"; then\n\t  tmp_inherited_linker_flags=`$ECHO \"$inherited_linker_flags\" | $SED 's/-framework \\([^ $]*\\)/\\1.ltframework/g'`\n\t  for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do\n\t    case \" $new_inherited_linker_flags \" in\n\t      *\" $tmp_inherited_linker_flag \"*) ;;\n\t      *) new_inherited_linker_flags=\"$new_inherited_linker_flags $tmp_inherited_linker_flag\";;\n\t    esac\n\t  done\n\tfi\n\tdependency_libs=`$ECHO \" $dependency_libs\" | $SED 's% \\([^ $]*\\).ltframework% -framework \\1%g'`\n\tif test \"$linkmode,$pass\" = \"lib,link\" ||\n\t   test \"$linkmode,$pass\" = \"prog,scan\" ||\n\t   { test \"$linkmode\" != prog && test \"$linkmode\" != lib; }; then\n\t  test -n \"$dlopen\" && dlfiles=\"$dlfiles $dlopen\"\n\t  test -n \"$dlpreopen\" && dlprefiles=\"$dlprefiles $dlpreopen\"\n\tfi\n\n\tif test \"$pass\" = conv; then\n\t  # Only check for convenience libraries\n\t  deplibs=\"$lib $deplibs\"\n\t  if test -z \"$libdir\"; then\n\t    if test -z \"$old_library\"; then\n\t      func_fatal_error \"cannot find name of link library for \\`$lib'\"\n\t    fi\n\t    # It is a libtool convenience library, so add in its objects.\n\t    convenience=\"$convenience $ladir/$objdir/$old_library\"\n\t    old_convenience=\"$old_convenience $ladir/$objdir/$old_library\"\n\t  elif test \"$linkmode\" != prog && test \"$linkmode\" != lib; then\n\t    func_fatal_error \"\\`$lib' is not a convenience library\"\n\t  fi\n\t  tmp_libs=\n\t  for deplib in $dependency_libs; do\n\t    deplibs=\"$deplib $deplibs\"\n\t    if $opt_duplicate_deps ; then\n\t      case \"$tmp_libs \" in\n\t      *\" $deplib \"*) specialdeplibs=\"$specialdeplibs $deplib\" ;;\n\t      esac\n\t    fi\n\t    tmp_libs=\"$tmp_libs $deplib\"\n\t  done\n\t  continue\n\tfi # $pass = conv\n\n\n\t# Get the name of the library we link against.\n\tlinklib=\n\tfor l in $old_library $library_names; do\n\t  linklib=\"$l\"\n\tdone\n\tif test -z \"$linklib\"; then\n\t  func_fatal_error \"cannot find name of link library for \\`$lib'\"\n\tfi\n\n\t# This library was specified with -dlopen.\n\tif test \"$pass\" = dlopen; then\n\t  if test -z \"$libdir\"; then\n\t    func_fatal_error \"cannot -dlopen a convenience library: \\`$lib'\"\n\t  fi\n\t  if test -z \"$dlname\" ||\n\t     test \"$dlopen_support\" != yes ||\n\t     test \"$build_libtool_libs\" = no; then\n\t    # If there is no dlname, no dlopen support or we're linking\n\t    # statically, we need to preload.  We also need to preload any\n\t    # dependent libraries so libltdl's deplib preloader doesn't\n\t    # bomb out in the load deplibs phase.\n\t    dlprefiles=\"$dlprefiles $lib $dependency_libs\"\n\t  else\n\t    newdlfiles=\"$newdlfiles $lib\"\n\t  fi\n\t  continue\n\tfi # $pass = dlopen\n\n\t# We need an absolute path.\n\tcase $ladir in\n\t[\\\\/]* | [A-Za-z]:[\\\\/]*) abs_ladir=\"$ladir\" ;;\n\t*)\n\t  abs_ladir=`cd \"$ladir\" && pwd`\n\t  if test -z \"$abs_ladir\"; then\n\t    func_warning \"cannot determine absolute directory name of \\`$ladir'\"\n\t    func_warning \"passing it literally to the linker, although it might fail\"\n\t    abs_ladir=\"$ladir\"\n\t  fi\n\t  ;;\n\tesac\n\tfunc_basename \"$lib\"\n\tlaname=\"$func_basename_result\"\n\n\t# Find the relevant object directory and library name.\n\tif test \"X$installed\" = Xyes; then\n\t  if test ! -f \"$libdir/$linklib\" && test -f \"$abs_ladir/$linklib\"; then\n\t    func_warning \"library \\`$lib' was moved.\"\n\t    dir=\"$ladir\"\n\t    absdir=\"$abs_ladir\"\n\t    libdir=\"$abs_ladir\"\n\t  else\n\t    dir=\"$libdir\"\n\t    absdir=\"$libdir\"\n\t  fi\n\t  test \"X$hardcode_automatic\" = Xyes && avoidtemprpath=yes\n\telse\n\t  if test ! -f \"$ladir/$objdir/$linklib\" && test -f \"$abs_ladir/$linklib\"; then\n\t    dir=\"$ladir\"\n\t    absdir=\"$abs_ladir\"\n\t    # Remove this search path later\n\t    notinst_path=\"$notinst_path $abs_ladir\"\n\t  else\n\t    dir=\"$ladir/$objdir\"\n\t    absdir=\"$abs_ladir/$objdir\"\n\t    # Remove this search path later\n\t    notinst_path=\"$notinst_path $abs_ladir\"\n\t  fi\n\tfi # $installed = yes\n\tfunc_stripname 'lib' '.la' \"$laname\"\n\tname=$func_stripname_result\n\n\t# This library was specified with -dlpreopen.\n\tif test \"$pass\" = dlpreopen; then\n\t  if test -z \"$libdir\" && test \"$linkmode\" = prog; then\n\t    func_fatal_error \"only libraries may -dlpreopen a convenience library: \\`$lib'\"\n\t  fi\n\t  # Prefer using a static library (so that no silly _DYNAMIC symbols\n\t  # are required to link).\n\t  if test -n \"$old_library\"; then\n\t    newdlprefiles=\"$newdlprefiles $dir/$old_library\"\n\t    # Keep a list of preopened convenience libraries to check\n\t    # that they are being used correctly in the link pass.\n\t    test -z \"$libdir\" && \\\n\t\tdlpreconveniencelibs=\"$dlpreconveniencelibs $dir/$old_library\"\n\t  # Otherwise, use the dlname, so that lt_dlopen finds it.\n\t  elif test -n \"$dlname\"; then\n\t    newdlprefiles=\"$newdlprefiles $dir/$dlname\"\n\t  else\n\t    newdlprefiles=\"$newdlprefiles $dir/$linklib\"\n\t  fi\n\tfi # $pass = dlpreopen\n\n\tif test -z \"$libdir\"; then\n\t  # Link the convenience library\n\t  if test \"$linkmode\" = lib; then\n\t    deplibs=\"$dir/$old_library $deplibs\"\n\t  elif test \"$linkmode,$pass\" = \"prog,link\"; then\n\t    compile_deplibs=\"$dir/$old_library $compile_deplibs\"\n\t    finalize_deplibs=\"$dir/$old_library $finalize_deplibs\"\n\t  else\n\t    deplibs=\"$lib $deplibs\" # used for prog,scan pass\n\t  fi\n\t  continue\n\tfi\n\n\n\tif test \"$linkmode\" = prog && test \"$pass\" != link; then\n\t  newlib_search_path=\"$newlib_search_path $ladir\"\n\t  deplibs=\"$lib $deplibs\"\n\n\t  linkalldeplibs=no\n\t  if test \"$link_all_deplibs\" != no || test -z \"$library_names\" ||\n\t     test \"$build_libtool_libs\" = no; then\n\t    linkalldeplibs=yes\n\t  fi\n\n\t  tmp_libs=\n\t  for deplib in $dependency_libs; do\n\t    case $deplib in\n\t    -L*) func_stripname '-L' '' \"$deplib\"\n\t         newlib_search_path=\"$newlib_search_path $func_stripname_result\"\n\t\t ;;\n\t    esac\n\t    # Need to link against all dependency_libs?\n\t    if test \"$linkalldeplibs\" = yes; then\n\t      deplibs=\"$deplib $deplibs\"\n\t    else\n\t      # Need to hardcode shared library paths\n\t      # or/and link against static libraries\n\t      newdependency_libs=\"$deplib $newdependency_libs\"\n\t    fi\n\t    if $opt_duplicate_deps ; then\n\t      case \"$tmp_libs \" in\n\t      *\" $deplib \"*) specialdeplibs=\"$specialdeplibs $deplib\" ;;\n\t      esac\n\t    fi\n\t    tmp_libs=\"$tmp_libs $deplib\"\n\t  done # for deplib\n\t  continue\n\tfi # $linkmode = prog...\n\n\tif test \"$linkmode,$pass\" = \"prog,link\"; then\n\t  if test -n \"$library_names\" &&\n\t     { { test \"$prefer_static_libs\" = no ||\n\t         test \"$prefer_static_libs,$installed\" = \"built,yes\"; } ||\n\t       test -z \"$old_library\"; }; then\n\t    # We need to hardcode the library path\n\t    if test -n \"$shlibpath_var\" && test -z \"$avoidtemprpath\" ; then\n\t      # Make sure the rpath contains only unique directories.\n\t      case \"$temp_rpath:\" in\n\t      *\"$absdir:\"*) ;;\n\t      *) temp_rpath=\"$temp_rpath$absdir:\" ;;\n\t      esac\n\t    fi\n\n\t    # Hardcode the library path.\n\t    # Skip directories that are in the system default run-time\n\t    # search path.\n\t    case \" $sys_lib_dlsearch_path \" in\n\t    *\" $absdir \"*) ;;\n\t    *)\n\t      case \"$compile_rpath \" in\n\t      *\" $absdir \"*) ;;\n\t      *) compile_rpath=\"$compile_rpath $absdir\"\n\t      esac\n\t      ;;\n\t    esac\n\t    case \" $sys_lib_dlsearch_path \" in\n\t    *\" $libdir \"*) ;;\n\t    *)\n\t      case \"$finalize_rpath \" in\n\t      *\" $libdir \"*) ;;\n\t      *) finalize_rpath=\"$finalize_rpath $libdir\"\n\t      esac\n\t      ;;\n\t    esac\n\t  fi # $linkmode,$pass = prog,link...\n\n\t  if test \"$alldeplibs\" = yes &&\n\t     { test \"$deplibs_check_method\" = pass_all ||\n\t       { test \"$build_libtool_libs\" = yes &&\n\t\t test -n \"$library_names\"; }; }; then\n\t    # We only need to search for static libraries\n\t    continue\n\t  fi\n\tfi\n\n\tlink_static=no # Whether the deplib will be linked statically\n\tuse_static_libs=$prefer_static_libs\n\tif test \"$use_static_libs\" = built && test \"$installed\" = yes; then\n\t  use_static_libs=no\n\tfi\n\tif test -n \"$library_names\" &&\n\t   { test \"$use_static_libs\" = no || test -z \"$old_library\"; }; then\n\t  case $host in\n\t  *cygwin* | *mingw* | *cegcc*)\n\t      # No point in relinking DLLs because paths are not encoded\n\t      notinst_deplibs=\"$notinst_deplibs $lib\"\n\t      need_relink=no\n\t    ;;\n\t  *)\n\t    if test \"$installed\" = no; then\n\t      notinst_deplibs=\"$notinst_deplibs $lib\"\n\t      need_relink=yes\n\t    fi\n\t    ;;\n\t  esac\n\t  # This is a shared library\n\n\t  # Warn about portability, can't link against -module's on some\n\t  # systems (darwin).  Don't bleat about dlopened modules though!\n\t  dlopenmodule=\"\"\n\t  for dlpremoduletest in $dlprefiles; do\n\t    if test \"X$dlpremoduletest\" = \"X$lib\"; then\n\t      dlopenmodule=\"$dlpremoduletest\"\n\t      break\n\t    fi\n\t  done\n\t  if test -z \"$dlopenmodule\" && test \"$shouldnotlink\" = yes && test \"$pass\" = link; then\n\t    echo\n\t    if test \"$linkmode\" = prog; then\n\t      $ECHO \"*** Warning: Linking the executable $output against the loadable module\"\n\t    else\n\t      $ECHO \"*** Warning: Linking the shared library $output against the loadable module\"\n\t    fi\n\t    $ECHO \"*** $linklib is not portable!\"\n\t  fi\n\t  if test \"$linkmode\" = lib &&\n\t     test \"$hardcode_into_libs\" = yes; then\n\t    # Hardcode the library path.\n\t    # Skip directories that are in the system default run-time\n\t    # search path.\n\t    case \" $sys_lib_dlsearch_path \" in\n\t    *\" $absdir \"*) ;;\n\t    *)\n\t      case \"$compile_rpath \" in\n\t      *\" $absdir \"*) ;;\n\t      *) compile_rpath=\"$compile_rpath $absdir\"\n\t      esac\n\t      ;;\n\t    esac\n\t    case \" $sys_lib_dlsearch_path \" in\n\t    *\" $libdir \"*) ;;\n\t    *)\n\t      case \"$finalize_rpath \" in\n\t      *\" $libdir \"*) ;;\n\t      *) finalize_rpath=\"$finalize_rpath $libdir\"\n\t      esac\n\t      ;;\n\t    esac\n\t  fi\n\n\t  if test -n \"$old_archive_from_expsyms_cmds\"; then\n\t    # figure out the soname\n\t    set dummy $library_names\n\t    shift\n\t    realname=\"$1\"\n\t    shift\n\t    eval \"libname=\\\"$libname_spec\\\"\"\n\t    # use dlname if we got it. it's perfectly good, no?\n\t    if test -n \"$dlname\"; then\n\t      soname=\"$dlname\"\n\t    elif test -n \"$soname_spec\"; then\n\t      # bleh windows\n\t      case $host in\n\t      *cygwin* | mingw* | *cegcc*)\n\t        func_arith $current - $age\n\t\tmajor=$func_arith_result\n\t\tversuffix=\"-$major\"\n\t\t;;\n\t      esac\n\t      eval \"soname=\\\"$soname_spec\\\"\"\n\t    else\n\t      soname=\"$realname\"\n\t    fi\n\n\t    # Make a new name for the extract_expsyms_cmds to use\n\t    soroot=\"$soname\"\n\t    func_basename \"$soroot\"\n\t    soname=\"$func_basename_result\"\n\t    func_stripname 'lib' '.dll' \"$soname\"\n\t    newlib=libimp-$func_stripname_result.a\n\n\t    # If the library has no export list, then create one now\n\t    if test -f \"$output_objdir/$soname-def\"; then :\n\t    else\n\t      func_verbose \"extracting exported symbol list from \\`$soname'\"\n\t      func_execute_cmds \"$extract_expsyms_cmds\" 'exit $?'\n\t    fi\n\n\t    # Create $newlib\n\t    if test -f \"$output_objdir/$newlib\"; then :; else\n\t      func_verbose \"generating import library for \\`$soname'\"\n\t      func_execute_cmds \"$old_archive_from_expsyms_cmds\" 'exit $?'\n\t    fi\n\t    # make sure the library variables are pointing to the new library\n\t    dir=$output_objdir\n\t    linklib=$newlib\n\t  fi # test -n \"$old_archive_from_expsyms_cmds\"\n\n\t  if test \"$linkmode\" = prog || test \"$mode\" != relink; then\n\t    add_shlibpath=\n\t    add_dir=\n\t    add=\n\t    lib_linked=yes\n\t    case $hardcode_action in\n\t    immediate | unsupported)\n\t      if test \"$hardcode_direct\" = no; then\n\t\tadd=\"$dir/$linklib\"\n\t\tcase $host in\n\t\t  *-*-sco3.2v5.0.[024]*) add_dir=\"-L$dir\" ;;\n\t\t  *-*-sysv4*uw2*) add_dir=\"-L$dir\" ;;\n\t\t  *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \\\n\t\t    *-*-unixware7*) add_dir=\"-L$dir\" ;;\n\t\t  *-*-darwin* )\n\t\t    # if the lib is a (non-dlopened) module then we can not\n\t\t    # link against it, someone is ignoring the earlier warnings\n\t\t    if /usr/bin/file -L $add 2> /dev/null |\n\t\t\t $GREP \": [^:]* bundle\" >/dev/null ; then\n\t\t      if test \"X$dlopenmodule\" != \"X$lib\"; then\n\t\t\t$ECHO \"*** Warning: lib $linklib is a module, not a shared library\"\n\t\t\tif test -z \"$old_library\" ; then\n\t\t\t  echo\n\t\t\t  echo \"*** And there doesn't seem to be a static archive available\"\n\t\t\t  echo \"*** The link will probably fail, sorry\"\n\t\t\telse\n\t\t\t  add=\"$dir/$old_library\"\n\t\t\tfi\n\t\t      elif test -n \"$old_library\"; then\n\t\t\tadd=\"$dir/$old_library\"\n\t\t      fi\n\t\t    fi\n\t\tesac\n\t      elif test \"$hardcode_minus_L\" = no; then\n\t\tcase $host in\n\t\t*-*-sunos*) add_shlibpath=\"$dir\" ;;\n\t\tesac\n\t\tadd_dir=\"-L$dir\"\n\t\tadd=\"-l$name\"\n\t      elif test \"$hardcode_shlibpath_var\" = no; then\n\t\tadd_shlibpath=\"$dir\"\n\t\tadd=\"-l$name\"\n\t      else\n\t\tlib_linked=no\n\t      fi\n\t      ;;\n\t    relink)\n\t      if test \"$hardcode_direct\" = yes &&\n\t         test \"$hardcode_direct_absolute\" = no; then\n\t\tadd=\"$dir/$linklib\"\n\t      elif test \"$hardcode_minus_L\" = yes; then\n\t\tadd_dir=\"-L$absdir\"\n\t\t# Try looking first in the location we're being installed to.\n\t\tif test -n \"$inst_prefix_dir\"; then\n\t\t  case $libdir in\n\t\t    [\\\\/]*)\n\t\t      add_dir=\"$add_dir -L$inst_prefix_dir$libdir\"\n\t\t      ;;\n\t\t  esac\n\t\tfi\n\t\tadd=\"-l$name\"\n\t      elif test \"$hardcode_shlibpath_var\" = yes; then\n\t\tadd_shlibpath=\"$dir\"\n\t\tadd=\"-l$name\"\n\t      else\n\t\tlib_linked=no\n\t      fi\n\t      ;;\n\t    *) lib_linked=no ;;\n\t    esac\n\n\t    if test \"$lib_linked\" != yes; then\n\t      func_fatal_configuration \"unsupported hardcode properties\"\n\t    fi\n\n\t    if test -n \"$add_shlibpath\"; then\n\t      case :$compile_shlibpath: in\n\t      *\":$add_shlibpath:\"*) ;;\n\t      *) compile_shlibpath=\"$compile_shlibpath$add_shlibpath:\" ;;\n\t      esac\n\t    fi\n\t    if test \"$linkmode\" = prog; then\n\t      test -n \"$add_dir\" && compile_deplibs=\"$add_dir $compile_deplibs\"\n\t      test -n \"$add\" && compile_deplibs=\"$add $compile_deplibs\"\n\t    else\n\t      test -n \"$add_dir\" && deplibs=\"$add_dir $deplibs\"\n\t      test -n \"$add\" && deplibs=\"$add $deplibs\"\n\t      if test \"$hardcode_direct\" != yes &&\n\t\t test \"$hardcode_minus_L\" != yes &&\n\t\t test \"$hardcode_shlibpath_var\" = yes; then\n\t\tcase :$finalize_shlibpath: in\n\t\t*\":$libdir:\"*) ;;\n\t\t*) finalize_shlibpath=\"$finalize_shlibpath$libdir:\" ;;\n\t\tesac\n\t      fi\n\t    fi\n\t  fi\n\n\t  if test \"$linkmode\" = prog || test \"$mode\" = relink; then\n\t    add_shlibpath=\n\t    add_dir=\n\t    add=\n\t    # Finalize command for both is simple: just hardcode it.\n\t    if test \"$hardcode_direct\" = yes &&\n\t       test \"$hardcode_direct_absolute\" = no; then\n\t      add=\"$libdir/$linklib\"\n\t    elif test \"$hardcode_minus_L\" = yes; then\n\t      add_dir=\"-L$libdir\"\n\t      add=\"-l$name\"\n\t    elif test \"$hardcode_shlibpath_var\" = yes; then\n\t      case :$finalize_shlibpath: in\n\t      *\":$libdir:\"*) ;;\n\t      *) finalize_shlibpath=\"$finalize_shlibpath$libdir:\" ;;\n\t      esac\n\t      add=\"-l$name\"\n\t    elif test \"$hardcode_automatic\" = yes; then\n\t      if test -n \"$inst_prefix_dir\" &&\n\t\t test -f \"$inst_prefix_dir$libdir/$linklib\" ; then\n\t\tadd=\"$inst_prefix_dir$libdir/$linklib\"\n\t      else\n\t\tadd=\"$libdir/$linklib\"\n\t      fi\n\t    else\n\t      # We cannot seem to hardcode it, guess we'll fake it.\n\t      add_dir=\"-L$libdir\"\n\t      # Try looking first in the location we're being installed to.\n\t      if test -n \"$inst_prefix_dir\"; then\n\t\tcase $libdir in\n\t\t  [\\\\/]*)\n\t\t    add_dir=\"$add_dir -L$inst_prefix_dir$libdir\"\n\t\t    ;;\n\t\tesac\n\t      fi\n\t      add=\"-l$name\"\n\t    fi\n\n\t    if test \"$linkmode\" = prog; then\n\t      test -n \"$add_dir\" && finalize_deplibs=\"$add_dir $finalize_deplibs\"\n\t      test -n \"$add\" && finalize_deplibs=\"$add $finalize_deplibs\"\n\t    else\n\t      test -n \"$add_dir\" && deplibs=\"$add_dir $deplibs\"\n\t      test -n \"$add\" && deplibs=\"$add $deplibs\"\n\t    fi\n\t  fi\n\telif test \"$linkmode\" = prog; then\n\t  # Here we assume that one of hardcode_direct or hardcode_minus_L\n\t  # is not unsupported.  This is valid on all known static and\n\t  # shared platforms.\n\t  if test \"$hardcode_direct\" != unsupported; then\n\t    test -n \"$old_library\" && linklib=\"$old_library\"\n\t    compile_deplibs=\"$dir/$linklib $compile_deplibs\"\n\t    finalize_deplibs=\"$dir/$linklib $finalize_deplibs\"\n\t  else\n\t    compile_deplibs=\"-l$name -L$dir $compile_deplibs\"\n\t    finalize_deplibs=\"-l$name -L$dir $finalize_deplibs\"\n\t  fi\n\telif test \"$build_libtool_libs\" = yes; then\n\t  # Not a shared library\n\t  if test \"$deplibs_check_method\" != pass_all; then\n\t    # We're trying link a shared library against a static one\n\t    # but the system doesn't support it.\n\n\t    # Just print a warning and add the library to dependency_libs so\n\t    # that the program can be linked against the static library.\n\t    echo\n\t    $ECHO \"*** Warning: This system can not link to static lib archive $lib.\"\n\t    echo \"*** I have the capability to make that library automatically link in when\"\n\t    echo \"*** you link to this library.  But I can only do this if you have a\"\n\t    echo \"*** shared version of the library, which you do not appear to have.\"\n\t    if test \"$module\" = yes; then\n\t      echo \"*** But as you try to build a module library, libtool will still create \"\n\t      echo \"*** a static module, that should work as long as the dlopening application\"\n\t      echo \"*** is linked with the -dlopen flag to resolve symbols at runtime.\"\n\t      if test -z \"$global_symbol_pipe\"; then\n\t\techo\n\t\techo \"*** However, this would only work if libtool was able to extract symbol\"\n\t\techo \"*** lists from a program, using \\`nm' or equivalent, but libtool could\"\n\t\techo \"*** not find such a program.  So, this module is probably useless.\"\n\t\techo \"*** \\`nm' from GNU binutils and a full rebuild may help.\"\n\t      fi\n\t      if test \"$build_old_libs\" = no; then\n\t\tbuild_libtool_libs=module\n\t\tbuild_old_libs=yes\n\t      else\n\t\tbuild_libtool_libs=no\n\t      fi\n\t    fi\n\t  else\n\t    deplibs=\"$dir/$old_library $deplibs\"\n\t    link_static=yes\n\t  fi\n\tfi # link shared/static library?\n\n\tif test \"$linkmode\" = lib; then\n\t  if test -n \"$dependency_libs\" &&\n\t     { test \"$hardcode_into_libs\" != yes ||\n\t       test \"$build_old_libs\" = yes ||\n\t       test \"$link_static\" = yes; }; then\n\t    # Extract -R from dependency_libs\n\t    temp_deplibs=\n\t    for libdir in $dependency_libs; do\n\t      case $libdir in\n\t      -R*) func_stripname '-R' '' \"$libdir\"\n\t           temp_xrpath=$func_stripname_result\n\t\t   case \" $xrpath \" in\n\t\t   *\" $temp_xrpath \"*) ;;\n\t\t   *) xrpath=\"$xrpath $temp_xrpath\";;\n\t\t   esac;;\n\t      *) temp_deplibs=\"$temp_deplibs $libdir\";;\n\t      esac\n\t    done\n\t    dependency_libs=\"$temp_deplibs\"\n\t  fi\n\n\t  newlib_search_path=\"$newlib_search_path $absdir\"\n\t  # Link against this library\n\t  test \"$link_static\" = no && newdependency_libs=\"$abs_ladir/$laname $newdependency_libs\"\n\t  # ... and its dependency_libs\n\t  tmp_libs=\n\t  for deplib in $dependency_libs; do\n\t    newdependency_libs=\"$deplib $newdependency_libs\"\n\t    if $opt_duplicate_deps ; then\n\t      case \"$tmp_libs \" in\n\t      *\" $deplib \"*) specialdeplibs=\"$specialdeplibs $deplib\" ;;\n\t      esac\n\t    fi\n\t    tmp_libs=\"$tmp_libs $deplib\"\n\t  done\n\n\t  if test \"$link_all_deplibs\" != no; then\n\t    # Add the search paths of all dependency libraries\n\t    for deplib in $dependency_libs; do\n\t      path=\n\t      case $deplib in\n\t      -L*) path=\"$deplib\" ;;\n\t      *.la)\n\t        func_dirname \"$deplib\" \"\" \".\"\n\t\tdir=\"$func_dirname_result\"\n\t\t# We need an absolute path.\n\t\tcase $dir in\n\t\t[\\\\/]* | [A-Za-z]:[\\\\/]*) absdir=\"$dir\" ;;\n\t\t*)\n\t\t  absdir=`cd \"$dir\" && pwd`\n\t\t  if test -z \"$absdir\"; then\n\t\t    func_warning \"cannot determine absolute directory name of \\`$dir'\"\n\t\t    absdir=\"$dir\"\n\t\t  fi\n\t\t  ;;\n\t\tesac\n\t\tif $GREP \"^installed=no\" $deplib > /dev/null; then\n\t\tcase $host in\n\t\t*-*-darwin*)\n\t\t  depdepl=\n\t\t  deplibrary_names=`${SED} -n -e 's/^library_names=\\(.*\\)$/\\1/p' $deplib`\n\t\t  if test -n \"$deplibrary_names\" ; then\n\t\t    for tmp in $deplibrary_names ; do\n\t\t      depdepl=$tmp\n\t\t    done\n\t\t    if test -f \"$absdir/$objdir/$depdepl\" ; then\n\t\t      depdepl=\"$absdir/$objdir/$depdepl\"\n\t\t      darwin_install_name=`${OTOOL} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'`\n                      if test -z \"$darwin_install_name\"; then\n                          darwin_install_name=`${OTOOL64} -L $depdepl  | awk '{if (NR == 2) {print $1;exit}}'`\n                      fi\n\t\t      compiler_flags=\"$compiler_flags ${wl}-dylib_file ${wl}${darwin_install_name}:${depdepl}\"\n\t\t      linker_flags=\"$linker_flags -dylib_file ${darwin_install_name}:${depdepl}\"\n\t\t      path=\n\t\t    fi\n\t\t  fi\n\t\t  ;;\n\t\t*)\n\t\t  path=\"-L$absdir/$objdir\"\n\t\t  ;;\n\t\tesac\n\t\telse\n\t\t  libdir=`${SED} -n -e 's/^libdir=\\(.*\\)$/\\1/p' $deplib`\n\t\t  test -z \"$libdir\" && \\\n\t\t    func_fatal_error \"\\`$deplib' is not a valid libtool archive\"\n\t\t  test \"$absdir\" != \"$libdir\" && \\\n\t\t    func_warning \"\\`$deplib' seems to be moved\"\n\n\t\t  path=\"-L$absdir\"\n\t\tfi\n\t\t;;\n\t      esac\n\t      case \" $deplibs \" in\n\t      *\" $path \"*) ;;\n\t      *) deplibs=\"$path $deplibs\" ;;\n\t      esac\n\t    done\n\t  fi # link_all_deplibs != no\n\tfi # linkmode = lib\n      done # for deplib in $libs\n      if test \"$pass\" = link; then\n\tif test \"$linkmode\" = \"prog\"; then\n\t  compile_deplibs=\"$new_inherited_linker_flags $compile_deplibs\"\n\t  finalize_deplibs=\"$new_inherited_linker_flags $finalize_deplibs\"\n\telse\n\t  compiler_flags=\"$compiler_flags \"`$ECHO \" $new_inherited_linker_flags\" | $SED 's% \\([^ $]*\\).ltframework% -framework \\1%g'`\n\tfi\n      fi\n      dependency_libs=\"$newdependency_libs\"\n      if test \"$pass\" = dlpreopen; then\n\t# Link the dlpreopened libraries before other libraries\n\tfor deplib in $save_deplibs; do\n\t  deplibs=\"$deplib $deplibs\"\n\tdone\n      fi\n      if test \"$pass\" != dlopen; then\n\tif test \"$pass\" != conv; then\n\t  # Make sure lib_search_path contains only unique directories.\n\t  lib_search_path=\n\t  for dir in $newlib_search_path; do\n\t    case \"$lib_search_path \" in\n\t    *\" $dir \"*) ;;\n\t    *) lib_search_path=\"$lib_search_path $dir\" ;;\n\t    esac\n\t  done\n\t  newlib_search_path=\n\tfi\n\n\tif test \"$linkmode,$pass\" != \"prog,link\"; then\n\t  vars=\"deplibs\"\n\telse\n\t  vars=\"compile_deplibs finalize_deplibs\"\n\tfi\n\tfor var in $vars dependency_libs; do\n\t  # Add libraries to $var in reverse order\n\t  eval tmp_libs=\\$$var\n\t  new_libs=\n\t  for deplib in $tmp_libs; do\n\t    # FIXME: Pedantically, this is the right thing to do, so\n\t    #        that some nasty dependency loop isn't accidentally\n\t    #        broken:\n\t    #new_libs=\"$deplib $new_libs\"\n\t    # Pragmatically, this seems to cause very few problems in\n\t    # practice:\n\t    case $deplib in\n\t    -L*) new_libs=\"$deplib $new_libs\" ;;\n\t    -R*) ;;\n\t    *)\n\t      # And here is the reason: when a library appears more\n\t      # than once as an explicit dependence of a library, or\n\t      # is implicitly linked in more than once by the\n\t      # compiler, it is considered special, and multiple\n\t      # occurrences thereof are not removed.  Compare this\n\t      # with having the same library being listed as a\n\t      # dependency of multiple other libraries: in this case,\n\t      # we know (pedantically, we assume) the library does not\n\t      # need to be listed more than once, so we keep only the\n\t      # last copy.  This is not always right, but it is rare\n\t      # enough that we require users that really mean to play\n\t      # such unportable linking tricks to link the library\n\t      # using -Wl,-lname, so that libtool does not consider it\n\t      # for duplicate removal.\n\t      case \" $specialdeplibs \" in\n\t      *\" $deplib \"*) new_libs=\"$deplib $new_libs\" ;;\n\t      *)\n\t\tcase \" $new_libs \" in\n\t\t*\" $deplib \"*) ;;\n\t\t*) new_libs=\"$deplib $new_libs\" ;;\n\t\tesac\n\t\t;;\n\t      esac\n\t      ;;\n\t    esac\n\t  done\n\t  tmp_libs=\n\t  for deplib in $new_libs; do\n\t    case $deplib in\n\t    -L*)\n\t      case \" $tmp_libs \" in\n\t      *\" $deplib \"*) ;;\n\t      *) tmp_libs=\"$tmp_libs $deplib\" ;;\n\t      esac\n\t      ;;\n\t    *) tmp_libs=\"$tmp_libs $deplib\" ;;\n\t    esac\n\t  done\n\t  eval $var=\\$tmp_libs\n\tdone # for var\n      fi\n      # Last step: remove runtime libs from dependency_libs\n      # (they stay in deplibs)\n      tmp_libs=\n      for i in $dependency_libs ; do\n\tcase \" $predeps $postdeps $compiler_lib_search_path \" in\n\t*\" $i \"*)\n\t  i=\"\"\n\t  ;;\n\tesac\n\tif test -n \"$i\" ; then\n\t  tmp_libs=\"$tmp_libs $i\"\n\tfi\n      done\n      dependency_libs=$tmp_libs\n    done # for pass\n    if test \"$linkmode\" = prog; then\n      dlfiles=\"$newdlfiles\"\n    fi\n    if test \"$linkmode\" = prog || test \"$linkmode\" = lib; then\n      dlprefiles=\"$newdlprefiles\"\n    fi\n\n    case $linkmode in\n    oldlib)\n      if test -n \"$dlfiles$dlprefiles\" || test \"$dlself\" != no; then\n\tfunc_warning \"\\`-dlopen' is ignored for archives\"\n      fi\n\n      case \" $deplibs\" in\n      *\\ -l* | *\\ -L*)\n\tfunc_warning \"\\`-l' and \\`-L' are ignored for archives\" ;;\n      esac\n\n      test -n \"$rpath\" && \\\n\tfunc_warning \"\\`-rpath' is ignored for archives\"\n\n      test -n \"$xrpath\" && \\\n\tfunc_warning \"\\`-R' is ignored for archives\"\n\n      test -n \"$vinfo\" && \\\n\tfunc_warning \"\\`-version-info/-version-number' is ignored for archives\"\n\n      test -n \"$release\" && \\\n\tfunc_warning \"\\`-release' is ignored for archives\"\n\n      test -n \"$export_symbols$export_symbols_regex\" && \\\n\tfunc_warning \"\\`-export-symbols' is ignored for archives\"\n\n      # Now set the variables for building old libraries.\n      build_libtool_libs=no\n      oldlibs=\"$output\"\n      objs=\"$objs$old_deplibs\"\n      ;;\n\n    lib)\n      # Make sure we only generate libraries of the form `libNAME.la'.\n      case $outputname in\n      lib*)\n\tfunc_stripname 'lib' '.la' \"$outputname\"\n\tname=$func_stripname_result\n\teval \"shared_ext=\\\"$shrext_cmds\\\"\"\n\teval \"libname=\\\"$libname_spec\\\"\"\n\t;;\n      *)\n\ttest \"$module\" = no && \\\n\t  func_fatal_help \"libtool library \\`$output' must begin with \\`lib'\"\n\n\tif test \"$need_lib_prefix\" != no; then\n\t  # Add the \"lib\" prefix for modules if required\n\t  func_stripname '' '.la' \"$outputname\"\n\t  name=$func_stripname_result\n\t  eval \"shared_ext=\\\"$shrext_cmds\\\"\"\n\t  eval \"libname=\\\"$libname_spec\\\"\"\n\telse\n\t  func_stripname '' '.la' \"$outputname\"\n\t  libname=$func_stripname_result\n\tfi\n\t;;\n      esac\n\n      if test -n \"$objs\"; then\n\tif test \"$deplibs_check_method\" != pass_all; then\n\t  func_fatal_error \"cannot build libtool library \\`$output' from non-libtool objects on this host:$objs\"\n\telse\n\t  echo\n\t  $ECHO \"*** Warning: Linking the shared library $output against the non-libtool\"\n\t  $ECHO \"*** objects $objs is not portable!\"\n\t  libobjs=\"$libobjs $objs\"\n\tfi\n      fi\n\n      test \"$dlself\" != no && \\\n\tfunc_warning \"\\`-dlopen self' is ignored for libtool libraries\"\n\n      set dummy $rpath\n      shift\n      test \"$#\" -gt 1 && \\\n\tfunc_warning \"ignoring multiple \\`-rpath's for a libtool library\"\n\n      install_libdir=\"$1\"\n\n      oldlibs=\n      if test -z \"$rpath\"; then\n\tif test \"$build_libtool_libs\" = yes; then\n\t  # Building a libtool convenience library.\n\t  # Some compilers have problems with a `.al' extension so\n\t  # convenience libraries should have the same extension an\n\t  # archive normally would.\n\t  oldlibs=\"$output_objdir/$libname.$libext $oldlibs\"\n\t  build_libtool_libs=convenience\n\t  build_old_libs=yes\n\tfi\n\n\ttest -n \"$vinfo\" && \\\n\t  func_warning \"\\`-version-info/-version-number' is ignored for convenience libraries\"\n\n\ttest -n \"$release\" && \\\n\t  func_warning \"\\`-release' is ignored for convenience libraries\"\n      else\n\n\t# Parse the version information argument.\n\tsave_ifs=\"$IFS\"; IFS=':'\n\tset dummy $vinfo 0 0 0\n\tshift\n\tIFS=\"$save_ifs\"\n\n\ttest -n \"$7\" && \\\n\t  func_fatal_help \"too many parameters to \\`-version-info'\"\n\n\t# convert absolute version numbers to libtool ages\n\t# this retains compatibility with .la files and attempts\n\t# to make the code below a bit more comprehensible\n\n\tcase $vinfo_number in\n\tyes)\n\t  number_major=\"$1\"\n\t  number_minor=\"$2\"\n\t  number_revision=\"$3\"\n\t  #\n\t  # There are really only two kinds -- those that\n\t  # use the current revision as the major version\n\t  # and those that subtract age and use age as\n\t  # a minor version.  But, then there is irix\n\t  # which has an extra 1 added just for fun\n\t  #\n\t  case $version_type in\n\t  darwin|linux|osf|windows|none)\n\t    func_arith $number_major + $number_minor\n\t    current=$func_arith_result\n\t    age=\"$number_minor\"\n\t    revision=\"$number_revision\"\n\t    ;;\n\t  freebsd-aout|freebsd-elf|qnx|sunos)\n\t    current=\"$number_major\"\n\t    revision=\"$number_minor\"\n\t    age=\"0\"\n\t    ;;\n\t  irix|nonstopux)\n\t    func_arith $number_major + $number_minor\n\t    current=$func_arith_result\n\t    age=\"$number_minor\"\n\t    revision=\"$number_minor\"\n\t    lt_irix_increment=no\n\t    ;;\n\t  esac\n\t  ;;\n\tno)\n\t  current=\"$1\"\n\t  revision=\"$2\"\n\t  age=\"$3\"\n\t  ;;\n\tesac\n\n\t# Check that each of the things are valid numbers.\n\tcase $current in\n\t0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;\n\t*)\n\t  func_error \"CURRENT \\`$current' must be a nonnegative integer\"\n\t  func_fatal_error \"\\`$vinfo' is not valid version information\"\n\t  ;;\n\tesac\n\n\tcase $revision in\n\t0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;\n\t*)\n\t  func_error \"REVISION \\`$revision' must be a nonnegative integer\"\n\t  func_fatal_error \"\\`$vinfo' is not valid version information\"\n\t  ;;\n\tesac\n\n\tcase $age in\n\t0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;\n\t*)\n\t  func_error \"AGE \\`$age' must be a nonnegative integer\"\n\t  func_fatal_error \"\\`$vinfo' is not valid version information\"\n\t  ;;\n\tesac\n\n\tif test \"$age\" -gt \"$current\"; then\n\t  func_error \"AGE \\`$age' is greater than the current interface number \\`$current'\"\n\t  func_fatal_error \"\\`$vinfo' is not valid version information\"\n\tfi\n\n\t# Calculate the version variables.\n\tmajor=\n\tversuffix=\n\tverstring=\n\tcase $version_type in\n\tnone) ;;\n\n\tdarwin)\n\t  # Like Linux, but with the current version available in\n\t  # verstring for coding it into the library header\n\t  func_arith $current - $age\n\t  major=.$func_arith_result\n\t  versuffix=\"$major.$age.$revision\"\n\t  # Darwin ld doesn't like 0 for these options...\n\t  func_arith $current + 1\n\t  minor_current=$func_arith_result\n\t  xlcverstring=\"${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision\"\n\t  verstring=\"-compatibility_version $minor_current -current_version $minor_current.$revision\"\n\t  ;;\n\n\tfreebsd-aout)\n\t  major=\".$current\"\n\t  versuffix=\".$current.$revision\";\n\t  ;;\n\n\tfreebsd-elf)\n\t  major=\".$current\"\n\t  versuffix=\".$current\"\n\t  ;;\n\n\tirix | nonstopux)\n\t  if test \"X$lt_irix_increment\" = \"Xno\"; then\n\t    func_arith $current - $age\n\t  else\n\t    func_arith $current - $age + 1\n\t  fi\n\t  major=$func_arith_result\n\n\t  case $version_type in\n\t    nonstopux) verstring_prefix=nonstopux ;;\n\t    *)         verstring_prefix=sgi ;;\n\t  esac\n\t  verstring=\"$verstring_prefix$major.$revision\"\n\n\t  # Add in all the interfaces that we are compatible with.\n\t  loop=$revision\n\t  while test \"$loop\" -ne 0; do\n\t    func_arith $revision - $loop\n\t    iface=$func_arith_result\n\t    func_arith $loop - 1\n\t    loop=$func_arith_result\n\t    verstring=\"$verstring_prefix$major.$iface:$verstring\"\n\t  done\n\n\t  # Before this point, $major must not contain `.'.\n\t  major=.$major\n\t  versuffix=\"$major.$revision\"\n\t  ;;\n\n\tlinux)\n\t  func_arith $current - $age\n\t  major=.$func_arith_result\n\t  versuffix=\"$major.$age.$revision\"\n\t  ;;\n\n\tosf)\n\t  func_arith $current - $age\n\t  major=.$func_arith_result\n\t  versuffix=\".$current.$age.$revision\"\n\t  verstring=\"$current.$age.$revision\"\n\n\t  # Add in all the interfaces that we are compatible with.\n\t  loop=$age\n\t  while test \"$loop\" -ne 0; do\n\t    func_arith $current - $loop\n\t    iface=$func_arith_result\n\t    func_arith $loop - 1\n\t    loop=$func_arith_result\n\t    verstring=\"$verstring:${iface}.0\"\n\t  done\n\n\t  # Make executables depend on our current version.\n\t  verstring=\"$verstring:${current}.0\"\n\t  ;;\n\n\tqnx)\n\t  major=\".$current\"\n\t  versuffix=\".$current\"\n\t  ;;\n\n\tsunos)\n\t  major=\".$current\"\n\t  versuffix=\".$current.$revision\"\n\t  ;;\n\n\twindows)\n\t  # Use '-' rather than '.', since we only want one\n\t  # extension on DOS 8.3 filesystems.\n\t  func_arith $current - $age\n\t  major=$func_arith_result\n\t  versuffix=\"-$major\"\n\t  ;;\n\n\t*)\n\t  func_fatal_configuration \"unknown library version type \\`$version_type'\"\n\t  ;;\n\tesac\n\n\t# Clear the version info if we defaulted, and they specified a release.\n\tif test -z \"$vinfo\" && test -n \"$release\"; then\n\t  major=\n\t  case $version_type in\n\t  darwin)\n\t    # we can't check for \"0.0\" in archive_cmds due to quoting\n\t    # problems, so we reset it completely\n\t    verstring=\n\t    ;;\n\t  *)\n\t    verstring=\"0.0\"\n\t    ;;\n\t  esac\n\t  if test \"$need_version\" = no; then\n\t    versuffix=\n\t  else\n\t    versuffix=\".0.0\"\n\t  fi\n\tfi\n\n\t# Remove version info from name if versioning should be avoided\n\tif test \"$avoid_version\" = yes && test \"$need_version\" = no; then\n\t  major=\n\t  versuffix=\n\t  verstring=\"\"\n\tfi\n\n\t# Check to see if the archive will have undefined symbols.\n\tif test \"$allow_undefined\" = yes; then\n\t  if test \"$allow_undefined_flag\" = unsupported; then\n\t    func_warning \"undefined symbols not allowed in $host shared libraries\"\n\t    build_libtool_libs=no\n\t    build_old_libs=yes\n\t  fi\n\telse\n\t  # Don't allow undefined symbols.\n\t  allow_undefined_flag=\"$no_undefined_flag\"\n\tfi\n\n      fi\n\n      func_generate_dlsyms \"$libname\" \"$libname\" \"yes\"\n      libobjs=\"$libobjs $symfileobj\"\n      test \"X$libobjs\" = \"X \" && libobjs=\n\n      if test \"$mode\" != relink; then\n\t# Remove our outputs, but don't remove object files since they\n\t# may have been created when compiling PIC objects.\n\tremovelist=\n\ttempremovelist=`$ECHO \"$output_objdir/*\"`\n\tfor p in $tempremovelist; do\n\t  case $p in\n\t    *.$objext | *.gcno)\n\t       ;;\n\t    $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*)\n\t       if test \"X$precious_files_regex\" != \"X\"; then\n\t\t if $ECHO \"$p\" | $EGREP -e \"$precious_files_regex\" >/dev/null 2>&1\n\t\t then\n\t\t   continue\n\t\t fi\n\t       fi\n\t       removelist=\"$removelist $p\"\n\t       ;;\n\t    *) ;;\n\t  esac\n\tdone\n\ttest -n \"$removelist\" && \\\n\t  func_show_eval \"${RM}r \\$removelist\"\n      fi\n\n      # Now set the variables for building old libraries.\n      if test \"$build_old_libs\" = yes && test \"$build_libtool_libs\" != convenience ; then\n\toldlibs=\"$oldlibs $output_objdir/$libname.$libext\"\n\n\t# Transform .lo files to .o files.\n\toldobjs=\"$objs \"`$ECHO \"$libobjs\" | $SP2NL | $SED \"/\\.${libext}$/d; $lo2o\" | $NL2SP`\n      fi\n\n      # Eliminate all temporary directories.\n      #for path in $notinst_path; do\n      #\tlib_search_path=`$ECHO \"$lib_search_path \" | $SED \"s% $path % %g\"`\n      #\tdeplibs=`$ECHO \"$deplibs \" | $SED \"s% -L$path % %g\"`\n      #\tdependency_libs=`$ECHO \"$dependency_libs \" | $SED \"s% -L$path % %g\"`\n      #done\n\n      if test -n \"$xrpath\"; then\n\t# If the user specified any rpath flags, then add them.\n\ttemp_xrpath=\n\tfor libdir in $xrpath; do\n\t  temp_xrpath=\"$temp_xrpath -R$libdir\"\n\t  case \"$finalize_rpath \" in\n\t  *\" $libdir \"*) ;;\n\t  *) finalize_rpath=\"$finalize_rpath $libdir\" ;;\n\t  esac\n\tdone\n\tif test \"$hardcode_into_libs\" != yes || test \"$build_old_libs\" = yes; then\n\t  dependency_libs=\"$temp_xrpath $dependency_libs\"\n\tfi\n      fi\n\n      # Make sure dlfiles contains only unique files that won't be dlpreopened\n      old_dlfiles=\"$dlfiles\"\n      dlfiles=\n      for lib in $old_dlfiles; do\n\tcase \" $dlprefiles $dlfiles \" in\n\t*\" $lib \"*) ;;\n\t*) dlfiles=\"$dlfiles $lib\" ;;\n\tesac\n      done\n\n      # Make sure dlprefiles contains only unique files\n      old_dlprefiles=\"$dlprefiles\"\n      dlprefiles=\n      for lib in $old_dlprefiles; do\n\tcase \"$dlprefiles \" in\n\t*\" $lib \"*) ;;\n\t*) dlprefiles=\"$dlprefiles $lib\" ;;\n\tesac\n      done\n\n      if test \"$build_libtool_libs\" = yes; then\n\tif test -n \"$rpath\"; then\n\t  case $host in\n\t  *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*)\n\t    # these systems don't actually have a c library (as such)!\n\t    ;;\n\t  *-*-rhapsody* | *-*-darwin1.[012])\n\t    # Rhapsody C library is in the System framework\n\t    deplibs=\"$deplibs System.ltframework\"\n\t    ;;\n\t  *-*-netbsd*)\n\t    # Don't link with libc until the a.out ld.so is fixed.\n\t    ;;\n\t  *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)\n\t    # Do not include libc due to us having libc/libc_r.\n\t    ;;\n\t  *-*-sco3.2v5* | *-*-sco5v6*)\n\t    # Causes problems with __ctype\n\t    ;;\n\t  *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)\n\t    # Compiler inserts libc in the correct place for threads to work\n\t    ;;\n\t  *)\n\t    # Add libc to deplibs on all other systems if necessary.\n\t    if test \"$build_libtool_need_lc\" = \"yes\"; then\n\t      deplibs=\"$deplibs -lc\"\n\t    fi\n\t    ;;\n\t  esac\n\tfi\n\n\t# Transform deplibs into only deplibs that can be linked in shared.\n\tname_save=$name\n\tlibname_save=$libname\n\trelease_save=$release\n\tversuffix_save=$versuffix\n\tmajor_save=$major\n\t# I'm not sure if I'm treating the release correctly.  I think\n\t# release should show up in the -l (ie -lgmp5) so we don't want to\n\t# add it in twice.  Is that correct?\n\trelease=\"\"\n\tversuffix=\"\"\n\tmajor=\"\"\n\tnewdeplibs=\n\tdroppeddeps=no\n\tcase $deplibs_check_method in\n\tpass_all)\n\t  # Don't check for shared/static.  Everything works.\n\t  # This might be a little naive.  We might want to check\n\t  # whether the library exists or not.  But this is on\n\t  # osf3 & osf4 and I'm not really sure... Just\n\t  # implementing what was already the behavior.\n\t  newdeplibs=$deplibs\n\t  ;;\n\ttest_compile)\n\t  # This code stresses the \"libraries are programs\" paradigm to its\n\t  # limits. Maybe even breaks it.  We compile a program, linking it\n\t  # against the deplibs as a proxy for the library.  Then we can check\n\t  # whether they linked in statically or dynamically with ldd.\n\t  $opt_dry_run || $RM conftest.c\n\t  cat > conftest.c <<EOF\n\t  int main() { return 0; }\nEOF\n\t  $opt_dry_run || $RM conftest\n\t  if $LTCC $LTCFLAGS -o conftest conftest.c $deplibs; then\n\t    ldd_output=`ldd conftest`\n\t    for i in $deplibs; do\n\t      case $i in\n\t      -l*)\n\t\tfunc_stripname -l '' \"$i\"\n\t\tname=$func_stripname_result\n\t\tif test \"X$allow_libtool_libs_with_static_runtimes\" = \"Xyes\" ; then\n\t\t  case \" $predeps $postdeps \" in\n\t\t  *\" $i \"*)\n\t\t    newdeplibs=\"$newdeplibs $i\"\n\t\t    i=\"\"\n\t\t    ;;\n\t\t  esac\n\t\tfi\n\t\tif test -n \"$i\" ; then\n\t\t  eval \"libname=\\\"$libname_spec\\\"\"\n\t\t  eval \"deplib_matches=\\\"$library_names_spec\\\"\"\n\t\t  set dummy $deplib_matches; shift\n\t\t  deplib_match=$1\n\t\t  if test `expr \"$ldd_output\" : \".*$deplib_match\"` -ne 0 ; then\n\t\t    newdeplibs=\"$newdeplibs $i\"\n\t\t  else\n\t\t    droppeddeps=yes\n\t\t    echo\n\t\t    $ECHO \"*** Warning: dynamic linker does not accept needed library $i.\"\n\t\t    echo \"*** I have the capability to make that library automatically link in when\"\n\t\t    echo \"*** you link to this library.  But I can only do this if you have a\"\n\t\t    echo \"*** shared version of the library, which I believe you do not have\"\n\t\t    echo \"*** because a test_compile did reveal that the linker did not use it for\"\n\t\t    echo \"*** its dynamic dependency list that programs get resolved with at runtime.\"\n\t\t  fi\n\t\tfi\n\t\t;;\n\t      *)\n\t\tnewdeplibs=\"$newdeplibs $i\"\n\t\t;;\n\t      esac\n\t    done\n\t  else\n\t    # Error occurred in the first compile.  Let's try to salvage\n\t    # the situation: Compile a separate program for each library.\n\t    for i in $deplibs; do\n\t      case $i in\n\t      -l*)\n\t\tfunc_stripname -l '' \"$i\"\n\t\tname=$func_stripname_result\n\t\t$opt_dry_run || $RM conftest\n\t\tif $LTCC $LTCFLAGS -o conftest conftest.c $i; then\n\t\t  ldd_output=`ldd conftest`\n\t\t  if test \"X$allow_libtool_libs_with_static_runtimes\" = \"Xyes\" ; then\n\t\t    case \" $predeps $postdeps \" in\n\t\t    *\" $i \"*)\n\t\t      newdeplibs=\"$newdeplibs $i\"\n\t\t      i=\"\"\n\t\t      ;;\n\t\t    esac\n\t\t  fi\n\t\t  if test -n \"$i\" ; then\n\t\t    eval \"libname=\\\"$libname_spec\\\"\"\n\t\t    eval \"deplib_matches=\\\"$library_names_spec\\\"\"\n\t\t    set dummy $deplib_matches; shift\n\t\t    deplib_match=$1\n\t\t    if test `expr \"$ldd_output\" : \".*$deplib_match\"` -ne 0 ; then\n\t\t      newdeplibs=\"$newdeplibs $i\"\n\t\t    else\n\t\t      droppeddeps=yes\n\t\t      echo\n\t\t      $ECHO \"*** Warning: dynamic linker does not accept needed library $i.\"\n\t\t      echo \"*** I have the capability to make that library automatically link in when\"\n\t\t      echo \"*** you link to this library.  But I can only do this if you have a\"\n\t\t      echo \"*** shared version of the library, which you do not appear to have\"\n\t\t      echo \"*** because a test_compile did reveal that the linker did not use this one\"\n\t\t      echo \"*** as a dynamic dependency that programs can get resolved with at runtime.\"\n\t\t    fi\n\t\t  fi\n\t\telse\n\t\t  droppeddeps=yes\n\t\t  echo\n\t\t  $ECHO \"*** Warning!  Library $i is needed by this library but I was not able to\"\n\t\t  echo \"*** make it link in!  You will probably need to install it or some\"\n\t\t  echo \"*** library that it depends on before this library will be fully\"\n\t\t  echo \"*** functional.  Installing it before continuing would be even better.\"\n\t\tfi\n\t\t;;\n\t      *)\n\t\tnewdeplibs=\"$newdeplibs $i\"\n\t\t;;\n\t      esac\n\t    done\n\t  fi\n\t  ;;\n\tfile_magic*)\n\t  set dummy $deplibs_check_method; shift\n\t  file_magic_regex=`expr \"$deplibs_check_method\" : \"$1 \\(.*\\)\"`\n\t  for a_deplib in $deplibs; do\n\t    case $a_deplib in\n\t    -l*)\n\t      func_stripname -l '' \"$a_deplib\"\n\t      name=$func_stripname_result\n\t      if test \"X$allow_libtool_libs_with_static_runtimes\" = \"Xyes\" ; then\n\t\tcase \" $predeps $postdeps \" in\n\t\t*\" $a_deplib \"*)\n\t\t  newdeplibs=\"$newdeplibs $a_deplib\"\n\t\t  a_deplib=\"\"\n\t\t  ;;\n\t\tesac\n\t      fi\n\t      if test -n \"$a_deplib\" ; then\n\t\teval \"libname=\\\"$libname_spec\\\"\"\n\t\tfor i in $lib_search_path $sys_lib_search_path $shlib_search_path; do\n\t\t  potential_libs=`ls $i/$libname[.-]* 2>/dev/null`\n\t\t  for potent_lib in $potential_libs; do\n\t\t      # Follow soft links.\n\t\t      if ls -lLd \"$potent_lib\" 2>/dev/null |\n\t\t\t $GREP \" -> \" >/dev/null; then\n\t\t\tcontinue\n\t\t      fi\n\t\t      # The statement above tries to avoid entering an\n\t\t      # endless loop below, in case of cyclic links.\n\t\t      # We might still enter an endless loop, since a link\n\t\t      # loop can be closed while we follow links,\n\t\t      # but so what?\n\t\t      potlib=\"$potent_lib\"\n\t\t      while test -h \"$potlib\" 2>/dev/null; do\n\t\t\tpotliblink=`ls -ld $potlib | ${SED} 's/.* -> //'`\n\t\t\tcase $potliblink in\n\t\t\t[\\\\/]* | [A-Za-z]:[\\\\/]*) potlib=\"$potliblink\";;\n\t\t\t*) potlib=`$ECHO \"$potlib\" | $SED 's,[^/]*$,,'`\"$potliblink\";;\n\t\t\tesac\n\t\t      done\n\t\t      if eval \"$file_magic_cmd \\\"\\$potlib\\\"\" 2>/dev/null |\n\t\t\t $SED -e 10q |\n\t\t\t $EGREP \"$file_magic_regex\" > /dev/null; then\n\t\t\tnewdeplibs=\"$newdeplibs $a_deplib\"\n\t\t\ta_deplib=\"\"\n\t\t\tbreak 2\n\t\t      fi\n\t\t  done\n\t\tdone\n\t      fi\n\t      if test -n \"$a_deplib\" ; then\n\t\tdroppeddeps=yes\n\t\techo\n\t\t$ECHO \"*** Warning: linker path does not have real file for library $a_deplib.\"\n\t\techo \"*** I have the capability to make that library automatically link in when\"\n\t\techo \"*** you link to this library.  But I can only do this if you have a\"\n\t\techo \"*** shared version of the library, which you do not appear to have\"\n\t\techo \"*** because I did check the linker path looking for a file starting\"\n\t\tif test -z \"$potlib\" ; then\n\t\t  $ECHO \"*** with $libname but no candidates were found. (...for file magic test)\"\n\t\telse\n\t\t  $ECHO \"*** with $libname and none of the candidates passed a file format test\"\n\t\t  $ECHO \"*** using a file magic. Last file checked: $potlib\"\n\t\tfi\n\t      fi\n\t      ;;\n\t    *)\n\t      # Add a -L argument.\n\t      newdeplibs=\"$newdeplibs $a_deplib\"\n\t      ;;\n\t    esac\n\t  done # Gone through all deplibs.\n\t  ;;\n\tmatch_pattern*)\n\t  set dummy $deplibs_check_method; shift\n\t  match_pattern_regex=`expr \"$deplibs_check_method\" : \"$1 \\(.*\\)\"`\n\t  for a_deplib in $deplibs; do\n\t    case $a_deplib in\n\t    -l*)\n\t      func_stripname -l '' \"$a_deplib\"\n\t      name=$func_stripname_result\n\t      if test \"X$allow_libtool_libs_with_static_runtimes\" = \"Xyes\" ; then\n\t\tcase \" $predeps $postdeps \" in\n\t\t*\" $a_deplib \"*)\n\t\t  newdeplibs=\"$newdeplibs $a_deplib\"\n\t\t  a_deplib=\"\"\n\t\t  ;;\n\t\tesac\n\t      fi\n\t      if test -n \"$a_deplib\" ; then\n\t\teval \"libname=\\\"$libname_spec\\\"\"\n\t\tfor i in $lib_search_path $sys_lib_search_path $shlib_search_path; do\n\t\t  potential_libs=`ls $i/$libname[.-]* 2>/dev/null`\n\t\t  for potent_lib in $potential_libs; do\n\t\t    potlib=\"$potent_lib\" # see symlink-check above in file_magic test\n\t\t    if eval \"\\$ECHO \\\"$potent_lib\\\"\" 2>/dev/null | $SED 10q | \\\n\t\t       $EGREP \"$match_pattern_regex\" > /dev/null; then\n\t\t      newdeplibs=\"$newdeplibs $a_deplib\"\n\t\t      a_deplib=\"\"\n\t\t      break 2\n\t\t    fi\n\t\t  done\n\t\tdone\n\t      fi\n\t      if test -n \"$a_deplib\" ; then\n\t\tdroppeddeps=yes\n\t\techo\n\t\t$ECHO \"*** Warning: linker path does not have real file for library $a_deplib.\"\n\t\techo \"*** I have the capability to make that library automatically link in when\"\n\t\techo \"*** you link to this library.  But I can only do this if you have a\"\n\t\techo \"*** shared version of the library, which you do not appear to have\"\n\t\techo \"*** because I did check the linker path looking for a file starting\"\n\t\tif test -z \"$potlib\" ; then\n\t\t  $ECHO \"*** with $libname but no candidates were found. (...for regex pattern test)\"\n\t\telse\n\t\t  $ECHO \"*** with $libname and none of the candidates passed a file format test\"\n\t\t  $ECHO \"*** using a regex pattern. Last file checked: $potlib\"\n\t\tfi\n\t      fi\n\t      ;;\n\t    *)\n\t      # Add a -L argument.\n\t      newdeplibs=\"$newdeplibs $a_deplib\"\n\t      ;;\n\t    esac\n\t  done # Gone through all deplibs.\n\t  ;;\n\tnone | unknown | *)\n\t  newdeplibs=\"\"\n\t  tmp_deplibs=`$ECHO \" $deplibs\" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'`\n\t  if test \"X$allow_libtool_libs_with_static_runtimes\" = \"Xyes\" ; then\n\t    for i in $predeps $postdeps ; do\n\t      # can't use Xsed below, because $i might contain '/'\n\t      tmp_deplibs=`$ECHO \" $tmp_deplibs\" | $SED \"s,$i,,\"`\n\t    done\n\t  fi\n\t  case $tmp_deplibs in\n\t  *[!\\\t\\ ]*)\n\t    echo\n\t    if test \"X$deplibs_check_method\" = \"Xnone\"; then\n\t      echo \"*** Warning: inter-library dependencies are not supported in this platform.\"\n\t    else\n\t      echo \"*** Warning: inter-library dependencies are not known to be supported.\"\n\t    fi\n\t    echo \"*** All declared inter-library dependencies are being dropped.\"\n\t    droppeddeps=yes\n\t    ;;\n\t  esac\n\t  ;;\n\tesac\n\tversuffix=$versuffix_save\n\tmajor=$major_save\n\trelease=$release_save\n\tlibname=$libname_save\n\tname=$name_save\n\n\tcase $host in\n\t*-*-rhapsody* | *-*-darwin1.[012])\n\t  # On Rhapsody replace the C library with the System framework\n\t  newdeplibs=`$ECHO \" $newdeplibs\" | $SED 's/ -lc / System.ltframework /'`\n\t  ;;\n\tesac\n\n\tif test \"$droppeddeps\" = yes; then\n\t  if test \"$module\" = yes; then\n\t    echo\n\t    echo \"*** Warning: libtool could not satisfy all declared inter-library\"\n\t    $ECHO \"*** dependencies of module $libname.  Therefore, libtool will create\"\n\t    echo \"*** a static module, that should work as long as the dlopening\"\n\t    echo \"*** application is linked with the -dlopen flag.\"\n\t    if test -z \"$global_symbol_pipe\"; then\n\t      echo\n\t      echo \"*** However, this would only work if libtool was able to extract symbol\"\n\t      echo \"*** lists from a program, using \\`nm' or equivalent, but libtool could\"\n\t      echo \"*** not find such a program.  So, this module is probably useless.\"\n\t      echo \"*** \\`nm' from GNU binutils and a full rebuild may help.\"\n\t    fi\n\t    if test \"$build_old_libs\" = no; then\n\t      oldlibs=\"$output_objdir/$libname.$libext\"\n\t      build_libtool_libs=module\n\t      build_old_libs=yes\n\t    else\n\t      build_libtool_libs=no\n\t    fi\n\t  else\n\t    echo \"*** The inter-library dependencies that have been dropped here will be\"\n\t    echo \"*** automatically added whenever a program is linked with this library\"\n\t    echo \"*** or is declared to -dlopen it.\"\n\n\t    if test \"$allow_undefined\" = no; then\n\t      echo\n\t      echo \"*** Since this library must not contain undefined symbols,\"\n\t      echo \"*** because either the platform does not support them or\"\n\t      echo \"*** it was explicitly requested with -no-undefined,\"\n\t      echo \"*** libtool will only create a static version of it.\"\n\t      if test \"$build_old_libs\" = no; then\n\t\toldlibs=\"$output_objdir/$libname.$libext\"\n\t\tbuild_libtool_libs=module\n\t\tbuild_old_libs=yes\n\t      else\n\t\tbuild_libtool_libs=no\n\t      fi\n\t    fi\n\t  fi\n\tfi\n\t# Done checking deplibs!\n\tdeplibs=$newdeplibs\n      fi\n      # Time to change all our \"foo.ltframework\" stuff back to \"-framework foo\"\n      case $host in\n\t*-*-darwin*)\n\t  newdeplibs=`$ECHO \" $newdeplibs\" | $SED 's% \\([^ $]*\\).ltframework% -framework \\1%g'`\n\t  new_inherited_linker_flags=`$ECHO \" $new_inherited_linker_flags\" | $SED 's% \\([^ $]*\\).ltframework% -framework \\1%g'`\n\t  deplibs=`$ECHO \" $deplibs\" | $SED 's% \\([^ $]*\\).ltframework% -framework \\1%g'`\n\t  ;;\n      esac\n\n      # move library search paths that coincide with paths to not yet\n      # installed libraries to the beginning of the library search list\n      new_libs=\n      for path in $notinst_path; do\n\tcase \" $new_libs \" in\n\t*\" -L$path/$objdir \"*) ;;\n\t*)\n\t  case \" $deplibs \" in\n\t  *\" -L$path/$objdir \"*)\n\t    new_libs=\"$new_libs -L$path/$objdir\" ;;\n\t  esac\n\t  ;;\n\tesac\n      done\n      for deplib in $deplibs; do\n\tcase $deplib in\n\t-L*)\n\t  case \" $new_libs \" in\n\t  *\" $deplib \"*) ;;\n\t  *) new_libs=\"$new_libs $deplib\" ;;\n\t  esac\n\t  ;;\n\t*) new_libs=\"$new_libs $deplib\" ;;\n\tesac\n      done\n      deplibs=\"$new_libs\"\n\n      # All the library-specific variables (install_libdir is set above).\n      library_names=\n      old_library=\n      dlname=\n\n      # Test again, we may have decided not to build it any more\n      if test \"$build_libtool_libs\" = yes; then\n\tif test \"$hardcode_into_libs\" = yes; then\n\t  # Hardcode the library paths\n\t  hardcode_libdirs=\n\t  dep_rpath=\n\t  rpath=\"$finalize_rpath\"\n\t  test \"$mode\" != relink && rpath=\"$compile_rpath$rpath\"\n\t  for libdir in $rpath; do\n\t    if test -n \"$hardcode_libdir_flag_spec\"; then\n\t      if test -n \"$hardcode_libdir_separator\"; then\n\t\tif test -z \"$hardcode_libdirs\"; then\n\t\t  hardcode_libdirs=\"$libdir\"\n\t\telse\n\t\t  # Just accumulate the unique libdirs.\n\t\t  case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in\n\t\t  *\"$hardcode_libdir_separator$libdir$hardcode_libdir_separator\"*)\n\t\t    ;;\n\t\t  *)\n\t\t    hardcode_libdirs=\"$hardcode_libdirs$hardcode_libdir_separator$libdir\"\n\t\t    ;;\n\t\t  esac\n\t\tfi\n\t      else\n\t\teval \"flag=\\\"$hardcode_libdir_flag_spec\\\"\"\n\t\tdep_rpath=\"$dep_rpath $flag\"\n\t      fi\n\t    elif test -n \"$runpath_var\"; then\n\t      case \"$perm_rpath \" in\n\t      *\" $libdir \"*) ;;\n\t      *) perm_rpath=\"$perm_rpath $libdir\" ;;\n\t      esac\n\t    fi\n\t  done\n\t  # Substitute the hardcoded libdirs into the rpath.\n\t  if test -n \"$hardcode_libdir_separator\" &&\n\t     test -n \"$hardcode_libdirs\"; then\n\t    libdir=\"$hardcode_libdirs\"\n\t    if test -n \"$hardcode_libdir_flag_spec_ld\"; then\n\t      eval \"dep_rpath=\\\"$hardcode_libdir_flag_spec_ld\\\"\"\n\t    else\n\t      eval \"dep_rpath=\\\"$hardcode_libdir_flag_spec\\\"\"\n\t    fi\n\t  fi\n\t  if test -n \"$runpath_var\" && test -n \"$perm_rpath\"; then\n\t    # We should set the runpath_var.\n\t    rpath=\n\t    for dir in $perm_rpath; do\n\t      rpath=\"$rpath$dir:\"\n\t    done\n\t    eval $runpath_var=\\$rpath\\$$runpath_var\n\t    export $runpath_var\n\t  fi\n\t  test -n \"$dep_rpath\" && deplibs=\"$dep_rpath $deplibs\"\n\tfi\n\n\tshlibpath=\"$finalize_shlibpath\"\n\ttest \"$mode\" != relink && shlibpath=\"$compile_shlibpath$shlibpath\"\n\tif test -n \"$shlibpath\"; then\n\t  eval $shlibpath_var=\\$shlibpath\\$$shlibpath_var\n\t  export $shlibpath_var\n\tfi\n\n\t# Get the real and link names of the library.\n\teval \"shared_ext=\\\"$shrext_cmds\\\"\"\n\teval \"library_names=\\\"$library_names_spec\\\"\"\n\tset dummy $library_names\n\tshift\n\trealname=\"$1\"\n\tshift\n\n\tif test -n \"$soname_spec\"; then\n\t  eval \"soname=\\\"$soname_spec\\\"\"\n\telse\n\t  soname=\"$realname\"\n\tfi\n\tif test -z \"$dlname\"; then\n\t  dlname=$soname\n\tfi\n\n\tlib=\"$output_objdir/$realname\"\n\tlinknames=\n\tfor link\n\tdo\n\t  linknames=\"$linknames $link\"\n\tdone\n\n\t# Use standard objects if they are pic\n\ttest -z \"$pic_flag\" && libobjs=`$ECHO \"$libobjs\" | $SP2NL | $SED \"$lo2o\" | $NL2SP`\n\ttest \"X$libobjs\" = \"X \" && libobjs=\n\n\tdelfiles=\n\tif test -n \"$export_symbols\" && test -n \"$include_expsyms\"; then\n\t  $opt_dry_run || cp \"$export_symbols\" \"$output_objdir/$libname.uexp\"\n\t  export_symbols=\"$output_objdir/$libname.uexp\"\n\t  delfiles=\"$delfiles $export_symbols\"\n\tfi\n\n\torig_export_symbols=\n\tcase $host_os in\n\tcygwin* | mingw* | cegcc*)\n\t  if test -n \"$export_symbols\" && test -z \"$export_symbols_regex\"; then\n\t    # exporting using user supplied symfile\n\t    if test \"x`$SED 1q $export_symbols`\" != xEXPORTS; then\n\t      # and it's NOT already a .def file. Must figure out\n\t      # which of the given symbols are data symbols and tag\n\t      # them as such. So, trigger use of export_symbols_cmds.\n\t      # export_symbols gets reassigned inside the \"prepare\n\t      # the list of exported symbols\" if statement, so the\n\t      # include_expsyms logic still works.\n\t      orig_export_symbols=\"$export_symbols\"\n\t      export_symbols=\n\t      always_export_symbols=yes\n\t    fi\n\t  fi\n\t  ;;\n\tesac\n\n\t# Prepare the list of exported symbols\n\tif test -z \"$export_symbols\"; then\n\t  if test \"$always_export_symbols\" = yes || test -n \"$export_symbols_regex\"; then\n\t    func_verbose \"generating symbol list for \\`$libname.la'\"\n\t    export_symbols=\"$output_objdir/$libname.exp\"\n\t    $opt_dry_run || $RM $export_symbols\n\t    cmds=$export_symbols_cmds\n\t    save_ifs=\"$IFS\"; IFS='~'\n\t    for cmd in $cmds; do\n\t      IFS=\"$save_ifs\"\n\t      eval \"cmd=\\\"$cmd\\\"\"\n\t      func_len \" $cmd\"\n\t      len=$func_len_result\n\t      if test \"$len\" -lt \"$max_cmd_len\" || test \"$max_cmd_len\" -le -1; then\n\t\tfunc_show_eval \"$cmd\" 'exit $?'\n\t\tskipped_export=false\n\t      else\n\t\t# The command line is too long to execute in one step.\n\t\tfunc_verbose \"using reloadable object file for export list...\"\n\t\tskipped_export=:\n\t\t# Break out early, otherwise skipped_export may be\n\t\t# set to false by a later but shorter cmd.\n\t\tbreak\n\t      fi\n\t    done\n\t    IFS=\"$save_ifs\"\n\t    if test -n \"$export_symbols_regex\" && test \"X$skipped_export\" != \"X:\"; then\n\t      func_show_eval '$EGREP -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\"'\n\t      func_show_eval '$MV \"${export_symbols}T\" \"$export_symbols\"'\n\t    fi\n\t  fi\n\tfi\n\n\tif test -n \"$export_symbols\" && test -n \"$include_expsyms\"; then\n\t  tmp_export_symbols=\"$export_symbols\"\n\t  test -n \"$orig_export_symbols\" && tmp_export_symbols=\"$orig_export_symbols\"\n\t  $opt_dry_run || $ECHO \"$include_expsyms\" | $SP2NL >> \"$tmp_export_symbols\"\n\tfi\n\n\tif test \"X$skipped_export\" != \"X:\" && test -n \"$orig_export_symbols\"; then\n\t  # The given exports_symbols file has to be filtered, so filter it.\n\t  func_verbose \"filter symbol list for \\`$libname.la' to tag DATA exports\"\n\t  # FIXME: $output_objdir/$libname.filter potentially contains lots of\n\t  # 's' commands which not all seds can handle. GNU sed should be fine\n\t  # though. Also, the filter scales superlinearly with the number of\n\t  # global variables. join(1) would be nice here, but unfortunately\n\t  # isn't a blessed tool.\n\t  $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\\(.*\\)\\([ \\,].*\\),s|^\\1$|\\1\\2|,' < $export_symbols > $output_objdir/$libname.filter\n\t  delfiles=\"$delfiles $export_symbols $output_objdir/$libname.filter\"\n\t  export_symbols=$output_objdir/$libname.def\n\t  $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols\n\tfi\n\n\ttmp_deplibs=\n\tfor test_deplib in $deplibs; do\n\t  case \" $convenience \" in\n\t  *\" $test_deplib \"*) ;;\n\t  *)\n\t    tmp_deplibs=\"$tmp_deplibs $test_deplib\"\n\t    ;;\n\t  esac\n\tdone\n\tdeplibs=\"$tmp_deplibs\"\n\n\tif test -n \"$convenience\"; then\n\t  if test -n \"$whole_archive_flag_spec\" &&\n\t    test \"$compiler_needs_object\" = yes &&\n\t    test -z \"$libobjs\"; then\n\t    # extract the archives, so we have objects to list.\n\t    # TODO: could optimize this to just extract one archive.\n\t    whole_archive_flag_spec=\n\t  fi\n\t  if test -n \"$whole_archive_flag_spec\"; then\n\t    save_libobjs=$libobjs\n\t    eval \"libobjs=\\\"\\$libobjs $whole_archive_flag_spec\\\"\"\n\t    test \"X$libobjs\" = \"X \" && libobjs=\n\t  else\n\t    gentop=\"$output_objdir/${outputname}x\"\n\t    generated=\"$generated $gentop\"\n\n\t    func_extract_archives $gentop $convenience\n\t    libobjs=\"$libobjs $func_extract_archives_result\"\n\t    test \"X$libobjs\" = \"X \" && libobjs=\n\t  fi\n\tfi\n\n\tif test \"$thread_safe\" = yes && test -n \"$thread_safe_flag_spec\"; then\n\t  eval \"flag=\\\"$thread_safe_flag_spec\\\"\"\n\t  linker_flags=\"$linker_flags $flag\"\n\tfi\n\n\t# Make a backup of the uninstalled library when relinking\n\tif test \"$mode\" = relink; then\n\t  $opt_dry_run || (cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U) || exit $?\n\tfi\n\n\t# Do each of the archive commands.\n\tif test \"$module\" = yes && test -n \"$module_cmds\" ; then\n\t  if test -n \"$export_symbols\" && test -n \"$module_expsym_cmds\"; then\n\t    eval \"test_cmds=\\\"$module_expsym_cmds\\\"\"\n\t    cmds=$module_expsym_cmds\n\t  else\n\t    eval \"test_cmds=\\\"$module_cmds\\\"\"\n\t    cmds=$module_cmds\n\t  fi\n\telse\n\t  if test -n \"$export_symbols\" && test -n \"$archive_expsym_cmds\"; then\n\t    eval \"test_cmds=\\\"$archive_expsym_cmds\\\"\"\n\t    cmds=$archive_expsym_cmds\n\t  else\n\t    eval \"test_cmds=\\\"$archive_cmds\\\"\"\n\t    cmds=$archive_cmds\n\t  fi\n\tfi\n\n\tif test \"X$skipped_export\" != \"X:\" &&\n\t   func_len \" $test_cmds\" &&\n\t   len=$func_len_result &&\n\t   test \"$len\" -lt \"$max_cmd_len\" || test \"$max_cmd_len\" -le -1; then\n\t  :\n\telse\n\t  # The command line is too long to link in one step, link piecewise\n\t  # or, if using GNU ld and skipped_export is not :, use a linker\n\t  # script.\n\n\t  # Save the value of $output and $libobjs because we want to\n\t  # use them later.  If we have whole_archive_flag_spec, we\n\t  # want to use save_libobjs as it was before\n\t  # whole_archive_flag_spec was expanded, because we can't\n\t  # assume the linker understands whole_archive_flag_spec.\n\t  # This may have to be revisited, in case too many\n\t  # convenience libraries get linked in and end up exceeding\n\t  # the spec.\n\t  if test -z \"$convenience\" || test -z \"$whole_archive_flag_spec\"; then\n\t    save_libobjs=$libobjs\n\t  fi\n\t  save_output=$output\n\t  func_basename \"$output\"\n\t  output_la=$func_basename_result\n\n\t  # Clear the reloadable object creation command queue and\n\t  # initialize k to one.\n\t  test_cmds=\n\t  concat_cmds=\n\t  objlist=\n\t  last_robj=\n\t  k=1\n\n\t  if test -n \"$save_libobjs\" && test \"X$skipped_export\" != \"X:\" && test \"$with_gnu_ld\" = yes; then\n\t    output=${output_objdir}/${output_la}.lnkscript\n\t    func_verbose \"creating GNU ld script: $output\"\n\t    echo 'INPUT (' > $output\n\t    for obj in $save_libobjs\n\t    do\n\t      $ECHO \"$obj\" >> $output\n\t    done\n\t    echo ')' >> $output\n\t    delfiles=\"$delfiles $output\"\n\t  elif test -n \"$save_libobjs\" && test \"X$skipped_export\" != \"X:\" && test \"X$file_list_spec\" != X; then\n\t    output=${output_objdir}/${output_la}.lnk\n\t    func_verbose \"creating linker input file list: $output\"\n\t    : > $output\n\t    set x $save_libobjs\n\t    shift\n\t    firstobj=\n\t    if test \"$compiler_needs_object\" = yes; then\n\t      firstobj=\"$1 \"\n\t      shift\n\t    fi\n\t    for obj\n\t    do\n\t      $ECHO \"$obj\" >> $output\n\t    done\n\t    delfiles=\"$delfiles $output\"\n\t    output=$firstobj\\\"$file_list_spec$output\\\"\n\t  else\n\t    if test -n \"$save_libobjs\"; then\n\t      func_verbose \"creating reloadable object files...\"\n\t      output=$output_objdir/$output_la-${k}.$objext\n\t      eval \"test_cmds=\\\"$reload_cmds\\\"\"\n\t      func_len \" $test_cmds\"\n\t      len0=$func_len_result\n\t      len=$len0\n\n\t      # Loop over the list of objects to be linked.\n\t      for obj in $save_libobjs\n\t      do\n\t\tfunc_len \" $obj\"\n\t\tfunc_arith $len + $func_len_result\n\t\tlen=$func_arith_result\n\t\tif test \"X$objlist\" = X ||\n\t\t   test \"$len\" -lt \"$max_cmd_len\"; then\n\t\t  func_append objlist \" $obj\"\n\t\telse\n\t\t  # The command $test_cmds is almost too long, add a\n\t\t  # command to the queue.\n\t\t  if test \"$k\" -eq 1 ; then\n\t\t    # The first file doesn't have a previous command to add.\n\t\t    reload_objs=$objlist\n\t\t    eval \"concat_cmds=\\\"$reload_cmds\\\"\"\n\t\t  else\n\t\t    # All subsequent reloadable object files will link in\n\t\t    # the last one created.\n\t\t    reload_objs=\"$objlist $last_robj\"\n\t\t    eval \"concat_cmds=\\\"\\$concat_cmds~$reload_cmds~\\$RM $last_robj\\\"\"\n\t\t  fi\n\t\t  last_robj=$output_objdir/$output_la-${k}.$objext\n\t\t  func_arith $k + 1\n\t\t  k=$func_arith_result\n\t\t  output=$output_objdir/$output_la-${k}.$objext\n\t\t  objlist=\" $obj\"\n\t\t  func_len \" $last_robj\"\n\t\t  func_arith $len0 + $func_len_result\n\t\t  len=$func_arith_result\n\t\tfi\n\t      done\n\t      # Handle the remaining objects by creating one last\n\t      # reloadable object file.  All subsequent reloadable object\n\t      # files will link in the last one created.\n\t      test -z \"$concat_cmds\" || concat_cmds=$concat_cmds~\n\t      reload_objs=\"$objlist $last_robj\"\n\t      eval \"concat_cmds=\\\"\\${concat_cmds}$reload_cmds\\\"\"\n\t      if test -n \"$last_robj\"; then\n\t        eval \"concat_cmds=\\\"\\${concat_cmds}~\\$RM $last_robj\\\"\"\n\t      fi\n\t      delfiles=\"$delfiles $output\"\n\n\t    else\n\t      output=\n\t    fi\n\n\t    if ${skipped_export-false}; then\n\t      func_verbose \"generating symbol list for \\`$libname.la'\"\n\t      export_symbols=\"$output_objdir/$libname.exp\"\n\t      $opt_dry_run || $RM $export_symbols\n\t      libobjs=$output\n\t      # Append the command to create the export file.\n\t      test -z \"$concat_cmds\" || concat_cmds=$concat_cmds~\n\t      eval \"concat_cmds=\\\"\\$concat_cmds$export_symbols_cmds\\\"\"\n\t      if test -n \"$last_robj\"; then\n\t\teval \"concat_cmds=\\\"\\$concat_cmds~\\$RM $last_robj\\\"\"\n\t      fi\n\t    fi\n\n\t    test -n \"$save_libobjs\" &&\n\t      func_verbose \"creating a temporary reloadable object file: $output\"\n\n\t    # Loop through the commands generated above and execute them.\n\t    save_ifs=\"$IFS\"; IFS='~'\n\t    for cmd in $concat_cmds; do\n\t      IFS=\"$save_ifs\"\n\t      $opt_silent || {\n\t\t  func_quote_for_expand \"$cmd\"\n\t\t  eval \"func_echo $func_quote_for_expand_result\"\n\t      }\n\t      $opt_dry_run || eval \"$cmd\" || {\n\t\tlt_exit=$?\n\n\t\t# Restore the uninstalled library and exit\n\t\tif test \"$mode\" = relink; then\n\t\t  ( cd \"$output_objdir\" && \\\n\t\t    $RM \"${realname}T\" && \\\n\t\t    $MV \"${realname}U\" \"$realname\" )\n\t\tfi\n\n\t\texit $lt_exit\n\t      }\n\t    done\n\t    IFS=\"$save_ifs\"\n\n\t    if test -n \"$export_symbols_regex\" && ${skipped_export-false}; then\n\t      func_show_eval '$EGREP -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\"'\n\t      func_show_eval '$MV \"${export_symbols}T\" \"$export_symbols\"'\n\t    fi\n\t  fi\n\n          if ${skipped_export-false}; then\n\t    if test -n \"$export_symbols\" && test -n \"$include_expsyms\"; then\n\t      tmp_export_symbols=\"$export_symbols\"\n\t      test -n \"$orig_export_symbols\" && tmp_export_symbols=\"$orig_export_symbols\"\n\t      $opt_dry_run || $ECHO \"$include_expsyms\" | $SP2NL >> \"$tmp_export_symbols\"\n\t    fi\n\n\t    if test -n \"$orig_export_symbols\"; then\n\t      # The given exports_symbols file has to be filtered, so filter it.\n\t      func_verbose \"filter symbol list for \\`$libname.la' to tag DATA exports\"\n\t      # FIXME: $output_objdir/$libname.filter potentially contains lots of\n\t      # 's' commands which not all seds can handle. GNU sed should be fine\n\t      # though. Also, the filter scales superlinearly with the number of\n\t      # global variables. join(1) would be nice here, but unfortunately\n\t      # isn't a blessed tool.\n\t      $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\\(.*\\)\\([ \\,].*\\),s|^\\1$|\\1\\2|,' < $export_symbols > $output_objdir/$libname.filter\n\t      delfiles=\"$delfiles $export_symbols $output_objdir/$libname.filter\"\n\t      export_symbols=$output_objdir/$libname.def\n\t      $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols\n\t    fi\n\t  fi\n\n\t  libobjs=$output\n\t  # Restore the value of output.\n\t  output=$save_output\n\n\t  if test -n \"$convenience\" && test -n \"$whole_archive_flag_spec\"; then\n\t    eval \"libobjs=\\\"\\$libobjs $whole_archive_flag_spec\\\"\"\n\t    test \"X$libobjs\" = \"X \" && libobjs=\n\t  fi\n\t  # Expand the library linking commands again to reset the\n\t  # value of $libobjs for piecewise linking.\n\n\t  # Do each of the archive commands.\n\t  if test \"$module\" = yes && test -n \"$module_cmds\" ; then\n\t    if test -n \"$export_symbols\" && test -n \"$module_expsym_cmds\"; then\n\t      cmds=$module_expsym_cmds\n\t    else\n\t      cmds=$module_cmds\n\t    fi\n\t  else\n\t    if test -n \"$export_symbols\" && test -n \"$archive_expsym_cmds\"; then\n\t      cmds=$archive_expsym_cmds\n\t    else\n\t      cmds=$archive_cmds\n\t    fi\n\t  fi\n\tfi\n\n\tif test -n \"$delfiles\"; then\n\t  # Append the command to remove temporary files to $cmds.\n\t  eval \"cmds=\\\"\\$cmds~\\$RM $delfiles\\\"\"\n\tfi\n\n\t# Add any objects from preloaded convenience libraries\n\tif test -n \"$dlprefiles\"; then\n\t  gentop=\"$output_objdir/${outputname}x\"\n\t  generated=\"$generated $gentop\"\n\n\t  func_extract_archives $gentop $dlprefiles\n\t  libobjs=\"$libobjs $func_extract_archives_result\"\n\t  test \"X$libobjs\" = \"X \" && libobjs=\n\tfi\n\n\tsave_ifs=\"$IFS\"; IFS='~'\n\tfor cmd in $cmds; do\n\t  IFS=\"$save_ifs\"\n\t  eval \"cmd=\\\"$cmd\\\"\"\n\t  $opt_silent || {\n\t    func_quote_for_expand \"$cmd\"\n\t    eval \"func_echo $func_quote_for_expand_result\"\n\t  }\n\t  $opt_dry_run || eval \"$cmd\" || {\n\t    lt_exit=$?\n\n\t    # Restore the uninstalled library and exit\n\t    if test \"$mode\" = relink; then\n\t      ( cd \"$output_objdir\" && \\\n\t        $RM \"${realname}T\" && \\\n\t\t$MV \"${realname}U\" \"$realname\" )\n\t    fi\n\n\t    exit $lt_exit\n\t  }\n\tdone\n\tIFS=\"$save_ifs\"\n\n\t# Restore the uninstalled library and exit\n\tif test \"$mode\" = relink; then\n\t  $opt_dry_run || (cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname) || exit $?\n\n\t  if test -n \"$convenience\"; then\n\t    if test -z \"$whole_archive_flag_spec\"; then\n\t      func_show_eval '${RM}r \"$gentop\"'\n\t    fi\n\t  fi\n\n\t  exit $EXIT_SUCCESS\n\tfi\n\n\t# Create links to the real library.\n\tfor linkname in $linknames; do\n\t  if test \"$realname\" != \"$linkname\"; then\n\t    func_show_eval '(cd \"$output_objdir\" && $RM \"$linkname\" && $LN_S \"$realname\" \"$linkname\")' 'exit $?'\n\t  fi\n\tdone\n\n\t# If -module or -export-dynamic was specified, set the dlname.\n\tif test \"$module\" = yes || test \"$export_dynamic\" = yes; then\n\t  # On all known operating systems, these are identical.\n\t  dlname=\"$soname\"\n\tfi\n      fi\n      ;;\n\n    obj)\n      if test -n \"$dlfiles$dlprefiles\" || test \"$dlself\" != no; then\n\tfunc_warning \"\\`-dlopen' is ignored for objects\"\n      fi\n\n      case \" $deplibs\" in\n      *\\ -l* | *\\ -L*)\n\tfunc_warning \"\\`-l' and \\`-L' are ignored for objects\" ;;\n      esac\n\n      test -n \"$rpath\" && \\\n\tfunc_warning \"\\`-rpath' is ignored for objects\"\n\n      test -n \"$xrpath\" && \\\n\tfunc_warning \"\\`-R' is ignored for objects\"\n\n      test -n \"$vinfo\" && \\\n\tfunc_warning \"\\`-version-info' is ignored for objects\"\n\n      test -n \"$release\" && \\\n\tfunc_warning \"\\`-release' is ignored for objects\"\n\n      case $output in\n      *.lo)\n\ttest -n \"$objs$old_deplibs\" && \\\n\t  func_fatal_error \"cannot build library object \\`$output' from non-libtool objects\"\n\n\tlibobj=$output\n\tfunc_lo2o \"$libobj\"\n\tobj=$func_lo2o_result\n\t;;\n      *)\n\tlibobj=\n\tobj=\"$output\"\n\t;;\n      esac\n\n      # Delete the old objects.\n      $opt_dry_run || $RM $obj $libobj\n\n      # Objects from convenience libraries.  This assumes\n      # single-version convenience libraries.  Whenever we create\n      # different ones for PIC/non-PIC, this we'll have to duplicate\n      # the extraction.\n      reload_conv_objs=\n      gentop=\n      # reload_cmds runs $LD directly, so let us get rid of\n      # -Wl from whole_archive_flag_spec and hope we can get by with\n      # turning comma into space..\n      wl=\n\n      if test -n \"$convenience\"; then\n\tif test -n \"$whole_archive_flag_spec\"; then\n\t  eval \"tmp_whole_archive_flags=\\\"$whole_archive_flag_spec\\\"\"\n\t  reload_conv_objs=$reload_objs\\ `$ECHO \"$tmp_whole_archive_flags\" | $SED 's|,| |g'`\n\telse\n\t  gentop=\"$output_objdir/${obj}x\"\n\t  generated=\"$generated $gentop\"\n\n\t  func_extract_archives $gentop $convenience\n\t  reload_conv_objs=\"$reload_objs $func_extract_archives_result\"\n\tfi\n      fi\n\n      # Create the old-style object.\n      reload_objs=\"$objs$old_deplibs \"`$ECHO \"$libobjs\" | $SP2NL | $SED \"/\\.${libext}$/d; /\\.lib$/d; $lo2o\" | $NL2SP`\" $reload_conv_objs\" ### testsuite: skip nested quoting test\n\n      output=\"$obj\"\n      func_execute_cmds \"$reload_cmds\" 'exit $?'\n\n      # Exit if we aren't doing a library object file.\n      if test -z \"$libobj\"; then\n\tif test -n \"$gentop\"; then\n\t  func_show_eval '${RM}r \"$gentop\"'\n\tfi\n\n\texit $EXIT_SUCCESS\n      fi\n\n      if test \"$build_libtool_libs\" != yes; then\n\tif test -n \"$gentop\"; then\n\t  func_show_eval '${RM}r \"$gentop\"'\n\tfi\n\n\t# Create an invalid libtool object if no PIC, so that we don't\n\t# accidentally link it into a program.\n\t# $show \"echo timestamp > $libobj\"\n\t# $opt_dry_run || echo timestamp > $libobj || exit $?\n\texit $EXIT_SUCCESS\n      fi\n\n      if test -n \"$pic_flag\" || test \"$pic_mode\" != default; then\n\t# Only do commands if we really have different PIC objects.\n\treload_objs=\"$libobjs $reload_conv_objs\"\n\toutput=\"$libobj\"\n\tfunc_execute_cmds \"$reload_cmds\" 'exit $?'\n      fi\n\n      if test -n \"$gentop\"; then\n\tfunc_show_eval '${RM}r \"$gentop\"'\n      fi\n\n      exit $EXIT_SUCCESS\n      ;;\n\n    prog)\n      case $host in\n\t*cygwin*) func_stripname '' '.exe' \"$output\"\n\t          output=$func_stripname_result.exe;;\n      esac\n      test -n \"$vinfo\" && \\\n\tfunc_warning \"\\`-version-info' is ignored for programs\"\n\n      test -n \"$release\" && \\\n\tfunc_warning \"\\`-release' is ignored for programs\"\n\n      test \"$preload\" = yes \\\n        && test \"$dlopen_support\" = unknown \\\n\t&& test \"$dlopen_self\" = unknown \\\n\t&& test \"$dlopen_self_static\" = unknown && \\\n\t  func_warning \"\\`LT_INIT([dlopen])' not used. Assuming no dlopen support.\"\n\n      case $host in\n      *-*-rhapsody* | *-*-darwin1.[012])\n\t# On Rhapsody replace the C library is the System framework\n\tcompile_deplibs=`$ECHO \" $compile_deplibs\" | $SED 's/ -lc / System.ltframework /'`\n\tfinalize_deplibs=`$ECHO \" $finalize_deplibs\" | $SED 's/ -lc / System.ltframework /'`\n\t;;\n      esac\n\n      case $host in\n      *-*-darwin*)\n\t# Don't allow lazy linking, it breaks C++ global constructors\n\t# But is supposedly fixed on 10.4 or later (yay!).\n\tif test \"$tagname\" = CXX ; then\n\t  case ${MACOSX_DEPLOYMENT_TARGET-10.0} in\n\t    10.[0123])\n\t      compile_command=\"$compile_command ${wl}-bind_at_load\"\n\t      finalize_command=\"$finalize_command ${wl}-bind_at_load\"\n\t    ;;\n\t  esac\n\tfi\n\t# Time to change all our \"foo.ltframework\" stuff back to \"-framework foo\"\n\tcompile_deplibs=`$ECHO \" $compile_deplibs\" | $SED 's% \\([^ $]*\\).ltframework% -framework \\1%g'`\n\tfinalize_deplibs=`$ECHO \" $finalize_deplibs\" | $SED 's% \\([^ $]*\\).ltframework% -framework \\1%g'`\n\t;;\n      esac\n\n\n      # move library search paths that coincide with paths to not yet\n      # installed libraries to the beginning of the library search list\n      new_libs=\n      for path in $notinst_path; do\n\tcase \" $new_libs \" in\n\t*\" -L$path/$objdir \"*) ;;\n\t*)\n\t  case \" $compile_deplibs \" in\n\t  *\" -L$path/$objdir \"*)\n\t    new_libs=\"$new_libs -L$path/$objdir\" ;;\n\t  esac\n\t  ;;\n\tesac\n      done\n      for deplib in $compile_deplibs; do\n\tcase $deplib in\n\t-L*)\n\t  case \" $new_libs \" in\n\t  *\" $deplib \"*) ;;\n\t  *) new_libs=\"$new_libs $deplib\" ;;\n\t  esac\n\t  ;;\n\t*) new_libs=\"$new_libs $deplib\" ;;\n\tesac\n      done\n      compile_deplibs=\"$new_libs\"\n\n\n      compile_command=\"$compile_command $compile_deplibs\"\n      finalize_command=\"$finalize_command $finalize_deplibs\"\n\n      if test -n \"$rpath$xrpath\"; then\n\t# If the user specified any rpath flags, then add them.\n\tfor libdir in $rpath $xrpath; do\n\t  # This is the magic to use -rpath.\n\t  case \"$finalize_rpath \" in\n\t  *\" $libdir \"*) ;;\n\t  *) finalize_rpath=\"$finalize_rpath $libdir\" ;;\n\t  esac\n\tdone\n      fi\n\n      # Now hardcode the library paths\n      rpath=\n      hardcode_libdirs=\n      for libdir in $compile_rpath $finalize_rpath; do\n\tif test -n \"$hardcode_libdir_flag_spec\"; then\n\t  if test -n \"$hardcode_libdir_separator\"; then\n\t    if test -z \"$hardcode_libdirs\"; then\n\t      hardcode_libdirs=\"$libdir\"\n\t    else\n\t      # Just accumulate the unique libdirs.\n\t      case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in\n\t      *\"$hardcode_libdir_separator$libdir$hardcode_libdir_separator\"*)\n\t\t;;\n\t      *)\n\t\thardcode_libdirs=\"$hardcode_libdirs$hardcode_libdir_separator$libdir\"\n\t\t;;\n\t      esac\n\t    fi\n\t  else\n\t    eval \"flag=\\\"$hardcode_libdir_flag_spec\\\"\"\n\t    rpath=\"$rpath $flag\"\n\t  fi\n\telif test -n \"$runpath_var\"; then\n\t  case \"$perm_rpath \" in\n\t  *\" $libdir \"*) ;;\n\t  *) perm_rpath=\"$perm_rpath $libdir\" ;;\n\t  esac\n\tfi\n\tcase $host in\n\t*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*)\n\t  testbindir=`${ECHO} \"$libdir\" | ${SED} -e 's*/lib$*/bin*'`\n\t  case :$dllsearchpath: in\n\t  *\":$libdir:\"*) ;;\n\t  ::) dllsearchpath=$libdir;;\n\t  *) dllsearchpath=\"$dllsearchpath:$libdir\";;\n\t  esac\n\t  case :$dllsearchpath: in\n\t  *\":$testbindir:\"*) ;;\n\t  ::) dllsearchpath=$testbindir;;\n\t  *) dllsearchpath=\"$dllsearchpath:$testbindir\";;\n\t  esac\n\t  ;;\n\tesac\n      done\n      # Substitute the hardcoded libdirs into the rpath.\n      if test -n \"$hardcode_libdir_separator\" &&\n\t test -n \"$hardcode_libdirs\"; then\n\tlibdir=\"$hardcode_libdirs\"\n\teval \"rpath=\\\" $hardcode_libdir_flag_spec\\\"\"\n      fi\n      compile_rpath=\"$rpath\"\n\n      rpath=\n      hardcode_libdirs=\n      for libdir in $finalize_rpath; do\n\tif test -n \"$hardcode_libdir_flag_spec\"; then\n\t  if test -n \"$hardcode_libdir_separator\"; then\n\t    if test -z \"$hardcode_libdirs\"; then\n\t      hardcode_libdirs=\"$libdir\"\n\t    else\n\t      # Just accumulate the unique libdirs.\n\t      case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in\n\t      *\"$hardcode_libdir_separator$libdir$hardcode_libdir_separator\"*)\n\t\t;;\n\t      *)\n\t\thardcode_libdirs=\"$hardcode_libdirs$hardcode_libdir_separator$libdir\"\n\t\t;;\n\t      esac\n\t    fi\n\t  else\n\t    eval \"flag=\\\"$hardcode_libdir_flag_spec\\\"\"\n\t    rpath=\"$rpath $flag\"\n\t  fi\n\telif test -n \"$runpath_var\"; then\n\t  case \"$finalize_perm_rpath \" in\n\t  *\" $libdir \"*) ;;\n\t  *) finalize_perm_rpath=\"$finalize_perm_rpath $libdir\" ;;\n\t  esac\n\tfi\n      done\n      # Substitute the hardcoded libdirs into the rpath.\n      if test -n \"$hardcode_libdir_separator\" &&\n\t test -n \"$hardcode_libdirs\"; then\n\tlibdir=\"$hardcode_libdirs\"\n\teval \"rpath=\\\" $hardcode_libdir_flag_spec\\\"\"\n      fi\n      finalize_rpath=\"$rpath\"\n\n      if test -n \"$libobjs\" && test \"$build_old_libs\" = yes; then\n\t# Transform all the library objects into standard objects.\n\tcompile_command=`$ECHO \"$compile_command\" | $SP2NL | $SED \"$lo2o\" | $NL2SP`\n\tfinalize_command=`$ECHO \"$finalize_command\" | $SP2NL | $SED \"$lo2o\" | $NL2SP`\n      fi\n\n      func_generate_dlsyms \"$outputname\" \"@PROGRAM@\" \"no\"\n\n      # template prelinking step\n      if test -n \"$prelink_cmds\"; then\n\tfunc_execute_cmds \"$prelink_cmds\" 'exit $?'\n      fi\n\n      wrappers_required=yes\n      case $host in\n      *cegcc* | *mingw32ce*)\n        # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway.\n        wrappers_required=no\n        ;;\n      *cygwin* | *mingw* )\n        if test \"$build_libtool_libs\" != yes; then\n          wrappers_required=no\n        fi\n        ;;\n      *)\n        if test \"$need_relink\" = no || test \"$build_libtool_libs\" != yes; then\n          wrappers_required=no\n        fi\n        ;;\n      esac\n      if test \"$wrappers_required\" = no; then\n\t# Replace the output file specification.\n\tcompile_command=`$ECHO \"$compile_command\" | $SED 's%@OUTPUT@%'\"$output\"'%g'`\n\tlink_command=\"$compile_command$compile_rpath\"\n\n\t# We have no uninstalled library dependencies, so finalize right now.\n\texit_status=0\n\tfunc_show_eval \"$link_command\" 'exit_status=$?'\n\n\t# Delete the generated files.\n\tif test -f \"$output_objdir/${outputname}S.${objext}\"; then\n\t  func_show_eval '$RM \"$output_objdir/${outputname}S.${objext}\"'\n\tfi\n\n\texit $exit_status\n      fi\n\n      if test -n \"$compile_shlibpath$finalize_shlibpath\"; then\n\tcompile_command=\"$shlibpath_var=\\\"$compile_shlibpath$finalize_shlibpath\\$$shlibpath_var\\\" $compile_command\"\n      fi\n      if test -n \"$finalize_shlibpath\"; then\n\tfinalize_command=\"$shlibpath_var=\\\"$finalize_shlibpath\\$$shlibpath_var\\\" $finalize_command\"\n      fi\n\n      compile_var=\n      finalize_var=\n      if test -n \"$runpath_var\"; then\n\tif test -n \"$perm_rpath\"; then\n\t  # We should set the runpath_var.\n\t  rpath=\n\t  for dir in $perm_rpath; do\n\t    rpath=\"$rpath$dir:\"\n\t  done\n\t  compile_var=\"$runpath_var=\\\"$rpath\\$$runpath_var\\\" \"\n\tfi\n\tif test -n \"$finalize_perm_rpath\"; then\n\t  # We should set the runpath_var.\n\t  rpath=\n\t  for dir in $finalize_perm_rpath; do\n\t    rpath=\"$rpath$dir:\"\n\t  done\n\t  finalize_var=\"$runpath_var=\\\"$rpath\\$$runpath_var\\\" \"\n\tfi\n      fi\n\n      if test \"$no_install\" = yes; then\n\t# We don't need to create a wrapper script.\n\tlink_command=\"$compile_var$compile_command$compile_rpath\"\n\t# Replace the output file specification.\n\tlink_command=`$ECHO \"$link_command\" | $SED 's%@OUTPUT@%'\"$output\"'%g'`\n\t# Delete the old output file.\n\t$opt_dry_run || $RM $output\n\t# Link the executable and exit\n\tfunc_show_eval \"$link_command\" 'exit $?'\n\texit $EXIT_SUCCESS\n      fi\n\n      if test \"$hardcode_action\" = relink; then\n\t# Fast installation is not supported\n\tlink_command=\"$compile_var$compile_command$compile_rpath\"\n\trelink_command=\"$finalize_var$finalize_command$finalize_rpath\"\n\n\tfunc_warning \"this platform does not like uninstalled shared libraries\"\n\tfunc_warning \"\\`$output' will be relinked during installation\"\n      else\n\tif test \"$fast_install\" != no; then\n\t  link_command=\"$finalize_var$compile_command$finalize_rpath\"\n\t  if test \"$fast_install\" = yes; then\n\t    relink_command=`$ECHO \"$compile_var$compile_command$compile_rpath\" | $SED 's%@OUTPUT@%\\$progdir/\\$file%g'`\n\t  else\n\t    # fast_install is set to needless\n\t    relink_command=\n\t  fi\n\telse\n\t  link_command=\"$compile_var$compile_command$compile_rpath\"\n\t  relink_command=\"$finalize_var$finalize_command$finalize_rpath\"\n\tfi\n      fi\n\n      # Replace the output file specification.\n      link_command=`$ECHO \"$link_command\" | $SED 's%@OUTPUT@%'\"$output_objdir/$outputname\"'%g'`\n\n      # Delete the old output files.\n      $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname\n\n      func_show_eval \"$link_command\" 'exit $?'\n\n      # Now create the wrapper script.\n      func_verbose \"creating $output\"\n\n      # Quote the relink command for shipping.\n      if test -n \"$relink_command\"; then\n\t# Preserve any variables that may affect compiler behavior\n\tfor var in $variables_saved_for_relink; do\n\t  if eval test -z \\\"\\${$var+set}\\\"; then\n\t    relink_command=\"{ test -z \\\"\\${$var+set}\\\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command\"\n\t  elif eval var_value=\\$$var; test -z \"$var_value\"; then\n\t    relink_command=\"$var=; export $var; $relink_command\"\n\t  else\n\t    func_quote_for_eval \"$var_value\"\n\t    relink_command=\"$var=$func_quote_for_eval_result; export $var; $relink_command\"\n\t  fi\n\tdone\n\trelink_command=\"(cd `pwd`; $relink_command)\"\n\trelink_command=`$ECHO \"$relink_command\" | $SED \"$sed_quote_subst\"`\n      fi\n\n      # Only actually do things if not in dry run mode.\n      $opt_dry_run || {\n\t# win32 will think the script is a binary if it has\n\t# a .exe suffix, so we strip it off here.\n\tcase $output in\n\t  *.exe) func_stripname '' '.exe' \"$output\"\n\t         output=$func_stripname_result ;;\n\tesac\n\t# test for cygwin because mv fails w/o .exe extensions\n\tcase $host in\n\t  *cygwin*)\n\t    exeext=.exe\n\t    func_stripname '' '.exe' \"$outputname\"\n\t    outputname=$func_stripname_result ;;\n\t  *) exeext= ;;\n\tesac\n\tcase $host in\n\t  *cygwin* | *mingw* )\n\t    func_dirname_and_basename \"$output\" \"\" \".\"\n\t    output_name=$func_basename_result\n\t    output_path=$func_dirname_result\n\t    cwrappersource=\"$output_path/$objdir/lt-$output_name.c\"\n\t    cwrapper=\"$output_path/$output_name.exe\"\n\t    $RM $cwrappersource $cwrapper\n\t    trap \"$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE\" 1 2 15\n\n\t    func_emit_cwrapperexe_src > $cwrappersource\n\n\t    # The wrapper executable is built using the $host compiler,\n\t    # because it contains $host paths and files. If cross-\n\t    # compiling, it, like the target executable, must be\n\t    # executed on the $host or under an emulation environment.\n\t    $opt_dry_run || {\n\t      $LTCC $LTCFLAGS -o $cwrapper $cwrappersource\n\t      $STRIP $cwrapper\n\t    }\n\n\t    # Now, create the wrapper script for func_source use:\n\t    func_ltwrapper_scriptname $cwrapper\n\t    $RM $func_ltwrapper_scriptname_result\n\t    trap \"$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE\" 1 2 15\n\t    $opt_dry_run || {\n\t      # note: this script will not be executed, so do not chmod.\n\t      if test \"x$build\" = \"x$host\" ; then\n\t\t$cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result\n\t      else\n\t\tfunc_emit_wrapper no > $func_ltwrapper_scriptname_result\n\t      fi\n\t    }\n\t  ;;\n\t  * )\n\t    $RM $output\n\t    trap \"$RM $output; exit $EXIT_FAILURE\" 1 2 15\n\n\t    func_emit_wrapper no > $output\n\t    chmod +x $output\n\t  ;;\n\tesac\n      }\n      exit $EXIT_SUCCESS\n      ;;\n    esac\n\n    # See if we need to build an old-fashioned archive.\n    for oldlib in $oldlibs; do\n\n      if test \"$build_libtool_libs\" = convenience; then\n\toldobjs=\"$libobjs_save $symfileobj\"\n\taddlibs=\"$convenience\"\n\tbuild_libtool_libs=no\n      else\n\tif test \"$build_libtool_libs\" = module; then\n\t  oldobjs=\"$libobjs_save\"\n\t  build_libtool_libs=no\n\telse\n\t  oldobjs=\"$old_deplibs $non_pic_objects\"\n\t  if test \"$preload\" = yes && test -f \"$symfileobj\"; then\n\t    oldobjs=\"$oldobjs $symfileobj\"\n\t  fi\n\tfi\n\taddlibs=\"$old_convenience\"\n      fi\n\n      if test -n \"$addlibs\"; then\n\tgentop=\"$output_objdir/${outputname}x\"\n\tgenerated=\"$generated $gentop\"\n\n\tfunc_extract_archives $gentop $addlibs\n\toldobjs=\"$oldobjs $func_extract_archives_result\"\n      fi\n\n      # Do each command in the archive commands.\n      if test -n \"$old_archive_from_new_cmds\" && test \"$build_libtool_libs\" = yes; then\n\tcmds=$old_archive_from_new_cmds\n      else\n\n\t# Add any objects from preloaded convenience libraries\n\tif test -n \"$dlprefiles\"; then\n\t  gentop=\"$output_objdir/${outputname}x\"\n\t  generated=\"$generated $gentop\"\n\n\t  func_extract_archives $gentop $dlprefiles\n\t  oldobjs=\"$oldobjs $func_extract_archives_result\"\n\tfi\n\n\t# POSIX demands no paths to be encoded in archives.  We have\n\t# to avoid creating archives with duplicate basenames if we\n\t# might have to extract them afterwards, e.g., when creating a\n\t# static archive out of a convenience library, or when linking\n\t# the entirety of a libtool archive into another (currently\n\t# not supported by libtool).\n\tif (for obj in $oldobjs\n\t    do\n\t      func_basename \"$obj\"\n\t      $ECHO \"$func_basename_result\"\n\t    done | sort | sort -uc >/dev/null 2>&1); then\n\t  :\n\telse\n\t  echo \"copying selected object files to avoid basename conflicts...\"\n\t  gentop=\"$output_objdir/${outputname}x\"\n\t  generated=\"$generated $gentop\"\n\t  func_mkdir_p \"$gentop\"\n\t  save_oldobjs=$oldobjs\n\t  oldobjs=\n\t  counter=1\n\t  for obj in $save_oldobjs\n\t  do\n\t    func_basename \"$obj\"\n\t    objbase=\"$func_basename_result\"\n\t    case \" $oldobjs \" in\n\t    \" \") oldobjs=$obj ;;\n\t    *[\\ /]\"$objbase \"*)\n\t      while :; do\n\t\t# Make sure we don't pick an alternate name that also\n\t\t# overlaps.\n\t\tnewobj=lt$counter-$objbase\n\t\tfunc_arith $counter + 1\n\t\tcounter=$func_arith_result\n\t\tcase \" $oldobjs \" in\n\t\t*[\\ /]\"$newobj \"*) ;;\n\t\t*) if test ! -f \"$gentop/$newobj\"; then break; fi ;;\n\t\tesac\n\t      done\n\t      func_show_eval \"ln $obj $gentop/$newobj || cp $obj $gentop/$newobj\"\n\t      oldobjs=\"$oldobjs $gentop/$newobj\"\n\t      ;;\n\t    *) oldobjs=\"$oldobjs $obj\" ;;\n\t    esac\n\t  done\n\tfi\n\teval \"cmds=\\\"$old_archive_cmds\\\"\"\n\n\tfunc_len \" $cmds\"\n\tlen=$func_len_result\n\tif test \"$len\" -lt \"$max_cmd_len\" || test \"$max_cmd_len\" -le -1; then\n\t  cmds=$old_archive_cmds\n\telse\n\t  # the command line is too long to link in one step, link in parts\n\t  func_verbose \"using piecewise archive linking...\"\n\t  save_RANLIB=$RANLIB\n\t  RANLIB=:\n\t  objlist=\n\t  concat_cmds=\n\t  save_oldobjs=$oldobjs\n\t  oldobjs=\n\t  # Is there a better way of finding the last object in the list?\n\t  for obj in $save_oldobjs\n\t  do\n\t    last_oldobj=$obj\n\t  done\n\t  eval \"test_cmds=\\\"$old_archive_cmds\\\"\"\n\t  func_len \" $test_cmds\"\n\t  len0=$func_len_result\n\t  len=$len0\n\t  for obj in $save_oldobjs\n\t  do\n\t    func_len \" $obj\"\n\t    func_arith $len + $func_len_result\n\t    len=$func_arith_result\n\t    func_append objlist \" $obj\"\n\t    if test \"$len\" -lt \"$max_cmd_len\"; then\n\t      :\n\t    else\n\t      # the above command should be used before it gets too long\n\t      oldobjs=$objlist\n\t      if test \"$obj\" = \"$last_oldobj\" ; then\n\t\tRANLIB=$save_RANLIB\n\t      fi\n\t      test -z \"$concat_cmds\" || concat_cmds=$concat_cmds~\n\t      eval \"concat_cmds=\\\"\\${concat_cmds}$old_archive_cmds\\\"\"\n\t      objlist=\n\t      len=$len0\n\t    fi\n\t  done\n\t  RANLIB=$save_RANLIB\n\t  oldobjs=$objlist\n\t  if test \"X$oldobjs\" = \"X\" ; then\n\t    eval \"cmds=\\\"\\$concat_cmds\\\"\"\n\t  else\n\t    eval \"cmds=\\\"\\$concat_cmds~\\$old_archive_cmds\\\"\"\n\t  fi\n\tfi\n      fi\n      func_execute_cmds \"$cmds\" 'exit $?'\n    done\n\n    test -n \"$generated\" && \\\n      func_show_eval \"${RM}r$generated\"\n\n    # Now create the libtool archive.\n    case $output in\n    *.la)\n      old_library=\n      test \"$build_old_libs\" = yes && old_library=\"$libname.$libext\"\n      func_verbose \"creating $output\"\n\n      # Preserve any variables that may affect compiler behavior\n      for var in $variables_saved_for_relink; do\n\tif eval test -z \\\"\\${$var+set}\\\"; then\n\t  relink_command=\"{ test -z \\\"\\${$var+set}\\\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command\"\n\telif eval var_value=\\$$var; test -z \"$var_value\"; then\n\t  relink_command=\"$var=; export $var; $relink_command\"\n\telse\n\t  func_quote_for_eval \"$var_value\"\n\t  relink_command=\"$var=$func_quote_for_eval_result; export $var; $relink_command\"\n\tfi\n      done\n      # Quote the link command for shipping.\n      relink_command=\"(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)\"\n      relink_command=`$ECHO \"$relink_command\" | $SED \"$sed_quote_subst\"`\n      if test \"$hardcode_automatic\" = yes ; then\n\trelink_command=\n      fi\n\n      # Only create the output if not a dry run.\n      $opt_dry_run || {\n\tfor installed in no yes; do\n\t  if test \"$installed\" = yes; then\n\t    if test -z \"$install_libdir\"; then\n\t      break\n\t    fi\n\t    output=\"$output_objdir/$outputname\"i\n\t    # Replace all uninstalled libtool libraries with the installed ones\n\t    newdependency_libs=\n\t    for deplib in $dependency_libs; do\n\t      case $deplib in\n\t      *.la)\n\t\tfunc_basename \"$deplib\"\n\t\tname=\"$func_basename_result\"\n\t\tlibdir=`${SED} -n -e 's/^libdir=\\(.*\\)$/\\1/p' $deplib`\n\t\ttest -z \"$libdir\" && \\\n\t\t  func_fatal_error \"\\`$deplib' is not a valid libtool archive\"\n\t\tnewdependency_libs=\"$newdependency_libs $libdir/$name\"\n\t\t;;\n\t      *) newdependency_libs=\"$newdependency_libs $deplib\" ;;\n\t      esac\n\t    done\n\t    dependency_libs=\"$newdependency_libs\"\n\t    newdlfiles=\n\n\t    for lib in $dlfiles; do\n\t      case $lib in\n\t      *.la)\n\t        func_basename \"$lib\"\n\t\tname=\"$func_basename_result\"\n\t\tlibdir=`${SED} -n -e 's/^libdir=\\(.*\\)$/\\1/p' $lib`\n\t\ttest -z \"$libdir\" && \\\n\t\t  func_fatal_error \"\\`$lib' is not a valid libtool archive\"\n\t\tnewdlfiles=\"$newdlfiles $libdir/$name\"\n\t\t;;\n\t      *) newdlfiles=\"$newdlfiles $lib\" ;;\n\t      esac\n\t    done\n\t    dlfiles=\"$newdlfiles\"\n\t    newdlprefiles=\n\t    for lib in $dlprefiles; do\n\t      case $lib in\n\t      *.la)\n\t\t# Only pass preopened files to the pseudo-archive (for\n\t\t# eventual linking with the app. that links it) if we\n\t\t# didn't already link the preopened objects directly into\n\t\t# the library:\n\t\tfunc_basename \"$lib\"\n\t\tname=\"$func_basename_result\"\n\t\tlibdir=`${SED} -n -e 's/^libdir=\\(.*\\)$/\\1/p' $lib`\n\t\ttest -z \"$libdir\" && \\\n\t\t  func_fatal_error \"\\`$lib' is not a valid libtool archive\"\n\t\tnewdlprefiles=\"$newdlprefiles $libdir/$name\"\n\t\t;;\n\t      esac\n\t    done\n\t    dlprefiles=\"$newdlprefiles\"\n\t  else\n\t    newdlfiles=\n\t    for lib in $dlfiles; do\n\t      case $lib in\n\t\t[\\\\/]* | [A-Za-z]:[\\\\/]*) abs=\"$lib\" ;;\n\t\t*) abs=`pwd`\"/$lib\" ;;\n\t      esac\n\t      newdlfiles=\"$newdlfiles $abs\"\n\t    done\n\t    dlfiles=\"$newdlfiles\"\n\t    newdlprefiles=\n\t    for lib in $dlprefiles; do\n\t      case $lib in\n\t\t[\\\\/]* | [A-Za-z]:[\\\\/]*) abs=\"$lib\" ;;\n\t\t*) abs=`pwd`\"/$lib\" ;;\n\t      esac\n\t      newdlprefiles=\"$newdlprefiles $abs\"\n\t    done\n\t    dlprefiles=\"$newdlprefiles\"\n\t  fi\n\t  $RM $output\n\t  # place dlname in correct position for cygwin\n\t  # In fact, it would be nice if we could use this code for all target\n\t  # systems that can't hard-code library paths into their executables\n\t  # and that have no shared library path variable independent of PATH,\n\t  # but it turns out we can't easily determine that from inspecting\n\t  # libtool variables, so we have to hard-code the OSs to which it\n\t  # applies here; at the moment, that means platforms that use the PE\n\t  # object format with DLL files.  See the long comment at the top of\n\t  # tests/bindir.at for full details.\n\t  tdlname=$dlname\n\t  case $host,$output,$installed,$module,$dlname in\n\t    *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll)\n\t      # If a -bindir argument was supplied, place the dll there.\n\t      if test \"x$bindir\" != x ;\n\t      then\n\t\tfunc_relative_path \"$install_libdir\" \"$bindir\"\n\t\ttdlname=$func_relative_path_result$dlname\n\t      else\n\t\t# Otherwise fall back on heuristic.\n\t\ttdlname=../bin/$dlname\n\t      fi\n\t      ;;\n\t  esac\n\t  $ECHO > $output \"\\\n# $outputname - a libtool library file\n# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION\n#\n# Please DO NOT delete this file!\n# It is necessary for linking the library.\n\n# The name that we can dlopen(3).\ndlname='$tdlname'\n\n# Names of this library.\nlibrary_names='$library_names'\n\n# The name of the static archive.\nold_library='$old_library'\n\n# Linker flags that can not go in dependency_libs.\ninherited_linker_flags='$new_inherited_linker_flags'\n\n# Libraries that this one depends upon.\ndependency_libs='$dependency_libs'\n\n# Names of additional weak libraries provided by this library\nweak_library_names='$weak_libs'\n\n# Version information for $libname.\ncurrent=$current\nage=$age\nrevision=$revision\n\n# Is this an already installed library?\ninstalled=$installed\n\n# Should we warn about portability when linking against -modules?\nshouldnotlink=$module\n\n# Files to dlopen/dlpreopen\ndlopen='$dlfiles'\ndlpreopen='$dlprefiles'\n\n# Directory that this library needs to be installed in:\nlibdir='$install_libdir'\"\n\t  if test \"$installed\" = no && test \"$need_relink\" = yes; then\n\t    $ECHO >> $output \"\\\nrelink_command=\\\"$relink_command\\\"\"\n\t  fi\n\tdone\n      }\n\n      # Do a symbolic link so that the libtool archive can be found in\n      # LD_LIBRARY_PATH before the program is installed.\n      func_show_eval '( cd \"$output_objdir\" && $RM \"$outputname\" && $LN_S \"../$outputname\" \"$outputname\" )' 'exit $?'\n      ;;\n    esac\n    exit $EXIT_SUCCESS\n}\n\n{ test \"$mode\" = link || test \"$mode\" = relink; } &&\n    func_mode_link ${1+\"$@\"}\n\n\n# func_mode_uninstall arg...\nfunc_mode_uninstall ()\n{\n    $opt_debug\n    RM=\"$nonopt\"\n    files=\n    rmforce=\n    exit_status=0\n\n    # This variable tells wrapper scripts just to set variables rather\n    # than running their programs.\n    libtool_install_magic=\"$magic\"\n\n    for arg\n    do\n      case $arg in\n      -f) RM=\"$RM $arg\"; rmforce=yes ;;\n      -*) RM=\"$RM $arg\" ;;\n      *) files=\"$files $arg\" ;;\n      esac\n    done\n\n    test -z \"$RM\" && \\\n      func_fatal_help \"you must specify an RM program\"\n\n    rmdirs=\n\n    origobjdir=\"$objdir\"\n    for file in $files; do\n      func_dirname \"$file\" \"\" \".\"\n      dir=\"$func_dirname_result\"\n      if test \"X$dir\" = X.; then\n\tobjdir=\"$origobjdir\"\n      else\n\tobjdir=\"$dir/$origobjdir\"\n      fi\n      func_basename \"$file\"\n      name=\"$func_basename_result\"\n      test \"$mode\" = uninstall && objdir=\"$dir\"\n\n      # Remember objdir for removal later, being careful to avoid duplicates\n      if test \"$mode\" = clean; then\n\tcase \" $rmdirs \" in\n\t  *\" $objdir \"*) ;;\n\t  *) rmdirs=\"$rmdirs $objdir\" ;;\n\tesac\n      fi\n\n      # Don't error if the file doesn't exist and rm -f was used.\n      if { test -L \"$file\"; } >/dev/null 2>&1 ||\n\t { test -h \"$file\"; } >/dev/null 2>&1 ||\n\t test -f \"$file\"; then\n\t:\n      elif test -d \"$file\"; then\n\texit_status=1\n\tcontinue\n      elif test \"$rmforce\" = yes; then\n\tcontinue\n      fi\n\n      rmfiles=\"$file\"\n\n      case $name in\n      *.la)\n\t# Possibly a libtool archive, so verify it.\n\tif func_lalib_p \"$file\"; then\n\t  func_source $dir/$name\n\n\t  # Delete the libtool libraries and symlinks.\n\t  for n in $library_names; do\n\t    rmfiles=\"$rmfiles $objdir/$n\"\n\t  done\n\t  test -n \"$old_library\" && rmfiles=\"$rmfiles $objdir/$old_library\"\n\n\t  case \"$mode\" in\n\t  clean)\n\t    case \"  $library_names \" in\n\t    # \"  \" in the beginning catches empty $dlname\n\t    *\" $dlname \"*) ;;\n\t    *) rmfiles=\"$rmfiles $objdir/$dlname\" ;;\n\t    esac\n\t    test -n \"$libdir\" && rmfiles=\"$rmfiles $objdir/$name $objdir/${name}i\"\n\t    ;;\n\t  uninstall)\n\t    if test -n \"$library_names\"; then\n\t      # Do each command in the postuninstall commands.\n\t      func_execute_cmds \"$postuninstall_cmds\" 'test \"$rmforce\" = yes || exit_status=1'\n\t    fi\n\n\t    if test -n \"$old_library\"; then\n\t      # Do each command in the old_postuninstall commands.\n\t      func_execute_cmds \"$old_postuninstall_cmds\" 'test \"$rmforce\" = yes || exit_status=1'\n\t    fi\n\t    # FIXME: should reinstall the best remaining shared library.\n\t    ;;\n\t  esac\n\tfi\n\t;;\n\n      *.lo)\n\t# Possibly a libtool object, so verify it.\n\tif func_lalib_p \"$file\"; then\n\n\t  # Read the .lo file\n\t  func_source $dir/$name\n\n\t  # Add PIC object to the list of files to remove.\n\t  if test -n \"$pic_object\" &&\n\t     test \"$pic_object\" != none; then\n\t    rmfiles=\"$rmfiles $dir/$pic_object\"\n\t  fi\n\n\t  # Add non-PIC object to the list of files to remove.\n\t  if test -n \"$non_pic_object\" &&\n\t     test \"$non_pic_object\" != none; then\n\t    rmfiles=\"$rmfiles $dir/$non_pic_object\"\n\t  fi\n\tfi\n\t;;\n\n      *)\n\tif test \"$mode\" = clean ; then\n\t  noexename=$name\n\t  case $file in\n\t  *.exe)\n\t    func_stripname '' '.exe' \"$file\"\n\t    file=$func_stripname_result\n\t    func_stripname '' '.exe' \"$name\"\n\t    noexename=$func_stripname_result\n\t    # $file with .exe has already been added to rmfiles,\n\t    # add $file without .exe\n\t    rmfiles=\"$rmfiles $file\"\n\t    ;;\n\t  esac\n\t  # Do a test to see if this is a libtool program.\n\t  if func_ltwrapper_p \"$file\"; then\n\t    if func_ltwrapper_executable_p \"$file\"; then\n\t      func_ltwrapper_scriptname \"$file\"\n\t      relink_command=\n\t      func_source $func_ltwrapper_scriptname_result\n\t      rmfiles=\"$rmfiles $func_ltwrapper_scriptname_result\"\n\t    else\n\t      relink_command=\n\t      func_source $dir/$noexename\n\t    fi\n\n\t    # note $name still contains .exe if it was in $file originally\n\t    # as does the version of $file that was added into $rmfiles\n\t    rmfiles=\"$rmfiles $objdir/$name $objdir/${name}S.${objext}\"\n\t    if test \"$fast_install\" = yes && test -n \"$relink_command\"; then\n\t      rmfiles=\"$rmfiles $objdir/lt-$name\"\n\t    fi\n\t    if test \"X$noexename\" != \"X$name\" ; then\n\t      rmfiles=\"$rmfiles $objdir/lt-${noexename}.c\"\n\t    fi\n\t  fi\n\tfi\n\t;;\n      esac\n      func_show_eval \"$RM $rmfiles\" 'exit_status=1'\n    done\n    objdir=\"$origobjdir\"\n\n    # Try to remove the ${objdir}s in the directories where we deleted files\n    for dir in $rmdirs; do\n      if test -d \"$dir\"; then\n\tfunc_show_eval \"rmdir $dir >/dev/null 2>&1\"\n      fi\n    done\n\n    exit $exit_status\n}\n\n{ test \"$mode\" = uninstall || test \"$mode\" = clean; } &&\n    func_mode_uninstall ${1+\"$@\"}\n\ntest -z \"$mode\" && {\n  help=\"$generic_help\"\n  func_fatal_help \"you must specify a MODE\"\n}\n\ntest -z \"$exec_cmd\" && \\\n  func_fatal_help \"invalid operation mode \\`$mode'\"\n\nif test -n \"$exec_cmd\"; then\n  eval exec \"$exec_cmd\"\n  exit $EXIT_FAILURE\nfi\n\nexit $exit_status\n\n\n# The TAGs below are defined such that we never get into a situation\n# in which we disable both kinds of libraries.  Given conflicting\n# choices, we go for a static library, that is the most portable,\n# since we can't tell whether shared libraries were disabled because\n# the user asked for that or because the platform doesn't support\n# them.  This is particularly important on AIX, because we don't\n# support having both static and shared libraries enabled at the same\n# time on that platform, so we default to a shared-only configuration.\n# If a disable-shared tag is given, we'll fallback to a static-only\n# configuration.  But we'll never go from static-only to shared-only.\n\n# ### BEGIN LIBTOOL TAG CONFIG: disable-shared\nbuild_libtool_libs=no\nbuild_old_libs=yes\n# ### END LIBTOOL TAG CONFIG: disable-shared\n\n# ### BEGIN LIBTOOL TAG CONFIG: disable-static\nbuild_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac`\n# ### END LIBTOOL TAG CONFIG: disable-static\n\n# Local Variables:\n# mode:shell-script\n# sh-indentation:2\n# End:\n# vi:sw=2\n\n"
  },
  {
    "path": "src/vendor/libbacktrace/macho.c",
    "content": "/* elf.c -- Get debug data from a Mach-O file for backtraces.\n   Copyright (C) 2020-2024 Free Software Foundation, Inc.\n   Written by Ian Lance Taylor, Google.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n    (1) Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n\n    (2) Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in\n    the documentation and/or other materials provided with the\n    distribution.\n\n    (3) The name of the author may not be used to\n    endorse or promote products derived from this software without\n    specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\nIMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,\nINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\nHOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\nIN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGE.  */\n\n#include \"config.h\"\n\n#include <sys/types.h>\n#include <dirent.h>\n#include <stdlib.h>\n#include <string.h>\n\n#ifdef HAVE_MACH_O_DYLD_H\n#include <mach-o/dyld.h>\n#endif\n\n#include \"backtrace.h\"\n#include \"internal.h\"\n\n/* Mach-O file header for a 32-bit executable.  */\n\nstruct macho_header_32\n{\n  uint32_t magic;\t/* Magic number (MACH_O_MAGIC_32) */\n  uint32_t cputype;\t/* CPU type */\n  uint32_t cpusubtype;\t/* CPU subtype */\n  uint32_t filetype;\t/* Type of file (object, executable) */\n  uint32_t ncmds;\t/* Number of load commands */\n  uint32_t sizeofcmds;\t/* Total size of load commands */\n  uint32_t flags;\t/* Flags for special features */\n};\n\n/* Mach-O file header for a 64-bit executable.  */\n\nstruct macho_header_64\n{\n  uint32_t magic;\t/* Magic number (MACH_O_MAGIC_64) */\n  uint32_t cputype;\t/* CPU type */\n  uint32_t cpusubtype;\t/* CPU subtype */\n  uint32_t filetype;\t/* Type of file (object, executable) */\n  uint32_t ncmds;\t/* Number of load commands */\n  uint32_t sizeofcmds;\t/* Total size of load commands */\n  uint32_t flags;\t/* Flags for special features */\n  uint32_t reserved;\t/* Reserved */\n};\n\n/* Mach-O file header for a fat executable.  */\n\nstruct macho_header_fat\n{\n  uint32_t magic;\t/* Magic number (MACH_O_MH_(MAGIC|CIGAM)_FAT(_64)?) */\n  uint32_t nfat_arch;   /* Number of components */\n};\n\n/* Values for the header magic field.  */\n\n#define MACH_O_MH_MAGIC_32\t0xfeedface\n#define MACH_O_MH_MAGIC_64\t0xfeedfacf\n#define MACH_O_MH_MAGIC_FAT\t0xcafebabe\n#define MACH_O_MH_CIGAM_FAT\t0xbebafeca\n#define MACH_O_MH_MAGIC_FAT_64\t0xcafebabf\n#define MACH_O_MH_CIGAM_FAT_64\t0xbfbafeca\n\n/* Value for the header filetype field.  */\n\n#define MACH_O_MH_EXECUTE\t0x02\n#define MACH_O_MH_DYLIB\t\t0x06\n#define MACH_O_MH_BUNDLE\t0x08\n#define MACH_O_MH_DSYM\t\t0x0a\n\n/* A component of a fat file.  A fat file starts with a\n   macho_header_fat followed by nfat_arch instances of this\n   struct.  */\n\nstruct macho_fat_arch\n{\n  uint32_t cputype;\t/* CPU type */\n  uint32_t cpusubtype;\t/* CPU subtype */\n  uint32_t offset;\t/* File offset of this entry */\n  uint32_t size;\t/* Size of this entry */\n  uint32_t align;\t/* Alignment of this entry */\n};\n\n/* A component of a 64-bit fat file.  This is used if the magic field\n   is MAGIC_FAT_64.  This is only used when some file size or file\n   offset is too large to represent in the 32-bit format.  */\n\nstruct macho_fat_arch_64\n{\n  uint32_t cputype;\t/* CPU type */\n  uint32_t cpusubtype;\t/* CPU subtype */\n  uint64_t offset;\t/* File offset of this entry */\n  uint64_t size;\t/* Size of this entry */\n  uint32_t align;\t/* Alignment of this entry */\n  uint32_t reserved;\t/* Reserved */\n};\n\n/* Values for the fat_arch cputype field (and the header cputype\n   field).  */\n\n#define MACH_O_CPU_ARCH_ABI64 0x01000000\n\n#define MACH_O_CPU_TYPE_X86 7\n#define MACH_O_CPU_TYPE_ARM 12\n#define MACH_O_CPU_TYPE_PPC 18\n\n#define MACH_O_CPU_TYPE_X86_64 (MACH_O_CPU_TYPE_X86 | MACH_O_CPU_ARCH_ABI64)\n#define MACH_O_CPU_TYPE_ARM64  (MACH_O_CPU_TYPE_ARM | MACH_O_CPU_ARCH_ABI64)\n#define MACH_O_CPU_TYPE_PPC64  (MACH_O_CPU_TYPE_PPC | MACH_O_CPU_ARCH_ABI64)\n\n/* The header of a load command.  */\n\nstruct macho_load_command\n{\n  uint32_t cmd;\t\t/* The type of load command */\n  uint32_t cmdsize;\t/* Size in bytes of the entire command */\n};\n\n/* Values for the load_command cmd field.  */\n\n#define MACH_O_LC_SEGMENT\t0x01\n#define MACH_O_LC_SYMTAB\t0x02\n#define MACH_O_LC_SEGMENT_64\t0x19\n#define MACH_O_LC_UUID\t\t0x1b\n\n/* The length of a section of segment name.  */\n\n#define MACH_O_NAMELEN (16)\n\n/* LC_SEGMENT load command.  */\n\nstruct macho_segment_command\n{\n  uint32_t cmd;\t\t\t/* The type of load command (LC_SEGMENT) */\n  uint32_t cmdsize;\t\t/* Size in bytes of the entire command */\n  char segname[MACH_O_NAMELEN];\t/* Segment name */\n  uint32_t vmaddr;\t\t/* Virtual memory address */\n  uint32_t vmsize;\t\t/* Virtual memory size */\n  uint32_t fileoff;\t\t/* Offset of data to be mapped */\n  uint32_t filesize;\t\t/* Size of data in file */\n  uint32_t maxprot;\t\t/* Maximum permitted virtual protection */\n  uint32_t initprot;\t\t/* Initial virtual memory protection */\n  uint32_t nsects;\t\t/* Number of sections in this segment */\n  uint32_t flags;\t\t/* Flags */\n};\n\n/* LC_SEGMENT_64 load command.  */\n\nstruct macho_segment_64_command\n{\n  uint32_t cmd;\t\t\t/* The type of load command (LC_SEGMENT) */\n  uint32_t cmdsize;\t\t/* Size in bytes of the entire command */\n  char segname[MACH_O_NAMELEN];\t/* Segment name */\n  uint64_t vmaddr;\t\t/* Virtual memory address */\n  uint64_t vmsize;\t\t/* Virtual memory size */\n  uint64_t fileoff;\t\t/* Offset of data to be mapped */\n  uint64_t filesize;\t\t/* Size of data in file */\n  uint32_t maxprot;\t\t/* Maximum permitted virtual protection */\n  uint32_t initprot;\t\t/* Initial virtual memory protection */\n  uint32_t nsects;\t\t/* Number of sections in this segment */\n  uint32_t flags;\t\t/* Flags */\n};\n\n/* LC_SYMTAB load command.  */\n\nstruct macho_symtab_command\n{\n  uint32_t cmd;\t\t/* The type of load command (LC_SEGMENT) */\n  uint32_t cmdsize;\t/* Size in bytes of the entire command */\n  uint32_t symoff;\t/* File offset of symbol table */\n  uint32_t nsyms;\t/* Number of symbols */\n  uint32_t stroff;\t/* File offset of string table */\n  uint32_t strsize;\t/* String table size */\n};\n\n/* The length of a Mach-O uuid.  */\n\n#define MACH_O_UUID_LEN (16)\n\n/* LC_UUID load command.  */\n\nstruct macho_uuid_command\n{\n  uint32_t cmd;\t\t\t\t/* Type of load command (LC_UUID) */\n  uint32_t cmdsize;\t\t\t/* Size in bytes of command */\n  unsigned char uuid[MACH_O_UUID_LEN];\t/* UUID */\n};\n\n/* 32-bit section header within a LC_SEGMENT segment.  */\n\nstruct macho_section\n{\n  char sectname[MACH_O_NAMELEN];\t/* Section name */\n  char segment[MACH_O_NAMELEN];\t\t/* Segment of this section */\n  uint32_t addr;\t\t\t/* Address in memory */\n  uint32_t size;\t\t\t/* Section size */\n  uint32_t offset;\t\t\t/* File offset */\n  uint32_t align;\t\t\t/* Log2 of section alignment */\n  uint32_t reloff;\t\t\t/* File offset of relocations */\n  uint32_t nreloc;\t\t\t/* Number of relocs for this section */\n  uint32_t flags;\t\t\t/* Flags */\n  uint32_t reserved1;\n  uint32_t reserved2;\n};\n\n/* 64-bit section header within a LC_SEGMENT_64 segment.   */\n\nstruct macho_section_64\n{\n  char sectname[MACH_O_NAMELEN];\t/* Section name */\n  char segment[MACH_O_NAMELEN];\t\t/* Segment of this section */\n  uint64_t addr;\t\t\t/* Address in memory */\n  uint64_t size;\t\t\t/* Section size */\n  uint32_t offset;\t\t\t/* File offset */\n  uint32_t align;\t\t\t/* Log2 of section alignment */\n  uint32_t reloff;\t\t\t/* File offset of section relocations */\n  uint32_t nreloc;\t\t\t/* Number of relocs for this section */\n  uint32_t flags;\t\t\t/* Flags */\n  uint32_t reserved1;\n  uint32_t reserved2;\n  uint32_t reserved3;\n};\n\n/* 32-bit symbol data.  */\n\nstruct macho_nlist\n{\n  uint32_t n_strx;\t/* Index of name in string table */\n  uint8_t n_type;\t/* Type flag */\n  uint8_t n_sect;\t/* Section number */\n  uint16_t n_desc;\t/* Stabs description field */\n  uint32_t n_value;\t/* Value */\n};\n\n/* 64-bit symbol data.  */\n\nstruct macho_nlist_64\n{\n  uint32_t n_strx;\t/* Index of name in string table */\n  uint8_t n_type;\t/* Type flag */\n  uint8_t n_sect;\t/* Section number */\n  uint16_t n_desc;\t/* Stabs description field */\n  uint64_t n_value;\t/* Value */\n};\n\n/* Value found in nlist n_type field.  */\n\n#define MACH_O_N_STAB\t0xe0\t/* Stabs debugging symbol */\n#define MACH_O_N_TYPE\t0x0e\t/* Mask for type bits */\n\n/* Values found after masking with MACH_O_N_TYPE.  */\n#define MACH_O_N_UNDF\t0x00\t/* Undefined symbol */\n#define MACH_O_N_ABS\t0x02\t/* Absolute symbol */\n#define MACH_O_N_SECT\t0x0e\t/* Defined in section from n_sect field */\n\n#define MACH_O_GLOBAL   0x0f    /* global symbol */\n#define MACH_O_N_FNAME  0x26    /* static symbol: name,,n_sect,type,address */\n#define MACH_O_N_FUN    0x24    /* procedure: name,,n_sect,linenumber,address */\n\n/* Information we keep for a Mach-O symbol.  */\n\nstruct macho_symbol\n{\n  const char *name;\t/* Symbol name */\n  uintptr_t address;\t/* Symbol address */\n};\n\n/* Information to pass to macho_syminfo.  */\n\nstruct macho_syminfo_data\n{\n  struct macho_syminfo_data *next;\t/* Next module */\n  struct macho_symbol *symbols;\t\t/* Symbols sorted by address */\n  size_t count;\t\t\t\t/* Number of symbols */\n};\n\n/* Names of sections, indexed by enum dwarf_section in internal.h.  */\n\nstatic const char * const dwarf_section_names[DEBUG_MAX] =\n{\n  \"__debug_info\",\n  \"__debug_line\",\n  \"__debug_abbrev\",\n  \"__debug_ranges\",\n  \"__debug_str\",\n  \"\", /* DEBUG_ADDR */\n  \"__debug_str_offs\",\n  \"\", /* DEBUG_LINE_STR */\n  \"__debug_rnglists\"\n};\n\n/* A dummy callback function used when we can't find any debug info.  */\n\nstatic int\nmacho_nodebug (struct backtrace_state *state ATTRIBUTE_UNUSED,\n\t       uintptr_t pc ATTRIBUTE_UNUSED,\n\t       backtrace_full_callback callback ATTRIBUTE_UNUSED,\n\t       backtrace_error_callback error_callback, void *data)\n{\n  error_callback (data, \"no debug info in Mach-O executable (make sure to compile with -g; may need to run dsymutil)\", -1);\n  return 0;\n}\n\n/* A dummy callback function used when we can't find a symbol\n   table.  */\n\nvoid\nmacho_nosyms (struct backtrace_state *state ATTRIBUTE_UNUSED,\n\t      uintptr_t addr ATTRIBUTE_UNUSED,\n\t      backtrace_syminfo_callback callback ATTRIBUTE_UNUSED,\n\t      backtrace_error_callback error_callback, void *data)\n{\n  error_callback (data, \"no symbol table in Mach-O executable\", -1);\n}\n\n/* Add a single DWARF section to DWARF_SECTIONS, if we need the\n   section.  Returns 1 on success, 0 on failure.  */\n\nstatic int\nmacho_add_dwarf_section (struct backtrace_state *state, int descriptor,\n\t\t\t const char *sectname, uint32_t offset, uint64_t size,\n\t\t\t backtrace_error_callback error_callback, void *data,\n\t\t\t struct dwarf_sections *dwarf_sections)\n{\n  int i;\n\n  for (i = 0; i < (int) DEBUG_MAX; ++i)\n    {\n      if (dwarf_section_names[i][0] != '\\0'\n\t  && strncmp (sectname, dwarf_section_names[i], MACH_O_NAMELEN) == 0)\n\t{\n\t  struct backtrace_view section_view;\n\n\t  /* FIXME: Perhaps it would be better to try to use a single\n\t     view to read all the DWARF data, as we try to do for\n\t     ELF.  */\n\n\t  if (!backtrace_get_view (state, descriptor, offset, size,\n\t\t\t\t   error_callback, data, &section_view))\n\t    return 0;\n\t  dwarf_sections->data[i] = (const unsigned char *) section_view.data;\n\t  dwarf_sections->size[i] = size;\n\t  break;\n\t}\n    }\n  return 1;\n}\n\n/* Collect DWARF sections from a DWARF segment.  Returns 1 on success,\n   0 on failure.  */\n\nstatic int\nmacho_add_dwarf_segment (struct backtrace_state *state, int descriptor,\n\t\t\t off_t offset, unsigned int cmd, const char *psecs,\n\t\t\t size_t sizesecs, unsigned int nsects,\n\t\t\t backtrace_error_callback error_callback, void *data,\n\t\t\t struct dwarf_sections *dwarf_sections)\n{\n  size_t sec_header_size;\n  size_t secoffset;\n  unsigned int i;\n\n  switch (cmd)\n    {\n    case MACH_O_LC_SEGMENT:\n      sec_header_size = sizeof (struct macho_section);\n      break;\n    case MACH_O_LC_SEGMENT_64:\n      sec_header_size = sizeof (struct macho_section_64);\n      break;\n    default:\n      abort ();\n    }\n\n  secoffset = 0;\n  for (i = 0; i < nsects; ++i)\n    {\n      if (secoffset + sec_header_size > sizesecs)\n\t{\n\t  error_callback (data, \"section overflow withing segment\", 0);\n\t  return 0;\n\t}\n\n      switch (cmd)\n\t{\n\tcase MACH_O_LC_SEGMENT:\n\t  {\n\t    struct macho_section section;\n\n\t    memcpy (&section, psecs + secoffset, sizeof section);\n\t    macho_add_dwarf_section (state, descriptor, section.sectname,\n\t\t\t\t     offset + section.offset, section.size,\n\t\t\t\t     error_callback, data, dwarf_sections);\n\t  }\n\t  break;\n\n\tcase MACH_O_LC_SEGMENT_64:\n\t  {\n\t    struct macho_section_64 section;\n\n\t    memcpy (&section, psecs + secoffset, sizeof section);\n\t    macho_add_dwarf_section (state, descriptor, section.sectname,\n\t\t\t\t     offset + section.offset, section.size,\n\t\t\t\t     error_callback, data, dwarf_sections);\n\t  }\n\t  break;\n\n\tdefault:\n\t  abort ();\n\t}\n\n      secoffset += sec_header_size;\n    }\n\n  return 1;\n}\n\n/* Compare struct macho_symbol for qsort.  */\n\nstatic int\nmacho_symbol_compare (const void *v1, const void *v2)\n{\n  const struct macho_symbol *m1 = (const struct macho_symbol *) v1;\n  const struct macho_symbol *m2 = (const struct macho_symbol *) v2;\n\n  if (m1->address < m2->address)\n    return -1;\n  else if (m1->address > m2->address)\n    return 1;\n  else\n    return 0;\n}\n\n/* Compare an address against a macho_symbol for bsearch.  We allocate\n   one extra entry in the array so that this can safely look at the\n   next entry.  */\n\nstatic int\nmacho_symbol_search (const void *vkey, const void *ventry)\n{\n  const uintptr_t *key = (const uintptr_t *) vkey;\n  const struct macho_symbol *entry = (const struct macho_symbol *) ventry;\n  uintptr_t addr;\n\n  addr = *key;\n  if (addr < entry->address)\n    return -1;\n  else if (entry->name[0] == '\\0'\n\t   && entry->address == ~(uintptr_t) 0)\n    return -1;\n  else if ((entry + 1)->name[0] == '\\0'\n\t   && (entry + 1)->address == ~(uintptr_t) 0)\n    return -1;\n  else if (addr >= (entry + 1)->address)\n    return 1;\n  else\n    return 0;\n}\n\n/* Return whether the symbol type field indicates a symbol table entry\n   that we care about: a function or data symbol.  */\n\nstatic int\nmacho_defined_symbol (uint8_t type)\n{\n  if ((type & MACH_O_N_STAB) != 0)\n  {\n    switch (type)\n     {\n     case MACH_O_N_FNAME:\n      return 1;\n     case MACH_O_N_FUN:\n      return 1;\n     default:\n      return 0;\n     }\n  }\n  switch (type & MACH_O_N_TYPE)\n    {\n    case MACH_O_N_UNDF:\n      return 0;\n    case MACH_O_N_ABS:\n    case MACH_O_N_SECT:\n      return 1;\n    default:\n      return 0;\n    }\n}\n\n/* Add symbol table information for a Mach-O file.  */\n\nstatic int\nmacho_add_symtab (struct backtrace_state *state, int descriptor,\n\t\t  struct libbacktrace_base_address base_address, int is_64,\n\t\t  off_t symoff, unsigned int nsyms, off_t stroff,\n\t\t  unsigned int strsize,\n\t\t  backtrace_error_callback error_callback, void *data)\n{\n  size_t symsize;\n  struct backtrace_view sym_view;\n  int sym_view_valid;\n  struct backtrace_view str_view;\n  int str_view_valid;\n  size_t ndefs;\n  size_t symtaboff;\n  unsigned int i;\n  size_t macho_symbol_size;\n  struct macho_symbol *macho_symbols;\n  unsigned int j;\n  struct macho_syminfo_data *sdata;\n\n  sym_view_valid = 0;\n  str_view_valid = 0;\n  macho_symbol_size = 0;\n  macho_symbols = NULL;\n\n  if (is_64)\n    symsize = sizeof (struct macho_nlist_64);\n  else\n    symsize = sizeof (struct macho_nlist);\n\n  if (!backtrace_get_view (state, descriptor, symoff, nsyms * symsize,\n\t\t\t   error_callback, data, &sym_view))\n    goto fail;\n  sym_view_valid = 1;\n\n  if (!backtrace_get_view (state, descriptor, stroff, strsize,\n\t\t\t   error_callback, data, &str_view))\n    return 0;\n  str_view_valid = 1;\n\n  ndefs = 0;\n  symtaboff = 0;\n  for (i = 0; i < nsyms; ++i, symtaboff += symsize)\n    {\n      if (is_64)\n\t{\n\t  struct macho_nlist_64 nlist;\n\n\t  memcpy (&nlist, (const char *) sym_view.data + symtaboff,\n\t\t  sizeof nlist);\n\t  if (macho_defined_symbol (nlist.n_type))\n\t    ++ndefs;\n\t}\n      else\n\t{\n\t  struct macho_nlist nlist;\n\n\t  memcpy (&nlist, (const char *) sym_view.data + symtaboff,\n\t\t  sizeof nlist);\n\t  if (macho_defined_symbol (nlist.n_type))\n\t    ++ndefs;\n\t}\n    }\n\n  /* Add 1 to ndefs to make room for a sentinel.  */\n  macho_symbol_size = (ndefs + 1) * sizeof (struct macho_symbol);\n  macho_symbols = ((struct macho_symbol *)\n\t\t   backtrace_alloc (state, macho_symbol_size, error_callback,\n\t\t\t\t    data));\n  if (macho_symbols == NULL)\n    goto fail;\n\n  j = 0;\n  symtaboff = 0;\n  for (i = 0; i < nsyms; ++i, symtaboff += symsize)\n    {\n      uint32_t strx;\n      uint64_t value;\n      const char *name;\n\n      strx = 0;\n      value = 0;\n      if (is_64)\n\t{\n\t  struct macho_nlist_64 nlist;\n\n\t  memcpy (&nlist, (const char *) sym_view.data + symtaboff,\n\t\t  sizeof nlist);\n\t  if (!macho_defined_symbol (nlist.n_type))\n\t    continue;\n\n\t  strx = nlist.n_strx;\n\t  value = nlist.n_value;\n\t}\n      else\n\t{\n\t  struct macho_nlist nlist;\n\n\t  memcpy (&nlist, (const char *) sym_view.data + symtaboff,\n\t\t  sizeof nlist);\n\t  if (!macho_defined_symbol (nlist.n_type))\n\t    continue;\n\n\t  strx = nlist.n_strx;\n\t  value = nlist.n_value;\n\t}\n\n      if (strx >= strsize)\n\t{\n\t  error_callback (data, \"symbol string index out of range\", 0);\n\t  goto fail;\n\t}\n\n      name = (const char *) str_view.data + strx;\n      if (name[0] == '_')\n\t++name;\n      macho_symbols[j].name = name;\n      macho_symbols[j].address = libbacktrace_add_base (value, base_address);\n      ++j;\n    }\n\n  sdata = ((struct macho_syminfo_data *)\n\t   backtrace_alloc (state, sizeof *sdata, error_callback, data));\n  if (sdata == NULL)\n    goto fail;\n\n  /* We need to keep the string table since it holds the names, but we\n     can release the symbol table.  */\n\n  backtrace_release_view (state, &sym_view, error_callback, data);\n  sym_view_valid = 0;\n  str_view_valid = 0;\n\n  /* Add a trailing sentinel symbol.  */\n  macho_symbols[j].name = \"\";\n  macho_symbols[j].address = ~(uintptr_t) 0;\n\n  backtrace_qsort (macho_symbols, ndefs + 1, sizeof (struct macho_symbol),\n\t\t   macho_symbol_compare);\n\n  sdata->next = NULL;\n  sdata->symbols = macho_symbols;\n  sdata->count = ndefs;\n\n  if (!state->threaded)\n    {\n      struct macho_syminfo_data **pp;\n\n      for (pp = (struct macho_syminfo_data **) (void *) &state->syminfo_data;\n\t   *pp != NULL;\n\t   pp = &(*pp)->next)\n\t;\n      *pp = sdata;\n    }\n  else\n    {\n      while (1)\n\t{\n\t  struct macho_syminfo_data **pp;\n\n\t  pp = (struct macho_syminfo_data **) (void *) &state->syminfo_data;\n\n\t  while (1)\n\t    {\n\t      struct macho_syminfo_data *p;\n\n\t      p = backtrace_atomic_load_pointer (pp);\n\t      if (p == NULL)\n\t\tbreak;\n\n\t      pp = &p->next;\n\t    }\n\n\t  if (__sync_bool_compare_and_swap (pp, NULL, sdata))\n\t    break;\n\t}\n    }\n\n  return 1;\n\n fail:\n  if (macho_symbols != NULL)\n    backtrace_free (state, macho_symbols, macho_symbol_size,\n\t\t    error_callback, data);\n  if (sym_view_valid)\n    backtrace_release_view (state, &sym_view, error_callback, data);\n  if (str_view_valid)\n    backtrace_release_view (state, &str_view, error_callback, data);\n  return 0;\n}\n\n/* Return the symbol name and value for an ADDR.  */\n\nvoid\nmacho_syminfo (struct backtrace_state *state, uintptr_t addr,\n\t       backtrace_syminfo_callback callback,\n\t       backtrace_error_callback error_callback ATTRIBUTE_UNUSED,\n\t       void *data)\n{\n  struct macho_syminfo_data *sdata;\n  struct macho_symbol *sym;\n\n  sym = NULL;\n  if (!state->threaded)\n    {\n      for (sdata = (struct macho_syminfo_data *) state->syminfo_data;\n\t   sdata != NULL;\n\t   sdata = sdata->next)\n\t{\n\t  sym = ((struct macho_symbol *)\n\t\t bsearch (&addr, sdata->symbols, sdata->count,\n\t\t\t  sizeof (struct macho_symbol), macho_symbol_search));\n\t  if (sym != NULL)\n\t    break;\n\t}\n    }\n  else\n    {\n      struct macho_syminfo_data **pp;\n\n      pp = (struct macho_syminfo_data **) (void *) &state->syminfo_data;\n      while (1)\n\t{\n\t  sdata = backtrace_atomic_load_pointer (pp);\n\t  if (sdata == NULL)\n\t    break;\n\n\t  sym = ((struct macho_symbol *)\n\t\t bsearch (&addr, sdata->symbols, sdata->count,\n\t\t\t  sizeof (struct macho_symbol), macho_symbol_search));\n\t  if (sym != NULL)\n\t    break;\n\n\t  pp = &sdata->next;\n\t}\n    }\n\n  if (sym == NULL)\n    callback (data, addr, NULL, 0, 0);\n  else\n    callback (data, addr, sym->name, sym->address, 0);\n}\n\n/* Look through a fat file to find the relevant executable.  Returns 1\n   on success, 0 on failure (in both cases descriptor is closed).  */\n\nstatic int\nmacho_add_fat (struct backtrace_state *state, const char *filename,\n\t       int descriptor, int swapped, off_t offset,\n\t       const unsigned char *match_uuid,\n\t       struct libbacktrace_base_address base_address,\n\t       int skip_symtab, uint32_t nfat_arch, int is_64,\n\t       backtrace_error_callback error_callback, void *data,\n\t       fileline *fileline_fn, int *found_sym)\n{\n  int arch_view_valid;\n  unsigned int cputype;\n  size_t arch_size;\n  struct backtrace_view arch_view;\n  unsigned int i;\n\n  arch_view_valid = 0;\n\n#if defined (__x86_64__)\n  cputype = MACH_O_CPU_TYPE_X86_64;\n#elif defined (__i386__)\n  cputype = MACH_O_CPU_TYPE_X86;\n#elif defined (__aarch64__)\n  cputype = MACH_O_CPU_TYPE_ARM64;\n#elif defined (__arm__)\n  cputype = MACH_O_CPU_TYPE_ARM;\n#elif defined (__ppc__)\n  cputype = MACH_O_CPU_TYPE_PPC;\n#elif defined (__ppc64__)\n  cputype = MACH_O_CPU_TYPE_PPC64;\n#else\n  error_callback (data, \"unknown Mach-O architecture\", 0);\n  goto fail;\n#endif\n\n  if (is_64)\n    arch_size = sizeof (struct macho_fat_arch_64);\n  else\n    arch_size = sizeof (struct macho_fat_arch);\n\n  if (!backtrace_get_view (state, descriptor, offset,\n\t\t\t   nfat_arch * arch_size,\n\t\t\t   error_callback, data, &arch_view))\n    goto fail;\n\n  for (i = 0; i < nfat_arch; ++i)\n    {\n      uint32_t fcputype;\n      uint64_t foffset;\n\n      if (is_64)\n\t{\n\t  struct macho_fat_arch_64 fat_arch_64;\n\n\t  memcpy (&fat_arch_64,\n\t\t  (const char *) arch_view.data + i * arch_size,\n\t\t  arch_size);\n\t  fcputype = fat_arch_64.cputype;\n\t  foffset = fat_arch_64.offset;\n\t  if (swapped)\n\t    {\n\t      fcputype = __builtin_bswap32 (fcputype);\n\t      foffset = __builtin_bswap64 (foffset);\n\t    }\n\t}\n      else\n\t{\n\t  struct macho_fat_arch fat_arch_32;\n\n\t  memcpy (&fat_arch_32,\n\t\t  (const char *) arch_view.data + i * arch_size,\n\t\t  arch_size);\n\t  fcputype = fat_arch_32.cputype;\n\t  foffset = (uint64_t) fat_arch_32.offset;\n\t  if (swapped)\n\t    {\n\t      fcputype = __builtin_bswap32 (fcputype);\n\t      foffset = (uint64_t) __builtin_bswap32 ((uint32_t) foffset);\n\t    }\n\t}\n\n      if (fcputype == cputype)\n\t{\n\t  /* FIXME: What about cpusubtype?  */\n\t  backtrace_release_view (state, &arch_view, error_callback, data);\n\t  return macho_add (state, filename, descriptor, foffset, match_uuid,\n\t\t\t    base_address, skip_symtab, error_callback, data,\n\t\t\t    fileline_fn, found_sym);\n\t}\n    }\n\n  error_callback (data, \"could not find executable in fat file\", 0);\n\n fail:\n  if (arch_view_valid)\n    backtrace_release_view (state, &arch_view, error_callback, data);\n  if (descriptor != -1)\n    backtrace_close (descriptor, error_callback, data);\n  return 0;\n}\n\n/* Look for the dsym file for FILENAME.  This is called if FILENAME\n   does not have debug info or a symbol table.  Returns 1 on success,\n   0 on failure.  */\n\nstatic int\nmacho_add_dsym (struct backtrace_state *state, const char *filename,\n\t\tstruct libbacktrace_base_address base_address,\n\t\tconst unsigned char *uuid,\n\t\tbacktrace_error_callback error_callback, void *data,\n\t\tfileline* fileline_fn)\n{\n  const char *p;\n  const char *dirname;\n  char *diralc;\n  size_t dirnamelen;\n  const char *basename;\n  size_t basenamelen;\n  const char *dsymsuffixdir;\n  size_t dsymsuffixdirlen;\n  size_t dsymlen;\n  char *dsym;\n  char *ps;\n  int d;\n  int does_not_exist;\n  int dummy_found_sym;\n\n  diralc = NULL;\n  dirnamelen = 0;\n  dsym = NULL;\n  dsymlen = 0;\n\n  p = strrchr (filename, '/');\n  if (p == NULL)\n    {\n      dirname = \".\";\n      dirnamelen = 1;\n      basename = filename;\n      basenamelen = strlen (basename);\n      diralc = NULL;\n    }\n  else\n    {\n      dirnamelen = p - filename;\n      diralc = backtrace_alloc (state, dirnamelen + 1, error_callback, data);\n      if (diralc == NULL)\n\tgoto fail;\n      memcpy (diralc, filename, dirnamelen);\n      diralc[dirnamelen] = '\\0';\n      dirname = diralc;\n      basename = p + 1;\n      basenamelen = strlen (basename);\n    }\n\n  dsymsuffixdir = \".dSYM/Contents/Resources/DWARF/\";\n  dsymsuffixdirlen = strlen (dsymsuffixdir);\n\n  dsymlen = (dirnamelen\n\t     + 1\n\t     + basenamelen\n\t     + dsymsuffixdirlen\n\t     + basenamelen\n\t     + 1);\n  dsym = backtrace_alloc (state, dsymlen, error_callback, data);\n  if (dsym == NULL)\n    goto fail;\n\n  ps = dsym;\n  memcpy (ps, dirname, dirnamelen);\n  ps += dirnamelen;\n  *ps++ = '/';\n  memcpy (ps, basename, basenamelen);\n  ps += basenamelen;\n  memcpy (ps, dsymsuffixdir, dsymsuffixdirlen);\n  ps += dsymsuffixdirlen;\n  memcpy (ps, basename, basenamelen);\n  ps += basenamelen;\n  *ps = '\\0';\n\n  if (diralc != NULL)\n    {\n      backtrace_free (state, diralc, dirnamelen + 1, error_callback, data);\n      diralc = NULL;\n    }\n\n  d = backtrace_open (dsym, error_callback, data, &does_not_exist);\n  if (d < 0)\n    {\n      /* The file does not exist, so we can't read the debug info.\n\t Just return success.  */\n      backtrace_free (state, dsym, dsymlen, error_callback, data);\n      return 1;\n    }\n\n  if (!macho_add (state, dsym, d, 0, uuid, base_address, 1,\n\t\t  error_callback, data, fileline_fn, &dummy_found_sym))\n    goto fail;\n\n  backtrace_free (state, dsym, dsymlen, error_callback, data);\n\n  return 1;\n\n fail:\n  if (dsym != NULL)\n    backtrace_free (state, dsym, dsymlen, error_callback, data);\n  if (diralc != NULL)\n    backtrace_free (state, diralc, dirnamelen, error_callback, data);\n  return 0;\n}\n\n/* Add the backtrace data for a Macho-O file.  Returns 1 on success, 0\n   on failure (in both cases descriptor is closed).\n\n   FILENAME: the name of the executable.\n   DESCRIPTOR: an open descriptor for the executable, closed here.\n   OFFSET: the offset within the file of this executable, for fat files.\n   MATCH_UUID: if not NULL, UUID that must match.\n   BASE_ADDRESS: the load address of the executable.\n   SKIP_SYMTAB: if non-zero, ignore the symbol table; used for dSYM files.\n   FILELINE_FN: set to the fileline function, by backtrace_dwarf_add.\n   FOUND_SYM: set to non-zero if we found the symbol table.\n*/\n\nint\nmacho_add (struct backtrace_state *state, const char *filename, int descriptor,\n\t   off_t offset, const unsigned char *match_uuid,\n\t   struct libbacktrace_base_address base_address, int skip_symtab,\n\t   backtrace_error_callback error_callback, void *data,\n\t   fileline *fileline_fn, int *found_sym)\n{\n  struct backtrace_view header_view;\n  struct macho_header_32 header;\n  off_t hdroffset;\n  int is_64;\n  struct backtrace_view cmds_view;\n  int cmds_view_valid;\n  struct dwarf_sections dwarf_sections;\n  int have_dwarf;\n  unsigned char uuid[MACH_O_UUID_LEN];\n  int have_uuid;\n  size_t cmdoffset;\n  unsigned int i;\n\n  *found_sym = 0;\n\n  cmds_view_valid = 0;\n\n  /* The 32-bit and 64-bit file headers start out the same, so we can\n     just always read the 32-bit version.  A fat header is shorter but\n     it will always be followed by data, so it's OK to read extra.  */\n\n  if (!backtrace_get_view (state, descriptor, offset,\n\t\t\t   sizeof (struct macho_header_32),\n\t\t\t   error_callback, data, &header_view))\n    goto fail;\n\n  memcpy (&header, header_view.data, sizeof header);\n\n  backtrace_release_view (state, &header_view, error_callback, data);\n\n  switch (header.magic)\n    {\n    case MACH_O_MH_MAGIC_32:\n      is_64 = 0;\n      hdroffset = offset + sizeof (struct macho_header_32);\n      break;\n    case MACH_O_MH_MAGIC_64:\n      is_64 = 1;\n      hdroffset = offset + sizeof (struct macho_header_64);\n      break;\n    case MACH_O_MH_MAGIC_FAT:\n    case MACH_O_MH_MAGIC_FAT_64:\n      {\n\tstruct macho_header_fat fat_header;\n\n\thdroffset = offset + sizeof (struct macho_header_fat);\n\tmemcpy (&fat_header, &header, sizeof fat_header);\n\treturn macho_add_fat (state, filename, descriptor, 0, hdroffset,\n\t\t\t      match_uuid, base_address, skip_symtab,\n\t\t\t      fat_header.nfat_arch,\n\t\t\t      header.magic == MACH_O_MH_MAGIC_FAT_64,\n\t\t\t      error_callback, data, fileline_fn, found_sym);\n      }\n    case MACH_O_MH_CIGAM_FAT:\n    case MACH_O_MH_CIGAM_FAT_64:\n      {\n\tstruct macho_header_fat fat_header;\n\tuint32_t nfat_arch;\n\n\thdroffset = offset + sizeof (struct macho_header_fat);\n\tmemcpy (&fat_header, &header, sizeof fat_header);\n\tnfat_arch = __builtin_bswap32 (fat_header.nfat_arch);\n\treturn macho_add_fat (state, filename, descriptor, 1, hdroffset,\n\t\t\t      match_uuid, base_address, skip_symtab,\n\t\t\t      nfat_arch,\n\t\t\t      header.magic == MACH_O_MH_CIGAM_FAT_64,\n\t\t\t      error_callback, data, fileline_fn, found_sym);\n      }\n    default:\n      error_callback (data, \"executable file is not in Mach-O format\", 0);\n      goto fail;\n    }\n\n  switch (header.filetype)\n    {\n    case MACH_O_MH_EXECUTE:\n    case MACH_O_MH_DYLIB:\n    case MACH_O_MH_DSYM:\n    case MACH_O_MH_BUNDLE:\n      break;\n    default:\n      error_callback (data, \"executable file is not an executable\", 0);\n      goto fail;\n    }\n\n  if (!backtrace_get_view (state, descriptor, hdroffset, header.sizeofcmds,\n\t\t\t   error_callback, data, &cmds_view))\n    goto fail;\n  cmds_view_valid = 1;\n\n  memset (&dwarf_sections, 0, sizeof dwarf_sections);\n  have_dwarf = 0;\n  memset (&uuid, 0, sizeof uuid);\n  have_uuid = 0;\n\n  cmdoffset = 0;\n  for (i = 0; i < header.ncmds; ++i)\n    {\n      const char *pcmd;\n      struct macho_load_command load_command;\n\n      if (cmdoffset + sizeof load_command > header.sizeofcmds)\n\tbreak;\n\n      pcmd = (const char *) cmds_view.data + cmdoffset;\n      memcpy (&load_command, pcmd, sizeof load_command);\n\n      switch (load_command.cmd)\n\t{\n\tcase MACH_O_LC_SEGMENT:\n\t  {\n\t    struct macho_segment_command segcmd;\n\n\t    memcpy (&segcmd, pcmd, sizeof segcmd);\n\t    if (memcmp (segcmd.segname,\n\t\t\t\"__DWARF\\0\\0\\0\\0\\0\\0\\0\\0\\0\",\n\t\t\tMACH_O_NAMELEN) == 0)\n\t      {\n\t\tif (!macho_add_dwarf_segment (state, descriptor, offset,\n\t\t\t\t\t      load_command.cmd,\n\t\t\t\t\t      pcmd + sizeof segcmd,\n\t\t\t\t\t      (load_command.cmdsize\n\t\t\t\t\t       - sizeof segcmd),\n\t\t\t\t\t      segcmd.nsects, error_callback,\n\t\t\t\t\t      data, &dwarf_sections))\n\t\t  goto fail;\n\t\thave_dwarf = 1;\n\t      }\n\t  }\n\t  break;\n\n\tcase MACH_O_LC_SEGMENT_64:\n\t  {\n\t    struct macho_segment_64_command segcmd;\n\n\t    memcpy (&segcmd, pcmd, sizeof segcmd);\n\t    if (memcmp (segcmd.segname,\n\t\t\t\"__DWARF\\0\\0\\0\\0\\0\\0\\0\\0\\0\",\n\t\t\tMACH_O_NAMELEN) == 0)\n\t      {\n\t\tif (!macho_add_dwarf_segment (state, descriptor, offset,\n\t\t\t\t\t      load_command.cmd,\n\t\t\t\t\t      pcmd + sizeof segcmd,\n\t\t\t\t\t      (load_command.cmdsize\n\t\t\t\t\t       - sizeof segcmd),\n\t\t\t\t\t      segcmd.nsects, error_callback,\n\t\t\t\t\t      data, &dwarf_sections))\n\t\t  goto fail;\n\t\thave_dwarf = 1;\n\t      }\n\t  }\n\t  break;\n\n\tcase MACH_O_LC_SYMTAB:\n\t  if (!skip_symtab)\n\t    {\n\t      struct macho_symtab_command symcmd;\n\n\t      memcpy (&symcmd, pcmd, sizeof symcmd);\n\t      if (!macho_add_symtab (state, descriptor, base_address, is_64,\n\t\t\t\t     offset + symcmd.symoff, symcmd.nsyms,\n\t\t\t\t     offset + symcmd.stroff, symcmd.strsize,\n\t\t\t\t     error_callback, data))\n\t\tgoto fail;\n\n\t      *found_sym = 1;\n\t    }\n\t  break;\n\n\tcase MACH_O_LC_UUID:\n\t  {\n\t    struct macho_uuid_command uuidcmd;\n\n\t    memcpy (&uuidcmd, pcmd, sizeof uuidcmd);\n\t    memcpy (&uuid[0], &uuidcmd.uuid[0], MACH_O_UUID_LEN);\n\t    have_uuid = 1;\n\t  }\n\t  break;\n\n\tdefault:\n\t  break;\n\t}\n\n      cmdoffset += load_command.cmdsize;\n    }\n\n  if (!backtrace_close (descriptor, error_callback, data))\n    goto fail;\n  descriptor = -1;\n\n  backtrace_release_view (state, &cmds_view, error_callback, data);\n  cmds_view_valid = 0;\n\n  if (match_uuid != NULL)\n    {\n      /* If we don't have a UUID, or it doesn't match, just ignore\n\t this file.  */\n      if (!have_uuid\n\t  || memcmp (match_uuid, &uuid[0], MACH_O_UUID_LEN) != 0)\n\treturn 1;\n    }\n\n  if (have_dwarf)\n    {\n      int is_big_endian;\n\n      is_big_endian = 0;\n#if defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__)\n#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__\n      is_big_endian = 1;\n#endif\n#endif\n\n      if (!backtrace_dwarf_add (state, base_address, &dwarf_sections,\n\t\t\t\tis_big_endian, NULL, error_callback, data,\n\t\t\t\tfileline_fn, NULL))\n\tgoto fail;\n    }\n\n  if (!have_dwarf && have_uuid)\n    {\n      if (!macho_add_dsym (state, filename, base_address, &uuid[0],\n\t\t\t   error_callback, data, fileline_fn))\n\tgoto fail;\n    }\n\n  return 1;\n\n fail:\n  if (cmds_view_valid)\n    backtrace_release_view (state, &cmds_view, error_callback, data);\n  if (descriptor != -1)\n    backtrace_close (descriptor, error_callback, data);\n  return 0;\n}\n\n#ifdef HAVE_MACH_O_DYLD_H\n\n/* Initialize the backtrace data we need from a Mach-O executable\n   using the dyld support functions.  This closes descriptor.  */\n\nint\nbacktrace_initialize (struct backtrace_state *state, const char *filename,\n\t\t      int descriptor, backtrace_error_callback error_callback,\n\t\t      void *data, fileline *fileline_fn)\n{\n  uint32_t c;\n  uint32_t i;\n  int closed_descriptor;\n  int found_sym;\n  fileline macho_fileline_fn;\n\n  closed_descriptor = 0;\n  found_sym = 0;\n  macho_fileline_fn = macho_nodebug;\n\n  c = _dyld_image_count ();\n  for (i = 0; i < c; ++i)\n    {\n      struct libbacktrace_base_address base_address;\n      const char *name;\n      int d;\n      fileline mff;\n      int mfs;\n\n      name = _dyld_get_image_name (i);\n      if (name == NULL)\n\tcontinue;\n\n      if (strcmp (name, filename) == 0 && !closed_descriptor)\n\t{\n\t  d = descriptor;\n\t  closed_descriptor = 1;\n\t}\n      else\n\t{\n\t  int does_not_exist;\n\n\t  d = backtrace_open (name, error_callback, data, &does_not_exist);\n\t  if (d < 0)\n\t    continue;\n\t}\n\n      base_address.m = _dyld_get_image_vmaddr_slide (i);\n\n      mff = macho_nodebug;\n      if (!macho_add (state, name, d, 0, NULL, base_address, 0,\n\t\t      error_callback, data, &mff, &mfs))\n\tcontinue;\n\n      if (mff != macho_nodebug)\n\tmacho_fileline_fn = mff;\n      if (mfs)\n\tfound_sym = 1;\n    }\n\n  if (!closed_descriptor)\n    backtrace_close (descriptor, error_callback, data);\n\n  if (!state->threaded)\n    {\n      if (found_sym)\n\tstate->syminfo_fn = macho_syminfo;\n      else if (state->syminfo_fn == NULL)\n\tstate->syminfo_fn = macho_nosyms;\n    }\n  else\n    {\n      if (found_sym)\n\tbacktrace_atomic_store_pointer (&state->syminfo_fn, macho_syminfo);\n      else\n\t(void) __sync_bool_compare_and_swap (&state->syminfo_fn, NULL,\n\t\t\t\t\t     macho_nosyms);\n    }\n\n  if (!state->threaded)\n    *fileline_fn = state->fileline_fn;\n  else\n    *fileline_fn = backtrace_atomic_load_pointer (&state->fileline_fn);\n\n  if (*fileline_fn == NULL || *fileline_fn == macho_nodebug)\n    *fileline_fn = macho_fileline_fn;\n\n  return 1;\n}\n\n#else /* !defined (HAVE_MACH_O_DYLD_H) */\n\n/* Initialize the backtrace data we need from a Mach-O executable\n   without using the dyld support functions.  This closes\n   descriptor.  */\n\nint\nbacktrace_initialize (struct backtrace_state *state, const char *filename,\n\t\t      int descriptor, backtrace_error_callback error_callback,\n\t\t      void *data, fileline *fileline_fn)\n{\n  fileline macho_fileline_fn;\n  struct libbacktrace_base_address zero_base_address;\n  int found_sym;\n\n  macho_fileline_fn = macho_nodebug;\n  memset (&zero_base_address, 0, sizeof zero_base_address);\n  if (!macho_add (state, filename, descriptor, 0, NULL, zero_base_address, 0,\n\t\t  error_callback, data, &macho_fileline_fn, &found_sym))\n    return 0;\n\n  if (!state->threaded)\n    {\n      if (found_sym)\n\tstate->syminfo_fn = macho_syminfo;\n      else if (state->syminfo_fn == NULL)\n\tstate->syminfo_fn = macho_nosyms;\n    }\n  else\n    {\n      if (found_sym)\n\tbacktrace_atomic_store_pointer (&state->syminfo_fn, macho_syminfo);\n      else\n\t(void) __sync_bool_compare_and_swap (&state->syminfo_fn, NULL,\n\t\t\t\t\t     macho_nosyms);\n    }\n\n  if (!state->threaded)\n    *fileline_fn = state->fileline_fn;\n  else\n    *fileline_fn = backtrace_atomic_load_pointer (&state->fileline_fn);\n\n  if (*fileline_fn == NULL || *fileline_fn == macho_nodebug)\n    *fileline_fn = macho_fileline_fn;\n\n  return 1;\n}\n\n#endif /* !defined (HAVE_MACH_O_DYLD_H) */\n"
  },
  {
    "path": "src/vendor/libbacktrace/missing",
    "content": "#! /bin/sh\n# Common wrapper for a few potentially missing GNU programs.\n\nscriptversion=2013-10-28.13; # UTC\n\n# Copyright (C) 1996-2014 Free Software Foundation, Inc.\n# Originally written by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.\n\n# This program is free software; you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation; either version 2, or (at your option)\n# any later version.\n\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n\n# You should have received a copy of the GNU General Public License\n# along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\n# As a special exception to the GNU General Public License, if you\n# distribute this file as part of a program that contains a\n# configuration script generated by Autoconf, you may include it under\n# the same distribution terms that you use for the rest of that program.\n\nif test $# -eq 0; then\n  echo 1>&2 \"Try '$0 --help' for more information\"\n  exit 1\nfi\n\ncase $1 in\n\n  --is-lightweight)\n    # Used by our autoconf macros to check whether the available missing\n    # script is modern enough.\n    exit 0\n    ;;\n\n  --run)\n    # Back-compat with the calling convention used by older automake.\n    shift\n    ;;\n\n  -h|--h|--he|--hel|--help)\n    echo \"\\\n$0 [OPTION]... PROGRAM [ARGUMENT]...\n\nRun 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due\nto PROGRAM being missing or too old.\n\nOptions:\n  -h, --help      display this help and exit\n  -v, --version   output version information and exit\n\nSupported PROGRAM values:\n  aclocal   autoconf  autoheader   autom4te  automake  makeinfo\n  bison     yacc      flex         lex       help2man\n\nVersion suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and\n'g' are ignored when checking the name.\n\nSend bug reports to <bug-automake@gnu.org>.\"\n    exit $?\n    ;;\n\n  -v|--v|--ve|--ver|--vers|--versi|--versio|--version)\n    echo \"missing $scriptversion (GNU Automake)\"\n    exit $?\n    ;;\n\n  -*)\n    echo 1>&2 \"$0: unknown '$1' option\"\n    echo 1>&2 \"Try '$0 --help' for more information\"\n    exit 1\n    ;;\n\nesac\n\n# Run the given program, remember its exit status.\n\"$@\"; st=$?\n\n# If it succeeded, we are done.\ntest $st -eq 0 && exit 0\n\n# Also exit now if we it failed (or wasn't found), and '--version' was\n# passed; such an option is passed most likely to detect whether the\n# program is present and works.\ncase $2 in --version|--help) exit $st;; esac\n\n# Exit code 63 means version mismatch.  This often happens when the user\n# tries to use an ancient version of a tool on a file that requires a\n# minimum version.\nif test $st -eq 63; then\n  msg=\"probably too old\"\nelif test $st -eq 127; then\n  # Program was missing.\n  msg=\"missing on your system\"\nelse\n  # Program was found and executed, but failed.  Give up.\n  exit $st\nfi\n\nperl_URL=http://www.perl.org/\nflex_URL=http://flex.sourceforge.net/\ngnu_software_URL=http://www.gnu.org/software\n\nprogram_details ()\n{\n  case $1 in\n    aclocal|automake)\n      echo \"The '$1' program is part of the GNU Automake package:\"\n      echo \"<$gnu_software_URL/automake>\"\n      echo \"It also requires GNU Autoconf, GNU m4 and Perl in order to run:\"\n      echo \"<$gnu_software_URL/autoconf>\"\n      echo \"<$gnu_software_URL/m4/>\"\n      echo \"<$perl_URL>\"\n      ;;\n    autoconf|autom4te|autoheader)\n      echo \"The '$1' program is part of the GNU Autoconf package:\"\n      echo \"<$gnu_software_URL/autoconf/>\"\n      echo \"It also requires GNU m4 and Perl in order to run:\"\n      echo \"<$gnu_software_URL/m4/>\"\n      echo \"<$perl_URL>\"\n      ;;\n  esac\n}\n\ngive_advice ()\n{\n  # Normalize program name to check for.\n  normalized_program=`echo \"$1\" | sed '\n    s/^gnu-//; t\n    s/^gnu//; t\n    s/^g//; t'`\n\n  printf '%s\\n' \"'$1' is $msg.\"\n\n  configure_deps=\"'configure.ac' or m4 files included by 'configure.ac'\"\n  case $normalized_program in\n    autoconf*)\n      echo \"You should only need it if you modified 'configure.ac',\"\n      echo \"or m4 files included by it.\"\n      program_details 'autoconf'\n      ;;\n    autoheader*)\n      echo \"You should only need it if you modified 'acconfig.h' or\"\n      echo \"$configure_deps.\"\n      program_details 'autoheader'\n      ;;\n    automake*)\n      echo \"You should only need it if you modified 'Makefile.am' or\"\n      echo \"$configure_deps.\"\n      program_details 'automake'\n      ;;\n    aclocal*)\n      echo \"You should only need it if you modified 'acinclude.m4' or\"\n      echo \"$configure_deps.\"\n      program_details 'aclocal'\n      ;;\n   autom4te*)\n      echo \"You might have modified some maintainer files that require\"\n      echo \"the 'autom4te' program to be rebuilt.\"\n      program_details 'autom4te'\n      ;;\n    bison*|yacc*)\n      echo \"You should only need it if you modified a '.y' file.\"\n      echo \"You may want to install the GNU Bison package:\"\n      echo \"<$gnu_software_URL/bison/>\"\n      ;;\n    lex*|flex*)\n      echo \"You should only need it if you modified a '.l' file.\"\n      echo \"You may want to install the Fast Lexical Analyzer package:\"\n      echo \"<$flex_URL>\"\n      ;;\n    help2man*)\n      echo \"You should only need it if you modified a dependency\" \\\n           \"of a man page.\"\n      echo \"You may want to install the GNU Help2man package:\"\n      echo \"<$gnu_software_URL/help2man/>\"\n    ;;\n    makeinfo*)\n      echo \"You should only need it if you modified a '.texi' file, or\"\n      echo \"any other file indirectly affecting the aspect of the manual.\"\n      echo \"You might want to install the Texinfo package:\"\n      echo \"<$gnu_software_URL/texinfo/>\"\n      echo \"The spurious makeinfo call might also be the consequence of\"\n      echo \"using a buggy 'make' (AIX, DU, IRIX), in which case you might\"\n      echo \"want to install GNU make:\"\n      echo \"<$gnu_software_URL/make/>\"\n      ;;\n    *)\n      echo \"You might have modified some files without having the proper\"\n      echo \"tools for further handling them.  Check the 'README' file, it\"\n      echo \"often tells you about the needed prerequisites for installing\"\n      echo \"this package.  You may also peek at any GNU archive site, in\"\n      echo \"case some other package contains this missing '$1' program.\"\n      ;;\n  esac\n}\n\ngive_advice \"$1\" | sed -e '1s/^/WARNING: /' \\\n                       -e '2,$s/^/         /' >&2\n\n# Propagate the correct exit status (expected to be 127 for a program\n# not found, 63 for a program that failed due to version mismatch).\nexit $st\n\n# Local variables:\n# eval: (add-hook 'write-file-hooks 'time-stamp)\n# time-stamp-start: \"scriptversion=\"\n# time-stamp-format: \"%:y-%02m-%02d.%02H\"\n# time-stamp-time-zone: \"UTC\"\n# time-stamp-end: \"; # UTC\"\n# End:\n"
  },
  {
    "path": "src/vendor/libbacktrace/mmap.c",
    "content": "/* mmap.c -- Memory allocation with mmap.\n   Copyright (C) 2012-2024 Free Software Foundation, Inc.\n   Written by Ian Lance Taylor, Google.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n    (1) Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n\n    (2) Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in\n    the documentation and/or other materials provided with the\n    distribution.\n\n    (3) The name of the author may not be used to\n    endorse or promote products derived from this software without\n    specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\nIMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,\nINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\nHOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\nIN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGE.  */\n\n#include \"config.h\"\n\n#include <errno.h>\n#include <string.h>\n#include <stdlib.h>\n#include <unistd.h>\n#include <sys/types.h>\n#include <sys/mman.h>\n\n#include \"backtrace.h\"\n#include \"internal.h\"\n\n#ifndef HAVE_DECL_GETPAGESIZE\nextern int getpagesize (void);\n#endif\n\n/* Memory allocation on systems that provide anonymous mmap.  This\n   permits the backtrace functions to be invoked from a signal\n   handler, assuming that mmap is async-signal safe.  */\n\n#ifndef MAP_ANONYMOUS\n#define MAP_ANONYMOUS MAP_ANON\n#endif\n\n#ifndef MAP_FAILED\n#define MAP_FAILED ((void *)-1)\n#endif\n\n/* A list of free memory blocks.  */\n\nstruct backtrace_freelist_struct\n{\n  /* Next on list.  */\n  struct backtrace_freelist_struct *next;\n  /* Size of this block, including this structure.  */\n  size_t size;\n};\n\n/* Free memory allocated by backtrace_alloc.  */\n\nstatic void\nbacktrace_free_locked (struct backtrace_state *state, void *addr, size_t size)\n{\n  /* Just leak small blocks.  We don't have to be perfect.  Don't put\n     more than 16 entries on the free list, to avoid wasting time\n     searching when allocating a block.  If we have more than 16\n     entries, leak the smallest entry.  */\n\n  if (size >= sizeof (struct backtrace_freelist_struct))\n    {\n      size_t c;\n      struct backtrace_freelist_struct **ppsmall;\n      struct backtrace_freelist_struct **pp;\n      struct backtrace_freelist_struct *p;\n\n      c = 0;\n      ppsmall = NULL;\n      for (pp = &state->freelist; *pp != NULL; pp = &(*pp)->next)\n\t{\n\t  if (ppsmall == NULL || (*pp)->size < (*ppsmall)->size)\n\t    ppsmall = pp;\n\t  ++c;\n\t}\n      if (c >= 16)\n\t{\n\t  if (size <= (*ppsmall)->size)\n\t    return;\n\t  *ppsmall = (*ppsmall)->next;\n\t}\n\n      p = (struct backtrace_freelist_struct *) addr;\n      p->next = state->freelist;\n      p->size = size;\n      state->freelist = p;\n    }\n}\n\n/* Allocate memory like malloc.  If ERROR_CALLBACK is NULL, don't\n   report an error.  */\n\nvoid *\nbacktrace_alloc (struct backtrace_state *state,\n\t\t size_t size, backtrace_error_callback error_callback,\n\t\t void *data)\n{\n  void *ret;\n  int locked;\n  struct backtrace_freelist_struct **pp;\n  size_t pagesize;\n  size_t asksize;\n  void *page;\n\n  ret = NULL;\n\n  /* If we can acquire the lock, then see if there is space on the\n     free list.  If we can't acquire the lock, drop straight into\n     using mmap.  __sync_lock_test_and_set returns the old state of\n     the lock, so we have acquired it if it returns 0.  */\n\n  if (!state->threaded)\n    locked = 1;\n  else\n    locked = __sync_lock_test_and_set (&state->lock_alloc, 1) == 0;\n\n  if (locked)\n    {\n      for (pp = &state->freelist; *pp != NULL; pp = &(*pp)->next)\n\t{\n\t  if ((*pp)->size >= size)\n\t    {\n\t      struct backtrace_freelist_struct *p;\n\n\t      p = *pp;\n\t      *pp = p->next;\n\n\t      /* Round for alignment; we assume that no type we care about\n\t\t is more than 8 bytes.  */\n\t      size = (size + 7) & ~ (size_t) 7;\n\t      if (size < p->size)\n\t\tbacktrace_free_locked (state, (char *) p + size,\n\t\t\t\t       p->size - size);\n\n\t      ret = (void *) p;\n\n\t      break;\n\t    }\n\t}\n\n      if (state->threaded)\n\t__sync_lock_release (&state->lock_alloc);\n    }\n\n  if (ret == NULL)\n    {\n      /* Allocate a new page.  */\n\n      pagesize = getpagesize ();\n      asksize = (size + pagesize - 1) & ~ (pagesize - 1);\n      page = mmap (NULL, asksize, PROT_READ | PROT_WRITE,\n\t\t   MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);\n      if (page == MAP_FAILED)\n\t{\n\t  if (error_callback)\n\t    error_callback (data, \"mmap\", errno);\n\t}\n      else\n\t{\n\t  size = (size + 7) & ~ (size_t) 7;\n\t  if (size < asksize)\n\t    backtrace_free (state, (char *) page + size, asksize - size,\n\t\t\t    error_callback, data);\n\n\t  ret = page;\n\t}\n    }\n\n  return ret;\n}\n\n/* Free memory allocated by backtrace_alloc.  */\n\nvoid\nbacktrace_free (struct backtrace_state *state, void *addr, size_t size,\n\t\tbacktrace_error_callback error_callback ATTRIBUTE_UNUSED,\n\t\tvoid *data ATTRIBUTE_UNUSED)\n{\n  int locked;\n\n  /* If we are freeing a large aligned block, just release it back to\n     the system.  This case arises when growing a vector for a large\n     binary with lots of debug info.  Calling munmap here may cause us\n     to call mmap again if there is also a large shared library; we\n     just live with that.  */\n  if (size >= 16 * 4096)\n    {\n      size_t pagesize;\n\n      pagesize = getpagesize ();\n      if (((uintptr_t) addr & (pagesize - 1)) == 0\n\t  && (size & (pagesize - 1)) == 0)\n\t{\n\t  /* If munmap fails for some reason, just add the block to\n\t     the freelist.  */\n\t  if (munmap (addr, size) == 0)\n\t    return;\n\t}\n    }\n\n  /* If we can acquire the lock, add the new space to the free list.\n     If we can't acquire the lock, just leak the memory.\n     __sync_lock_test_and_set returns the old state of the lock, so we\n     have acquired it if it returns 0.  */\n\n  if (!state->threaded)\n    locked = 1;\n  else\n    locked = __sync_lock_test_and_set (&state->lock_alloc, 1) == 0;\n\n  if (locked)\n    {\n      backtrace_free_locked (state, addr, size);\n\n      if (state->threaded)\n\t__sync_lock_release (&state->lock_alloc);\n    }\n}\n\n/* Grow VEC by SIZE bytes.  */\n\nvoid *\nbacktrace_vector_grow (struct backtrace_state *state,size_t size,\n\t\t       backtrace_error_callback error_callback,\n\t\t       void *data, struct backtrace_vector *vec)\n{\n  void *ret;\n\n  if (size > vec->alc)\n    {\n      size_t pagesize;\n      size_t alc;\n      void *base;\n\n      pagesize = getpagesize ();\n      alc = vec->size + size;\n      if (vec->size == 0)\n\talc = 16 * size;\n      else if (alc < pagesize)\n\t{\n\t  alc *= 2;\n\t  if (alc > pagesize)\n\t    alc = pagesize;\n\t}\n      else\n\t{\n\t  alc *= 2;\n\t  alc = (alc + pagesize - 1) & ~ (pagesize - 1);\n\t}\n      base = backtrace_alloc (state, alc, error_callback, data);\n      if (base == NULL)\n\treturn NULL;\n      if (vec->base != NULL)\n\t{\n\t  memcpy (base, vec->base, vec->size);\n\t  backtrace_free (state, vec->base, vec->size + vec->alc,\n\t\t\t  error_callback, data);\n\t}\n      vec->base = base;\n      vec->alc = alc - vec->size;\n    }\n\n  ret = (char *) vec->base + vec->size;\n  vec->size += size;\n  vec->alc -= size;\n  return ret;\n}\n\n/* Finish the current allocation on VEC.  */\n\nvoid *\nbacktrace_vector_finish (\n  struct backtrace_state *state ATTRIBUTE_UNUSED,\n  struct backtrace_vector *vec,\n  backtrace_error_callback error_callback ATTRIBUTE_UNUSED,\n  void *data ATTRIBUTE_UNUSED)\n{\n  void *ret;\n\n  ret = vec->base;\n  vec->base = (char *) vec->base + vec->size;\n  vec->size = 0;\n  return ret;\n}\n\n/* Release any extra space allocated for VEC.  */\n\nint\nbacktrace_vector_release (struct backtrace_state *state,\n\t\t\t  struct backtrace_vector *vec,\n\t\t\t  backtrace_error_callback error_callback,\n\t\t\t  void *data)\n{\n  size_t size;\n  size_t alc;\n  size_t aligned;\n\n  /* Make sure that the block that we free is aligned on an 8-byte\n     boundary.  */\n  size = vec->size;\n  alc = vec->alc;\n  aligned = (size + 7) & ~ (size_t) 7;\n  alc -= aligned - size;\n\n  backtrace_free (state, (char *) vec->base + aligned, alc,\n\t\t  error_callback, data);\n  vec->alc = 0;\n  if (vec->size == 0)\n    vec->base = NULL;\n  return 1;\n}\n"
  },
  {
    "path": "src/vendor/libbacktrace/mmapio.c",
    "content": "/* mmapio.c -- File views using mmap.\n   Copyright (C) 2012-2024 Free Software Foundation, Inc.\n   Written by Ian Lance Taylor, Google.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n    (1) Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n\n    (2) Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in\n    the documentation and/or other materials provided with the\n    distribution.\n\n    (3) The name of the author may not be used to\n    endorse or promote products derived from this software without\n    specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\nIMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,\nINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\nHOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\nIN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGE.  */\n\n#include \"config.h\"\n\n#include <errno.h>\n#include <sys/types.h>\n#include <sys/mman.h>\n#include <unistd.h>\n\n#include \"backtrace.h\"\n#include \"internal.h\"\n\n#ifndef HAVE_DECL_GETPAGESIZE\nextern int getpagesize (void);\n#endif\n\n#ifndef MAP_FAILED\n#define MAP_FAILED ((void *)-1)\n#endif\n\n/* This file implements file views and memory allocation when mmap is\n   available.  */\n\n/* Create a view of SIZE bytes from DESCRIPTOR at OFFSET.  */\n\nint\nbacktrace_get_view (struct backtrace_state *state ATTRIBUTE_UNUSED,\n\t\t    int descriptor, off_t offset, uint64_t size,\n\t\t    backtrace_error_callback error_callback,\n\t\t    void *data, struct backtrace_view *view)\n{\n  size_t pagesize;\n  unsigned int inpage;\n  off_t pageoff;\n  void *map;\n\n  if ((uint64_t) (size_t) size != size)\n    {\n      error_callback (data, \"file size too large\", 0);\n      return 0;\n    }\n\n  pagesize = getpagesize ();\n  inpage = offset % pagesize;\n  pageoff = offset - inpage;\n\n  size += inpage;\n  size = (size + (pagesize - 1)) & ~ (pagesize - 1);\n\n  map = mmap (NULL, size, PROT_READ, MAP_PRIVATE, descriptor, pageoff);\n  if (map == MAP_FAILED)\n    {\n      error_callback (data, \"mmap\", errno);\n      return 0;\n    }\n\n  view->data = (char *) map + inpage;\n  view->base = map;\n  view->len = size;\n\n  return 1;\n}\n\n/* Release a view read by backtrace_get_view.  */\n\nvoid\nbacktrace_release_view (struct backtrace_state *state ATTRIBUTE_UNUSED,\n\t\t\tstruct backtrace_view *view,\n\t\t\tbacktrace_error_callback error_callback,\n\t\t\tvoid *data)\n{\n  union {\n    const void *cv;\n    void *v;\n  } const_cast;\n\n  const_cast.cv = view->base;\n  if (munmap (const_cast.v, view->len) < 0)\n    error_callback (data, \"munmap\", errno);\n}\n"
  },
  {
    "path": "src/vendor/libbacktrace/move-if-change",
    "content": "#!/bin/sh\n# Like mv $1 $2, but if the files are the same, just delete $1.\n# Status is zero if successful, nonzero otherwise.\n\nVERSION='2012-01-06 07:23'; # UTC\n# The definition above must lie within the first 8 lines in order\n# for the Emacs time-stamp write hook (at end) to update it.\n# If you change this file with Emacs, please let the write hook\n# do its job.  Otherwise, update this string manually.\n\n# Copyright (C) 2002-2014 Free Software Foundation, Inc.\n\n# This program is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n\n# You should have received a copy of the GNU General Public License\n# along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\nusage=\"usage: $0 SOURCE DEST\"\n\nhelp=\"$usage\n  or:  $0 OPTION\nIf SOURCE is different than DEST, then move it to DEST; else remove SOURCE.\n\n  --help     display this help and exit\n  --version  output version information and exit\n\nThe variable CMPPROG can be used to specify an alternative to 'cmp'.\n\nReport bugs to <bug-gnulib@gnu.org>.\"\n\nversion=`expr \"$VERSION\" : '\\([^ ]*\\)'`\nversion=\"move-if-change (gnulib) $version\nCopyright (C) 2011 Free Software Foundation, Inc.\nLicense GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\nThis is free software: you are free to change and redistribute it.\nThere is NO WARRANTY, to the extent permitted by law.\"\n\ncmpprog=${CMPPROG-cmp}\n\nfor arg\ndo\n  case $arg in\n    --help | --hel | --he | --h)\n      exec echo \"$help\" ;;\n    --version | --versio | --versi | --vers | --ver | --ve | --v)\n      exec echo \"$version\" ;;\n    --)\n      shift\n      break ;;\n    -*)\n      echo \"$0: invalid option: $arg\" >&2\n      exit 1 ;;\n    *)\n      break ;;\n  esac\ndone\n\ntest $# -eq 2 || { echo \"$0: $usage\" >&2; exit 1; }\n\nif test -r \"$2\" && $cmpprog -- \"$1\" \"$2\" >/dev/null; then\n  rm -f -- \"$1\"\nelse\n  if mv -f -- \"$1\" \"$2\"; then :; else\n    # Ignore failure due to a concurrent move-if-change.\n    test -r \"$2\" && $cmpprog -- \"$1\" \"$2\" >/dev/null && rm -f -- \"$1\"\n  fi\nfi\n\n## Local Variables:\n## eval: (add-hook 'write-file-hooks 'time-stamp)\n## time-stamp-start: \"VERSION='\"\n## time-stamp-format: \"%:y-%02m-%02d %02H:%02M\"\n## time-stamp-time-zone: \"UTC\"\n## time-stamp-end: \"'; # UTC\"\n## End:\n"
  },
  {
    "path": "src/vendor/libbacktrace/mtest.c",
    "content": "/* mtest.c -- Minidebug test for libbacktrace library\n   Copyright (C) 2020-2024 Free Software Foundation, Inc.\n   Written by Ian Lance Taylor, Google.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n    (1) Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n\n    (2) Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in\n    the documentation and/or other materials provided with the\n    distribution.\n\n    (3) The name of the author may not be used to\n    endorse or promote products derived from this software without\n    specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\nIMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,\nINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\nHOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\nIN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGE.  */\n\n/* This program tests using libbacktrace with a program that uses the\n   minidebuginfo format in a .gnu_debugdata section.  See\n   https://sourceware.org/gdb/current/onlinedocs/gdb/MiniDebugInfo.html\n   for a bit more information about minidebuginfo.  What is relevant\n   for libbacktrace is that we have just a symbol table, with no debug\n   info, so we should be able to do a function backtrace, but we can't\n   do a file/line backtrace.  */\n\n#include <assert.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"backtrace.h\"\n#include \"backtrace-supported.h\"\n\n#include \"testlib.h\"\n\nstatic int test1 (void) __attribute__ ((noinline, noclone, optnone, unused));\nstatic int f2 (int) __attribute__ ((noinline, noclone));\nstatic int f3 (int, int) __attribute__ ((noinline, noclone));\n\n/* Collected PC values.  */\n\nstatic uintptr_t addrs[20];\n\n/* The backtrace callback function.  This is like callback_one in\n   testlib.c, but it saves the PC also.  */\n\nstatic int\ncallback_mtest (void *vdata, uintptr_t pc, const char *filename, int lineno,\n\t\tconst char *function)\n{\n  struct bdata *data = (struct bdata *) vdata;\n\n  if (data->index >= sizeof addrs / sizeof addrs[0])\n    {\n      fprintf (stderr, \"callback_mtest: callback called too many times\\n\");\n      data->failed = 1;\n      return 1;\n    }\n\n  addrs[data->index] = pc;\n\n  return callback_one (vdata, pc, filename, lineno, function);\n}\n\n/* Test the backtrace function with non-inlined functions.  (We don't\n   test with inlined functions because they won't work with minidebug\n   anyhow.)  */\n\nstatic int\ntest1 (void)\n{\n  /* Returning a value here and elsewhere avoids a tailcall which\n     would mess up the backtrace.  */\n  return f2 (__LINE__) + 1;\n}\n\nstatic int\nf2 (int f1line)\n{\n  return f3 (f1line, __LINE__) + 2;\n}\n\nstatic int\nf3 (int f1line __attribute__ ((unused)), int f2line __attribute__ ((unused)))\n{\n  struct info all[20];\n  struct bdata data;\n  int i;\n  size_t j;\n\n  data.all = &all[0];\n  data.index = 0;\n  data.max = 20;\n  data.failed = 0;\n\n  i = backtrace_full (state, 0, callback_mtest, error_callback_one, &data);\n\n  if (i != 0)\n    {\n      fprintf (stderr, \"test1: unexpected return value %d\\n\", i);\n      data.failed = 1;\n    }\n\n  if (data.index < 3)\n    {\n      fprintf (stderr,\n\t       \"test1: not enough frames; got %zu, expected at least 3\\n\",\n\t       data.index);\n      data.failed = 1;\n    }\n\n  /* When using minidebug we don't expect the function name here.  */\n\n  for (j = 0; j < 3 && j < data.index; j++)\n    {\n      if (all[j].function == NULL)\n\t{\n\t  struct symdata symdata;\n\n\t  symdata.name = NULL;\n\t  symdata.val = 0;\n\t  symdata.size = 0;\n\t  symdata.failed = 0;\n\n\t  i = backtrace_syminfo (state, addrs[j], callback_three,\n\t\t\t\t error_callback_three, &symdata);\n\t  if (i == 0)\n\t    {\n\t      fprintf (stderr,\n\t\t       (\"test1: [%zu], unexpected return value from \"\n\t\t\t\"backtrace_syminfo %d\\n\"),\n\t\t       j, i);\n\t      data.failed = 1;\n\t    }\n\t  else if (symdata.name == NULL)\n\t    {\n\t      fprintf (stderr, \"test1: [%zu]: syminfo did not find name\\n\", j);\n\t      data.failed = 1;\n\t    }\n\t  else\n\t    all[j].function = strdup (symdata.name);\n\t}\n    }\n\n  if (data.index > 0)\n    {\n      if (all[0].function == NULL)\n\t{\n\t  fprintf (stderr, \"test1: [0]: missing function name\\n\");\n\t  data.failed = 1;\n\t}\n      else if (strcmp (all[0].function, \"f3\") != 0)\n\t{\n\t  fprintf (stderr, \"test1: [0]: got %s expected %s\\n\",\n\t\t   all[0].function, \"f3\");\n\t  data.failed = 1;\n\t}\n    }\n\n  if (data.index > 1)\n    {\n      if (all[1].function == NULL)\n\t{\n\t  fprintf (stderr, \"test1: [1]: missing function name\\n\");\n\t  data.failed = 1;\n\t}\n      else if (strcmp (all[1].function, \"f2\") != 0)\n\t{\n\t  fprintf (stderr, \"test1: [1]: got %s expected %s\\n\",\n\t\t   all[0].function, \"f2\");\n\t  data.failed = 1;\n\t}\n    }\n\n  if (data.index > 2)\n    {\n      if (all[2].function == NULL)\n\t{\n\t  fprintf (stderr, \"test1: [2]: missing function name\\n\");\n\t  data.failed = 1;\n\t}\n      else if (strcmp (all[2].function, \"test1\") != 0)\n\t{\n\t  fprintf (stderr, \"test1: [2]: got %s expected %s\\n\",\n\t\t   all[0].function, \"test1\");\n\t  data.failed = 1;\n\t}\n    }\n\n  printf (\"%s: backtrace_full noinline\\n\", data.failed ? \"FAIL\" : \"PASS\");\n\n  if (data.failed)\n    ++failures;\n\n  return failures;\n}\n\n/* Test the backtrace_simple function with non-inlined functions.  */\n\nstatic int test3 (void) __attribute__ ((noinline, noclone, optnone, unused));\nstatic int f22 (int) __attribute__ ((noinline, noclone));\nstatic int f23 (int, int) __attribute__ ((noinline, noclone));\n\nstatic int\ntest3 (void)\n{\n  return f22 (__LINE__) + 1;\n}\n\nstatic int\nf22 (int f1line)\n{\n  return f23 (f1line, __LINE__) + 2;\n}\n\nstatic int\nf23 (int f1line __attribute__ ((unused)), int f2line __attribute__ ((unused)))\n{\n  uintptr_t addrs[20];\n  struct sdata data;\n  int i;\n\n  data.addrs = &addrs[0];\n  data.index = 0;\n  data.max = 20;\n  data.failed = 0;\n\n  i = backtrace_simple (state, 0, callback_two, error_callback_two, &data);\n\n  if (i != 0)\n    {\n      fprintf (stderr, \"test3: unexpected return value %d\\n\", i);\n      data.failed = 1;\n    }\n\n  if (!data.failed)\n    {\n      int j;\n\n      for (j = 0; j < 3; ++j)\n\t{\n\t  struct symdata symdata;\n\n\t  symdata.name = NULL;\n\t  symdata.val = 0;\n\t  symdata.size = 0;\n\t  symdata.failed = 0;\n\n\t  i = backtrace_syminfo (state, addrs[j], callback_three,\n\t\t\t\t error_callback_three, &symdata);\n\t  if (i == 0)\n\t    {\n\t      fprintf (stderr,\n\t\t       (\"test3: [%d]: unexpected return value \"\n\t\t\t\"from backtrace_syminfo %d\\n\"),\n\t\t       j, i);\n\t      symdata.failed = 1;\n\t    }\n\n\t  if (!symdata.failed)\n\t    {\n\t      const char *expected;\n\n\t      switch (j)\n\t\t{\n\t\tcase 0:\n\t\t  expected = \"f23\";\n\t\t  break;\n\t\tcase 1:\n\t\t  expected = \"f22\";\n\t\t  break;\n\t\tcase 2:\n\t\t  expected = \"test3\";\n\t\t  break;\n\t\tdefault:\n\t\t  assert (0);\n\t\t}\n\n\t      if (symdata.name == NULL)\n\t\t{\n\t\t  fprintf (stderr, \"test3: [%d]: NULL syminfo name\\n\", j);\n\t\t  symdata.failed = 1;\n\t\t}\n\t      /* Use strncmp, not strcmp, because GCC might create a\n\t\t clone.  */\n\t      else if (strncmp (symdata.name, expected, strlen (expected))\n\t\t       != 0)\n\t\t{\n\t\t  fprintf (stderr,\n\t\t\t   (\"test3: [%d]: unexpected syminfo name \"\n\t\t\t    \"got %s expected %s\\n\"),\n\t\t\t   j, symdata.name, expected);\n\t\t  symdata.failed = 1;\n\t\t}\n\t    }\n\n\t  if (symdata.failed)\n\t    data.failed = 1;\n\t}\n    }\n\n  printf (\"%s: backtrace_simple noinline\\n\", data.failed ? \"FAIL\" : \"PASS\");\n\n  if (data.failed)\n    ++failures;\n\n  return failures;\n}\n\nint test5 (void) __attribute__ ((unused));\n\nint global = 1;\n\nint\ntest5 (void)\n{\n  struct symdata symdata;\n  int i;\n  uintptr_t addr = (uintptr_t) &global;\n\n  if (sizeof (global) > 1)\n    addr += 1;\n\n  symdata.name = NULL;\n  symdata.val = 0;\n  symdata.size = 0;\n  symdata.failed = 0;\n\n  i = backtrace_syminfo (state, addr, callback_three,\n\t\t\t error_callback_three, &symdata);\n  if (i == 0)\n    {\n      fprintf (stderr,\n\t       \"test5: unexpected return value from backtrace_syminfo %d\\n\",\n\t       i);\n      symdata.failed = 1;\n    }\n\n  if (!symdata.failed)\n    {\n      if (symdata.name == NULL)\n\t{\n\t  fprintf (stderr, \"test5: NULL syminfo name\\n\");\n\t  symdata.failed = 1;\n\t}\n      else if (!(strncmp (symdata.name, \"global\", 6) == 0\n\t\t && (symdata.name[6] == '\\0'|| symdata.name[6] == '.')))\n\t{\n\t  fprintf (stderr,\n\t\t   \"test5: unexpected syminfo name got %s expected %s\\n\",\n\t\t   symdata.name, \"global\");\n\t  symdata.failed = 1;\n\t}\n      else if (symdata.val != (uintptr_t) &global)\n\t{\n\t  fprintf (stderr,\n\t\t   \"test5: unexpected syminfo value got %lx expected %lx\\n\",\n\t\t   (unsigned long) symdata.val,\n\t\t   (unsigned long) (uintptr_t) &global);\n\t  symdata.failed = 1;\n\t}\n      else if (symdata.size != sizeof (global) && symdata.size != 0)\n\t{\n\t  fprintf (stderr,\n\t\t   \"test5: unexpected syminfo size got %lx expected %lx\\n\",\n\t\t   (unsigned long) symdata.size,\n\t\t   (unsigned long) sizeof (global));\n\t  symdata.failed = 1;\n\t}\n    }\n\n  printf (\"%s: backtrace_syminfo variable\\n\",\n\t  symdata.failed ? \"FAIL\" : \"PASS\");\n\n  if (symdata.failed)\n    ++failures;\n\n  return failures;\n}\n\nint\nmain (int argc ATTRIBUTE_UNUSED, char **argv)\n{\n  state = backtrace_create_state (argv[0], BACKTRACE_SUPPORTS_THREADS,\n\t\t\t\t  error_callback_create, NULL);\n\n#if BACKTRACE_SUPPORTED\n  test1 ();\n  test3 ();\n#if BACKTRACE_SUPPORTS_DATA\n  test5 ();\n#endif\n#endif\n\n  exit (failures ? EXIT_FAILURE : EXIT_SUCCESS);\n}\n"
  },
  {
    "path": "src/vendor/libbacktrace/nounwind.c",
    "content": "/* backtrace.c -- Entry point for stack backtrace library.\n   Copyright (C) 2012-2024 Free Software Foundation, Inc.\n   Written by Ian Lance Taylor, Google.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n    (1) Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n\n    (2) Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in\n    the documentation and/or other materials provided with the\n    distribution.\n\n    (3) The name of the author may not be used to\n    endorse or promote products derived from this software without\n    specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\nIMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,\nINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\nHOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\nIN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGE.  */\n\n#include \"config.h\"\n\n#include <sys/types.h>\n\n#include \"backtrace.h\"\n\n#include \"internal.h\"\n\n/* This source file is compiled if the unwind library is not\n   available.  */\n\nint\nbacktrace_full (struct backtrace_state *state ATTRIBUTE_UNUSED,\n\t\tint skip ATTRIBUTE_UNUSED,\n\t\tbacktrace_full_callback callback ATTRIBUTE_UNUSED,\n\t\tbacktrace_error_callback error_callback, void *data)\n{\n  error_callback (data,\n\t\t  \"no stack trace because unwind library not available\",\n\t\t  0);\n  return 0;\n}\n\nint\nbacktrace_simple (struct backtrace_state *state ATTRIBUTE_UNUSED,\n\t\t  int skip ATTRIBUTE_UNUSED,\n\t\t  backtrace_simple_callback callback ATTRIBUTE_UNUSED,\n\t\t  backtrace_error_callback error_callback, void *data)\n{\n  error_callback (data,\n\t\t  \"no stack trace because unwind library not available\",\n\t\t  0);\n  return 0;\n}\n"
  },
  {
    "path": "src/vendor/libbacktrace/pecoff.c",
    "content": "/* pecoff.c -- Get debug data from a PE/COFFF file for backtraces.\n   Copyright (C) 2015-2024 Free Software Foundation, Inc.\n   Adapted from elf.c by Tristan Gingold, AdaCore.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n    (1) Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n\n    (2) Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in\n    the documentation and/or other materials provided with the\n    distribution.\n\n    (3) The name of the author may not be used to\n    endorse or promote products derived from this software without\n    specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\nIMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,\nINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\nHOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\nIN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGE.  */\n\n#include \"config.h\"\n\n#include <stdlib.h>\n#include <string.h>\n#include <sys/types.h>\n\n#include \"backtrace.h\"\n#include \"internal.h\"\n\n#ifdef HAVE_WINDOWS_H\n#ifndef WIN32_MEAN_AND_LEAN\n#define WIN32_MEAN_AND_LEAN\n#endif\n\n#ifndef NOMINMAX\n#define NOMINMAX\n#endif\n\n#include <windows.h>\n\n#ifdef HAVE_TLHELP32_H\n#include <tlhelp32.h>\n\n#ifdef UNICODE\n/* If UNICODE is defined, all the symbols are replaced by a macro to use the\n   wide variant. But we need the ansi variant, so undef the macros. */\n#undef MODULEENTRY32\n#undef Module32First\n#undef Module32Next\n#endif\n#endif\n\n#if defined(_ARM_)\n#define NTAPI\n#else\n#define NTAPI __stdcall\n#endif\n\n/* This is a simplified (but binary compatible) version of what Microsoft\n   defines in their documentation. */\nstruct dll_notification_data\n{\n  ULONG reserved;\n  /* The name as UNICODE_STRING struct. */\n  PVOID full_dll_name;\n  PVOID base_dll_name;\n  PVOID dll_base;\n  ULONG size_of_image;\n};\n\n#define LDR_DLL_NOTIFICATION_REASON_LOADED 1\n\ntypedef LONG NTSTATUS;\ntypedef VOID CALLBACK (*LDR_DLL_NOTIFICATION)(ULONG,\n\t\t\t\t\t      struct dll_notification_data*,\n\t\t\t\t\t      PVOID);\ntypedef NTSTATUS NTAPI (*LDR_REGISTER_FUNCTION)(ULONG,\n\t\t\t\t\t\tLDR_DLL_NOTIFICATION, PVOID,\n\t\t\t\t\t\tPVOID*);\n#endif\n\n/* Coff file header.  */\n\ntypedef struct {\n  uint16_t machine;\n  uint16_t number_of_sections;\n  uint32_t time_date_stamp;\n  uint32_t pointer_to_symbol_table;\n  uint32_t number_of_symbols;\n  uint16_t size_of_optional_header;\n  uint16_t characteristics;\n} b_coff_file_header;\n\n/* Coff optional header.  */\n\ntypedef struct {\n  uint16_t magic;\n  uint8_t  major_linker_version;\n  uint8_t  minor_linker_version;\n  uint32_t size_of_code;\n  uint32_t size_of_initialized_data;\n  uint32_t size_of_uninitialized_data;\n  uint32_t address_of_entry_point;\n  uint32_t base_of_code;\n  union {\n    struct {\n      uint32_t base_of_data;\n      uint32_t image_base;\n    } pe;\n    struct {\n      uint64_t image_base;\n    } pep;\n  } u;\n} b_coff_optional_header;\n\n/* Values of magic in optional header.  */\n\n#define PE_MAGIC 0x10b\t\t/* PE32 executable.  */\n#define PEP_MAGIC 0x20b\t\t/* PE32+ executable (for 64bit targets).  */\n\n/* Coff section header.  */\n\ntypedef struct {\n  char name[8];\n  uint32_t virtual_size;\n  uint32_t virtual_address;\n  uint32_t size_of_raw_data;\n  uint32_t pointer_to_raw_data;\n  uint32_t pointer_to_relocations;\n  uint32_t pointer_to_line_numbers;\n  uint16_t number_of_relocations;\n  uint16_t number_of_line_numbers;\n  uint32_t characteristics;\n} b_coff_section_header;\n\n/* Coff symbol name.  */\n\ntypedef union {\n  char short_name[8];\n  struct {\n    unsigned char zeroes[4];\n    unsigned char off[4];\n  } long_name;\n} b_coff_name;\n\n/* Coff symbol (external representation which is unaligned).  */\n\ntypedef struct {\n  b_coff_name name;\n  unsigned char value[4];\n  unsigned char section_number[2];\n  unsigned char type[2];\n  unsigned char storage_class;\n  unsigned char number_of_aux_symbols;\n} b_coff_external_symbol;\n\n/* Symbol types.  */\n\n#define N_TBSHFT 4\t\t\t/* Shift for the derived type.  */\n#define IMAGE_SYM_DTYPE_FUNCTION 2\t/* Function derived type.  */\n\n/* Size of a coff symbol.  */\n\n#define SYM_SZ 18\n\n/* Coff symbol, internal representation (aligned).  */\n\ntypedef struct {\n  const char *name;\n  uint32_t value;\n  int16_t sec;\n  uint16_t type;\n  uint16_t sc;\n} b_coff_internal_symbol;\n\n/* Names of sections, indexed by enum dwarf_section in internal.h.  */\n\nstatic const char * const debug_section_names[DEBUG_MAX] =\n{\n  \".debug_info\",\n  \".debug_line\",\n  \".debug_abbrev\",\n  \".debug_ranges\",\n  \".debug_str\",\n  \".debug_addr\",\n  \".debug_str_offsets\",\n  \".debug_line_str\",\n  \".debug_rnglists\"\n};\n\n/* Information we gather for the sections we care about.  */\n\nstruct debug_section_info\n{\n  /* Section file offset.  */\n  off_t offset;\n  /* Section size.  */\n  size_t size;\n};\n\n/* Information we keep for an coff symbol.  */\n\nstruct coff_symbol\n{\n  /* The name of the symbol.  */\n  const char *name;\n  /* The address of the symbol.  */\n  uintptr_t address;\n};\n\n/* Information to pass to coff_syminfo.  */\n\nstruct coff_syminfo_data\n{\n  /* Symbols for the next module.  */\n  struct coff_syminfo_data *next;\n  /* The COFF symbols, sorted by address.  */\n  struct coff_symbol *symbols;\n  /* The number of symbols.  */\n  size_t count;\n};\n\n/* A dummy callback function used when we can't find any debug info.  */\n\nstatic int\ncoff_nodebug (struct backtrace_state *state ATTRIBUTE_UNUSED,\n\t      uintptr_t pc ATTRIBUTE_UNUSED,\n\t      backtrace_full_callback callback ATTRIBUTE_UNUSED,\n\t      backtrace_error_callback error_callback, void *data)\n{\n  error_callback (data, \"no debug info in PE/COFF executable (make sure to compile with -g)\", -1);\n  return 0;\n}\n\n/* A dummy callback function used when we can't find a symbol\n   table.  */\n\nstatic void\ncoff_nosyms (struct backtrace_state *state ATTRIBUTE_UNUSED,\n\t     uintptr_t addr ATTRIBUTE_UNUSED,\n\t     backtrace_syminfo_callback callback ATTRIBUTE_UNUSED,\n\t     backtrace_error_callback error_callback, void *data)\n{\n  error_callback (data, \"no symbol table in PE/COFF executable\", -1);\n}\n\n/* Read a potentially unaligned 4 byte word at P, using native endianness.  */\n\nstatic uint32_t\ncoff_read4 (const unsigned char *p)\n{\n  uint32_t res;\n\n  memcpy (&res, p, 4);\n  return res;\n}\n\n/* Read a potentially unaligned 2 byte word at P, using native endianness.\n   All 2 byte word in symbols are always aligned, but for coherency all\n   fields are declared as char arrays.  */\n\nstatic uint16_t\ncoff_read2 (const unsigned char *p)\n{\n  uint16_t res;\n\n  memcpy (&res, p, sizeof (res));\n  return res;\n}\n\n/* Return the length (without the trailing 0) of a COFF short name.  */\n\nstatic size_t\ncoff_short_name_len (const char *name)\n{\n  int i;\n\n  for (i = 0; i < 8; i++)\n    if (name[i] == 0)\n      return i;\n  return 8;\n}\n\n/* Return true iff COFF short name CNAME is the same as NAME (a NUL-terminated\n   string).  */\n\nstatic int\ncoff_short_name_eq (const char *name, const char *cname)\n{\n  int i;\n\n  for (i = 0; i < 8; i++)\n    {\n      if (name[i] != cname[i])\n\treturn 0;\n      if (name[i] == 0)\n\treturn 1;\n    }\n  return name[8] == 0;\n}\n\n/* Return true iff NAME is the same as string at offset OFF.  */\n\nstatic int\ncoff_long_name_eq (const char *name, unsigned int off,\n\t\t   struct backtrace_view *str_view)\n{\n  if (off >= str_view->len)\n    return 0;\n  return strcmp (name, (const char *)str_view->data + off) == 0;\n}\n\n/* Compare struct coff_symbol for qsort.  */\n\nstatic int\ncoff_symbol_compare (const void *v1, const void *v2)\n{\n  const struct coff_symbol *e1 = (const struct coff_symbol *) v1;\n  const struct coff_symbol *e2 = (const struct coff_symbol *) v2;\n\n  if (e1->address < e2->address)\n    return -1;\n  else if (e1->address > e2->address)\n    return 1;\n  else\n    return 0;\n}\n\n/* Convert SYM to internal (and aligned) format ISYM, using string table\n   from STRTAB and STRTAB_SIZE, and number of sections SECTS_NUM.\n   Return -1 in case of error (invalid section number or string index).  */\n\nstatic int\ncoff_expand_symbol (b_coff_internal_symbol *isym,\n\t\t    const b_coff_external_symbol *sym,\n\t\t    uint16_t sects_num,\n\t\t    const unsigned char *strtab, size_t strtab_size)\n{\n  isym->type = coff_read2 (sym->type);\n  isym->sec = coff_read2 (sym->section_number);\n  isym->sc = sym->storage_class;\n\n  if (isym->sec > 0 && (uint16_t) isym->sec > sects_num)\n    return -1;\n  if (sym->name.short_name[0] != 0)\n    isym->name = sym->name.short_name;\n  else\n    {\n      uint32_t off = coff_read4 (sym->name.long_name.off);\n\n      if (off >= strtab_size)\n\treturn -1;\n      isym->name = (const char *) strtab + off;\n    }\n  return 0;\n}\n\n/* Return true iff SYM is a defined symbol for a function.  Data symbols\n   aren't considered because they aren't easily identified (same type as\n   section names, presence of symbols defined by the linker script).  */\n\nstatic int\ncoff_is_function_symbol (const b_coff_internal_symbol *isym)\n{\n  return (isym->type >> N_TBSHFT) == IMAGE_SYM_DTYPE_FUNCTION\n    && isym->sec > 0;\n}\n\n/* Initialize the symbol table info for coff_syminfo.  */\n\nstatic int\ncoff_initialize_syminfo (struct backtrace_state *state,\n\t\t\t struct libbacktrace_base_address base_address,\n\t\t\t int is_64, const b_coff_section_header *sects,\n\t\t\t size_t sects_num, const b_coff_external_symbol *syms,\n\t\t\t size_t syms_size, const unsigned char *strtab,\n\t\t\t size_t strtab_size,\n\t\t\t backtrace_error_callback error_callback,\n\t\t\t void *data, struct coff_syminfo_data *sdata)\n{\n  size_t syms_count;\n  char *coff_symstr;\n  size_t coff_symstr_len;\n  size_t coff_symbol_count;\n  size_t coff_symbol_size;\n  struct coff_symbol *coff_symbols;\n  struct coff_symbol *coff_sym;\n  char *coff_str;\n  size_t i;\n\n  syms_count = syms_size / SYM_SZ;\n\n  /* We only care about function symbols.  Count them.  Also count size of\n     strings for in-symbol names.  */\n  coff_symbol_count = 0;\n  coff_symstr_len = 0;\n  for (i = 0; i < syms_count; ++i)\n    {\n      const b_coff_external_symbol *asym = &syms[i];\n      b_coff_internal_symbol isym;\n\n      if (coff_expand_symbol (&isym, asym, sects_num, strtab, strtab_size) < 0)\n\t{\n\t  error_callback (data, \"invalid section or offset in coff symbol\", 0);\n\t  return 0;\n\t}\n      if (coff_is_function_symbol (&isym))\n\t{\n\t  ++coff_symbol_count;\n\t  if (asym->name.short_name[0] != 0)\n\t    coff_symstr_len += coff_short_name_len (asym->name.short_name) + 1;\n\t}\n\n      i += asym->number_of_aux_symbols;\n    }\n\n  coff_symbol_size = (coff_symbol_count + 1) * sizeof (struct coff_symbol);\n  coff_symbols = ((struct coff_symbol *)\n\t\t  backtrace_alloc (state, coff_symbol_size, error_callback,\n\t\t\t\t   data));\n  if (coff_symbols == NULL)\n    return 0;\n\n  /* Allocate memory for symbols strings.  */\n  if (coff_symstr_len > 0)\n    {\n      coff_symstr = ((char *)\n\t\t     backtrace_alloc (state, coff_symstr_len, error_callback,\n\t\t\t\t      data));\n      if (coff_symstr == NULL)\n\t{\n\t  backtrace_free (state, coff_symbols, coff_symbol_size,\n\t\t\t  error_callback, data);\n\t  return 0;\n\t}\n    }\n  else\n    coff_symstr = NULL;\n\n  /* Copy symbols.  */\n  coff_sym = coff_symbols;\n  coff_str = coff_symstr;\n  for (i = 0; i < syms_count; ++i)\n    {\n      const b_coff_external_symbol *asym = &syms[i];\n      b_coff_internal_symbol isym;\n\n      if (coff_expand_symbol (&isym, asym, sects_num, strtab, strtab_size))\n\t{\n\t  /* Should not fail, as it was already tested in the previous\n\t     loop.  */\n\t  abort ();\n\t}\n      if (coff_is_function_symbol (&isym))\n\t{\n\t  const char *name;\n\t  int16_t secnum;\n\n\t  if (asym->name.short_name[0] != 0)\n\t    {\n\t      size_t len = coff_short_name_len (isym.name);\n\t      name = coff_str;\n\t      memcpy (coff_str, isym.name, len);\n\t      coff_str[len] = 0;\n\t      coff_str += len + 1;\n\t    }\n\t  else\n\t    name = isym.name;\n\n\t  if (!is_64)\n\t    {\n\t      /* Strip leading '_'.  */\n\t      if (name[0] == '_')\n\t\tname++;\n\t    }\n\n\t  /* Symbol value is section relative, so we need to read the address\n\t     of its section.  */\n\t  secnum = coff_read2 (asym->section_number);\n\n\t  coff_sym->name = name;\n\t  coff_sym->address =\n\t    libbacktrace_add_base ((coff_read4 (asym->value)\n\t\t\t\t    + sects[secnum - 1].virtual_address),\n\t\t\t\t   base_address);\n\t  coff_sym++;\n\t}\n\n      i += asym->number_of_aux_symbols;\n    }\n\n  /* End of symbols marker.  */\n  coff_sym->name = NULL;\n  coff_sym->address = -1;\n\n  backtrace_qsort (coff_symbols, coff_symbol_count,\n\t\t   sizeof (struct coff_symbol), coff_symbol_compare);\n\n  sdata->next = NULL;\n  sdata->symbols = coff_symbols;\n  sdata->count = coff_symbol_count;\n\n  return 1;\n}\n\n/* Add EDATA to the list in STATE.  */\n\nstatic void\ncoff_add_syminfo_data (struct backtrace_state *state,\n\t\t       struct coff_syminfo_data *sdata)\n{\n  if (!state->threaded)\n    {\n      struct coff_syminfo_data **pp;\n\n      for (pp = (struct coff_syminfo_data **) (void *) &state->syminfo_data;\n\t   *pp != NULL;\n\t   pp = &(*pp)->next)\n\t;\n      *pp = sdata;\n    }\n  else\n    {\n      while (1)\n\t{\n\t  struct coff_syminfo_data **pp;\n\n\t  pp = (struct coff_syminfo_data **) (void *) &state->syminfo_data;\n\n\t  while (1)\n\t    {\n\t      struct coff_syminfo_data *p;\n\n\t      p = backtrace_atomic_load_pointer (pp);\n\n\t      if (p == NULL)\n\t\tbreak;\n\n\t      pp = &p->next;\n\t    }\n\n\t  if (__sync_bool_compare_and_swap (pp, NULL, sdata))\n\t    break;\n\t}\n    }\n}\n\n/* Compare an ADDR against an elf_symbol for bsearch.  We allocate one\n   extra entry in the array so that this can look safely at the next\n   entry.  */\n\nstatic int\ncoff_symbol_search (const void *vkey, const void *ventry)\n{\n  const uintptr_t *key = (const uintptr_t *) vkey;\n  const struct coff_symbol *entry = (const struct coff_symbol *) ventry;\n  uintptr_t addr;\n\n  addr = *key;\n  if (addr < entry->address)\n    return -1;\n  else if (addr >= entry[1].address)\n    return 1;\n  else\n    return 0;\n}\n\n/* Return the symbol name and value for an ADDR.  */\n\nstatic void\ncoff_syminfo (struct backtrace_state *state, uintptr_t addr,\n\t      backtrace_syminfo_callback callback,\n\t      backtrace_error_callback error_callback ATTRIBUTE_UNUSED,\n\t      void *data)\n{\n  struct coff_syminfo_data *sdata;\n  struct coff_symbol *sym = NULL;\n\n  if (!state->threaded)\n    {\n      for (sdata = (struct coff_syminfo_data *) state->syminfo_data;\n\t   sdata != NULL;\n\t   sdata = sdata->next)\n\t{\n\t  sym = ((struct coff_symbol *)\n\t\t bsearch (&addr, sdata->symbols, sdata->count,\n\t\t\t  sizeof (struct coff_symbol), coff_symbol_search));\n\t  if (sym != NULL)\n\t    break;\n\t}\n    }\n  else\n    {\n      struct coff_syminfo_data **pp;\n\n      pp = (struct coff_syminfo_data **) (void *) &state->syminfo_data;\n      while (1)\n\t{\n\t  sdata = backtrace_atomic_load_pointer (pp);\n\t  if (sdata == NULL)\n\t    break;\n\n\t  sym = ((struct coff_symbol *)\n\t\t bsearch (&addr, sdata->symbols, sdata->count,\n\t\t\t  sizeof (struct coff_symbol), coff_symbol_search));\n\t  if (sym != NULL)\n\t    break;\n\n\t  pp = &sdata->next;\n\t}\n    }\n\n  if (sym == NULL)\n    callback (data, addr, NULL, 0, 0);\n  else\n    callback (data, addr, sym->name, sym->address, 0);\n}\n\n/* Add the backtrace data for one PE/COFF file.  Returns 1 on success,\n   0 on failure (in both cases descriptor is closed).  */\n\nstatic int\ncoff_add (struct backtrace_state *state, int descriptor,\n\t  backtrace_error_callback error_callback, void *data,\n\t  fileline *fileline_fn, int *found_sym, int *found_dwarf,\n\t  uintptr_t module_handle ATTRIBUTE_UNUSED)\n{\n  struct backtrace_view fhdr_view;\n  off_t fhdr_off;\n  int magic_ok;\n  b_coff_file_header fhdr;\n  off_t opt_sects_off;\n  size_t opt_sects_size;\n  unsigned int sects_num;\n  struct backtrace_view sects_view;\n  int sects_view_valid;\n  const b_coff_optional_header *opt_hdr;\n  const b_coff_section_header *sects;\n  struct backtrace_view str_view;\n  int str_view_valid;\n  size_t str_size;\n  off_t str_off;\n  struct backtrace_view syms_view;\n  off_t syms_off;\n  size_t syms_size;\n  int syms_view_valid;\n  unsigned int syms_num;\n  unsigned int i;\n  struct debug_section_info sections[DEBUG_MAX];\n  off_t min_offset;\n  off_t max_offset;\n  struct backtrace_view debug_view;\n  int debug_view_valid;\n  int is_64;\n  struct libbacktrace_base_address image_base;\n  struct libbacktrace_base_address base_address;\n  struct dwarf_sections dwarf_sections;\n\n  *found_sym = 0;\n  *found_dwarf = 0;\n\n  sects_view_valid = 0;\n  syms_view_valid = 0;\n  str_view_valid = 0;\n  debug_view_valid = 0;\n\n  /* Map the MS-DOS stub (if any) and extract file header offset.  */\n  if (!backtrace_get_view (state, descriptor, 0, 0x40, error_callback,\n\t\t\t   data, &fhdr_view))\n    goto fail;\n\n  {\n    const unsigned char *vptr = fhdr_view.data;\n\n    if (vptr[0] == 'M' && vptr[1] == 'Z')\n      fhdr_off = coff_read4 (vptr + 0x3c);\n    else\n      fhdr_off = 0;\n  }\n\n  backtrace_release_view (state, &fhdr_view, error_callback, data);\n\n  /* Map the coff file header.  */\n  if (!backtrace_get_view (state, descriptor, fhdr_off,\n\t\t\t   sizeof (b_coff_file_header) + 4,\n\t\t\t   error_callback, data, &fhdr_view))\n    goto fail;\n\n  if (fhdr_off != 0)\n    {\n      const char *magic = (const char *) fhdr_view.data;\n      magic_ok = memcmp (magic, \"PE\\0\", 4) == 0;\n      fhdr_off += 4;\n\n      memcpy (&fhdr, fhdr_view.data + 4, sizeof fhdr);\n    }\n  else\n    {\n      memcpy (&fhdr, fhdr_view.data, sizeof fhdr);\n      /* TODO: test fhdr.machine for coff but non-PE platforms.  */\n      magic_ok = 0;\n    }\n  backtrace_release_view (state, &fhdr_view, error_callback, data);\n\n  if (!magic_ok)\n    {\n      error_callback (data, \"executable file is not COFF\", 0);\n      goto fail;\n    }\n\n  sects_num = fhdr.number_of_sections;\n  syms_num = fhdr.number_of_symbols;\n\n  opt_sects_off = fhdr_off + sizeof (fhdr);\n  opt_sects_size = (fhdr.size_of_optional_header\n\t\t    + sects_num * sizeof (b_coff_section_header));\n\n  /* To translate PC to file/line when using DWARF, we need to find\n     the .debug_info and .debug_line sections.  */\n\n  /* Read the optional header and the section headers.  */\n\n  if (!backtrace_get_view (state, descriptor, opt_sects_off, opt_sects_size,\n\t\t\t   error_callback, data, &sects_view))\n    goto fail;\n  sects_view_valid = 1;\n  opt_hdr = (const b_coff_optional_header *) sects_view.data;\n  sects = (const b_coff_section_header *)\n    (sects_view.data + fhdr.size_of_optional_header);\n\n  is_64 = 0;\n  memset (&image_base, 0, sizeof image_base);\n  if (fhdr.size_of_optional_header > sizeof (*opt_hdr))\n    {\n      if (opt_hdr->magic == PE_MAGIC)\n\timage_base.m = opt_hdr->u.pe.image_base;\n      else if (opt_hdr->magic == PEP_MAGIC)\n\t{\n\t  image_base.m = opt_hdr->u.pep.image_base;\n\t  is_64 = 1;\n\t}\n      else\n\t{\n\t  error_callback (data, \"bad magic in PE optional header\", 0);\n\t  goto fail;\n\t}\n    }\n\n  /* Read the symbol table and the string table.  */\n\n  if (fhdr.pointer_to_symbol_table == 0)\n    {\n      /* No symbol table, no string table.  */\n      str_off = 0;\n      str_size = 0;\n      syms_num = 0;\n      syms_size = 0;\n    }\n  else\n    {\n      /* Symbol table is followed by the string table.  The string table\n\t starts with its length (on 4 bytes).\n\t Map the symbol table and the length of the string table.  */\n      syms_off = fhdr.pointer_to_symbol_table;\n      syms_size = syms_num * SYM_SZ;\n\n      if (!backtrace_get_view (state, descriptor, syms_off, syms_size + 4,\n\t\t\t       error_callback, data, &syms_view))\n\tgoto fail;\n      syms_view_valid = 1;\n\n      str_size = coff_read4 (syms_view.data + syms_size);\n\n      str_off = syms_off + syms_size;\n\n      if (str_size > 4)\n\t{\n\t  /* Map string table (including the length word).  */\n\n\t  if (!backtrace_get_view (state, descriptor, str_off, str_size,\n\t\t\t\t   error_callback, data, &str_view))\n\t    goto fail;\n\t  str_view_valid = 1;\n\t}\n    }\n\n  memset (sections, 0, sizeof sections);\n\n  /* Look for the symbol table.  */\n  for (i = 0; i < sects_num; ++i)\n    {\n      const b_coff_section_header *s = sects + i;\n      unsigned int str_off;\n      int j;\n\n      if (s->name[0] == '/')\n\t{\n\t  /* Extended section name.  */\n\t  str_off = atoi (s->name + 1);\n\t}\n      else\n\tstr_off = 0;\n\n      for (j = 0; j < (int) DEBUG_MAX; ++j)\n\t{\n\t  const char *dbg_name = debug_section_names[j];\n\t  int match;\n\n\t  if (str_off != 0)\n\t    match = coff_long_name_eq (dbg_name, str_off, &str_view);\n\t  else\n\t    match = coff_short_name_eq (dbg_name, s->name);\n\t  if (match)\n\t    {\n\t      sections[j].offset = s->pointer_to_raw_data;\n\t      sections[j].size = s->virtual_size <= s->size_of_raw_data ?\n\t\ts->virtual_size : s->size_of_raw_data;\n\t      break;\n\t    }\n\t}\n    }\n\n  if (syms_num != 0)\n    {\n      struct coff_syminfo_data *sdata;\n\n      sdata = ((struct coff_syminfo_data *)\n\t       backtrace_alloc (state, sizeof *sdata, error_callback, data));\n      if (sdata == NULL)\n\tgoto fail;\n\n      if (!coff_initialize_syminfo (state, image_base, is_64,\n\t\t\t\t    sects, sects_num,\n\t\t\t\t    syms_view.data, syms_size,\n\t\t\t\t    str_view.data, str_size,\n\t\t\t\t    error_callback, data, sdata))\n\t{\n\t  backtrace_free (state, sdata, sizeof *sdata, error_callback, data);\n\t  goto fail;\n\t}\n\n      *found_sym = 1;\n\n      coff_add_syminfo_data (state, sdata);\n    }\n\n  backtrace_release_view (state, &sects_view, error_callback, data);\n  sects_view_valid = 0;\n  if (syms_view_valid)\n    {\n      backtrace_release_view (state, &syms_view, error_callback, data);\n      syms_view_valid = 0;\n    }\n\n  /* Read all the debug sections in a single view, since they are\n     probably adjacent in the file.  We never release this view.  */\n\n  min_offset = 0;\n  max_offset = 0;\n  for (i = 0; i < (int) DEBUG_MAX; ++i)\n    {\n      off_t end;\n\n      if (sections[i].size == 0)\n\tcontinue;\n      if (min_offset == 0 || sections[i].offset < min_offset)\n\tmin_offset = sections[i].offset;\n      end = sections[i].offset + sections[i].size;\n      if (end > max_offset)\n\tmax_offset = end;\n    }\n  if (min_offset == 0 || max_offset == 0)\n    {\n      if (!backtrace_close (descriptor, error_callback, data))\n\tgoto fail;\n      *fileline_fn = coff_nodebug;\n      return 1;\n    }\n\n  if (!backtrace_get_view (state, descriptor, min_offset,\n\t\t\t   max_offset - min_offset,\n\t\t\t   error_callback, data, &debug_view))\n    goto fail;\n  debug_view_valid = 1;\n\n  /* We've read all we need from the executable.  */\n  if (!backtrace_close (descriptor, error_callback, data))\n    goto fail;\n  descriptor = -1;\n\n  for (i = 0; i < (int) DEBUG_MAX; ++i)\n    {\n      size_t size = sections[i].size;\n      dwarf_sections.size[i] = size;\n      if (size == 0)\n\tdwarf_sections.data[i] = NULL;\n      else\n\tdwarf_sections.data[i] = ((const unsigned char *) debug_view.data\n\t\t\t\t  + (sections[i].offset - min_offset));\n    }\n\n  memset (&base_address, 0, sizeof base_address);\n#ifdef HAVE_WINDOWS_H\n  base_address.m = module_handle - image_base.m;\n#endif\n\n  if (!backtrace_dwarf_add (state, base_address, &dwarf_sections,\n\t\t\t    0, /* FIXME: is_bigendian */\n\t\t\t    NULL, /* altlink */\n\t\t\t    error_callback, data, fileline_fn,\n\t\t\t    NULL /* returned fileline_entry */))\n    goto fail;\n\n  *found_dwarf = 1;\n\n  return 1;\n\n fail:\n  if (sects_view_valid)\n    backtrace_release_view (state, &sects_view, error_callback, data);\n  if (str_view_valid)\n    backtrace_release_view (state, &str_view, error_callback, data);\n  if (syms_view_valid)\n    backtrace_release_view (state, &syms_view, error_callback, data);\n  if (debug_view_valid)\n    backtrace_release_view (state, &debug_view, error_callback, data);\n  if (descriptor != -1)\n    backtrace_close (descriptor, error_callback, data);\n  return 0;\n}\n\n#ifdef HAVE_WINDOWS_H\nstruct dll_notification_context\n{\n  struct backtrace_state *state;\n  backtrace_error_callback error_callback;\n  void *data;\n};\n\nstatic VOID CALLBACK\ndll_notification (ULONG reason,\n\t\t  struct dll_notification_data *notification_data,\n\t\t  PVOID context)\n{\n  char module_name[MAX_PATH];\n  int descriptor;\n  struct dll_notification_context* dll_context =\n    (struct dll_notification_context*) context;\n  struct backtrace_state *state = dll_context->state;\n  void *data = dll_context->data;\n  backtrace_error_callback error_callback = dll_context->data;\n  fileline fileline;\n  int found_sym;\n  int found_dwarf;\n  HMODULE module_handle;\n\n  if (reason != LDR_DLL_NOTIFICATION_REASON_LOADED)\n    return;\n\n  if (!GetModuleHandleExW ((GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS\n\t\t\t    | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT),\n\t\t\t   (wchar_t*) notification_data->dll_base,\n\t\t\t   &module_handle))\n    return;\n\n  if (!GetModuleFileNameA ((HMODULE) module_handle, module_name, MAX_PATH - 1))\n    return;\n\n  descriptor = backtrace_open (module_name, error_callback, data, NULL);\n\n  if (descriptor < 0)\n    return;\n\n  coff_add (state, descriptor, error_callback, data, &fileline, &found_sym,\n\t    &found_dwarf, (uintptr_t) module_handle);\n}\n#endif /* defined(HAVE_WINDOWS_H) */\n\n/* Initialize the backtrace data we need from an ELF executable.  At\n   the ELF level, all we need to do is find the debug info\n   sections.  */\n\nint\nbacktrace_initialize (struct backtrace_state *state,\n\t\t      const char *filename ATTRIBUTE_UNUSED, int descriptor,\n\t\t      backtrace_error_callback error_callback,\n\t\t      void *data, fileline *fileline_fn)\n{\n  int ret;\n  int found_sym;\n  int found_dwarf;\n  fileline coff_fileline_fn;\n  uintptr_t module_handle = 0;\n#ifdef HAVE_TLHELP32_H\n  fileline module_fileline_fn;\n  int module_found_sym;\n  HANDLE snapshot;\n#endif\n\n#ifdef HAVE_WINDOWS_H\n  HMODULE nt_dll_handle;\n\n  module_handle = (uintptr_t) GetModuleHandle (NULL);\n#endif\n\n  ret = coff_add (state, descriptor, error_callback, data,\n\t\t  &coff_fileline_fn, &found_sym, &found_dwarf, module_handle);\n  if (!ret)\n    return 0;\n\n#ifdef HAVE_TLHELP32_H\n  do\n    {\n      snapshot = CreateToolhelp32Snapshot (TH32CS_SNAPMODULE, 0);\n    }\n  while (snapshot == INVALID_HANDLE_VALUE\n\t && GetLastError () == ERROR_BAD_LENGTH);\n\n  if (snapshot != INVALID_HANDLE_VALUE)\n    {\n      MODULEENTRY32 entry;\n      BOOL ok;\n      entry.dwSize = sizeof (MODULEENTRY32);\n\n      for (ok = Module32First (snapshot, &entry); ok; ok = Module32Next (snapshot, &entry))\n\t{\n\t  if (strcmp (filename, entry.szExePath) == 0)\n\t    continue;\n\n\t  module_handle = (uintptr_t) entry.hModule;\n\t  if (module_handle == 0)\n\t    continue;\n\n\t  descriptor = backtrace_open (entry.szExePath, error_callback, data,\n\t\t\t\t       NULL);\n\t  if (descriptor < 0)\n\t    continue;\n\n\t  coff_add (state, descriptor, error_callback, data,\n\t\t    &module_fileline_fn, &module_found_sym, &found_dwarf,\n\t\t    module_handle);\n\t  if (module_found_sym)\n\t    found_sym = 1;\n\t}\n\n      CloseHandle (snapshot);\n    }\n#endif\n\n#ifdef HAVE_WINDOWS_H\n  nt_dll_handle = GetModuleHandleW (L\"ntdll.dll\");\n  if (nt_dll_handle)\n    {\n      LDR_REGISTER_FUNCTION register_func;\n      const char register_name[] = \"LdrRegisterDllNotification\";\n      register_func = (void*) GetProcAddress (nt_dll_handle,\n\t\t\t\t\t      register_name);\n\n      if (register_func)\n\t{\n\t  PVOID cookie;\n\t  struct dll_notification_context *context\n\t    = backtrace_alloc (state,\n\t\t\t       sizeof (struct dll_notification_context),\n\t\t\t       error_callback, data);\n\n\t  if (context)\n\t    {\n\t      context->state = state;\n\t      context->data = data;\n\t      context->error_callback = error_callback;\n\n\t      register_func (0, &dll_notification, context, &cookie);\n\t    }\n\t}\n    }\n#endif /* defined(HAVE_WINDOWS_H) */\n\n  if (!state->threaded)\n    {\n      if (found_sym)\n\tstate->syminfo_fn = coff_syminfo;\n      else if (state->syminfo_fn == NULL)\n\tstate->syminfo_fn = coff_nosyms;\n    }\n  else\n    {\n      if (found_sym)\n\tbacktrace_atomic_store_pointer (&state->syminfo_fn, coff_syminfo);\n      else\n\t(void) __sync_bool_compare_and_swap (&state->syminfo_fn, NULL,\n\t\t\t\t\t     coff_nosyms);\n    }\n\n  if (!state->threaded)\n    {\n      if (state->fileline_fn == NULL || state->fileline_fn == coff_nodebug)\n\t*fileline_fn = coff_fileline_fn;\n    }\n  else\n    {\n      fileline current_fn;\n\n      current_fn = backtrace_atomic_load_pointer (&state->fileline_fn);\n      if (current_fn == NULL || current_fn == coff_nodebug)\n\t*fileline_fn = coff_fileline_fn;\n    }\n\n  return 1;\n}\n"
  },
  {
    "path": "src/vendor/libbacktrace/posix.c",
    "content": "/* posix.c -- POSIX file I/O routines for the backtrace library.\n   Copyright (C) 2012-2024 Free Software Foundation, Inc.\n   Written by Ian Lance Taylor, Google.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n    (1) Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n\n    (2) Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in\n    the documentation and/or other materials provided with the\n    distribution.\n\n    (3) The name of the author may not be used to\n    endorse or promote products derived from this software without\n    specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\nIMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,\nINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\nHOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\nIN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGE.  */\n\n#include \"config.h\"\n\n#include <errno.h>\n#include <sys/types.h>\n#include <sys/stat.h>\n#include <fcntl.h>\n#include <unistd.h>\n\n#include \"backtrace.h\"\n#include \"internal.h\"\n\n#ifndef O_BINARY\n#define O_BINARY 0\n#endif\n\n#ifndef O_CLOEXEC\n#define O_CLOEXEC 0\n#endif\n\n#ifndef FD_CLOEXEC\n#define FD_CLOEXEC 1\n#endif\n\n/* Open a file for reading.  */\n\nint\nbacktrace_open (const char *filename, backtrace_error_callback error_callback,\n\t\tvoid *data, int *does_not_exist)\n{\n  int descriptor;\n\n  if (does_not_exist != NULL)\n    *does_not_exist = 0;\n\n  descriptor = open (filename, (int) (O_RDONLY | O_BINARY | O_CLOEXEC));\n  if (descriptor < 0)\n    {\n      /* If DOES_NOT_EXIST is not NULL, then don't call ERROR_CALLBACK\n\t if the file does not exist.  We treat lacking permission to\n\t open the file as the file not existing; this case arises when\n\t running the libgo syscall package tests as root.  */\n      if (does_not_exist != NULL && (errno == ENOENT || errno == EACCES))\n\t*does_not_exist = 1;\n      else\n\terror_callback (data, filename, errno);\n      return -1;\n    }\n\n#ifdef HAVE_FCNTL\n  /* Set FD_CLOEXEC just in case the kernel does not support\n     O_CLOEXEC. It doesn't matter if this fails for some reason.\n     FIXME: At some point it should be safe to only do this if\n     O_CLOEXEC == 0.  */\n  fcntl (descriptor, F_SETFD, FD_CLOEXEC);\n#endif\n\n  return descriptor;\n}\n\n/* Close DESCRIPTOR.  */\n\nint\nbacktrace_close (int descriptor, backtrace_error_callback error_callback,\n\t\t void *data)\n{\n  if (close (descriptor) < 0)\n    {\n      error_callback (data, \"close\", errno);\n      return 0;\n    }\n  return 1;\n}\n"
  },
  {
    "path": "src/vendor/libbacktrace/print.c",
    "content": "/* print.c -- Print the current backtrace.\n   Copyright (C) 2012-2024 Free Software Foundation, Inc.\n   Written by Ian Lance Taylor, Google.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n    (1) Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n\n    (2) Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in\n    the documentation and/or other materials provided with the\n    distribution.\n\n    (3) The name of the author may not be used to\n    endorse or promote products derived from this software without\n    specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\nIMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,\nINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\nHOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\nIN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGE.  */\n\n#include \"config.h\"\n\n#include <stdio.h>\n#include <string.h>\n#include <sys/types.h>\n\n#include \"backtrace.h\"\n#include \"internal.h\"\n\n/* Passed to callbacks.  */\n\nstruct print_data\n{\n  struct backtrace_state *state;\n  FILE *f;\n};\n\n/* Print errors to stderr.  */\n\nstatic void\nerror_callback (void *data, const char *msg, int errnum)\n{\n  struct print_data *pdata = (struct print_data *) data;\n\n  if (pdata->state->filename != NULL)\n    fprintf (stderr, \"%s: \", pdata->state->filename);\n  fprintf (stderr, \"libbacktrace: %s\", msg);\n  if (errnum > 0)\n    fprintf (stderr, \": %s\", strerror (errnum));\n  fputc ('\\n', stderr);\n}\n\n/* Print one level of a backtrace if we couldn't get a file or function name.\n   Use syminfo to try to get a symbol name.  */\n\nstatic void print_syminfo_callback (void *data, uintptr_t pc,\n\t\t\t\t    const char *symname, uintptr_t symval,\n\t\t\t\t    uintptr_t symsize ATTRIBUTE_UNUSED)\n{\n  struct print_data *pdata = (struct print_data *) data;\n\n  if (symname == NULL)\n    fprintf (pdata->f, \"0x%lx ???\\n\\t???:0\\n\", (unsigned long) pc);\n  else\n    fprintf (pdata->f, \"0x%lx ???\\n\\t%s+0x%lx:0\\n\",\n\t     (unsigned long) pc,\n\t     symname,\n\t     (unsigned long) (pc - symval));\n}\n\n/* Print one level of a backtrace.  */\n\nstatic int\nprint_callback (void *data, uintptr_t pc, const char *filename, int lineno,\n\t\tconst char *function)\n{\n  struct print_data *pdata = (struct print_data *) data;\n\n  if (function == NULL && filename == NULL)\n    {\n      backtrace_syminfo (pdata->state, pc, print_syminfo_callback,\n\t\t\t error_callback, data);\n      return 0;\n    }\n\n  fprintf (pdata->f, \"0x%lx %s\\n\\t%s:%d\\n\",\n\t   (unsigned long) pc,\n\t   function == NULL ? \"???\" : function,\n\t   filename == NULL ? \"???\" : filename,\n\t   lineno);\n  return 0;\n}\n\n/* Print a backtrace.  */\n\nvoid __attribute__((noinline))\nbacktrace_print (struct backtrace_state *state, int skip, FILE *f)\n{\n  struct print_data data;\n\n  data.state = state;\n  data.f = f;\n  backtrace_full (state, skip + 1, print_callback, error_callback,\n\t\t  (void *) &data);\n}\n"
  },
  {
    "path": "src/vendor/libbacktrace/read.c",
    "content": "/* read.c -- File views without mmap.\n   Copyright (C) 2012-2024 Free Software Foundation, Inc.\n   Written by Ian Lance Taylor, Google.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n    (1) Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n\n    (2) Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in\n    the documentation and/or other materials provided with the\n    distribution.\n\n    (3) The name of the author may not be used to\n    endorse or promote products derived from this software without\n    specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\nIMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,\nINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\nHOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\nIN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGE.  */\n\n#include \"config.h\"\n\n#include <errno.h>\n#include <stdlib.h>\n#include <sys/types.h>\n#include <unistd.h>\n\n#include \"backtrace.h\"\n#include \"internal.h\"\n\n/* This file implements file views when mmap is not available.  */\n\n/* Create a view of SIZE bytes from DESCRIPTOR at OFFSET.  */\n\nint\nbacktrace_get_view (struct backtrace_state *state, int descriptor,\n\t\t    off_t offset, uint64_t size,\n\t\t    backtrace_error_callback error_callback,\n\t\t    void *data, struct backtrace_view *view)\n{\n  uint64_t got;\n  ssize_t r;\n\n  if ((uint64_t) (size_t) size != size)\n    {\n      error_callback (data, \"file size too large\", 0);\n      return 0;\n    }\n\n  if (lseek (descriptor, offset, SEEK_SET) < 0)\n    {\n      error_callback (data, \"lseek\", errno);\n      return 0;\n    }\n\n  view->base = backtrace_alloc (state, size, error_callback, data);\n  if (view->base == NULL)\n    return 0;\n  view->data = view->base;\n  view->len = size;\n\n  got = 0;\n  while (got < size)\n    {\n      r = read (descriptor, view->base, size - got);\n      if (r < 0)\n\t{\n\t  error_callback (data, \"read\", errno);\n\t  free (view->base);\n\t  return 0;\n\t}\n      if (r == 0)\n\tbreak;\n      got += (uint64_t) r;\n    }\n\n  if (got < size)\n    {\n      error_callback (data, \"file too short\", 0);\n      free (view->base);\n      return 0;\n    }\n\n  return 1;\n}\n\n/* Release a view read by backtrace_get_view.  */\n\nvoid\nbacktrace_release_view (struct backtrace_state *state,\n\t\t\tstruct backtrace_view *view,\n\t\t\tbacktrace_error_callback error_callback,\n\t\t\tvoid *data)\n{\n  backtrace_free (state, view->base, view->len, error_callback, data);\n  view->data = NULL;\n  view->base = NULL;\n}\n"
  },
  {
    "path": "src/vendor/libbacktrace/simple.c",
    "content": "/* simple.c -- The backtrace_simple function.\n   Copyright (C) 2012-2024 Free Software Foundation, Inc.\n   Written by Ian Lance Taylor, Google.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n    (1) Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n\n    (2) Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in\n    the documentation and/or other materials provided with the\n    distribution.\n\n    (3) The name of the author may not be used to\n    endorse or promote products derived from this software without\n    specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\nIMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,\nINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\nHOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\nIN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGE.  */\n\n#include \"config.h\"\n\n#include \"unwind.h\"\n#include \"backtrace.h\"\n\n/* The simple_backtrace routine.  */\n\n/* Data passed through _Unwind_Backtrace.  */\n\nstruct backtrace_simple_data\n{\n  /* Number of frames to skip.  */\n  int skip;\n  /* Library state.  */\n  struct backtrace_state *state;\n  /* Callback routine.  */\n  backtrace_simple_callback callback;\n  /* Error callback routine.  */\n  backtrace_error_callback error_callback;\n  /* Data to pass to callback routine.  */\n  void *data;\n  /* Value to return from backtrace.  */\n  int ret;\n};\n\n/* Unwind library callback routine.  This is passed to\n   _Unwind_Backtrace.  */\n\nstatic _Unwind_Reason_Code\nsimple_unwind (struct _Unwind_Context *context, void *vdata)\n{\n  struct backtrace_simple_data *bdata = (struct backtrace_simple_data *) vdata;\n  uintptr_t pc;\n  int ip_before_insn = 0;\n\n#ifdef HAVE_GETIPINFO\n  pc = _Unwind_GetIPInfo (context, &ip_before_insn);\n#else\n  pc = _Unwind_GetIP (context);\n#endif\n\n  if (bdata->skip > 0)\n    {\n      --bdata->skip;\n      return _URC_NO_REASON;\n    }\n\n  if (!ip_before_insn)\n    --pc;\n\n  bdata->ret = bdata->callback (bdata->data, pc);\n\n  if (bdata->ret != 0)\n    return _URC_END_OF_STACK;\n\n  return _URC_NO_REASON;\n}\n\n/* Get a simple stack backtrace.  */\n\nint __attribute__((noinline))\nbacktrace_simple (struct backtrace_state *state, int skip,\n\t\t  backtrace_simple_callback callback,\n\t\t  backtrace_error_callback error_callback, void *data)\n{\n  struct backtrace_simple_data bdata;\n\n  bdata.skip = skip + 1;\n  bdata.state = state;\n  bdata.callback = callback;\n  bdata.error_callback = error_callback;\n  bdata.data = data;\n  bdata.ret = 0;\n  _Unwind_Backtrace (simple_unwind, &bdata);\n  return bdata.ret;\n}\n"
  },
  {
    "path": "src/vendor/libbacktrace/sort.c",
    "content": "/* sort.c -- Sort without allocating memory\n   Copyright (C) 2012-2024 Free Software Foundation, Inc.\n   Written by Ian Lance Taylor, Google.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n    (1) Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n\n    (2) Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in\n    the documentation and/or other materials provided with the\n    distribution.\n\n    (3) The name of the author may not be used to\n    endorse or promote products derived from this software without\n    specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\nIMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,\nINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\nHOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\nIN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGE.  */\n\n#include \"config.h\"\n\n#include <stddef.h>\n#include <sys/types.h>\n\n#include \"backtrace.h\"\n#include \"internal.h\"\n\n/* The GNU glibc version of qsort allocates memory, which we must not\n   do if we are invoked by a signal handler.  So provide our own\n   sort.  */\n\nstatic void\nswap (char *a, char *b, size_t size)\n{\n  size_t i;\n\n  for (i = 0; i < size; i++, a++, b++)\n    {\n      char t;\n\n      t = *a;\n      *a = *b;\n      *b = t;\n    }\n}\n\nvoid\nbacktrace_qsort (void *basearg, size_t count, size_t size,\n\t\t int (*compar) (const void *, const void *))\n{\n  char *base = (char *) basearg;\n  size_t i;\n  size_t mid;\n\n tail_recurse:\n  if (count < 2)\n    return;\n\n  /* The symbol table and DWARF tables, which is all we use this\n     routine for, tend to be roughly sorted.  Pick the middle element\n     in the array as our pivot point, so that we are more likely to\n     cut the array in half for each recursion step.  */\n  swap (base, base + (count / 2) * size, size);\n\n  mid = 0;\n  for (i = 1; i < count; i++)\n    {\n      if ((*compar) (base, base + i * size) > 0)\n\t{\n\t  ++mid;\n\t  if (i != mid)\n\t    swap (base + mid * size, base + i * size, size);\n\t}\n    }\n\n  if (mid > 0)\n    swap (base, base + mid * size, size);\n\n  /* Recurse with the smaller array, loop with the larger one.  That\n     ensures that our maximum stack depth is log count.  */\n  if (2 * mid < count)\n    {\n      backtrace_qsort (base, mid, size, compar);\n      base += (mid + 1) * size;\n      count -= mid + 1;\n      goto tail_recurse;\n    }\n  else\n    {\n      backtrace_qsort (base + (mid + 1) * size, count - (mid + 1),\n\t\t       size, compar);\n      count = mid;\n      goto tail_recurse;\n    }\n}\n"
  },
  {
    "path": "src/vendor/libbacktrace/state.c",
    "content": "/* state.c -- Create the backtrace state.\n   Copyright (C) 2012-2024 Free Software Foundation, Inc.\n   Written by Ian Lance Taylor, Google.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n    (1) Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n\n    (2) Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in\n    the documentation and/or other materials provided with the\n    distribution.\n\n    (3) The name of the author may not be used to\n    endorse or promote products derived from this software without\n    specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\nIMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,\nINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\nHOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\nIN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGE.  */\n\n#include \"config.h\"\n\n#include <string.h>\n#include <sys/types.h>\n\n#include \"backtrace.h\"\n#include \"backtrace-supported.h\"\n#include \"internal.h\"\n\n/* Create the backtrace state.  This will then be passed to all the\n   other routines.  */\n\nstruct backtrace_state *\nbacktrace_create_state (const char *filename, int threaded,\n\t\t\tbacktrace_error_callback error_callback,\n\t\t\tvoid *data)\n{\n  struct backtrace_state init_state;\n  struct backtrace_state *state;\n\n#ifndef HAVE_SYNC_FUNCTIONS\n  if (threaded)\n    {\n      error_callback (data, \"backtrace library does not support threads\", 0);\n      return NULL;\n    }\n#endif\n\n  memset (&init_state, 0, sizeof init_state);\n  init_state.filename = filename;\n  init_state.threaded = threaded;\n\n  state = ((struct backtrace_state *)\n\t   backtrace_alloc (&init_state, sizeof *state, error_callback, data));\n  if (state == NULL)\n    return NULL;\n  *state = init_state;\n\n  return state;\n}\n"
  },
  {
    "path": "src/vendor/libbacktrace/stest.c",
    "content": "/* stest.c -- Test for libbacktrace internal sort function\n   Copyright (C) 2012-2024 Free Software Foundation, Inc.\n   Written by Ian Lance Taylor, Google.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n    (1) Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n\n    (2) Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in\n    the documentation and/or other materials provided with the\n    distribution.\n\n    (3) The name of the author may not be used to\n    endorse or promote products derived from this software without\n    specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\nIMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,\nINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\nHOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\nIN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGE.  */\n\n#include \"config.h\"\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/types.h>\n\n#include \"backtrace.h\"\n#include \"internal.h\"\n\n/* Test the local qsort implementation.  */\n\n#define MAX 10\n\nstruct test\n{\n  size_t count;\n  int input[MAX];\n  int output[MAX];\n};\n\nstatic struct test tests[] =\n  {\n    {\n      10,\n      { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 },\n      { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }\n    },\n    {\n      9,\n      { 1, 2, 3, 4, 5, 6, 7, 8, 9 },\n      { 1, 2, 3, 4, 5, 6, 7, 8, 9 }\n    },\n    {\n      10,\n      { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 },\n      { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 },\n    },\n    {\n      9,\n      { 9, 8, 7, 6, 5, 4, 3, 2, 1 },\n      { 1, 2, 3, 4, 5, 6, 7, 8, 9 },\n    },\n    {\n      10,\n      { 2, 4, 6, 8, 10, 1, 3, 5, 7, 9 },\n      { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 },\n    },\n    {\n      5,\n      { 4, 5, 3, 1, 2 },\n      { 1, 2, 3, 4, 5 },\n    },\n    {\n      5,\n      { 1, 1, 1, 1, 1 },\n      { 1, 1, 1, 1, 1 },\n    },\n    {\n      5,\n      { 1, 1, 2, 1, 1 },\n      { 1, 1, 1, 1, 2 },\n    },\n    {\n      5,\n      { 2, 1, 1, 1, 1 },\n      { 1, 1, 1, 1, 2 },\n    },\n  };\n\nstatic int\ncompare (const void *a, const void *b)\n{\n  const int *ai = (const int *) a;\n  const int *bi = (const int *) b;\n\n  return *ai - *bi;\n}\n\nint\nmain (int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)\n{\n  int failures;\n  size_t i;\n  int a[MAX];\n\n  failures = 0;\n  for (i = 0; i < sizeof tests / sizeof tests[0]; i++)\n    {\n      memcpy (a, tests[i].input, tests[i].count * sizeof (int));\n      backtrace_qsort (a, tests[i].count, sizeof (int), compare);\n      if (memcmp (a, tests[i].output, tests[i].count * sizeof (int)) != 0)\n\t{\n\t  size_t j;\n\n\t  fprintf (stderr, \"test %d failed:\", (int) i);\n\t  for (j = 0; j < tests[i].count; j++)\n\t    fprintf (stderr, \" %d\", a[j]);\n\t  fprintf (stderr, \"\\n\");\n\t  ++failures;\n\t}\n    }\n\n  exit (failures > 0 ? EXIT_FAILURE : EXIT_SUCCESS);\n}\n"
  },
  {
    "path": "src/vendor/libbacktrace/test-driver",
    "content": "#! /bin/sh\n# test-driver - basic testsuite driver script.\n\nscriptversion=2016-01-11.22; # UTC\n\n# Copyright (C) 2011-2017 Free Software Foundation, Inc.\n#\n# This program is free software; you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation; either version 2, or (at your option)\n# any later version.\n#\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\n# As a special exception to the GNU General Public License, if you\n# distribute this file as part of a program that contains a\n# configuration script generated by Autoconf, you may include it under\n# the same distribution terms that you use for the rest of that program.\n\n# This file is maintained in Automake, please report\n# bugs to <bug-automake@gnu.org> or send patches to\n# <automake-patches@gnu.org>.\n\n# Make unconditional expansion of undefined variables an error.  This\n# helps a lot in preventing typo-related bugs.\nset -u\n\nusage_error ()\n{\n  echo \"$0: $*\" >&2\n  print_usage >&2\n  exit 2\n}\n\nprint_usage ()\n{\n  cat <<END\nUsage:\n  test-driver --test-name=NAME --log-file=PATH --trs-file=PATH\n              [--expect-failure={yes|no}] [--color-tests={yes|no}]\n              [--enable-hard-errors={yes|no}] [--]\n              TEST-SCRIPT [TEST-SCRIPT-ARGUMENTS]\nThe '--test-name', '--log-file' and '--trs-file' options are mandatory.\nEND\n}\n\ntest_name= # Used for reporting.\nlog_file=  # Where to save the output of the test script.\ntrs_file=  # Where to save the metadata of the test run.\nexpect_failure=no\ncolor_tests=no\nenable_hard_errors=yes\nwhile test $# -gt 0; do\n  case $1 in\n  --help) print_usage; exit $?;;\n  --version) echo \"test-driver $scriptversion\"; exit $?;;\n  --test-name) test_name=$2; shift;;\n  --log-file) log_file=$2; shift;;\n  --trs-file) trs_file=$2; shift;;\n  --color-tests) color_tests=$2; shift;;\n  --expect-failure) expect_failure=$2; shift;;\n  --enable-hard-errors) enable_hard_errors=$2; shift;;\n  --) shift; break;;\n  -*) usage_error \"invalid option: '$1'\";;\n   *) break;;\n  esac\n  shift\ndone\n\nmissing_opts=\ntest x\"$test_name\" = x && missing_opts=\"$missing_opts --test-name\"\ntest x\"$log_file\"  = x && missing_opts=\"$missing_opts --log-file\"\ntest x\"$trs_file\"  = x && missing_opts=\"$missing_opts --trs-file\"\nif test x\"$missing_opts\" != x; then\n  usage_error \"the following mandatory options are missing:$missing_opts\"\nfi\n\nif test $# -eq 0; then\n  usage_error \"missing argument\"\nfi\n\nif test $color_tests = yes; then\n  # Keep this in sync with 'lib/am/check.am:$(am__tty_colors)'.\n  red='\u001b[0;31m' # Red.\n  grn='\u001b[0;32m' # Green.\n  lgn='\u001b[1;32m' # Light green.\n  blu='\u001b[1;34m' # Blue.\n  mgn='\u001b[0;35m' # Magenta.\n  std='\u001b[m'     # No color.\nelse\n  red= grn= lgn= blu= mgn= std=\nfi\n\ndo_exit='rm -f $log_file $trs_file; (exit $st); exit $st'\ntrap \"st=129; $do_exit\" 1\ntrap \"st=130; $do_exit\" 2\ntrap \"st=141; $do_exit\" 13\ntrap \"st=143; $do_exit\" 15\n\n# Test script is run here.\n\"$@\" >$log_file 2>&1\nestatus=$?\n\nif test $enable_hard_errors = no && test $estatus -eq 99; then\n  tweaked_estatus=1\nelse\n  tweaked_estatus=$estatus\nfi\n\ncase $tweaked_estatus:$expect_failure in\n  0:yes) col=$red res=XPASS recheck=yes gcopy=yes;;\n  0:*)   col=$grn res=PASS  recheck=no  gcopy=no;;\n  77:*)  col=$blu res=SKIP  recheck=no  gcopy=yes;;\n  99:*)  col=$mgn res=ERROR recheck=yes gcopy=yes;;\n  *:yes) col=$lgn res=XFAIL recheck=no  gcopy=yes;;\n  *:*)   col=$red res=FAIL  recheck=yes gcopy=yes;;\nesac\n\n# Report the test outcome and exit status in the logs, so that one can\n# know whether the test passed or failed simply by looking at the '.log'\n# file, without the need of also peaking into the corresponding '.trs'\n# file (automake bug#11814).\necho \"$res $test_name (exit status: $estatus)\" >>$log_file\n\n# Report outcome to console.\necho \"${col}${res}${std}: $test_name\"\n\n# Register the test result, and other relevant metadata.\necho \":test-result: $res\" > $trs_file\necho \":global-test-result: $res\" >> $trs_file\necho \":recheck: $recheck\" >> $trs_file\necho \":copy-in-global-log: $gcopy\" >> $trs_file\n\n# Local Variables:\n# mode: shell-script\n# sh-indentation: 2\n# eval: (add-hook 'write-file-hooks 'time-stamp)\n# time-stamp-start: \"scriptversion=\"\n# time-stamp-format: \"%:y-%02m-%02d.%02H\"\n# time-stamp-time-zone: \"UTC0\"\n# time-stamp-end: \"; # UTC\"\n# End:\n"
  },
  {
    "path": "src/vendor/libbacktrace/test_format.c",
    "content": "/* test_format.c -- Test for libbacktrace library\n   Copyright (C) 2018-2024 Free Software Foundation, Inc.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n    (1) Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n\n    (2) Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in\n    the documentation and/or other materials provided with the\n    distribution.\n\n    (3) The name of the author may not be used to\n    endorse or promote products derived from this software without\n    specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\nIMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,\nINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\nHOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\nIN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGE.  */\n\n/* This program tests the externally visible interfaces of the\n   libbacktrace library.  */\n\n#include <assert.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <unistd.h>\n\n#include \"filenames.h\"\n\n#include \"backtrace.h\"\n#include \"backtrace-supported.h\"\n\n#include \"testlib.h\"\n\nint\nmain (int argc ATTRIBUTE_UNUSED, char **argv)\n{\n  state = backtrace_create_state (argv[0], BACKTRACE_SUPPORTS_THREADS,\n\t\t\t\t  error_callback_create, NULL);\n\n  exit (failures ? EXIT_FAILURE : EXIT_SUCCESS);\n}\n"
  },
  {
    "path": "src/vendor/libbacktrace/testlib.c",
    "content": "/* testlib.c -- test functions for libbacktrace library\n   Copyright (C) 2012-2024 Free Software Foundation, Inc.\n   Written by Ian Lance Taylor, Google.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n    (1) Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n\n    (2) Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in\n    the documentation and/or other materials provided with the\n    distribution.\n\n    (3) The name of the author may not be used to\n    endorse or promote products derived from this software without\n    specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\nIMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,\nINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\nHOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\nIN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGE.  */\n\n#include <assert.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"filenames.h\"\n\n#include \"backtrace.h\"\n\n#include \"testlib.h\"\n\n/* The backtrace state.  */\n\nvoid *state;\n\n/* The number of failures.  */\n\nint failures;\n\n/* Return the base name in a path.  */\n\nconst char *\nbase (const char *p)\n{\n  const char *last;\n  const char *s;\n\n  last = NULL;\n  for (s = p; *s != '\\0'; ++s)\n    {\n      if (IS_DIR_SEPARATOR (*s))\n\tlast = s + 1;\n    }\n  return last != NULL ? last : p;\n}\n\n/* Check an entry in a struct info array.  */\n\nvoid\ncheck (const char *name, int index, const struct info *all, int want_lineno,\n       const char *want_function, const char *want_file, int *failed)\n{\n  if (*failed)\n    return;\n  if (all[index].filename == NULL || all[index].function == NULL)\n    {\n      fprintf (stderr, \"%s: [%d]: missing file name or function name\\n\",\n\t       name, index);\n      *failed = 1;\n      return;\n    }\n  if (strcmp (base (all[index].filename), want_file) != 0)\n    {\n      fprintf (stderr, \"%s: [%d]: got %s expected %s\\n\", name, index,\n\t       all[index].filename, want_file);\n      *failed = 1;\n    }\n  if (all[index].lineno != want_lineno)\n    {\n      fprintf (stderr, \"%s: [%d]: got %d expected %d\\n\", name, index,\n\t       all[index].lineno, want_lineno);\n      *failed = 1;\n    }\n  if (strcmp (all[index].function, want_function) != 0)\n    {\n      fprintf (stderr, \"%s: [%d]: got %s expected %s\\n\", name, index,\n\t       all[index].function, want_function);\n      *failed = 1;\n    }\n}\n\n/* The backtrace callback function.  */\n\nint\ncallback_one (void *vdata, uintptr_t pc ATTRIBUTE_UNUSED,\n\t      const char *filename, int lineno, const char *function)\n{\n  struct bdata *data = (struct bdata *) vdata;\n  struct info *p;\n\n  if (data->index >= data->max)\n    {\n      fprintf (stderr, \"callback_one: callback called too many times\\n\");\n      data->failed = 1;\n      return 1;\n    }\n\n  p = &data->all[data->index];\n  if (filename == NULL)\n    p->filename = NULL;\n  else\n    {\n      p->filename = strdup (filename);\n      assert (p->filename != NULL);\n    }\n  p->lineno = lineno;\n  if (function == NULL)\n    p->function = NULL;\n  else\n    {\n      p->function = strdup (function);\n      assert (p->function != NULL);\n    }\n  ++data->index;\n\n  return 0;\n}\n\n/* An error callback passed to backtrace.  */\n\nvoid\nerror_callback_one (void *vdata, const char *msg, int errnum)\n{\n  struct bdata *data = (struct bdata *) vdata;\n\n  fprintf (stderr, \"%s\", msg);\n  if (errnum > 0)\n    fprintf (stderr, \": %s\", strerror (errnum));\n  fprintf (stderr, \"\\n\");\n  data->failed = 1;\n}\n\n/* The backtrace_simple callback function.  */\n\nint\ncallback_two (void *vdata, uintptr_t pc)\n{\n  struct sdata *data = (struct sdata *) vdata;\n\n  if (data->index >= data->max)\n    {\n      fprintf (stderr, \"callback_two: callback called too many times\\n\");\n      data->failed = 1;\n      return 1;\n    }\n\n  data->addrs[data->index] = pc;\n  ++data->index;\n\n  return 0;\n}\n\n/* An error callback passed to backtrace_simple.  */\n\nvoid\nerror_callback_two (void *vdata, const char *msg, int errnum)\n{\n  struct sdata *data = (struct sdata *) vdata;\n\n  fprintf (stderr, \"%s\", msg);\n  if (errnum > 0)\n    fprintf (stderr, \": %s\", strerror (errnum));\n  fprintf (stderr, \"\\n\");\n  data->failed = 1;\n}\n\n/* The backtrace_syminfo callback function.  */\n\nvoid\ncallback_three (void *vdata, uintptr_t pc ATTRIBUTE_UNUSED,\n\t\tconst char *symname, uintptr_t symval,\n\t\tuintptr_t symsize)\n{\n  struct symdata *data = (struct symdata *) vdata;\n\n  if (symname == NULL)\n    data->name = NULL;\n  else\n    {\n      data->name = strdup (symname);\n      assert (data->name != NULL);\n    }\n  data->val = symval;\n  data->size = symsize;\n}\n\n/* The backtrace_syminfo error callback function.  */\n\nvoid\nerror_callback_three (void *vdata, const char *msg, int errnum)\n{\n  struct symdata *data = (struct symdata *) vdata;\n\n  fprintf (stderr, \"%s\", msg);\n  if (errnum > 0)\n    fprintf (stderr, \": %s\", strerror (errnum));\n  fprintf (stderr, \"\\n\");\n  data->failed = 1;\n}\n\n/* The backtrace_create_state error callback function.  */\n\nvoid\nerror_callback_create (void *data ATTRIBUTE_UNUSED, const char *msg,\n                       int errnum)\n{\n  fprintf (stderr, \"%s\", msg);\n  if (errnum > 0)\n    fprintf (stderr, \": %s\", strerror (errnum));\n  fprintf (stderr, \"\\n\");\n  exit (EXIT_FAILURE);\n}\n"
  },
  {
    "path": "src/vendor/libbacktrace/testlib.h",
    "content": "/* testlib.h -- Header for test functions for libbacktrace library\n   Copyright (C) 2012-2024 Free Software Foundation, Inc.\n   Written by Ian Lance Taylor, Google.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n    (1) Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n\n    (2) Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in\n    the documentation and/or other materials provided with the\n    distribution.\n\n    (3) The name of the author may not be used to\n    endorse or promote products derived from this software without\n    specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\nIMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,\nINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\nHOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\nIN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGE.  */\n\n#ifndef LIBBACKTRACE_TESTLIB_H\n#define LIBBACKTRACE_TESTLIB_H\n\n/* Portable attribute syntax.  Actually some of these tests probably\n   won't work if the attributes are not recognized.  */\n\n#ifndef GCC_VERSION\n# define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__)\n#endif\n\n#if (GCC_VERSION < 2007)\n# define __attribute__(x)\n#endif\n\n#ifndef ATTRIBUTE_UNUSED\n# define ATTRIBUTE_UNUSED __attribute__ ((__unused__))\n#endif\n\n/* Used to collect backtrace info.  */\n\nstruct info\n{\n  char *filename;\n  int lineno;\n  char *function;\n};\n\n/* Passed to backtrace callback function.  */\n\nstruct bdata\n{\n  struct info *all;\n  size_t index;\n  size_t max;\n  int failed;\n};\n\n/* Passed to backtrace_simple callback function.  */\n\nstruct sdata\n{\n  uintptr_t *addrs;\n  size_t index;\n  size_t max;\n  int failed;\n};\n\n/* Passed to backtrace_syminfo callback function.  */\n\nstruct symdata\n{\n  const char *name;\n  uintptr_t val, size;\n  int failed;\n};\n\n/* The backtrace state.  */\n\nextern void *state;\n\n/* The number of failures.  */\n\nextern int failures;\n\nextern const char *base (const char *p);\nextern void check (const char *name, int index, const struct info *all,\n\t\t   int want_lineno, const char *want_function,\n\t\t   const char *want_file, int *failed);\nextern int callback_one (void *, uintptr_t, const char *, int, const char *);\nextern void error_callback_one (void *, const char *, int);\nextern int callback_two (void *, uintptr_t);\nextern void error_callback_two (void *, const char *, int);\nextern void callback_three (void *, uintptr_t, const char *, uintptr_t,\n\t\t\t    uintptr_t);\nextern void error_callback_three (void *, const char *, int);\nextern void error_callback_create (void *, const char *, int);\n\n#endif /* !defined(LIBBACKTRACE_TESTLIB_H) */\n"
  },
  {
    "path": "src/vendor/libbacktrace/ttest.c",
    "content": "/* ttest.c -- Test for libbacktrace library\n   Copyright (C) 2017-2024 Free Software Foundation, Inc.\n   Written by Ian Lance Taylor, Google.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n    (1) Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n\n    (2) Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in\n    the documentation and/or other materials provided with the\n    distribution.\n\n    (3) The name of the author may not be used to\n    endorse or promote products derived from this software without\n    specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\nIMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,\nINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\nHOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\nIN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGE.  */\n\n/* Test using the libbacktrace library from multiple threads.  */\n\n#include <assert.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include <pthread.h>\n\n#include \"filenames.h\"\n\n#include \"backtrace.h\"\n#include \"backtrace-supported.h\"\n\n#include \"testlib.h\"\n\nstatic int f2 (int) __attribute__ ((noinline));\nstatic int f3 (int, int) __attribute__ ((noinline));\n\n/* Test that a simple backtrace works.  This is called via\n   pthread_create.  It returns the number of failures, as void *.  */\n\nstatic void *\ntest1_thread (void *arg ATTRIBUTE_UNUSED)\n{\n  /* Returning a value here and elsewhere avoids a tailcall which\n     would mess up the backtrace.  */\n  return (void *) (uintptr_t) (f2 (__LINE__) - 2);\n}\n\nstatic int\nf2 (int f1line)\n{\n  return f3 (f1line, __LINE__) + 2;\n}\n\nstatic int\nf3 (int f1line, int f2line)\n{\n  struct info all[20];\n  struct bdata data;\n  int f3line;\n  int i;\n\n  data.all = &all[0];\n  data.index = 0;\n  data.max = 20;\n  data.failed = 0;\n\n  f3line = __LINE__ + 1;\n  i = backtrace_full (state, 0, callback_one, error_callback_one, &data);\n\n  if (i != 0)\n    {\n      fprintf (stderr, \"test1: unexpected return value %d\\n\", i);\n      data.failed = 1;\n    }\n\n  if (data.index < 3)\n    {\n      fprintf (stderr,\n\t       \"test1: not enough frames; got %zu, expected at least 3\\n\",\n\t       data.index);\n      data.failed = 1;\n    }\n\n  check (\"test1\", 0, all, f3line, \"f3\", \"ttest.c\", &data.failed);\n  check (\"test1\", 1, all, f2line, \"f2\", \"ttest.c\", &data.failed);\n  check (\"test1\", 2, all, f1line, \"test1_thread\", \"ttest.c\", &data.failed);\n\n  return data.failed;\n}\n\n/* Run the test with 10 threads simultaneously.  */\n\n#define THREAD_COUNT 10\n\nstatic void test1 (void) __attribute__ ((unused));\n\nstatic void\ntest1 (void)\n{\n  pthread_t atid[THREAD_COUNT];\n  int i;\n  int errnum;\n  int this_fail;\n  void *ret;\n\n  for (i = 0; i < THREAD_COUNT; i++)\n    {\n      errnum = pthread_create (&atid[i], NULL, test1_thread, NULL);\n      if (errnum != 0)\n\t{\n\t  fprintf (stderr, \"pthread_create %d: %s\\n\", i, strerror (errnum));\n\t  exit (EXIT_FAILURE);\n\t}\n    }\n\n  this_fail = 0;\n  for (i = 0; i < THREAD_COUNT; i++)\n    {\n      errnum = pthread_join (atid[i], &ret);\n      if (errnum != 0)\n\t{\n\t  fprintf (stderr, \"pthread_join %d: %s\\n\", i, strerror (errnum));\n\t  exit (EXIT_FAILURE);\n\t}\n      this_fail += (int) (uintptr_t) ret;\n    }\n\n  printf (\"%s: threaded backtrace_full noinline\\n\", this_fail > 0 ? \"FAIL\" : \"PASS\");\n\n  failures += this_fail;\n}\n\nint\nmain (int argc ATTRIBUTE_UNUSED, char **argv)\n{\n  state = backtrace_create_state (argv[0], BACKTRACE_SUPPORTS_THREADS,\n\t\t\t\t  error_callback_create, NULL);\n\n#if BACKTRACE_SUPPORTED\n#if BACKTRACE_SUPPORTS_THREADS\n  test1 ();\n#endif\n#endif\n\n  exit (failures ? EXIT_FAILURE : EXIT_SUCCESS);\n}\n"
  },
  {
    "path": "src/vendor/libbacktrace/unittest.c",
    "content": "/* unittest.c -- Test for libbacktrace library\n   Copyright (C) 2018-2024 Free Software Foundation, Inc.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n    (1) Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n\n    (2) Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in\n    the documentation and/or other materials provided with the\n    distribution.\n\n    (3) The name of the author may not be used to\n    endorse or promote products derived from this software without\n    specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\nIMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,\nINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\nHOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\nIN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGE.  */\n\n#include <assert.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <unistd.h>\n\n#include \"filenames.h\"\n\n#include \"backtrace.h\"\n#include \"backtrace-supported.h\"\n\n#include \"testlib.h\"\n\n#include \"internal.h\"\n\nstatic unsigned count;\n\nstatic void\nerror_callback (void *vdata ATTRIBUTE_UNUSED, const char *msg ATTRIBUTE_UNUSED,\n\t\tint errnum ATTRIBUTE_UNUSED)\n{\n  ++count;\n}\n\nstatic int\ntest1 (void)\n{\n  int res;\n  int failed;\n\n  struct backtrace_vector vec;\n\n  memset (&vec, 0, sizeof vec);\n\n  backtrace_vector_grow (state, 100, error_callback, NULL, &vec);\n  vec.alc += vec.size;\n  vec.size = 0;\n\n  count = 0;\n  res = backtrace_vector_release (state, &vec, error_callback, NULL);\n  failed = res != 1 || count != 0 || vec.base != NULL;\n\n  printf (\"%s: unittest backtrace_vector_release size == 0\\n\",\n\t  failed ? \"FAIL\": \"PASS\");\n\n  if (failed)\n    ++failures;\n\n  return failures;\n}\n\nint\nmain (int argc ATTRIBUTE_UNUSED, char **argv)\n{\n  state = backtrace_create_state (argv[0], BACKTRACE_SUPPORTS_THREADS,\n\t\t\t\t  error_callback_create, NULL);\n\n  test1 ();\n\n  exit (failures ? EXIT_FAILURE : EXIT_SUCCESS);\n}\n"
  },
  {
    "path": "src/vendor/libbacktrace/unknown.c",
    "content": "/* unknown.c -- used when backtrace configury does not know file format.\n   Copyright (C) 2012-2024 Free Software Foundation, Inc.\n   Written by Ian Lance Taylor, Google.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n    (1) Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n\n    (2) Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in\n    the documentation and/or other materials provided with the\n    distribution.\n\n    (3) The name of the author may not be used to\n    endorse or promote products derived from this software without\n    specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\nIMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,\nINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\nHOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\nIN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGE.  */\n\n#include \"config.h\"\n\n#include <sys/types.h>\n\n#include \"backtrace.h\"\n#include \"internal.h\"\n\n/* A trivial routine that always fails to find fileline data.  */\n\nstatic int\nunknown_fileline (struct backtrace_state *state ATTRIBUTE_UNUSED,\n\t\t  uintptr_t pc, backtrace_full_callback callback,\n\t\t  backtrace_error_callback error_callback ATTRIBUTE_UNUSED,\n\t\t  void *data)\n\n{\n  return callback (data, pc, NULL, 0, NULL);\n}\n\n/* Initialize the backtrace data when we don't know how to read the\n   debug info.  */\n\nint\nbacktrace_initialize (struct backtrace_state *state ATTRIBUTE_UNUSED,\n\t\t      const char *filename ATTRIBUTE_UNUSED,\n\t\t      int descriptor ATTRIBUTE_UNUSED,\n\t\t      backtrace_error_callback error_callback ATTRIBUTE_UNUSED,\n\t\t      void *data ATTRIBUTE_UNUSED, fileline *fileline_fn)\n{\n  state->fileline_data = NULL;\n  *fileline_fn = unknown_fileline;\n  return 1;\n}\n"
  },
  {
    "path": "src/vendor/libbacktrace/xcoff.c",
    "content": "/* xcoff.c -- Get debug data from an XCOFF file for backtraces.\n   Copyright (C) 2012-2024 Free Software Foundation, Inc.\n   Adapted from elf.c.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n    (1) Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n\n    (2) Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in\n    the documentation and/or other materials provided with the\n    distribution.\n\n    (3) The name of the author may not be used to\n    endorse or promote products derived from this software without\n    specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\nIMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,\nINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\nHOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\nIN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGE.  */\n\n#include \"config.h\"\n\n#include <errno.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/types.h>\n\n#ifdef HAVE_LOADQUERY\n#include <sys/ldr.h>\n#endif\n\n#include \"backtrace.h\"\n#include \"internal.h\"\n\n/* The configure script must tell us whether we are 32-bit or 64-bit\n   XCOFF.  We could make this code test and support either possibility,\n   but there is no point.  This code only works for the currently\n   running executable, which means that we know the XCOFF mode at\n   configure time.  */\n\n#if BACKTRACE_XCOFF_SIZE != 32 && BACKTRACE_XCOFF_SIZE != 64\n#error \"Unknown BACKTRACE_XCOFF_SIZE\"\n#endif\n\n/* XCOFF file header.  */\n\n#if BACKTRACE_XCOFF_SIZE == 32\n\ntypedef struct {\n  uint16_t f_magic;\n  uint16_t f_nscns;\n  uint32_t f_timdat;\n  uint32_t f_symptr;\n  uint32_t f_nsyms;\n  uint16_t f_opthdr;\n  uint16_t f_flags;\n} b_xcoff_filhdr;\n\n#define XCOFF_MAGIC\t0737\n\n#else /* BACKTRACE_XCOFF_SIZE != 32 */\n\ntypedef struct {\n  uint16_t f_magic;\n  uint16_t f_nscns;\n  uint32_t f_timdat;\n  uint64_t f_symptr;\n  uint16_t f_opthdr;\n  uint16_t f_flags;\n  uint32_t f_nsyms;\n} b_xcoff_filhdr;\n\n#define XCOFF_MAGIC\t0767\n\n#endif /* BACKTRACE_XCOFF_SIZE != 32 */\n\n#define F_SHROBJ\t0x2000\t/* File is a shared object.  */\n\n/* XCOFF section header.  */\n\n#if BACKTRACE_XCOFF_SIZE == 32\n\ntypedef struct {\n  char s_name[8];\n  uint32_t s_paddr;\n  uint32_t s_vaddr;\n  uint32_t s_size;\n  uint32_t s_scnptr;\n  uint32_t s_relptr;\n  uint32_t s_lnnoptr;\n  uint16_t s_nreloc;\n  uint16_t s_nlnno;\n  uint32_t s_flags;\n} b_xcoff_scnhdr;\n\n#define _OVERFLOW_MARKER\t65535\n\n#else /* BACKTRACE_XCOFF_SIZE != 32 */\n\ntypedef struct {\n  char name[8];\n  uint64_t s_paddr;\n  uint64_t s_vaddr;\n  uint64_t s_size;\n  uint64_t s_scnptr;\n  uint64_t s_relptr;\n  uint64_t s_lnnoptr;\n  uint32_t s_nreloc;\n  uint32_t s_nlnno;\n  uint32_t s_flags;\n} b_xcoff_scnhdr;\n\n#endif /* BACKTRACE_XCOFF_SIZE != 32 */\n\n#define STYP_DWARF\t0x10\t/* DWARF debugging section.  */\n#define STYP_TEXT\t0x20\t/* Executable text (code) section.  */\n#define STYP_OVRFLO\t0x8000\t/* Line-number field overflow section.  */\n\n#define SSUBTYP_DWINFO\t0x10000\t/* DWARF info section.  */\n#define SSUBTYP_DWLINE\t0x20000\t/* DWARF line-number section.  */\n#define SSUBTYP_DWARNGE\t0x50000\t/* DWARF aranges section.  */\n#define SSUBTYP_DWABREV\t0x60000\t/* DWARF abbreviation section.  */\n#define SSUBTYP_DWSTR\t0x70000\t/* DWARF strings section.  */\n#define SSUBTYP_DWRNGES\t0x80000\t/* DWARF ranges section.  */\n\n/* XCOFF symbol.  */\n\n#define SYMNMLEN\t8\n\n#if BACKTRACE_XCOFF_SIZE == 32\n\ntypedef struct {\n  union {\n    char _name[SYMNMLEN];\n    struct {\n      uint32_t _zeroes;\n      uint32_t _offset;\n    } _s;\n  } _u;\n#define n_name\t\t_u._name\n#define n_zeroes\t_u._s._zeroes\n#define n_offset_\t_u._s._offset\n\n  uint32_t n_value;\n  int16_t  n_scnum;\n  uint16_t n_type;\n  uint8_t  n_sclass;\n  uint8_t  n_numaux;\n} __attribute__ ((packed)) b_xcoff_syment;\n\n#else /* BACKTRACE_XCOFF_SIZE != 32 */\n\ntypedef struct {\n  uint64_t n_value;\n  uint32_t n_offset_;\n  int16_t  n_scnum;\n  uint16_t n_type;\n  uint8_t  n_sclass;\n  uint8_t  n_numaux;\n} __attribute__ ((packed)) b_xcoff_syment;\n\n#endif /* BACKTRACE_XCOFF_SIZE != 32 */\n\n#define SYMESZ\t18\n\n#define C_EXT\t\t2\t/* External symbol.  */\n#define C_FCN\t\t101\t/* Beginning or end of function.  */\n#define C_FILE\t\t103\t/* Source file name.  */\n#define C_HIDEXT\t107\t/* Unnamed external symbol.  */\n#define C_BINCL\t\t108\t/* Beginning of include file.  */\n#define C_EINCL\t\t109\t/* End of include file.  */\n#define C_WEAKEXT\t111\t/* Weak external symbol.  */\n\n#define ISFCN(x)\t((x) & 0x0020)\n\n/* XCOFF AUX entry.  */\n\n#define AUXESZ\t\t18\n#define FILNMLEN\t14\n\ntypedef union {\n#if BACKTRACE_XCOFF_SIZE == 32\n  struct {\n    uint16_t pad;\n    uint16_t x_lnnohi;\n    uint16_t x_lnno;\n  } x_block;\n#else\n  struct {\n    uint32_t x_lnno;\n  } x_block;\n#endif\n  union {\n    char x_fname[FILNMLEN];\n    struct {\n      uint32_t x_zeroes;\n      uint32_t x_offset;\n      char     pad[FILNMLEN-8];\n      uint8_t  x_ftype;\n    } _x;\n  } x_file;\n#if BACKTRACE_XCOFF_SIZE == 32\n  struct {\n    uint32_t x_exptr;\n    uint32_t x_fsize;\n    uint32_t x_lnnoptr;\n    uint32_t x_endndx;\n  } x_fcn;\n#else\n  struct {\n    uint64_t x_lnnoptr;\n    uint32_t x_fsize;\n    uint32_t x_endndx;\n  } x_fcn;\n#endif\n  struct {\n    uint8_t pad[AUXESZ-1];\n    uint8_t x_auxtype;\n  } x_auxtype;\n} __attribute__ ((packed)) b_xcoff_auxent;\n\n/* XCOFF line number entry.  */\n\n#if BACKTRACE_XCOFF_SIZE == 32\n\ntypedef struct {\n  union {\n    uint32_t l_symndx;\n    uint32_t l_paddr;\n  } l_addr;\n  uint16_t l_lnno;\n} b_xcoff_lineno;\n\n#define LINESZ\t6\n\n#else /* BACKTRACE_XCOFF_SIZE != 32 */\n\ntypedef struct {\n  union {\n    uint32_t l_symndx;\n    uint64_t l_paddr;\n  } l_addr;\n  uint32_t l_lnno;\n} b_xcoff_lineno;\n\n#define LINESZ\t12\n\n#endif /* BACKTRACE_XCOFF_SIZE != 32 */\n\n#if BACKTRACE_XCOFF_SIZE == 32\n#define XCOFF_AIX_TEXTBASE\t0x10000000u\n#else\n#define XCOFF_AIX_TEXTBASE\t0x100000000ul\n#endif\n\n/* AIX big archive fixed-length header.  */\n\n#define AIAMAGBIG\t\"<bigaf>\\n\"\n\ntypedef struct {\n  char fl_magic[8];\t/* Archive magic string.  */\n  char fl_memoff[20];\t/* Offset to member table.  */\n  char fl_gstoff[20];\t/* Offset to global symbol table.  */\n  char fl_gst64off[20];\t/* Offset to global symbol table for 64-bit objects.  */\n  char fl_fstmoff[20];\t/* Offset to first archive member.  */\n  char fl_freeoff[20];\t/* Offset to first member on free list.  */\n} b_ar_fl_hdr;\n\n/* AIX big archive file member header.  */\n\ntypedef struct {\n  char ar_size[20];\t/* File member size - decimal.  */\n  char ar_nxtmem[20];\t/* Next member offset - decimal.  */\n  char ar_prvmem[20];\t/* Previous member offset - decimal.  */\n  char ar_date[12];\t/* File member date - decimal.  */\n  char ar_uid[12];\t/* File member userid - decimal.  */\n  char ar_gid[12];\t/* File member group id - decimal.  */\n  char ar_mode[12];\t/* File member mode - octal.  */\n  char ar_namlen[4];\t/* File member name length - decimal.  */\n  char ar_name[2];\t/* Start of member name.  */\n} b_ar_hdr;\n\n\n/* Information we keep for an XCOFF symbol.  */\n\nstruct xcoff_symbol\n{\n  /* The name of the symbol.  */\n  const char *name;\n  /* The address of the symbol.  */\n  uintptr_t address;\n  /* The size of the symbol.  */\n  size_t size;\n};\n\n/* Information to pass to xcoff_syminfo.  */\n\nstruct xcoff_syminfo_data\n{\n  /* Symbols for the next module.  */\n  struct xcoff_syminfo_data *next;\n  /* The XCOFF symbols, sorted by address.  */\n  struct xcoff_symbol *symbols;\n  /* The number of symbols.  */\n  size_t count;\n};\n\n/* Information about an include file.  */\n\nstruct xcoff_incl\n{\n  /* File name.  */\n  const char *filename;\n  /* Offset to first line number from the include file.  */\n  uintptr_t begin;\n  /* Offset to last line number from the include file.  */\n  uintptr_t end;\n};\n\n/* A growable vector of include files information.  */\n\nstruct xcoff_incl_vector\n{\n  /* Memory.  This is an array of struct xcoff_incl.  */\n  struct backtrace_vector vec;\n  /* Number of include files.  */\n  size_t count;\n};\n\n/* A growable vector of functions information.  */\n\nstruct xcoff_func\n{\n  /* PC.  */\n  uintptr_t pc;\n  /* The size of the function.  */\n  size_t size;\n  /* Function name.  */\n  const char *name;\n  /* File name.  */\n  const char *filename;\n  /* Pointer to first lnno entry.  */\n  uintptr_t lnnoptr;\n  /* Base address of containing section.  */\n  uintptr_t sect_base;\n  /* Starting source line number.  */\n  int lnno;\n};\n\n/* A growable vector of function information.  This is used while\n   reading the function symbols.  */\n\nstruct xcoff_func_vector\n{\n  /* Memory.  This is an array of struct xcoff_func.  */\n  struct backtrace_vector vec;\n  /* Number of valid mappings.  */\n  size_t count;\n};\n\n/* The information we need to map a PC to a file and line.  */\n\nstruct xcoff_fileline_data\n{\n  /* The data for the next file we know about.  */\n  struct xcoff_fileline_data *next;\n  /* Functions information.  */\n  struct xcoff_func_vector func_vec;\n  /* Include files information.  */\n  struct xcoff_incl_vector incl_vec;\n  /* Line numbers information.  */\n  const unsigned char *linenos;\n  size_t linenos_size;\n  uint64_t lnnoptr0;\n  /* Loader address.  */\n  uintptr_t base_address;\n};\n\n/* Information we gather for the DWARF sections we care about.  */\n\nstruct dwsect_info\n{\n  /* Section file offset.  */\n  off_t offset;\n  /* Section size.  */\n  size_t size;\n  /* Section contents, after read from file.  */\n  const unsigned char *data;\n};\n\n/* A dummy callback function used when we can't find any debug info.  */\n\nstatic int\nxcoff_nodebug (struct backtrace_state *state ATTRIBUTE_UNUSED,\n\t       uintptr_t pc ATTRIBUTE_UNUSED,\n\t       backtrace_full_callback callback ATTRIBUTE_UNUSED,\n\t       backtrace_error_callback error_callback, void *data)\n{\n  error_callback (data, \"no debug info in XCOFF executable\", -1);\n  return 0;\n}\n\n/* A dummy callback function used when we can't find a symbol\n   table.  */\n\nstatic void\nxcoff_nosyms (struct backtrace_state *state ATTRIBUTE_UNUSED,\n\t      uintptr_t addr ATTRIBUTE_UNUSED,\n\t      backtrace_syminfo_callback callback ATTRIBUTE_UNUSED,\n\t      backtrace_error_callback error_callback, void *data)\n{\n  error_callback (data, \"no symbol table in XCOFF executable\", -1);\n}\n\n/* Compare struct xcoff_symbol for qsort.  */\n\nstatic int\nxcoff_symbol_compare (const void *v1, const void *v2)\n{\n  const struct xcoff_symbol *e1 = (const struct xcoff_symbol *) v1;\n  const struct xcoff_symbol *e2 = (const struct xcoff_symbol *) v2;\n\n  if (e1->address < e2->address)\n    return -1;\n  else if (e1->address > e2->address)\n    return 1;\n  else\n    return 0;\n}\n\n/* Compare an ADDR against an xcoff_symbol for bsearch.  */\n\nstatic int\nxcoff_symbol_search (const void *vkey, const void *ventry)\n{\n  const uintptr_t *key = (const uintptr_t *) vkey;\n  const struct xcoff_symbol *entry = (const struct xcoff_symbol *) ventry;\n  uintptr_t addr;\n\n  addr = *key;\n  if (addr < entry->address)\n    return -1;\n  else if ((entry->size == 0 && addr > entry->address)\n\t   || (entry->size > 0 && addr >= entry->address + entry->size))\n    return 1;\n  else\n    return 0;\n}\n\n/* Add XDATA to the list in STATE.  */\n\nstatic void\nxcoff_add_syminfo_data (struct backtrace_state *state,\n\t\t\tstruct xcoff_syminfo_data *xdata)\n{\n  if (!state->threaded)\n    {\n      struct xcoff_syminfo_data **pp;\n\n      for (pp = (struct xcoff_syminfo_data **) (void *) &state->syminfo_data;\n\t   *pp != NULL;\n\t   pp = &(*pp)->next)\n\t;\n      *pp = xdata;\n    }\n  else\n    {\n      while (1)\n\t{\n\t  struct xcoff_syminfo_data **pp;\n\n\t  pp = (struct xcoff_syminfo_data **) (void *) &state->syminfo_data;\n\n\t  while (1)\n\t    {\n\t      struct xcoff_syminfo_data *p;\n\n\t      p = backtrace_atomic_load_pointer (pp);\n\n\t      if (p == NULL)\n\t\tbreak;\n\n\t      pp = &p->next;\n\t    }\n\n\t  if (__sync_bool_compare_and_swap (pp, NULL, xdata))\n\t    break;\n\t}\n    }\n}\n\n/* Return the symbol name and value for an ADDR.  */\n\nstatic void\nxcoff_syminfo (struct backtrace_state *state ATTRIBUTE_UNUSED, uintptr_t addr,\n\t       backtrace_syminfo_callback callback,\n\t       backtrace_error_callback error_callback ATTRIBUTE_UNUSED,\n\t       void *data)\n{\n  struct xcoff_syminfo_data *edata;\n  struct xcoff_symbol *sym = NULL;\n  const char *name;\n\n  if (!state->threaded)\n    {\n      for (edata = (struct xcoff_syminfo_data *) state->syminfo_data;\n\t   edata != NULL;\n\t   edata = edata->next)\n\t{\n\t  sym = ((struct xcoff_symbol *)\n\t\t bsearch (&addr, edata->symbols, edata->count,\n\t\t\t  sizeof (struct xcoff_symbol), xcoff_symbol_search));\n\t  if (sym != NULL)\n\t    break;\n\t}\n    }\n  else\n    {\n      struct xcoff_syminfo_data **pp;\n\n      pp = (struct xcoff_syminfo_data **) (void *) &state->syminfo_data;\n      while (1)\n\t{\n\t  edata = backtrace_atomic_load_pointer (pp);\n\t  if (edata == NULL)\n\t    break;\n\n\t  sym = ((struct xcoff_symbol *)\n\t\t bsearch (&addr, edata->symbols, edata->count,\n\t\t\t  sizeof (struct xcoff_symbol), xcoff_symbol_search));\n\t  if (sym != NULL)\n\t    break;\n\n\t  pp = &edata->next;\n\t}\n    }\n\n  if (sym == NULL)\n    callback (data, addr, NULL, 0, 0);\n  else\n    {\n      name = sym->name;\n      /* AIX prepends a '.' to function entry points, remove it.  */\n      if (name && *name == '.')\n\t++name;\n      callback (data, addr, name, sym->address, sym->size);\n    }\n}\n\n/* Return the name of an XCOFF symbol.  */\n\nstatic const char *\nxcoff_symname (const b_xcoff_syment *asym,\n\t       const unsigned char *strtab, size_t strtab_size)\n{\n#if BACKTRACE_XCOFF_SIZE == 32\n  if (asym->n_zeroes != 0)\n    {\n      /* Make a copy as we will release the symtab view.  */\n      char name[SYMNMLEN+1];\n      strncpy (name, asym->n_name, SYMNMLEN);\n      name[SYMNMLEN] = '\\0';\n      return strdup (name);\n    }\n#endif\n  if (asym->n_sclass & 0x80)\n    return NULL; /* .debug */\n  if (asym->n_offset_ >= strtab_size)\n    return NULL;\n  return (const char *) strtab + asym->n_offset_;\n}\n\n/* Initialize the symbol table info for xcoff_syminfo.  */\n\nstatic int\nxcoff_initialize_syminfo (struct backtrace_state *state,\n\t\t\t  uintptr_t base_address,\n\t\t\t  const b_xcoff_syment *syms, size_t nsyms,\n\t\t\t  const unsigned char *strtab, size_t strtab_size,\n\t\t\t  backtrace_error_callback error_callback, void *data,\n\t\t\t  struct xcoff_syminfo_data *sdata)\n{\n  size_t xcoff_symbol_count;\n  size_t xcoff_symbol_size;\n  struct xcoff_symbol *xcoff_symbols;\n  size_t i;\n  unsigned int j;\n\n  /* We only care about function symbols.  Count them.  */\n  xcoff_symbol_count = 0;\n  for (i = 0; i < nsyms; ++i)\n    {\n      const b_xcoff_syment *asym = &syms[i];\n      if ((asym->n_sclass == C_EXT || asym->n_sclass == C_HIDEXT\n\t    || asym->n_sclass == C_WEAKEXT)\n\t  && ISFCN (asym->n_type) && asym->n_numaux > 0 && asym->n_scnum > 0)\n\t++xcoff_symbol_count;\n\n      i += asym->n_numaux;\n    }\n\n  xcoff_symbol_size = xcoff_symbol_count * sizeof (struct xcoff_symbol);\n  xcoff_symbols = ((struct xcoff_symbol *)\n\t\t   backtrace_alloc (state, xcoff_symbol_size, error_callback,\n\t\t\t\t    data));\n  if (xcoff_symbols == NULL)\n    return 0;\n\n  j = 0;\n  for (i = 0; i < nsyms; ++i)\n    {\n      const b_xcoff_syment *asym = &syms[i];\n      if ((asym->n_sclass == C_EXT || asym->n_sclass == C_HIDEXT\n\t    || asym->n_sclass == C_WEAKEXT)\n\t  && ISFCN (asym->n_type) && asym->n_numaux > 0 && asym->n_scnum > 0)\n\t{\n\t  const b_xcoff_auxent *aux = (const b_xcoff_auxent *) (asym + 1);\n\t  xcoff_symbols[j].name = xcoff_symname (asym, strtab, strtab_size);\n\t  xcoff_symbols[j].address = base_address + asym->n_value;\n\t  /* x_fsize will be 0 if there is no debug information.  */\n\t  xcoff_symbols[j].size = aux->x_fcn.x_fsize;\n\t  ++j;\n\t}\n\n      i += asym->n_numaux;\n    }\n\n  backtrace_qsort (xcoff_symbols, xcoff_symbol_count,\n\t\t   sizeof (struct xcoff_symbol), xcoff_symbol_compare);\n\n  sdata->next = NULL;\n  sdata->symbols = xcoff_symbols;\n  sdata->count = xcoff_symbol_count;\n\n  return 1;\n}\n\n/* Compare struct xcoff_func for qsort.  */\n\nstatic int\nxcoff_func_compare (const void *v1, const void *v2)\n{\n  const struct xcoff_func *fn1 = (const struct xcoff_func *) v1;\n  const struct xcoff_func *fn2 = (const struct xcoff_func *) v2;\n\n  if (fn1->pc < fn2->pc)\n    return -1;\n  else if (fn1->pc > fn2->pc)\n    return 1;\n  else\n    return 0;\n}\n\n/* Compare a PC against an xcoff_func for bsearch.  */\n\nstatic int\nxcoff_func_search (const void *vkey, const void *ventry)\n{\n  const uintptr_t *key = (const uintptr_t *) vkey;\n  const struct xcoff_func *entry = (const struct xcoff_func *) ventry;\n  uintptr_t pc;\n\n  pc = *key;\n  if (pc < entry->pc)\n    return -1;\n  else if ((entry->size == 0 && pc > entry->pc)\n\t   || (entry->size > 0 && pc >= entry->pc + entry->size))\n    return 1;\n  else\n    return 0;\n}\n\n/* Compare struct xcoff_incl for qsort.  */\n\nstatic int\nxcoff_incl_compare (const void *v1, const void *v2)\n{\n  const struct xcoff_incl *in1 = (const struct xcoff_incl *) v1;\n  const struct xcoff_incl *in2 = (const struct xcoff_incl *) v2;\n\n  if (in1->begin < in2->begin)\n    return -1;\n  else if (in1->begin > in2->begin)\n    return 1;\n  else\n    return 0;\n}\n\n/* Find a lnnoptr in an include file.  */\n\nstatic int\nxcoff_incl_search (const void *vkey, const void *ventry)\n{\n  const uintptr_t *key = (const uintptr_t *) vkey;\n  const struct xcoff_incl *entry = (const struct xcoff_incl *) ventry;\n  uintptr_t lnno;\n\n  lnno = *key;\n  if (lnno < entry->begin)\n    return -1;\n  else if (lnno > entry->end)\n    return 1;\n  else\n    return 0;\n}\n\n/* Look for a PC in the function vector for one module.  On success,\n   call CALLBACK and return whatever it returns.  On error, call\n   ERROR_CALLBACK and return 0.  Sets *FOUND to 1 if the PC is found,\n   0 if not.  */\n\nstatic int\nxcoff_lookup_pc (struct backtrace_state *state ATTRIBUTE_UNUSED,\n\t\t struct xcoff_fileline_data *fdata, uintptr_t pc,\n\t\t backtrace_full_callback callback,\n\t\t backtrace_error_callback error_callback ATTRIBUTE_UNUSED,\n\t\t void *data, int *found)\n{\n  const struct xcoff_incl *incl, *bincl;\n  const struct xcoff_func *fn;\n  const b_xcoff_lineno *lineno;\n  const unsigned char *lineptr;\n  const char *function;\n  const char *filename;\n  uintptr_t lnnoptr, match;\n  uint32_t lnno = 0;\n\n  *found = 1;\n\n  if ((pc & 3) != 0)\n    ++pc;\n\n  /* Find the function first.  */\n  fn = ((struct xcoff_func *)\n\tbsearch (&pc, fdata->func_vec.vec.base, fdata->func_vec.count,\n\t\t sizeof (struct xcoff_func), xcoff_func_search));\n  if (fn == NULL)\n    {\n      *found = 0;\n      return 0;\n    }\n\n  filename = fn->filename;\n\n  /* Find the line number next.  */\n\n  /* Skip first entry that points to symtab.  */\n  lnnoptr = fn->lnnoptr + LINESZ;\n  match = lnnoptr;\n\n  lineptr = fdata->linenos + (lnnoptr - fdata->lnnoptr0);\n  while (lineptr + LINESZ <= fdata->linenos + fdata->linenos_size)\n    {\n      lineno = (const b_xcoff_lineno *) lineptr;\n      if (lineno->l_lnno == 0)\n\tbreak;\n      if (pc <= fdata->base_address + lineno->l_addr.l_paddr)\n\tbreak;\n      match = lnnoptr;\n      lnno = lineno->l_lnno;\n\n      lnnoptr += LINESZ;\n      lineptr += LINESZ;\n    }\n\n  /* If part of a function other than the beginning comes from an\n     include file, the line numbers are absolute, rather than\n     relative to the beginning of the function.  */\n  incl = ((struct xcoff_incl *)\n\t  bsearch (&match, fdata->incl_vec.vec.base,\n\t\t   fdata->incl_vec.count, sizeof (struct xcoff_incl),\n\t\t   xcoff_incl_search));\n  if (incl != NULL)\n    {\n      bincl = ((struct xcoff_incl *)\n\t       bsearch (&fn->lnnoptr, fdata->incl_vec.vec.base,\n\t\t\tfdata->incl_vec.count, sizeof (struct xcoff_incl),\n\t\t\txcoff_incl_search));\n      if (bincl != NULL && strcmp (incl->filename, bincl->filename) == 0)\n\t{\n\t  lnno += fn->lnno - 1;\n\t}\n      filename = incl->filename;\n    }\n  else\n    {\n      lnno += fn->lnno - 1;\n    }\n\n  function = fn->name;\n  /* AIX prepends a '.' to function entry points, remove it.  */\n  if (function != NULL && *function == '.')\n    ++function;\n  return callback (data, pc, filename, lnno, function);\n}\n\n/* Return the file/line information for a PC using the XCOFF lineno\n   mapping we built earlier.  */\n\nstatic int\nxcoff_fileline (struct backtrace_state *state, uintptr_t pc,\n\t\tbacktrace_full_callback callback,\n\t\tbacktrace_error_callback error_callback, void *data)\n\n{\n  struct xcoff_fileline_data *fdata;\n  int found;\n  int ret;\n\n  if (!state->threaded)\n    {\n      for (fdata = (struct xcoff_fileline_data *) state->fileline_data;\n\t   fdata != NULL;\n\t   fdata = fdata->next)\n\t{\n\t  ret = xcoff_lookup_pc (state, fdata, pc, callback, error_callback,\n\t\t\t\t data, &found);\n\t  if (ret != 0 || found)\n\t    return ret;\n\t}\n    }\n  else\n    {\n      struct xcoff_fileline_data **pp;\n\n      pp = (struct xcoff_fileline_data **) (void *) &state->fileline_data;\n      while (1)\n\t{\n\t  fdata = backtrace_atomic_load_pointer (pp);\n\t  if (fdata == NULL)\n\t    break;\n\n\t  ret = xcoff_lookup_pc (state, fdata, pc, callback, error_callback,\n\t\t\t\t data, &found);\n\t  if (ret != 0 || found)\n\t    return ret;\n\n\t  pp = &fdata->next;\n\t}\n    }\n\n  /* FIXME: See if any libraries have been dlopen'ed.  */\n\n  return callback (data, pc, NULL, 0, NULL);\n}\n\n/* Initialize the function vector info for xcoff_fileline.  */\n\nstatic int\nxcoff_initialize_fileline (struct backtrace_state *state,\n\t\t\t   uintptr_t base_address,\n\t\t\t   const b_xcoff_scnhdr *sects,\n\t\t\t   const b_xcoff_syment *syms, size_t nsyms,\n\t\t\t   const unsigned char *strtab, size_t strtab_size,\n\t\t\t   const unsigned char *linenos, size_t linenos_size,\n\t\t\t   uint64_t lnnoptr0,\n\t\t\t   backtrace_error_callback error_callback, void *data)\n{\n  struct xcoff_fileline_data *fdata;\n  struct xcoff_func *fn;\n  const b_xcoff_syment *fsym;\n  const b_xcoff_auxent *aux;\n  const char *filename;\n  const char *name;\n  struct xcoff_incl *incl;\n  uintptr_t begin, end;\n  uintptr_t lnno, lnnoptr;\n  uint32_t fsize;\n  size_t i;\n\n  fdata = ((struct xcoff_fileline_data *)\n\t   backtrace_alloc (state, sizeof (struct xcoff_fileline_data),\n\t\t\t    error_callback, data));\n  if (fdata == NULL)\n    return 0;\n  memset (fdata, 0, sizeof *fdata);\n  fdata->base_address = base_address;\n  fdata->linenos = linenos;\n  fdata->linenos_size = linenos_size;\n  fdata->lnnoptr0 = lnnoptr0;\n\n  begin = 0;\n  filename = NULL;\n  fsym = NULL;\n  lnnoptr = 0;\n  fsize = 0;\n  for (i = 0; i < nsyms; ++i)\n    {\n      const b_xcoff_syment *asym = &syms[i];\n\n      switch (asym->n_sclass)\n\t{\n\t  case C_BINCL:\n\t    begin = asym->n_value;\n\t    break;\n\n\t  case C_EINCL:\n\t    if (begin == 0)\n\t      break;\n\t    end = asym->n_value;\n\t    incl = ((struct xcoff_incl *)\n\t\t    backtrace_vector_grow (state, sizeof (struct xcoff_incl),\n\t\t\t\t\t   error_callback, data,\n\t\t\t\t\t   &fdata->incl_vec.vec));\n\t    if (incl != NULL)\n\t      {\n\t\tincl->filename = xcoff_symname (asym, strtab, strtab_size);\n\t\tincl->begin = begin;\n\t\tincl->end = end;\n\t\t++fdata->incl_vec.count;\n\t      }\n\t    begin = 0;\n\t    break;\n\n\t  case C_FILE:\n\t    filename = xcoff_symname (asym, strtab, strtab_size);\n\t    if (filename == NULL)\n\t      break;\n\n\t    /* If the file auxiliary entry is not used, the symbol name is\n\t       the name of the source file. If the file auxiliary entry is\n\t       used, then the symbol name should be .file, and the first\n\t       file auxiliary entry (by convention) contains the source\n\t       file name.  */\n\n\t    if (asym->n_numaux > 0 && strcmp (filename, \".file\") == 0)\n\t      {\n\t\taux = (const b_xcoff_auxent *) (asym + 1);\n\t\tif (aux->x_file._x.x_zeroes != 0)\n\t\t  {\n\t\t    /* Make a copy as we will release the symtab view.  */\n\t\t    char name[FILNMLEN+1];\n\t\t    strncpy (name, aux->x_file.x_fname, FILNMLEN);\n\t\t    name[FILNMLEN] = '\\0';\n\t\t    filename = strdup (name);\n\t\t  }\n\t\telse if (aux->x_file._x.x_offset < strtab_size)\n\t\t  filename = (const char *) strtab + aux->x_file._x.x_offset;\n\t\telse\n\t\t  filename = NULL;\n\t      }\n\t    break;\n\n\t  case C_EXT:\n\t  case C_HIDEXT:\n\t  case C_WEAKEXT:\n\t    fsym = NULL;\n\t    lnnoptr = 0;\n\t    fsize = 0;\n\t    if (!ISFCN (asym->n_type) || asym->n_numaux == 0\n\t\t|| asym->n_scnum <= 0)\n\t      break;\n\t    if (filename == NULL)\n\t      break;\n\t    aux = (const b_xcoff_auxent *) (asym + 1);\n\t    lnnoptr = aux->x_fcn.x_lnnoptr;\n\t    if (lnnoptr < lnnoptr0\n\t\t|| lnnoptr + LINESZ > lnnoptr0 + linenos_size)\n\t      break;\n\t    /* x_fsize will be 0 if there is no debug information.  */\n\t    fsize = aux->x_fcn.x_fsize;\n\t    fsym = asym;\n\t    break;\n\n\t  case C_FCN:\n\t    if (asym->n_numaux == 0)\n\t      break;\n\t    if (fsym == NULL)\n\t      break;\n\t    name = xcoff_symname (asym, strtab, strtab_size);\n\t    if (name == NULL || strcmp (name, \".bf\") != 0)\n\t      {\n\t\tfsym = NULL;\n\t\tbreak;\n\t      }\n\t    aux = (const b_xcoff_auxent *) (asym + 1);\n#if BACKTRACE_XCOFF_SIZE == 32\n\t    lnno = (uint32_t) aux->x_block.x_lnnohi << 16\n\t\t | aux->x_block.x_lnno;\n#else\n\t    lnno = aux->x_block.x_lnno;\n#endif\n\t    fn = ((struct xcoff_func *)\n\t\t  backtrace_vector_grow (state, sizeof (struct xcoff_func),\n\t\t\t\t\t error_callback, data,\n\t\t\t\t\t &fdata->func_vec.vec));\n\t    if (fn == NULL)\n\t      break;\n\t    fn->name = xcoff_symname (fsym, strtab, strtab_size);\n\t    fn->filename = filename;\n\t    fn->sect_base = sects[fsym->n_scnum - 1].s_paddr;\n\t    fn->pc = base_address + fsym->n_value;\n\t    fn->size = fsize;\n\t    fn->lnno = lnno;\n\t    fn->lnnoptr = lnnoptr;\n\t    ++fdata->func_vec.count;\n\t    break;\n\t}\n\n      i += asym->n_numaux;\n    }\n\n  if (!backtrace_vector_release (state, &fdata->func_vec.vec, error_callback,\n\t\t\t\t data))\n    goto fail;\n  backtrace_qsort (fdata->func_vec.vec.base, fdata->func_vec.count,\n\t\t   sizeof (struct xcoff_func), xcoff_func_compare);\n\n  if (!backtrace_vector_release (state, &fdata->incl_vec.vec, error_callback,\n\t\t\t\t data))\n    goto fail;\n  backtrace_qsort (fdata->incl_vec.vec.base, fdata->incl_vec.count,\n\t\t   sizeof (struct xcoff_incl), xcoff_incl_compare);\n\n  if (!state->threaded)\n    {\n      struct xcoff_fileline_data **pp;\n\n      for (pp = (struct xcoff_fileline_data **) (void *) &state->fileline_data;\n\t   *pp != NULL;\n\t   pp = &(*pp)->next)\n\t;\n      *pp = fdata;\n    }\n  else\n    {\n      while (1)\n\t{\n\t  struct xcoff_fileline_data **pp;\n\n\t  pp = (struct xcoff_fileline_data **) (void *) &state->fileline_data;\n\n\t  while (1)\n\t    {\n\t      struct xcoff_fileline_data *p;\n\n\t      p = backtrace_atomic_load_pointer (pp);\n\n\t      if (p == NULL)\n\t\tbreak;\n\n\t      pp = &p->next;\n\t    }\n\n\t  if (__sync_bool_compare_and_swap (pp, NULL, fdata))\n\t    break;\n\t}\n    }\n\n  return 1;\n\nfail:\n  return 0;\n}\n\n/* Add the backtrace data for one XCOFF file.  Returns 1 on success,\n   0 on failure (in both cases descriptor is closed).  */\n\nstatic int\nxcoff_add (struct backtrace_state *state, int descriptor, off_t offset,\n\t   uintptr_t base_address, backtrace_error_callback error_callback,\n\t   void *data, fileline *fileline_fn, int *found_sym, int exe)\n{\n  struct backtrace_view fhdr_view;\n  struct backtrace_view sects_view;\n  struct backtrace_view linenos_view;\n  struct backtrace_view syms_view;\n  struct backtrace_view str_view;\n  struct backtrace_view dwarf_view;\n  b_xcoff_filhdr fhdr;\n  const b_xcoff_scnhdr *sects;\n  const b_xcoff_scnhdr *stext;\n  uint64_t lnnoptr;\n  uint32_t nlnno;\n  off_t str_off;\n  off_t min_offset;\n  off_t max_offset;\n  struct dwsect_info dwsect[DEBUG_MAX];\n  size_t sects_size;\n  size_t syms_size;\n  int32_t str_size;\n  int sects_view_valid;\n  int linenos_view_valid;\n  int syms_view_valid;\n  int str_view_valid;\n  int dwarf_view_valid;\n  int magic_ok;\n  int i;\n  struct dwarf_sections dwarf_sections;\n\n  *found_sym = 0;\n\n  sects_view_valid = 0;\n  linenos_view_valid = 0;\n  syms_view_valid = 0;\n  str_view_valid = 0;\n  dwarf_view_valid = 0;\n\n  str_size = 0;\n\n  /* Map the XCOFF file header.  */\n  if (!backtrace_get_view (state, descriptor, offset, sizeof (b_xcoff_filhdr),\n\t\t\t   error_callback, data, &fhdr_view))\n    goto fail;\n\n  memcpy (&fhdr, fhdr_view.data, sizeof fhdr);\n  magic_ok = (fhdr.f_magic == XCOFF_MAGIC);\n\n  backtrace_release_view (state, &fhdr_view, error_callback, data);\n\n  if (!magic_ok)\n    {\n      if (exe)\n\terror_callback (data, \"executable file is not XCOFF\", 0);\n      goto fail;\n    }\n\n  /* Verify object is of expected type.  */\n  if ((exe && (fhdr.f_flags & F_SHROBJ))\n      || (!exe && !(fhdr.f_flags & F_SHROBJ)))\n    goto fail;\n\n  /* Read the section headers.  */\n\n  sects_size = fhdr.f_nscns * sizeof (b_xcoff_scnhdr);\n\n  if (!backtrace_get_view (state, descriptor,\n\t\t\t   offset + sizeof (fhdr) + fhdr.f_opthdr,\n\t\t\t   sects_size, error_callback, data, &sects_view))\n    goto fail;\n  sects_view_valid = 1;\n  sects = (const b_xcoff_scnhdr *) sects_view.data;\n\n  /* FIXME: assumes only one .text section.  */\n  for (i = 0; i < fhdr.f_nscns; ++i)\n    if ((sects[i].s_flags & 0xffff) == STYP_TEXT)\n      break;\n  if (i == fhdr.f_nscns)\n    goto fail;\n\n  stext = &sects[i];\n\n  /* base_address represents the difference between the\n     virtual memory address of the shared object or a loaded\n     executable and the offset of that object in the file\n     from which it was loaded.\n     On AIX, virtual address is either fixed for executable\n     or given by ldinfo.  This address will include the XCOFF\n     headers.  */\n  base_address = ((exe ? XCOFF_AIX_TEXTBASE : base_address)\n\t\t  + stext->s_scnptr\n\t\t  - stext->s_paddr);\n\n  lnnoptr = stext->s_lnnoptr;\n  nlnno = stext->s_nlnno;\n\n#if BACKTRACE_XCOFF_SIZE == 32\n  if (nlnno == _OVERFLOW_MARKER)\n    {\n      int sntext = i + 1;\n      /* Find the matching .ovrflo section.  */\n      for (i = 0; i < fhdr.f_nscns; ++i)\n\t{\n\t  if (((sects[i].s_flags & 0xffff) == STYP_OVRFLO)\n\t      && sects[i].s_nlnno == sntext)\n\t    {\n\t      nlnno = sects[i].s_vaddr;\n\t      break;\n\t    }\n\t}\n    }\n#endif\n\n  /* Read the symbol table and the string table.  */\n\n  if (fhdr.f_symptr != 0)\n    {\n      struct xcoff_syminfo_data *sdata;\n\n      /* Symbol table is followed by the string table.  The string table\n\t starts with its length (on 4 bytes).\n\t Map the symbol table and the length of the string table.  */\n      syms_size = fhdr.f_nsyms * sizeof (b_xcoff_syment);\n\n      if (!backtrace_get_view (state, descriptor, offset + fhdr.f_symptr,\n\t\t\t       syms_size + 4, error_callback, data,\n\t\t\t       &syms_view))\n\tgoto fail;\n      syms_view_valid = 1;\n\n      memcpy (&str_size, syms_view.data + syms_size, 4);\n\n      str_off = fhdr.f_symptr + syms_size;\n\n      if (str_size > 4)\n\t{\n\t  /* Map string table (including the length word).  */\n\n\t  if (!backtrace_get_view (state, descriptor, offset + str_off,\n\t\t\t\t   str_size, error_callback, data, &str_view))\n\t    goto fail;\n\t  str_view_valid = 1;\n\t}\n\n      sdata = ((struct xcoff_syminfo_data *)\n\t       backtrace_alloc (state, sizeof *sdata, error_callback, data));\n      if (sdata == NULL)\n\tgoto fail;\n\n      if (!xcoff_initialize_syminfo (state, base_address,\n\t\t\t\t     syms_view.data, fhdr.f_nsyms,\n\t\t\t\t     str_view.data, str_size,\n\t\t\t\t     error_callback, data, sdata))\n\t{\n\t  backtrace_free (state, sdata, sizeof *sdata, error_callback, data);\n\t  goto fail;\n\t}\n\n      *found_sym = 1;\n\n      xcoff_add_syminfo_data (state, sdata);\n    }\n\n  /* Read all the DWARF sections in a single view, since they are\n     probably adjacent in the file.  We never release this view.  */\n\n  min_offset = 0;\n  max_offset = 0;\n  memset (dwsect, 0, sizeof dwsect);\n  for (i = 0; i < fhdr.f_nscns; ++i)\n    {\n      off_t end;\n      int idx;\n\n      if ((sects[i].s_flags & 0xffff) != STYP_DWARF\n\t  || sects[i].s_size == 0)\n\tcontinue;\n      /* Map DWARF section to array index.  */\n      switch (sects[i].s_flags & 0xffff0000)\n\t{\n\t  case SSUBTYP_DWINFO:\n\t    idx = DEBUG_INFO;\n\t    break;\n\t  case SSUBTYP_DWLINE:\n\t    idx = DEBUG_LINE;\n\t    break;\n\t  case SSUBTYP_DWABREV:\n\t    idx = DEBUG_ABBREV;\n\t    break;\n\t  case SSUBTYP_DWRNGES:\n\t    idx = DEBUG_RANGES;\n\t    break;\n\t  case SSUBTYP_DWSTR:\n\t    idx = DEBUG_STR;\n\t    break;\n\t  default:\n\t    continue;\n\t}\n      if (min_offset == 0 || (off_t) sects[i].s_scnptr < min_offset)\n\tmin_offset = sects[i].s_scnptr;\n      end = sects[i].s_scnptr + sects[i].s_size;\n      if (end > max_offset)\n\tmax_offset = end;\n      dwsect[idx].offset = sects[i].s_scnptr;\n      dwsect[idx].size = sects[i].s_size;\n    }\n  if (min_offset != 0 && max_offset != 0)\n    {\n      if (!backtrace_get_view (state, descriptor, offset + min_offset,\n\t\t\t       max_offset - min_offset,\n\t\t\t       error_callback, data, &dwarf_view))\n\tgoto fail;\n      dwarf_view_valid = 1;\n\n      for (i = 0; i < (int) DEBUG_MAX; ++i)\n\t{\n\t  if (dwsect[i].offset == 0)\n\t    dwsect[i].data = NULL;\n\t  else\n\t    dwsect[i].data = ((const unsigned char *) dwarf_view.data\n\t\t\t      + (dwsect[i].offset - min_offset));\n\t}\n\n      memset (&dwarf_sections, 0, sizeof dwarf_sections);\n\n      dwarf_sections.data[DEBUG_INFO] = dwsect[DEBUG_INFO].data;\n      dwarf_sections.size[DEBUG_INFO] = dwsect[DEBUG_INFO].size;\n      dwarf_sections.data[DEBUG_LINE] = dwsect[DEBUG_LINE].data;\n      dwarf_sections.size[DEBUG_LINE] = dwsect[DEBUG_LINE].size;\n      dwarf_sections.data[DEBUG_ABBREV] = dwsect[DEBUG_ABBREV].data;\n      dwarf_sections.size[DEBUG_ABBREV] = dwsect[DEBUG_ABBREV].size;\n      dwarf_sections.data[DEBUG_RANGES] = dwsect[DEBUG_RANGES].data;\n      dwarf_sections.size[DEBUG_RANGES] = dwsect[DEBUG_RANGES].size;\n      dwarf_sections.data[DEBUG_STR] = dwsect[DEBUG_STR].data;\n      dwarf_sections.size[DEBUG_STR] = dwsect[DEBUG_STR].size;\n\n      if (!backtrace_dwarf_add (state, base_address, &dwarf_sections,\n\t\t\t\t1, /* big endian */\n\t\t\t\tNULL, /* altlink */\n\t\t\t\terror_callback, data, fileline_fn,\n\t\t\t\tNULL /* returned fileline_entry */))\n\tgoto fail;\n    }\n\n  /* Read the XCOFF line number entries if DWARF sections not found.  */\n\n  if (!dwarf_view_valid && fhdr.f_symptr != 0 && lnnoptr != 0)\n    {\n      size_t linenos_size = (size_t) nlnno * LINESZ;\n\n      /* We never release this view.  */\n      if (!backtrace_get_view (state, descriptor, offset + lnnoptr,\n\t\t\t       linenos_size,\n\t\t\t       error_callback, data, &linenos_view))\n\tgoto fail;\n      linenos_view_valid = 1;\n\n      if (xcoff_initialize_fileline (state, base_address, sects,\n\t\t\t\t     syms_view.data, fhdr.f_nsyms,\n\t\t\t\t     str_view.data, str_size,\n\t\t\t\t     linenos_view.data, linenos_size,\n\t\t\t\t     lnnoptr, error_callback, data))\n\t*fileline_fn = xcoff_fileline;\n    }\n\n  backtrace_release_view (state, &sects_view, error_callback, data);\n  sects_view_valid = 0;\n  if (syms_view_valid)\n    backtrace_release_view (state, &syms_view, error_callback, data);\n  syms_view_valid = 0;\n\n  /* We've read all we need from the executable.  */\n  if (!backtrace_close (descriptor, error_callback, data))\n    goto fail;\n  descriptor = -1;\n\n  return 1;\n\n fail:\n  if (sects_view_valid)\n    backtrace_release_view (state, &sects_view, error_callback, data);\n  if (str_view_valid)\n    backtrace_release_view (state, &str_view, error_callback, data);\n  if (syms_view_valid)\n    backtrace_release_view (state, &syms_view, error_callback, data);\n  if (linenos_view_valid)\n    backtrace_release_view (state, &linenos_view, error_callback, data);\n  if (dwarf_view_valid)\n    backtrace_release_view (state, &dwarf_view, error_callback, data);\n  if (descriptor != -1 && offset == 0)\n    backtrace_close (descriptor, error_callback, data);\n  return 0;\n}\n\n#ifdef HAVE_LOADQUERY\n\n/* Read an integer value in human-readable format from an AIX\n   big archive fixed-length or member header.  */\n\nstatic int\nxcoff_parse_decimal (const char *buf, size_t size, off_t *off)\n{\n  char str[32];\n  char *end;\n\n  if (size >= sizeof str)\n    return 0;\n  memcpy (str, buf, size);\n  str[size] = '\\0';\n  *off = strtol (str, &end, 10);\n  if (*end != '\\0' && *end != ' ')\n    return 0;\n\n  return 1;\n}\n\n/* Add the backtrace data for a member of an AIX big archive.\n   Returns 1 on success, 0 on failure.  */\n\nstatic int\nxcoff_armem_add (struct backtrace_state *state, int descriptor,\n\t\t uintptr_t base_address, const char *member,\n\t\t backtrace_error_callback error_callback, void *data,\n\t\t fileline *fileline_fn, int *found_sym)\n{\n  struct backtrace_view view;\n  b_ar_fl_hdr fl_hdr;\n  const b_ar_hdr *ar_hdr;\n  off_t off;\n  off_t len;\n  int memlen;\n\n  *found_sym = 0;\n\n  /* Map archive fixed-length header.  */\n\n  if (!backtrace_get_view (state, descriptor, 0, sizeof (b_ar_fl_hdr),\n\t\t\t   error_callback, data, &view))\n    goto fail;\n\n  memcpy (&fl_hdr, view.data, sizeof (b_ar_fl_hdr));\n\n  backtrace_release_view (state, &view, error_callback, data);\n\n  if (memcmp (fl_hdr.fl_magic, AIAMAGBIG, 8) != 0)\n    goto fail;\n\n  memlen = strlen (member);\n\n  /* Read offset of first archive member.  */\n  if (!xcoff_parse_decimal (fl_hdr.fl_fstmoff, sizeof fl_hdr.fl_fstmoff, &off))\n    goto fail;\n  while (off != 0)\n    {\n      /* Map archive member header and member name.  */\n\n      if (!backtrace_get_view (state, descriptor, off,\n\t\t\t       sizeof (b_ar_hdr) + memlen,\n\t\t\t       error_callback, data, &view))\n\tbreak;\n\n      ar_hdr = (const b_ar_hdr *) view.data;\n\n      /* Read archive member name length.  */\n      if (!xcoff_parse_decimal (ar_hdr->ar_namlen, sizeof ar_hdr->ar_namlen,\n\t\t\t\t&len))\n\t{\n\t  backtrace_release_view (state, &view, error_callback, data);\n\t  break;\n\t}\n      if (len == memlen && !memcmp (ar_hdr->ar_name, member, memlen))\n\t{\n\t  off = (off + sizeof (b_ar_hdr) + memlen + 1) & ~1;\n\n\t  /* The archive can contain several members with the same name\n\t     (e.g. 32-bit and 64-bit), so continue if not ok.  */\n\n\t  if (xcoff_add (state, descriptor, off, base_address, error_callback,\n\t\t\t data, fileline_fn, found_sym, 0))\n\t    {\n\t      backtrace_release_view (state, &view, error_callback, data);\n\t      return 1;\n\t    }\n\t}\n\n      /* Read offset of next archive member.  */\n      if (!xcoff_parse_decimal (ar_hdr->ar_nxtmem, sizeof ar_hdr->ar_nxtmem,\n\t\t\t\t&off))\n\t{\n\t  backtrace_release_view (state, &view, error_callback, data);\n\t  break;\n\t}\n      backtrace_release_view (state, &view, error_callback, data);\n    }\n\n fail:\n  /* No matching member found.  */\n  backtrace_close (descriptor, error_callback, data);\n  return 0;\n}\n\n/* Add the backtrace data for dynamically loaded libraries.  */\n\nstatic void\nxcoff_add_shared_libs (struct backtrace_state *state,\n\t\t       backtrace_error_callback error_callback,\n\t\t       void *data, fileline *fileline_fn, int *found_sym)\n{\n  const struct ld_info *ldinfo;\n  void *buf;\n  unsigned int buflen;\n  const char *member;\n  int descriptor;\n  int does_not_exist;\n  int lib_found_sym;\n  int ret;\n\n  /* Retrieve the list of loaded libraries.  */\n\n  buf = NULL;\n  buflen = 512;\n  do\n    {\n      buf = realloc (buf, buflen);\n      if (buf == NULL)\n\t{\n\t  ret = -1;\n\t  break;\n\t}\n      ret = loadquery (L_GETINFO, buf, buflen);\n      if (ret == 0)\n\tbreak;\n      buflen *= 2;\n    }\n  while (ret == -1 && errno == ENOMEM);\n  if (ret != 0)\n    {\n      free (buf);\n      return;\n    }\n\n  ldinfo = (const struct ld_info *) buf;\n  while ((const char *) ldinfo < (const char *) buf + buflen)\n    {\n      if (*ldinfo->ldinfo_filename != '/')\n\tgoto next;\n\n      descriptor = backtrace_open (ldinfo->ldinfo_filename, error_callback,\n\t\t\t\t   data, &does_not_exist);\n      if (descriptor < 0)\n\tgoto next;\n\n      /* Check if it is an archive (member name not empty).  */\n\n      member = ldinfo->ldinfo_filename + strlen (ldinfo->ldinfo_filename) + 1;\n      if (*member)\n\t{\n\t  xcoff_armem_add (state, descriptor,\n\t\t\t   (uintptr_t) ldinfo->ldinfo_textorg, member,\n\t\t\t   error_callback, data, fileline_fn, &lib_found_sym);\n\t}\n      else\n\t{\n\t  xcoff_add (state, descriptor, 0, (uintptr_t) ldinfo->ldinfo_textorg,\n\t\t     error_callback, data, fileline_fn, &lib_found_sym, 0);\n\t}\n      if (lib_found_sym)\n\t*found_sym = 1;\n\n next:\n      if (ldinfo->ldinfo_next == 0)\n\tbreak;\n      ldinfo = (const struct ld_info *) ((const char *) ldinfo\n\t\t\t\t\t + ldinfo->ldinfo_next);\n    }\n\n    free (buf);\n}\n#endif /* HAVE_LOADQUERY */\n\n/* Initialize the backtrace data we need from an XCOFF executable.\n   Returns 1 on success, 0 on failure.  */\n\nint\nbacktrace_initialize (struct backtrace_state *state,\n\t\t      const char *filename ATTRIBUTE_UNUSED, int descriptor,\n\t\t      backtrace_error_callback error_callback,\n\t\t      void *data, fileline *fileline_fn)\n{\n  int ret;\n  int found_sym;\n  fileline xcoff_fileline_fn = xcoff_nodebug;\n\n  ret = xcoff_add (state, descriptor, 0, 0, error_callback, data,\n\t\t   &xcoff_fileline_fn, &found_sym, 1);\n  if (!ret)\n    return 0;\n\n#ifdef HAVE_LOADQUERY\n  xcoff_add_shared_libs (state, error_callback, data, &xcoff_fileline_fn,\n\t\t\t &found_sym);\n#endif\n\n  if (!state->threaded)\n    {\n      if (found_sym)\n\tstate->syminfo_fn = xcoff_syminfo;\n      else if (state->syminfo_fn == NULL)\n\tstate->syminfo_fn = xcoff_nosyms;\n    }\n  else\n    {\n      if (found_sym)\n\tbacktrace_atomic_store_pointer (&state->syminfo_fn, xcoff_syminfo);\n      else\n\t(void) __sync_bool_compare_and_swap (&state->syminfo_fn, NULL,\n\t\t\t\t\t     xcoff_nosyms);\n    }\n\n  if (!state->threaded)\n    {\n      if (state->fileline_fn == NULL || state->fileline_fn == xcoff_nodebug)\n\t*fileline_fn = xcoff_fileline_fn;\n    }\n  else\n    {\n      fileline current_fn;\n\n      current_fn = backtrace_atomic_load_pointer (&state->fileline_fn);\n      if (current_fn == NULL || current_fn == xcoff_nodebug)\n\t*fileline_fn = xcoff_fileline_fn;\n    }\n\n  return 1;\n}\n"
  },
  {
    "path": "src/vendor/libbacktrace/xztest.c",
    "content": "/* xztest.c -- Test for libbacktrace LZMA decoder.\n   Copyright (C) 2020-2024 Free Software Foundation, Inc.\n   Written by Ian Lance Taylor, Google.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n    (1) Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n\n    (2) Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in\n    the documentation and/or other materials provided with the\n    distribution.\n\n    (3) The name of the author may not be used to\n    endorse or promote products derived from this software without\n    specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\nIMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,\nINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\nHOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\nIN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGE.  */\n\n#include \"config.h\"\n\n#include <errno.h>\n#include <limits.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <time.h>\n#include <sys/types.h>\n#include <sys/stat.h>\n\n#ifdef HAVE_LIBLZMA\n#include <lzma.h>\n#endif\n\n#include \"backtrace.h\"\n#include \"backtrace-supported.h\"\n\n#include \"internal.h\"\n#include \"testlib.h\"\n\n#ifndef HAVE_CLOCK_GETTIME\n\ntypedef int xclockid_t;\n\nstatic int\nxclock_gettime (xclockid_t id ATTRIBUTE_UNUSED,\n\t\tstruct timespec *ts ATTRIBUTE_UNUSED)\n{\n  errno = EINVAL;\n  return -1;\n}\n\n#define clockid_t xclockid_t\n#define clock_gettime xclock_gettime\n#undef CLOCK_REALTIME\n#define CLOCK_REALTIME 0\n\n#endif /* !defined(HAVE_CLOCK_GETTIME) */\n\n#ifdef CLOCK_PROCESS_CPUTIME_ID\n#define LIBLZMA_CLOCK_GETTIME_ARG CLOCK_PROCESS_CPUTIME_ID\n#else\n#define LIBLZMA_CLOCK_GETTIME_ARG CLOCK_REALTIME\n#endif\n\n/* Some tests for the local lzma inflation code.  */\n\nstruct lzma_test\n{\n  const char *name;\n  const char *uncompressed;\n  size_t uncompressed_len;\n  const char *compressed;\n  size_t compressed_len;\n};\n\n/* Error callback.  */\n\nstatic void\nerror_callback_compress (void *vdata ATTRIBUTE_UNUSED, const char *msg,\n\t\t\t int errnum)\n{\n  fprintf (stderr, \"%s\", msg);\n  if (errnum > 0)\n    fprintf (stderr, \": %s\", strerror (errnum));\n  fprintf (stderr, \"\\n\");\n  exit (EXIT_FAILURE);\n}\n\nstatic const struct lzma_test tests[] =\n{\n  {\n    \"empty\",\n    \"\",\n    0,\n    (\"\\xfd\\x37\\x7a\\x58\\x5a\\x00\\x00\\x04\\xe6\\xd6\\xb4\\x46\\x00\\x00\\x00\\x00\"\n     \"\\x1c\\xdf\\x44\\x21\\x1f\\xb6\\xf3\\x7d\\x01\\x00\\x00\\x00\\x00\\x04\\x59\\x5a\"),\n    32,\n  },\n  {\n    \"hello\",\n    \"hello, world\\n\",\n    0,\n    (\"\\xfd\\x37\\x7a\\x58\\x5a\\x00\\x00\\x04\\xe6\\xd6\\xb4\\x46\\x02\\x00\\x21\\x01\"\n     \"\\x16\\x00\\x00\\x00\\x74\\x2f\\xe5\\xa3\\x01\\x00\\x0c\\x68\\x65\\x6c\\x6c\\x6f\"\n     \"\\x2c\\x20\\x77\\x6f\\x72\\x6c\\x64\\x0a\\x00\\x00\\x00\\x00\\x7b\\x46\\x5a\\x81\"\n     \"\\xc9\\x12\\xb8\\xea\\x00\\x01\\x25\\x0d\\x71\\x19\\xc4\\xb6\\x1f\\xb6\\xf3\\x7d\"\n     \"\\x01\\x00\\x00\\x00\\x00\\x04\\x59\\x5a\"),\n    72,\n  },\n  {\n    \"goodbye\",\n    \"goodbye, world\",\n    0,\n    (\"\\xfd\\x37\\x7a\\x58\\x5a\\x00\\x00\\x04\\xe6\\xd6\\xb4\\x46\\x02\\x00\\x21\\x01\"\n     \"\\x16\\x00\\x00\\x00\\x74\\x2f\\xe5\\xa3\\x01\\x00\\x0d\\x67\\x6f\\x6f\\x64\\x62\"\n     \"\\x79\\x65\\x2c\\x20\\x77\\x6f\\x72\\x6c\\x64\\x00\\x00\\x00\\xf6\\xf8\\xa3\\x33\"\n     \"\\x8c\\x4e\\xc9\\x68\\x00\\x01\\x26\\x0e\\x08\\x1b\\xe0\\x04\\x1f\\xb6\\xf3\\x7d\"\n     \"\\x01\\x00\\x00\\x00\\x00\\x04\\x59\\x5a\"),\n    72,\n  },\n};\n\n/* Test the hand coded samples.  */\n\nstatic void\ntest_samples (struct backtrace_state *state)\n{\n  size_t i;\n\n  for (i = 0; i < sizeof tests / sizeof tests[0]; ++i)\n    {\n      unsigned char *uncompressed;\n      size_t uncompressed_len;\n\n      uncompressed = NULL;\n      uncompressed_len = 0;\n      if (!backtrace_uncompress_lzma (state,\n\t\t\t\t      ((const unsigned char *)\n\t\t\t\t       tests[i].compressed),\n\t\t\t\t      tests[i].compressed_len,\n\t\t\t\t      error_callback_compress, NULL,\n\t\t\t\t      &uncompressed, &uncompressed_len))\n\t{\n\t  fprintf (stderr, \"test %s: uncompress failed\\n\", tests[i].name);\n\t  ++failures;\n\t}\n      else\n\t{\n\t  size_t v;\n\n\t  v = tests[i].uncompressed_len;\n\t  if (v == 0)\n\t    v = strlen (tests[i].uncompressed);\n\t  if (uncompressed_len != v)\n\t    {\n\t      fprintf (stderr,\n\t\t       \"test %s: got uncompressed length %zu, want %zu\\n\",\n\t\t       tests[i].name, uncompressed_len, v);\n\t      ++failures;\n\t    }\n\t  else if (v > 0 && memcmp (tests[i].uncompressed, uncompressed, v) != 0)\n\t    {\n\t      size_t j;\n\n\t      fprintf (stderr, \"test %s: uncompressed data mismatch\\n\",\n\t\t       tests[i].name);\n\t      for (j = 0; j < v; ++j)\n\t\tif (tests[i].uncompressed[j] != uncompressed[j])\n\t\t  fprintf (stderr, \"  %zu: got %#x want %#x\\n\", j,\n\t\t\t   uncompressed[j], tests[i].uncompressed[j]);\n\t      ++failures;\n\t    }\n\t  else\n\t    printf (\"PASS: lzma %s\\n\", tests[i].name);\n\n\t  backtrace_free (state, uncompressed, uncompressed_len,\n\t\t\t  error_callback_compress, NULL);\n\t}\n    }\n}\n\n#if HAVE_LIBLZMA\n\n/* Given a set of TRIALS timings, discard the lowest and highest\n   values and return the mean average of the rest.  */\n\nstatic size_t\naverage_time (const size_t *times, size_t trials)\n{\n  size_t imax;\n  size_t max;\n  size_t imin;\n  size_t min;\n  size_t i;\n  size_t sum;\n\n  imin = 0;\n  imax = 0;\n  min = times[0];\n  max = times[0];\n  for (i = 1; i < trials; ++i)\n    {\n      if (times[i] < min)\n\t{\n\t  imin = i;\n\t  min = times[i];\n\t}\n      if (times[i] > max)\n\t{\n\t  imax = i;\n\t  max = times[i];\n\t}\n    }\n\n  sum = 0;\n  for (i = 0; i < trials; ++i)\n    {\n      if (i != imax && i != imin)\n\tsum += times[i];\n    }\n  return sum / (trials - 2);\n}\n\n#endif\n\n/* Test a larger text, if available.  */\n\nstatic void\ntest_large (struct backtrace_state *state ATTRIBUTE_UNUSED)\n{\n#if HAVE_LIBLZMA\n  unsigned char *orig_buf;\n  size_t orig_bufsize;\n  size_t i;\n  lzma_stream initial_stream = LZMA_STREAM_INIT;\n  lzma_stream stream;\n  unsigned char *compressed_buf;\n  size_t compressed_bufsize;\n  unsigned char *uncompressed_buf;\n  size_t uncompressed_bufsize;\n  unsigned char *spare_buf;\n  int r;\n  clockid_t cid;\n  struct timespec ts1;\n  struct timespec ts2;\n  size_t ctime;\n  size_t ztime;\n  const size_t trials = 16;\n  size_t ctimes[16];\n  size_t ztimes[16];\n  static const char * const names[] = {\n    \"Isaac.Newton-Opticks.txt\",\n    \"../libgo/go/testdata/Isaac.Newton-Opticks.txt\",\n  };\n\n  orig_buf = NULL;\n  orig_bufsize = 0;\n  uncompressed_buf = NULL;\n  compressed_buf = NULL;\n\n  for (i = 0; i < sizeof names / sizeof names[0]; ++i)\n    {\n      size_t len;\n      char *namebuf;\n      FILE *e;\n      struct stat st;\n      char *rbuf;\n      size_t got;\n\n      len = strlen (SRCDIR) + strlen (names[i]) + 2;\n      namebuf = malloc (len);\n      if (namebuf == NULL)\n\t{\n\t  perror (\"malloc\");\n\t  goto fail;\n\t}\n      snprintf (namebuf, len, \"%s/%s\", SRCDIR, names[i]);\n      e = fopen (namebuf, \"r\");\n      free (namebuf);\n      if (e == NULL)\n\tcontinue;\n      if (fstat (fileno (e), &st) < 0)\n\t{\n\t  perror (\"fstat\");\n\t  fclose (e);\n\t  continue;\n\t}\n      rbuf = malloc (st.st_size);\n      if (rbuf == NULL)\n\t{\n\t  perror (\"malloc\");\n\t  goto fail;\n\t}\n      got = fread (rbuf, 1, st.st_size, e);\n      fclose (e);\n      if (got > 0)\n\t{\n\t  orig_buf = (unsigned char *) rbuf;\n\t  orig_bufsize = got;\n\t  break;\n\t}\n      free (rbuf);\n    }\n\n  if (orig_buf == NULL)\n    {\n      /* We couldn't find an input file.  */\n      printf (\"UNSUPPORTED: lzma large\\n\");\n      return;\n    }\n\n  stream = initial_stream;\n  r =  lzma_easy_encoder (&stream, 6, LZMA_CHECK_CRC32);\n  if (r != LZMA_OK)\n    {\n      fprintf (stderr, \"lzma_easy_encoder failed: %d\\n\", r);\n      goto fail;\n    }\n\n  compressed_bufsize = orig_bufsize + 100;\n  compressed_buf = malloc (compressed_bufsize);\n  if (compressed_buf == NULL)\n    {\n      perror (\"malloc\");\n      goto fail;\n    }\n\n  stream.next_in = orig_buf;\n  stream.avail_in = orig_bufsize;\n  stream.next_out = compressed_buf;\n  stream.avail_out = compressed_bufsize;\n\n  do\n    {\n      r = lzma_code (&stream, LZMA_FINISH);\n      if (r != LZMA_OK && r != LZMA_STREAM_END)\n\t{\n\t  fprintf (stderr, \"lzma_code failed: %d\\n\", r);\n\t  goto fail;\n\t}\n    }\n  while (r != LZMA_STREAM_END);\n\n  compressed_bufsize = stream.total_out;\n\n  if (!backtrace_uncompress_lzma (state, (unsigned char *) compressed_buf,\n\t\t\t\t  compressed_bufsize,\n\t\t\t\t  error_callback_compress, NULL,\n\t\t\t\t  &uncompressed_buf, &uncompressed_bufsize))\n    {\n      fprintf (stderr, \"lzma large: backtrace_uncompress_lzma failed\\n\");\n      goto fail;\n    }\n\n  if (uncompressed_bufsize != orig_bufsize)\n    {\n      fprintf (stderr,\n\t       \"lzma large: got uncompressed length %zu, want %zu\\n\",\n\t       uncompressed_bufsize, orig_bufsize);\n      goto fail;\n    }\n\n  if (memcmp (uncompressed_buf, orig_buf, uncompressed_bufsize) != 0)\n    {\n      fprintf (stderr, \"lzma large: uncompressed data mismatch\\n\");\n      goto fail;\n    }\n\n  printf (\"PASS: lzma large\\n\");\n\n  spare_buf = malloc (orig_bufsize);\n  if (spare_buf == NULL)\n    {\n      perror (\"malloc\");\n      goto fail;\n    }\n\n  for (i = 0; i < trials; ++i)\n    {\n      cid = LIBLZMA_CLOCK_GETTIME_ARG;\n      if (clock_gettime (cid, &ts1) < 0)\n\t{\n\t  if (errno == EINVAL)\n\t    return;\n\t  perror (\"clock_gettime\");\n\t  return;\n\t}\n\n      if (!backtrace_uncompress_lzma (state,\n\t\t\t\t      (unsigned char *) compressed_buf,\n\t\t\t\t      compressed_bufsize,\n\t\t\t\t      error_callback_compress, NULL,\n\t\t\t\t      &uncompressed_buf,\n\t\t\t\t      &uncompressed_bufsize))\n\t{\n\t  fprintf (stderr,\n\t\t   (\"lzma large: \"\n\t\t    \"benchmark backtrace_uncompress_lzma failed\\n\"));\n\t  return;\n\t}\n\n      if (clock_gettime (cid, &ts2) < 0)\n\t{\n\t  perror (\"clock_gettime\");\n\t  return;\n\t}\n\n      ctime = (ts2.tv_sec - ts1.tv_sec) * 1000000000;\n      ctime += ts2.tv_nsec - ts1.tv_nsec;\n      ctimes[i] = ctime;\n\n      stream = initial_stream;\n\n      r = lzma_auto_decoder (&stream, UINT64_MAX, 0);\n      if (r != LZMA_OK)\n\t{\n\t  fprintf (stderr, \"lzma_stream_decoder failed: %d\\n\", r);\n\t  goto fail;\n\t}\n\n      stream.next_in = compressed_buf;\n      stream.avail_in = compressed_bufsize;\n      stream.next_out = spare_buf;\n      stream.avail_out = orig_bufsize;\n\n      if (clock_gettime (cid, &ts1) < 0)\n\t{\n\t  perror(\"clock_gettime\");\n\t  return;\n\t}\n\n      do\n\t{\n\t  r = lzma_code (&stream, LZMA_FINISH);\n\t  if (r != LZMA_OK && r != LZMA_STREAM_END)\n\t    {\n\t      fprintf (stderr, \"lzma_code failed: %d\\n\", r);\n\t      goto fail;\n\t    }\n\t}\n      while (r != LZMA_STREAM_END);\n\n      if (clock_gettime (cid, &ts2) < 0)\n\t{\n\t  perror (\"clock_gettime\");\n\t  return;\n\t}\n\n      ztime = (ts2.tv_sec - ts1.tv_sec) * 1000000000;\n      ztime += ts2.tv_nsec - ts1.tv_nsec;\n      ztimes[i] = ztime;\n    }\n\n  /* Toss the highest and lowest times and average the rest.  */\n  ctime = average_time (ctimes, trials);\n  ztime = average_time (ztimes, trials);\n\n  printf (\"backtrace: %zu ns\\n\", ctime);\n  printf (\"liblzma  : %zu ns\\n\", ztime);\n  printf (\"ratio    : %g\\n\", (double) ztime / (double) ctime);\n\n  return;\n\n fail:\n  printf (\"FAIL: lzma large\\n\");\n  ++failures;\n\n  if (orig_buf != NULL)\n    free (orig_buf);\n  if (compressed_buf != NULL)\n    free (compressed_buf);\n  if (uncompressed_buf != NULL)\n    free (uncompressed_buf);\n\n#else /* !HAVE_LIBLZMA */\n\n printf (\"UNSUPPORTED: lzma large\\n\");\n\n#endif /* !HAVE_LIBLZMA */\n}\n\nint\nmain (int argc ATTRIBUTE_UNUSED, char **argv)\n{\n  struct backtrace_state *state;\n\n  state = backtrace_create_state (argv[0], BACKTRACE_SUPPORTS_THREADS,\n\t\t\t\t  error_callback_create, NULL);\n\n  test_samples (state);\n  test_large (state);\n\n  exit (failures != 0 ? EXIT_FAILURE : EXIT_SUCCESS);\n}\n"
  },
  {
    "path": "src/vendor/libbacktrace/zstdtest.c",
    "content": "/* ztest.c -- Test for libbacktrace zstd code.\n   Copyright (C) 2022-2024 Free Software Foundation, Inc.\n   Written by Ian Lance Taylor, Google.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n    (1) Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n\n    (2) Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in\n    the documentation and/or other materials provided with the\n    distribution.\n\n    (3) The name of the author may not be used to\n    endorse or promote products derived from this software without\n    specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\nIMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,\nINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\nHOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\nIN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGE.  */\n\n#include \"config.h\"\n\n#include <errno.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <time.h>\n#include <sys/types.h>\n#include <sys/stat.h>\n\n#ifdef HAVE_ZSTD\n#include <zstd.h>\n#endif\n\n#include \"backtrace.h\"\n#include \"backtrace-supported.h\"\n\n#include \"internal.h\"\n#include \"testlib.h\"\n\n#ifndef HAVE_CLOCK_GETTIME\n\ntypedef int xclockid_t;\n\nstatic int\nxclock_gettime (xclockid_t id ATTRIBUTE_UNUSED,\n\t\tstruct timespec *ts ATTRIBUTE_UNUSED)\n{\n  errno = EINVAL;\n  return -1;\n}\n\n#define clockid_t xclockid_t\n#define clock_gettime xclock_gettime\n#undef CLOCK_REALTIME\n#define CLOCK_REALTIME 0\n\n#endif /* !defined(HAVE_CLOCK_GETTIME) */\n\n#ifdef CLOCK_PROCESS_CPUTIME_ID\n#define ZSTD_CLOCK_GETTIME_ARG CLOCK_PROCESS_CPUTIME_ID\n#else\n#define ZSTD_CLOCK_GETTIME_ARG CLOCK_REALTIME\n#endif\n\n/* Some tests for the local zstd inflation code.  */\n\nstruct zstd_test\n{\n  const char *name;\n  const char *uncompressed;\n  size_t uncompressed_len;\n  const char *compressed;\n  size_t compressed_len;\n};\n\n/* Error callback.  */\n\nstatic void\nerror_callback_compress (void *vdata ATTRIBUTE_UNUSED, const char *msg,\n\t\t\t int errnum)\n{\n  fprintf (stderr, \"%s\", msg);\n  if (errnum > 0)\n    fprintf (stderr, \": %s\", strerror (errnum));\n  fprintf (stderr, \"\\n\");\n  exit (EXIT_FAILURE);\n}\n\nstatic const struct zstd_test tests[] =\n{\n  {\n    \"empty\",\n    \"\",\n    0,\n    \"\\x28\\xb5\\x2f\\xfd\\x24\\x00\\x01\\x00\\x00\\x99\\xe9\\xd8\\x51\",\n    13,\n  },\n  {\n    \"hello\",\n    \"hello, world\\n\",\n    0,\n    (\"\\x28\\xb5\\x2f\\xfd\\x24\\x0d\\x69\\x00\\x00\\x68\\x65\\x6c\\x6c\\x6f\\x2c\\x20\"\n     \"\\x77\\x6f\\x72\\x6c\\x64\\x0a\\x4c\\x1f\\xf9\\xf1\"),\n    26,\n  },\n  {\n    \"goodbye\",\n    \"goodbye, world\",\n    0,\n    (\"\\x28\\xb5\\x2f\\xfd\\x24\\x0e\\x71\\x00\\x00\\x67\\x6f\\x6f\\x64\\x62\\x79\\x65\"\n     \"\\x2c\\x20\\x77\\x6f\\x72\\x6c\\x64\\x61\\x7b\\x4b\\x83\"),\n    27,\n  },\n  {\n    \"ranges\",\n    (\"\\xcc\\x11\\x00\\x00\\x00\\x00\\x00\\x00\\xd5\\x13\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x1c\\x14\\x00\\x00\\x00\\x00\\x00\\x00\\x72\\x14\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x9d\\x14\\x00\\x00\\x00\\x00\\x00\\x00\\xd5\\x14\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\xfb\\x12\\x00\\x00\\x00\\x00\\x00\\x00\\x09\\x13\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x0c\\x13\\x00\\x00\\x00\\x00\\x00\\x00\\xcb\\x13\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x29\\x14\\x00\\x00\\x00\\x00\\x00\\x00\\x4e\\x14\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x9d\\x14\\x00\\x00\\x00\\x00\\x00\\x00\\xd5\\x14\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\xfb\\x12\\x00\\x00\\x00\\x00\\x00\\x00\\x09\\x13\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x67\\x13\\x00\\x00\\x00\\x00\\x00\\x00\\xcb\\x13\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x9d\\x14\\x00\\x00\\x00\\x00\\x00\\x00\\xd5\\x14\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x5f\\x0b\\x00\\x00\\x00\\x00\\x00\\x00\\x6c\\x0b\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x7d\\x0b\\x00\\x00\\x00\\x00\\x00\\x00\\x7e\\x0c\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x38\\x0f\\x00\\x00\\x00\\x00\\x00\\x00\\x5c\\x0f\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x83\\x0c\\x00\\x00\\x00\\x00\\x00\\x00\\xfa\\x0c\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\xfd\\x0d\\x00\\x00\\x00\\x00\\x00\\x00\\xef\\x0e\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x14\\x0f\\x00\\x00\\x00\\x00\\x00\\x00\\x38\\x0f\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x9f\\x0f\\x00\\x00\\x00\\x00\\x00\\x00\\xac\\x0f\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\xdb\\x0f\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\x0f\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\xfd\\x0d\\x00\\x00\\x00\\x00\\x00\\x00\\xd8\\x0e\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x9f\\x0f\\x00\\x00\\x00\\x00\\x00\\x00\\xac\\x0f\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\xdb\\x0f\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\x0f\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\xfa\\x0c\\x00\\x00\\x00\\x00\\x00\\x00\\xea\\x0d\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\xef\\x0e\\x00\\x00\\x00\\x00\\x00\\x00\\x14\\x0f\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x5c\\x0f\\x00\\x00\\x00\\x00\\x00\\x00\\x9f\\x0f\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\xac\\x0f\\x00\\x00\\x00\\x00\\x00\\x00\\xdb\\x0f\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\xff\\x0f\\x00\\x00\\x00\\x00\\x00\\x00\\x2c\\x10\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x60\\x11\\x00\\x00\\x00\\x00\\x00\\x00\\xd1\\x16\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x40\\x0b\\x00\\x00\\x00\\x00\\x00\\x00\\x2c\\x10\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x7a\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xb6\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x9f\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\xa7\\x01\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x7a\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xa9\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x9f\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\xa7\\x01\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"),\n    672,\n    (\"\\x28\\xb5\\x2f\\xfd\\x64\\xa0\\x01\\x2d\\x05\\x00\\xc4\\x04\\xcc\\x11\\x00\\xd5\"\n     \"\\x13\\x00\\x1c\\x14\\x00\\x72\\x9d\\xd5\\xfb\\x12\\x00\\x09\\x0c\\x13\\xcb\\x13\"\n     \"\\x29\\x4e\\x67\\x5f\\x0b\\x6c\\x0b\\x7d\\x0b\\x7e\\x0c\\x38\\x0f\\x5c\\x0f\\x83\"\n     \"\\x0c\\xfa\\x0c\\xfd\\x0d\\xef\\x0e\\x14\\x38\\x9f\\x0f\\xac\\x0f\\xdb\\x0f\\xff\"\n     \"\\x0f\\xd8\\x9f\\xac\\xdb\\xff\\xea\\x5c\\x2c\\x10\\x60\\xd1\\x16\\x40\\x0b\\x7a\"\n     \"\\x00\\xb6\\x00\\x9f\\x01\\xa7\\x01\\xa9\\x36\\x20\\xa0\\x83\\x14\\x34\\x63\\x4a\"\n     \"\\x21\\x70\\x8c\\x07\\x46\\x03\\x4e\\x10\\x62\\x3c\\x06\\x4e\\xc8\\x8c\\xb0\\x32\"\n     \"\\x2a\\x59\\xad\\xb2\\xf1\\x02\\x82\\x7c\\x33\\xcb\\x92\\x6f\\x32\\x4f\\x9b\\xb0\"\n     \"\\xa2\\x30\\xf0\\xc0\\x06\\x1e\\x98\\x99\\x2c\\x06\\x1e\\xd8\\xc0\\x03\\x56\\xd8\"\n     \"\\xc0\\x03\\x0f\\x6c\\xe0\\x01\\xf1\\xf0\\xee\\x9a\\xc6\\xc8\\x97\\x99\\xd1\\x6c\"\n     \"\\xb4\\x21\\x45\\x3b\\x10\\xe4\\x7b\\x99\\x4d\\x8a\\x36\\x64\\x5c\\x77\\x08\\x02\"\n     \"\\xcb\\xe0\\xce\"),\n    179,\n  }\n};\n\n/* Test the hand coded samples.  */\n\nstatic void\ntest_samples (struct backtrace_state *state)\n{\n  size_t i;\n\n  for (i = 0; i < sizeof tests / sizeof tests[0]; ++i)\n    {\n      unsigned char *uncompressed;\n      size_t uncompressed_len;\n\n      uncompressed_len = tests[i].uncompressed_len;\n      if (uncompressed_len == 0)\n\tuncompressed_len = strlen (tests[i].uncompressed);\n\n      uncompressed = (unsigned char *) malloc (uncompressed_len);\n      if (uncompressed == NULL)\n\t{\n\t  perror (\"malloc\");\n\t  fprintf (stderr, \"test %s: uncompress failed\\n\", tests[i].name);\n\t  ++failures;\n\t  continue;\n\t}\n\n      if (!backtrace_uncompress_zstd (state,\n\t\t\t\t      ((const unsigned char *)\n\t\t\t\t       tests[i].compressed),\n\t\t\t\t      tests[i].compressed_len,\n\t\t\t\t      error_callback_compress, NULL,\n\t\t\t\t      uncompressed, uncompressed_len))\n\t{\n\t  fprintf (stderr, \"test %s: uncompress failed\\n\", tests[i].name);\n\t  ++failures;\n\t}\n      else\n\t{\n\t  if (memcmp (tests[i].uncompressed, uncompressed, uncompressed_len)\n\t      != 0)\n\t    {\n\t      size_t j;\n\n\t      fprintf (stderr, \"test %s: uncompressed data mismatch\\n\",\n\t\t       tests[i].name);\n\t      for (j = 0; j < uncompressed_len; ++j)\n\t\tif (tests[i].uncompressed[j] != uncompressed[j])\n\t\t  fprintf (stderr, \"  %zu: got %#x want %#x\\n\", j,\n\t\t\t   uncompressed[j], tests[i].uncompressed[j]);\n\t      ++failures;\n\t    }\n\t  else\n\t    printf (\"PASS: uncompress %s\\n\", tests[i].name);\n\t}\n\n      free (uncompressed);\n    }\n}\n\n#ifdef HAVE_ZSTD\n\n/* Given a set of TRIALS timings, discard the lowest and highest\n   values and return the mean average of the rest.  */\n\nstatic size_t\naverage_time (const size_t *times, size_t trials)\n{\n  size_t imax;\n  size_t max;\n  size_t imin;\n  size_t min;\n  size_t i;\n  size_t sum;\n\n  imin = 0;\n  imax = 0;\n  min = times[0];\n  max = times[0];\n  for (i = 1; i < trials; ++i)\n    {\n      if (times[i] < min)\n\t{\n\t  imin = i;\n\t  min = times[i];\n\t}\n      if (times[i] > max)\n\t{\n\t  imax = i;\n\t  max = times[i];\n\t}\n    }\n\n  sum = 0;\n  for (i = 0; i < trials; ++i)\n    {\n      if (i != imax && i != imin)\n\tsum += times[i];\n    }\n  return sum / (trials - 2);\n}\n\n#endif\n\n/* Test a larger text, if available.  */\n\nstatic void\ntest_large (struct backtrace_state *state ATTRIBUTE_UNUSED)\n{\n#ifdef HAVE_ZSTD\n  unsigned char *orig_buf;\n  size_t orig_bufsize;\n  size_t i;\n  char *compressed_buf;\n  size_t compressed_bufsize;\n  size_t compressed_size;\n  unsigned char *uncompressed_buf;\n  size_t r;\n  clockid_t cid;\n  struct timespec ts1;\n  struct timespec ts2;\n  size_t ctime;\n  size_t ztime;\n  const size_t trials = 16;\n  size_t ctimes[16];\n  size_t ztimes[16];\n  static const char * const names[] = {\n    \"Isaac.Newton-Opticks.txt\",\n    \"../libgo/go/testdata/Isaac.Newton-Opticks.txt\",\n  };\n\n  orig_buf = NULL;\n  orig_bufsize = 0;\n  uncompressed_buf = NULL;\n  compressed_buf = NULL;\n\n  for (i = 0; i < sizeof names / sizeof names[0]; ++i)\n    {\n      size_t len;\n      char *namebuf;\n      FILE *e;\n      struct stat st;\n      char *rbuf;\n      size_t got;\n\n      len = strlen (SRCDIR) + strlen (names[i]) + 2;\n      namebuf = malloc (len);\n      if (namebuf == NULL)\n\t{\n\t  perror (\"malloc\");\n\t  goto fail;\n\t}\n      snprintf (namebuf, len, \"%s/%s\", SRCDIR, names[i]);\n      e = fopen (namebuf, \"r\");\n      free (namebuf);\n      if (e == NULL)\n\tcontinue;\n      if (fstat (fileno (e), &st) < 0)\n\t{\n\t  perror (\"fstat\");\n\t  fclose (e);\n\t  continue;\n\t}\n      rbuf = malloc (st.st_size);\n      if (rbuf == NULL)\n\t{\n\t  perror (\"malloc\");\n\t  goto fail;\n\t}\n      got = fread (rbuf, 1, st.st_size, e);\n      fclose (e);\n      if (got > 0)\n\t{\n\t  orig_buf = (unsigned char *) rbuf;\n\t  orig_bufsize = got;\n\t  break;\n\t}\n      free (rbuf);\n    }\n\n  if (orig_buf == NULL)\n    {\n      /* We couldn't find an input file.  */\n      printf (\"UNSUPPORTED: zstd large\\n\");\n      return;\n    }\n\n  compressed_bufsize = ZSTD_compressBound (orig_bufsize);\n  compressed_buf = malloc (compressed_bufsize);\n  if (compressed_buf == NULL)\n    {\n      perror (\"malloc\");\n      goto fail;\n    }\n\n  r = ZSTD_compress (compressed_buf, compressed_bufsize,\n\t\t     orig_buf, orig_bufsize,\n\t\t     ZSTD_CLEVEL_DEFAULT);\n  if (ZSTD_isError (r))\n    {\n      fprintf (stderr, \"zstd compress failed: %s\\n\", ZSTD_getErrorName (r));\n      goto fail;\n    }\n  compressed_size = r;\n\n  uncompressed_buf = malloc (orig_bufsize);\n  if (uncompressed_buf == NULL)\n    {\n      perror (\"malloc\");\n      goto fail;\n    }\n\n  if (!backtrace_uncompress_zstd (state, (unsigned char *) compressed_buf,\n\t\t\t\t  compressed_size,\n\t\t\t\t  error_callback_compress, NULL,\n\t\t\t\t  uncompressed_buf, orig_bufsize))\n    {\n      fprintf (stderr, \"zstd large: backtrace_uncompress_zstd failed\\n\");\n      goto fail;\n    }\n\n  if (memcmp (uncompressed_buf, orig_buf, orig_bufsize) != 0)\n    {\n      size_t j;\n\n      fprintf (stderr, \"zstd large: uncompressed data mismatch\\n\");\n      for (j = 0; j < orig_bufsize; ++j)\n\tif (orig_buf[j] != uncompressed_buf[j])\n\t  fprintf (stderr, \"  %zu: got %#x want %#x\\n\", j,\n\t\t   uncompressed_buf[j], orig_buf[j]);\n      goto fail;\n    }\n\n  printf (\"PASS: zstd large\\n\");\n\n  for (i = 0; i < trials; ++i)\n    {\n      cid = ZSTD_CLOCK_GETTIME_ARG;\n      if (clock_gettime (cid, &ts1) < 0)\n\t{\n\t  if (errno == EINVAL)\n\t    return;\n\t  perror (\"clock_gettime\");\n\t  return;\n\t}\n\n      if (!backtrace_uncompress_zstd (state,\n\t\t\t\t      (unsigned char *) compressed_buf,\n\t\t\t\t      compressed_size,\n\t\t\t\t      error_callback_compress, NULL,\n\t\t\t\t      uncompressed_buf,\n\t\t\t\t      orig_bufsize))\n\t{\n\t  fprintf (stderr,\n\t\t   (\"zstd large: \"\n\t\t    \"benchmark backtrace_uncompress_zstd failed\\n\"));\n\t  return;\n\t}\n\n      if (clock_gettime (cid, &ts2) < 0)\n\t{\n\t  perror (\"clock_gettime\");\n\t  return;\n\t}\n\n      ctime = (ts2.tv_sec - ts1.tv_sec) * 1000000000;\n      ctime += ts2.tv_nsec - ts1.tv_nsec;\n      ctimes[i] = ctime;\n\n      if (clock_gettime (cid, &ts1) < 0)\n\t{\n\t  perror(\"clock_gettime\");\n\t  return;\n\t}\n\n      r = ZSTD_decompress (uncompressed_buf, orig_bufsize,\n\t\t\t   compressed_buf, compressed_size);\n\n      if (clock_gettime (cid, &ts2) < 0)\n\t{\n\t  perror (\"clock_gettime\");\n\t  return;\n\t}\n\n      if (ZSTD_isError (r))\n\t{\n\t  fprintf (stderr,\n\t\t   \"zstd large: benchmark zlib uncompress failed: %s\\n\",\n\t\t   ZSTD_getErrorName (r));\n\t  return;\n\t}\n\n      ztime = (ts2.tv_sec - ts1.tv_sec) * 1000000000;\n      ztime += ts2.tv_nsec - ts1.tv_nsec;\n      ztimes[i] = ztime;\n    }\n\n  /* Toss the highest and lowest times and average the rest.  */\n  ctime = average_time (ctimes, trials);\n  ztime = average_time (ztimes, trials);\n\n  printf (\"backtrace: %zu ns\\n\", ctime);\n  printf (\"zstd     : %zu ns\\n\", ztime);\n  printf (\"ratio    : %g\\n\", (double) ztime / (double) ctime);\n\n  return;\n\n fail:\n  printf (\"FAIL: zstd large\\n\");\n  ++failures;\n\n  if (orig_buf != NULL)\n    free (orig_buf);\n  if (compressed_buf != NULL)\n    free (compressed_buf);\n  if (uncompressed_buf != NULL)\n    free (uncompressed_buf);\n\n#else /* !HAVE_ZSTD */\n\n printf (\"UNSUPPORTED: zstd large\\n\");\n\n#endif /* !HAVE_ZSTD */\n}\n\nint\nmain (int argc ATTRIBUTE_UNUSED, char **argv)\n{\n  struct backtrace_state *state;\n\n  state = backtrace_create_state (argv[0], BACKTRACE_SUPPORTS_THREADS,\n\t\t\t\t  error_callback_create, NULL);\n\n  test_samples (state);\n  test_large (state);\n\n  exit (failures != 0 ? EXIT_FAILURE : EXIT_SUCCESS);\n}\n"
  },
  {
    "path": "src/vendor/libbacktrace/ztest.c",
    "content": "/* ztest.c -- Test for libbacktrace inflate code.\n   Copyright (C) 2017-2024 Free Software Foundation, Inc.\n   Written by Ian Lance Taylor, Google.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n    (1) Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n\n    (2) Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in\n    the documentation and/or other materials provided with the\n    distribution.\n\n    (3) The name of the author may not be used to\n    endorse or promote products derived from this software without\n    specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\nIMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,\nINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\nHOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\nSTRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\nIN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGE.  */\n\n#include \"config.h\"\n\n#include <errno.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <time.h>\n#include <sys/types.h>\n#include <sys/stat.h>\n\n#ifdef HAVE_ZLIB\n#include <zlib.h>\n#endif\n\n#include \"backtrace.h\"\n#include \"backtrace-supported.h\"\n\n#include \"internal.h\"\n#include \"testlib.h\"\n\n#ifndef HAVE_CLOCK_GETTIME\n\ntypedef int xclockid_t;\n\nstatic int\nxclock_gettime (xclockid_t id ATTRIBUTE_UNUSED,\n\t\tstruct timespec *ts ATTRIBUTE_UNUSED)\n{\n  errno = EINVAL;\n  return -1;\n}\n\n#define clockid_t xclockid_t\n#define clock_gettime xclock_gettime\n#undef CLOCK_REALTIME\n#define CLOCK_REALTIME 0\n\n#endif /* !defined(HAVE_CLOCK_GETTIME) */\n\n#ifdef CLOCK_PROCESS_CPUTIME_ID\n#define ZLIB_CLOCK_GETTIME_ARG CLOCK_PROCESS_CPUTIME_ID\n#else\n#define ZLIB_CLOCK_GETTIME_ARG CLOCK_REALTIME\n#endif\n\n/* Some tests for the local zlib inflation code.  */\n\nstruct zlib_test\n{\n  const char *name;\n  const char *uncompressed;\n  size_t uncompressed_len;\n  const char *compressed;\n  size_t compressed_len;\n};\n\n/* Error callback.  */\n\nstatic void\nerror_callback_compress (void *vdata ATTRIBUTE_UNUSED, const char *msg,\n\t\t\t int errnum)\n{\n  fprintf (stderr, \"%s\", msg);\n  if (errnum > 0)\n    fprintf (stderr, \": %s\", strerror (errnum));\n  fprintf (stderr, \"\\n\");\n  exit (EXIT_FAILURE);\n}\n\nstatic const struct zlib_test tests[] =\n{\n  {\n    \"empty\",\n    \"\",\n    0,\n    \"\\x78\\x9c\\x03\\x00\\x00\\x00\\x00\\x01\",\n    8,\n  },\n  {\n    \"hello\",\n    \"hello, world\\n\",\n    0,\n    (\"\\x78\\x9c\\xca\\x48\\xcd\\xc9\\xc9\\xd7\\x51\\x28\\xcf\"\n     \"\\x2f\\xca\\x49\\xe1\\x02\\x04\\x00\\x00\\xff\\xff\\x21\\xe7\\x04\\x93\"),\n    25,\n  },\n  {\n    \"goodbye\",\n    \"goodbye, world\",\n    0,\n    (\"\\x78\\x9c\\x4b\\xcf\\xcf\\x4f\\x49\\xaa\"\n     \"\\x4c\\xd5\\x51\\x28\\xcf\\x2f\\xca\\x49\"\n     \"\\x01\\x00\\x28\\xa5\\x05\\x5e\"),\n    22,\n  },\n  {\n    \"ranges\",\n    (\"\\xcc\\x11\\x00\\x00\\x00\\x00\\x00\\x00\\xd5\\x13\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x1c\\x14\\x00\\x00\\x00\\x00\\x00\\x00\\x72\\x14\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x9d\\x14\\x00\\x00\\x00\\x00\\x00\\x00\\xd5\\x14\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\xfb\\x12\\x00\\x00\\x00\\x00\\x00\\x00\\x09\\x13\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x0c\\x13\\x00\\x00\\x00\\x00\\x00\\x00\\xcb\\x13\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x29\\x14\\x00\\x00\\x00\\x00\\x00\\x00\\x4e\\x14\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x9d\\x14\\x00\\x00\\x00\\x00\\x00\\x00\\xd5\\x14\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\xfb\\x12\\x00\\x00\\x00\\x00\\x00\\x00\\x09\\x13\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x67\\x13\\x00\\x00\\x00\\x00\\x00\\x00\\xcb\\x13\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x9d\\x14\\x00\\x00\\x00\\x00\\x00\\x00\\xd5\\x14\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x5f\\x0b\\x00\\x00\\x00\\x00\\x00\\x00\\x6c\\x0b\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x7d\\x0b\\x00\\x00\\x00\\x00\\x00\\x00\\x7e\\x0c\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x38\\x0f\\x00\\x00\\x00\\x00\\x00\\x00\\x5c\\x0f\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x83\\x0c\\x00\\x00\\x00\\x00\\x00\\x00\\xfa\\x0c\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\xfd\\x0d\\x00\\x00\\x00\\x00\\x00\\x00\\xef\\x0e\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x14\\x0f\\x00\\x00\\x00\\x00\\x00\\x00\\x38\\x0f\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x9f\\x0f\\x00\\x00\\x00\\x00\\x00\\x00\\xac\\x0f\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\xdb\\x0f\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\x0f\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\xfd\\x0d\\x00\\x00\\x00\\x00\\x00\\x00\\xd8\\x0e\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x9f\\x0f\\x00\\x00\\x00\\x00\\x00\\x00\\xac\\x0f\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\xdb\\x0f\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\x0f\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\xfa\\x0c\\x00\\x00\\x00\\x00\\x00\\x00\\xea\\x0d\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\xef\\x0e\\x00\\x00\\x00\\x00\\x00\\x00\\x14\\x0f\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x5c\\x0f\\x00\\x00\\x00\\x00\\x00\\x00\\x9f\\x0f\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\xac\\x0f\\x00\\x00\\x00\\x00\\x00\\x00\\xdb\\x0f\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\xff\\x0f\\x00\\x00\\x00\\x00\\x00\\x00\\x2c\\x10\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x60\\x11\\x00\\x00\\x00\\x00\\x00\\x00\\xd1\\x16\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x40\\x0b\\x00\\x00\\x00\\x00\\x00\\x00\\x2c\\x10\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x7a\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xb6\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x9f\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\xa7\\x01\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x7a\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xa9\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x9f\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\xa7\\x01\\x00\\x00\\x00\\x00\\x00\\x00\"\n     \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"),\n    672,\n    (\"\\x78\\x9c\\x3b\\x23\\xc8\\x00\\x06\\x57\\x85\\x21\\xb4\\x8c\\x08\\x84\\x2e\\x82\"\n     \"\\xd2\\x73\\xa1\\xf4\\x55\\x28\\x8d\\x0e\\x7e\\x0b\\x41\\x68\\x4e\\xa8\\x7e\\x1e\"\n     \"\\x28\\x7d\\x1a\\x4a\\x6b\\x42\\xf5\\xf9\\x91\\x69\\x5e\\x3a\\x9a\\x79\\x84\\xf4\"\n     \"\\xc7\\x73\\x43\\xe8\\x1c\\x28\\x5d\\x0b\\xa5\\xeb\\x78\\x20\\xb4\\x05\\x3f\\x84\"\n     \"\\x8e\\xe1\\xc7\\xae\\xbf\\x19\\xaa\\xee\\x17\\x94\\xfe\\xcb\\x0b\\xa1\\xdf\\xf3\"\n     \"\\x41\\x68\\x11\\x7e\\x54\\x73\\xe6\\x43\\xe9\\x35\\x50\\xfa\\x36\\x94\\xfe\\x8f\"\n     \"\\xc3\\x7c\\x98\\x79\\x37\\xf8\\xc8\\xd3\\x0f\\x73\\xd7\\x2b\\x1c\\xee\\x8a\\x21\"\n     \"\\xd2\\x5d\\x3a\\x02\\xd8\\xcd\\x4f\\x80\\xa6\\x87\\x8b\\x62\\x10\\xda\\x81\\x1b\"\n     \"\\xbf\\xfa\\x2a\\x28\\xbd\\x0d\\x4a\\xcf\\x67\\x84\\xd0\\xcb\\x19\\xf1\\xab\\x5f\"\n     \"\\x49\\xa4\\x7a\\x00\\x48\\x97\\x29\\xd4\"),\n    152,\n  }\n};\n\n/* Test the hand coded samples.  */\n\nstatic void\ntest_samples (struct backtrace_state *state)\n{\n  size_t i;\n\n  for (i = 0; i < sizeof tests / sizeof tests[0]; ++i)\n    {\n      char *p;\n      size_t v;\n      size_t j;\n      unsigned char *uncompressed;\n      size_t uncompressed_len;\n\n      p = malloc (12 + tests[i].compressed_len);\n      memcpy (p, \"ZLIB\", 4);\n      v = tests[i].uncompressed_len;\n      if (v == 0)\n\tv = strlen (tests[i].uncompressed);\n      for (j = 0; j < 8; ++j)\n\tp[j + 4] = (v >> ((7 - j) * 8)) & 0xff;\n      memcpy (p + 12, tests[i].compressed, tests[i].compressed_len);\n      uncompressed = NULL;\n      uncompressed_len = 0;\n      if (!backtrace_uncompress_zdebug (state, (unsigned char *) p,\n\t\t\t\t\ttests[i].compressed_len + 12,\n\t\t\t\t\terror_callback_compress, NULL,\n\t\t\t\t\t&uncompressed, &uncompressed_len))\n\t{\n\t  fprintf (stderr, \"test %s: uncompress failed\\n\", tests[i].name);\n\t  ++failures;\n\t}\n      else\n\t{\n\t  if (uncompressed_len != v)\n\t    {\n\t      fprintf (stderr,\n\t\t       \"test %s: got uncompressed length %zu, want %zu\\n\",\n\t\t       tests[i].name, uncompressed_len, v);\n\t      ++failures;\n\t    }\n\t  else if (memcmp (tests[i].uncompressed, uncompressed, v) != 0)\n\t    {\n\t      size_t j;\n\n\t      fprintf (stderr, \"test %s: uncompressed data mismatch\\n\",\n\t\t       tests[i].name);\n\t      for (j = 0; j < v; ++j)\n\t\tif (tests[i].uncompressed[j] != uncompressed[j])\n\t\t  fprintf (stderr, \"  %zu: got %#x want %#x\\n\", j,\n\t\t\t   uncompressed[j], tests[i].uncompressed[j]);\n\t      ++failures;\n\t    }\n\t  else\n\t    printf (\"PASS: inflate %s\\n\", tests[i].name);\n\n\t  backtrace_free (state, uncompressed, uncompressed_len,\n\t\t\t  error_callback_compress, NULL);\n\t}\n    }\n}\n\n#ifdef HAVE_ZLIB\n\n/* Given a set of TRIALS timings, discard the lowest and highest\n   values and return the mean average of the rest.  */\n\nstatic size_t\naverage_time (const size_t *times, size_t trials)\n{\n  size_t imax;\n  size_t max;\n  size_t imin;\n  size_t min;\n  size_t i;\n  size_t sum;\n\n  imin = 0;\n  imax = 0;\n  min = times[0];\n  max = times[0];\n  for (i = 1; i < trials; ++i)\n    {\n      if (times[i] < min)\n\t{\n\t  imin = i;\n\t  min = times[i];\n\t}\n      if (times[i] > max)\n\t{\n\t  imax = i;\n\t  max = times[i];\n\t}\n    }\n\n  sum = 0;\n  for (i = 0; i < trials; ++i)\n    {\n      if (i != imax && i != imin)\n\tsum += times[i];\n    }\n  return sum / (trials - 2);\n}\n\n#endif\n\n/* Test a larger text, if available.  */\n\nstatic void\ntest_large (struct backtrace_state *state ATTRIBUTE_UNUSED)\n{\n#ifdef HAVE_ZLIB\n  unsigned char *orig_buf;\n  size_t orig_bufsize;\n  size_t i;\n  char *compressed_buf;\n  size_t compressed_bufsize;\n  unsigned long compress_sizearg;\n  unsigned char *uncompressed_buf;\n  size_t uncompressed_bufsize;\n  int r;\n  clockid_t cid;\n  struct timespec ts1;\n  struct timespec ts2;\n  size_t ctime;\n  size_t ztime;\n  const size_t trials = 16;\n  size_t ctimes[16];\n  size_t ztimes[16];\n  static const char * const names[] = {\n    \"Isaac.Newton-Opticks.txt\",\n    \"../libgo/go/testdata/Isaac.Newton-Opticks.txt\",\n  };\n\n  orig_buf = NULL;\n  orig_bufsize = 0;\n  uncompressed_buf = NULL;\n  compressed_buf = NULL;\n\n  for (i = 0; i < sizeof names / sizeof names[0]; ++i)\n    {\n      size_t len;\n      char *namebuf;\n      FILE *e;\n      struct stat st;\n      char *rbuf;\n      size_t got;\n\n      len = strlen (SRCDIR) + strlen (names[i]) + 2;\n      namebuf = malloc (len);\n      if (namebuf == NULL)\n\t{\n\t  perror (\"malloc\");\n\t  goto fail;\n\t}\n      snprintf (namebuf, len, \"%s/%s\", SRCDIR, names[i]);\n      e = fopen (namebuf, \"r\");\n      free (namebuf);\n      if (e == NULL)\n\tcontinue;\n      if (fstat (fileno (e), &st) < 0)\n\t{\n\t  perror (\"fstat\");\n\t  fclose (e);\n\t  continue;\n\t}\n      rbuf = malloc (st.st_size);\n      if (rbuf == NULL)\n\t{\n\t  perror (\"malloc\");\n\t  goto fail;\n\t}\n      got = fread (rbuf, 1, st.st_size, e);\n      fclose (e);\n      if (got > 0)\n\t{\n\t  orig_buf = (unsigned char *) rbuf;\n\t  orig_bufsize = got;\n\t  break;\n\t}\n      free (rbuf);\n    }\n\n  if (orig_buf == NULL)\n    {\n      /* We couldn't find an input file.  */\n      printf (\"UNSUPPORTED: inflate large\\n\");\n      return;\n    }\n\n  compressed_bufsize = compressBound (orig_bufsize) + 12;\n  compressed_buf = malloc (compressed_bufsize);\n  if (compressed_buf == NULL)\n    {\n      perror (\"malloc\");\n      goto fail;\n    }\n\n  compress_sizearg = compressed_bufsize - 12;\n  r = compress ((unsigned char *) compressed_buf + 12, &compress_sizearg,\n\t\torig_buf, orig_bufsize);\n  if (r != Z_OK)\n    {\n      fprintf (stderr, \"zlib compress failed: %d\\n\", r);\n      goto fail;\n    }\n\n  compressed_bufsize = compress_sizearg + 12;\n\n  /* Prepare the header that our library expects.  */\n  memcpy (compressed_buf, \"ZLIB\", 4);\n  for (i = 0; i < 8; ++i)\n    compressed_buf[i + 4] = (orig_bufsize >> ((7 - i) * 8)) & 0xff;\n\n  uncompressed_buf = malloc (orig_bufsize);\n  if (uncompressed_buf == NULL)\n    {\n      perror (\"malloc\");\n      goto fail;\n    }\n  uncompressed_bufsize = orig_bufsize;\n\n  if (!backtrace_uncompress_zdebug (state, (unsigned char *) compressed_buf,\n\t\t\t\t    compressed_bufsize,\n\t\t\t\t    error_callback_compress, NULL,\n\t\t\t\t    &uncompressed_buf, &uncompressed_bufsize))\n    {\n      fprintf (stderr, \"inflate large: backtrace_uncompress_zdebug failed\\n\");\n      goto fail;\n    }\n\n  if (uncompressed_bufsize != orig_bufsize)\n    {\n      fprintf (stderr,\n\t       \"inflate large: got uncompressed length %zu, want %zu\\n\",\n\t       uncompressed_bufsize, orig_bufsize);\n      goto fail;\n    }\n\n  if (memcmp (uncompressed_buf, orig_buf, uncompressed_bufsize) != 0)\n    {\n      fprintf (stderr, \"inflate large: uncompressed data mismatch\\n\");\n      goto fail;\n    }\n\n  printf (\"PASS: inflate large\\n\");\n\n  for (i = 0; i < trials; ++i)\n    {\n      unsigned long uncompress_sizearg;\n\n      cid = ZLIB_CLOCK_GETTIME_ARG;\n      if (clock_gettime (cid, &ts1) < 0)\n\t{\n\t  if (errno == EINVAL)\n\t    return;\n\t  perror (\"clock_gettime\");\n\t  return;\n\t}\n\n      if (!backtrace_uncompress_zdebug (state,\n\t\t\t\t\t(unsigned char *) compressed_buf,\n\t\t\t\t\tcompressed_bufsize,\n\t\t\t\t\terror_callback_compress, NULL,\n\t\t\t\t\t&uncompressed_buf,\n\t\t\t\t\t&uncompressed_bufsize))\n\t{\n\t  fprintf (stderr,\n\t\t   (\"inflate large: \"\n\t\t    \"benchmark backtrace_uncompress_zdebug failed\\n\"));\n\t  return;\n\t}\n\n      if (clock_gettime (cid, &ts2) < 0)\n\t{\n\t  perror (\"clock_gettime\");\n\t  return;\n\t}\n\n      ctime = (ts2.tv_sec - ts1.tv_sec) * 1000000000;\n      ctime += ts2.tv_nsec - ts1.tv_nsec;\n      ctimes[i] = ctime;\n\n      if (clock_gettime (cid, &ts1) < 0)\n\t{\n\t  perror(\"clock_gettime\");\n\t  return;\n\t}\n\n      uncompress_sizearg = uncompressed_bufsize;\n      r = uncompress ((unsigned char *) uncompressed_buf, &uncompress_sizearg,\n\t\t      (unsigned char *) compressed_buf + 12,\n\t\t      compressed_bufsize - 12);\n\n      if (clock_gettime (cid, &ts2) < 0)\n\t{\n\t  perror (\"clock_gettime\");\n\t  return;\n\t}\n\n      if (r != Z_OK)\n\t{\n\t  fprintf (stderr,\n\t\t   \"inflate large: benchmark zlib uncompress failed: %d\\n\",\n\t\t   r);\n\t  return;\n\t}\n\n      ztime = (ts2.tv_sec - ts1.tv_sec) * 1000000000;\n      ztime += ts2.tv_nsec - ts1.tv_nsec;\n      ztimes[i] = ztime;\n    }\n\n  /* Toss the highest and lowest times and average the rest.  */\n  ctime = average_time (ctimes, trials);\n  ztime = average_time (ztimes, trials);\n\n  printf (\"backtrace: %zu ns\\n\", ctime);\n  printf (\"zlib     : %zu ns\\n\", ztime);\n  printf (\"ratio    : %g\\n\", (double) ztime / (double) ctime);\n\n  return;\n\n fail:\n  printf (\"FAIL: inflate large\\n\");\n  ++failures;\n\n  if (orig_buf != NULL)\n    free (orig_buf);\n  if (compressed_buf != NULL)\n    free (compressed_buf);\n  if (uncompressed_buf != NULL)\n    free (uncompressed_buf);\n\n#else /* !HAVE_ZLIB */\n\n printf (\"UNSUPPORTED: inflate large\\n\");\n\n#endif /* !HAVE_ZLIB */\n}\n\nint\nmain (int argc ATTRIBUTE_UNUSED, char **argv)\n{\n  struct backtrace_state *state;\n\n  state = backtrace_create_state (argv[0], BACKTRACE_SUPPORTS_THREADS,\n\t\t\t\t  error_callback_create, NULL);\n\n  test_samples (state);\n  test_large (state);\n\n  exit (failures != 0 ? EXIT_FAILURE : EXIT_SUCCESS);\n}\n"
  },
  {
    "path": "src/vendor/libbacktrace-patches/0001-Expose-some-internal-functions-of-libbacktrace.patch",
    "content": "From d99c0a30bacfe6cae604a85250f12587d0fee932 Mon Sep 17 00:00:00 2001\nFrom: Matt Wozniski <mwozniski@bloomberg.net>\nDate: Thu, 25 Jul 2024 18:59:09 -0400\nSubject: [PATCH] Expose some internal functions of libbacktrace\n\nMemray uses these for more control than the public entry points give.\n---\n Makefile.am |  2 +-\n Makefile.in |  2 +-\n elf.c       | 10 +++++-----\n internal.h  | 39 +++++++++++++++++++++++++++++++++++++++\n macho.c     | 31 +++++++++++++++++++------------\n 5 files changed, 65 insertions(+), 19 deletions(-)\n\ndiff --git a/Makefile.am b/Makefile.am\nindex 4d509a2..f80a9e6 100644\n--- a/Makefile.am\n+++ b/Makefile.am\n@@ -35,7 +35,7 @@ AM_CPPFLAGS =\n \n AM_CFLAGS = $(EXTRA_FLAGS) $(WARN_FLAGS) $(PIC_FLAG)\n \n-include_HEADERS = backtrace.h backtrace-supported.h\n+include_HEADERS = backtrace.h backtrace-supported.h internal.h\n \n lib_LTLIBRARIES = libbacktrace.la\n \ndiff --git a/Makefile.in b/Makefile.in\nindex 4df8436..eafad7d 100644\n--- a/Makefile.in\n+++ b/Makefile.in\n@@ -994,7 +994,7 @@ top_srcdir = @top_srcdir@\n ACLOCAL_AMFLAGS = -I config\n AM_CPPFLAGS = \n AM_CFLAGS = $(EXTRA_FLAGS) $(WARN_FLAGS) $(PIC_FLAG)\n-include_HEADERS = backtrace.h backtrace-supported.h\n+include_HEADERS = backtrace.h backtrace-supported.h internal.h\n lib_LTLIBRARIES = libbacktrace.la\n libbacktrace_la_SOURCES = \\\n \tbacktrace.h \\\ndiff --git a/elf.c b/elf.c\nindex 0040479..80482a4 100644\n--- a/elf.c\n+++ b/elf.c\n@@ -557,7 +557,7 @@ elf_crc32_file (struct backtrace_state *state, int descriptor,\n /* A dummy callback function used when we can't find a symbol\n    table.  */\n \n-static void\n+void\n elf_nosyms (struct backtrace_state *state ATTRIBUTE_UNUSED,\n \t    uintptr_t addr ATTRIBUTE_UNUSED,\n \t    backtrace_syminfo_callback callback ATTRIBUTE_UNUSED,\n@@ -631,7 +631,7 @@ elf_symbol_search (const void *vkey, const void *ventry)\n \n /* Initialize the symbol table info for elf_syminfo.  */\n \n-static int\n+int\n elf_initialize_syminfo (struct backtrace_state *state,\n \t\t\tstruct libbacktrace_base_address base_address,\n \t\t\tconst unsigned char *symtab_data, size_t symtab_size,\n@@ -759,7 +759,7 @@ elf_add_syminfo_data (struct backtrace_state *state,\n \n /* Return the symbol name and value for an ADDR.  */\n \n-static void\n+void\n elf_syminfo (struct backtrace_state *state, uintptr_t addr,\n \t     backtrace_syminfo_callback callback,\n \t     backtrace_error_callback error_callback ATTRIBUTE_UNUSED,\n@@ -1090,7 +1090,7 @@ elf_open_debugfile_by_debuglink (struct backtrace_state *state,\n     {\n       uint32_t got_crc;\n \n-      got_crc = elf_crc32_file (state, ddescriptor, error_callback, data);\n+      got_crc = debuglink_crc ? elf_crc32_file (state, ddescriptor, error_callback, data) : 0;\n       if (got_crc != debuglink_crc)\n \t{\n \t  backtrace_close (ddescriptor, error_callback, data);\n@@ -6497,7 +6497,7 @@ backtrace_uncompress_lzma (struct backtrace_state *state,\n    elf_add will need to be called on the descriptor again after\n    base_address is determined.  */\n \n-static int\n+int\n elf_add (struct backtrace_state *state, const char *filename, int descriptor,\n \t const unsigned char *memory, size_t memory_size,\n \t struct libbacktrace_base_address base_address,\ndiff --git a/internal.h b/internal.h\nindex fe2abe5..fdadc24 100644\n--- a/internal.h\n+++ b/internal.h\n@@ -33,6 +33,10 @@ POSSIBILITY OF SUCH DAMAGE.  */\n #ifndef BACKTRACE_INTERNAL_H\n #define BACKTRACE_INTERNAL_H\n \n+#ifdef __cplusplus\n+extern \"C\" {\n+#endif\n+\n /* We assume that <sys/types.h> and \"backtrace.h\" have already been\n    included.  */\n \n@@ -425,4 +429,39 @@ extern int backtrace_uncompress_lzma (struct backtrace_state *,\n \t\t\t\t      unsigned char **uncompressed,\n \t\t\t\t      size_t *uncompressed_size);\n \n+struct elf_ppc64_opd_data;\n+extern int elf_add (struct backtrace_state *state, const char *filename, int descriptor,\n+\t const unsigned char *memory, size_t memory_size,\n+\t struct libbacktrace_base_address base_address,\n+\t struct elf_ppc64_opd_data *caller_opd,\n+\t backtrace_error_callback error_callback, void *data,\n+\t fileline *fileline_fn, int *found_sym, int *found_dwarf,\n+\t struct dwarf_data **fileline_entry, int exe, int debuginfo,\n+\t const char *with_buildid_data, uint32_t with_buildid_size);\n+extern void elf_syminfo (struct backtrace_state *state, uintptr_t addr,\n+\t     backtrace_syminfo_callback callback,\n+\t     backtrace_error_callback error_callback ATTRIBUTE_UNUSED,\n+\t     void *data);\n+extern void elf_nosyms (struct backtrace_state *state ATTRIBUTE_UNUSED,\n+\t    uintptr_t addr ATTRIBUTE_UNUSED,\n+\t    backtrace_syminfo_callback callback ATTRIBUTE_UNUSED,\n+\t    backtrace_error_callback error_callback, void *data);\n+\n+extern int macho_add (struct backtrace_state *state, const char *filename, int descriptor,\n+\t   off_t offset, const unsigned char *match_uuid,\n+\t   struct libbacktrace_base_address base_address, int skip_symtab,\n+\t   backtrace_error_callback error_callback, void *data,\n+\t   fileline *fileline_fn, int *found_sym);\n+extern void macho_syminfo (struct backtrace_state *state, uintptr_t addr,\n+\t       backtrace_syminfo_callback callback,\n+\t       backtrace_error_callback error_callback ATTRIBUTE_UNUSED,\n+\t       void *data);\n+extern void macho_nosyms (struct backtrace_state *state ATTRIBUTE_UNUSED,\n+\t      uintptr_t addr ATTRIBUTE_UNUSED,\n+\t      backtrace_syminfo_callback callback ATTRIBUTE_UNUSED,\n+\t      backtrace_error_callback error_callback, void *data);\n+#ifdef __cplusplus\n+}\n+#endif\n+\n #endif\ndiff --git a/macho.c b/macho.c\nindex fc4c959..527c5ac 100644\n--- a/macho.c\n+++ b/macho.c\n@@ -92,6 +92,7 @@ struct macho_header_fat\n \n #define MACH_O_MH_EXECUTE\t0x02\n #define MACH_O_MH_DYLIB\t\t0x06\n+#define MACH_O_MH_BUNDLE\t0x08\n #define MACH_O_MH_DSYM\t\t0x0a\n \n /* A component of a fat file.  A fat file starts with a\n@@ -279,6 +280,9 @@ struct macho_nlist_64\n #define MACH_O_N_ABS\t0x02\t/* Absolute symbol */\n #define MACH_O_N_SECT\t0x0e\t/* Defined in section from n_sect field */\n \n+#define MACH_O_GLOBAL   0x0f    /* global symbol */\n+#define MACH_O_N_FNAME  0x26    /* static symbol: name,,n_sect,type,address */\n+#define MACH_O_N_FUN    0x24    /* procedure: name,,n_sect,linenumber,address */\n \n /* Information we keep for a Mach-O symbol.  */\n \n@@ -312,13 +316,6 @@ static const char * const dwarf_section_names[DEBUG_MAX] =\n   \"__debug_rnglists\"\n };\n \n-/* Forward declaration.  */\n-\n-static int macho_add (struct backtrace_state *, const char *, int, off_t,\n-\t\t      const unsigned char *, struct libbacktrace_base_address,\n-\t\t      int, backtrace_error_callback, void *, fileline *,\n-\t\t      int *);\n-\n /* A dummy callback function used when we can't find any debug info.  */\n \n static int\n@@ -334,7 +331,7 @@ macho_nodebug (struct backtrace_state *state ATTRIBUTE_UNUSED,\n /* A dummy callback function used when we can't find a symbol\n    table.  */\n \n-static void\n+void\n macho_nosyms (struct backtrace_state *state ATTRIBUTE_UNUSED,\n \t      uintptr_t addr ATTRIBUTE_UNUSED,\n \t      backtrace_syminfo_callback callback ATTRIBUTE_UNUSED,\n@@ -494,13 +491,22 @@ static int\n macho_defined_symbol (uint8_t type)\n {\n   if ((type & MACH_O_N_STAB) != 0)\n-    return 0;\n+  {\n+    switch (type)\n+     {\n+     case MACH_O_N_FNAME:\n+      return 1;\n+     case MACH_O_N_FUN:\n+      return 1;\n+     default:\n+      return 0;\n+     }\n+  }\n   switch (type & MACH_O_N_TYPE)\n     {\n     case MACH_O_N_UNDF:\n       return 0;\n     case MACH_O_N_ABS:\n-      return 1;\n     case MACH_O_N_SECT:\n       return 1;\n     default:\n@@ -703,7 +709,7 @@ macho_add_symtab (struct backtrace_state *state, int descriptor,\n \n /* Return the symbol name and value for an ADDR.  */\n \n-static void\n+void\n macho_syminfo (struct backtrace_state *state, uintptr_t addr,\n \t       backtrace_syminfo_callback callback,\n \t       backtrace_error_callback error_callback ATTRIBUTE_UNUSED,\n@@ -978,7 +984,7 @@ macho_add_dsym (struct backtrace_state *state, const char *filename,\n    FOUND_SYM: set to non-zero if we found the symbol table.\n */\n \n-static int\n+int\n macho_add (struct backtrace_state *state, const char *filename, int descriptor,\n \t   off_t offset, const unsigned char *match_uuid,\n \t   struct libbacktrace_base_address base_address, int skip_symtab,\n@@ -1063,6 +1069,7 @@ macho_add (struct backtrace_state *state, const char *filename, int descriptor,\n     case MACH_O_MH_EXECUTE:\n     case MACH_O_MH_DYLIB:\n     case MACH_O_MH_DSYM:\n+    case MACH_O_MH_BUNDLE:\n       break;\n     default:\n       error_callback (data, \"executable file is not an executable\", 0);\n-- \n2.42.3\n\n"
  },
  {
    "path": "src/vendor/libbacktrace-patches/0002-Add-debuginfod-support-to-libbacktrace.patch",
    "content": "From b052eda140ac673de19a3060523fb250d898ffb6 Mon Sep 17 00:00:00 2001\nFrom: Matt Wozniski <mwozniski@bloomberg.net>\nDate: Thu, 25 Jul 2024 18:59:10 -0400\nSubject: [PATCH] Add debuginfod support to libbacktrace\n\nAllow fetching debug info from a debuginfod server when unwinding.\n---\n Makefile.am          |   5 +-\n Makefile.in          |   5 +-\n debuginfod_support.h | 115 +++++++++++++++++++++++++++++++++++++++++++\n elf.c                |  64 ++++++++++++++++++++++++\n 4 files changed, 185 insertions(+), 4 deletions(-)\n create mode 100644 debuginfod_support.h\n\ndiff --git a/Makefile.am b/Makefile.am\nindex f80a9e6..15e87c7 100644\n--- a/Makefile.am\n+++ b/Makefile.am\n@@ -35,7 +35,7 @@ AM_CPPFLAGS =\n \n AM_CFLAGS = $(EXTRA_FLAGS) $(WARN_FLAGS) $(PIC_FLAG)\n \n-include_HEADERS = backtrace.h backtrace-supported.h internal.h\n+include_HEADERS = backtrace.h backtrace-supported.h internal.h debuginfod_support.h\n \n lib_LTLIBRARIES = libbacktrace.la\n \n@@ -45,6 +45,7 @@ libbacktrace_la_SOURCES = \\\n \tdwarf.c \\\n \tfileline.c \\\n \tinternal.h \\\n+\tdebuginfod_support.h \\\n \tposix.c \\\n \tprint.c \\\n \tsort.c \\\n@@ -685,7 +686,7 @@ alloc.lo: config.h backtrace.h internal.h\n backtrace.lo: config.h backtrace.h internal.h\n btest.lo: filenames.h backtrace.h backtrace-supported.h\n dwarf.lo: config.h filenames.h backtrace.h internal.h\n-elf.lo: config.h backtrace.h internal.h\n+elf.lo: config.h backtrace.h internal.h debuginfod_support.h\n fileline.lo: config.h backtrace.h internal.h\n macho.lo: config.h backtrace.h internal.h\n mmap.lo: config.h backtrace.h internal.h\ndiff --git a/Makefile.in b/Makefile.in\nindex eafad7d..5d9363a 100644\n--- a/Makefile.in\n+++ b/Makefile.in\n@@ -994,7 +994,7 @@ top_srcdir = @top_srcdir@\n ACLOCAL_AMFLAGS = -I config\n AM_CPPFLAGS = \n AM_CFLAGS = $(EXTRA_FLAGS) $(WARN_FLAGS) $(PIC_FLAG)\n-include_HEADERS = backtrace.h backtrace-supported.h internal.h\n+include_HEADERS = backtrace.h backtrace-supported.h internal.h debuginfod_support.h\n lib_LTLIBRARIES = libbacktrace.la\n libbacktrace_la_SOURCES = \\\n \tbacktrace.h \\\n@@ -1002,6 +1002,7 @@ libbacktrace_la_SOURCES = \\\n \tdwarf.c \\\n \tfileline.c \\\n \tinternal.h \\\n+\tdebuginfod_support.h \\\n \tposix.c \\\n \tprint.c \\\n \tsort.c \\\n@@ -2794,7 +2795,7 @@ alloc.lo: config.h backtrace.h internal.h\n backtrace.lo: config.h backtrace.h internal.h\n btest.lo: filenames.h backtrace.h backtrace-supported.h\n dwarf.lo: config.h filenames.h backtrace.h internal.h\n-elf.lo: config.h backtrace.h internal.h\n+elf.lo: config.h backtrace.h internal.h debuginfod_support.h\n fileline.lo: config.h backtrace.h internal.h\n macho.lo: config.h backtrace.h internal.h\n mmap.lo: config.h backtrace.h internal.h\ndiff --git a/debuginfod_support.h b/debuginfod_support.h\nnew file mode 100644\nindex 0000000..78f4d8d\n--- /dev/null\n+++ b/debuginfod_support.h\n@@ -0,0 +1,115 @@\n+/* External declarations for the libdebuginfod client library.\n+   Copyright (C) 2019-2020 Red Hat, Inc.\n+   This file is part of elfutils.\n+\n+   This file is free software; you can redistribute it and/or modify\n+   it under the terms of either\n+\n+   * the GNU Lesser General Public License as published by the Free\n+       Software Foundation; either version 3 of the License, or (at\n+       your option) any later version\n+\n+   or\n+\n+   * the GNU General Public License as published by the Free\n+       Software Foundation; either version 2 of the License, or (at\n+       your option) any later version\n+\n+   or both in parallel, as here.\n+\n+   elfutils is distributed in the hope that it will be useful, but\n+   WITHOUT ANY WARRANTY; without even the implied warranty of\n+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n+   General Public License for more details.\n+\n+   You should have received copies of the GNU General Public License and\n+   the GNU Lesser General Public License along with this program.  If\n+   not, see <http://www.gnu.org/licenses/>.  */\n+\n+#ifndef _DEBUGINFOD_CLIENT_H\n+#define _DEBUGINFOD_CLIENT_H 1\n+\n+/* Names of environment variables that control the client logic. */\n+#define DEBUGINFOD_URLS_ENV_VAR \"DEBUGINFOD_URLS\"\n+#define DEBUGINFOD_CACHE_PATH_ENV_VAR \"DEBUGINFOD_CACHE_PATH\"\n+#define DEBUGINFOD_TIMEOUT_ENV_VAR \"DEBUGINFOD_TIMEOUT\"\n+#define DEBUGINFOD_PROGRESS_ENV_VAR \"DEBUGINFOD_PROGRESS\"\n+#define DEBUGINFOD_VERBOSE_ENV_VAR \"DEBUGINFOD_VERBOSE\"\n+#define DEBUGINFOD_RETRY_LIMIT_ENV_VAR \"DEBUGINFOD_RETRY_LIMIT\"\n+#define DEBUGINFOD_MAXSIZE_ENV_VAR \"DEBUGINFOD_MAXSIZE\"\n+#define DEBUGINFOD_MAXTIME_ENV_VAR \"DEBUGINFOD_MAXTIME\"\n+#define DEBUGINFOD_HEADERS_FILE_ENV_VAR \"DEBUGINFOD_HEADERS_FILE\"\n+\n+/* Handle for debuginfod-client connection.  */\n+typedef struct debuginfod_client debuginfod_client;\n+\n+#ifdef __cplusplus\n+extern \"C\" {\n+#endif\n+\n+/* Create a handle for a new debuginfod-client session.  */\n+debuginfod_client *debuginfod_begin (void);\n+\n+/* Query the urls contained in $DEBUGINFOD_URLS for a file with\n+   the specified type and build id.  If build_id_len == 0, the\n+   build_id is supplied as a lowercase hexadecimal string; otherwise\n+   it is a binary blob of given length.\n+\n+   If successful, return a file descriptor to the target, otherwise\n+   return a posix error code.  If successful, set *path to a\n+   strdup'd copy of the name of the same file in the cache.\n+   Caller must free() it later. */\n+\n+int debuginfod_find_debuginfo (debuginfod_client *client,\n+\t\t\t       const unsigned char *build_id,\n+                               int build_id_len,\n+                               char **path);\n+\n+int debuginfod_find_executable (debuginfod_client *client,\n+\t\t\t\tconst unsigned char *build_id,\n+                                int build_id_len,\n+                                char **path);\n+\n+int debuginfod_find_source (debuginfod_client *client,\n+\t\t\t    const unsigned char *build_id,\n+                            int build_id_len,\n+                            const char *filename,\n+                            char **path);\n+\n+int debuginfod_find_section (debuginfod_client *client,\n+\t\t\t     const unsigned char *build_id,\n+\t\t\t     int build_id_len,\n+\t\t\t     const char *section,\n+\t\t\t     char **path);\n+\n+typedef int (*debuginfod_progressfn_t)(debuginfod_client *c, long a, long b);\n+void debuginfod_set_progressfn(debuginfod_client *c,\n+\t\t\t       debuginfod_progressfn_t fn);\n+\n+void debuginfod_set_verbose_fd(debuginfod_client *c, int fd);\n+\n+/* Set the user parameter.  */\n+void debuginfod_set_user_data (debuginfod_client *client, void *value);\n+\n+/* Get the user parameter.  */\n+void* debuginfod_get_user_data (debuginfod_client *client);\n+\n+/* Get the current or last active URL, if known.  */\n+const char* debuginfod_get_url (debuginfod_client *client);\n+\n+/* Returns set of x-debuginfod* header lines received from current or\n+   last active transfer, \\n separated, if known. */\n+const char* debuginfod_get_headers(debuginfod_client *client);\n+\n+/* Add an outgoing HTTP request  \"Header: Value\".  Copies string.  */\n+int debuginfod_add_http_header (debuginfod_client *client, const char* header);\n+\n+/* Release debuginfod client connection context handle.  */\n+void debuginfod_end (debuginfod_client *client);\n+\n+#ifdef __cplusplus\n+}\n+#endif\n+\n+\n+#endif /* _DEBUGINFOD_CLIENT_H */\ndiff --git a/elf.c b/elf.c\nindex 80482a4..61f08af 100644\n--- a/elf.c\n+++ b/elf.c\n@@ -38,6 +38,7 @@ POSSIBILITY OF SUCH DAMAGE.  */\n #include <sys/types.h>\n #include <sys/stat.h>\n #include <unistd.h>\n+#include <dlfcn.h>\n \n #ifdef HAVE_DL_ITERATE_PHDR\n  #ifdef HAVE_LINK_H\n@@ -50,6 +51,7 @@ POSSIBILITY OF SUCH DAMAGE.  */\n \n #include \"backtrace.h\"\n #include \"internal.h\"\n+#include \"debuginfod_support.h\"\n \n #ifndef S_ISLNK\n  #ifndef S_IFLNK\n@@ -859,6 +861,39 @@ elf_readlink (struct backtrace_state *state, const char *filename,\n \n #define SYSTEM_BUILD_ID_DIR \"/usr/lib/debug/.build-id/\"\n \n+static int debuginfod_guard = 0;\n+\n+static int\n+elf_open_debugfile_by_debuginfod (const char *buildid_data,\n+\t\t\t       size_t buildid_size,\n+\t\t\t       backtrace_error_callback error_callback,\n+\t\t\t       void *data)\n+{\n+  char* path = NULL;\n+  const unsigned char* bi = (const unsigned char*)buildid_data;\n+\n+  debuginfod_client* client = debuginfod_begin();\n+  if (!client) {\n+    return -1;\n+  }\n+\n+  const int fd = debuginfod_find_debuginfo(client, bi, buildid_size, &path);\n+\n+  debuginfod_end(client);\n+\n+  if (!path || fd <= 0) {\n+    return -1;\n+  }\n+\n+  const int ret = backtrace_open (path, error_callback, data, NULL);\n+\n+  free(path);\n+  close(fd);\n+\n+  return ret;\n+}\n+\n+\n /* Open a separate debug info file, using the build ID to find it.\n    Returns an open file descriptor, or -1.\n \n@@ -6949,6 +6984,14 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,\n \n       d = elf_open_debugfile_by_buildid (state, buildid_data, buildid_size,\n \t\t\t\t\t error_callback, data);\n+      if (d < 0 && !debuginfod_guard) {\n+          char* env = getenv(DEBUGINFOD_PROGRESS_ENV_VAR);\n+          if (env) {\n+            fprintf(stderr, \"Trying to download debuginfo for %s\\n\", filename);\n+          }\n+          d = elf_open_debugfile_by_debuginfod(buildid_data, buildid_size,\n+                                               error_callback, data);\n+      }\n       if (d >= 0)\n \t{\n \t  int ret;\n@@ -7435,7 +7478,28 @@ backtrace_initialize (struct backtrace_state *state, const char *filename,\n   pd.exe_filename = filename;\n   pd.exe_descriptor = ret < 0 ? descriptor : -1;\n \n+  /* Here, There Be Dragons: we are about to call dl_iterate_phdr,\n+     which is a glibc-internal function that holds a libc internal\n+     lock. As this function needs to iterate over all the loaded\n+     modules, this lock is shared by dlopen so no new modules can be\n+     loaded while is iterating. This is a problem for us, as the\n+     debuginfod client will use libcurl to spawn threads to download\n+     debuginfo files, and libcurl uses dlopen to load a bunch of stuff\n+     for its backend in some versions. This can cause a deadlock because\n+     the debuginfod client will wait until the libcurl threads finish but\n+     they will never finish because they are waiting for the dlopen lock\n+     to be released, which will not happen until the call to dl_iterate_phdr\n+     finishes.\n+\n+     To avoid this, we use a global variable to detect if we are already\n+     iterating over the modules, and if so, we skip the query to debuginfod\n+     and just try with the other default methods.\n+\n+     Note this ONLY affects the symbol resolution when retrieving a backtrace,\n+     and it doesn't affect offline symbolication.  */\n+  debuginfod_guard++;\n   dl_iterate_phdr (phdr_callback, (void *) &pd);\n+  debuginfod_guard--;\n \n   if (!state->threaded)\n     {\n-- \n2.42.3\n\n"
  },
  {
    "path": "src/vendor/regenerate_libbacktrace.sh",
    "content": "#!/usr/bin/env bash\nset -Eeuo pipefail\n\nif [[ $# -ne 0 ]] && [[ $# -ne 1 ]]; then\n    echo \"Usage: $0 [new-commit]\"\n    exit 1\nfi\n\nold_snapshot=7e2b7da3d6568d2e4e78658f22e701746a48d7e1\nnew_snapshot=${1:-}\n\necho \">>> Cloning libbacktrace\"\nrm -rf libbacktrace\ngit clone https://github.com/ianlancetaylor/libbacktrace.git libbacktrace\n\necho \"Applying patches\"\ncd libbacktrace\ngit checkout \"$old_snapshot\"\ngit am ../libbacktrace-patches/*\n\nif [[ -n \"$new_snapshot\" ]]; then\n    echo \"Rebasing on $new_snapshot\"\n    if git rebase \"$new_snapshot\"; then\n        echo \"Rebased successfully. Updating patches.\"\n        (cd ../libbacktrace-patches && git rm -f 0*)\n        git format-patch \"$new_snapshot\" --no-numbered --output-directory=../libbacktrace-patches\n        (cd ../libbacktrace-patches && git add 0*)\n    else\n        echo \"Failed to apply patches. You must finish rebasing manually.\"\n        echo \"When you are satisfied, update the patches by running:\"\n        echo \"  git format-patch $new_snapshot --no-numbered --output-directory=../libbacktrace-patches\"\n        echo \"Be sure to remove the old patches first if the file names will change.\"\n        exit 1\n    fi\nfi\n\nrm -rf .git\n\necho \"Regenerated vendored libbacktrace\"\n"
  },
  {
    "path": "tests/__init__.py",
    "content": ""
  },
  {
    "path": "tests/conftest.py",
    "content": "import socket\nimport sys\n\nimport pytest\nfrom packaging import version\n\nSNAPSHOT_MINIMUM_VERSIONS = {\n    \"textual\": \"6.8.0\",\n    \"pytest-textual-snapshot\": \"1.1.0\",\n}\n\n\n@pytest.fixture\ndef free_port():\n    s = socket.socket()\n    s.bind((\"\", 0))\n    port_number = s.getsockname()[1]\n    s.close()\n    return port_number\n\n\ndef _snapshot_skip_reason():\n    if sys.version_info < (3, 8):\n        # Every version available for 3.7 is too old\n        return f\"snapshot tests require textual>={SNAPSHOT_MINIMUM_VERSIONS['textual']}\"\n\n    from importlib import metadata  # Added in 3.8\n\n    for lib, min_ver in SNAPSHOT_MINIMUM_VERSIONS.items():\n        try:\n            ver = version.parse(metadata.version(lib))\n        except ImportError:\n            return f\"snapshot tests require {lib} but it is not installed\"\n\n        if ver < version.parse(min_ver):\n            return f\"snapshot tests require {lib}>={min_ver} but {ver} is installed\"\n\n    return None\n\n\ndef pytest_configure(config):\n    if config.option.update_snapshots:\n        from importlib import metadata  # Added in 3.8\n\n        for lib, min_ver in SNAPSHOT_MINIMUM_VERSIONS.items():\n            ver = version.parse(metadata.version(lib))\n            if ver != version.parse(min_ver):\n                pytest.exit(\n                    f\"snapshots must be generated with {lib}=={min_ver}\"\n                    f\" or SNAPSHOT_MINIMUM_VERSIONS must be updated to {ver}\"\n                    f\" in {__file__}\"\n                )\n        return\n\n    reason = _snapshot_skip_reason()\n    if reason:\n        config.issue_config_time_warning(UserWarning(reason), stacklevel=2)\n        config.option.warn_unused_snapshots = True\n\n\ndef pytest_collection_modifyitems(config, items):\n    reason = _snapshot_skip_reason()\n    if reason:\n        for item in items:\n            if \"snap_compare\" in item.fixturenames:\n                item.add_marker(pytest.mark.skip(reason=reason))\n"
  },
  {
    "path": "tests/integration/__init__.py",
    "content": ""
  },
  {
    "path": "tests/integration/misbehaving_extension/__init__.py",
    "content": ""
  },
  {
    "path": "tests/integration/misbehaving_extension/misbehaving.cpp",
    "content": "#define PY_SSIZE_T_CLEAN\n#include <Python.h>\n\n#include <dlfcn.h>\n#include <assert.h>\n#include <pthread.h>\n\n#ifdef __linux__\n#include <malloc.h>\n#endif\n\npthread_t thread;\n\nvoid*\nworker(void* args)\n{\n    PyGILState_STATE gstate = PyGILState_Ensure();\n    PyObject* callback = (PyObject*) args;\n    PyObject* result = PyObject_CallFunction(callback, NULL);\n    assert(result != NULL);\n    Py_DECREF(result);\n    PyGILState_Release(gstate);\n    return NULL;\n}\n\nvoid start_threads(void* args)\n{\n    int ret = pthread_create(&thread, NULL, &worker, args);\n    assert(0 == ret);\n}\n\nvoid join_threads()\n{\n    pthread_join(thread, NULL);\n}\n\nPyObject* dlopen_self(PyObject *, PyObject *args) {\n    PyObject* callback;\n    if (!PyArg_ParseTuple(args,\"O\", &callback))\n    {\n        PyErr_SetString(PyExc_ValueError, \"Failed to parse arguments\");\n        Py_RETURN_NONE;\n    }\n    Py_BEGIN_ALLOW_THREADS\n    void* p = dlopen(NULL, RTLD_NOW);\n    dlclose(p);\n    Py_END_ALLOW_THREADS\n\n    PyObject* result = PyObject_CallFunction(callback, NULL);\n    assert(result != NULL);\n    Py_DECREF(result);\n\n    Py_RETURN_NONE;\n}\n\nPyObject*\ncall_fn(PyObject*, PyObject* args)\n{\n    PyObject* callback;\n    if (!PyArg_ParseTuple(args,\"O\", &callback))\n    {\n        PyErr_SetString(PyExc_ValueError, \"Failed to parse arguments\");\n        Py_RETURN_NONE;\n    }\n    Py_BEGIN_ALLOW_THREADS\n    start_threads(callback);\n    join_threads();\n    Py_END_ALLOW_THREADS\n    Py_RETURN_NONE;\n}\n\nPyObject*\ncall_fn_no_thread(PyObject*, PyObject* args)\n{\n    PyObject* callback;\n    if (!PyArg_ParseTuple(args,\"O\", &callback))\n    {\n        PyErr_SetString(PyExc_ValueError, \"Failed to parse arguments\");\n        Py_RETURN_NONE;\n    }\n    worker(callback);\n    Py_RETURN_NONE;\n}\n\n\n\nstatic PyMethodDef methods[] = {\n        {\"dlopen_self\", dlopen_self, METH_VARARGS, \"Call dlopen without the GIL\"},\n        {\"call_fn\", call_fn, METH_VARARGS, \"Call Python function on a thread\"},\n        {\"call_fn_no_thread\", call_fn_no_thread, METH_VARARGS, \"Call Python function with PyGILState_Ensure\"},\n        {NULL, NULL, 0, NULL},\n};\n\nstatic struct PyModuleDef moduledef = {PyModuleDef_HEAD_INIT, \"misbehaving\", \"\", -1, methods};\n\nPyMODINIT_FUNC\nPyInit_misbehaving(void)\n{\n    PyObject *mod = PyModule_Create(&moduledef);\n#ifdef Py_GIL_DISABLED\n    PyUnstable_Module_SetGIL(mod, Py_MOD_GIL_NOT_USED);\n#endif\n    return mod;\n}\n"
  },
  {
    "path": "tests/integration/misbehaving_extension/setup.py",
    "content": "import os\nimport sysconfig\nfrom distutils.core import Extension\nfrom distutils.core import setup\n\nROOT = os.path.realpath(os.path.dirname(__file__))\nLDSHARED = os.environ.get(\"LDSHARED\", sysconfig.get_config_var(\"LDSHARED\"))\nif LDSHARED:\n    LDSHARED = LDSHARED.replace(\"--strip-all\", \"-g\")\n    os.environ[\"LDSHARED\"] = LDSHARED\n\nsetup(\n    name=\"misbehaving\",\n    version=\"0.0\",\n    ext_modules=[\n        Extension(\n            \"misbehaving\",\n            language=\"c++\",\n            sources=[os.path.join(ROOT, \"misbehaving.cpp\")],\n        ),\n    ],\n    zip_safe=False,\n)\n"
  },
  {
    "path": "tests/integration/multithreaded_extension/__init__.py",
    "content": ""
  },
  {
    "path": "tests/integration/multithreaded_extension/main.py",
    "content": "import sys\n\nimport testext\n\n\ndef foo():\n    fifo = sys.argv[1]\n    with open(sys.argv[1], \"w\") as fifo:\n        fifo.write(\"ready\")\n    testext.sleep10()\n\n\nfoo()\n"
  },
  {
    "path": "tests/integration/multithreaded_extension/setup.py",
    "content": "import os\nimport sysconfig\nfrom distutils.core import Extension\nfrom distutils.core import setup\n\nROOT = os.path.realpath(os.path.dirname(__file__))\nLDSHARED = os.environ.get(\"LDSHARED\", sysconfig.get_config_var(\"LDSHARED\"))\nif LDSHARED:\n    LDSHARED = LDSHARED.replace(\"--strip-all\", \"-g\")\n    os.environ[\"LDSHARED\"] = LDSHARED\n\nsetup(\n    name=\"testext\",\n    version=\"0.0\",\n    ext_modules=[\n        Extension(\n            \"testext\",\n            language=\"c++\",\n            sources=[os.path.join(ROOT, \"testext.cpp\")],\n            extra_compile_args=[\"-O0\", \"-g3\"],\n        ),\n    ],\n    zip_safe=False,\n)\n"
  },
  {
    "path": "tests/integration/multithreaded_extension/testext.cpp",
    "content": "#define PY_SSIZE_T_CLEAN\n#include <Python.h>\n\n#include <assert.h>\n#include <pthread.h>\n\n#ifdef __linux__\n#include <malloc.h>\n#endif\n\nnamespace {  // unnamed\n\n#pragma GCC push_options\n#pragma GCC optimize (\"O0\")\n\nconst int NUM_THREADS = 100;\nconst int NUM_BUFFERS = 100;\npthread_t threads[NUM_THREADS];\n\nextern \"C\" void\nallocate_memory()\n{\n    unsigned long* buffers[NUM_BUFFERS];\n    for (int i=0; i < NUM_BUFFERS; ++i) {\n        int ret = posix_memalign((void**)buffers+i, sizeof(void*), sizeof(void*)*(i+1));\n        if (ret) {\n            buffers[i] = NULL;\n            break;\n        }\n    }\n    for (int i=0; i < NUM_BUFFERS; ++i) {\n        free(buffers[i]);\n    }\n}\n\nextern \"C\" void*\nworker(void*)\n{\n    allocate_memory();\n    return NULL;\n}\n\nvoid start_threads()\n{\n    for (int i=0; i<NUM_THREADS; ++i) {\n        pthread_t thread;\n        int ret = pthread_create(&thread, NULL, &worker, NULL);\n        assert(0 == ret);\n        threads[i] = thread;\n    }\n}\n\nvoid join_threads()\n{\n    for (int i=0; i<NUM_THREADS; ++i) {\n        pthread_join(threads[i], NULL);\n    }\n}\n\n__attribute__((optnone)) static void cleanup_handler(void* arg) {\n  void* data = valloc(sizeof(int));\n  free(data);\n}\n\nstatic void* create_tls_in_thread(void *arg) {\n  pthread_key_t thread_specific_storage;\n  pthread_key_create(&thread_specific_storage, cleanup_handler);\n  pthread_setspecific(thread_specific_storage, (void*)12);\n  pthread_exit(NULL);\n  return NULL;\n}\n\nvoid valloc_on_thread_exit() {\n  pthread_t thread_id;\n  void *result;\n  pthread_create(&thread_id, NULL, create_tls_in_thread, NULL);\n  pthread_join(thread_id, &result);\n}\n\nPyObject*\nrun(PyObject*, PyObject*)\n{\n    start_threads();\n    join_threads();\n    Py_RETURN_NONE;\n}\n\nPyObject*\nrun_valloc_at_exit(PyObject*, PyObject*)\n{\n    valloc_on_thread_exit();\n    Py_RETURN_NONE;\n}\n\n#pragma GCC pop_options\n\n}  // unnamed namespace\n\nstatic PyMethodDef methods[] = {\n        {\"run\", run, METH_NOARGS, \"Run a bunch of threads\"},\n        {\"run_valloc_at_exit\", run_valloc_at_exit, METH_NOARGS, \"Run valloc while exiting a thread\"},\n        {NULL, NULL, 0, NULL},\n};\n\nstatic struct PyModuleDef moduledef = {PyModuleDef_HEAD_INIT, \"testext\", \"\", -1, methods};\n\nPyMODINIT_FUNC\nPyInit_testext(void)\n{\n    PyObject *mod = PyModule_Create(&moduledef);\n#ifdef Py_GIL_DISABLED\n    PyUnstable_Module_SetGIL(mod, Py_MOD_GIL_NOT_USED);\n#endif\n    return mod;\n}\n"
  },
  {
    "path": "tests/integration/native_extension/main.py",
    "content": "import sys\n\nimport testext\n\n\ndef foo():\n    fifo = sys.argv[1]\n    with open(sys.argv[1], \"w\") as fifo:\n        fifo.write(\"ready\")\n    testext.sleep10()\n\n\nfoo()\n"
  },
  {
    "path": "tests/integration/native_extension/native_ext.c",
    "content": "#define PY_SSIZE_T_CLEAN\n#include <Python.h>\n\n#include <assert.h>\n#include <pthread.h>\n#ifdef __linux__\n#include <malloc.h>\n#endif\n\n#pragma GCC push_options\n#pragma GCC optimize (\"O0\")\n\n// Regular call chain\n//\n__attribute__((noinline)) static void baz() {\n    void* p = valloc(1234);\n    free(p);\n}\n\n__attribute__((noinline)) static void bar() {\n    baz();\n}\n\n__attribute__((noinline)) static void foo() {\n    bar();\n}\n\nPyObject*\nrun_simple(PyObject* mod , PyObject* arg)\n{\n    foo();\n    Py_RETURN_NONE;\n}\n\n// Inlined call chain\n\n__attribute__((always_inline)) static inline void baz_inline() {\n    void *p = valloc(1234);\n    free(p);\n}\n\n__attribute__((always_inline)) static inline void bar_inline() {\n    baz_inline();\n}\n\n__attribute__((always_inline)) static inline void foo_inline() {\n    bar_inline();\n}\n\nPyObject*\nrun_inline(PyObject* mod, PyObject* arg)\n{\n    foo_inline();\n    Py_RETURN_NONE;\n}\n\nvoid* thread_worker(void* arg)\n{\n    foo();\n    return NULL;\n}\n\nPyObject*\nrun_in_thread(PyObject* mod, PyObject* arg)\n{\n    pthread_t thread;\n    pthread_create(&thread, NULL, &thread_worker, NULL);\n    pthread_join(thread, NULL);\n    Py_RETURN_NONE;\n}\n\nvoid deep_call(long n) {\n    if (n == 0) {\n        return foo();\n    }\n    return deep_call(n-1);\n}\n\nPyObject*\nrun_deep(PyObject* mod, PyObject* n_stack)\n{\n    long n = PyLong_AsLong(n_stack);\n    if (n == -1 && PyErr_Occurred()) {\n        return NULL;\n    }\n    deep_call(n);\n    Py_RETURN_NONE;\n}\n\n\nPyObject*\nrun_recursive(PyObject* mod, PyObject* args)\n{\n    long n;\n    PyObject* callback;\n    if (!PyArg_ParseTuple(args, \"lO\", &n, &callback)) {\n        return NULL;\n    }\n    if (n <= 0) {\n        foo();\n        Py_RETURN_NONE;\n    }\n    return PyObject_CallFunction(callback, \"i\", n-1);\n}\n\n#pragma GCC pop_options\n\nstatic PyMethodDef methods[] = {\n        {\"run_simple\", run_simple, METH_NOARGS, \"Execute a chain of native functions\"},\n        {\"run_inline\", run_inline, METH_NOARGS, \"Execute a chain of native inlined_functions\"},\n        {\"run_in_thread\", run_in_thread, METH_NOARGS, \"Like run_simple, but in a bg thread\"},\n        {\"run_deep\", run_deep, METH_O, \"Execute a chain of native inlined functions in a deep stack\"},\n        {\"run_recursive\", run_recursive, METH_VARARGS, \"Execute a callback if the second argument is bigger than 0\"},\n        {NULL, NULL, 0, NULL},\n};\n\nstatic struct PyModuleDef moduledef = {PyModuleDef_HEAD_INIT, \"native_ext\", \"\", -1, methods};\n\nPyMODINIT_FUNC\nPyInit_native_ext(void)\n{\n    PyObject *mod = PyModule_Create(&moduledef);\n#ifdef Py_GIL_DISABLED\n    PyUnstable_Module_SetGIL(mod, Py_MOD_GIL_NOT_USED);\n#endif\n    return mod;\n}\n"
  },
  {
    "path": "tests/integration/native_extension/setup.py",
    "content": "import os\nimport sysconfig\nfrom distutils.core import Extension\nfrom distutils.core import setup\n\nROOT = os.path.realpath(os.path.dirname(__file__))\nLDSHARED = os.environ.get(\"LDSHARED\", sysconfig.get_config_var(\"LDSHARED\"))\nif LDSHARED:\n    LDSHARED = LDSHARED.replace(\"--strip-all\", \"-g\")\n    os.environ[\"LDSHARED\"] = LDSHARED\n\nsetup(\n    name=\"native_ext\",\n    version=\"0.0\",\n    ext_modules=[\n        Extension(\n            \"native_ext\",\n            language=\"c\",\n            sources=[os.path.join(ROOT, \"native_ext.c\")],\n            extra_compile_args=[\"-O0\", \"-g3\"],\n        ),\n    ],\n    zip_safe=False,\n)\n"
  },
  {
    "path": "tests/integration/rpath_extension/ext.c",
    "content": "#include <Python.h>\n#include <dlfcn.h>\n\n\nstatic PyObject *hello_world(PyObject *self, PyObject *args) {\n    // Load the shared library\n    void *lib_handle = dlopen(\"sharedlib.so\", RTLD_LAZY);\n\n    if (!lib_handle) {\n        PyErr_SetString(PyExc_RuntimeError, dlerror());\n        return NULL;\n    }\n\n    // Get the function pointer\n    void (*my_shared_function)() = dlsym(lib_handle, \"my_shared_function\");\n    if (!my_shared_function) {\n        PyErr_SetString(PyExc_RuntimeError, dlerror());\n        dlclose(lib_handle);\n        return NULL;\n    }\n\n    // Call the function\n    my_shared_function();\n\n    // Close the shared library\n    dlclose(lib_handle);\n\n    Py_RETURN_NONE;\n}\n\nstatic PyMethodDef methods[] = {\n    {\"hello_world\", hello_world, METH_NOARGS, \"Print Hello, World!\"},\n    {NULL, NULL, 0, NULL}\n};\n\nstatic struct PyModuleDef module = {\n    PyModuleDef_HEAD_INIT,\n    \"ext\",\n    NULL,\n    -1,\n    methods\n};\n\nPyMODINIT_FUNC PyInit_ext(void) {\n    PyObject *mod = PyModule_Create(&module);\n#ifdef Py_GIL_DISABLED\n    PyUnstable_Module_SetGIL(mod, Py_MOD_GIL_NOT_USED);\n#endif\n    return mod;\n}\n"
  },
  {
    "path": "tests/integration/rpath_extension/setup.py",
    "content": "import subprocess\n\nfrom setuptools import Extension\nfrom setuptools import setup\n\n# Compile the shared library before building the extension\nsubprocess.run(\n    [\"gcc\", \"-shared\", \"-o\", \"sharedlibs/sharedlib.so\", \"sharedlibs/sharedlib.c\"]\n)\n\n\nsetup(\n    name=\"ext\",\n    version=\"1.0\",\n    ext_modules=[\n        Extension(\n            \"ext\",\n            sources=[\"ext.c\"],\n            extra_link_args=[\"-Wl,-rpath,$ORIGIN/sharedlibs\"],\n        )\n    ],\n)\n"
  },
  {
    "path": "tests/integration/rpath_extension/sharedlibs/sharedlib.c",
    "content": "#include <stdio.h>\n\nvoid my_shared_function() {\n    printf(\"This is a function from your_shared_lib!\\n\");\n}\n"
  },
  {
    "path": "tests/integration/test_api.py",
    "content": "\"\"\"Tests for exercising the public API.\"\"\"\n\nimport pytest\n\nfrom memray import FileDestination\nfrom memray import FileFormat\nfrom memray import FileReader\nfrom memray import SocketDestination\nfrom memray import Tracker\nfrom memray._test import MemoryAllocator\nfrom tests.utils import filter_relevant_allocations\n\n\ndef test_file_reader_as_context_manager(tmp_path):\n    # GIVEN\n    allocator = MemoryAllocator()\n    result_file = tmp_path / \"test.bin\"\n    # WHEN\n    with Tracker(result_file):\n        allocator.valloc(1234)\n        allocator.free()\n\n    # THEN\n    with FileReader(result_file) as reader:\n        pass\n\n    with pytest.raises(ValueError, match=\"Operation on a closed FileReader\"):\n        list(reader.get_high_watermark_allocation_records())\n\n\ndef test_file_destination(tmp_path):\n    # GIVEN\n    allocator = MemoryAllocator()\n    result_file = tmp_path / \"test.bin\"\n    # WHEN\n    with Tracker(destination=FileDestination(result_file)):\n        allocator.valloc(1234)\n        allocator.free()\n\n    # THEN\n    with FileReader(result_file) as reader:\n        all_allocations = reader.get_allocation_records()\n        vallocs_and_their_frees = list(filter_relevant_allocations(all_allocations))\n        assert len(vallocs_and_their_frees) == 2\n\n\ndef test_file_destination_str_path(tmp_path):\n    # GIVEN\n    allocator = MemoryAllocator()\n    result_file = str(tmp_path / \"test.bin\")\n    # WHEN\n    with Tracker(destination=FileDestination(result_file)):\n        allocator.valloc(1234)\n        allocator.free()\n\n    # THEN\n    with FileReader(result_file) as reader:\n        all_allocations = reader.get_allocation_records()\n        vallocs_and_their_frees = list(filter_relevant_allocations(all_allocations))\n        assert len(vallocs_and_their_frees) == 2\n\n\ndef test_combine_destination_args():\n    \"\"\"Combining `writer` and `file_name` arguments in the `Tracker` should\n    raise an exception.\"\"\"\n\n    # GIVEN/WHEN/THEN\n    with pytest.raises(\n        TypeError,\n        match=\"Exactly one of 'file_name' or 'destination' argument must be specified\",\n    ):\n        with Tracker(destination=SocketDestination(server_port=1234), file_name=\"foo\"):\n            pass\n\n\ndef test_no_destination_arg():\n    \"\"\"Not passing either `writer` or `file_name` argument in the `Tracker` should\n    raise an exception.\"\"\"\n\n    # GIVEN/WHEN/THEN\n    with pytest.raises(\n        TypeError,\n        match=\"Exactly one of 'file_name' or 'destination' argument must be specified\",\n    ):\n        with Tracker():  # pragma: no cover\n            pass\n\n\ndef test_follow_fork_with_socket_destination():\n    # GIVEN\n    with pytest.raises(RuntimeError, match=\"follow_fork requires an output file\"):\n        with Tracker(\n            destination=SocketDestination(server_port=1234), follow_fork=True\n        ):  # pragma: no cover\n            pass\n\n\ndef test_aggregated_capture_with_socket_destination():\n    # GIVEN\n    with pytest.raises(\n        RuntimeError, match=\"AGGREGATED_ALLOCATIONS requires an output file\"\n    ):\n        with Tracker(\n            destination=SocketDestination(server_port=1234),\n            file_format=FileFormat.AGGREGATED_ALLOCATIONS,\n        ):  # pragma: no cover\n            pass\n"
  },
  {
    "path": "tests/integration/test_attach.py",
    "content": "import functools\nimport subprocess\nimport sys\n\nimport pytest\n\nfrom memray import AllocatorType\nfrom memray import FileReader\nfrom memray.commands.attach import debugger_available\nfrom tests.utils import filter_relevant_allocations\n\nPROGRAM = \"\"\"\nimport sys\nimport threading\nimport time\n\nfrom memray._test import MemoryAllocator\n\nstop_looping = threading.Event()\n\n\ndef io_thread_body():\n    print(\"ready\")\n    for line in sys.stdin:\n        stop_looping.set()\n\n\ndef alloc_thread_body():\n    while not stop_looping.is_set():\n        allocator = MemoryAllocator()\n        allocator.malloc(1024)\n        allocator.free()\n\n\ndef foo():\n    bar()\n\n\ndef bar():\n    baz()\n\n\ndef baz():\n    allocator = MemoryAllocator()\n    allocator.valloc(50 * 1024 * 1024)\n    allocator.free()\n\n\n# Debugger attaches wait for allocator or deallocator calls, so we can't just\n# block waiting for a signal. Allocate and free in a loop in the background.\n# Additionally, there must be a Python loop in the main thread, because that's\n# the thread `sys.remote_exec` attaches to and it needs the eval breaker. Spawn\n# another background thread to let us know when to stop looping.\nio_thread = threading.Thread(target=io_thread_body)\nio_thread.start()\n\nalloc_thread = threading.Thread(target=alloc_thread_body)\nalloc_thread.start()\n\nwhile not stop_looping.is_set():\n    time.sleep(0.1)\n\nalloc_thread.join()\nio_thread.join()\n\nfoo()\n\"\"\"\n\n\ndef generate_attach_command(method, output, *args):\n    cmd = [\n        sys.executable,\n        \"-m\",\n        \"memray\",\n        \"attach\",\n        \"--verbose\",\n        \"--force\",\n        \"--method\",\n        method,\n        \"-o\",\n        str(output),\n    ]\n\n    if args:\n        cmd.extend(args)\n\n    return cmd\n\n\ndef generate_detach_command(method, *args):\n    cmd = [\n        sys.executable,\n        \"-m\",\n        \"memray\",\n        \"detach\",\n        \"--verbose\",\n        \"--method\",\n        method,\n    ]\n\n    if args:\n        cmd.extend(args)\n\n    return cmd\n\n\ndef run_process(cmd, wait_for_stderr=False):\n    process_stderr = \"\"\n    tracked_process = subprocess.Popen(\n        [sys.executable, \"-Wignore\", \"-uc\", PROGRAM],\n        stdin=subprocess.PIPE,\n        stdout=subprocess.PIPE,\n        stderr=subprocess.PIPE,\n        text=True,\n    )\n\n    # Help the type checker out...\n    assert tracked_process.stdin is not None\n    assert tracked_process.stdout is not None\n\n    assert tracked_process.stdout.readline() == \"ready\\n\"\n\n    cmd.append(str(tracked_process.pid))\n\n    # WHEN\n    try:\n        subprocess.check_output(cmd, stderr=subprocess.STDOUT, text=True)\n    except subprocess.CalledProcessError as exc:\n        # The test has failed; we'd just wait forever.\n        wait_for_stderr = False\n\n        if \"Couldn't write extended state status\" in exc.output:\n            # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=898048\n            pytest.xfail(\"gdb < 8 does not support this CPU\")\n        else:\n            print(exc.output)\n            raise\n    finally:\n        print(\"1\", file=tracked_process.stdin, flush=True)\n        if wait_for_stderr:\n            process_stderr = tracked_process.stderr.readline()\n            # Skip any lines like 'WARNING: Correcting symbol for malloc'\n            while \"warning\" in process_stderr.lower():\n                process_stderr = tracked_process.stderr.readline()\n        tracked_process.stdin.close()\n        tracked_process.wait()\n\n    # THEN\n    assert \"\" == tracked_process.stdout.read()\n    assert tracked_process.returncode == 0\n    return process_stderr\n\n\ndef get_call_stack(allocation):\n    return [f[0] for f in allocation.stack_trace()]\n\n\ndef get_relevant_vallocs(records):\n    return [\n        record\n        for record in filter_relevant_allocations(records)\n        if record.allocator == AllocatorType.VALLOC\n    ]\n\n\n@functools.lru_cache(maxsize=None)\ndef debugging_method_works(method):\n    proc = subprocess.Popen(\n        [sys.executable, \"-Wignore\", \"-uc\", r'input(\"ready\\n\")'],\n        stdin=subprocess.PIPE,\n        stdout=subprocess.PIPE,\n        text=True,\n    )\n    assert proc.stdout.readline() == \"ready\\n\"\n    try:\n        if method == \"sys.remote_exec\":\n            cmd = [\n                sys.executable,\n                \"-uc\",\n                f\"import sys; sys.remote_exec({proc.pid}, '/dev/null')\",\n            ]\n        elif method == \"gdb\":\n            cmd = [\"gdb\", \"-batch\", \"-p\", str(proc.pid)]\n        elif method == \"lldb\":\n            cmd = [\"lldb\", \"--batch\", \"-p\", str(proc.pid)]\n        else:\n            raise ValueError(f\"Unknown method: {method}\")\n\n        try:\n            subprocess.check_call(cmd)\n            return True\n        except Exception:\n            return False\n    finally:\n        proc.terminate()\n        proc.wait()\n\n\ndef skip_if_not_supported(method):\n    if not debugger_available(method):\n        pytest.skip(f\"{method} isn't available\")\n\n    if not debugging_method_works(method):\n        pytest.skip(f\"{method} cannot attach to remote processes on this system\")\n\n\n@pytest.mark.parametrize(\"method\", [\"sys.remote_exec\", \"lldb\", \"gdb\"])\ndef test_basic_attach(tmp_path, method):\n    skip_if_not_supported(method)\n\n    # GIVEN\n    output = tmp_path / \"test.bin\"\n    attach_cmd = generate_attach_command(method, output)\n\n    # WHEN\n    run_process(attach_cmd)\n\n    # THEN\n    reader = FileReader(output)\n    (valloc,) = get_relevant_vallocs(reader.get_allocation_records())\n    assert get_call_stack(valloc) == [\"valloc\", \"baz\", \"bar\", \"foo\", \"<module>\"]\n\n\n@pytest.mark.parametrize(\"method\", [\"sys.remote_exec\", \"lldb\", \"gdb\"])\ndef test_aggregated_attach(tmp_path, method):\n    skip_if_not_supported(method)\n\n    # GIVEN\n    output = tmp_path / \"test.bin\"\n    attach_cmd = generate_attach_command(method, output, \"--aggregate\")\n\n    # WHEN\n    run_process(attach_cmd)\n\n    # THEN\n    reader = FileReader(output)\n    with pytest.raises(\n        NotImplementedError,\n        match=\"Can't get all allocations from a pre-aggregated capture file.\",\n    ):\n        list(reader.get_allocation_records())\n\n    (valloc,) = get_relevant_vallocs(reader.get_high_watermark_allocation_records())\n    assert get_call_stack(valloc) == [\"valloc\", \"baz\", \"bar\", \"foo\", \"<module>\"]\n\n\n@pytest.mark.parametrize(\"method\", [\"sys.remote_exec\", \"lldb\", \"gdb\"])\ndef test_attach_time(tmp_path, method):\n    skip_if_not_supported(method)\n\n    # GIVEN\n    output = tmp_path / \"test.bin\"\n    attach_cmd = generate_attach_command(method, output, \"--duration\", \"1\")\n\n    # WHEN\n    process_stderr = run_process(attach_cmd, wait_for_stderr=True)\n\n    # THEN\n    assert \"memray: Deactivating tracking: 1 seconds have elapsed\" in process_stderr\n\n\n@pytest.mark.parametrize(\"method\", [\"sys.remote_exec\", \"lldb\", \"gdb\"])\ndef test_detach_without_attach(method):\n    skip_if_not_supported(method)\n\n    # GIVEN\n    detach_cmd = generate_detach_command(method)\n\n    # WHEN\n    with pytest.raises(subprocess.CalledProcessError) as exc_info:\n        run_process(detach_cmd)\n\n    # THEN\n    assert (\n        \"Failed to stop tracking in remote process:\"\n        \" no previous `memray attach` call detected\"\n    ) in exc_info.value.stdout\n"
  },
  {
    "path": "tests/integration/test_extensions.py",
    "content": "import shutil\nimport subprocess\nimport sys\nfrom pathlib import Path\nfrom textwrap import dedent\n\nimport pytest\n\nfrom memray import AllocatorType\nfrom memray import FileReader\nfrom memray import Tracker\nfrom memray._test import MemoryAllocator\n\nHERE = Path(__file__).parent\nTEST_MULTITHREADED_EXTENSION = HERE / \"multithreaded_extension\"\nTEST_MISBEHAVING_EXTENSION = HERE / \"misbehaving_extension\"\nTEST_RPATH_EXTENSION = HERE / \"rpath_extension\"\n\n\n@pytest.mark.valgrind\ndef test_multithreaded_extension(tmpdir, monkeypatch):\n    \"\"\"Test tracking allocations in a native extension which spawns multiple threads,\n    each thread allocating and freeing memory.\"\"\"\n    # GIVEN\n    output = Path(tmpdir) / \"test.bin\"\n    extension_name = \"multithreaded_extension\"\n    extension_path = tmpdir / extension_name\n    shutil.copytree(TEST_MULTITHREADED_EXTENSION, extension_path)\n    subprocess.run(\n        [sys.executable, str(extension_path / \"setup.py\"), \"build_ext\", \"--inplace\"],\n        check=True,\n        cwd=extension_path,\n        capture_output=True,\n    )\n\n    # WHEN\n    with monkeypatch.context() as ctx:\n        ctx.setattr(sys, \"path\", [*sys.path, str(extension_path)])\n        from testext import run  # type: ignore\n\n        with Tracker(output):\n            run()\n\n    # THEN\n    records = list(FileReader(output).get_allocation_records())\n    assert records\n\n    memaligns = [\n        record for record in records if record.allocator == AllocatorType.POSIX_MEMALIGN\n    ]\n    assert len(memaligns) == 100 * 100  # 100 threads allocate 100 times in testext\n\n    # We don't keep track of the native stacks. Make sure they are empty\n    assert all(len(memalign.stack_trace()) == 0 for memalign in memaligns)\n\n    memaligns_addr = {record.address for record in memaligns}\n    memalign_frees = [\n        record\n        for record in records\n        if record.address in memaligns_addr and record.allocator == AllocatorType.FREE\n    ]\n\n    assert len(memalign_frees) >= 100 * 100\n\n\ndef test_misbehaving_extension(tmpdir, monkeypatch):\n    \"\"\"Check that we can correctly track allocations in an extension which invokes\n    Python code in a thread and does not register trace functions.\"\"\"\n    # GIVEN\n    output = Path(tmpdir) / \"test.bin\"\n    extension_name = \"misbehaving_extension\"\n    extension_path = tmpdir / extension_name\n    shutil.copytree(TEST_MISBEHAVING_EXTENSION, extension_path)\n    subprocess.run(\n        [sys.executable, str(extension_path / \"setup.py\"), \"build_ext\", \"--inplace\"],\n        check=True,\n        cwd=extension_path,\n        capture_output=True,\n    )\n\n    def allocating_function():  # pragma: no cover\n        allocator = MemoryAllocator()\n        allocator.valloc(1234)\n        allocator.free()\n\n    # WHEN\n    with monkeypatch.context() as ctx:\n        ctx.setattr(sys, \"path\", [*sys.path, str(extension_path)])\n        from misbehaving import call_fn  # type: ignore\n\n        with Tracker(output):\n            call_fn(allocating_function)\n\n    # THEN\n    allocations = list(FileReader(output).get_allocation_records())\n    allocs = [\n        event\n        for event in allocations\n        if event.size == 1234 and event.allocator == AllocatorType.VALLOC\n    ]\n    assert len(allocs) == 1\n    (alloc,) = allocs\n\n    stack_trace = alloc.stack_trace()\n    assert len(stack_trace)\n\n    *_, bottom_frame = stack_trace\n    func, filename, line = bottom_frame\n    assert func == \"allocating_function\"\n    assert filename.endswith(__file__)\n    assert line == 83\n\n    frees = [\n        event\n        for event in allocations\n        if event.address == alloc.address and event.allocator == AllocatorType.FREE\n    ]\n    assert len(frees) >= 1\n\n\ndef test_extension_that_uses_pygilstate_ensure(tmpdir, monkeypatch):\n    \"\"\"Check that we can correctly track allocations in an extension which invokes\n    Python code in a thread and does not register trace functions.\"\"\"\n    # GIVEN\n    output = Path(tmpdir) / \"test.bin\"\n    extension_name = \"misbehaving_extension\"\n    extension_path = tmpdir / extension_name\n    shutil.copytree(TEST_MISBEHAVING_EXTENSION, extension_path)\n    subprocess.run(\n        [sys.executable, str(extension_path / \"setup.py\"), \"build_ext\", \"--inplace\"],\n        check=True,\n        cwd=extension_path,\n        capture_output=True,\n    )\n\n    def allocating_function():\n        allocator = MemoryAllocator()\n        allocator.valloc(1234)\n        allocator.free()\n\n    def foo1():\n        foo2()\n\n    def foo2():\n        call_fn_no_thread(allocating_function)\n\n    # WHEN\n    with monkeypatch.context() as ctx:\n        ctx.setattr(sys, \"path\", [*sys.path, str(extension_path)])\n        from misbehaving import call_fn_no_thread\n\n        allocator = MemoryAllocator()\n        with Tracker(output):\n            foo1()\n            allocator.valloc(1234)\n            allocator.free()\n\n    # THEN\n    allocations = list(FileReader(output).get_allocation_records())\n    allocs = [\n        event\n        for event in allocations\n        if event.size == 1234 and event.allocator == AllocatorType.VALLOC\n    ]\n    assert len(allocs) == 2\n    (alloc1, alloc2) = allocs\n\n    stack_trace = alloc1.stack_trace()\n    assert len(stack_trace)\n    first_frame, *_, bottom_frame = stack_trace\n    func, filename, line = bottom_frame\n    assert func == \"test_extension_that_uses_pygilstate_ensure\"\n    assert filename.endswith(__file__)\n    assert line == 154\n\n    # We should have 2 frames here: this function calling `allocator.valloc`,\n    # and `allocator.valloc` calling the C `valloc`.\n    # We should not see any call to foo1() or foo2().\n    stack_trace = alloc2.stack_trace()\n    assert len(stack_trace) == 2\n    (callee, caller) = stack_trace\n    func, filename, line = callee\n    assert func == \"valloc\"\n    assert filename.endswith(\"/_test.py\")\n\n    func, filename, line = caller\n    assert func == \"test_extension_that_uses_pygilstate_ensure\"\n    assert filename.endswith(__file__)\n    assert line == 155\n\n    frees = [\n        event\n        for event in allocations\n        if event.address in (alloc1.address, alloc2.address)\n        and event.allocator == AllocatorType.FREE\n    ]\n    assert len(frees) >= 1\n\n\ndef test_native_dlopen(tmpdir, monkeypatch):\n    \"\"\"Check that we can correctly track allocations in an extension which calls\n    dlopen() without the GIL held\"\"\"\n    # GIVEN\n    output = Path(tmpdir) / \"test.bin\"\n    extension_name = \"misbehaving_extension\"\n    extension_path = tmpdir / extension_name\n    shutil.copytree(TEST_MISBEHAVING_EXTENSION, extension_path)\n    subprocess.run(\n        [sys.executable, str(extension_path / \"setup.py\"), \"build_ext\", \"--inplace\"],\n        check=True,\n        cwd=extension_path,\n        capture_output=True,\n    )\n\n    def allocating_function():\n        allocator = MemoryAllocator()\n        allocator.valloc(1234)\n        allocator.free()\n\n    # WHEN\n    with monkeypatch.context() as ctx:\n        ctx.setattr(sys, \"path\", [*sys.path, str(extension_path)])\n        from misbehaving import dlopen_self  # type: ignore\n\n        with Tracker(output):\n            dlopen_self(allocating_function)\n\n    # THEN\n    allocations = list(FileReader(output).get_allocation_records())\n    allocs = [\n        event\n        for event in allocations\n        if event.size == 1234 and event.allocator == AllocatorType.VALLOC\n    ]\n    assert len(allocs) == 1\n    (alloc,) = allocs\n\n    stack_trace = alloc.stack_trace()\n    assert len(stack_trace)\n\n    *_, bottom_frame = stack_trace\n    func, filename, line = bottom_frame\n    assert func == \"test_native_dlopen\"\n    assert filename.endswith(__file__)\n    assert line == 226\n\n    frees = [\n        event\n        for event in allocations\n        if event.address == alloc.address and event.allocator == AllocatorType.FREE\n    ]\n    assert len(frees) >= 1\n\n\n@pytest.mark.valgrind\ndef test_valloc_at_thread_exit(tmpdir, monkeypatch):\n    \"\"\"Test tracking allocations that happen while a thread is shutting down\"\"\"\n    # GIVEN\n    output = Path(tmpdir) / \"test.bin\"\n    extension_name = \"multithreaded_extension\"\n    extension_path = tmpdir / extension_name\n    shutil.copytree(TEST_MULTITHREADED_EXTENSION, extension_path)\n    subprocess.run(\n        [sys.executable, str(extension_path / \"setup.py\"), \"build_ext\", \"--inplace\"],\n        check=True,\n        cwd=extension_path,\n        capture_output=True,\n    )\n\n    # WHEN\n    with monkeypatch.context() as ctx:\n        ctx.setattr(sys, \"path\", [*sys.path, str(extension_path)])\n        from testext import run_valloc_at_exit  # type: ignore\n\n        with Tracker(output, native_traces=True):\n            run_valloc_at_exit()\n\n    # THEN\n    records = list(FileReader(output).get_allocation_records())\n    assert records\n\n    vallocs = [record for record in records if record.allocator == AllocatorType.VALLOC]\n    assert len(vallocs) == 1\n\n\ndef test_valloc_at_thread_exit_in_subprocess(tmpdir, monkeypatch):\n    \"\"\"Test tracking allocations in the destructor of a TLS variable.\n\n    Ensure that TLS variable is created before Memray is imported.\n    \"\"\"\n    # GIVEN\n    output = Path(tmpdir) / \"test.bin\"\n    extension_name = \"multithreaded_extension\"\n    extension_path = tmpdir / extension_name\n    shutil.copytree(TEST_MULTITHREADED_EXTENSION, extension_path)\n    subprocess.run(\n        [sys.executable, str(extension_path / \"setup.py\"), \"build_ext\", \"--inplace\"],\n        check=True,\n        cwd=extension_path,\n        capture_output=True,\n    )\n\n    code = dedent(\n        f\"\"\"\n        from testext import run_valloc_at_exit\n        run_valloc_at_exit()  # First call creates the test extension TLS.\n\n        from memray import Tracker\n        with Tracker({str(output)!r}, native_traces=True):\n            run_valloc_at_exit()\n        \"\"\"\n    )\n\n    # WHEN\n    with monkeypatch.context() as ctx:\n        ctx.setenv(\"PYTHONPATH\", str(extension_path), prepend=\":\")\n        subprocess.run(\n            [sys.executable, \"-c\", code],\n            check=True,\n        )\n\n    # THEN\n    records = list(FileReader(output).get_allocation_records())\n    assert records\n\n    vallocs = [record for record in records if record.allocator == AllocatorType.VALLOC]\n    assert len(vallocs) == 1\n\n\n@pytest.mark.parametrize(\"py_finalize\", [True, False])\ndef test_hard_exit(tmpdir, py_finalize):\n    \"\"\"Test a program that exits directly under the context manager\"\"\"\n\n    # GIVEN\n\n    # Run a program that calls from memray._test.exit under a Tracker context\n    # manager and check that it finishes without error\n\n    output = Path(tmpdir) / \"test.bin\"\n    code = dedent(\n        f\"\"\"\\\n    from memray._test import exit\n    from memray import Tracker\n    with Tracker(\"{output}\"):\n        exit(py_finalize={py_finalize})\n    \"\"\"\n    )\n\n    # WHEN\n    subprocess.run(\n        [sys.executable, \"-c\", code],\n        check=True,\n        capture_output=True,\n    )\n\n    # THEN\n    # No assertions, just check that the program exits without error\n\n\n@pytest.mark.skipif(\n    sys.platform == \"darwin\", reason=\"Test requires a linker that supports $ORIGIN\"\n)\ndef test_dlopen_with_rpath(tmpdir, monkeypatch):\n    # GIVEN\n    output = Path(tmpdir) / \"test.bin\"\n    extension_name = \"sharedlibs\"\n    extension_path = tmpdir / extension_name\n    shutil.copytree(TEST_RPATH_EXTENSION, extension_path)\n    subprocess.run(\n        [sys.executable, str(extension_path / \"setup.py\"), \"build_ext\", \"--inplace\"],\n        check=True,\n        cwd=extension_path,\n        capture_output=True,\n    )\n\n    # WHEN\n    with monkeypatch.context() as ctx:\n        ctx.setattr(sys, \"path\", [*sys.path, str(extension_path)])\n        from ext import hello_world  # type: ignore\n\n        try:\n            hello_world()\n        except RuntimeError:\n            pytest.skip(\"Test requires a linker that supports -rpath\")\n\n        # THEN\n        with Tracker(output):\n            hello_world()\n"
  },
  {
    "path": "tests/integration/test_greenlet.py",
    "content": "import subprocess\nimport sys\nimport textwrap\nfrom pathlib import Path\n\nimport pytest\n\nfrom memray import AllocatorType\nfrom memray import FileReader\nfrom tests.utils import filter_relevant_allocations\n\npytestmark = pytest.mark.skipif(\n    sys.version_info >= (3, 14), reason=\"Greenlet does not yet support Python 3.14\"\n)\n\n\ndef test_integration_with_greenlet(tmpdir):\n    \"\"\"Verify that we can track Python stacks when greenlet is in use.\"\"\"\n    # GIVEN\n    output = Path(tmpdir) / \"test.bin\"\n    subprocess_code = textwrap.dedent(\n        f\"\"\"\n        import greenlet\n\n        from memray import Tracker\n        from memray._test import MemoryAllocator\n\n\n        def apple():\n            banana()\n\n\n        def banana():\n            allocator.valloc(1024 * 10)\n            animal.switch()\n            allocator.valloc(1024 * 30)\n\n\n        def ant():\n            allocator.valloc(1024 * 20)\n            fruit.switch()\n            allocator.valloc(1024 * 40)\n            bat()\n            allocator.valloc(1024 * 60)\n\n\n        def bat():\n            allocator.valloc(1024 * 50)\n\n\n        def test():\n            fruit.switch()\n            assert fruit.dead\n            animal.switch()\n            assert animal.dead\n            allocator.valloc(1024 * 70)\n\n\n        allocator = MemoryAllocator()\n        output = \"{output}\"\n\n        with Tracker(output):\n            fruit = greenlet.greenlet(apple)\n            animal = greenlet.greenlet(ant)\n            test()\n        \"\"\"\n    )\n\n    # WHEN\n    subprocess.run([sys.executable, \"-Xdev\", \"-c\", subprocess_code], timeout=5)\n\n    # THEN\n    reader = FileReader(output)\n    records = list(reader.get_allocation_records())\n    vallocs = [\n        record\n        for record in filter_relevant_allocations(records)\n        if record.allocator == AllocatorType.VALLOC\n    ]\n\n    def stack(alloc):\n        return [frame[0] for frame in alloc.stack_trace()]\n\n    assert stack(vallocs[0]) == [\"valloc\", \"banana\", \"apple\"]\n    assert vallocs[0].size == 10 * 1024\n\n    assert stack(vallocs[1]) == [\"valloc\", \"ant\"]\n    assert vallocs[1].size == 20 * 1024\n\n    assert stack(vallocs[2]) == [\"valloc\", \"banana\", \"apple\"]\n    assert vallocs[2].size == 30 * 1024\n\n    assert stack(vallocs[3]) == [\"valloc\", \"ant\"]\n    assert vallocs[3].size == 40 * 1024\n\n    assert stack(vallocs[4]) == [\"valloc\", \"bat\", \"ant\"]\n    assert vallocs[4].size == 50 * 1024\n\n    assert stack(vallocs[5]) == [\"valloc\", \"ant\"]\n    assert vallocs[5].size == 60 * 1024\n\n    assert stack(vallocs[6]) == [\"valloc\", \"test\", \"<module>\"]\n    assert vallocs[6].size == 70 * 1024\n\n\ndef test_importing_greenlet_after_tracking_starts(tmpdir):\n    # GIVEN\n    output = Path(tmpdir) / \"test.bin\"\n    subprocess_code = textwrap.dedent(\n        f\"\"\"\n        from memray import Tracker\n        from memray._test import MemoryAllocator\n\n\n        def apple():\n            banana()\n\n\n        def banana():\n            allocator.valloc(1024 * 10)\n            animal.switch()\n            allocator.valloc(1024 * 30)\n\n\n        def ant():\n            allocator.valloc(1024 * 20)\n            fruit.switch()\n            allocator.valloc(1024 * 40)\n            bat()\n            allocator.valloc(1024 * 60)\n\n\n        def bat():\n            allocator.valloc(1024 * 50)\n\n\n        def test():\n            fruit.switch()\n            assert fruit.dead\n            animal.switch()\n            assert animal.dead\n            allocator.valloc(1024 * 70)\n\n\n        allocator = MemoryAllocator()\n        output = \"{output}\"\n\n        with Tracker(output):\n            import greenlet\n\n            fruit = greenlet.greenlet(apple)\n            animal = greenlet.greenlet(ant)\n            test()\n        \"\"\"\n    )\n\n    # WHEN\n    subprocess.run([sys.executable, \"-Xdev\", \"-c\", subprocess_code], timeout=5)\n\n    # THEN\n    reader = FileReader(output)\n    records = list(reader.get_allocation_records())\n    vallocs = [\n        record\n        for record in filter_relevant_allocations(records)\n        if record.allocator == AllocatorType.VALLOC\n    ]\n\n    def stack(alloc):\n        return [frame[0] for frame in alloc.stack_trace()]\n\n    assert stack(vallocs[0]) == [\"valloc\", \"banana\", \"apple\"]\n    assert vallocs[0].size == 10 * 1024\n\n    assert stack(vallocs[1]) == [\"valloc\", \"ant\"]\n    assert vallocs[1].size == 20 * 1024\n\n    assert stack(vallocs[2]) == [\"valloc\", \"banana\", \"apple\"]\n    assert vallocs[2].size == 30 * 1024\n\n    assert stack(vallocs[3]) == [\"valloc\", \"ant\"]\n    assert vallocs[3].size == 40 * 1024\n\n    assert stack(vallocs[4]) == [\"valloc\", \"bat\", \"ant\"]\n    assert vallocs[4].size == 50 * 1024\n\n    assert stack(vallocs[5]) == [\"valloc\", \"ant\"]\n    assert vallocs[5].size == 60 * 1024\n\n    assert stack(vallocs[6]) == [\"valloc\", \"test\", \"<module>\"]\n    assert vallocs[6].size == 70 * 1024\n\n    # 0 and 2 are fruit, 1 and 3 and 4 and 5 are animal, 6 is main.\n    assert vallocs[0].tid != vallocs[1].tid != vallocs[6].tid\n    assert vallocs[0].tid == vallocs[2].tid\n    assert vallocs[1].tid == vallocs[3].tid == vallocs[4].tid == vallocs[5].tid\n\n\ndef test_uninstall_profile_in_greenlet(tmpdir):\n    \"\"\"Verify that memray handles profile function changes in greenlets correctly.\"\"\"\n    # GIVEN\n    output = Path(tmpdir) / \"test.bin\"\n    subprocess_code = textwrap.dedent(\n        f\"\"\"\n        import greenlet\n        import sys\n\n        from memray import Tracker\n        from memray._test import MemoryAllocator\n\n        def foo():\n            bar()\n            allocator.valloc(1024 * 10)\n\n        def bar():\n            baz()\n\n        def baz():\n            sys.setprofile(None)\n            other.switch()\n\n        def test():\n            allocator.valloc(1024 * 70)\n            main_greenlet.switch()\n\n\n        allocator = MemoryAllocator()\n        output = \"{output}\"\n\n        with Tracker(output):\n            main_greenlet = greenlet.getcurrent()\n            other = greenlet.greenlet(test)\n            foo()\n\n        \"\"\"\n    )\n\n    # WHEN\n    subprocess.run([sys.executable, \"-Xdev\", \"-c\", subprocess_code], timeout=5)\n\n    # THEN\n    reader = FileReader(output)\n    records = list(reader.get_allocation_records())\n    vallocs = [\n        record\n        for record in filter_relevant_allocations(records)\n        if record.allocator == AllocatorType.VALLOC\n    ]\n\n    def stack(alloc):\n        return [frame[0] for frame in alloc.stack_trace()]\n\n    # Verify allocations and their stack traces (which should be empty\n    # because we remove the tracking function)\n    assert len(vallocs) == 2\n\n    assert stack(vallocs[0]) == []\n    assert vallocs[0].size == 70 * 1024\n\n    assert stack(vallocs[1]) == []\n    assert vallocs[1].size == 10 * 1024\n\n    # Verify thread IDs\n    main_tid = vallocs[0].tid  # inner greenlet\n    outer_tid = vallocs[1].tid  # outer greenlet\n    assert main_tid == outer_tid\n"
  },
  {
    "path": "tests/integration/test_ipython.py",
    "content": "import os\n\nimport pytest\nfrom IPython.core.displaypub import CapturingDisplayPublisher\nfrom IPython.core.interactiveshell import InteractiveShell\nfrom traitlets.config import Config\n\n\ndef run_in_ipython_shell(tmpdir, cells):\n    \"\"\"Run the given cells in an IPython shell and return the HTML output.\"\"\"\n    InteractiveShell.clear_instance()\n\n    config = Config()\n    config.HistoryAccessor.enabled = False  # Disable sqlite history\n    shell = InteractiveShell.instance(\n        display_pub_class=CapturingDisplayPublisher,\n        config=config,\n    )\n    prev_running_dir = os.getcwd()\n    try:\n        os.chdir(tmpdir)\n        for cell in cells:\n            shell.run_cell(cell)\n    finally:\n        os.chdir(prev_running_dir)\n\n    InteractiveShell.clear_instance()\n    try:\n        html = shell.display_pub.outputs[-1][\"data\"][\"text/html\"]\n        return html\n    except IndexError:\n        return None\n\n\n@pytest.mark.filterwarnings(\"ignore\")\nclass TestIPython:\n    def test_ipython_profiling(self, tmpdir):\n        \"\"\"Test that the IPython extension works.\"\"\"\n        # GIVEN\n        code = [\n            \"%load_ext memray\",\n            \"\"\"\n            %%memray_flamegraph\n            x = \"a\" * 10000\n            \"\"\",\n        ]\n\n        # WHEN\n\n        html = run_in_ipython_shell(tmpdir, code)\n\n        # THEN\n\n        assert html is not None\n        assert \"<iframe\" in html\n        assert \"flamegraph.html\" in html\n\n    def test_exception_while_ipython_profiling(self, tmpdir):\n        \"\"\"Test that the IPython extension works even if an exception\n        is raised.\"\"\"\n        # GIVEN\n\n        code = [\n            \"%load_ext memray\",\n            \"\"\"\n            %%memray_flamegraph\n            x = \"a\" * 10000\n            1/0\n            \"\"\",\n        ]\n\n        # WHEN\n\n        html = run_in_ipython_shell(tmpdir, code)\n\n        # THEN\n\n        assert html is not None\n        assert \"<iframe\" in html\n        assert \"flamegraph.html\" in html\n\n    def test_passing_help_argument(self, tmpdir, capsys):\n        # GIVEN\n\n        code = [\n            \"%load_ext memray\",\n            \"\"\"\n            %%memray_flamegraph -h\n            \"\"\",\n        ]\n\n        # WHEN\n\n        html = run_in_ipython_shell(tmpdir, code)\n\n        # THEN\n\n        assert html is None\n        stdout, stderr = capsys.readouterr()\n        assert \"show this help message\" in stdout\n        assert \"\" == stderr\n\n    def test_passing_invalid_argument(self, tmpdir, capsys):\n        # GIVEN\n\n        code = [\n            \"%load_ext memray\",\n            \"\"\"\n            %%memray_flamegraph --oopsie\n            \"\"\",\n        ]\n\n        # WHEN\n\n        html = run_in_ipython_shell(tmpdir, code)\n\n        # THEN\n\n        assert html is None\n        stdout, stderr = capsys.readouterr()\n        assert \"\" == stdout\n        assert \"usage:\" in stderr\n\n    def test_passing_valid_arguments(self, tmpdir, capsys):\n        # GIVEN\n\n        code = [\n            \"%load_ext memray\",\n            \"\"\"\n            %%memray_flamegraph --leaks --max-memory-records 5\n            x = \"a\" * 10000\n            \"\"\",\n        ]\n\n        # WHEN\n\n        html = run_in_ipython_shell(tmpdir, code)\n\n        # THEN\n\n        assert html is not None\n        stdout, _ = capsys.readouterr()\n        assert \"<iframe\" in html\n        assert \"flamegraph.html\" in html\n        assert \"Results saved to\" in stdout\n\n    @pytest.mark.parametrize(\n        \"args,title\",\n        [\n            (\"--temporary-allocation-threshold=2\", \"flamegraph report\"),\n            (\"--leaks\", \"flamegraph report (memory leaks)\"),\n            (\"--temporal\", \"temporal flamegraph report\"),\n            (\"--leaks --temporal\", \"temporal flamegraph report (memory leaks)\"),\n        ],\n    )\n    def test_report_title_by_report_type(self, tmpdir, capsys, args, title):\n        # GIVEN\n        code = [\n            \"%load_ext memray\",\n            f\"\"\"\n            %%memray_flamegraph {args}\n            x = \"a\" * 10000\n            \"\"\",\n        ]\n\n        # WHEN\n        html = run_in_ipython_shell(tmpdir, code)\n\n        # THEN\n        assert html is not None\n        stdout, _ = capsys.readouterr()\n        assert \"<iframe\" in html\n        assert \"flamegraph.html\" in html\n        assert \"Results saved to\" in stdout\n\n        title_tag = f\"<title>memray - {title}</title>\"\n        assert title_tag in next(tmpdir.visit(\"**/flamegraph.html\")).read()\n\n    def test_passing_temporal_and_temporary_allocations(self, tmpdir, capsys):\n        # GIVEN\n        code = [\n            \"%load_ext memray\",\n            \"\"\"\n            %%memray_flamegraph --temporal --temporary-allocation-threshold=2\n            \"\"\",\n        ]\n\n        # WHEN\n        html = run_in_ipython_shell(tmpdir, code)\n\n        # THEN\n        assert html is None\n        stdout, stderr = capsys.readouterr()\n        assert \"\" == stdout\n        assert \"Can't create a temporal flame graph of temporary allocations\" in stderr\n"
  },
  {
    "path": "tests/integration/test_main.py",
    "content": "import contextlib\nimport json\nimport os\nimport platform\nimport pty\nimport re\nimport signal\nimport subprocess\nimport sys\nimport sysconfig\nimport textwrap\nimport time\nfrom pathlib import Path\nfrom unittest.mock import patch\n\nimport pytest\n\nfrom memray import FileFormat\nfrom memray import Tracker\nfrom memray._test import MemoryAllocator\nfrom memray._test import set_thread_name\nfrom memray.commands import main\n\nTIMEOUT = 10\n\n\n@pytest.fixture\ndef simple_test_file(tmp_path):\n    code_file = tmp_path / \"code.py\"\n    program = textwrap.dedent(\n        \"\"\"\\\n        from memray._test import MemoryAllocator\n        print(\"Allocating some memory!\")\n        allocator = MemoryAllocator()\n        allocator.valloc(1024)\n        \"\"\"\n    )\n    code_file.write_text(program)\n    yield code_file\n\n\n@pytest.fixture\ndef test_file_returns_from_fork(tmp_path):\n    code_file = tmp_path / \"code.py\"\n    program = textwrap.dedent(\n        \"\"\"\\\n        import os\n        os.fork()\n        \"\"\"\n    )\n    code_file.write_text(program)\n    yield code_file\n\n\n@contextlib.contextmanager\ndef track_and_wait(output_dir, sleep_after=100):\n    \"\"\"Creates a test script which does some allocations, and upon leaving the context manager,\n    it blocks until the allocations have completed.\"\"\"\n\n    fifo = output_dir / \"snapshot_taken.event\"\n    os.mkfifo(fifo)\n\n    program = textwrap.dedent(\n        f\"\"\"\\\n        import time\n        from memray._test import MemoryAllocator\n        allocator = MemoryAllocator()\n        allocator.valloc(1024)\n        allocator.free()\n        with open(\"{fifo}\", \"w\") as fifo:\n            fifo.write(\"done\")\n        time.sleep({sleep_after})\n        \"\"\"\n    )\n    program_file = output_dir / \"file.py\"\n    program_file.write_text(program)\n    yield program_file\n\n    # Wait until we are tracking\n    with open(fifo, \"r\") as f:\n        assert f.read() == \"done\"\n\n\ndef _wait_until_process_blocks(pid: int) -> None:\n    # Sleep longer on GitHub Actions macOS runners to reduce test flakiness\n    default_sleep = 5.0 if \"GITHUB_ACTIONS\" in os.environ else 1.0\n    if \"linux\" not in sys.platform:\n        time.sleep(default_sleep)\n        return\n    # Signal numbers from https://filippo.io/linux-syscall-table/\n    arch = platform.machine()\n    if arch == \"x86_64\":\n        sleep_syscall = \"35\"\n        connect_syscall = \"42\"\n        accept_syscall = \"43\"\n        clock_nanosleep = \"230\"\n    elif arch == \"aarch64\":\n        sleep_syscall = \"101\"\n        connect_syscall = \"203\"\n        accept_syscall = \"202\"\n        clock_nanosleep = \"115\"\n    else:\n        # No idea what syscalls numbers to wait on, so we will just\n        # sleep for a long enough period and hope for the best\n        time.sleep(default_sleep)\n        return\n    syscalls_to_wait = {sleep_syscall, clock_nanosleep, connect_syscall, accept_syscall}\n    current_syscall = \"\"\n    while True:\n        syscall = Path(f\"/proc/{pid}/syscall\")\n        current_syscall, *_ = syscall.read_text().split()\n        if current_syscall.strip() in syscalls_to_wait:\n            return\n        time.sleep(0.1)\n\n\ndef generate_sample_results(\n    tmp_path,\n    code,\n    *,\n    native=False,\n    trace_python_allocators=False,\n    disable_pymalloc=False,\n):\n    results_file = tmp_path / \"result.bin\"\n    env = os.environ.copy()\n    env[\"PYTHONMALLOC\"] = \"malloc\" if disable_pymalloc else \"default\"\n    subprocess.run(\n        [\n            sys.executable,\n            \"-m\",\n            \"memray\",\n            \"run\",\n            *([\"--native\"] if native else []),\n            *([\"--trace-python-allocators\"] if trace_python_allocators else []),\n            \"--output\",\n            str(results_file),\n            str(code),\n        ],\n        cwd=str(tmp_path),\n        check=True,\n        capture_output=True,\n        text=True,\n        env=env,\n    )\n    return results_file, code\n\n\nclass TestRunSubcommand:\n    def test_run(self, tmp_path, simple_test_file):\n        # GIVEN / WHEN\n        proc = subprocess.run(\n            [\n                sys.executable,\n                \"-m\",\n                \"memray\",\n                \"run\",\n                str(simple_test_file),\n            ],\n            check=True,\n            capture_output=True,\n            text=True,\n            cwd=str(tmp_path),\n        )\n\n        # THEN\n        assert \"Allocating some memory!\" in proc.stdout\n        assert proc.returncode == 0\n        assert \"example commands\" in proc.stdout\n\n        out_file = re.search(\"Writing profile results into (.*)\", proc.stdout).group(1)\n        assert (tmp_path / out_file).exists()\n\n    def test_run_override_output(self, tmp_path, simple_test_file):\n        # GIVEN\n        out_file = tmp_path / \"result.bin\"\n\n        # WHEN\n        proc = subprocess.run(\n            [\n                sys.executable,\n                \"-m\",\n                \"memray\",\n                \"run\",\n                \"--output\",\n                str(out_file),\n                str(simple_test_file),\n            ],\n            check=True,\n            capture_output=True,\n            text=True,\n        )\n\n        # THEN\n        assert \"Allocating some memory!\" in proc.stdout\n        assert proc.returncode == 0\n        assert out_file.exists()\n\n    def test_run_overwrite_output_file(self, tmp_path, simple_test_file):\n        # GIVEN\n        out_file = tmp_path / \"result.bin\"\n        out_file.write_bytes(b\"oops\" * 1024 * 1024)\n        assert out_file.stat().st_size == 4 * 1024 * 1024\n        assert out_file.read_bytes()[:4] == b\"oops\"\n\n        # WHEN\n        proc = subprocess.run(\n            [\n                sys.executable,\n                \"-m\",\n                \"memray\",\n                \"run\",\n                \"--force\",\n                \"--output\",\n                str(out_file),\n                str(simple_test_file),\n            ],\n            check=True,\n            capture_output=True,\n            text=True,\n        )\n\n        # THEN\n        assert \"Allocating some memory!\" in proc.stdout\n        assert proc.returncode == 0\n        assert 0 < out_file.stat().st_size < 4 * 1024 * 1024\n        assert out_file.read_bytes()[:4] != b\"oops\"\n\n    def test_run_file_with_args(self, tmp_path):\n        \"\"\"Execute a Python script and make sure the arguments in the script\n        are correctly forwarded.\"\"\"\n\n        # GIVEN\n        out_file = tmp_path / \"result.bin\"\n        target_file = tmp_path / \"test.py\"\n        target_file.write_text(\n            textwrap.dedent(\n                \"\"\"\\\n        import sys\n        print(f\"Command: {sys.argv[0]}\")\n        print(f\"Arg: {sys.argv[1]}\")\n        \"\"\"\n            )\n        )\n\n        # WHEN\n        proc = subprocess.run(\n            [\n                sys.executable,\n                \"-m\",\n                \"memray\",\n                \"run\",\n                \"--output\",\n                str(out_file),\n                str(target_file),\n                \"arg1\",\n            ],\n            check=True,\n            capture_output=True,\n            text=True,\n        )\n\n        # THEN\n        assert proc.returncode == 0\n        assert re.search(r\"Command: (.*)test\\.py\", proc.stdout)\n        assert \"Arg: arg1\" in proc.stdout\n        assert out_file.exists()\n\n    def test_sys_manipulations_when_running_script(self, tmp_path):\n        # GIVEN\n        out_file = tmp_path / \"result.bin\"\n        target_file = tmp_path / \"test.py\"\n        target_file.write_text(\"import json, sys; print(json.dumps(sys.path))\")\n\n        # WHEN\n        proc = subprocess.run(\n            [\n                sys.executable,\n                \"-m\",\n                \"memray\",\n                \"run\",\n                \"--quiet\",\n                \"--output\",\n                str(out_file),\n                str(target_file),\n                \"some\",\n                \"provided args\",\n            ],\n            check=True,\n            capture_output=True,\n            text=True,\n        )\n\n        # THEN\n        assert out_file.exists()\n        assert proc.returncode == 0\n        # Running `python -m` put cwd in sys.path; ensure we replaced it.\n        path = json.loads(proc.stdout)\n        assert os.getcwd() not in path\n        assert str(tmp_path) in path\n\n    @pytest.mark.parametrize(\n        \"isolation_flag\", [\"-I\"] + ([\"-P\"] if sys.version_info > (3, 11) else [])\n    )\n    def test_suppressing_sys_manipulations_when_running_script(\n        self, tmp_path, isolation_flag\n    ):\n        # GIVEN\n        out_file = tmp_path / \"result.bin\"\n        target_file = tmp_path / \"test.py\"\n        target_file.write_text(\"import json, sys; print(json.dumps(sys.path))\")\n\n        # WHEN\n        proc = subprocess.run(\n            [\n                sys.executable,\n                isolation_flag,\n                \"-m\",\n                \"memray\",\n                \"run\",\n                \"--quiet\",\n                \"--output\",\n                str(out_file),\n                str(target_file),\n                \"some\",\n                \"provided args\",\n            ],\n            check=True,\n            capture_output=True,\n            text=True,\n        )\n\n        # THEN\n        assert out_file.exists()\n        assert proc.returncode == 0\n        # Running `python -m` did not put cwd in sys.path; ensure it isn't\n        # there, and neither is the tmp_path we would have replaced it with.\n        path = json.loads(proc.stdout)\n        assert os.getcwd() not in path\n        assert str(tmp_path) not in path\n\n    def test_sys_manipulations_when_running_module(self, tmp_path):\n        # GIVEN\n        out_file = tmp_path / \"result.bin\"\n\n        # WHEN\n        proc = subprocess.run(\n            [\n                sys.executable,\n                \"-c\",\n                \"import sys; from memray.commands import main; sys.exit(main())\",\n                \"run\",\n                \"--quiet\",\n                \"--output\",\n                str(out_file),\n                \"-m\",\n                \"site\",\n            ],\n            check=True,\n            capture_output=True,\n            text=True,\n        )\n\n        # THEN\n        assert out_file.exists()\n        assert proc.returncode == 0\n        # Running `python -c` put \"\" in sys.path; ensure we replaced it.\n        path = eval(\n            \" \".join(line for line in proc.stdout.splitlines() if line.startswith(\" \"))\n        )\n        assert \"\" not in path\n        assert os.getcwd() in path\n\n    @pytest.mark.parametrize(\n        \"isolation_flag\", [\"-I\"] + ([\"-P\"] if sys.version_info > (3, 11) else [])\n    )\n    def test_suppressing_sys_manipulations_when_running_module(\n        self, tmp_path, isolation_flag\n    ):\n        # GIVEN\n        out_file = tmp_path / \"result.bin\"\n\n        # WHEN\n        proc = subprocess.run(\n            [\n                sys.executable,\n                isolation_flag,\n                \"-c\",\n                \"import sys; from memray.commands import main; sys.exit(main())\",\n                \"run\",\n                \"--quiet\",\n                \"--output\",\n                str(out_file),\n                \"-m\",\n                \"site\",\n            ],\n            check=True,\n            capture_output=True,\n            text=True,\n        )\n\n        # THEN\n        assert out_file.exists()\n        assert proc.returncode == 0\n        # Running `python -c` did not put \"\" in sys.path; ensure it isn't\n        # there, and neither is the os.getcwd() we would have replaced it with.\n        path = eval(\n            \" \".join(line for line in proc.stdout.splitlines() if line.startswith(\" \"))\n        )\n        assert \"\" not in path\n        assert os.getcwd() not in path\n\n    def test_sys_manipulations_when_running_cmd(self, tmp_path):\n        # GIVEN\n        out_file = tmp_path / \"result.bin\"\n\n        # WHEN\n        proc = subprocess.run(\n            [\n                sys.executable,\n                \"-m\",\n                \"memray\",\n                \"run\",\n                \"--quiet\",\n                \"--output\",\n                str(out_file),\n                \"-c\",\n                \"import json, sys; print(json.dumps(sys.path))\",\n            ],\n            check=True,\n            capture_output=True,\n            text=True,\n        )\n\n        # THEN\n        assert out_file.exists()\n        assert proc.returncode == 0\n        # Running `python -m` put cwd in sys.path; ensure we replaced it.\n        path = json.loads(proc.stdout)\n        assert os.getcwd() not in path\n        assert \"\" in path\n\n    @pytest.mark.parametrize(\n        \"isolation_flag\", [\"-I\"] + ([\"-P\"] if sys.version_info > (3, 11) else [])\n    )\n    def test_suppressing_sys_manipulations_when_running_cmd(\n        self, tmp_path, isolation_flag\n    ):\n        # GIVEN\n        out_file = tmp_path / \"result.bin\"\n\n        # WHEN\n        proc = subprocess.run(\n            [\n                sys.executable,\n                isolation_flag,\n                \"-m\",\n                \"memray\",\n                \"run\",\n                \"--quiet\",\n                \"--output\",\n                str(out_file),\n                \"-c\",\n                \"import json, sys; print(json.dumps(sys.path))\",\n            ],\n            check=True,\n            capture_output=True,\n            text=True,\n        )\n\n        # THEN\n        assert out_file.exists()\n        assert proc.returncode == 0\n        # Running `python -m` did not put cwd in sys.path; ensure it isn't\n        # there, and neither is the \"\" we would have replaced it with.\n        path = json.loads(proc.stdout)\n        assert os.getcwd() not in path\n        assert \"\" not in path\n\n    @pytest.mark.parametrize(\"option\", [None, \"--live\", \"--live-remote\"])\n    def test_run_file_that_is_not_python(self, capsys, option):\n        \"\"\"Execute a non-Python script and make sure that we raise a good error\"\"\"\n\n        # GIVEN / WHEN\n        assert main([\"run\", *([option] if option else ()), sys.executable]) == 1\n\n        # THEN\n        captured = capsys.readouterr()\n        assert (\n            captured.err.strip()\n            == \"Only valid Python files or commands can be executed under memray\"\n        )\n\n    @patch(\"memray.commands.run.os.getpid\")\n    def test_run_file_exists(self, getpid, tmp_path, monkeypatch, capsys):\n        # GIVEN / WHEN\n        getpid.return_value = 0\n        (tmp_path / \"memray-json.tool.0.bin\").touch()\n        monkeypatch.chdir(tmp_path)\n\n        # THEN\n        assert main([\"run\", \"-m\", \"json.tool\", \"-h\"]) == 1\n        captured = capsys.readouterr()\n        assert (\n            captured.err.strip()\n            == \"Could not create output file memray-json.tool.0.bin: File exists\"\n        )\n\n    def test_run_output_file_directory_does_not_exist(self, capsys):\n        # GIVEN / WHEN / THEN\n\n        assert main([\"run\", \"--output\", \"/doesn/t/exist\", \"-m\", \"json.tool\", \"-h\"]) == 1\n        captured = capsys.readouterr()\n        assert (\n            captured.err.strip()\n            == \"Could not create output file /doesn/t/exist: No such file or directory\"\n        )\n\n    @pytest.mark.parametrize(\"quiet\", [True, False])\n    def test_quiet(self, quiet, tmp_path, simple_test_file):\n        # GIVEN\n        out_file = tmp_path / \"result.bin\"\n\n        # WHEN\n        proc = subprocess.run(\n            [\n                sys.executable,\n                \"-m\",\n                \"memray\",\n                \"run\",\n                *([\"-q\"] if quiet else []),\n                \"--output\",\n                str(out_file),\n                str(simple_test_file),\n            ],\n            check=True,\n            capture_output=True,\n            text=True,\n        )\n\n        # THEN\n        assert proc.returncode == 0\n        assert out_file.exists()\n        if quiet:\n            assert str(out_file) not in proc.stdout\n        else:\n            assert str(out_file) in proc.stdout\n\n    def test_not_quiet_and_fork(self, tmp_path, test_file_returns_from_fork):\n        # GIVEN\n        out_file = tmp_path / \"result.bin\"\n\n        # WHEN\n        proc = subprocess.run(\n            [\n                sys.executable,\n                \"-m\",\n                \"memray\",\n                \"run\",\n                \"--output\",\n                str(out_file),\n                str(test_file_returns_from_fork),\n            ],\n            check=True,\n            capture_output=True,\n            text=True,\n        )\n\n        # THEN\n        assert proc.returncode == 0\n        assert out_file.exists()\n        assert proc.stdout.count(\"Some example commands to generate reports\") == 1\n\n\nclass TestParseSubcommand:\n    def test_successful_parse(self, tmp_path):\n        # GIVEN\n        record_types = [\n            \"ALLOCATION\",\n            \"MEMORY_MAP_START\",\n            \"SEGMENT_HEADER\",\n            \"SEGMENT\",\n            \"NATIVE_FRAME_ID\",\n            \"FRAME_PUSH\",\n            \"FRAME_POP\",\n            \"MEMORY_RECORD\",\n            \"CONTEXT_SWITCH\",\n            \"CODE_OBJECT\",\n            \"TRAILER\",\n        ]\n\n        code_file = tmp_path / \"code.py\"\n        program = textwrap.dedent(\n            \"\"\"\\\n            import time\n            from memray._test import MemoryAllocator\n            print(\"Allocating some memory!\")\n            allocator = MemoryAllocator()\n            allocator.valloc(1024)\n            allocator.free()\n            # Give it time to generate some memory records\n            time.sleep(0.1)\n            \"\"\"\n        )\n        code_file.write_text(program)\n        record_count_by_type = dict.fromkeys(record_types, 0)\n        results_file, _ = generate_sample_results(tmp_path, code_file, native=True)\n\n        # WHEN\n        proc = subprocess.run(\n            [\n                sys.executable,\n                \"-m\",\n                \"memray\",\n                \"parse\",\n                str(results_file),\n            ],\n            check=True,\n            capture_output=True,\n            text=True,\n            cwd=str(tmp_path),\n        )\n\n        # THEN\n        _, *records = proc.stdout.splitlines()\n\n        for record in records:\n            record_count_by_type[record.partition(\" \")[0]] += 1\n\n        for count in record_count_by_type.values():\n            assert count > 0\n\n    def test_successful_parse_of_aggregated_capture_file(self, tmp_path):\n        # GIVEN\n        results_file = tmp_path / \"result.bin\"\n        record_types = [\n            \"MEMORY_SNAPSHOT\",\n            \"AGGREGATED_ALLOCATION\",\n            \"PYTHON_TRACE_INDEX\",\n            \"PYTHON_FRAME_INDEX\",\n            \"NATIVE_TRACE_INDEX\",\n            \"MEMORY_MAP_START\",\n            \"SEGMENT_HEADER\",\n            \"SEGMENT\",\n            \"AGGREGATED_TRAILER\",\n            \"CODE_OBJECT\",\n        ]\n\n        with Tracker(\n            results_file,\n            native_traces=True,\n            file_format=FileFormat.AGGREGATED_ALLOCATIONS,\n        ):\n            if set_thread_name(\"main\") == 0:\n                # We should get CONTEXT_SWITCH and THREAD_RECORD records only\n                # if we can set the thread name. On macOS, we won't get these.\n                record_types.append(\"CONTEXT_SWITCH\")\n                record_types.append(\"THREAD_RECORD\")\n\n            allocator = MemoryAllocator()\n            allocator.valloc(1024)\n            allocator.free()\n            # Give it time to generate some memory records\n            time.sleep(0.1)\n\n        record_count_by_type = dict.fromkeys(record_types, 0)\n\n        # WHEN\n        proc = subprocess.run(\n            [\n                sys.executable,\n                \"-m\",\n                \"memray\",\n                \"parse\",\n                str(results_file),\n            ],\n            check=True,\n            capture_output=True,\n            text=True,\n            cwd=str(tmp_path),\n        )\n\n        # THEN\n        _, *records = proc.stdout.splitlines()\n        print(records)\n\n        for record in records:\n            record_count_by_type[record.partition(\" \")[0]] += 1\n\n        for count in record_count_by_type.values():\n            assert count > 0\n\n    def test_error_when_stdout_is_a_tty(self, tmp_path, simple_test_file):\n        # GIVEN\n        results_file, source_file = generate_sample_results(\n            tmp_path, simple_test_file, native=True\n        )\n        _, controlled = pty.openpty()\n\n        # WHEN\n        proc = subprocess.run(\n            [\n                sys.executable,\n                \"-m\",\n                \"memray\",\n                \"parse\",\n                str(results_file),\n            ],\n            stdout=controlled,\n            stderr=subprocess.PIPE,\n            text=True,\n            cwd=str(tmp_path),\n        )\n\n        # THEN\n        assert \"You must redirect stdout\" in proc.stderr\n        assert proc.returncode == 1\n\n    def test_error_when_input_file_does_not_exist(self, tmp_path):\n        # GIVEN\n        results_file = tmp_path / \"does/not/exist\"\n\n        # WHEN\n        proc = subprocess.run(\n            [\n                sys.executable,\n                \"-m\",\n                \"memray\",\n                \"parse\",\n                results_file,\n            ],\n            capture_output=True,\n            text=True,\n            cwd=str(tmp_path),\n        )\n\n        # THEN\n        assert \"Reason: No such file\" in proc.stderr\n        assert proc.returncode == 1\n\n\nclass TestFlamegraphSubCommand:\n    def test_reads_from_correct_file(self, tmp_path, simple_test_file):\n        # GIVEN\n        results_file, source_file = generate_sample_results(\n            tmp_path, simple_test_file, native=True\n        )\n\n        # WHEN\n        subprocess.run(\n            [\n                sys.executable,\n                \"-m\",\n                \"memray\",\n                \"flamegraph\",\n                str(results_file),\n            ],\n            cwd=str(tmp_path),\n            check=True,\n            capture_output=True,\n            text=True,\n        )\n\n        # THEN\n        output_file = tmp_path / \"memray-flamegraph-result.html\"\n        assert output_file.exists()\n        assert str(source_file) in output_file.read_text()\n\n    def test_no_web_embeds_d3_assets(self, tmp_path, simple_test_file):\n        # GIVEN\n        results_file, _ = generate_sample_results(\n            tmp_path, simple_test_file, native=True\n        )\n\n        # WHEN\n        subprocess.run(\n            [\n                sys.executable,\n                \"-m\",\n                \"memray\",\n                \"flamegraph\",\n                \"--no-web\",\n                str(results_file),\n            ],\n            cwd=str(tmp_path),\n            check=True,\n            capture_output=True,\n            text=True,\n        )\n\n        # THEN\n        output_file = tmp_path / \"memray-flamegraph-result.html\"\n        html = output_file.read_text()\n        assert '<script src=\"https://' not in html\n        assert '<link rel=\"stylesheet\" href=\"https://' not in html\n        assert \"createPopper\" not in html\n        assert \"d3.schemePastel1\" in html\n\n    def test_can_generate_reports_with_native_traces(self, tmp_path, simple_test_file):\n        # GIVEN\n        results_file, source_file = generate_sample_results(\n            tmp_path, simple_test_file, native=True\n        )\n\n        # WHEN\n        subprocess.run(\n            [\n                sys.executable,\n                \"-m\",\n                \"memray\",\n                \"flamegraph\",\n                str(results_file),\n            ],\n            cwd=str(tmp_path),\n            check=True,\n            capture_output=True,\n            text=True,\n        )\n\n        # THEN\n        output_file = tmp_path / \"memray-flamegraph-result.html\"\n        assert output_file.exists()\n        assert str(source_file) in output_file.read_text()\n\n    def test_writes_to_correct_file(self, tmp_path, simple_test_file):\n        # GIVEN\n        results_file, source_file = generate_sample_results(\n            tmp_path, simple_test_file, native=True\n        )\n        output_file = tmp_path / \"output.html\"\n\n        # WHEN\n        subprocess.run(\n            [\n                sys.executable,\n                \"-m\",\n                \"memray\",\n                \"flamegraph\",\n                str(results_file),\n                \"--output\",\n                str(output_file),\n            ],\n            check=True,\n            capture_output=True,\n            text=True,\n        )\n\n        # THEN\n        assert output_file.exists()\n        assert str(source_file) in output_file.read_text()\n\n    def test_output_file_already_exists(self, tmp_path, simple_test_file, monkeypatch):\n        \"\"\"Check that when the output file is derived form the input name, we\n        fail when there is already a file with the same name as the output.\"\"\"\n\n        # GIVEN\n        monkeypatch.chdir(tmp_path)\n        # This will generate \"result.bin\"\n        results_file, source_file = generate_sample_results(\n            tmp_path, simple_test_file, native=True\n        )\n        output_file = tmp_path / \"memray-flamegraph-result.html\"\n        output_file.touch()\n\n        # WHEN\n        ret = main([\"flamegraph\", str(results_file)])\n\n        # THEN\n        assert ret != 0\n\n    def test_split_threads_subcommand(self, tmp_path, simple_test_file):\n        # GIVEN\n        results_file, source_file = generate_sample_results(\n            tmp_path, simple_test_file, native=True\n        )\n        output_file = tmp_path / \"output.html\"\n\n        # WHEN\n        subprocess.run(\n            [\n                sys.executable,\n                \"-m\",\n                \"memray\",\n                \"flamegraph\",\n                \"--split-threads\",\n                str(results_file),\n                \"--output\",\n                str(output_file),\n            ],\n            check=True,\n            capture_output=True,\n            text=True,\n        )\n\n        # THEN\n        assert output_file.exists()\n        assert str(source_file) in output_file.read_text()\n\n    @pytest.mark.parametrize(\"trace_python_allocators\", [True, False])\n    @pytest.mark.parametrize(\"disable_pymalloc\", [True, False])\n    def test_leaks_with_pymalloc_warning(\n        self,\n        tmp_path,\n        simple_test_file,\n        trace_python_allocators,\n        disable_pymalloc,\n    ):\n        if disable_pymalloc and sysconfig.get_config_var(\"Py_GIL_DISABLED\"):\n            pytest.skip(\"PYTHONMALLOC=malloc is not supported in free-threading builds\")\n\n        # GIVEN\n        results_file, _ = generate_sample_results(\n            tmp_path,\n            simple_test_file,\n            native=True,\n            trace_python_allocators=trace_python_allocators,\n            disable_pymalloc=disable_pymalloc,\n        )\n        output_file = tmp_path / \"output.html\"\n        warning_expected = not trace_python_allocators and not disable_pymalloc\n\n        # WHEN\n        subprocess.run(\n            [\n                sys.executable,\n                \"-m\",\n                \"memray\",\n                \"flamegraph\",\n                \"--leaks\",\n                str(results_file),\n            ],\n            check=True,\n            capture_output=True,\n            text=True,\n        )\n\n        # THEN\n        output_file = tmp_path / \"memray-flamegraph-result.html\"\n        assert output_file.exists()\n        assert warning_expected == (\n            \"Report generated using <code>--leaks</code> with an arena allocator\"\n            in output_file.read_text()\n        )\n\n\nclass TestSummarySubCommand:\n    def test_summary_generated(self, tmp_path, simple_test_file):\n        # GIVEN\n        results_file, _ = generate_sample_results(\n            tmp_path, simple_test_file, native=True\n        )\n\n        # WHEN\n        output = subprocess.check_output(\n            [\n                sys.executable,\n                \"-m\",\n                \"memray\",\n                \"summary\",\n                str(results_file),\n            ],\n            cwd=str(tmp_path),\n            text=True,\n        )\n\n        # THEN\n        assert output\n\n    def test_temporary_allocations_summary(self, tmp_path, simple_test_file):\n        # GIVEN\n        results_file, _ = generate_sample_results(tmp_path, simple_test_file)\n\n        # WHEN\n        output = subprocess.check_output(\n            [\n                sys.executable,\n                \"-m\",\n                \"memray\",\n                \"summary\",\n                \"--temporary-allocations\",\n                str(results_file),\n            ],\n            cwd=str(tmp_path),\n            text=True,\n        )\n\n        # THEN\n        assert output\n\n\nclass TestTreeSubCommand:\n    def test_tree_generated(self, tmp_path, simple_test_file):\n        # GIVEN\n        results_file, _ = generate_sample_results(\n            tmp_path, simple_test_file, native=True\n        )\n        env = os.environ.copy()\n        env[\"TEXTUAL_PRESS\"] = \"q\"\n\n        # WHEN\n        output = subprocess.check_output(\n            [\n                sys.executable,\n                \"-m\",\n                \"memray\",\n                \"tree\",\n                str(results_file),\n            ],\n            cwd=str(tmp_path),\n            stderr=subprocess.DEVNULL,\n            text=True,\n            env=env,\n        )\n\n        # THEN\n        assert output\n\n    def test_temporary_allocations_tree(self, tmp_path, simple_test_file):\n        # GIVEN\n        results_file, _ = generate_sample_results(tmp_path, simple_test_file)\n        env = os.environ.copy()\n        env[\"TEXTUAL_PRESS\"] = \"q\"\n\n        # WHEN\n        output = subprocess.check_output(\n            [\n                sys.executable,\n                \"-m\",\n                \"memray\",\n                \"tree\",\n                \"--temporary-allocations\",\n                str(results_file),\n            ],\n            cwd=str(tmp_path),\n            stderr=subprocess.DEVNULL,\n            text=True,\n            env=env,\n        )\n\n        # THEN\n        assert output\n\n\nclass TestStatsSubCommand:\n    def test_report_generated(self, tmp_path, simple_test_file):\n        # GIVEN\n        results_file, _ = generate_sample_results(\n            tmp_path, simple_test_file, native=True\n        )\n\n        # WHEN\n        output = subprocess.check_output(\n            [\n                sys.executable,\n                \"-m\",\n                \"memray\",\n                \"stats\",\n                str(results_file),\n            ],\n            cwd=str(tmp_path),\n            text=True,\n        )\n\n        # THEN\n        assert \"VALLOC\" in output\n\n    def test_json_generated(self, tmp_path, simple_test_file):\n        # GIVEN\n        results_file, _ = generate_sample_results(tmp_path, simple_test_file)\n        json_file = tmp_path / \"memray-stats-result.bin.json\"\n\n        # WHEN\n        subprocess.check_output(\n            [\n                sys.executable,\n                \"-m\",\n                \"memray\",\n                \"stats\",\n                \"--json\",\n                str(results_file),\n            ],\n            cwd=str(tmp_path),\n            text=True,\n        )\n\n        # THEN\n        assert json_file.exists()\n        assert isinstance(json.loads(json_file.read_text()), dict)\n\n    def test_json_generated_to_pretty_file_name(self, tmp_path, simple_test_file):\n        # GIVEN\n        orig_results_file, _ = generate_sample_results(tmp_path, simple_test_file)\n        results_file = orig_results_file.with_name(\"memray-foobar.bin\")\n        orig_results_file.rename(results_file)\n        json_file = tmp_path / \"memray-stats-foobar.bin.json\"\n\n        # WHEN\n        subprocess.check_output(\n            [\n                sys.executable,\n                \"-m\",\n                \"memray\",\n                \"stats\",\n                \"--json\",\n                str(results_file),\n            ],\n            cwd=str(tmp_path),\n            text=True,\n        )\n\n        # THEN\n        assert json_file.exists()\n        assert isinstance(json.loads(json_file.read_text()), dict)\n\n    def test_json_generated_to_known_file(self, tmp_path, simple_test_file):\n        # GIVEN\n        results_file, _ = generate_sample_results(tmp_path, simple_test_file)\n        json_file = tmp_path / \"output.json\"\n\n        # WHEN\n        subprocess.check_output(\n            [\n                sys.executable,\n                \"-m\",\n                \"memray\",\n                \"stats\",\n                \"--json\",\n                \"-o\",\n                str(json_file),\n                str(results_file),\n            ],\n            cwd=str(tmp_path),\n            text=True,\n        )\n\n        # THEN\n        assert json_file.exists()\n        assert isinstance(json.loads(json_file.read_text()), dict)\n\n    def test_json_generated_to_existing_known_file(self, tmp_path, simple_test_file):\n        # GIVEN\n        results_file, _ = generate_sample_results(tmp_path, simple_test_file)\n        json_file = tmp_path / \"output.json\"\n        json_file.write_text(\"oops\")\n\n        # WHEN\n        try:\n            exc = None\n            subprocess.check_output(\n                [\n                    sys.executable,\n                    \"-m\",\n                    \"memray\",\n                    \"stats\",\n                    \"--json\",\n                    \"-o\",\n                    str(json_file),\n                    str(results_file),\n                ],\n                cwd=str(tmp_path),\n                stderr=subprocess.PIPE,\n                text=True,\n            )\n        except subprocess.CalledProcessError as e:\n            exc = e\n\n        # THEN\n        assert exc is not None\n        assert \"File already exists, will not overwrite\" in exc.stderr\n\n    def test_json_overwrites_existing_known_file(self, tmp_path, simple_test_file):\n        # GIVEN\n        results_file, _ = generate_sample_results(tmp_path, simple_test_file)\n        json_file = tmp_path / \"output.json\"\n        json_file.write_text(\"oops\")\n\n        # WHEN\n        subprocess.check_output(\n            [\n                sys.executable,\n                \"-m\",\n                \"memray\",\n                \"stats\",\n                \"--json\",\n                \"--force\",\n                \"--output\",\n                str(json_file),\n                str(results_file),\n            ],\n            cwd=str(tmp_path),\n            stderr=subprocess.PIPE,\n            text=True,\n        )\n\n        # THEN\n        assert json_file.exists()\n        assert isinstance(json.loads(json_file.read_text()), dict)\n\n    def test_report_detects_corrupt_input(self, tmp_path):\n        # GIVEN\n        bad_file = Path(tmp_path) / \"badfile.bin\"\n        bad_file.write_text(\"This is some garbage\")\n\n        # WHEN\n        proc = subprocess.run(\n            [\n                sys.executable,\n                \"-m\",\n                \"memray\",\n                \"stats\",\n                str(bad_file),\n            ],\n            capture_output=True,\n            text=True,\n        )\n\n        # THEN\n        assert proc.returncode == 1\n        assert re.match(r\"Failed to compute statistics for .*badfile\\.bin\", proc.stderr)\n\n\nclass TestTableSubCommand:\n    def test_reads_from_correct_file(self, tmp_path, simple_test_file):\n        # GIVEN\n        results_file, source_file = generate_sample_results(\n            tmp_path, simple_test_file, native=True\n        )\n\n        # WHEN\n        subprocess.run(\n            [\n                sys.executable,\n                \"-m\",\n                \"memray\",\n                \"table\",\n                str(results_file),\n            ],\n            cwd=str(tmp_path),\n            check=True,\n            capture_output=True,\n            text=True,\n        )\n\n        # THEN\n        output_file = tmp_path / \"memray-table-result.html\"\n        assert output_file.exists()\n        assert str(source_file) in output_file.read_text()\n\n    def test_no_split_threads(self, tmp_path):\n        # GIVEN/WHEN/THEN\n        with pytest.raises(subprocess.CalledProcessError):\n            subprocess.run(\n                [\n                    sys.executable,\n                    \"-m\",\n                    \"memray\",\n                    \"table\",\n                    \"--split-threads\",\n                    \"somefile\",\n                ],\n                cwd=str(tmp_path),\n                check=True,\n                capture_output=True,\n                text=True,\n            )\n\n\nclass TestReporterSubCommands:\n    @pytest.mark.parametrize(\n        \"report\", [\"flamegraph\", \"table\", \"summary\", \"tree\", \"stats\"]\n    )\n    def test_report_detects_missing_input(self, report):\n        # GIVEN / WHEN\n        proc = subprocess.run(\n            [\n                sys.executable,\n                \"-m\",\n                \"memray\",\n                report,\n                \"nosuchfile\",\n            ],\n            capture_output=True,\n            text=True,\n        )\n\n        # THEN\n        assert proc.returncode == 1\n        assert \"No such file: nosuchfile\" in proc.stderr\n\n    @pytest.mark.parametrize(\"report\", [\"flamegraph\", \"table\", \"summary\", \"tree\"])\n    def test_report_detects_corrupt_input(self, tmp_path, report):\n        # GIVEN\n        bad_file = Path(tmp_path) / \"badfile.bin\"\n        bad_file.write_text(\"This is some garbage\")\n\n        # WHEN\n        proc = subprocess.run(\n            [\n                sys.executable,\n                \"-m\",\n                \"memray\",\n                report,\n                str(bad_file),\n            ],\n            capture_output=True,\n            text=True,\n        )\n\n        # THEN\n        assert proc.returncode == 1\n        assert re.match(\n            r\"Failed to parse allocation records in .*badfile\\.bin\", proc.stderr\n        )\n\n    @pytest.mark.parametrize(\"report\", [\"flamegraph\", \"table\"])\n    def test_report_leaks_argument(self, tmp_path, simple_test_file, report):\n        results_file, source_file = generate_sample_results(\n            tmp_path, simple_test_file, native=True\n        )\n        output_file = tmp_path / \"output.html\"\n\n        # WHEN\n        subprocess.run(\n            [\n                sys.executable,\n                \"-m\",\n                \"memray\",\n                report,\n                \"--leaks\",\n                str(results_file),\n            ],\n            check=True,\n            capture_output=True,\n            text=True,\n        )\n\n        # THEN\n        output_file = tmp_path / f\"memray-{report}-result.html\"\n        assert output_file.exists()\n        assert str(source_file) in output_file.read_text()\n\n    @pytest.mark.parametrize(\"report\", [\"flamegraph\", \"table\"])\n    def test_report_temporary_allocations_argument(\n        self, tmp_path, simple_test_file, report\n    ):\n        results_file, source_file = generate_sample_results(\n            tmp_path, simple_test_file, native=True\n        )\n        output_file = tmp_path / \"output.html\"\n\n        # WHEN\n        subprocess.run(\n            [\n                sys.executable,\n                \"-m\",\n                \"memray\",\n                report,\n                str(results_file),\n                \"--temporary-allocations\",\n            ],\n            check=True,\n            capture_output=True,\n            text=True,\n        )\n\n        # THEN\n        output_file = tmp_path / f\"memray-{report}-result.html\"\n        assert output_file.exists()\n        assert str(source_file) in output_file.read_text()\n\n    @pytest.mark.parametrize(\"report\", [\"flamegraph\", \"table\"])\n    def test_report_incompatible_arguments(self, tmp_path, simple_test_file, report):\n        results_file, _ = generate_sample_results(\n            tmp_path, simple_test_file, native=True\n        )\n\n        # WHEN\n        proc = subprocess.run(\n            [\n                sys.executable,\n                \"-m\",\n                \"memray\",\n                report,\n                \"--temporary-allocations\",\n                \"--leaks\",\n                str(results_file),\n            ],\n            capture_output=True,\n            text=True,\n        )\n\n        # THEN\n        assert proc.returncode != 0\n        assert (\n            \"--leaks: not allowed with argument --temporary-allocations\" in proc.stderr\n        )\n\n    @pytest.mark.parametrize(\"report\", [\"flamegraph\", \"table\", \"summary\", \"tree\"])\n    def test_report_both_temporary_allocation_arguments(\n        self, tmp_path, simple_test_file, report\n    ):\n        results_file, _ = generate_sample_results(\n            tmp_path, simple_test_file, native=True\n        )\n\n        # WHEN\n        proc = subprocess.run(\n            [\n                sys.executable,\n                \"-m\",\n                \"memray\",\n                report,\n                \"--temporary-allocations\",\n                \"--temporary-allocation-threshold=1\",\n                str(results_file),\n            ],\n            capture_output=True,\n            text=True,\n        )\n\n        # THEN\n        assert proc.returncode != 0\n        assert (\n            \"--temporary-allocation-threshold: not allowed with\"\n            \" argument --temporary-allocations\" in proc.stderr\n        )\n\n\nclass TestLiveRemoteSubcommand:\n    def test_live_tracking(self, tmp_path, simple_test_file, free_port):\n        # GIVEN\n        server = subprocess.Popen(\n            [\n                sys.executable,\n                \"-m\",\n                \"memray\",\n                \"run\",\n                \"--live-remote\",\n                \"--live-port\",\n                str(free_port),\n                str(simple_test_file),\n            ],\n            stderr=subprocess.PIPE,\n            stdout=subprocess.PIPE,\n        )\n\n        _wait_until_process_blocks(server.pid)\n\n        client = subprocess.Popen(\n            [\n                sys.executable,\n                \"-m\",\n                \"memray\",\n                \"live\",\n                str(free_port),\n            ],\n            stdout=subprocess.PIPE,\n            stderr=subprocess.DEVNULL,\n            stdin=subprocess.PIPE,\n        )\n\n        # WHEN\n\n        try:\n            server.communicate(timeout=TIMEOUT)\n            client.communicate(b\"q\", timeout=TIMEOUT)\n        except subprocess.TimeoutExpired:\n            server.terminate()\n            client.terminate()\n            server.wait(timeout=TIMEOUT)\n            client.wait(timeout=TIMEOUT)\n            raise\n\n        server.communicate()\n\n        # THEN\n        assert server.returncode == 0\n        assert client.returncode == 0\n\n    def test_live_tracking_waits_for_client(self, simple_test_file):\n        # GIVEN/WHEN\n        server = subprocess.Popen(\n            [\n                sys.executable,\n                \"-m\",\n                \"memray\",\n                \"run\",\n                \"--live-remote\",\n                str(simple_test_file),\n            ],\n            env={\"PYTHONUNBUFFERED\": \"1\"},\n            stdout=subprocess.PIPE,\n            stderr=subprocess.PIPE,\n        )\n\n        # THEN\n        assert b\"another shell to see live results\\n\" in server.stdout.readline()\n        server.terminate()\n        server.wait(timeout=TIMEOUT)\n\n    @pytest.mark.parametrize(\"port\", [0, 2**16, 1000000])\n    def test_run_live_tracking_invalid_port(self, simple_test_file, port):\n        # GIVEN/WHEN\n        server = subprocess.Popen(\n            [\n                sys.executable,\n                \"-m\",\n                \"memray\",\n                \"run\",\n                \"--live-remote\",\n                \"--live-port\",\n                str(port),\n                str(simple_test_file),\n            ],\n            env={\"PYTHONUNBUFFERED\": \"1\"},\n            stdout=subprocess.PIPE,\n            stderr=subprocess.PIPE,\n            text=True,\n        )\n\n        # THEN\n        assert \"Invalid port\" in server.stderr.readline()\n        server.terminate()\n        server.wait(timeout=TIMEOUT)\n\n    @pytest.mark.parametrize(\"port\", [0, 2**16, 1000000])\n    def test_live_tracking_invalid_port(self, port):\n        # GIVEN/WHEN\n        server = subprocess.Popen(\n            [\n                sys.executable,\n                \"-m\",\n                \"memray\",\n                \"live\",\n                str(port),\n            ],\n            env={\"PYTHONUNBUFFERED\": \"1\"},\n            stdout=subprocess.PIPE,\n            stderr=subprocess.PIPE,\n            text=True,\n        )\n\n        # THEN\n        assert \"Invalid port\" in server.stderr.readline()\n        server.terminate()\n        server.wait(timeout=TIMEOUT)\n\n    def test_live_tracking_server_when_client_disconnects(self, free_port, tmp_path):\n        # GIVEN\n        test_file = tmp_path / \"test.py\"\n        test_file.write_text(\"import time; time.sleep(3)\")\n\n        server = subprocess.Popen(\n            [\n                sys.executable,\n                \"-m\",\n                \"memray\",\n                \"run\",\n                \"--live-port\",\n                str(free_port),\n                \"--live-remote\",\n                str(test_file),\n            ],\n            env={\"PYTHONUNBUFFERED\": \"1\"},\n            stdout=subprocess.PIPE,\n            stderr=subprocess.PIPE,\n            text=True,\n        )\n\n        _wait_until_process_blocks(server.pid)\n\n        client = subprocess.Popen(\n            [\n                sys.executable,\n                \"-m\",\n                \"memray\",\n                \"live\",\n                str(free_port),\n            ],\n            stdin=subprocess.PIPE,\n            stdout=subprocess.PIPE,\n            stderr=subprocess.DEVNULL,\n        )\n\n        # WHEN\n        try:\n            client.communicate(b\"q\", timeout=TIMEOUT)\n        except subprocess.TimeoutExpired:\n            client.terminate()\n            client.wait(timeout=TIMEOUT)\n            raise\n\n        try:\n            _, stderr = server.communicate(timeout=TIMEOUT)\n        except subprocess.TimeoutExpired:\n            server.terminate()\n            server.wait(timeout=TIMEOUT)\n            raise\n\n        # THEN\n        assert \"Encountered error in 'send' call:\" not in stderr\n        assert \"Traceback\" not in stderr\n\n    def test_live_tracking_server_exits_properly_on_sigint(self, simple_test_file):\n        # GIVEN\n        server = subprocess.Popen(\n            [\n                sys.executable,\n                \"-m\",\n                \"memray\",\n                \"run\",\n                \"--live-remote\",\n                str(simple_test_file),\n            ],\n            env={\"PYTHONUNBUFFERED\": \"1\"},\n            stdout=subprocess.PIPE,\n            stderr=subprocess.PIPE,\n            # Explicitly reset the signal handler for SIGINT to work around any signal\n            # masking that might happen on Jenkins.\n            preexec_fn=lambda: signal.signal(signal.SIGINT, signal.default_int_handler),\n        )\n\n        # WHEN\n        server.stdout.readline()  # wait for the startup message\n        # Ensure that it's waiting on the socket\n        _wait_until_process_blocks(server.pid)\n\n        server.send_signal(signal.SIGINT)\n        try:\n            _, stderr = server.communicate(timeout=TIMEOUT)\n        except subprocess.TimeoutExpired:\n            server.kill()\n            server.wait(timeout=TIMEOUT)\n            raise\n\n        # THEN\n        assert server.returncode == 0\n        assert b\"Exception ignored\" not in stderr\n        assert b\"Traceback (most recent call last):\" not in stderr\n        assert b\"Interrupted system call\" not in stderr\n\n    def test_live_client_exits_properly_on_sigint_before_connecting(self, free_port):\n        # GIVEN\n        client = subprocess.Popen(\n            [\n                sys.executable,\n                \"-m\",\n                \"memray\",\n                \"live\",\n                str(free_port),\n            ],\n            stderr=subprocess.PIPE,\n            stdout=subprocess.PIPE,\n            # Explicitly reset the signal handler for SIGINT to work around any signal\n            # masking that might happen on Jenkins.\n            preexec_fn=lambda: signal.signal(signal.SIGINT, signal.default_int_handler),\n        )\n\n        # Ensure that it's waiting on the socket\n        _wait_until_process_blocks(client.pid)\n\n        # WHEN\n        client.send_signal(signal.SIGINT)\n        try:\n            client.wait(timeout=TIMEOUT)\n        except subprocess.TimeoutExpired:\n            client.terminate()\n\n        # THEN\n        assert client.returncode == 0\n\n\nclass TestLiveSubcommand:\n    def test_live_tracking(self, tmp_path):\n        # GIVEN\n        with track_and_wait(tmp_path) as program_file:\n            server = subprocess.Popen(\n                [\n                    sys.executable,\n                    \"-m\",\n                    \"memray\",\n                    \"run\",\n                    \"--live\",\n                    str(program_file),\n                ],\n                stdin=subprocess.PIPE,\n                stderr=subprocess.PIPE,\n                stdout=subprocess.PIPE,\n            )\n\n        # WHEN\n        try:\n            server.communicate(b\"q\", timeout=TIMEOUT)\n        except subprocess.TimeoutExpired:\n            server.kill()\n            raise\n\n        # THEN\n        assert server.returncode == 0\n\n\nclass TestTransformSubCommands:\n    def test_report_detects_missing_input(self):\n        # GIVEN / WHEN\n        proc = subprocess.run(\n            [\n                sys.executable,\n                \"-m\",\n                \"memray\",\n                \"transform\",\n                \"gprof2dot\",\n                \"nosuchfile\",\n            ],\n            capture_output=True,\n            text=True,\n        )\n\n        # THEN\n        assert proc.returncode == 1\n        assert \"No such file: nosuchfile\" in proc.stderr\n\n    def test_report_detects_corrupt_input(self, tmp_path):\n        # GIVEN\n        bad_file = Path(tmp_path) / \"badfile.bin\"\n        bad_file.write_text(\"This is some garbage\")\n\n        # WHEN\n        proc = subprocess.run(\n            [\n                sys.executable,\n                \"-m\",\n                \"memray\",\n                \"transform\",\n                \"gprof2dot\",\n                str(bad_file),\n            ],\n            capture_output=True,\n            text=True,\n        )\n\n        # THEN\n        assert proc.returncode == 1\n        assert re.match(\n            r\"Failed to parse allocation records in .*badfile\\.bin\", proc.stderr\n        )\n\n    def test_report_leaks_argument(self, tmp_path, simple_test_file):\n        results_file, source_file = generate_sample_results(\n            tmp_path, simple_test_file, native=True\n        )\n        output_file = tmp_path / \"output.html\"\n\n        # WHEN\n        subprocess.run(\n            [\n                sys.executable,\n                \"-m\",\n                \"memray\",\n                \"transform\",\n                \"gprof2dot\",\n                \"--leaks\",\n                str(results_file),\n            ],\n            check=True,\n            capture_output=True,\n            text=True,\n        )\n\n        # THEN\n        output_file = tmp_path / \"memray-gprof2dot-result.json\"\n        assert output_file.exists()\n        output_text = output_file.read_text()\n        if \"<unknown stack>\" in output_text:\n            pytest.xfail(\"Hybrid stack generation is not fully working\")\n        assert str(source_file) in output_text\n"
  },
  {
    "path": "tests/integration/test_native_tracking.py",
    "content": "import functools\nimport os\nimport shutil\nimport subprocess\nimport sys\nimport textwrap\nimport threading\nfrom pathlib import Path\n\nimport pytest\n\nfrom memray import AllocatorType\nfrom memray import FileReader\nfrom memray import Tracker\nfrom memray._test import MemoryAllocator\nfrom tests.utils import filter_relevant_allocations\n\nHERE = Path(__file__).parent\nTEST_MULTITHREADED_EXTENSION = HERE / \"multithreaded_extension\"\nTEST_NATIVE_EXTENSION = HERE / \"native_extension\"\n\n\ndef test_multithreaded_extension_with_native_tracking(tmpdir, monkeypatch):\n    \"\"\"Test tracking allocations in a native extension which spawns multiple threads,\n    each thread allocating and freeing memory.\"\"\"\n    # GIVEN\n    output = Path(tmpdir) / \"test.bin\"\n    extension_name = \"multithreaded_extension\"\n    extension_path = tmpdir / extension_name\n    shutil.copytree(TEST_MULTITHREADED_EXTENSION, extension_path)\n    subprocess.run(\n        [sys.executable, str(extension_path / \"setup.py\"), \"build_ext\", \"--inplace\"],\n        check=True,\n        cwd=extension_path,\n        capture_output=True,\n    )\n\n    # WHEN\n    with monkeypatch.context() as ctx:\n        ctx.setattr(sys, \"path\", [*sys.path, str(extension_path)])\n        from testext import run  # type: ignore\n\n        with Tracker(output, native_traces=True):\n            run()\n\n    # THEN\n    records = list(FileReader(output).get_allocation_records())\n    memaligns = []\n    memalign_frees = []\n    outstanding_memaligns = set()\n\n    for record in records:\n        if record.allocator == AllocatorType.POSIX_MEMALIGN:\n            memaligns.append(record)\n            outstanding_memaligns.add(record.address)\n        elif record.allocator == AllocatorType.FREE:\n            if record.address in outstanding_memaligns:\n                outstanding_memaligns.remove(record.address)\n                memalign_frees.append(record)\n\n    assert len(memaligns) == 100 * 100  # 100 threads allocate 100 times in testext\n    assert all(len(memalign.stack_trace()) == 0 for memalign in memaligns)\n    expected_symbols = [\"allocate_memory\", \"worker\"]\n    assert all(\n        expected_symbols == [stack[0] for stack in record.native_stack_trace()][:2]\n        for record in memaligns\n    )\n\n    assert len(memalign_frees) == 100 * 100\n    for record in memalign_frees:\n        with pytest.raises(NotImplementedError):\n            record.stack_trace()\n        with pytest.raises(NotImplementedError):\n            record.native_stack_trace()\n\n\n@pytest.mark.valgrind\ndef test_simple_call_chain_with_native_tracking(tmpdir, monkeypatch):\n    # GIVEN\n    output = Path(tmpdir) / \"test.bin\"\n    extension_name = \"multithreaded_extension\"\n    extension_path = tmpdir / extension_name\n    shutil.copytree(TEST_NATIVE_EXTENSION, extension_path)\n    subprocess.run(\n        [sys.executable, str(extension_path / \"setup.py\"), \"build_ext\", \"--inplace\"],\n        check=True,\n        cwd=extension_path,\n        capture_output=True,\n    )\n\n    # WHEN\n    with monkeypatch.context() as ctx:\n        ctx.setattr(sys, \"path\", [*sys.path, str(extension_path)])\n        from native_ext import run_simple  # type: ignore\n\n        with Tracker(output, native_traces=True):\n            run_simple()\n\n    # THEN\n    records = list(FileReader(output).get_allocation_records())\n    vallocs = [\n        record\n        for record in filter_relevant_allocations(records)\n        if record.allocator == AllocatorType.VALLOC\n    ]\n\n    assert len(vallocs) == 1\n    (valloc,) = vallocs\n\n    (python_stack_trace,) = valloc.stack_trace()\n    func, filename, line = python_stack_trace\n    assert func == \"test_simple_call_chain_with_native_tracking\"\n    assert filename.endswith(__file__)\n\n    expected_symbols = [\"baz\", \"bar\", \"foo\"]\n    assert expected_symbols == [stack[0] for stack in valloc.native_stack_trace()[:3]]\n\n\n@pytest.mark.skipif(\n    sys.platform == \"darwin\",\n    reason=\"we cannot use debug information to resolve inline functions on macOS\",\n)\ndef test_inlined_call_chain_with_native_tracking(tmpdir, monkeypatch):\n    # GIVEN\n    output = Path(tmpdir) / \"test.bin\"\n    extension_name = \"multithreaded_extension\"\n    extension_path = tmpdir / extension_name\n    shutil.copytree(TEST_NATIVE_EXTENSION, extension_path)\n    subprocess.run(\n        [sys.executable, str(extension_path / \"setup.py\"), \"build_ext\", \"--inplace\"],\n        check=True,\n        cwd=extension_path,\n        capture_output=True,\n    )\n\n    # WHEN\n    with monkeypatch.context() as ctx:\n        ctx.setattr(sys, \"path\", [*sys.path, str(extension_path)])\n        from native_ext import run_inline\n\n        with Tracker(output, native_traces=True):\n            run_inline()\n\n    # THEN\n    records = list(FileReader(output).get_allocation_records())\n    vallocs = [\n        record\n        for record in filter_relevant_allocations(records)\n        if record.allocator == AllocatorType.VALLOC\n    ]\n\n    assert len(vallocs) == 1\n    (valloc,) = vallocs\n\n    (python_stack_trace,) = valloc.stack_trace()\n    func, filename, line = python_stack_trace\n    assert func == \"test_inlined_call_chain_with_native_tracking\"\n    assert filename.endswith(__file__)\n\n    expected_symbols = [\"baz_inline\", \"bar_inline\", \"foo_inline\"]\n    assert expected_symbols == [stack[0] for stack in valloc.native_stack_trace()[:3]]\n\n\n@pytest.mark.valgrind\ndef test_deep_call_chain_with_native_tracking(tmpdir, monkeypatch):\n    # GIVEN\n    output = Path(tmpdir) / \"test.bin\"\n    extension_name = \"multithreaded_extension\"\n    extension_path = tmpdir / extension_name\n    shutil.copytree(TEST_NATIVE_EXTENSION, extension_path)\n    subprocess.run(\n        [sys.executable, str(extension_path / \"setup.py\"), \"build_ext\", \"--inplace\"],\n        check=True,\n        cwd=extension_path,\n        capture_output=True,\n    )\n\n    # WHEN\n    with monkeypatch.context() as ctx:\n        ctx.setattr(sys, \"path\", [*sys.path, str(extension_path)])\n        from native_ext import run_deep\n\n        with Tracker(output, native_traces=True):\n            run_deep(2048)\n\n    # THEN\n    records = list(FileReader(output).get_allocation_records())\n    vallocs = [\n        record\n        for record in filter_relevant_allocations(records)\n        if record.allocator == AllocatorType.VALLOC\n    ]\n\n    assert len(vallocs) == 1\n    (valloc,) = vallocs\n\n    (python_stack_trace,) = valloc.stack_trace()\n    func, filename, line = python_stack_trace\n    assert func == \"test_deep_call_chain_with_native_tracking\"\n    assert filename.endswith(__file__)\n\n    expected_symbols = [\"baz\", \"bar\", \"foo\"]\n    native_stack = tuple(valloc.native_stack_trace())\n    assert len(native_stack) > 2048\n    assert expected_symbols == [stack[0] for stack in native_stack[:3]]\n    assert all(\"deep_call\" in stack[0] for stack in native_stack[3 : 3 + 2048])\n\n\ndef test_hybrid_stack_in_pure_python(tmpdir):\n    # GIVEN\n    allocator = MemoryAllocator()\n    output = Path(tmpdir) / \"test.bin\"\n    MAX_RECURSIONS = 4\n\n    def recursive_func(n):\n        if n == 1:\n            return allocator.valloc(1234)\n        return recursive_func(n - 1)\n\n    # WHEN\n\n    with Tracker(output, native_traces=True):\n        recursive_func(MAX_RECURSIONS)\n\n    # THEN\n    records = list(FileReader(output).get_allocation_records())\n    vallocs = [\n        record\n        for record in filter_relevant_allocations(records)\n        if record.allocator == AllocatorType.VALLOC\n    ]\n\n    assert len(vallocs) == 1\n    (valloc,) = vallocs\n\n    hybrid_stack = tuple(frame[0] for frame in valloc.hybrid_stack_trace())\n    assert hybrid_stack.count(\"recursive_func\") == MAX_RECURSIONS\n\n    # The cython frame of valloc() must not appear in the hybrid stack trace because we\n    # already have it in as a native information\n    assert (\n        hybrid_stack.count(\"recursive_func\")\n        == len(valloc.stack_trace()) - 2\n        == MAX_RECURSIONS\n    )\n    assert len(valloc.stack_trace()) <= len(hybrid_stack)\n    if sys.version_info < (3, 11):\n        # The hybrid stack can be bigger than the native stack in 3.11, because\n        # non-entry frames are present in the hybrid stack but missing in the\n        # native stack. In 3.10 and earlier, the hybrid stack can't be bigger.\n        assert len(hybrid_stack) <= len(valloc.native_stack_trace())\n\n    # The hybrid stack trace must run until the latest python function seen by the tracker\n    assert hybrid_stack[-1] == \"test_hybrid_stack_in_pure_python\"\n\n\ndef test_hybrid_stack_in_pure_python_with_callbacks(tmpdir):\n    # GIVEN\n    allocator = MemoryAllocator()\n    output = Path(tmpdir) / \"test.bin\"\n\n    def ham():\n        spam()\n\n    def spam():\n        functools.partial(foo)()\n\n    def foo():\n        bar()\n\n    def bar():\n        baz()\n\n    def baz():\n        return allocator.valloc(1234)\n\n    funcs = (\"ham\", \"spam\", \"foo\", \"bar\", \"baz\")\n\n    # WHEN\n\n    with Tracker(output, native_traces=True):\n        ham()\n\n    # THEN\n    records = list(FileReader(output).get_allocation_records())\n    vallocs = [\n        record\n        for record in filter_relevant_allocations(records)\n        if record.allocator == AllocatorType.VALLOC\n    ]\n\n    assert len(vallocs) == 1\n    (valloc,) = vallocs\n\n    hybrid_stack = tuple(frame[0] for frame in valloc.hybrid_stack_trace())\n    pos = {func: hybrid_stack.index(func) for func in funcs}\n    assert pos[\"ham\"] > pos[\"spam\"] > pos[\"foo\"] > pos[\"bar\"] > pos[\"baz\"]\n    if sys.version_info >= (3, 11) and sys.implementation.name == \"cpython\":\n        # Some frames should be non-entry frames, and therefore adjacent to their caller\n        assert pos[\"ham\"] == pos[\"spam\"] + 1\n        assert pos[\"spam\"] > pos[\"foo\"] + 1  # map() introduces extra frames\n        assert pos[\"foo\"] == pos[\"bar\"] + 1\n        assert pos[\"bar\"] == pos[\"baz\"] + 1\n    else:\n        # All frames are entry frames; there are C frames between any 2 Python calls\n        assert pos[\"ham\"] > pos[\"spam\"] + 1\n        assert pos[\"spam\"] > pos[\"foo\"] + 1\n        assert pos[\"foo\"] > pos[\"bar\"] + 1\n        assert pos[\"bar\"] > pos[\"baz\"] + 1\n\n    # Cython frames don't show up with their Python name, neither in the hybrid\n    # stack or the Python stack.\n    assert hybrid_stack.count(\"valloc\") == 1\n    assert [frame[0] for frame in valloc.stack_trace()].count(\"valloc\") == 1\n\n\ndef test_hybrid_stack_of_allocations_inside_ceval(tmpdir):\n    # GIVEN\n    output = Path(tmpdir) / \"test.bin\"\n\n    extension_name = \"native_extension\"\n    extension_path = tmpdir / extension_name\n    shutil.copytree(TEST_NATIVE_EXTENSION, extension_path)\n    subprocess.run(\n        [sys.executable, str(extension_path / \"setup.py\"), \"build_ext\", \"--inplace\"],\n        check=True,\n        cwd=extension_path,\n        capture_output=True,\n    )\n\n    # WHEN\n    program = textwrap.dedent(\n        \"\"\"\n        import functools\n        import sys\n\n        import memray._test\n        import native_ext\n\n\n        def foo():\n            native_ext.run_recursive(1, bar)\n\n\n        def bar(_):\n            allocator = memray._test.MemoryAllocator()\n            allocator.valloc(1234)\n            baz()\n\n\n        def baz():\n            pass\n\n\n        with memray.Tracker(sys.argv[1], native_traces=True):\n            functools.partial(foo)()\n        \"\"\"\n    )\n    env = os.environ.copy()\n    env[\"PYTHONPATH\"] = str(extension_path)\n\n    # WHEN\n    subprocess.run(\n        [sys.executable, \"-c\", program, str(output)],\n        check=True,\n        env=env,\n    )\n\n    # THEN\n    records = list(FileReader(output).get_allocation_records())\n    found_an_interesting_stack = False\n    for record in records:\n        try:\n            stack = [frame[0] for frame in record.hybrid_stack_trace()]\n        except NotImplementedError:\n            continue  # Must be a free; we don't have its stack.\n\n        print(stack)\n\n        # This function never allocates anything, so we should never see it.\n        assert \"baz\" not in stack\n\n        if \"run_recursive\" in stack:\n            found_an_interesting_stack = True\n            # foo calls run_recursive, not the other way around.\n            assert stack.index(\"foo\") > stack.index(\"run_recursive\")\n\n    assert found_an_interesting_stack\n\n\ndef test_hybrid_stack_in_recursive_python_c_call(tmpdir, monkeypatch):\n    # GIVEN\n    output = Path(tmpdir) / \"test.bin\"\n    extension_name = \"multithreaded_extension\"\n    extension_path = tmpdir / extension_name\n    shutil.copytree(TEST_NATIVE_EXTENSION, extension_path)\n    subprocess.run(\n        [sys.executable, str(extension_path / \"setup.py\"), \"build_ext\", \"--inplace\"],\n        check=True,\n        cwd=extension_path,\n        capture_output=True,\n    )\n\n    MAX_RECURSIONS = 4\n\n    # WHEN\n    with monkeypatch.context() as ctx:\n        ctx.setattr(sys, \"path\", [*sys.path, str(extension_path)])\n        from native_ext import run_recursive\n\n        def callback(n):\n            return run_recursive(n, callback)\n\n        with Tracker(output, native_traces=True):\n            run_recursive(MAX_RECURSIONS, callback)\n\n    # THEN\n    records = list(FileReader(output).get_allocation_records())\n    vallocs = [\n        record\n        for record in filter_relevant_allocations(records)\n        if record.allocator == AllocatorType.VALLOC\n    ]\n\n    assert len(vallocs) == 1\n    (valloc,) = vallocs\n\n    hybrid_stack = tuple(frame[0] for frame in valloc.hybrid_stack_trace())\n    assert hybrid_stack.count(\"callback\") == MAX_RECURSIONS\n    assert (\n        sum(1 if \"run_recursive\" in elem else 0 for elem in hybrid_stack)\n        == MAX_RECURSIONS + 1\n    )\n\n    assert hybrid_stack.count(\"callback\") == MAX_RECURSIONS\n    assert len(valloc.stack_trace()) == MAX_RECURSIONS + 1\n    assert valloc.stack_trace()[-1][0] == \"test_hybrid_stack_in_recursive_python_c_call\"\n    assert (\n        len(valloc.stack_trace())\n        <= len(hybrid_stack)\n        <= len(valloc.native_stack_trace())\n    )\n\n    # The hybrid stack trace must run until the latest python function seen by the tracker\n    assert hybrid_stack[-1] == \"test_hybrid_stack_in_recursive_python_c_call\"\n\n\ndef test_hybrid_stack_in_a_thread(tmpdir, monkeypatch):\n    # GIVEN\n    output = Path(tmpdir) / \"test.bin\"\n    extension_name = \"multithreaded_extension\"\n    extension_path = tmpdir / extension_name\n    shutil.copytree(TEST_NATIVE_EXTENSION, extension_path)\n    subprocess.run(\n        [sys.executable, str(extension_path / \"setup.py\"), \"build_ext\", \"--inplace\"],\n        check=True,\n        cwd=extension_path,\n        capture_output=True,\n    )\n\n    # WHEN\n    with monkeypatch.context() as ctx:\n        ctx.setattr(sys, \"path\", [*sys.path, str(extension_path)])\n        from native_ext import run_in_thread\n\n        with Tracker(output, native_traces=True):\n            run_in_thread()\n\n    # THEN\n    records = list(FileReader(output).get_allocation_records())\n    vallocs = [\n        record\n        for record in filter_relevant_allocations(records)\n        if record.allocator == AllocatorType.VALLOC\n    ]\n\n    assert len(vallocs) == 1\n    (valloc,) = vallocs\n\n    assert len(valloc.stack_trace()) == 0\n    expected_symbols = [\"baz\", \"bar\", \"foo\"]\n    assert expected_symbols == [stack[0] for stack in valloc.hybrid_stack_trace()][:3]\n\n\ndef test_hybrid_stack_of_python_thread_starts_with_native_frames(tmp_path):\n    \"\"\"Ensure there are native frames above a thread's first Python frame.\"\"\"\n    # GIVEN\n    allocator = MemoryAllocator()\n    output = tmp_path / \"test.bin\"\n\n    def func():\n        allocator.valloc(1234)\n        allocator.free()\n\n    # WHEN\n    with Tracker(output, native_traces=True):\n        thread = threading.Thread(target=func)\n        thread.start()\n        thread.join()\n\n    # THEN\n    allocations = list(FileReader(output).get_allocation_records())\n\n    vallocs = [\n        event\n        for event in allocations\n        if event.size == 1234 and event.allocator == AllocatorType.VALLOC\n    ]\n    (valloc,) = vallocs\n    assert not valloc.hybrid_stack_trace()[-1][1].endswith(\".py\")\n\n\n@pytest.mark.parametrize(\"native_traces\", [True, False])\ndef test_native_tracing_header(native_traces, tmpdir):\n    # GIVEN\n    allocator = MemoryAllocator()\n    output = Path(tmpdir) / \"test.bin\"\n\n    # WHEN\n\n    with Tracker(output, native_traces=native_traces):\n        allocator.valloc(1234)\n\n    # THEN\n    assert FileReader(output).metadata.has_native_traces is native_traces\n"
  },
  {
    "path": "tests/integration/test_object_tracking.py",
    "content": "import gc\nimport sys\n\nimport pytest\n\nfrom memray import FileReader\nfrom memray import Tracker\n\n# Define a decorator for tests that require Python 3.13+\nrequires_at_least_py313 = pytest.mark.skipif(\n    sys.version_info < (3, 13, 3),\n    reason=\"Python object reference tracking requires Python 3.13 or later\",\n)\n\n# Define a decorator for tests that verify version-check errors on older Python\nrequires_older_python_than_py313 = pytest.mark.skipif(\n    sys.version_info >= (3, 13, 3),\n    reason=\"This test verifies error handling on Python < 3.13\",\n)\n\n\nclass MyClass:\n    def __init__(self, name):\n        self.name = name\n        self.data = list(range(10))  # Create some data\n\n\n@requires_older_python_than_py313\ndef test_track_object_lifetimes_version_check(tmp_path):\n    output = tmp_path / \"test.bin\"\n\n    # On Python < 3.13, creating a Tracker with track_object_lifetimes=True\n    # should raise RuntimeError\n    with pytest.raises(RuntimeError) as exc_info:\n        with Tracker(output, track_object_lifetimes=True):\n            pass\n    assert \"Python object reference tracking requires Python 3.13.3 or later\" in str(\n        exc_info.value\n    )\n    assert f\"Current version: {sys.version_info.major}.{sys.version_info.minor}\" in str(\n        exc_info.value\n    )\n\n\n@requires_older_python_than_py313\ndef test_get_surviving_objects_version_check(tmp_path):\n    output = tmp_path / \"test.bin\"\n\n    # Create a tracker without reference tracking (should work on all versions)\n    with Tracker(output) as tracker:\n        MyClass(\"test_object\")  # noqa\n\n    with pytest.raises(RuntimeError) as exc_info:\n        tracker.get_surviving_objects()\n    assert (\n        \"track_object_lifetimes=True was not provided at Tracker construction\"\n        in str(exc_info.value)\n    )\n\n\n@requires_older_python_than_py313\ndef test_get_tracked_objects_version_check(tmp_path):\n    output = tmp_path / \"test.bin\"\n\n    # Create a tracker without reference tracking\n    with Tracker(output):\n        MyClass(\"test_object\")\n\n    # Create FileReader\n    reader = FileReader(output)\n\n    # Calling get_object_lifetime_events should raise RuntimeError\n    with pytest.raises(RuntimeError) as exc_info:\n        list(reader.get_object_lifetime_events())\n    assert \"Object lifetime events are not available in this capture file\" in str(\n        exc_info.value\n    )\n\n\n@requires_at_least_py313\ndef test_track_object_lifetimes_disabled_by_default(tmp_path):\n    # GIVEN\n    output = tmp_path / \"test.bin\"\n\n    # WHEN\n    with Tracker(output) as tracker:\n        MyClass(\"test_object\")\n\n    # THEN\n    # Should raise RuntimeError because track_object_lifetimes was not enabled\n    with pytest.raises(RuntimeError) as exc_info:\n        tracker.get_surviving_objects()\n    assert (\n        \"track_object_lifetimes=True was not provided at Tracker construction\"\n        in str(exc_info.value)\n    )\n\n\n@requires_at_least_py313\ndef test_track_object_lifetimes_simple_object(tmp_path):\n    # GIVEN\n    output = tmp_path / \"test.bin\"\n\n    # WHEN\n    with Tracker(output, track_object_lifetimes=True) as tracker:\n        obj = MyClass(\"test_object\")\n        obj_id = id(obj)\n\n    # THEN\n    # The object should be tracked and returned in surviving_objects\n    surviving_objects = tracker.get_surviving_objects()\n\n    # There should be at least one surviving object (our MyClass instance)\n    assert len(surviving_objects) >= 1\n\n    # Ensure our object is in the list\n    test_obj = obj\n    assert any(o is obj for o in surviving_objects)\n\n    assert test_obj is not None, \"Our test object was not found in surviving objects\"\n    assert id(test_obj) == obj_id, \"Object IDs should match\"\n    assert test_obj.data == list(range(10)), \"Object data should be preserved\"\n\n    # Get tracked objects from the file and create address -> object mapping\n    reader = FileReader(output)\n    created_objects = {\n        obj.address: obj\n        for obj in reader.get_object_lifetime_events(included_objects=surviving_objects)\n        if obj.is_created\n    }\n\n    # Verify our object is in the tracked objects\n    assert obj_id in created_objects, \"Object ID should be in tracked objects\"\n    tracked_obj = created_objects[obj_id]\n    assert tracked_obj.is_created, \"Object should be marked as created\"\n\n\n@requires_at_least_py313\ndef test_track_object_lifetimes_deallocated_object(tmp_path):\n    # GIVEN\n    output = tmp_path / \"test.bin\"\n\n    # WHEN\n    # Create object and then delete it before the tracker exits\n    obj_ids = []\n    with Tracker(output, track_object_lifetimes=True) as tracker:\n        obj1 = MyClass(\"test_object1\")\n        obj_ids.append(id(obj1))\n\n        obj2 = MyClass(\"test_object2\")\n        obj_ids.append(id(obj2))\n\n        # Delete obj1 and make sure it's garbage collected\n        del obj1\n        gc.collect()\n\n    # THEN\n    # Only obj2 should be in the surviving objects\n    surviving_objects = tracker.get_surviving_objects()\n\n    # Check that only one of our created objects survived\n    test_objects = [obj for obj in surviving_objects if isinstance(obj, MyClass)]\n    assert len(test_objects) == 1\n    assert test_objects[0].name == \"test_object2\"\n\n    # Verify the ID matches obj2\n    assert test_objects[0] is obj2\n\n    # Get tracked objects from the file and create address -> object mapping\n    reader = FileReader(output)\n    created_objects = {\n        obj.address: obj\n        for obj in reader.get_object_lifetime_events()\n        if obj.is_created\n    }\n    deleted_objects = {\n        obj.address: obj\n        for obj in reader.get_object_lifetime_events()\n        if not obj.is_created\n    }\n\n    # Both objects should have creation records, even though one was deleted\n    assert obj_ids[0] in created_objects, \"Object 1 should have a creation record\"\n    assert obj_ids[1] in created_objects, \"Object 2 should have a creation record\"\n\n    # One object should have a deallocation record\n    assert obj_ids[0] in deleted_objects, \"Object 1 should have a deallocation record\"\n    assert (\n        obj_ids[1] not in deleted_objects\n    ), \"Object 2 should not have a deallocation record\"\n\n\n@requires_at_least_py313\ndef test_track_object_lifetimes_with_stack_trace(tmp_path):\n    # GIVEN\n    output = tmp_path / \"test.bin\"\n\n    # WHEN\n    with Tracker(output, track_object_lifetimes=True) as tracker:\n        obj = MyClass(\"test_object\")\n        obj_id = id(obj)\n\n    # THEN\n    # Check we can get stack traces for the tracked object\n    reader = FileReader(output)\n\n    # Find our object in the surviving objects\n    surviving_objects = tracker.get_surviving_objects()\n    assert any(\n        o is obj for o in surviving_objects\n    ), \"Test object not found in surviving objects\"\n\n    # Get tracked objects from the file and create address -> object mapping\n    created_objects = {\n        obj.address: obj\n        for obj in reader.get_object_lifetime_events(included_objects=surviving_objects)\n        if obj.is_created\n    }\n\n    # Should have our test object in the tracked objects\n    assert obj_id in created_objects, \"Object ID should be in tracked objects\"\n    tracked_obj = created_objects[obj_id]\n\n    # Get stack trace for the object\n    stack_trace = tracked_obj.hybrid_stack_trace()\n    assert stack_trace is not None, \"Stack trace should be available for the object\"\n    assert len(stack_trace) > 0, \"Stack trace should have at least one frame\"\n    assert stack_trace[0] == (\n        \"test_track_object_lifetimes_with_stack_trace\",\n        __file__,\n        200,\n    )\n\n    # Check that we can get native stack trace too\n    native_stack_trace = tracked_obj.native_stack_trace()\n    assert native_stack_trace == []\n\n    # Check Python stack trace\n    python_stack_trace = tracked_obj.stack_trace()\n    assert python_stack_trace is not None, \"Python stack trace should be available\"\n    assert python_stack_trace == [\n        (\"test_track_object_lifetimes_with_stack_trace\", __file__, 200)\n    ]\n\n\n@requires_at_least_py313\ndef test_multiple_surviving_objects(tmp_path):\n    # GIVEN\n    output = tmp_path / \"test.bin\"\n\n    # WHEN\n    objects = []\n    with Tracker(output, track_object_lifetimes=True) as tracker:\n        # Create multiple objects of different types\n        objects.append(MyClass(\"object1\"))\n        objects.append(MyClass(\"object2\"))\n        string_object = MyClass.__name__ * 2\n        objects.append(string_object)\n        objects.append({\"dict\": \"object\"})\n        objects.append([1, 2, 3])\n\n    # THEN\n    surviving_objects = tracker.get_surviving_objects()\n\n    # We should have at least our 5 objects\n    assert len(surviving_objects) >= 5\n\n    # Check for our custom objects\n    for obj in objects:\n        assert any(o is obj for o in surviving_objects)\n\n    # Get tracked objects from the file and create address -> object mapping\n    reader = FileReader(output)\n    created_objects = {\n        obj.address: obj\n        for obj in reader.get_object_lifetime_events(included_objects=surviving_objects)\n        if obj.is_created\n    }\n\n    # All objects should have creation records\n    for obj in objects:\n        assert (\n            id(obj) in created_objects\n        ), f\"Object with ID {id(obj)} should have a creation record\"\n\n\n@requires_at_least_py313\ndef test_object_tracking_in_threads(tmp_path):\n    # GIVEN\n    import threading\n\n    output = tmp_path / \"test.bin\"\n\n    # WHEN\n    thread_objects = {}\n\n    def thread_function(name):\n        # Create an object in this thread\n        obj = MyClass(f\"thread_{name}\")\n        thread_objects[name] = obj\n\n    with Tracker(output, track_object_lifetimes=True) as tracker:\n        # Create and run threads\n        threads = []\n        for i in range(3):\n            thread_name = f\"thread_{i}\"\n            thread = threading.Thread(target=thread_function, args=(thread_name,))\n            threads.append(thread)\n            thread.start()\n\n        # Wait for all threads to complete\n        for thread in threads:\n            thread.join()\n\n    # THEN\n    surviving_objects = tracker.get_surviving_objects()\n\n    # Check that objects created in threads are tracked\n    for name, obj in thread_objects.items():\n        # Find the object in surviving_objects\n        assert any(o is obj for o in surviving_objects)\n\n    # Get tracked objects from the file and create address -> object mapping\n    reader = FileReader(output)\n    created_objects = {\n        obj.address: obj\n        for obj in reader.get_object_lifetime_events(included_objects=surviving_objects)\n        if obj.is_created\n    }\n\n    # Verify each thread object has a creation record\n    for name, obj in thread_objects.items():\n        obj_id = id(obj)\n        assert (\n            obj_id in created_objects\n        ), f\"Object for thread {name} should have a creation record\"\n\n\n@requires_at_least_py313\ndef test_object_stack_trace_with_native_traces(tmp_path):\n    # GIVEN\n    output = tmp_path / \"test.bin\"\n\n    # WHEN\n    with Tracker(output, native_traces=True, track_object_lifetimes=True) as tracker:\n        obj = MyClass(\"test_object\")\n        obj_id = id(obj)\n\n    # THEN\n    # Get a handle to the file reader\n    reader = FileReader(output)\n    surviving_objects = tracker.get_surviving_objects()\n\n    # Find our test object\n    assert any(o is obj for o in surviving_objects)\n\n    # Get tracked objects from the file and create address -> object mapping\n    created_objects = {\n        obj.address: obj\n        for obj in reader.get_object_lifetime_events(included_objects=surviving_objects)\n        if obj.is_created\n    }\n\n    # Our object should be in the tracked objects\n    assert obj_id in created_objects, \"Object ID should be in tracked objects\"\n    tracked_obj = created_objects[obj_id]\n\n    # Get stack trace for the object\n    expected_stack_trace = (\"test_object_stack_trace_with_native_traces\", __file__, 346)\n\n    stack_trace = tracked_obj.hybrid_stack_trace()\n    assert stack_trace is not None, \"Stack trace should be available for the object\"\n    assert len(stack_trace) > 0, \"Stack trace should have at least one frame\"\n    assert expected_stack_trace in stack_trace\n\n    # Check that we can get native stack trace too\n    native_stack_trace = tracked_obj.native_stack_trace()\n    assert native_stack_trace is not None, \"Native stack trace should be available\"\n    assert len(native_stack_trace) > 0\n\n    # Check Python stack trace\n    python_stack_trace = tracked_obj.stack_trace()\n    assert python_stack_trace is not None, \"Python stack trace should be available\"\n    assert python_stack_trace != stack_trace\n    assert expected_stack_trace in python_stack_trace\n\n\n@requires_at_least_py313\ndef test_get_tracked_objects_without_filter(tmp_path):\n    # GIVEN\n    output = tmp_path / \"test.bin\"\n\n    # WHEN\n    with Tracker(output, track_object_lifetimes=True):\n        obj1 = MyClass(\"object1\")\n        obj2 = MyClass(\"object2\")\n\n        # Delete obj1 to create a deallocation record\n        obj1_id = id(obj1)\n        obj2_id = id(obj2)\n        del obj1\n        gc.collect()\n\n    # THEN\n    reader = FileReader(output)\n\n    # Get all tracked objects (without filter)\n    all_tracked_objects = list(reader.get_object_lifetime_events())\n\n    # Should have at least 3 records: 2 creation records and 1 deallocation record\n    assert (\n        len(all_tracked_objects) >= 3\n    ), \"Should have at least 3 tracked object records\"\n\n    # Create separate dictionaries for created and deallocated objects\n    created_objects = {\n        obj.address: obj for obj in all_tracked_objects if obj.is_created\n    }\n    deallocated_objects = {\n        obj.address: obj for obj in all_tracked_objects if not obj.is_created\n    }\n\n    # Both objects should have creation records\n    assert obj1_id in created_objects, \"obj1 should have a creation record\"\n    assert obj2_id in created_objects, \"obj2 should have a creation record\"\n\n    # Only obj1 should have a deallocation record\n    assert obj1_id in deallocated_objects, \"obj1 should have a deallocation record\"\n    assert (\n        obj2_id not in deallocated_objects\n    ), \"obj2 should not have a deallocation record\"\n\n    # Check we can get stack traces from the created objects\n    for address, obj in created_objects.items():\n        stack_trace = obj.stack_trace()\n        assert (\n            stack_trace is not None\n        ), f\"Stack trace should be available for object at {address}\"\n        assert (\n            len(stack_trace) > 0\n        ), f\"Stack trace should have at least one frame for object at {address}\"\n\n\n@requires_at_least_py313\ndef test_track_object_lifetimes_aggregating_writer(tmp_path):\n    # GIVEN\n    output = tmp_path / \"test.bin\"\n\n    # WHEN - Use aggregating writer (FileFormat.AGGREGATED_ALLOCATIONS)\n    from memray import FileFormat\n\n    objects = []\n    with Tracker(\n        output,\n        track_object_lifetimes=True,\n        file_format=FileFormat.AGGREGATED_ALLOCATIONS,\n    ) as tracker:\n        # Create multiple objects\n        obj1 = MyClass(\"aggregated_object1\")\n        obj2 = MyClass(\"aggregated_object2\")\n        objects.extend([obj1, obj2])\n\n        # Create and delete an object to test that only surviving ones are recorded\n        temp_obj = MyClass(\"temp_object\")\n        temp_obj_id = id(temp_obj)\n        del temp_obj\n        gc.collect()\n\n    # THEN\n    # Get surviving objects from tracker\n    surviving_objects = tracker.get_surviving_objects()\n\n    # Both obj1 and obj2 should be in surviving objects\n    assert len([o for o in surviving_objects if isinstance(o, MyClass)]) >= 2\n    assert any(\n        o is obj1 for o in surviving_objects\n    ), \"obj1 should be in surviving objects\"\n    assert any(\n        o is obj2 for o in surviving_objects\n    ), \"obj2 should be in surviving objects\"\n\n    # The temporary object should not be in surviving objects (it was deleted)\n    assert not any(\n        id(o) == temp_obj_id for o in surviving_objects\n    ), \"temp_obj should not be in surviving objects\"\n\n    # Read from the aggregated file to verify surviving objects are written correctly\n    reader = FileReader(output)\n\n    # Get object lifetime events - should only return surviving objects for aggregated files\n    tracked_objects = list(\n        reader.get_object_lifetime_events(included_objects=surviving_objects)\n    )\n\n    # All tracked objects in aggregated format should be marked as created (surviving)\n    for obj in tracked_objects:\n        assert (\n            obj.is_created\n        ), \"All objects in aggregated format should be marked as created/surviving\"\n\n    # Should include our test objects\n    tracked_addresses = {obj.address for obj in tracked_objects}\n    assert id(obj1) in tracked_addresses, \"obj1 should be in tracked objects\"\n    assert id(obj2) in tracked_addresses, \"obj2 should be in tracked objects\"\n    assert (\n        temp_obj_id not in tracked_addresses\n    ), \"temp_obj should not be in tracked objects\"\n\n\n@requires_at_least_py313\ndef test_track_object_lifetimes_fails_before_tracking_starts(tmp_path):\n    # GIVEN\n    output = tmp_path / \"test.bin\"\n\n    # WHEN\n    tracker = Tracker(output, track_object_lifetimes=True)\n    with pytest.raises(RuntimeError) as exc_info:\n        tracker.get_surviving_objects()\n\n    # THEN\n    assert \"Tracking was never started or has not finished yet or failed.\" in str(\n        exc_info.value\n    )\n\n\n@requires_at_least_py313\ndef test_track_object_lifetimes_fails_before_tracking_ends(tmp_path):\n    # GIVEN\n    output = tmp_path / \"test.bin\"\n\n    # WHEN\n    with Tracker(output, track_object_lifetimes=True) as tracker:\n        with pytest.raises(RuntimeError) as exc_info:\n            tracker.get_surviving_objects()\n\n    # THEN\n    assert \"Tracking was never started or has not finished yet or failed.\" in str(\n        exc_info.value\n    )\n"
  },
  {
    "path": "tests/integration/test_processes.py",
    "content": "import multiprocessing\nimport sys\nfrom multiprocessing import Pool\nfrom pathlib import Path\n\nimport pytest\n\nfrom memray import AllocatorType\nfrom memray import FileReader\nfrom memray import Tracker\nfrom memray._test import MemoryAllocator\nfrom memray._test import PymallocDomain\nfrom memray._test import PymallocMemoryAllocator\nfrom tests.utils import filter_relevant_allocations\nfrom tests.utils import filter_relevant_pymalloc_allocations\n\n\n@pytest.fixture(scope=\"module\", autouse=True)\ndef set_multiprocessing_to_fork():\n    current_method = multiprocessing.get_start_method()\n    multiprocessing.set_start_method(\"fork\", force=True)\n    yield\n    multiprocessing.set_start_method(current_method, force=True)\n\n\ndef multiproc_func(repetitions):  # pragma: no cover\n    allocator = MemoryAllocator()\n    for _ in range(repetitions):\n        allocator.valloc(1234)\n        allocator.free()\n\n\ndef pymalloc_multiproc_func():  # pragma: no cover\n    allocator = PymallocMemoryAllocator(PymallocDomain.PYMALLOC_RAW)\n    allocator.calloc(1234)\n    allocator.free()\n\n\n@pytest.mark.no_cover\ndef test_allocations_with_multiprocessing(tmpdir):\n    # GIVEN\n    output = Path(tmpdir) / \"test.bin\"\n    allocator = MemoryAllocator()\n\n    # WHEN\n    with Tracker(output):\n        with Pool(3) as p:\n            p.map(multiproc_func, [1, 10, 100, 1000, 2000, 3000, 4000, 5000])\n\n        allocator.valloc(1234)\n        allocator.free()\n\n    relevant_records = list(\n        filter_relevant_allocations(FileReader(output).get_allocation_records())\n    )\n    assert len(relevant_records) == 2\n\n    vallocs = [\n        record\n        for record in relevant_records\n        if record.allocator == AllocatorType.VALLOC\n    ]\n    assert len(vallocs) == 1\n    (valloc,) = vallocs\n    assert valloc.size == 1234\n\n    frees = [\n        record for record in relevant_records if record.allocator == AllocatorType.FREE\n    ]\n    assert len(frees) == 1\n\n    # No files created by child processes\n    child_files = Path(tmpdir).glob(\"test.bin.*\")\n    assert list(child_files) == []\n\n\n@pytest.mark.no_cover\ndef test_allocations_with_multiprocessing_following_fork(tmpdir):\n    # GIVEN\n    output = Path(tmpdir) / \"test.bin\"\n    allocator = MemoryAllocator()\n\n    # WHEN\n    with Tracker(output, follow_fork=True):\n        with Pool(3) as p:\n            p.map(multiproc_func, [1, 10, 100, 1000, 2000, 3000, 4000, 5000])\n\n        allocator.valloc(1234)\n        allocator.free()\n\n    # THEN\n    relevant_records = list(\n        filter_relevant_allocations(FileReader(output).get_allocation_records())\n    )\n    assert len(relevant_records) == 2\n\n    vallocs = [\n        record\n        for record in relevant_records\n        if record.allocator == AllocatorType.VALLOC\n    ]\n    assert len(vallocs) == 1\n    (valloc,) = vallocs\n    assert valloc.size == 1234\n\n    frees = [\n        record for record in relevant_records if record.allocator == AllocatorType.FREE\n    ]\n    assert len(frees) == 1\n\n    child_files = Path(tmpdir).glob(\"test.bin.*\")\n    child_records = []\n    for child_file in child_files:\n        child_records.extend(\n            filter_relevant_allocations(FileReader(child_file).get_allocation_records())\n        )\n\n    child_vallocs = [\n        record for record in child_records if record.allocator == AllocatorType.VALLOC\n    ]\n\n    child_frees = [\n        record for record in child_records if record.allocator == AllocatorType.FREE\n    ]\n\n    num_expected = 5000 + 4000 + 3000 + 2000 + 1000 + 100 + 10 + 1\n    assert len(child_vallocs) == num_expected\n\n    # We may be missing up to 1 free per process in the pool due to our\n    # heuristic for recovering from truncated files (see the comment\n    # where d_readable_size is set in source.cpp)\n    assert 0 <= len(child_vallocs) - len(child_frees) <= 3\n    for valloc in child_vallocs:\n        assert valloc.size == 1234\n\n\n@pytest.mark.no_cover\ndef test_pymalloc_allocations_after_fork(tmpdir):\n    # GIVEN\n    output = Path(tmpdir) / \"test.bin\"\n\n    # WHEN\n    with Tracker(output, follow_fork=True, trace_python_allocators=True):\n        with Pool(3) as p:\n            p.starmap(pymalloc_multiproc_func, [()] * 10)\n\n    # THEN\n    child_files = Path(tmpdir).glob(\"test.bin.*\")\n    child_records = []\n    for child_file in child_files:\n        child_records.extend(\n            filter_relevant_pymalloc_allocations(\n                FileReader(child_file).get_allocation_records(), size=1234\n            )\n        )\n\n    print(child_records)\n    child_callocs = [\n        record\n        for record in child_records\n        if record.allocator == AllocatorType.PYMALLOC_CALLOC and record.size == 1234\n    ]\n\n    num_expected = 10\n    assert len(child_callocs) == num_expected\n\n\n@pytest.mark.no_cover\ndef test_stack_cleanup_after_fork(tmpdir):\n    \"\"\"Test that we don't crash miserably when we try to write pending Python\n    frames when the profile function is deactivated if the tracker has been\n    destroyed after a fork without `follow_fork=True`\"\"\"\n\n    # GIVEN\n    output = Path(tmpdir) / \"test.bin\"\n\n    def foo():\n        with Pool() as pool:\n            result = pool.map_async(sys.setprofile, [None])\n            return result.get(timeout=1)\n\n    # WHEN\n\n    with Tracker(output, follow_fork=False):\n        result = foo()\n\n    # THEN\n\n    assert result == [None]\n"
  },
  {
    "path": "tests/integration/test_record_writer.py",
    "content": "import inspect\nimport itertools\nimport os\nimport re\nimport subprocess\nimport sys\nimport sysconfig\nimport textwrap\nfrom unittest.mock import ANY\n\nfrom memray import AllocatorType\nfrom memray import FileFormat\nfrom memray import FileReader\nfrom memray._memray import RecordWriterTestHarness\n\n\ndef get_sample_line_number_tables():\n    callers = []\n\n    def save_caller():\n        stack = inspect.stack()\n        caller = stack[1].frame\n        linetable = RecordWriterTestHarness.get_linetable(caller.f_code)\n\n        callers.append(\n            {\n                \"lasti\": RecordWriterTestHarness.get_lasti(caller),\n                \"linetable\": linetable,\n            }\n        )\n\n    def foo():\n        x = 10\n        y = 20\n        _ = x + y\n        save_caller()\n        return\n\n    def bar():\n        x = []\n        for _ in range(100):\n            x.append(x)\n\n        save_caller()\n\n        return None\n\n    def baz():\n        yield\n        save_caller()\n        return \"foo\"\n\n    foo()\n    bar()\n    list(baz())\n    return callers\n\n\ndef parse_capture_file(output_file):\n    output = subprocess.check_output(\n        [sys.executable, \"-m\", \"memray\", \"parse\", output_file],\n        encoding=\"utf-8\",\n    )\n    parsed = output.splitlines()\n    header, *rest = parsed\n\n    assert header.startswith(\"HEADER \")\n    header_fields = list(re.findall(r\"(\\S+)=(.*?)\\s*(?=\\S+=|$)\", header))\n    return header_fields, rest\n\n\ndef sort_runs_of_same_record_type(records):\n    sorted_records = []\n    for _, group in itertools.groupby(records, lambda line: line.split(\" \", 1)[0]):\n        sorted_records.extend(sorted(group))\n    return sorted_records\n\n\ndef test_write_basic_records(tmp_path):\n    \"\"\"Test writing basic records to a file.\"\"\"\n    # GIVEN\n    output_file = tmp_path / \"test.memray\"\n\n    # WHEN\n    writer = RecordWriterTestHarness(\n        str(output_file),\n        native_traces=True,\n        trace_python_allocators=True,\n        file_format=FileFormat.ALL_ALLOCATIONS,\n        main_tid=10,\n        skipped_frames=15,\n    )\n\n    assert writer.write_memory_record(1757101101880, 1024)\n    assert writer.write_memory_record(1757101102880, 2048)\n\n    assert writer.write_thread_record(1, \"MainThread\")\n    assert writer.write_thread_record(2, \"Other Thread\")\n\n    assert writer.write_code_object(1, \"a\", \"a.py\", b\"\", 1)\n    assert writer.write_code_object(2, \"b\", \"b.py\", b\"\", 11)\n    assert writer.write_code_object(3, \"c\", \"c.py\", b\"\", 21)\n\n    assert writer.write_frame_push(1, 1, 12, True)\n    assert writer.write_frame_push(1, 2, 34, True)\n    assert writer.write_frame_push(1, 3, 56, True)\n\n    assert writer.write_frame_pop(1, 0)\n    assert writer.write_frame_pop(1, 1)\n    assert writer.write_frame_pop(1, 16)\n    assert writer.write_frame_pop(1, 17)\n\n    assert writer.write_unresolved_native_frame(0xDEADBEEF, 1)\n    assert writer.write_unresolved_native_frame(0xFEEDCAFE, 2)\n\n    assert writer.write_allocation_record(1, 0x1000, 1024, AllocatorType.MALLOC, 1)\n    assert writer.write_allocation_record(1, 0x2000, 2048, AllocatorType.PYMALLOC_FREE)\n    assert writer.write_allocation_record(1, 0x3000, 4096, AllocatorType.POSIX_MEMALIGN)\n\n    assert writer.write_allocation_record(2, 0x4000, 4096, AllocatorType.MALLOC, 2)\n\n    assert writer.write_mappings(\n        [\n            {\n                \"filename\": \"/usr/lib/libc.so.6\",\n                \"addr\": 0xF1234567,\n                \"segments\": [\n                    {\"vaddr\": 0x12345678, \"memsz\": 0x1000},\n                    {\"vaddr\": 0xF2345678, \"memsz\": 0x2000},\n                ],\n            }\n        ]\n    )\n\n    assert writer.write_trailer()\n\n    # THEN\n    header_fields, records = parse_capture_file(output_file)\n    allocator = (\n        \"mimalloc\" if sysconfig.get_config_var(\"Py_GIL_DISABLED\") else \"pymalloc\"\n    )\n\n    assert header_fields == [\n        (\"magic\", \"memray\"),\n        (\"version\", \"12\"),\n        (\"python_version\", f\"{sys.hexversion:08x}\"),\n        (\"native_traces\", \"true\"),\n        (\"file_format\", \"ALL_ALLOCATIONS\"),\n        (\"n_allocations\", \"0\"),\n        (\"n_frames\", \"0\"),\n        (\"start_time\", ANY),\n        (\"end_time\", ANY),\n        (\"pid\", f\"{os.getpid()}\"),\n        (\"main_tid\", \"10\"),\n        (\"skipped_frames_on_main_tid\", \"15\"),\n        (\"command_line\", \"memray test harness\"),\n        (\"python_allocator\", allocator),\n        (\"trace_python_allocators\", \"true\"),\n        (\"track_object_lifetimes\", \"false\"),\n    ]\n\n    expected_parse_output = \"\"\"\n        MEMORY_RECORD time=1757101101880 memory=1024\n        MEMORY_RECORD time=1757101102880 memory=2048\n        CONTEXT_SWITCH tid=1\n        THREAD MainThread\n        CONTEXT_SWITCH tid=2\n        THREAD Other Thread\n        CODE_OBJECT code_id=1 function_name=a filename=a.py firstlineno=1 linetable_size=0\n        CODE_OBJECT code_id=2 function_name=b filename=b.py firstlineno=11 linetable_size=0\n        CODE_OBJECT code_id=3 function_name=c filename=c.py firstlineno=21 linetable_size=0\n        CONTEXT_SWITCH tid=1\n        FRAME_PUSH code_object_id=1 instruction_offset=12 is_entry_frame=1\n        FRAME_PUSH code_object_id=2 instruction_offset=34 is_entry_frame=1\n        FRAME_PUSH code_object_id=3 instruction_offset=56 is_entry_frame=1\n        FRAME_POP count=1\n        FRAME_POP count=16\n        FRAME_POP count=16\n        FRAME_POP count=1\n        NATIVE_FRAME_ID ip=0xdeadbeef index=1\n        NATIVE_FRAME_ID ip=0xfeedcafe index=2\n        ALLOCATION address=0x1000 size=1024 allocator=malloc native_frame_id=1\n        ALLOCATION address=0x2000 size=0 allocator=pymalloc_free native_frame_id=0\n        ALLOCATION address=0x3000 size=4096 allocator=posix_memalign native_frame_id=0\n        CONTEXT_SWITCH tid=2\n        ALLOCATION address=0x4000 size=4096 allocator=malloc native_frame_id=2\n        MEMORY_MAP_START\n        SEGMENT_HEADER filename=/usr/lib/libc.so.6 num_segments=2 addr=0xf1234567\n        SEGMENT 0x12345678 1000\n        SEGMENT 0xf2345678 2000\n        TRAILER\n    \"\"\"\n\n    expected_records = textwrap.dedent(expected_parse_output).strip().splitlines()\n    assert records == expected_records\n\n\ndef test_write_aggregated_records(tmp_path):\n    \"\"\"Test writing aggregated records to a file.\"\"\"\n    # GIVEN\n    output_file = tmp_path / \"test_aggregated.memray\"\n\n    # WHEN\n    writer = RecordWriterTestHarness(\n        str(output_file),\n        native_traces=False,\n        trace_python_allocators=False,\n        file_format=FileFormat.AGGREGATED_ALLOCATIONS,\n    )\n\n    assert writer.write_memory_record(1757105244685, 10000)\n\n    assert writer.write_code_object(10, \"a\", \"a.py\", b\"\", 1)\n    assert writer.write_code_object(20, \"b\", \"b.py\", b\"\", 11)\n    assert writer.write_code_object(30, \"c\", \"c.py\", b\"\", 21)\n\n    assert writer.write_frame_push(1, 1, 12, True)\n    assert writer.write_frame_push(1, 2, 34, True)\n    assert writer.write_allocation_record(1, 0x1000, 1024, AllocatorType.MALLOC)\n\n    assert writer.write_frame_push(2, 3, 56, True)\n    assert writer.write_allocation_record(2, 0x2000, 2048, AllocatorType.MALLOC)\n\n    assert writer.write_memory_record(1757105245685, 20000)\n\n    assert writer.write_trailer()\n\n    # THEN\n    header_fields, records = parse_capture_file(output_file)\n    allocator = (\n        \"mimalloc\" if sysconfig.get_config_var(\"Py_GIL_DISABLED\") else \"pymalloc\"\n    )\n\n    assert header_fields == [\n        (\"magic\", \"memray\"),\n        (\"version\", \"12\"),\n        (\"python_version\", f\"{sys.hexversion:08x}\"),\n        (\"native_traces\", \"false\"),\n        (\"file_format\", \"AGGREGATED_ALLOCATIONS\"),\n        (\"n_allocations\", \"0\"),\n        (\"n_frames\", \"0\"),\n        (\"start_time\", ANY),\n        (\"end_time\", ANY),\n        (\"pid\", f\"{os.getpid()}\"),\n        (\"main_tid\", \"1\"),\n        (\"skipped_frames_on_main_tid\", \"0\"),\n        (\"command_line\", \"memray test harness\"),\n        (\"python_allocator\", allocator),\n        (\"trace_python_allocators\", \"false\"),\n        (\"track_object_lifetimes\", \"false\"),\n    ]\n\n    records = sort_runs_of_same_record_type(records)\n    expected_parse_output = \"\"\"\n        MEMORY_SNAPSHOT time=1757105244685 rss=10000 heap=0\n        MEMORY_SNAPSHOT time=1757105245685 rss=20000 heap=3072\n        CODE_OBJECT code_id=10 function_name=a filename=a.py firstlineno=1 linetable_size=0\n        CODE_OBJECT code_id=20 function_name=b filename=b.py firstlineno=11 linetable_size=0\n        CODE_OBJECT code_id=30 function_name=c filename=c.py firstlineno=21 linetable_size=0\n        PYTHON_FRAME_INDEX frame_id=0 code_object_id=1 instruction_offset=12 is_entry_frame=1\n        PYTHON_FRAME_INDEX frame_id=1 code_object_id=2 instruction_offset=34 is_entry_frame=1\n        PYTHON_FRAME_INDEX frame_id=2 code_object_id=3 instruction_offset=56 is_entry_frame=1\n        PYTHON_TRACE_INDEX frame_id=0 parent_index=0\n        PYTHON_TRACE_INDEX frame_id=1 parent_index=1\n        PYTHON_TRACE_INDEX frame_id=2 parent_index=0\n        AGGREGATED_ALLOCATION tid=1 allocator=malloc native_frame_id=0 python_frame_id=2 native_segment_generation=0 n_allocations_in_high_water_mark=1 n_allocations_leaked=1 bytes_in_high_water_mark=1024 bytes_leaked=1024\n        AGGREGATED_ALLOCATION tid=2 allocator=malloc native_frame_id=0 python_frame_id=3 native_segment_generation=0 n_allocations_in_high_water_mark=1 n_allocations_leaked=1 bytes_in_high_water_mark=2048 bytes_leaked=2048\n        AGGREGATED_TRAILER\n    \"\"\"  # noqa: E501\n    expected_records = sort_runs_of_same_record_type(\n        textwrap.dedent(expected_parse_output).strip().splitlines()\n    )\n\n    assert records == expected_records\n\n\ndef test_decoding_line_numbers(tmp_path):\n    # GIVEN\n    funcs = get_sample_line_number_tables()\n    output_file = tmp_path / \"test.memray\"\n\n    # WHEN\n    writer = RecordWriterTestHarness(str(output_file))\n\n    assert writer.write_code_object(1, \"foo\", \"foo a.py\", funcs[0][\"linetable\"], 1)\n    assert writer.write_code_object(2, \"bar\", \"bar b.py\", funcs[1][\"linetable\"], 11)\n    assert writer.write_code_object(3, \"baz\", \"baz c.py\", funcs[2][\"linetable\"], 21)\n\n    assert writer.write_frame_push(1, 1, funcs[0][\"lasti\"], True)\n    assert writer.write_frame_push(1, 2, funcs[1][\"lasti\"], True)\n    assert writer.write_frame_push(1, 3, funcs[2][\"lasti\"], True)\n\n    assert writer.write_allocation_record(1, 0x1000, 1024, AllocatorType.MALLOC)\n\n    # THEN\n    with FileReader(output_file) as reader:\n        allocations = list(reader.get_allocation_records())\n        assert len(allocations) == 1\n        assert allocations[0].stack_trace() == [\n            (\"baz\", \"baz c.py\", 23),\n            (\"bar\", \"bar b.py\", 16),\n            (\"foo\", \"foo a.py\", 5),\n        ]\n\n\ndef test_write_object_tracking_records(tmp_path):\n    \"\"\"Test writing object tracking records to a file.\"\"\"\n    # GIVEN\n    output_file = tmp_path / \"test_object_tracking.memray\"\n\n    # WHEN\n    writer = RecordWriterTestHarness(\n        str(output_file),\n        native_traces=True,\n        trace_python_allocators=False,\n        track_object_lifetimes=True,\n        file_format=FileFormat.ALL_ALLOCATIONS,\n        main_tid=1,\n    )\n\n    # Write object tracking records\n    assert writer.write_object_record(1, 0x12345678, True, 0)  # Object created\n    assert writer.write_object_record(\n        1, 0x87654321, True, 1\n    )  # Object created with native frame\n    assert writer.write_object_record(1, 0x12345678, False, 0)  # Object destroyed\n    assert writer.write_object_record(\n        1, 0x87654321, False, 1\n    )  # Object destroyed with native frame\n\n    assert writer.write_trailer()\n\n    # THEN\n    header_fields, records = parse_capture_file(output_file)\n\n    # Check that track_object_lifetimes is in the header\n    header_dict = dict(header_fields)\n    assert header_dict.get(\"track_object_lifetimes\") == \"true\"\n\n    expected_parse_output = \"\"\"\n    CONTEXT_SWITCH tid=1\n    OBJECT_RECORD address=0x12345678 native_frame_id=0\n    OBJECT_RECORD address=0x87654320 native_frame_id=1\n    OBJECT_RECORD address=0x12345678 native_frame_id=0\n    OBJECT_RECORD address=0x87654320 native_frame_id=0\n    TRAILER\n    \"\"\"\n\n    expected_records = textwrap.dedent(expected_parse_output).strip().splitlines()\n    assert records == expected_records\n\n\ndef test_write_object_tracking_records_aggregated(tmp_path):\n    # GIVEN\n    output_file = tmp_path / \"test_object_tracking_aggregated.memray\"\n\n    # WHEN\n    writer = RecordWriterTestHarness(\n        str(output_file),\n        native_traces=True,\n        trace_python_allocators=False,\n        track_object_lifetimes=True,\n        file_format=FileFormat.AGGREGATED_ALLOCATIONS,\n        main_tid=1,\n    )\n\n    # Write object tracking records - create and destroy some objects\n    assert writer.write_object_record(1, 0x12345678, True, 0)  # Object created\n    assert writer.write_object_record(\n        1, 0x87654321, True, 1\n    )  # Object created with native frame\n    assert writer.write_object_record(1, 0xAABBCCDD, True, 2)  # Another object created\n    assert writer.write_object_record(1, 0x12345678, False, 0)  # First object destroyed\n    # 0x87654321 and 0xAABBCCDD survive\n\n    assert writer.write_trailer()\n\n    # THEN\n    header_fields, records = parse_capture_file(output_file)\n\n    # Check that track_object_lifetimes is in the header\n    header_dict = dict(header_fields)\n    assert header_dict.get(\"track_object_lifetimes\") == \"true\"\n    assert header_dict.get(\"file_format\") == \"AGGREGATED_ALLOCATIONS\"\n\n    expected_parse_output = \"\"\"\n    SURVIVING_OBJECT address=0x0xaabbccd8 native_frame_id=2\n    SURVIVING_OBJECT address=0x0x87654320 native_frame_id=1\n    AGGREGATED_TRAILER\n    \"\"\"\n\n    records = sort_runs_of_same_record_type(records)\n    expected_records = sort_runs_of_same_record_type(\n        textwrap.dedent(expected_parse_output).strip().splitlines()\n    )\n\n    assert records == expected_records\n"
  },
  {
    "path": "tests/integration/test_socket.py",
    "content": "\"\"\"Tests to exercise socket-based read and write operations in the Tracker.\"\"\"\n\nimport os\nimport subprocess\nimport sys\nimport textwrap\nimport time\nfrom contextlib import contextmanager\nfrom pathlib import Path\nfrom typing import Iterator\nfrom typing import Set\nfrom typing import Tuple\n\nimport pytest\n\nfrom memray import AllocatorType\nfrom memray import SocketReader\nfrom tests.utils import filter_relevant_allocations\n\nTIMEOUT = 5\nALLOCATION_SIZE = 1234\nMULTI_ALLOCATION_COUNT = 10\n\n#\n# Test helpers\n#\n_SCRIPT_TEMPLATE = \"\"\"\nimport sys\nfrom memray._test import MemoryAllocator\nfrom memray._memray import SocketDestination\nfrom memray._memray import Tracker\n\n# Sanity checks\nport = int(sys.argv[1])\nassert sys.argv[2].endswith(\"allocations_made.event\")\nassert sys.argv[3].endswith(\"snapshot_taken.event\")\n\n\ndef get_tracker():\n    return Tracker(destination=SocketDestination(server_port=port))\n\n\ndef snapshot_point():\n    print(\"[child] Notifying allocations made\")\n    with open(sys.argv[2], \"w\") as allocations_made:\n        allocations_made.write(\"done\")\n    print(\"[child] Waiting on snapshot taken\")\n    with open(sys.argv[3], \"r\") as snapshot_taken:\n        response = snapshot_taken.read()\n    assert response == \"done\"\n    print(\"[child] Continuing execution\")\n\n{body}\n\"\"\"\n\nALLOCATE_THEN_FREE_THEN_SNAPSHOT = textwrap.dedent(\n    f\"\"\"\n        allocator = MemoryAllocator()\n\n        with get_tracker():\n            allocator.valloc({ALLOCATION_SIZE})\n            allocator.free()\n            snapshot_point()\n    \"\"\"\n)\nALLOCATE_THEN_SNAPSHOT_THEN_FREE = textwrap.dedent(\n    f\"\"\"\n        allocator = MemoryAllocator()\n        with get_tracker():\n            allocator.valloc({ALLOCATION_SIZE})\n            snapshot_point()\n            allocator.free()\n    \"\"\"\n)\nALLOCATE_MANY_THEN_SNAPSHOT_THEN_FREE_MANY = textwrap.dedent(\n    f\"\"\"\n        allocators = [MemoryAllocator() for _ in range({MULTI_ALLOCATION_COUNT})]\n        with get_tracker():\n            for allocator in allocators:\n                allocator.valloc({ALLOCATION_SIZE})\n            snapshot_point()\n            for allocator in allocators:\n                allocator.free()\n    \"\"\"\n)\n\n\n@contextmanager\ndef run_till_snapshot_point(\n    program: str,\n    *,\n    reader: SocketReader,\n    tmp_path: Path,\n    free_port: int,\n) -> Iterator[None]:\n    allocations_made = tmp_path / \"allocations_made.event\"\n    snapshot_taken = tmp_path / \"snapshot_taken.event\"\n    os.mkfifo(allocations_made)\n    os.mkfifo(snapshot_taken)\n\n    script = _SCRIPT_TEMPLATE.format(body=program)\n\n    env = os.environ.copy()\n    env.pop(\"PYTHONMALLOC\", None)\n    proc = subprocess.Popen(\n        [\n            sys.executable,\n            \"-c\",\n            script,\n            str(free_port),\n            allocations_made,\n            snapshot_taken,\n        ],\n        env=env,\n    )\n\n    try:\n        with reader:\n            print(\"[parent] Waiting on allocations made\")\n            with open(allocations_made, \"r\") as f1:\n                assert f1.read() == \"done\"\n\n            print(\"[parent] Deferring to caller\")\n            # Wait a bit of time, for background thread to receive + process the records.\n            time.sleep(0.1)\n            yield\n\n            print(\"[parent] Notifying program to continue\")\n            with open(snapshot_taken, \"w\") as f2:\n                f2.write(\"done\")\n            print(\"[parent] Will close socket reader now.\")\n    finally:\n        print(\"[parent] Waiting on child to exit.\")\n        try:\n            assert proc.wait(timeout=TIMEOUT) == 0\n        except subprocess.TimeoutExpired:\n            print(\"[parent] Killing child, after timeout.\")\n            proc.kill()\n            raise\n\n\n#\n# Actual tests\n#\nclass TestSocketReaderErrorHandling:\n    @pytest.mark.valgrind\n    def test_get_current_snapshot_raises_before_context(self, free_port: int) -> None:\n        # GIVEN\n        reader = SocketReader(port=free_port)\n\n        # WHEN / THEN\n        with pytest.raises(StopIteration):\n            next(reader.get_current_snapshot(merge_threads=False))\n\n    def test_get_is_active_after_context(self, free_port: int, tmp_path: Path) -> None:\n        # GIVEN\n        reader = SocketReader(port=free_port)\n        program = ALLOCATE_THEN_SNAPSHOT_THEN_FREE\n\n        # WHEN\n        with run_till_snapshot_point(\n            program,\n            reader=reader,\n            tmp_path=tmp_path,\n            free_port=free_port,\n        ):\n            pass\n\n        # THEN\n        assert reader.is_active is False\n\n    @pytest.mark.valgrind\n    def test_get_current_snapshot_raises_after_context(\n        self, free_port: int, tmp_path: Path\n    ) -> None:\n        # GIVEN\n        reader = SocketReader(port=free_port)\n        program = ALLOCATE_THEN_SNAPSHOT_THEN_FREE\n\n        # WHEN\n        with run_till_snapshot_point(\n            program,\n            reader=reader,\n            tmp_path=tmp_path,\n            free_port=free_port,\n        ):\n            pass\n\n        # THEN\n        with pytest.raises(StopIteration):\n            next(reader.get_current_snapshot(merge_threads=False))\n\n    @pytest.mark.valgrind\n    def test_get_current_snapshot_first_yield_after_context_raises(\n        self, free_port: int, tmp_path: Path\n    ) -> None:\n        # GIVEN\n        reader = SocketReader(port=free_port)\n        program = ALLOCATE_THEN_SNAPSHOT_THEN_FREE\n\n        # WHEN\n        with run_till_snapshot_point(\n            program,\n            reader=reader,\n            tmp_path=tmp_path,\n            free_port=free_port,\n        ):\n            snapshot = reader.get_current_snapshot(merge_threads=False)\n\n        # THEN\n        with pytest.raises(StopIteration):\n            next(snapshot)\n\n    @pytest.mark.valgrind\n    def test_nested_context_is_diallowed(self, free_port: int, tmp_path: Path) -> None:\n        # GIVEN\n        reader = SocketReader(port=free_port)\n        program = ALLOCATE_THEN_FREE_THEN_SNAPSHOT\n\n        # WHEN\n        with run_till_snapshot_point(\n            program,\n            reader=reader,\n            tmp_path=tmp_path,\n            free_port=free_port,\n        ):\n            # THEN\n            with pytest.raises(\n                ValueError, match=\"Can not enter (.*)context (.*)more than once\"\n            ):\n                with reader:\n                    pass\n\n\nclass TestSocketReaderAccess:\n    @pytest.mark.valgrind\n    def test_empty_snapshot_after_free(self, free_port: int, tmp_path: Path) -> None:\n        # GIVEN\n        reader = SocketReader(port=free_port)\n        program = ALLOCATE_THEN_FREE_THEN_SNAPSHOT\n\n        # WHEN\n        with run_till_snapshot_point(\n            program,\n            reader=reader,\n            tmp_path=tmp_path,\n            free_port=free_port,\n        ):\n            unfiltered_snapshot = list(reader.get_current_snapshot(merge_threads=False))\n\n        # THEN\n        snapshot = list(filter_relevant_allocations(unfiltered_snapshot))\n        assert snapshot == []\n\n    @pytest.mark.valgrind\n    def test_single_allocation_snapshot(self, free_port: int, tmp_path: Path) -> None:\n        # GIVEN\n        reader = SocketReader(port=free_port)\n        program = ALLOCATE_THEN_SNAPSHOT_THEN_FREE\n\n        # WHEN\n        with run_till_snapshot_point(\n            program,\n            reader=reader,\n            tmp_path=tmp_path,\n            free_port=free_port,\n        ):\n            unfiltered_snapshot = list(reader.get_current_snapshot(merge_threads=False))\n\n        # THEN\n        snapshot = list(filter_relevant_allocations(unfiltered_snapshot))\n        assert len(snapshot) == 1\n\n        allocation = snapshot[0]\n        assert allocation.size == ALLOCATION_SIZE * 1\n        assert allocation.allocator == AllocatorType.VALLOC\n\n        symbol, filename, lineno = allocation.stack_trace()[0]\n        assert symbol == \"valloc\"\n        assert filename.endswith(\"/_test.py\")\n        assert 0 < lineno < 200\n\n    @pytest.mark.valgrind\n    def test_multi_allocation_snapshot(self, free_port: int, tmp_path: Path) -> None:\n        # GIVEN\n        reader = SocketReader(port=free_port)\n        program = ALLOCATE_MANY_THEN_SNAPSHOT_THEN_FREE_MANY\n\n        # WHEN\n        with run_till_snapshot_point(\n            program,\n            reader=reader,\n            tmp_path=tmp_path,\n            free_port=free_port,\n        ):\n            unfiltered_snapshot = list(reader.get_current_snapshot(merge_threads=False))\n\n        # THEN\n        snapshot = list(filter_relevant_allocations(unfiltered_snapshot))\n        assert len(snapshot) == 1\n\n        allocation = snapshot[0]\n        assert allocation.size == ALLOCATION_SIZE * 10\n        assert allocation.allocator == AllocatorType.VALLOC\n\n        symbol, filename, lineno = allocation.stack_trace()[0]\n        assert symbol == \"valloc\"\n        assert filename.endswith(\"/_test.py\")\n        assert 0 < lineno < 200\n\n    @pytest.mark.valgrind\n    def test_multiple_context_entries_does_not_crash(\n        self, free_port: int, tmp_path: Path\n    ) -> None:\n        # GIVEN\n        reader = SocketReader(port=free_port)\n        program = ALLOCATE_THEN_FREE_THEN_SNAPSHOT\n        tmp_path_one = tmp_path / \"one\"\n        tmp_path_one.mkdir()\n        tmp_path_two = tmp_path / \"two\"\n        tmp_path_two.mkdir()\n\n        # WHEN\n        with run_till_snapshot_point(\n            program,\n            reader=reader,\n            tmp_path=tmp_path_one,\n            free_port=free_port,\n        ):\n            pass\n\n        # THEN\n        with run_till_snapshot_point(\n            program,\n            reader=reader,\n            tmp_path=tmp_path_two,\n            free_port=free_port,\n        ):\n            pass\n\n    @pytest.mark.valgrind\n    def test_command_line(self, free_port: int, tmp_path: Path) -> None:\n        # GIVEN\n        reader = SocketReader(port=free_port)\n        program = ALLOCATE_THEN_FREE_THEN_SNAPSHOT\n\n        # WHEN\n        with run_till_snapshot_point(\n            program,\n            reader=reader,\n            tmp_path=tmp_path,\n            free_port=free_port,\n        ):\n            command_line = reader.command_line\n\n        # THEN\n        assert command_line\n        assert command_line.startswith(\"-c\")  # these samples run with `python -c`\n        assert str(free_port) in command_line\n\n    @pytest.mark.valgrind\n    def test_reading_allocations_while_reading_stack_traces(\n        self, free_port: int, tmp_path: Path\n    ) -> None:\n        \"\"\"This test exist mainly to give valgrind/helgrind the opportunity to\n        see races between fetching stack traces and the background thread\n        fetching allocations. Therefore no interesting asserts are done in\n        the test itself.\n\n        The test will spawn a tracked process that is constantly creating new\n        functions and code objects so the process is constantly sending new\n        frames to the SocketReader, triggering tons of updates of the internal\n        structures inside. We want to check that if we get the stack traces\n        inside the allocations it won't crash/race with fetching new allocations\n        \"\"\"\n        # GIVEN\n        script = textwrap.dedent(\n            f\"\"\"\\\n            from memray._test import MemoryAllocator\n            from memray._memray import SocketDestination\n            from memray._memray import Tracker\n            from itertools import count\n            import textwrap\n\n            def foo(allocator, n):\n                fname = f\"blech_{{n}}\"\n                namespace = {{}}\n\n                exec(textwrap.dedent(f'''\n                def {{fname}}(allocator):\n                    allocator.valloc(1024)\n                    allocator.free()\n                '''), namespace, namespace)\n\n                func = namespace[fname]\n                func(allocator)\n\n            with Tracker(destination=SocketDestination(server_port={free_port})):\n                allocator = MemoryAllocator()\n                for n in count(0):\n                    foo(allocator, n)\n        \"\"\"\n        )\n        code = [\n            sys.executable,\n            \"-c\",\n            script,\n        ]\n        traces: Set[Tuple[str, str, int]] = set()\n        MAX_TRACES = 10\n\n        # WHEN\n        with subprocess.Popen(code) as proc:\n            with SocketReader(port=free_port) as reader:\n                while len(traces) < MAX_TRACES:\n                    for allocation in reader.get_current_snapshot(merge_threads=False):\n                        traces.update(allocation.stack_trace())\n\n                proc.terminate()\n\n        # THEN\n        assert len(traces) >= MAX_TRACES\n"
  },
  {
    "path": "tests/integration/test_threads.py",
    "content": "import threading\nfrom pathlib import Path\n\nfrom memray import AllocatorType\nfrom memray import FileReader\nfrom memray import Tracker\nfrom memray._test import MemoryAllocator\nfrom memray._test import set_thread_name\nfrom tests.utils import filter_relevant_allocations\nfrom tests.utils import skip_if_macos\n\nHERE = Path(__file__).parent\nTEST_MULTITHREADED_EXTENSION = HERE / \"multithreaded_extension\"\n\n\ndef allocating_function(allocator, flag_event, wait_event):\n    allocator.valloc(1234)\n    allocator.free()\n    flag_event.set()\n    wait_event.wait()\n    allocator.valloc(1234)\n    allocator.free()\n\n\ndef test_thread_allocations_after_tracker_is_deactivated(tmpdir):\n    # GIVEN\n    output = Path(tmpdir) / \"test.bin\"\n    wait_event = threading.Event()\n    flag_event = threading.Event()\n    allocator = MemoryAllocator()\n\n    # WHEN\n    with Tracker(output):\n        t = threading.Thread(\n            target=allocating_function, args=(allocator, flag_event, wait_event)\n        )\n        t.start()\n        flag_event.wait()\n\n    # Keep allocating in the same thread while the tracker is not active\n    wait_event.set()\n    t.join()\n\n    # THEN\n    relevant_records = list(\n        filter_relevant_allocations(FileReader(output).get_allocation_records())\n    )\n    assert len(relevant_records) == 2\n\n    vallocs = [\n        record\n        for record in relevant_records\n        if record.allocator == AllocatorType.VALLOC\n    ]\n    assert len(vallocs) == 1\n    (valloc,) = vallocs\n    assert valloc.size == 1234\n\n    frees = [\n        record for record in relevant_records if record.allocator == AllocatorType.FREE\n    ]\n    assert len(frees) == 1\n\n\n@skip_if_macos\ndef test_thread_name(tmpdir):\n    # GIVEN\n    output = Path(tmpdir) / \"test.bin\"\n    allocator = MemoryAllocator()\n\n    def allocating_function():\n        set_thread_name(\"my thread name\")\n        allocator.valloc(1234)\n        allocator.free()\n\n    # WHEN\n    with Tracker(output):\n        t = threading.Thread(target=allocating_function)\n        t.start()\n        t.join()\n\n    # THEN\n    relevant_records = list(\n        filter_relevant_allocations(FileReader(output).get_allocation_records())\n    )\n    assert len(relevant_records) == 2\n\n    vallocs = [\n        record\n        for record in relevant_records\n        if record.allocator == AllocatorType.VALLOC\n    ]\n    assert len(vallocs) == 1\n    (valloc,) = vallocs\n    assert valloc.size == 1234\n    assert \"my thread name\" == valloc.thread_name\n\n\ndef test_setting_python_thread_name(tmpdir):\n    # GIVEN\n    output = Path(tmpdir) / \"test.bin\"\n    allocator = MemoryAllocator()\n    name_set_inside_thread = threading.Event()\n    name_set_outside_thread = threading.Event()\n    prctl_rc = -1\n\n    def allocating_function():\n        allocator.valloc(1234)\n        allocator.free()\n\n        threading.current_thread().name = \"set inside thread\"\n        allocator.valloc(1234)\n        allocator.free()\n\n        name_set_inside_thread.set()\n        name_set_outside_thread.wait()\n        allocator.valloc(1234)\n        allocator.free()\n\n        nonlocal prctl_rc\n        prctl_rc = set_thread_name(\"set by prctl\")\n        allocator.valloc(1234)\n        allocator.free()\n\n    # WHEN\n    with Tracker(output):\n        t = threading.Thread(target=allocating_function, name=\"set before start\")\n        t.start()\n        name_set_inside_thread.wait()\n        t.name = \"set outside running thread\"\n        name_set_outside_thread.set()\n        t.join()\n\n    # THEN\n    expected_names = [\n        \"set before start\",\n        \"set inside thread\",\n        \"set outside running thread\",\n        \"set by prctl\" if prctl_rc == 0 else \"set outside running thread\",\n    ]\n    names = [\n        rec.thread_name\n        for rec in FileReader(output).get_allocation_records()\n        if rec.allocator == AllocatorType.VALLOC\n    ]\n    assert names == expected_names\n"
  },
  {
    "path": "tests/integration/test_tracing.py",
    "content": "import mmap\nimport os\nimport sys\nimport threading\nfrom pathlib import Path\n\nimport pytest\n\nfrom memray import AllocatorType\nfrom memray import FileReader\nfrom memray import Tracker\nfrom memray._test import MemoryAllocator\nfrom memray._test import _cython_nested_allocation\nfrom memray._test import allocate_without_gil_held\nfrom memray._test import function_caller\n\n\ndef alloc_func3(allocator):\n    x = 1\n    allocator.valloc(123456)\n    x = 2\n    allocator.free()\n    x = 3\n    return x\n\n\ndef alloc_func2(allocator):\n    y = 1\n    alloc_func3(allocator)\n    y = 2\n    return y\n\n\ndef alloc_func1(allocator):\n    z = 1\n    alloc_func2(allocator)\n    z = 2\n    return z\n\n\ndef test_traceback(tmpdir):\n    # GIVEN\n    allocator = MemoryAllocator()\n    output = Path(tmpdir) / \"test.bin\"\n\n    # WHEN\n\n    with Tracker(output):\n        alloc_func1(allocator)\n    records = list(FileReader(output).get_allocation_records())\n\n    # THEN\n\n    allocs = [record for record in records if record.allocator == AllocatorType.VALLOC]\n    assert len(allocs) == 1\n    (alloc,) = allocs\n    traceback = list(alloc.stack_trace())\n    assert traceback[-4:] == [\n        (\"alloc_func3\", __file__, 20),\n        (\"alloc_func2\", __file__, 29),\n        (\"alloc_func1\", __file__, 36),\n        (\"test_traceback\", __file__, 49),\n    ]\n    frees = [\n        record\n        for record in records\n        if record.allocator == AllocatorType.FREE and record.address == alloc.address\n    ]\n    assert len(frees) == 1\n    (free,) = frees\n    with pytest.raises(NotImplementedError):\n        free.stack_trace()\n\n\ndef test_traceback_for_high_watermark(tmpdir):\n    # GIVEN\n    allocator = MemoryAllocator()\n    output = Path(tmpdir) / \"test.bin\"\n\n    # WHEN\n\n    with Tracker(output):\n        alloc_func1(allocator)\n    records = list(FileReader(output).get_high_watermark_allocation_records())\n\n    # THEN\n\n    allocs = [record for record in records if record.allocator == AllocatorType.VALLOC]\n    assert len(allocs) == 1\n    (alloc,) = allocs\n    traceback = list(alloc.stack_trace())\n    assert traceback[-4:] == [\n        (\"alloc_func3\", __file__, 20),\n        (\"alloc_func2\", __file__, 29),\n        (\"alloc_func1\", __file__, 36),\n        (\"test_traceback_for_high_watermark\", __file__, 83),\n    ]\n\n\ndef test_traceback_iteration_does_not_depend_on_the_order_of_elements(tmpdir):\n    # GIVEN\n    allocator = MemoryAllocator()\n    output = Path(tmpdir) / \"test.bin\"\n\n    # WHEN\n\n    with Tracker(output):\n        alloc_func1(allocator)\n        alloc_func1(allocator)\n\n    # THEN\n\n    records = list(FileReader(output).get_allocation_records())\n    allocs = [record for record in records if record.allocator == AllocatorType.VALLOC]\n    alloc1, alloc2 = allocs\n    traceback1 = list(alloc1.stack_trace())\n    traceback2 = list(alloc2.stack_trace())\n\n    records = list(FileReader(output).get_allocation_records())\n    allocs = [record for record in records if record.allocator == AllocatorType.VALLOC]\n    alloc1, alloc2 = allocs\n    assert traceback2 == list(alloc2.stack_trace())\n    assert traceback1 == list(alloc1.stack_trace())\n\n\ndef test_cython_traceback(tmpdir):\n    # GIVEN\n    allocator = MemoryAllocator()\n    output = Path(tmpdir) / \"test.bin\"\n\n    # WHEN\n\n    with Tracker(output):\n        _cython_nested_allocation(allocator.valloc, 1234)\n    allocator.free()\n    records = list(FileReader(output).get_allocation_records())\n\n    # THEN\n\n    allocs = [record for record in records if record.allocator == AllocatorType.VALLOC]\n    assert len(allocs) == 2\n    alloc1, alloc2 = allocs\n\n    traceback = list(alloc1.stack_trace())\n    assert traceback == [\n        (\"valloc\", sys.modules[\"memray._test\"].__file__, 44),\n        (\"test_cython_traceback\", __file__, 134),\n    ]\n\n    traceback = list(alloc2.stack_trace())\n    assert traceback == [\n        (\"test_cython_traceback\", __file__, 134),\n    ]\n\n    frees = [\n        record\n        for record in records\n        if record.allocator == AllocatorType.FREE and record.address == alloc2.address\n    ]\n    assert len(frees) == 1\n    (free,) = frees\n    with pytest.raises(NotImplementedError):\n        free.stack_trace()\n\n\ndef test_large_number_of_frame_pops_between_subsequent_allocations(tmpdir):\n    # GIVEN\n    output = Path(tmpdir) / \"test.bin\"\n\n    def allocate_deep(depth):\n        if depth <= 1:\n            return mmap.mmap(-1, 1234)\n        return allocate_deep(depth - 1)\n\n    # WHEN\n    # Note: we don't actually care about the native stacks, but we use\n    # native_traces=True to ensure that the allocation we care about inside\n    # of `mmap.mmap` has a different stack than any allocation that the\n    # interpreter itself performs. Otherwise, our high water mark aggregator\n    # could combine the mmap we care about with other allocations performed\n    # inside the interpreter that happen to share the same Python stack.\n    with Tracker(output, native_traces=True):\n        with allocate_deep(20):\n            with mmap.mmap(-1, 12345):\n                pass\n    records = list(FileReader(output).get_high_watermark_allocation_records())\n\n    # THEN\n    allocs = [\n        record\n        for record in records\n        if record.allocator == AllocatorType.MMAP and record.size == 1234\n    ]\n    assert len(allocs) == 1\n    (alloc,) = allocs\n    traceback = list(alloc.stack_trace())\n    assert len(traceback) == 21\n\n    allocs = [\n        record\n        for record in records\n        if record.allocator == AllocatorType.MMAP and record.size == 12345\n    ]\n    assert len(allocs) == 1\n    (alloc,) = allocs\n    traceback = list(alloc.stack_trace())\n    assert len(traceback) == 1\n\n\ndef test_records_can_be_retrieved_twice(tmpdir):\n    # GIVEN\n    allocator = MemoryAllocator()\n    output = Path(tmpdir) / \"test.bin\"\n\n    # WHEN\n\n    with Tracker(output):\n        alloc_func1(allocator)\n\n    # THEN\n\n    reader = FileReader(output)\n    records1 = list(reader.get_allocation_records())\n    records2 = list(reader.get_allocation_records())\n\n    assert records1 == records2\n\n\ndef test_high_watermark_records_can_be_retrieved_twice(tmpdir):\n    # GIVEN\n    allocator = MemoryAllocator()\n    output = Path(tmpdir) / \"test.bin\"\n\n    # WHEN\n\n    with Tracker(output):\n        alloc_func1(allocator)\n\n    # THEN\n\n    reader = FileReader(output)\n    records1 = list(reader.get_high_watermark_allocation_records())\n    records2 = list(reader.get_high_watermark_allocation_records())\n\n    assert records1 == records2\n\n\ndef test_traceback_can_be_retrieved_twice(tmpdir):\n    # GIVEN\n    allocator = MemoryAllocator()\n    output = Path(tmpdir) / \"test.bin\"\n\n    # WHEN\n\n    with Tracker(output):\n        alloc_func1(allocator)\n\n    # THEN\n\n    records = list(FileReader(output).get_allocation_records())\n    allocs = [record for record in records if record.allocator == AllocatorType.VALLOC]\n    (alloc,) = allocs\n    traceback1 = list(alloc.stack_trace())\n    traceback2 = list(alloc.stack_trace())\n    assert traceback1 == traceback2\n\n\ndef test_traceback_for_high_watermark_records_can_be_retrieved_twice(tmpdir):\n    # GIVEN\n    allocator = MemoryAllocator()\n    output = Path(tmpdir) / \"test.bin\"\n\n    # WHEN\n\n    with Tracker(output):\n        alloc_func1(allocator)\n\n    # THEN\n\n    reader = FileReader(output)\n    records = list(reader.get_high_watermark_allocation_records())\n    (alloc,) = records\n    traceback1 = list(alloc.stack_trace())\n    records = list(reader.get_high_watermark_allocation_records())\n    (alloc,) = records\n    traceback2 = list(alloc.stack_trace())\n\n    assert traceback1 == traceback2\n\n\ndef test_profile_function_is_restored_after_tracking(tmpdir):\n    # GIVEN\n    def profilefunc(*args):\n        pass\n\n    output = Path(tmpdir) / \"test.bin\"\n\n    # WHEN\n\n    sys.setprofile(profilefunc)\n\n    with Tracker(output):\n        assert sys.getprofile() != profilefunc\n\n    # THEN\n    assert sys.getprofile() == profilefunc\n\n\ndef test_initial_tracking_frames_are_correctly_populated(tmpdir):\n    # GIVEN\n    allocator = MemoryAllocator()\n    output = Path(tmpdir) / \"test.bin\"\n\n    def foo():\n        allocator.valloc(1234)\n        allocator.free()\n\n    # WHEN\n\n    with Tracker(output):\n        foo()\n    records = list(FileReader(output).get_allocation_records())\n\n    # THEN\n\n    allocs = [record for record in records if record.allocator == AllocatorType.VALLOC]\n    assert len(allocs) == 1\n    (alloc,) = allocs\n    traceback = [frame[0] for frame in alloc.stack_trace()]\n    assert traceback[-4:] == [\n        \"valloc\",\n        \"foo\",\n        \"test_initial_tracking_frames_are_correctly_populated\",\n    ]\n\n\ndef test_restart_tracing_function_gets_correctly_the_frames(tmpdir):\n    # GIVEN\n    allocator = MemoryAllocator()\n    output = Path(tmpdir) / \"test.bin\"\n\n    def foo():\n        allocator.valloc(1234)\n        allocator.free()\n\n    # WHEN\n\n    # Do some prelininary tracing to populate the initial frames\n    with Tracker(output):\n        foo()\n\n    output.unlink()\n\n    def bar():\n        foo()\n\n    # Do another *independent* round of tracking. The previous frames\n    # should not interfere with this tracing.\n    with Tracker(output):\n        bar()\n    records = list(FileReader(output).get_allocation_records())\n\n    # THEN\n\n    allocs = [record for record in records if record.allocator == AllocatorType.VALLOC]\n    assert len(allocs) == 1\n    (alloc,) = allocs\n    traceback = [frame[0] for frame in alloc.stack_trace()]\n    assert traceback[-5:] == [\n        \"valloc\",\n        \"foo\",\n        \"bar\",\n        \"test_restart_tracing_function_gets_correctly_the_frames\",\n    ]\n\n\ndef test_num_records(tmpdir):\n    # GIVEN\n    allocator = MemoryAllocator()\n    output = Path(tmpdir) / \"test.bin\"\n\n    # WHEN\n\n    with Tracker(output):\n        alloc_func1(allocator)\n        alloc_func1(allocator)\n\n    # THEN\n    reader = FileReader(output)\n    n_records = len(list(reader.get_allocation_records()))\n    assert n_records == reader.metadata.total_allocations\n\n\ndef test_allocations_in_root_frame_have_correct_line_number(tmpdir):\n    # GIVEN\n    output = Path(tmpdir) / \"test.bin\"\n    first = second = None\n\n    # WHEN\n    with Tracker(output):\n        first = mmap.mmap(-1, 1)\n        second = mmap.mmap(-1, 1)\n        del first\n        del second\n\n    # THEN\n    records = list(FileReader(output).get_allocation_records())\n    print(records)\n    allocs = [\n        record\n        for record in records\n        if record.allocator == AllocatorType.MMAP and record.size == 1\n    ]\n\n    assert len(allocs) == 2\n    alloc1, alloc2 = allocs\n    func1, file1, line1 = alloc1.stack_trace()[0]\n    func2, file2, line2 = alloc2.stack_trace()[0]\n    assert func1 == \"test_allocations_in_root_frame_have_correct_line_number\"\n    assert func2 == \"test_allocations_in_root_frame_have_correct_line_number\"\n    assert file1 == __file__\n    assert file2 == __file__\n    assert abs(line1 - line2) == 1\n\n\ndef test_equal_stack_traces_compare_equal(tmpdir):\n    # GIVEN\n    allocator = MemoryAllocator()\n    output = Path(tmpdir) / \"test.bin\"\n\n    # WHEN\n\n    with Tracker(output):\n        for _ in range(2):\n            alloc_func1(allocator)\n            alloc_func2(allocator)\n\n    # THEN\n\n    records = list(FileReader(output).get_allocation_records())\n    allocs = [record for record in records if record.allocator == AllocatorType.VALLOC]\n\n    assert len(allocs) == 4\n    first_alloc1, first_alloc2, second_alloc1, second_alloc2 = allocs\n\n    assert first_alloc1.stack_id == second_alloc1.stack_id\n    assert first_alloc1.stack_trace() == second_alloc1.stack_trace()\n    assert first_alloc2.stack_id == second_alloc2.stack_id\n    assert first_alloc2.stack_trace() == second_alloc2.stack_trace()\n\n    assert first_alloc1.stack_id != first_alloc2.stack_id\n    assert second_alloc1.stack_id != second_alloc2.stack_id\n\n\ndef test_identical_stack_traces_started_in_different_lines_in_the_root_do_not_compare_equal(\n    tmpdir,\n):  # GIVEN\n    allocator = MemoryAllocator()\n    output = Path(tmpdir) / \"test.bin\"\n\n    # WHEN\n\n    with Tracker(output):\n        alloc_func1(allocator)\n        alloc_func2(allocator)\n        alloc_func1(allocator)\n        alloc_func2(allocator)\n\n    # THEN\n\n    records = list(FileReader(output).get_allocation_records())\n    allocs = [record for record in records if record.allocator == AllocatorType.VALLOC]\n\n    assert len(allocs) == 4\n    first_alloc1, first_alloc2, second_alloc1, second_alloc2 = allocs\n\n    assert first_alloc1.stack_id != second_alloc1.stack_id\n    assert first_alloc1.stack_trace()[:-1] == second_alloc1.stack_trace()[:-1]\n    assert first_alloc1.stack_trace()[-1] != second_alloc1.stack_trace()[-1]\n    assert first_alloc2.stack_id != second_alloc2.stack_id\n    assert first_alloc2.stack_trace()[:-1] == second_alloc2.stack_trace()[:-1]\n    assert first_alloc2.stack_trace()[-1] != second_alloc2.stack_trace()[-1]\n\n    assert first_alloc1.stack_id != first_alloc2.stack_id\n    assert second_alloc1.stack_id != second_alloc2.stack_id\n\n\ndef test_identical_stack_traces_started_in_different_lines_in_a_function_do_not_compare_equal(\n    tmpdir,\n):\n    # GIVEN\n    allocator = MemoryAllocator()\n    output = Path(tmpdir) / \"test.bin\"\n\n    # WHEN\n\n    def foo():\n        alloc_func1(allocator)\n        alloc_func2(allocator)\n        alloc_func1(allocator)\n        alloc_func2(allocator)\n\n    with Tracker(output):\n        foo()\n\n    # THEN\n\n    records = list(FileReader(output).get_allocation_records())\n    allocs = [record for record in records if record.allocator == AllocatorType.VALLOC]\n\n    assert len(allocs) == 4\n    first_alloc1, first_alloc2, second_alloc1, second_alloc2 = allocs\n\n    assert first_alloc1.stack_id != second_alloc1.stack_id\n    assert first_alloc1.stack_trace() != second_alloc1.stack_trace()\n    assert first_alloc2.stack_id != second_alloc2.stack_id\n    assert first_alloc2.stack_trace() != second_alloc2.stack_trace()\n\n    assert first_alloc1.stack_id != first_alloc2.stack_id\n    assert second_alloc1.stack_id != second_alloc2.stack_id\n\n\ndef test_allocation_in_thread_started_before_tracking_starts(tmp_path):\n    \"\"\"Test capturing the stack of a thread started before tracking started.\n\n    The intended execution flow is:\n    Main Thread          Background Thread\n    -----------          -----------------\n    Start thread\n                         Call thread_body\n    Install tracker\n                         Call func1\n                         Perform an allocation\n                         Exit\n    Join thread\n    Uninstall tracker\n    \"\"\"\n    # GIVEN\n    thread_body_entered = threading.Event()\n    tracker_installed = threading.Event()\n    allocator = MemoryAllocator()\n    output = tmp_path / \"test.bin\"\n\n    def thread_body():\n        thread_body_entered.set()\n        tracker_installed.wait()\n        func1()\n\n    def func1():\n        allocator.valloc(1234)\n        allocator.free()\n\n    # WHEN\n    bg_thread = threading.Thread(target=thread_body)\n    bg_thread.start()\n\n    thread_body_entered.wait()\n    with Tracker(output):\n        tracker_installed.set()\n        bg_thread.join()\n\n    # THEN\n    allocations = list(FileReader(output).get_allocation_records())\n\n    vallocs = [\n        event\n        for event in allocations\n        if event.size == 1234 and event.allocator == AllocatorType.VALLOC\n    ]\n    assert len(vallocs) == 1\n\n    funcs = [frame[0] for frame in vallocs[0].stack_trace()]\n    assert funcs == [\n        \"valloc\",\n        \"func1\",\n        \"thread_body\",\n        \"run\",\n        \"_bootstrap_inner\",\n        \"_bootstrap\",\n    ]\n\n\ndef test_allocation_in_thread_before_reacquiring_gil_after_tracking_starts(tmp_path):\n    \"\"\"\n    The intended execution flow is:\n    Main Thread          Background Thread\n    -----------          -----------------\n    Start thread\n                         Call allocate_without_gil_held\n                         release GIL\n    Install tracker\n                         Perform an allocation for 1234 bytes\n                         acquire GIL\n                         Perform an allocation for 4321 bytes\n                         Exit\n    Join thread\n    Uninstall tracker\n    \"\"\"\n    # GIVEN\n    wake_up_main_r, wake_up_main_w = os.pipe()\n    wake_up_thread_r, wake_up_thread_w = os.pipe()\n    output = tmp_path / \"test.bin\"\n\n    def thread_body():\n        allocate_without_gil_held(wake_up_main_w, wake_up_thread_r)\n\n    # WHEN\n    bg_thread = threading.Thread(target=thread_body)\n    bg_thread.start()\n\n    os.read(wake_up_main_r, 1)\n    with Tracker(output):\n        os.write(wake_up_thread_w, b\"x\")\n        bg_thread.join()\n\n    # THEN\n    allocations = list(FileReader(output).get_allocation_records())\n\n    vallocs = [\n        event for event in allocations if event.allocator == AllocatorType.VALLOC\n    ]\n    assert len(vallocs) == 2\n\n    funcs1 = [frame[0] for frame in vallocs[0].stack_trace()]\n    funcs2 = [frame[0] for frame in vallocs[1].stack_trace()]\n    expected = [\"thread_body\", \"run\", \"_bootstrap_inner\", \"_bootstrap\"]\n    assert funcs1 == funcs2 == expected\n\n\ndef test_thread_surviving_multiple_trackers(tmp_path):\n    # GIVEN\n    orig_tracker_used = threading.Event()\n    new_tracker_installed = threading.Event()\n    allocator = MemoryAllocator()\n    output1 = tmp_path / \"test.bin.1\"\n    output2 = tmp_path / \"test.bin.2\"\n\n    def deeper_function():\n        allocator.valloc(1234)\n        allocator.free()\n        orig_tracker_used.set()\n        new_tracker_installed.wait()\n        allocator.valloc(1234)\n        allocator.free()\n\n    def tracking_function():\n        deeper_function()\n\n    # WHEN\n    with Tracker(output1):\n        bg_thread = threading.Thread(target=tracking_function)\n        bg_thread.start()\n        orig_tracker_used.wait()\n\n    with Tracker(output2):\n        new_tracker_installed.set()\n        bg_thread.join()\n\n    # THEN\n    tracker1_allocations = list(FileReader(output1).get_allocation_records())\n    tracker2_allocations = list(FileReader(output2).get_allocation_records())\n\n    tracker1_vallocs = [\n        event\n        for event in tracker1_allocations\n        if event.size == 1234 and event.allocator == AllocatorType.VALLOC\n    ]\n    tracker2_vallocs = [\n        event\n        for event in tracker2_allocations\n        if event.size == 1234 and event.allocator == AllocatorType.VALLOC\n    ]\n    assert len(tracker1_vallocs) == len(tracker2_vallocs) == 1\n    assert tracker1_vallocs[0].stack_trace() != tracker2_vallocs[0].stack_trace()\n\n\ndef test_thread_surviving_multiple_trackers_with_changing_callstack(tmp_path):\n    \"\"\"Test the call stack of a thread changing between two tracking sessions.\n\n    The intended execution flow is:\n    Main Thread          Background Thread\n    -----------          -----------------\n    Install tracker\n    Start thread\n                         Call thread_body\n                         Call func1\n                         Perform an allocation\n    Uninstall tracker\n                         Return from func1\n    Install new tracker\n                         Call func2\n                         Perform an allocation\n                         Return from func2\n                         Return from thread_body\n    Uninstall tracker\n\n    We use a bunch of events to force this order.\n    \"\"\"\n    # GIVEN\n    allocation_performed_in_func1 = threading.Event()\n    tracker_uninstalled = threading.Event()\n    returned_from_func1 = threading.Event()\n    new_tracker_installed = threading.Event()\n\n    allocator = MemoryAllocator()\n    output1 = tmp_path / \"test.bin.1\"\n    output2 = tmp_path / \"test.bin.2\"\n\n    def thread_body():\n        func1()\n        returned_from_func1.set()\n        new_tracker_installed.wait()\n        func2()\n\n    def func1():\n        allocator.valloc(1234)\n        allocator.free()\n        allocation_performed_in_func1.set()\n        tracker_uninstalled.wait()\n\n    def func2():\n        allocator.valloc(1234)\n        allocator.free()\n\n    # WHEN\n    with Tracker(output1):\n        bg_thread = threading.Thread(target=thread_body)\n        bg_thread.start()\n        allocation_performed_in_func1.wait()\n\n    tracker_uninstalled.set()\n    returned_from_func1.wait()\n\n    with Tracker(output2):\n        new_tracker_installed.set()\n        bg_thread.join()\n\n    # THEN\n    tracker1_allocations = list(FileReader(output1).get_allocation_records())\n    tracker2_allocations = list(FileReader(output2).get_allocation_records())\n\n    tracker1_vallocs = [\n        event\n        for event in tracker1_allocations\n        if event.size == 1234 and event.allocator == AllocatorType.VALLOC\n    ]\n    tracker2_vallocs = [\n        event\n        for event in tracker2_allocations\n        if event.size == 1234 and event.allocator == AllocatorType.VALLOC\n    ]\n    assert len(tracker1_vallocs) == len(tracker2_vallocs) == 1\n\n    tracker1_funcs = [frame[0] for frame in tracker1_vallocs[0].stack_trace()]\n    tracker2_funcs = [frame[0] for frame in tracker2_vallocs[0].stack_trace()]\n\n    common_frames = [\"thread_body\", \"run\", \"_bootstrap_inner\", \"_bootstrap\"]\n    assert tracker1_funcs == [\"valloc\", \"func1\"] + common_frames\n    assert tracker2_funcs == [\"valloc\", \"func2\"] + common_frames\n\n\ndef test_cython_frame_in_pre_existing_thread_stack(tmp_path):\n    \"\"\"Test starting tracking when another thread's stack has Cython frames.\n\n    The intended execution flow is:\n    Main Thread          Background Thread\n    -----------          -----------------\n    Start thread\n                         Call thread_body\n                         Call function_caller (Cython frame)\n                         Call func1\n    Install new tracker\n                         Perform an allocation\n                         Return from func1\n                         Return from function_caller\n                         Perform an allocation\n                         Return from thread_body\n    Join thread\n    Uninstall tracker\n    \"\"\"\n    # GIVEN\n    ready_to_install_tracker = threading.Event()\n    tracker_installed = threading.Event()\n\n    allocator = MemoryAllocator()\n    output = tmp_path / \"test.bin\"\n\n    def thread_body():\n        function_caller(func1)\n        allocator.valloc(1234)\n        allocator.free()\n\n    def func1():\n        ready_to_install_tracker.set()\n        tracker_installed.wait()\n        allocator.valloc(1234)\n        allocator.free()\n\n    # WHEN\n    thread = threading.Thread(target=thread_body)\n    thread.start()\n    ready_to_install_tracker.wait()\n\n    with Tracker(output):\n        tracker_installed.set()\n        thread.join()\n\n    # THEN\n    allocations = list(FileReader(output).get_allocation_records())\n\n    vallocs = [\n        event\n        for event in allocations\n        if event.size == 1234 and event.allocator == AllocatorType.VALLOC\n    ]\n    assert len(vallocs) == 2\n\n    first, second = vallocs\n    alloc1_funcs = [frame[0] for frame in first.stack_trace()]\n    alloc2_funcs = [frame[0] for frame in second.stack_trace()]\n\n    # Cython frames called before tracking started aren't in the Python stack.\n    assert alloc1_funcs[:3] == [\"valloc\", \"func1\", \"thread_body\"]\n    assert alloc2_funcs[:2] == [\"valloc\", \"thread_body\"]\n\n\ndef test_cython_frame_in_pre_existing_thread_stack_when_restarting_tracking(tmp_path):\n    \"\"\"Test restarting tracking when another thread's stack has Cython frames.\n\n    The intended execution flow is:\n    Main Thread          Background Thread\n    -----------          -----------------\n    Install tracker\n    Start thread\n                         Call thread_body\n                         Call function_caller (Cython frame)\n                         Call func1\n    Uninstall tracker\n    Install new tracker\n                         Perform an allocation\n                         Return from func1\n                         Return from function_caller\n                         Perform an allocation\n                         Return from thread_body\n    Join thread\n    Uninstall tracker\n    \"\"\"\n    # GIVEN\n    ready_to_replace_tracker = threading.Event()\n    tracker_replaced = threading.Event()\n\n    allocator = MemoryAllocator()\n    output1 = tmp_path / \"test.bin.1\"\n    output2 = tmp_path / \"test.bin.2\"\n\n    def thread_body():\n        function_caller(func1)\n        allocator.valloc(1234)\n        allocator.free()\n\n    def func1():\n        ready_to_replace_tracker.set()\n        tracker_replaced.wait()\n        allocator.valloc(1234)\n        allocator.free()\n\n    # WHEN\n    with Tracker(output1):\n        thread = threading.Thread(target=thread_body)\n        thread.start()\n        ready_to_replace_tracker.wait()\n\n    with Tracker(output2):\n        tracker_replaced.set()\n        thread.join()\n\n    # THEN\n    allocations = list(FileReader(output2).get_allocation_records())\n\n    vallocs = [\n        event\n        for event in allocations\n        if event.size == 1234 and event.allocator == AllocatorType.VALLOC\n    ]\n    assert len(vallocs) == 2\n\n    first, second = vallocs\n    alloc1_funcs = [frame[0] for frame in first.stack_trace()]\n    alloc2_funcs = [frame[0] for frame in second.stack_trace()]\n\n    # Cython frames called before tracking started aren't in the Python stack.\n    assert alloc1_funcs[:3] == [\"valloc\", \"func1\", \"thread_body\"]\n\n    # But we do get pop events for them if tracking was enabled when they were\n    # pushed. Ensure we handle these unexpected pops.\n    assert alloc2_funcs[:2] == [\"valloc\", \"thread_body\"]\n\n\ndef test_allocation_after_unsetting_profile_function(tmp_path):\n    \"\"\"After tracking starts, unset the profile function then allocate.\n\n    Make sure that the stack for the allocation is unknown.\n    \"\"\"\n    # GIVEN\n    allocator = MemoryAllocator()\n    output = tmp_path / \"test.bin\"\n\n    def func():\n        allocator.valloc(1234)\n        allocator.free()\n        sys.setprofile(None)\n        allocator.valloc(1234)\n        allocator.free()\n\n    # WHEN\n    with Tracker(output):\n        func()\n\n    # THEN\n    allocations = list(FileReader(output).get_allocation_records())\n\n    vallocs = [\n        event\n        for event in allocations\n        if event.size == 1234 and event.allocator == AllocatorType.VALLOC\n    ]\n    assert len(vallocs) == 2\n\n    first, second = vallocs\n    alloc1_funcs = [frame[0] for frame in first.stack_trace()]\n    alloc2_funcs = [frame[0] for frame in second.stack_trace()]\n\n    assert alloc1_funcs == [\n        \"valloc\",\n        \"func\",\n        \"test_allocation_after_unsetting_profile_function\",\n    ]\n    assert alloc2_funcs == []\n\n\ndef test_allocation_in_thread_after_unsetting_profile_function(tmp_path):\n    \"\"\"In a thread, unset the profile function then allocate.\n\n    Make sure that the stack for the allocation is unknown.\n    \"\"\"\n    # GIVEN\n    allocator = MemoryAllocator()\n    output = tmp_path / \"test.bin\"\n\n    def func():\n        allocator.valloc(1234)\n        allocator.free()\n        sys.setprofile(None)\n        allocator.valloc(1234)\n        allocator.free()\n\n    # WHEN\n    with Tracker(output):\n        thread = threading.Thread(target=func)\n        thread.start()\n        thread.join()\n\n    # THEN\n    allocations = list(FileReader(output).get_allocation_records())\n\n    vallocs = [\n        event\n        for event in allocations\n        if event.size == 1234 and event.allocator == AllocatorType.VALLOC\n    ]\n    assert len(vallocs) == 2\n\n    first, second = vallocs\n    alloc1_funcs = [frame[0] for frame in first.stack_trace()]\n    alloc2_funcs = [frame[0] for frame in second.stack_trace()]\n\n    assert alloc1_funcs[:2] == [\"valloc\", \"func\"]\n    assert alloc2_funcs == []\n\n\nclass TestMmap:\n    @classmethod\n    def allocating_function(cls):\n        with mmap.mmap(-1, length=2048, access=mmap.ACCESS_WRITE) as mmap_obj:\n            mmap_obj[0:100] = b\"a\" * 100\n\n    @pytest.mark.valgrind\n    def test_mmap(self, tmpdir):\n        # GIVEN / WHEN\n        output = Path(tmpdir) / \"test.bin\"\n        with Tracker(output):\n            TestMmap.allocating_function()\n\n        # THEN\n        records = list(FileReader(output).get_allocation_records())\n\n        assert len(records) >= 2\n\n        mmap_record = next(\n            (record for record in records if AllocatorType.MMAP == record.allocator),\n            None,\n        )\n        assert mmap_record is not None\n        assert \"allocating_function\" in {\n            element[0] for element in mmap_record.stack_trace()\n        }\n\n        munmap_record = next(\n            (record for record in records if AllocatorType.MUNMAP == record.allocator),\n            None,\n        )\n        assert munmap_record is not None\n        with pytest.raises(NotImplementedError):\n            munmap_record.stack_trace()\n\n    @pytest.mark.valgrind\n    def test_mmap_in_thread(self, tmpdir):\n        # GIVEN / WHEN\n        output = Path(tmpdir) / \"test.bin\"\n\n        def custom_trace_fn():  # pragma: no cover\n            pass\n\n        try:\n            threading.setprofile(custom_trace_fn)\n            t = threading.Thread(target=TestMmap.allocating_function)\n            with Tracker(output):\n                t.start()\n                t.join()\n        finally:\n            profile_hook = threading._profile_hook\n            threading.setprofile(None)\n\n        # THEN\n        assert threading._profile_hook is None\n        assert profile_hook == custom_trace_fn\n        records = list(FileReader(output).get_allocation_records())\n\n        assert len(records) >= 2\n\n        mmap_record = next(\n            (\n                record\n                for record in records\n                if AllocatorType.MMAP == record.allocator and record.size == 2048\n            ),\n            None,\n        )\n        assert mmap_record is not None\n        assert \"allocating_function\" in {\n            element[0] for element in mmap_record.stack_trace()\n        }\n\n        munmap_record = next(\n            (record for record in records if AllocatorType.MUNMAP == record.allocator),\n            None,\n        )\n        assert munmap_record is not None\n        with pytest.raises(NotImplementedError):\n            munmap_record.stack_trace()\n"
  },
  {
    "path": "tests/integration/test_tracking.py",
    "content": "import collections\nimport datetime\nimport mmap\nimport os\nimport signal\nimport subprocess\nimport sys\nimport textwrap\nimport threading\nimport time\nfrom pathlib import Path\n\nimport pytest\n\nfrom memray import AllocatorType\nfrom memray import FileFormat\nfrom memray import FileReader\nfrom memray import Tracker\nfrom memray._memray import compute_statistics\nfrom memray._test import MemoryAllocator\nfrom memray._test import MmapAllocator\nfrom memray._test import PrimeCaches\nfrom memray._test import PymallocDomain\nfrom memray._test import PymallocMemoryAllocator\nfrom memray._test import _cython_allocate_in_two_places\nfrom memray._test import allocate_cpp_vector\nfrom memray._test import fill_cpp_vector\nfrom tests.utils import filter_relevant_allocations\nfrom tests.utils import run_without_tracer\n\nALLOCATORS = [\n    (\"malloc\", AllocatorType.MALLOC),\n    (\"valloc\", AllocatorType.VALLOC),\n    (\"pvalloc\", AllocatorType.PVALLOC),\n    (\"calloc\", AllocatorType.CALLOC),\n    (\"memalign\", AllocatorType.MEMALIGN),\n    (\"posix_memalign\", AllocatorType.POSIX_MEMALIGN),\n    (\"aligned_alloc\", AllocatorType.ALIGNED_ALLOC),\n    (\"realloc\", AllocatorType.REALLOC),\n]\n\nPYMALLOC_ALLOCATORS = [\n    (\"malloc\", AllocatorType.PYMALLOC_MALLOC),\n    (\"calloc\", AllocatorType.PYMALLOC_CALLOC),\n    (\"realloc\", AllocatorType.PYMALLOC_REALLOC),\n]\n\nPYMALLOC_DOMAINS = [\n    PymallocDomain.PYMALLOC_RAW,\n    PymallocDomain.PYMALLOC_MEM,\n    PymallocDomain.PYMALLOC_OBJECT,\n]\n\n\nPAGE_SIZE = mmap.PAGESIZE\nALLOC_SIZE = 123 * 8\n\n\n@pytest.mark.skipif(\n    sys.platform == \"darwin\", reason=\"Test triggers some extra allocations in macOS\"\n)\ndef test_no_allocations_while_tracking(tmp_path):\n    output = tmp_path / \"test.bin\"\n    with Tracker(output):\n        pass\n\n    records = list(FileReader(output).get_allocation_records())\n    assert not records\n\n\n@pytest.mark.parametrize([\"allocator_func\", \"allocator_type\"], ALLOCATORS)\ndef test_simple_allocation_tracking(allocator_func, allocator_type, tmp_path):\n    # GIVEN\n    allocator = MemoryAllocator()\n    output = tmp_path / \"test.bin\"\n\n    # WHEN\n    with Tracker(output):\n        res = getattr(allocator, allocator_func)(ALLOC_SIZE)\n        if res:\n            allocator.free()\n\n    if not res:\n        pytest.skip(f\"Allocator {allocator_func} not supported in this platform\")\n\n    # THEN\n    allocations = list(FileReader(output).get_allocation_records())\n    allocs = [\n        event\n        for event in allocations\n        if event.size == ALLOC_SIZE and event.allocator == allocator_type\n    ]\n    assert len(allocs) == 1\n    (alloc,) = allocs\n\n    frees = [\n        event\n        for event in allocations\n        if event.address == alloc.address and event.allocator == AllocatorType.FREE\n    ]\n    assert len(frees) >= 1\n\n\ndef test_simple_cpp_allocation_tracking(tmp_path):\n    # GIVEN\n    output = tmp_path / \"test.bin\"\n\n    # WHEN\n    with Tracker(output):\n        allocate_cpp_vector(ALLOC_SIZE)\n\n    # THEN\n    allocations = list(FileReader(output).get_allocation_records())\n    allocs = [event for event in allocations if event.size == ALLOC_SIZE]\n    assert len(allocs) == 1\n    (alloc,) = allocs\n\n    frees = [\n        event\n        for event in allocations\n        if event.address == alloc.address and event.allocator == AllocatorType.FREE\n    ]\n    assert len(frees) >= 1\n\n\n@pytest.mark.parametrize(\"domain\", PYMALLOC_DOMAINS)\n@pytest.mark.parametrize([\"allocator_func\", \"allocator_type\"], PYMALLOC_ALLOCATORS)\ndef test_simple_pymalloc_allocation_tracking(\n    allocator_func, allocator_type, domain, tmp_path\n):\n    # GIVEN\n    allocator = PymallocMemoryAllocator(domain)\n    output = tmp_path / \"test.bin\"\n\n    # WHEN\n    the_allocator = getattr(allocator, allocator_func)\n    with Tracker(output, trace_python_allocators=True):\n        res = the_allocator(ALLOC_SIZE)\n        if res:\n            allocator.free()\n\n    if not res:\n        pytest.skip(f\"Allocator {allocator_func} not supported in this platform\")\n\n    # THEN\n    allocations = list(FileReader(output).get_allocation_records())\n    allocs = [\n        event\n        for event in allocations\n        if event.size == ALLOC_SIZE and event.allocator == allocator_type\n    ]\n    assert len(allocs) == 1\n    (alloc,) = allocs\n\n    frees = [\n        event\n        for event in allocations\n        if event.address == alloc.address\n        and event.allocator == AllocatorType.PYMALLOC_FREE\n    ]\n    assert len(frees) >= 1\n\n\n@pytest.mark.parametrize(\"domain\", PYMALLOC_DOMAINS)\n@pytest.mark.parametrize([\"allocator_func\", \"allocator_type\"], PYMALLOC_ALLOCATORS)\ndef test_pymalloc_allocation_tracking_deactivated(\n    allocator_func, allocator_type, domain, tmp_path\n):\n    # GIVEN\n    allocator = PymallocMemoryAllocator(domain)\n    output = tmp_path / \"test.bin\"\n\n    # WHEN\n    the_allocator = getattr(allocator, allocator_func)\n    with Tracker(output, trace_python_allocators=False):\n        res = the_allocator(ALLOC_SIZE)\n        if res:\n            allocator.free()\n\n    if not res:\n        pytest.skip(f\"Allocator {allocator_func} not supported in this platform\")\n\n    # THEN\n    allocations = list(FileReader(output).get_allocation_records())\n    allocs = [event for event in allocations if event.allocator == allocator_type]\n    assert not allocs\n    frees = [\n        event for event in allocations if event.allocator == AllocatorType.PYMALLOC_FREE\n    ]\n    assert not frees\n\n\ndef test_mmap_tracking(tmp_path):\n    # GIVEN / WHEN\n    output = tmp_path / \"test.bin\"\n    with Tracker(output):\n        with mmap.mmap(-1, length=2048, access=mmap.ACCESS_WRITE) as mmap_obj:\n            mmap_obj[0:100] = b\"a\" * 100\n\n    # THEN\n    records = list(FileReader(output).get_allocation_records())\n    assert len(records) >= 2\n\n    mmap_records = [\n        record\n        for record in records\n        if AllocatorType.MMAP == record.allocator and record.size == 2048\n    ]\n    assert len(mmap_records) == 1\n    mmunmap_record = [\n        record for record in records if AllocatorType.MUNMAP == record.allocator\n    ]\n    assert len(mmunmap_record) == 1\n\n\ndef test_pthread_tracking(tmp_path):\n    # GIVEN\n    allocator = MemoryAllocator()\n\n    def tracking_function():  # pragma: no cover\n        allocator.valloc(ALLOC_SIZE)\n        allocator.free()\n\n    # WHEN\n    output = tmp_path / \"test.bin\"\n    with Tracker(output):\n        allocator.run_in_pthread(tracking_function)\n\n    # THEN\n    allocations = list(FileReader(output).get_allocation_records())\n    allocs = [\n        event\n        for event in allocations\n        if event.size == ALLOC_SIZE and event.allocator == AllocatorType.VALLOC\n    ]\n    assert len(allocs) == 1\n    (alloc,) = allocs\n\n    frees = [\n        event\n        for event in allocations\n        if event.address == alloc.address and event.allocator == AllocatorType.FREE\n    ]\n    assert len(frees) >= 1\n\n\ndef test_tracking_with_SIGKILL(tmpdir):\n    \"\"\"Verify that we can successfully retrieve the allocations after SIGKILL.\"\"\"\n    # GIVEN\n    output = Path(tmpdir) / \"test.bin\"\n    subprocess_code = textwrap.dedent(\n        f\"\"\"\n        import os\n        import signal\n        from memray import Tracker\n        from memray._test import MemoryAllocator\n\n        allocator = MemoryAllocator()\n        output = \"{output}\"\n\n        with Tracker(output) as tracker:\n            num_flushes = 0\n            last_size = os.stat(output).st_size\n\n            # Loop until two flushes occur, since the first flush might include\n            # a frame record but not an allocation record.\n            while num_flushes < 2:\n                allocator.valloc(1024)\n                new_size = os.stat(output).st_size\n                if new_size != last_size:\n                    last_size = new_size\n                    num_flushes += 1\n\n            # Kill ourselves without letting the tracker clean itself up.\n            os.kill(os.getpid(), signal.SIGKILL)\n    \"\"\"\n    )\n\n    # WHEN\n    process = subprocess.run([sys.executable, \"-c\", subprocess_code], timeout=5)\n\n    # THEN\n    assert process.returncode == -signal.SIGKILL\n\n    records = list(FileReader(output).get_allocation_records())\n    vallocs = [\n        record\n        for record in filter_relevant_allocations(records)\n        if record.allocator == AllocatorType.VALLOC\n    ]\n    (allocation, *rest) = vallocs\n    assert allocation.size == 1024\n\n\ndef test_no_allocations(tmpdir):\n    \"\"\"Verify that we can successfully read a file that has no allocations.\"\"\"\n    # GIVEN\n    output = Path(tmpdir) / \"test.bin\"\n    subprocess_code = textwrap.dedent(\n        f\"\"\"\n        import os\n        from memray import Tracker\n        output = \"{output}\"\n        tracker = Tracker(output)\n        with tracker:\n            os._exit(0)\n    \"\"\"\n    )\n\n    # WHEN\n    process = subprocess.run([sys.executable, \"-c\", subprocess_code], timeout=5)\n\n    # THEN\n    assert process.returncode == 0\n\n    records = list(FileReader(output).get_allocation_records())\n    assert not records\n\n\ndef test_unsupported_operations_on_aggregated_capture(tmpdir):\n    \"\"\"Verify that we can successfully read a file that has no allocations.\"\"\"\n    # GIVEN\n    output = Path(tmpdir) / \"test.bin\"\n    subprocess_code = textwrap.dedent(\n        f\"\"\"\n        import os\n        from memray import Tracker, FileFormat\n        output = \"{output}\"\n        tracker = Tracker(output, file_format=FileFormat.AGGREGATED_ALLOCATIONS)\n        with tracker:\n            pass\n        \"\"\"\n    )\n    process = subprocess.run([sys.executable, \"-c\", subprocess_code], timeout=5)\n    assert process.returncode == 0\n    reader = FileReader(output)\n\n    # WHEN / THEN\n    with pytest.raises(\n        NotImplementedError,\n        match=\"Can't find temporary allocations using a pre-aggregated capture file\",\n    ):\n        list(reader.get_temporary_allocation_records())\n\n    with pytest.raises(\n        NotImplementedError,\n        match=\"Can't get all allocations from a pre-aggregated capture file\",\n    ):\n        list(reader.get_allocation_records())\n\n    with pytest.raises(\n        NotImplementedError,\n        match=\"Can't compute statistics using a pre-aggregated capture file\",\n    ):\n        compute_statistics(str(output))\n\n\n@pytest.mark.parametrize(\n    \"file_format\",\n    [\n        pytest.param(FileFormat.ALL_ALLOCATIONS, id=\"ALL_ALLOCATIONS\"),\n        pytest.param(FileFormat.AGGREGATED_ALLOCATIONS, id=\"AGGREGATED_ALLOCATIONS\"),\n    ],\n)\nclass TestHighWatermark:\n    def test_no_allocations_while_tracking(self, tmp_path, file_format):\n        # GIVEN\n        output = tmp_path / \"test.bin\"\n\n        def tracking_function():\n            pass\n\n        with PrimeCaches():\n            tracking_function()\n\n        # WHEN\n        with Tracker(output, native_traces=True, file_format=file_format):\n            tracking_function()\n\n        # THEN\n        assert list(FileReader(output).get_high_watermark_allocation_records()) == []\n\n    @pytest.mark.parametrize([\"allocator_func\", \"allocator_type\"], ALLOCATORS)\n    def test_simple_allocation_tracking(\n        self, tmp_path, allocator_func, allocator_type, file_format\n    ):\n        # GIVEN\n        allocator = MemoryAllocator()\n        output = tmp_path / \"test.bin\"\n\n        # WHEN\n        with Tracker(output, file_format=file_format):\n            res = getattr(allocator, allocator_func)(ALLOC_SIZE)\n            if res:\n                allocator.free()\n\n        if not res:\n            pytest.skip(f\"Allocator {allocator_func} not supported in this platform\")\n\n        # THEN\n        peak_allocations_unfiltered = FileReader(\n            output\n        ).get_high_watermark_allocation_records()\n        peak_allocations = [\n            record\n            for record in peak_allocations_unfiltered\n            if record.size == ALLOC_SIZE\n        ]\n        assert len(peak_allocations) == 1, peak_allocations\n\n        record = peak_allocations[0]\n        assert record.allocator == allocator_type\n        assert record.n_allocations == 1\n\n    def test_multiple_high_watermark(self, tmp_path, file_format):\n        # GIVEN\n        allocator = MemoryAllocator()\n        output = tmp_path / \"test.bin\"\n\n        def test_function():\n            for _ in range(2):\n                allocator.valloc(1024)\n                allocator.free()\n\n        with PrimeCaches():\n            test_function()\n\n        # WHEN\n        with Tracker(output, file_format=file_format):\n            test_function()\n\n        # THEN\n        reader = FileReader(output)\n\n        if file_format == FileFormat.ALL_ALLOCATIONS:\n            all_allocations = list(\n                filter_relevant_allocations(reader.get_allocation_records())\n            )\n            assert len(all_allocations) == 4\n\n        peak_allocations = list(\n            filter_relevant_allocations(reader.get_high_watermark_allocation_records())\n        )\n        assert len(peak_allocations) == 1\n        record = peak_allocations[0]\n\n        assert record.allocator == AllocatorType.VALLOC\n        assert record.size == 1024\n        assert record.n_allocations == 1\n\n    def test_freed_before_high_watermark_do_not_appear(self, tmp_path, file_format):\n        # GIVEN\n        allocator1 = MemoryAllocator()\n        allocator2 = MemoryAllocator()\n        output = tmp_path / \"test.bin\"\n\n        def test_function():\n            allocator1.valloc(1024)\n            allocator1.free()\n            allocator2.valloc(2048)\n            allocator2.free()\n\n        with PrimeCaches():\n            test_function()\n\n        # WHEN\n        with Tracker(output, file_format=file_format):\n            test_function()\n\n        # THEN\n        reader = FileReader(output)\n\n        if file_format == FileFormat.ALL_ALLOCATIONS:\n            all_allocations = list(\n                filter_relevant_allocations(reader.get_allocation_records())\n            )\n            assert len(all_allocations) == 4\n\n        peak_allocations = list(\n            filter_relevant_allocations(reader.get_high_watermark_allocation_records())\n        )\n        assert len(peak_allocations) == 1\n\n        record = peak_allocations[0]\n        assert record.allocator == AllocatorType.VALLOC\n        assert record.size == 2048\n        assert record.n_allocations == 1\n\n    def test_freed_after_high_watermark_do_not_appear(self, tmp_path, file_format):\n        # GIVEN\n        allocator1 = MemoryAllocator()\n        allocator2 = MemoryAllocator()\n        output = tmp_path / \"test.bin\"\n\n        def test_function():\n            allocator2.valloc(2048)\n            allocator2.free()\n            allocator1.valloc(1024)\n            allocator1.free()\n\n        with PrimeCaches():\n            test_function()\n\n        # WHEN\n        with Tracker(output, file_format=file_format):\n            test_function()\n\n        # THEN\n        reader = FileReader(output)\n\n        if file_format == FileFormat.ALL_ALLOCATIONS:\n            all_allocations = list(\n                filter_relevant_allocations(reader.get_allocation_records())\n            )\n            assert len(all_allocations) == 4\n\n        peak_allocations = list(\n            filter_relevant_allocations(reader.get_high_watermark_allocation_records())\n        )\n        assert len(peak_allocations) == 1\n\n        record = peak_allocations[0]\n        assert record.allocator == AllocatorType.VALLOC\n        assert record.size == 2048\n        assert record.n_allocations == 1\n\n    def test_allocations_aggregation_on_same_line(self, tmp_path, file_format):\n        # GIVEN\n        allocators = []\n        output = tmp_path / \"test.bin\"\n\n        # WHEN\n        with Tracker(output, file_format=file_format):\n            for _ in range(2):\n                allocator = MemoryAllocator()\n                allocators.append(allocator)\n\n                allocator.valloc(1024)\n\n            for allocator in allocators:\n                allocator.free()\n\n        # THEN\n        reader = FileReader(output)\n\n        if file_format == FileFormat.ALL_ALLOCATIONS:\n            all_allocations = list(\n                filter_relevant_allocations(reader.get_allocation_records())\n            )\n            assert len(all_allocations) == 4\n\n        peak_allocations = list(\n            filter_relevant_allocations(reader.get_high_watermark_allocation_records())\n        )\n        assert len(peak_allocations) == 1\n\n        record = peak_allocations[0]\n        assert record.allocator == AllocatorType.VALLOC\n        assert record.size == 2048\n        assert record.n_allocations == 2\n\n    def test_aggregation_same_python_stack_and_same_native_stack(\n        self, tmp_path, file_format\n    ):\n        # GIVEN\n        allocators = []\n        output = tmp_path / \"test.bin\"\n\n        # WHEN\n        with Tracker(output, native_traces=True, file_format=file_format):\n            for _ in range(2):\n                allocator = MemoryAllocator()\n                allocators.append(allocator)\n\n                allocator.valloc(1024)\n\n            for allocator in allocators:\n                allocator.free()\n\n        # THEN\n        reader = FileReader(output)\n\n        if file_format == FileFormat.ALL_ALLOCATIONS:\n            all_allocations = list(\n                filter_relevant_allocations(reader.get_allocation_records())\n            )\n            assert len(all_allocations) == 4\n\n        peak_allocations = list(\n            filter_relevant_allocations(reader.get_high_watermark_allocation_records())\n        )\n        assert len(peak_allocations) == 1\n\n        record = peak_allocations[0]\n        assert record.allocator == AllocatorType.VALLOC\n        assert record.size == 2048\n        assert record.n_allocations == 2\n\n    def test_allocations_aggregation_on_different_lines(self, tmp_path, file_format):\n        # GIVEN\n        allocator1 = MemoryAllocator()\n        allocator2 = MemoryAllocator()\n        output = tmp_path / \"test.bin\"\n\n        # WHEN\n        with Tracker(output, file_format=file_format):\n            allocator1.valloc(1024)\n            allocator2.valloc(2048)\n            allocator1.free()\n            allocator2.free()\n\n        # THEN\n        reader = FileReader(output)\n\n        if file_format == FileFormat.ALL_ALLOCATIONS:\n            all_allocations = list(\n                filter_relevant_allocations(reader.get_allocation_records())\n            )\n            assert len(all_allocations) == 4\n\n        peak_allocations = list(\n            filter_relevant_allocations(reader.get_high_watermark_allocation_records())\n        )\n        assert len(peak_allocations) == 2\n        assert sum(record.size for record in peak_allocations) == 1024 + 2048\n        assert all(record.n_allocations == 1 for record in peak_allocations)\n\n    def test_aggregation_same_python_stack_but_different_native_stack(\n        self, tmp_path, file_format\n    ):\n        # GIVEN\n        output = tmp_path / \"test.bin\"\n\n        # WHEN\n        with Tracker(output, native_traces=True, file_format=file_format):\n            _cython_allocate_in_two_places(ALLOC_SIZE)\n\n        # THEN\n        reader = FileReader(output)\n\n        if file_format == FileFormat.ALL_ALLOCATIONS:\n            all_allocations = list(\n                filter_relevant_allocations(reader.get_allocation_records())\n            )\n            assert len(all_allocations) == 4\n\n        peak_allocations = list(\n            filter_relevant_allocations(reader.get_high_watermark_allocation_records())\n        )\n        assert len(peak_allocations) == 2\n        assert (\n            sum(record.size for record in peak_allocations) == ALLOC_SIZE + ALLOC_SIZE\n        )\n        assert all(record.n_allocations == 1 for record in peak_allocations)\n\n    def test_non_freed_allocations_are_accounted_for(self, tmp_path, file_format):\n        # GIVEN\n        allocator1 = MemoryAllocator()\n        allocator2 = MemoryAllocator()\n        output = tmp_path / \"test.bin\"\n\n        # WHEN\n        with Tracker(output, file_format=file_format):\n            allocator1.valloc(1024)\n            allocator2.valloc(2048)\n            allocator1.free()\n            allocator2.free()\n\n        # THEN\n        reader = FileReader(output)\n\n        if file_format == FileFormat.ALL_ALLOCATIONS:\n            all_allocations = list(\n                filter_relevant_allocations(reader.get_allocation_records())\n            )\n            assert len(all_allocations) == 4\n\n        peak_allocations = list(\n            filter_relevant_allocations(reader.get_high_watermark_allocation_records())\n        )\n        assert len(peak_allocations) == 2\n        assert sum(record.size for record in peak_allocations) == 1024 + 2048\n        assert all(record.n_allocations == 1 for record in peak_allocations)\n\n    def test_final_allocation_is_peak(self, tmp_path, file_format):\n        # GIVEN\n        allocator1 = MemoryAllocator()\n        allocator2 = MemoryAllocator()\n        output = tmp_path / \"test.bin\"\n\n        # WHEN\n        with Tracker(output, file_format=file_format):\n            allocator1.valloc(1024)\n            allocator1.free()\n            allocator2.valloc(2048)\n        allocator2.free()\n\n        # THEN\n        reader = FileReader(output)\n\n        if file_format == FileFormat.ALL_ALLOCATIONS:\n            all_allocations = list(\n                filter_relevant_allocations(reader.get_allocation_records())\n            )\n            assert len(all_allocations) == 3\n\n        peak_allocations = list(\n            filter_relevant_allocations(reader.get_high_watermark_allocation_records())\n        )\n        assert len(peak_allocations) == 1\n\n        record = peak_allocations[0]\n        assert record.n_allocations == 1\n        assert record.allocator == AllocatorType.VALLOC\n        assert record.size == 2048\n\n    def test_spiky_generally_increasing_to_final_peak(self, tmp_path, file_format):\n        \"\"\"Checks multiple aspects with an interesting toy function.\"\"\"\n\n        # GIVEN\n        def recursive(n, chunk_size):\n            \"\"\"Mimics generally-increasing but spiky usage\"\"\"\n            if not n:\n                return\n\n            allocator = MemoryAllocator()\n            print(f\"+{n:>2} kB\")\n            allocator.valloc(n * chunk_size)\n\n            # Don't keep allocated memory when recursing, ~50% of the calls.\n            if n % 2:\n                allocator.free()\n                print(f\"-{n:>2} kB\")\n                recursive(n - 1, chunk_size)\n            else:\n                recursive(n - 1, chunk_size)\n                allocator.free()\n                print(f\"-{n:>2} kB\")\n\n        # WHEN\n        output = tmp_path / \"test.bin\"\n        with Tracker(output, file_format=file_format):\n            recursive(10, 1024)\n\n        # THEN\n        reader = FileReader(output)\n\n        if file_format == FileFormat.ALL_ALLOCATIONS:\n            all_allocations = list(\n                filter_relevant_allocations(reader.get_allocation_records())\n            )\n            assert len(all_allocations) == 20\n            assert sum(record.size for record in all_allocations) == 56320\n\n        peak_allocations = list(\n            filter_relevant_allocations(reader.get_high_watermark_allocation_records())\n        )\n        assert all(record.n_allocations == 1 for record in peak_allocations)\n\n        expected = {10, 8, 6, 4, 2, 1}\n        assert len(peak_allocations) == len(expected)\n        assert {record.size / 1024 for record in peak_allocations} == expected\n\n    def test_allocations_after_high_watermark_is_freed_do_not_appear(\n        self, tmp_path, file_format\n    ):\n        # GIVEN\n        allocator = MemoryAllocator()\n        output = tmp_path / \"test.bin\"\n\n        def test_function():\n            allocator.valloc(2048)\n            allocator.free()\n            allocator.valloc(1024)\n\n        with PrimeCaches():\n            test_function()\n            allocator.free()\n\n        # WHEN\n        with Tracker(output, file_format=file_format):\n            test_function()\n        allocator.free()\n\n        # THEN\n        reader = FileReader(output)\n\n        if file_format == FileFormat.ALL_ALLOCATIONS:\n            all_allocations = list(\n                filter_relevant_allocations(reader.get_allocation_records())\n            )\n            assert len(all_allocations) == 3\n\n        peak_allocations = list(\n            filter_relevant_allocations(reader.get_high_watermark_allocation_records())\n        )\n        assert len(peak_allocations) == 1\n\n        record = peak_allocations[0]\n        assert record.n_allocations == 1\n        assert record.allocator == AllocatorType.VALLOC\n        assert record.size == 2048\n\n    def test_partial_munmap(self, tmp_path, file_format):\n        \"\"\"Partial munmap operations should be accurately tracked: we should\n        only account for the removal of the actually munmap'd chunk and not\n        the entire mmap'd region when a partial munmap is performed.\"\"\"\n\n        # GIVEN\n        output = tmp_path / \"test.bin\"\n\n        def test_function():\n            # Mmap some memory and free just the first page. This should not register\n            # the deallocation of the entire mmap'd region, only one page.\n            alloc = MmapAllocator(2 * PAGE_SIZE)\n            alloc.munmap(PAGE_SIZE)\n\n            # Now perform the peak allocation. This should be detected as the peak index.\n            MmapAllocator(10 * PAGE_SIZE)\n            # At this point we should have 11 * PAGE_SIZE allocated\n\n        with PrimeCaches():\n            test_function()\n\n        # WHEN\n        with Tracker(output, file_format=file_format):\n            test_function()\n\n        # THEN\n        reader = FileReader(output)\n        peak_allocations = list(reader.get_high_watermark_allocation_records())\n        assert len(peak_allocations) == 2\n        peak_memory = sum(x.size for x in peak_allocations)\n        assert peak_memory == 11 * PAGE_SIZE\n\n    def test_partial_munmap_gap(self, tmp_path, file_format):\n        \"\"\"Validate that removing chunks from a mmap'd region correctly accounts\n        for the parts removed. This test allocates 4 pages and removes the first\n        and last pages of the mmap'd region.\"\"\"\n\n        # GIVEN\n        output = tmp_path / \"test.bin\"\n\n        def test_function():\n            # Mmap some memory and free two pages: one at the beginning and one at the\n            # end of the region.\n            alloc = MmapAllocator(4 * PAGE_SIZE)\n            alloc.munmap(PAGE_SIZE)\n            alloc.munmap(PAGE_SIZE, 3 * PAGE_SIZE)\n\n            # Now perform the peak allocation. This should be detected as the peak index.\n            MmapAllocator(10 * PAGE_SIZE)\n            # At this point we should have 12 * PAGE_SIZE allocated\n\n        with PrimeCaches():\n            test_function()\n\n        # WHEN\n        with Tracker(output, file_format=file_format):\n            test_function()\n\n        # THEN\n        reader = FileReader(output)\n        peak_allocations = list(reader.get_high_watermark_allocation_records())\n        assert len(peak_allocations) == 2\n        peak_memory = sum(x.size for x in peak_allocations)\n        assert peak_memory == 12 * PAGE_SIZE\n\n    def test_munmap_multiple_mmaps(self, tmp_path, file_format):\n        \"\"\"Allocate multiple contiguous mmap'd regions and then deallocate all of them\n        with munmap in one go.\"\"\"\n\n        # GIVEN\n        output = tmp_path / \"test.bin\"\n        with Tracker(output, file_format=file_format):\n            # Ensure we have a long enough free buffer for the contiguous\n            # mmap's. We also need to make sure the allocation addresses are\n            # page-aligned later, and mmap does that for us. We can then use\n            # the pointer from this allocation for the actual test.\n            buf = MmapAllocator(8 * PAGE_SIZE)\n            buf.munmap(8 * PAGE_SIZE)\n\n            # WHEN\n            # Allocate 2 contiguous chunks of 4 pages (8 pages in total) and free them\n            # with a single munmap\n            alloc1 = MmapAllocator(4 * PAGE_SIZE, buf.address)\n            MmapAllocator(4 * PAGE_SIZE, alloc1.address + (4 * PAGE_SIZE))\n            alloc1.munmap(8 * PAGE_SIZE)\n\n            # Now perform the peak allocation. This should be detected as the peak index.\n            MmapAllocator(10 * PAGE_SIZE)\n\n        # THEN\n        reader = FileReader(output)\n        peak_allocations = list(\n            filter_relevant_allocations(\n                reader.get_high_watermark_allocation_records(), ranged=True\n            )\n        )\n        peak_memory = sum(x.size for x in peak_allocations)\n        assert peak_memory == 10 * PAGE_SIZE\n\n    def test_munmap_multiple_mmaps_multiple_munmaps(self, tmp_path, file_format):\n        \"\"\"Allocate multiple contiguous mmap'd regions and then with multiple munmap's, each\n        deallocating several mmap'd areas in one go.\"\"\"\n        # GIVEN\n        output = tmp_path / \"test.bin\"\n        with Tracker(output, file_format=file_format):\n            # Ensure we have a long enough free buffer for the contiguous\n            # mmap's. We also need to make sure the allocation addresses are\n            # page-aligned later, and mmap does that for us. We can then use\n            # the pointer from this allocation for the actual test.\n            buf = MmapAllocator(8 * PAGE_SIZE)\n            buf.munmap(8 * PAGE_SIZE)\n\n            # WHEN\n            alloc1 = MmapAllocator(2 * PAGE_SIZE, buf.address)\n            MmapAllocator(2 * PAGE_SIZE, buf.address + (2 * PAGE_SIZE))\n            MmapAllocator(2 * PAGE_SIZE, buf.address + (4 * PAGE_SIZE))\n            MmapAllocator(2 * PAGE_SIZE, buf.address + (6 * PAGE_SIZE))\n            alloc1.munmap(4 * PAGE_SIZE)\n            alloc1.munmap(4 * PAGE_SIZE, 4 * PAGE_SIZE)\n\n            # Now perform the peak allocation. This should be detected as the peak index.\n            MmapAllocator(10 * PAGE_SIZE)\n\n        # THEN\n        reader = FileReader(output)\n        peak_allocations = list(\n            filter_relevant_allocations(\n                reader.get_high_watermark_allocation_records(), ranged=True\n            )\n        )\n        peak_memory = sum(x.size for x in peak_allocations)\n        assert peak_memory == 10 * PAGE_SIZE\n\n    def test_partial_munmap_multiple_split_in_middle(self, tmp_path, file_format):\n        \"\"\"Deallocate pages in of a larger mmap'd area, splitting it into 3 areas.\"\"\"\n        # GIVEN\n        output = tmp_path / \"test.bin\"\n\n        def test_function():\n            alloc = MmapAllocator(5 * PAGE_SIZE)\n            alloc.munmap(PAGE_SIZE, 1 * PAGE_SIZE)\n            alloc.munmap(PAGE_SIZE, 3 * PAGE_SIZE)\n            MmapAllocator(10 * PAGE_SIZE)\n\n        with PrimeCaches():\n            test_function()\n\n        # WHEN\n        with Tracker(output, file_format=file_format):\n            test_function()\n\n        # THEN\n        reader = FileReader(output)\n        peak_allocations = list(reader.get_high_watermark_allocation_records())\n        assert len(peak_allocations) == 2\n        peak_memory = sum(x.size for x in peak_allocations)\n        assert peak_memory == 13 * PAGE_SIZE\n\n    def test_partial_munmap_split_in_middle(self, tmp_path, file_format):\n        \"\"\"Deallocate a single page in the middle of a larger mmap'd area.\"\"\"\n        # GIVEN\n        output = tmp_path / \"test.bin\"\n\n        def test_function():\n            alloc = MmapAllocator(8 * PAGE_SIZE)\n            alloc.munmap(PAGE_SIZE, 4 * PAGE_SIZE)\n\n            MmapAllocator(10 * PAGE_SIZE)\n\n        with PrimeCaches():\n            test_function()\n\n        # WHEN\n        with Tracker(output, file_format=file_format):\n            test_function()\n\n        # THEN\n        reader = FileReader(output)\n        peak_allocations = list(reader.get_high_watermark_allocation_records())\n        assert len(peak_allocations) == 2\n        peak_memory = sum(x.size for x in peak_allocations)\n        assert peak_memory == 17 * PAGE_SIZE\n\n\n@pytest.mark.parametrize(\n    \"file_format\",\n    [\n        pytest.param(FileFormat.ALL_ALLOCATIONS, id=\"ALL_ALLOCATIONS\"),\n        pytest.param(FileFormat.AGGREGATED_ALLOCATIONS, id=\"AGGREGATED_ALLOCATIONS\"),\n    ],\n)\nclass TestLeaks:\n    def test_leaks_allocations_are_detected(self, tmp_path, file_format):\n        # GIVEN\n        allocator = MemoryAllocator()\n        output = tmp_path / \"test.bin\"\n\n        # WHEN\n        with Tracker(output, file_format=file_format):\n            allocator.valloc(1024)\n        allocator.free()\n\n        # THEN\n        reader = FileReader(output)\n\n        if file_format == FileFormat.ALL_ALLOCATIONS:\n            all_allocations = list(\n                filter_relevant_allocations(reader.get_allocation_records())\n            )\n            assert len(all_allocations) == 1\n\n        leaked_allocations = list(\n            filter_relevant_allocations(reader.get_leaked_allocation_records())\n        )\n        assert len(leaked_allocations) == 1\n\n        record = leaked_allocations[0]\n        assert record.n_allocations == 1\n        assert record.allocator == AllocatorType.VALLOC\n        assert record.size == 1024\n\n    def test_allocations_that_are_freed_do_not_appear_as_leaks(\n        self, tmp_path, file_format\n    ):\n        # GIVEN\n        allocator = MemoryAllocator()\n        output = tmp_path / \"test.bin\"\n\n        # WHEN\n        with Tracker(output, file_format=file_format):\n            allocator.valloc(1024)\n            allocator.free()\n            allocator.valloc(1024)\n            allocator.free()\n            allocator.valloc(1024)\n            allocator.free()\n\n        # THEN\n        reader = FileReader(output)\n\n        if file_format == FileFormat.ALL_ALLOCATIONS:\n            all_allocations = list(\n                filter_relevant_allocations(reader.get_allocation_records())\n            )\n            assert len(all_allocations) == 6\n\n        leaked_allocations = list(\n            filter_relevant_allocations(reader.get_leaked_allocation_records())\n        )\n        assert not leaked_allocations\n\n    def test_leak_that_happens_in_the_middle_is_detected(self, tmp_path, file_format):\n        # GIVEN\n        allocator = MemoryAllocator()\n        leak_allocator = MemoryAllocator()\n        output = tmp_path / \"test.bin\"\n\n        # WHEN\n        with Tracker(output, file_format=file_format):\n            allocator.valloc(1024)\n            allocator.free()\n            allocator.valloc(1024)\n            leak_allocator.valloc(2048)\n            allocator.free()\n            allocator.valloc(1024)\n            allocator.free()\n        leak_allocator.free()\n\n        # THEN\n        reader = FileReader(output)\n\n        if file_format == FileFormat.ALL_ALLOCATIONS:\n            all_allocations = list(\n                filter_relevant_allocations(reader.get_allocation_records())\n            )\n            assert len(all_allocations) == 7\n\n        leaked_allocations = list(\n            filter_relevant_allocations(reader.get_leaked_allocation_records())\n        )\n\n        assert len(leaked_allocations) == 1\n\n        record = leaked_allocations[0]\n        assert record.n_allocations == 1\n        assert record.allocator == AllocatorType.VALLOC\n        assert record.size == 2048\n\n    def test_leaks_that_happen_in_different_lines(self, tmp_path, file_format):\n        # GIVEN\n        allocator1 = MemoryAllocator()\n        allocator2 = MemoryAllocator()\n        output = tmp_path / \"test.bin\"\n\n        # WHEN\n        with Tracker(output, file_format=file_format):\n            allocator1.valloc(1024)\n            allocator2.valloc(2048)\n\n        allocator1.free()\n        allocator2.free()\n\n        # THEN\n        leaked_allocations = list(\n            filter_relevant_allocations(\n                FileReader(output).get_leaked_allocation_records()\n            )\n        )\n        assert len(leaked_allocations) == 2\n        assert sum(record.size for record in leaked_allocations) == 1024 + 2048\n        assert all(record.n_allocations == 1 for record in leaked_allocations)\n\n    def test_leaks_that_happen_in_the_same_function_are_aggregated(\n        self, tmp_path, file_format\n    ):\n        # GIVEN\n        allocators = []\n        output = tmp_path / \"test.bin\"\n\n        def foo():\n            allocator = MemoryAllocator()\n            allocator.valloc(1024)\n            allocators.append(allocator)\n\n        # WHEN\n        with Tracker(output, file_format=file_format):\n            for _ in range(10):\n                foo()\n\n        for allocator in allocators:\n            allocator.free()\n\n        # THEN\n        reader = FileReader(output)\n\n        if file_format == FileFormat.ALL_ALLOCATIONS:\n            all_allocations = list(\n                filter_relevant_allocations(reader.get_allocation_records())\n            )\n            assert len(all_allocations) == 10\n\n        leaked_allocations = list(\n            filter_relevant_allocations(reader.get_leaked_allocation_records())\n        )\n        assert len(leaked_allocations) == 1\n        (allocation,) = leaked_allocations\n        assert allocation.size == 1024 * 10\n        assert allocation.n_allocations == 10\n\n    def test_unmatched_deallocations_are_not_reported(self, tmp_path, file_format):\n        # GIVEN\n        allocator = MemoryAllocator()\n        output = tmp_path / \"test.bin\"\n\n        # WHEN\n        allocator.valloc(ALLOC_SIZE)\n        with Tracker(output, file_format=file_format):\n            allocator.free()\n\n        # THEN\n        reader = FileReader(output)\n\n        if file_format == FileFormat.ALL_ALLOCATIONS:\n            all_allocations = list(reader.get_allocation_records())\n            assert len(all_allocations) >= 1\n\n        assert not list(\n            filter_relevant_allocations(reader.get_leaked_allocation_records())\n        )\n\n    def test_thread_allocations_multiple_threads(self, tmpdir, file_format):\n        # GIVEN\n        def allocating_function(allocator, amount, stop_flag):\n            allocator.posix_memalign(amount)\n            allocator.posix_memalign(amount)\n            # We need a barrier as pthread might reuse the same thread ID if the first thread\n            # finishes before the other one starts\n            stop_flag.wait()\n\n        # WHEN\n        alloc1 = MemoryAllocator()\n        stop_flag1 = threading.Event()\n        alloc2 = MemoryAllocator()\n        stop_flag2 = threading.Event()\n        output = Path(tmpdir) / \"test.bin\"\n        with Tracker(output, file_format=file_format):\n            t1 = threading.Thread(\n                target=allocating_function, args=(alloc1, 2048, stop_flag1)\n            )\n            t1.start()\n            t2 = threading.Thread(\n                target=allocating_function, args=(alloc2, 2048, stop_flag2)\n            )\n            t2.start()\n\n            stop_flag1.set()\n            t1.join()\n            stop_flag2.set()\n            t2.join()\n\n        # THEN\n        reader = FileReader(output)\n\n        if file_format == FileFormat.ALL_ALLOCATIONS:\n            all_allocations = [\n                record\n                for record in reader.get_allocation_records()\n                if record.allocator == AllocatorType.POSIX_MEMALIGN\n            ]\n            assert len(all_allocations) == 4\n\n        high_watermark_records = (\n            record\n            for record in reader.get_high_watermark_allocation_records(\n                merge_threads=False\n            )\n            if record.allocator == AllocatorType.POSIX_MEMALIGN\n        )\n        # Group the allocations per thread\n        records = collections.defaultdict(list)\n        for record in high_watermark_records:\n            records[record.tid].append(record)\n        assert len(records.keys()) == 2\n        # Each thread should have 4096 bytes total allocations\n        for allocations in records.values():\n            assert sum(allocation.size for allocation in allocations) == 4096\n\n\nclass TestTemporaryAllocations:\n    def test_temporary_allocations_are_detected(self, tmp_path):\n        # GIVEN\n        allocator = MemoryAllocator()\n        output = tmp_path / \"test.bin\"\n\n        # WHEN\n        with Tracker(output):\n            allocator.valloc(1024)\n            allocator.free()\n\n        # THEN\n        reader = FileReader(output)\n        all_allocations = list(\n            filter_relevant_allocations(reader.get_allocation_records())\n        )\n        assert len(all_allocations) == 2\n\n        temporary_allocations = list(\n            filter_relevant_allocations(reader.get_temporary_allocation_records())\n        )\n        assert len(temporary_allocations) == 1\n\n        record = temporary_allocations[0]\n        assert record.n_allocations == 1\n        assert record.allocator == AllocatorType.VALLOC\n        assert record.size == 1024\n\n    def test_temporary_allocations_with_two_allocators_are_detected(self, tmp_path):\n        # GIVEN\n        allocator1 = MemoryAllocator()\n        allocator2 = MemoryAllocator()\n        output = tmp_path / \"test.bin\"\n\n        # WHEN\n        with Tracker(output):\n            allocator1.valloc(1024)\n            allocator1.free()\n            allocator2.valloc(1024)\n            allocator2.free()\n        # THEN\n        reader = FileReader(output)\n        all_allocations = list(\n            filter_relevant_allocations(reader.get_allocation_records())\n        )\n        assert len(all_allocations) == 4\n\n        temporary_allocations = list(\n            filter_relevant_allocations(reader.get_temporary_allocation_records())\n        )\n        assert len(temporary_allocations) == 2\n\n        for record in temporary_allocations:\n            assert record.n_allocations == 1\n            assert record.allocator == AllocatorType.VALLOC\n            assert record.size == 1024\n\n    @pytest.mark.parametrize(\n        \"buffer_size\",\n        [\n            1,\n            2,\n            5,\n            10,\n        ],\n    )\n    def test_temporary_allocations_outside_buffer_are_not_detected(\n        self, tmp_path, buffer_size\n    ):\n        # GIVEN\n        allocators = [MemoryAllocator() for _ in range(buffer_size + 1)]\n        output = tmp_path / \"test.bin\"\n\n        # WHEN\n        with Tracker(output):\n            for allocator in allocators:\n                allocator.valloc(1024)\n            for allocator in reversed(allocators):\n                allocator.free()\n\n        # THEN\n        reader = FileReader(output)\n        all_allocations = list(\n            filter_relevant_allocations(reader.get_allocation_records())\n        )\n        assert len(all_allocations) == 2 * (buffer_size + 1)\n\n        temporary_allocations = list(\n            filter_relevant_allocations(\n                reader.get_temporary_allocation_records(threshold=buffer_size - 1)\n            )\n        )\n        assert len(temporary_allocations) == 1\n        (allocation,) = temporary_allocations\n        assert allocation.n_allocations == buffer_size\n\n    def test_temporary_allocations_that_happen_in_different_lines(self, tmp_path):\n        # GIVEN\n        allocator1 = MemoryAllocator()\n        allocator2 = MemoryAllocator()\n        output = tmp_path / \"test.bin\"\n\n        # WHEN\n        with Tracker(output):\n            allocator1.valloc(1024)\n            allocator1.free()\n            allocator2.valloc(2048)\n            allocator2.free()\n\n        # THEN\n        temporary_allocations = list(\n            filter_relevant_allocations(\n                FileReader(output).get_temporary_allocation_records()\n            )\n        )\n        assert len(temporary_allocations) == 2\n        assert sum(record.size for record in temporary_allocations) == 1024 + 2048\n        assert all(record.n_allocations == 1 for record in temporary_allocations)\n\n    def test_temporary_allocations_that_happen_in_the_same_function_are_aggregated(\n        self, tmp_path\n    ):\n        # GIVEN\n        output = tmp_path / \"test.bin\"\n\n        def foo():\n            allocator = MemoryAllocator()\n            allocator.valloc(1024)\n            allocator.free()\n\n        # WHEN\n        with Tracker(output):\n            for _ in range(10):\n                foo()\n\n        # THEN\n        reader = FileReader(output)\n        all_allocations = list(\n            filter_relevant_allocations(reader.get_allocation_records())\n        )\n        assert len(all_allocations) == 10 + 10  # 10 x valloc + 10 x free\n\n        temporary_allocations = list(\n            filter_relevant_allocations(reader.get_temporary_allocation_records())\n        )\n        assert len(temporary_allocations) == 1\n        (allocation,) = temporary_allocations\n        assert allocation.size == 1024 * 10\n        assert allocation.n_allocations == 10\n\n    def test_unmatched_allocations_are_not_reported(self, tmp_path):\n        # GIVEN\n        allocator = MemoryAllocator()\n        output = tmp_path / \"test.bin\"\n\n        # WHEN\n        with Tracker(output):\n            allocator.valloc(ALLOC_SIZE)\n        allocator.free()\n\n        # THEN\n        reader = FileReader(output)\n        all_allocations = list(reader.get_allocation_records())\n        assert len(all_allocations) >= 1\n        assert not list(\n            filter_relevant_allocations(reader.get_temporary_allocation_records())\n        )\n\n    def test_thread_allocations_multiple_threads(self, tmpdir):\n        # GIVEN\n        def allocating_function(allocator, amount, stop_flag):\n            allocator.posix_memalign(amount)\n            allocator.free()\n            allocator.posix_memalign(amount)\n            allocator.free()\n            # We need a barrier as pthread might reuse the same thread ID if the first thread\n            # finishes before the other one starts\n            stop_flag.wait()\n\n        # WHEN\n        alloc1 = MemoryAllocator()\n        stop_flag1 = threading.Event()\n        alloc2 = MemoryAllocator()\n        stop_flag2 = threading.Event()\n        output = Path(tmpdir) / \"test.bin\"\n        with Tracker(output):\n            t1 = threading.Thread(\n                target=allocating_function, args=(alloc1, 2048, stop_flag1)\n            )\n            t1.start()\n            t2 = threading.Thread(\n                target=allocating_function, args=(alloc2, 2048, stop_flag2)\n            )\n            t2.start()\n\n            stop_flag1.set()\n            t1.join()\n            stop_flag2.set()\n            t2.join()\n\n        # THEN\n        reader = FileReader(output)\n        all_allocations = [\n            record\n            for record in reader.get_allocation_records()\n            if record.allocator == AllocatorType.POSIX_MEMALIGN\n        ]\n        assert len(all_allocations) == 4\n\n        temporary_allocation_records = (\n            record\n            for record in reader.get_temporary_allocation_records(merge_threads=False)\n            if record.allocator == AllocatorType.POSIX_MEMALIGN\n        )\n        # Group the allocations per thread\n        records = collections.defaultdict(list)\n        for record in temporary_allocation_records:\n            records[record.tid].append(record)\n        assert len(records.keys()) == 2\n        # Each thread should have 4096 bytes total allocations\n        for allocations in records.values():\n            assert sum(allocation.size for allocation in allocations) == 4096\n\n    def test_intertwined_temporary_allocations_in_threads(self, tmpdir):\n        \"\"\"This test checks that temporary allocations are correctly detected\n        when they happen in different threads with interleaved calls to malloc\n        and free.\n\n        Note that there is not an easy way to synchronize this test because\n        using condition variables may allocate, disrupting the test as there\n        will be other spurious allocations between our call to posix_memalign\n        and the call to free.\n\n        The best effort is that both threads are synchronized by spinlocking\n        around a python boolean that uses the GIL as means to ensure the correct\n        ordering of allocations.\n        \"\"\"\n\n        # GIVEN\n        thread1_allocated = False\n        thread1_should_free = False\n\n        def thread1_body(allocator):\n            nonlocal thread1_allocated\n            allocator.posix_memalign(1234)\n            thread1_allocated = True\n            while not thread1_should_free:\n                pass\n            allocator.free()\n\n        def thread2_body(allocator):\n            nonlocal thread1_should_free\n            while not thread1_allocated:\n                pass\n            allocator.posix_memalign(1234)\n            allocator.free()\n            thread1_should_free = True\n\n        # WHEN\n        alloc1 = MemoryAllocator()\n        alloc2 = MemoryAllocator()\n        output = Path(tmpdir) / \"test.bin\"\n        with Tracker(output):\n            t1 = threading.Thread(target=thread1_body, args=[alloc1])\n            t1.start()\n            t2 = threading.Thread(\n                target=thread2_body,\n                args=[alloc2],\n            )\n            t2.start()\n\n            t1.join()\n            t2.join()\n\n        # THEN\n        reader = FileReader(output)\n        all_allocations = [\n            record\n            for record in reader.get_allocation_records()\n            if record.allocator == AllocatorType.POSIX_MEMALIGN\n        ]\n        assert len(all_allocations) == 2\n\n        temporary_allocation_records = (\n            record\n            for record in reader.get_temporary_allocation_records(merge_threads=False)\n            if record.allocator == AllocatorType.POSIX_MEMALIGN\n        )\n        # Group the allocations per thread\n        records = collections.defaultdict(list)\n        for record in temporary_allocation_records:\n            records[record.tid].append(record)\n        assert len(records.keys()) == 2\n        # Each thread should have 1234 bytes total allocations\n        for allocations in records.values():\n            assert sum(allocation.size for allocation in allocations) == 1234\n\n\nclass TestHeader:\n    def test_get_header(self, monkeypatch, tmpdir):\n        # GIVEN\n        allocator = MemoryAllocator()\n        output = Path(tmpdir) / \"test.bin\"\n\n        with PrimeCaches():\n            pass\n\n        # WHEN\n\n        monkeypatch.setattr(sys, \"argv\", [\"python\", \"-m\", \"pytest\"])\n        with run_without_tracer():\n            start_time = datetime.datetime.now().astimezone()\n            with Tracker(output):\n                for _ in range(100):\n                    allocator.valloc(1024)\n            end_time = datetime.datetime.now().astimezone()\n\n        reader = FileReader(output)\n        n_records = len(list(reader.get_allocation_records()))\n        metadata = reader.metadata\n\n        # THEN\n        assert metadata.end_time > metadata.start_time\n        assert abs(metadata.start_time - start_time).seconds < 1\n        assert abs(metadata.end_time - end_time).seconds < 1\n        assert metadata.total_allocations == n_records\n        assert metadata.command_line == \"python -m pytest\"\n        assert metadata.peak_memory == 1024 * 100\n\n    def test_get_header_after_snapshot(self, monkeypatch, tmpdir):\n        \"\"\"Verify that we can successfully retrieve the metadata after querying\n        the high watermark snapshot.\"\"\"\n        # GIVEN\n        allocator = MemoryAllocator()\n        output = Path(tmpdir) / \"test.bin\"\n\n        with PrimeCaches():\n            pass\n\n        # WHEN\n\n        monkeypatch.setattr(sys, \"argv\", [\"python\", \"-m\", \"pytest\"])\n        start_time = datetime.datetime.now().astimezone()\n        with Tracker(output):\n            for _ in range(100):\n                allocator.valloc(1024)\n        end_time = datetime.datetime.now().astimezone()\n\n        reader = FileReader(output)\n        peak, *_ = list(reader.get_high_watermark_allocation_records())\n        metadata = reader.metadata\n\n        # THEN\n        assert metadata.end_time > metadata.start_time\n        assert abs(metadata.start_time - start_time).seconds < 1\n        assert abs(metadata.end_time - end_time).seconds < 1\n        assert metadata.total_allocations == peak.n_allocations\n        assert metadata.command_line == \"python -m pytest\"\n        assert metadata.peak_memory == 1024 * 100\n\n    @pytest.mark.parametrize(\n        \"allocator, allocator_name\",\n        [\n            (\"malloc\", \"malloc\"),\n            (\"pymalloc\", \"pymalloc\"),\n            (\"pymalloc_debug\", \"pymalloc debug\"),\n            (\"mimalloc\", \"mimalloc\"),\n            (\"mimalloc_debug\", \"mimalloc debug\"),\n        ],\n    )\n    def test_header_allocator(self, allocator, allocator_name, tmpdir):\n        # GIVEN\n        output = Path(tmpdir) / \"test.bin\"\n        env = os.environ.copy()\n        env[\"PYTHONMALLOC\"] = allocator\n        if subprocess.run([sys.executable, \"-cpass\"], env=env).returncode != 0:\n            pytest.skip(f\"This interpreter doesn't support PYTHONMALLOC={allocator}\")\n\n        # WHEN\n\n        subprocess_code = textwrap.dedent(\n            f\"\"\"\n            from memray import Tracker\n            from memray._test import MemoryAllocator\n            allocator = MemoryAllocator()\n\n            with Tracker('{output}'):\n                allocator.valloc(1024)\n                allocator.free()\n            \"\"\"\n        )\n\n        subprocess.run([sys.executable, \"-c\", subprocess_code], timeout=5, env=env)\n\n        reader = FileReader(output)\n        metadata = reader.metadata\n\n        # THEN\n        assert metadata.python_allocator == allocator_name\n\n\ndef test_pymalloc_with_python_stack_traces(tmp_path):\n    \"\"\"Test that pymalloc allocations have Python stack traces\"\"\"\n    # GIVEN\n    allocator = PymallocMemoryAllocator(PymallocDomain.PYMALLOC_OBJECT)\n    output = tmp_path / \"test.bin\"\n\n    def alloc_func3():\n        return allocator.malloc(ALLOC_SIZE)\n\n    def alloc_func2():\n        return alloc_func3()\n\n    def alloc_func1():\n        return alloc_func2()\n\n    # WHEN\n    with Tracker(output, trace_python_allocators=True):\n        res = alloc_func1()\n        if res:\n            allocator.free()\n\n    if not res:\n        pytest.skip(\"PymallocMemoryAllocator not supported on this platform\")\n\n    # THEN\n    allocations = list(FileReader(output).get_allocation_records())\n    allocs = [\n        event\n        for event in allocations\n        if event.size == ALLOC_SIZE and event.allocator == AllocatorType.PYMALLOC_MALLOC\n    ]\n    assert len(allocs) == 1\n    (alloc,) = allocs\n\n    # Check the Python stack trace\n    traceback = list(alloc.stack_trace())\n    assert len(traceback) > 0\n\n    # Verify our calling functions are in the stack\n    func_names = [frame[0] for frame in traceback]\n    assert \"alloc_func3\" in func_names\n    assert \"alloc_func2\" in func_names\n    assert \"alloc_func1\" in func_names\n    assert \"test_pymalloc_with_python_stack_traces\" in func_names\n\n\nclass TestMemorySnapshots:\n    @pytest.mark.valgrind\n    def test_memory_snapshots_are_written(self, tmp_path):\n        # GIVEN\n        allocator = MemoryAllocator()\n        output = tmp_path / \"test.bin\"\n\n        # WHEN\n        with Tracker(output):\n            allocator.valloc(ALLOC_SIZE)\n            time.sleep(0.11)\n            allocator.free()\n\n        memory_snapshots = list(FileReader(output).get_memory_snapshots())\n\n        assert memory_snapshots\n        assert all(record.rss > 0 for record in memory_snapshots)\n        assert any(record.heap >= ALLOC_SIZE for record in memory_snapshots)\n        assert sorted(memory_snapshots, key=lambda r: r.time) == memory_snapshots\n        assert all(\n            _next.time - prev.time >= 10\n            for prev, _next in zip(memory_snapshots, memory_snapshots[1:])\n        )\n\n    def test_memory_snapshots_tick_interval(self, tmp_path):\n        # GIVEN\n        allocator = MemoryAllocator()\n        output = tmp_path / \"test.bin\"\n\n        # WHEN\n        with Tracker(output, memory_interval_ms=20):\n            allocator.valloc(ALLOC_SIZE)\n            time.sleep(1)\n\n        memory_snapshots = list(FileReader(output).get_memory_snapshots())\n\n        assert len(memory_snapshots)\n        assert all(record.rss > 0 for record in memory_snapshots)\n        assert any(record.heap >= ALLOC_SIZE for record in memory_snapshots)\n        assert sorted(memory_snapshots, key=lambda r: r.time) == memory_snapshots\n        assert all(\n            _next.time - prev.time >= 20\n            for prev, _next in zip(memory_snapshots, memory_snapshots[1:])\n        )\n\n    def test_memory_snapshots_limit_when_reading(self, tmp_path):\n        # GIVEN\n        allocator = MemoryAllocator()\n        output = tmp_path / \"test.bin\"\n\n        # WHEN\n        with Tracker(output):\n            for _ in range(2):\n                allocator.valloc(ALLOC_SIZE)\n                time.sleep(0.11)\n                allocator.free()\n\n        reader = FileReader(output)\n        memory_snapshots = list(reader.get_memory_snapshots())\n        temporal_records = list(reader.get_temporal_allocation_records())\n\n        assert memory_snapshots\n        n_snapshots = len(memory_snapshots)\n        n_temporal_records = len(temporal_records)\n\n        reader = FileReader(output, max_memory_records=n_snapshots // 2)\n        memory_snapshots = list(reader.get_memory_snapshots())\n        temporal_records = list(reader.get_temporal_allocation_records())\n\n        assert memory_snapshots\n        assert len(memory_snapshots) <= n_snapshots // 2 + 1\n        assert len(temporal_records) <= n_temporal_records // 2 + 1\n\n    def test_temporary_allocations_when_filling_vector_without_preallocating(\n        self, tmp_path\n    ):\n        # GIVEN\n        output = tmp_path / \"test.bin\"\n\n        # WHEN\n        with Tracker(output):\n            elements = fill_cpp_vector(2 << 10)\n\n        # THEN\n        reader = FileReader(output)\n        temporary_allocations = [\n            alloc\n            for alloc in reader.get_temporary_allocation_records(threshold=1)\n            if __file__ in alloc.stack_trace()[0][1]\n        ]\n        assert elements == 512\n        assert len(temporary_allocations) == 1\n        (record,) = temporary_allocations\n        assert record.n_allocations == 10\n        assert record.allocator == AllocatorType.MALLOC\n        assert record.size >= (2 << 10)\n\n    def test_temporary_allocations_when_filling_vector_without_preallocating_small_buffer(\n        self, tmp_path\n    ):\n        # GIVEN\n        output = tmp_path / \"test.bin\"\n\n        # WHEN\n        with Tracker(output):\n            elements = fill_cpp_vector(2 << 10)\n\n        # THEN\n        reader = FileReader(output)\n        temporary_allocations = [\n            alloc\n            for alloc in reader.get_temporary_allocation_records(threshold=0)\n            if __file__ in alloc.stack_trace()[0][1]\n        ]\n        assert elements == 512\n        assert len(temporary_allocations) == 1\n        (record,) = temporary_allocations\n        # With a buffer of 1 we only see the last allocation\n        assert record.n_allocations == 1\n        assert record.allocator == AllocatorType.MALLOC\n        assert record.size == 2 << 10\n"
  },
  {
    "path": "tests/test_utils.py",
    "content": "\"\"\"Tests for our testing utilities.\"\"\"\n\nfrom memray import AllocationRecord\nfrom memray import AllocatorType\nfrom tests.utils import MockAllocationRecord\nfrom tests.utils import filter_relevant_allocations\n\n\nclass TestFilterRelevantAllocations:\n    def test_filters_for_valloc_and_free(self):\n        records = [\n            MockAllocationRecord(1, 0x1000000, 1024, AllocatorType.MALLOC, 0, 0, []),\n            MockAllocationRecord(1, 0x1000000, 1024, AllocatorType.VALLOC, 0, 0, []),\n            MockAllocationRecord(1, 0x1000000, 0, AllocatorType.FREE, 0, 0, []),\n        ]\n        assert list(filter_relevant_allocations(records)) == [\n            MockAllocationRecord(1, 0x1000000, 1024, AllocatorType.VALLOC, 0, 0, []),\n            MockAllocationRecord(1, 0x1000000, 0, AllocatorType.FREE, 0, 0, []),\n        ]\n\n    def test_filters_based_on_addresses(self):\n        records = [\n            MockAllocationRecord(1, 0x2000000, 1024, AllocatorType.MALLOC, 0, 0, []),\n            MockAllocationRecord(1, 0x1000000, 1024, AllocatorType.VALLOC, 0, 0, []),\n            MockAllocationRecord(1, 0x2000000, 0, AllocatorType.FREE, 0, 0, []),\n            MockAllocationRecord(1, 0x1000000, 0, AllocatorType.FREE, 0, 0, []),\n        ]\n        assert list(filter_relevant_allocations(records)) == [\n            MockAllocationRecord(1, 0x1000000, 1024, AllocatorType.VALLOC, 0, 0, []),\n            MockAllocationRecord(1, 0x1000000, 0, AllocatorType.FREE, 0, 0, []),\n        ]\n\n    def test_free_records_with_valid_addresses_that_dont_match_do_not_appear(self):\n        records = [\n            MockAllocationRecord(1, 0x2000000, 0, AllocatorType.FREE, 0, 0, []),\n            MockAllocationRecord(1, 0x1000000, 0, AllocatorType.FREE, 0, 0, []),\n            MockAllocationRecord(1, 0x2000000, 1024, AllocatorType.MALLOC, 0, 0, []),\n            MockAllocationRecord(1, 0x1000000, 1024, AllocatorType.VALLOC, 0, 0, []),\n            MockAllocationRecord(1, 0x2000000, 0, AllocatorType.FREE, 0, 0, []),\n            MockAllocationRecord(1, 0x1000000, 0, AllocatorType.FREE, 0, 0, []),\n        ]\n        assert list(filter_relevant_allocations(records)) == [\n            MockAllocationRecord(1, 0x1000000, 1024, AllocatorType.VALLOC, 0, 0, []),\n            MockAllocationRecord(1, 0x1000000, 0, AllocatorType.FREE, 0, 0, []),\n        ]\n\n    def test_free_records_with_unmatched_addresses_do_not_appear(self):\n        records = [\n            MockAllocationRecord(1, 0x6000000, 0, AllocatorType.FREE, 0, 0, []),\n            MockAllocationRecord(1, 0x7000000, 0, AllocatorType.FREE, 0, 0, []),\n            MockAllocationRecord(1, 0x2000000, 1024, AllocatorType.MALLOC, 0, 0, []),\n            MockAllocationRecord(1, 0x1000000, 1024, AllocatorType.VALLOC, 0, 0, []),\n            MockAllocationRecord(1, 0x2000000, 0, AllocatorType.FREE, 0, 0, []),\n            MockAllocationRecord(1, 0x1000000, 0, AllocatorType.FREE, 0, 0, []),\n        ]\n        assert list(filter_relevant_allocations(records)) == [\n            MockAllocationRecord(1, 0x1000000, 1024, AllocatorType.VALLOC, 0, 0, []),\n            MockAllocationRecord(1, 0x1000000, 0, AllocatorType.FREE, 0, 0, []),\n        ]\n\n\nclass TestMockAllocationRecord:\n    def test_holds_values_at_correct_names(self):\n        tid = 0\n        address = 0x1140000\n        size = 1024\n        allocator = AllocatorType.MALLOC\n        stack_id = 1\n        n_allocations = 1\n        stack = [\"stack 0\", \"stack 1\"]\n\n        mock_record = MockAllocationRecord(\n            tid, address, size, allocator, stack_id, n_allocations, stack\n        )\n        assert mock_record.tid == tid\n        assert mock_record.address == address\n        assert mock_record.size == size\n        assert mock_record.allocator == allocator\n        assert mock_record.stack_id == stack_id\n        assert mock_record.n_allocations == n_allocations\n        assert mock_record.stack_trace() == stack\n        assert mock_record.stack_trace(max_stacks=1) == [\"stack 0\"]\n\n    def test_looks_like_AllocationRecord(self):\n        tid = 0\n        address = 0x1140000\n        size = 1024\n        allocator = AllocatorType.MALLOC\n        stack_id = 1\n        n_allocations = 1\n        stack = [\"i'm stack\"]\n\n        record = AllocationRecord(\n            (tid, address, size, allocator, stack_id, n_allocations)\n        )\n        mock_record = MockAllocationRecord(\n            tid, address, size, allocator, stack_id, n_allocations, stack\n        )\n\n        assert mock_record.tid == record.tid == tid\n        assert mock_record.address == record.address == address\n        assert mock_record.size == record.size == size\n        assert mock_record.allocator == record.allocator == allocator\n        assert mock_record.stack_id == record.stack_id == stack_id\n        assert mock_record.n_allocations == record.n_allocations == n_allocations\n\n    def test_equality(self):\n        one = MockAllocationRecord(1, 0x1000000, 0, AllocatorType.FREE, 0, 0, [])\n        two = MockAllocationRecord(1, 0x1000000, 0, AllocatorType.FREE, 0, 0, [])\n        three = MockAllocationRecord(2, 0x1000000, 0, AllocatorType.FREE, 0, 0, [])\n\n        assert one == one\n        assert one == two\n        assert one != three\n\n        assert two == one\n        assert two == two\n        assert two != three\n\n        assert three != one\n        assert three != two\n        assert three == three\n"
  },
  {
    "path": "tests/unit/__init__.py",
    "content": ""
  },
  {
    "path": "tests/unit/conftest.py",
    "content": "import pytest\n\n\n@pytest.fixture(autouse=True)\ndef use_80_columns(monkeypatch):\n    \"\"\"Override the COLUMNS environment variable to 80.\n\n    This matches the assumed terminal width that is hardcoded in the tests.\n    \"\"\"\n    monkeypatch.setenv(\"COLUMNS\", \"80\")\n"
  },
  {
    "path": "tests/unit/test_allocation_lifetime_aggregator.py",
    "content": "from dataclasses import dataclass\n\nfrom memray import AllocatorType\nfrom memray._memray import AllocationLifetimeAggregatorTestHarness\nfrom memray._memray import Interval\n\nCALLOC = AllocatorType.CALLOC\nFREE = AllocatorType.FREE\nMMAP = AllocatorType.MMAP\nMUNMAP = AllocatorType.MUNMAP\n\n\n@dataclass(frozen=True)\nclass Location:\n    tid: int\n    native_frame_id: int\n    frame_index: int\n    native_segment_generation: int\n\n\ndef test_no_allocations_at_start():\n    # GIVEN\n    tester = AllocationLifetimeAggregatorTestHarness()\n\n    # WHEN\n    # THEN\n    assert [] == list(tester.get_allocations())\n\n\ndef test_allocation_not_reported_when_freed_within_same_snapshot():\n    # GIVEN\n    tester = AllocationLifetimeAggregatorTestHarness()\n    loc = Location(\n        tid=1,\n        native_frame_id=4,\n        frame_index=5,\n        native_segment_generation=6,\n    )\n\n    # WHEN\n    tester.add_allocation(**loc.__dict__, allocator=CALLOC, address=4096, size=1234)\n    tester.add_allocation(**loc.__dict__, allocator=FREE, address=4096, size=0)\n\n    # THEN\n    assert [] == list(tester.get_allocations())\n\n\ndef test_allocation_reported_when_freed_within_different_snapshot():\n    # GIVEN\n    tester = AllocationLifetimeAggregatorTestHarness()\n    loc = Location(\n        tid=1,\n        native_frame_id=4,\n        frame_index=5,\n        native_segment_generation=6,\n    )\n\n    # WHEN\n    tester.add_allocation(**loc.__dict__, allocator=CALLOC, address=4096, size=1234)\n    tester.capture_snapshot()\n    tester.add_allocation(**loc.__dict__, allocator=FREE, address=4096, size=0)\n\n    # THEN\n    (alloc,) = tester.get_allocations()\n    assert alloc.allocator == CALLOC\n    assert alloc.native_stack_id == 4\n    assert alloc.stack_id == 5\n    assert alloc.native_segment_generation == 6\n    assert alloc.tid == 1\n    assert alloc.intervals == [Interval(0, 1, 1, 1234)]\n\n\ndef test_allocation_reported_when_leaked():\n    # GIVEN\n    tester = AllocationLifetimeAggregatorTestHarness()\n    loc = Location(\n        tid=1,\n        native_frame_id=4,\n        frame_index=5,\n        native_segment_generation=6,\n    )\n\n    # WHEN\n    tester.add_allocation(**loc.__dict__, allocator=CALLOC, address=4096, size=1234)\n\n    # THEN\n    (alloc,) = tester.get_allocations()\n    assert alloc.allocator == CALLOC\n    assert alloc.native_stack_id == 4\n    assert alloc.stack_id == 5\n    assert alloc.native_segment_generation == 6\n    assert alloc.tid == 1\n    assert alloc.intervals == [Interval(0, None, 1, 1234)]\n\n\ndef test_multiple_snapshots_between_allocation_and_deallocation():\n    # GIVEN\n    tester = AllocationLifetimeAggregatorTestHarness()\n    loc = Location(\n        tid=1,\n        native_frame_id=4,\n        frame_index=5,\n        native_segment_generation=6,\n    )\n\n    # WHEN\n    tester.capture_snapshot()\n    tester.capture_snapshot()\n    tester.add_allocation(**loc.__dict__, allocator=CALLOC, address=4096, size=1234)\n    tester.capture_snapshot()\n    tester.capture_snapshot()\n    tester.capture_snapshot()\n    tester.add_allocation(**loc.__dict__, allocator=FREE, address=4096, size=0)\n    tester.capture_snapshot()\n\n    # THEN\n    (alloc,) = tester.get_allocations()\n    assert alloc.allocator == CALLOC\n    assert alloc.native_stack_id == 4\n    assert alloc.stack_id == 5\n    assert alloc.native_segment_generation == 6\n    assert alloc.tid == 1\n    assert alloc.intervals == [Interval(2, 5, 1, 1234)]\n\n\ndef test_allocations_from_same_location_and_snapshot_freed_in_different_snapshots():\n    # GIVEN\n    tester = AllocationLifetimeAggregatorTestHarness()\n    loc = Location(\n        tid=1,\n        native_frame_id=4,\n        frame_index=5,\n        native_segment_generation=6,\n    )\n\n    # WHEN\n    tester.capture_snapshot()\n    tester.add_allocation(**loc.__dict__, allocator=CALLOC, address=4096, size=1234)\n    tester.add_allocation(**loc.__dict__, allocator=CALLOC, address=8192, size=4321)\n    tester.capture_snapshot()\n    tester.add_allocation(**loc.__dict__, allocator=FREE, address=8192, size=0)\n    tester.capture_snapshot()\n    tester.add_allocation(**loc.__dict__, allocator=FREE, address=4096, size=0)\n\n    # THEN\n    (alloc,) = tester.get_allocations()\n    assert alloc.allocator == CALLOC\n    assert alloc.native_stack_id == 4\n    assert alloc.stack_id == 5\n    assert alloc.native_segment_generation == 6\n    assert alloc.tid == 1\n    assert alloc.intervals == [Interval(1, 2, 1, 4321), Interval(1, 3, 1, 1234)]\n\n\ndef test_allocations_from_same_location_and_different_snapshots_freed_in_one_snapshot():\n    # GIVEN\n    tester = AllocationLifetimeAggregatorTestHarness()\n    loc = Location(\n        tid=1,\n        native_frame_id=4,\n        frame_index=5,\n        native_segment_generation=6,\n    )\n\n    # WHEN\n    tester.add_allocation(**loc.__dict__, allocator=CALLOC, address=4096, size=1234)\n    tester.capture_snapshot()\n    tester.add_allocation(**loc.__dict__, allocator=CALLOC, address=8192, size=4321)\n    tester.capture_snapshot()\n    tester.add_allocation(**loc.__dict__, allocator=FREE, address=8192, size=0)\n    tester.add_allocation(**loc.__dict__, allocator=FREE, address=4096, size=0)\n\n    # THEN\n    (alloc,) = tester.get_allocations()\n    assert alloc.allocator == CALLOC\n    assert alloc.native_stack_id == 4\n    assert alloc.stack_id == 5\n    assert alloc.native_segment_generation == 6\n    assert alloc.tid == 1\n    assert alloc.intervals == [Interval(0, 2, 1, 1234), Interval(1, 2, 1, 4321)]\n\n\ndef test_two_leaked_allocations_from_one_location():\n    # GIVEN\n    tester = AllocationLifetimeAggregatorTestHarness()\n    loc = Location(\n        tid=1,\n        native_frame_id=4,\n        frame_index=5,\n        native_segment_generation=6,\n    )\n\n    # WHEN\n    tester.add_allocation(**loc.__dict__, allocator=CALLOC, address=4096, size=1234)\n    tester.capture_snapshot()\n    tester.add_allocation(**loc.__dict__, allocator=CALLOC, address=8192, size=4321)\n    tester.capture_snapshot()\n\n    # THEN\n    (alloc,) = tester.get_allocations()\n    assert alloc.allocator == CALLOC\n    assert alloc.native_stack_id == 4\n    assert alloc.stack_id == 5\n    assert alloc.native_segment_generation == 6\n    assert alloc.tid == 1\n    assert alloc.intervals == [Interval(0, None, 1, 1234), Interval(1, None, 1, 4321)]\n\n\ndef test_allocations_made_and_freed_together_are_aggregated():\n    # GIVEN\n    tester = AllocationLifetimeAggregatorTestHarness()\n    loc = Location(\n        tid=1,\n        native_frame_id=4,\n        frame_index=5,\n        native_segment_generation=6,\n    )\n\n    # WHEN\n    tester.add_allocation(**loc.__dict__, allocator=CALLOC, address=4096, size=1234)\n    tester.add_allocation(**loc.__dict__, allocator=CALLOC, address=8192, size=4321)\n    tester.capture_snapshot()\n    tester.add_allocation(**loc.__dict__, allocator=FREE, address=8192, size=0)\n    tester.add_allocation(**loc.__dict__, allocator=FREE, address=4096, size=0)\n\n    # THEN\n    (alloc,) = tester.get_allocations()\n    assert alloc.allocator == CALLOC\n    assert alloc.native_stack_id == 4\n    assert alloc.stack_id == 5\n    assert alloc.native_segment_generation == 6\n    assert alloc.tid == 1\n    assert alloc.intervals == [Interval(0, 1, 2, 1234 + 4321)]\n\n\ndef test_leaked_allocations_within_one_snapshot_are_aggregated():\n    # GIVEN\n    tester = AllocationLifetimeAggregatorTestHarness()\n    loc = Location(\n        tid=1,\n        native_frame_id=4,\n        frame_index=5,\n        native_segment_generation=6,\n    )\n\n    # WHEN\n    tester.add_allocation(**loc.__dict__, allocator=CALLOC, address=4096, size=1234)\n    tester.add_allocation(**loc.__dict__, allocator=CALLOC, address=8192, size=4321)\n    tester.capture_snapshot()\n\n    # THEN\n    (alloc,) = tester.get_allocations()\n    assert alloc.allocator == CALLOC\n    assert alloc.native_stack_id == 4\n    assert alloc.stack_id == 5\n    assert alloc.native_segment_generation == 6\n    assert alloc.tid == 1\n    assert alloc.intervals == [Interval(0, None, 2, 1234 + 4321)]\n\n\ndef test_freed_allocations_from_different_locations_are_not_aggregated():\n    # GIVEN\n    tester = AllocationLifetimeAggregatorTestHarness()\n    loc1 = Location(\n        tid=1,\n        native_frame_id=4,\n        frame_index=5,\n        native_segment_generation=6,\n    )\n    loc2 = Location(\n        tid=1,\n        native_frame_id=7,\n        frame_index=8,\n        native_segment_generation=9,\n    )\n    free = Location(\n        tid=0,\n        native_frame_id=0,\n        frame_index=0,\n        native_segment_generation=0,\n    )\n\n    # WHEN\n    tester.add_allocation(**loc1.__dict__, allocator=CALLOC, address=4096, size=1234)\n    tester.add_allocation(**loc2.__dict__, allocator=CALLOC, address=8192, size=4321)\n    tester.capture_snapshot()\n    tester.add_allocation(**free.__dict__, allocator=FREE, address=8192, size=0)\n    tester.add_allocation(**free.__dict__, allocator=FREE, address=4096, size=0)\n\n    # THEN\n    alloc1, alloc2 = tester.get_allocations()\n    assert alloc1.allocator == CALLOC\n    assert alloc1.native_stack_id == 4\n    assert alloc1.stack_id == 5\n    assert alloc1.native_segment_generation == 6\n    assert alloc1.tid == 1\n    assert alloc1.intervals == [Interval(0, 1, 1, 1234)]\n\n    assert alloc2.allocator == CALLOC\n    assert alloc2.native_stack_id == 7\n    assert alloc2.stack_id == 8\n    assert alloc2.native_segment_generation == 9\n    assert alloc2.tid == 1\n    assert alloc2.intervals == [Interval(0, 1, 1, 4321)]\n\n\ndef test_leaked_allocations_from_different_locations_are_not_aggregated():\n    # GIVEN\n    tester = AllocationLifetimeAggregatorTestHarness()\n    loc1 = Location(\n        tid=1,\n        native_frame_id=4,\n        frame_index=5,\n        native_segment_generation=6,\n    )\n    loc2 = Location(\n        tid=1,\n        native_frame_id=7,\n        frame_index=8,\n        native_segment_generation=9,\n    )\n\n    # WHEN\n    tester.add_allocation(**loc1.__dict__, allocator=CALLOC, address=4096, size=1234)\n    tester.add_allocation(**loc2.__dict__, allocator=CALLOC, address=8192, size=4321)\n\n    # THEN\n    alloc1, alloc2 = tester.get_allocations()\n    assert alloc1.allocator == CALLOC\n    assert alloc1.native_stack_id == 4\n    assert alloc1.stack_id == 5\n    assert alloc1.native_segment_generation == 6\n    assert alloc1.tid == 1\n    assert alloc1.intervals == [Interval(0, None, 1, 1234)]\n\n    assert alloc2.allocator == CALLOC\n    assert alloc2.native_stack_id == 7\n    assert alloc2.stack_id == 8\n    assert alloc2.native_segment_generation == 9\n    assert alloc2.tid == 1\n    assert alloc2.intervals == [Interval(0, None, 1, 4321)]\n\n\ndef test_range_freed_in_same_snapshot():\n    # GIVEN\n    tester = AllocationLifetimeAggregatorTestHarness()\n    loc = Location(\n        tid=1,\n        native_frame_id=4,\n        frame_index=5,\n        native_segment_generation=6,\n    )\n\n    # WHEN\n    tester.add_allocation(**loc.__dict__, allocator=MMAP, address=4096, size=1234)\n    tester.add_allocation(**loc.__dict__, allocator=MUNMAP, address=4096, size=1234)\n\n    # THEN\n    assert [] == list(tester.get_allocations())\n\n\ndef test_range_freed_in_different_snapshot():\n    # GIVEN\n    tester = AllocationLifetimeAggregatorTestHarness()\n    loc = Location(\n        tid=1,\n        native_frame_id=4,\n        frame_index=5,\n        native_segment_generation=6,\n    )\n\n    # WHEN\n    tester.add_allocation(**loc.__dict__, allocator=MMAP, address=4096, size=1234)\n    tester.capture_snapshot()\n    tester.add_allocation(**loc.__dict__, allocator=MUNMAP, address=4096, size=1234)\n\n    # THEN\n    (alloc,) = tester.get_allocations()\n    assert alloc.allocator == MMAP\n    assert alloc.native_stack_id == 4\n    assert alloc.stack_id == 5\n    assert alloc.native_segment_generation == 6\n    assert alloc.tid == 1\n    assert alloc.intervals == [Interval(0, 1, 1, 1234)]\n\n\ndef test_range_leaked():\n    # GIVEN\n    tester = AllocationLifetimeAggregatorTestHarness()\n    loc = Location(\n        tid=1,\n        native_frame_id=4,\n        frame_index=5,\n        native_segment_generation=6,\n    )\n\n    # WHEN\n    tester.add_allocation(**loc.__dict__, allocator=MMAP, address=4096, size=1234)\n\n    # THEN\n    (alloc,) = tester.get_allocations()\n    assert alloc.allocator == MMAP\n    assert alloc.native_stack_id == 4\n    assert alloc.stack_id == 5\n    assert alloc.native_segment_generation == 6\n    assert alloc.tid == 1\n    assert alloc.intervals == [Interval(0, None, 1, 1234)]\n\n\ndef test_shrunk_then_leaked_range():\n    # GIVEN\n    tester = AllocationLifetimeAggregatorTestHarness()\n    loc = Location(\n        tid=1,\n        native_frame_id=4,\n        frame_index=5,\n        native_segment_generation=6,\n    )\n\n    # WHEN\n    tester.add_allocation(**loc.__dict__, allocator=MMAP, address=4096, size=1234)\n    tester.add_allocation(**loc.__dict__, allocator=MUNMAP, address=4096, size=1000)\n\n    # THEN\n    (alloc,) = tester.get_allocations()\n    assert alloc.allocator == MMAP\n    assert alloc.native_stack_id == 4\n    assert alloc.stack_id == 5\n    assert alloc.native_segment_generation == 6\n    assert alloc.tid == 1\n    assert alloc.intervals == [Interval(0, None, 1, 234)]\n\n\ndef test_shrunk_then_freed_range():\n    # GIVEN\n    tester = AllocationLifetimeAggregatorTestHarness()\n    loc = Location(\n        tid=1,\n        native_frame_id=4,\n        frame_index=5,\n        native_segment_generation=6,\n    )\n\n    # WHEN\n    tester.add_allocation(**loc.__dict__, allocator=MMAP, address=4096, size=1234)\n    tester.capture_snapshot()\n    tester.add_allocation(**loc.__dict__, allocator=MUNMAP, address=4096, size=1000)\n    tester.capture_snapshot()\n    tester.add_allocation(**loc.__dict__, allocator=MUNMAP, address=4096, size=1234)\n\n    # THEN\n    (alloc,) = tester.get_allocations()\n    assert alloc.allocator == MMAP\n    assert alloc.native_stack_id == 4\n    assert alloc.stack_id == 5\n    assert alloc.native_segment_generation == 6\n    assert alloc.tid == 1\n    assert alloc.intervals == [Interval(0, 1, 0, 1000), Interval(0, 2, 1, 234)]\n\n\ndef test_split_then_leaked_range():\n    # GIVEN\n    tester = AllocationLifetimeAggregatorTestHarness()\n    loc = Location(\n        tid=1,\n        native_frame_id=4,\n        frame_index=5,\n        native_segment_generation=6,\n    )\n\n    # WHEN\n    tester.add_allocation(**loc.__dict__, allocator=MMAP, address=4096, size=1234)\n    tester.capture_snapshot()\n    tester.add_allocation(**loc.__dict__, allocator=MUNMAP, address=5000, size=100)\n\n    # THEN\n    (alloc,) = tester.get_allocations()\n\n    assert alloc.allocator == MMAP\n    assert alloc.native_stack_id == 4\n    assert alloc.stack_id == 5\n    assert alloc.native_segment_generation == 6\n    assert alloc.tid == 1\n    assert alloc.intervals == [Interval(0, 1, 0, 100), Interval(0, None, 1, 1234 - 100)]\n\n\ndef test_split_then_freed_range():\n    # GIVEN\n    tester = AllocationLifetimeAggregatorTestHarness()\n    loc = Location(\n        tid=1,\n        native_frame_id=4,\n        frame_index=5,\n        native_segment_generation=6,\n    )\n\n    # WHEN\n    tester.add_allocation(**loc.__dict__, allocator=MMAP, address=4096, size=1234)\n    tester.capture_snapshot()\n    tester.add_allocation(**loc.__dict__, allocator=MUNMAP, address=5000, size=100)\n    tester.capture_snapshot()\n    tester.add_allocation(**loc.__dict__, allocator=MUNMAP, address=4096, size=904)\n    tester.capture_snapshot()\n    tester.add_allocation(**loc.__dict__, allocator=MUNMAP, address=5100, size=230)\n\n    # THEN\n    (alloc,) = tester.get_allocations()\n    assert alloc.allocator == MMAP\n    assert alloc.native_stack_id == 4\n    assert alloc.stack_id == 5\n    assert alloc.native_segment_generation == 6\n    assert alloc.tid == 1\n    assert alloc.intervals == [\n        Interval(0, 1, 0, 100),\n        Interval(0, 2, 0, 904),\n        Interval(0, 3, 1, 230),\n    ]\n"
  },
  {
    "path": "tests/unit/test_attach.py",
    "content": "from unittest.mock import patch\n\nimport pytest\n\nfrom memray.commands import main\n\n\n@patch(\"memray.commands.attach.debugger_available\")\nclass TestAttachSubCommand:\n    def test_memray_attach_aggregated_without_output_file(\n        self, is_debugger_available_mock, capsys\n    ):\n        # GIVEN\n        is_debugger_available_mock.return_value = True\n\n        # WHEN\n        with pytest.raises(SystemExit):\n            main([\"attach\", \"--aggregate\", \"1234\"])\n\n        captured = capsys.readouterr()\n        print(\"Error\", captured.err)\n        assert \"Can't use aggregated mode without an output file.\" in captured.err\n"
  },
  {
    "path": "tests/unit/test_cli.py",
    "content": "import argparse\nimport sys\nfrom pathlib import Path\nfrom unittest.mock import patch\n\nimport pytest\n\nfrom memray import FileDestination\nfrom memray import SocketDestination\nfrom memray.commands import main\nfrom memray.commands.flamegraph import FlamegraphCommand\nfrom memray.commands.run import RunCommand\nfrom memray.commands.stats import StatsCommand\nfrom memray.commands.summary import SummaryCommand\nfrom memray.commands.table import TableCommand\nfrom memray.commands.transform import TransformCommand\nfrom memray.commands.tree import TreeCommand\n\n\ndef test_no_args_passed(capsys):\n    with pytest.raises(SystemExit):\n        main([])\n\n    captured = capsys.readouterr()\n    assert \"usage:\" in captured.err\n    assert \"error: the following arguments are required:\" in captured.err\n\n\n@patch.object(RunCommand, \"validate_target_file\")\n@patch(\"memray.commands.run.Tracker\")\n@patch(\"memray.commands.run.runpy\")\n@patch(\"memray.commands.run.os.getpid\")\nclass TestRunSubCommand:\n    def test_run_without_arguments(\n        self, getpid_mock, runpy_mock, tracker_mock, validate_mock, capsys\n    ):\n        with pytest.raises(SystemExit):\n            main([\"run\"])\n\n        captured = capsys.readouterr()\n        assert \"usage: memray run [-m module | -c cmd | file] [args]\" in captured.err\n\n    def test_run_default_output(\n        self, getpid_mock, runpy_mock, tracker_mock, validate_mock\n    ):\n        getpid_mock.return_value = 0\n        assert 0 == main([\"run\", \"-m\", \"foobar\"])\n        runpy_mock.run_module.assert_called_with(\n            \"foobar\", run_name=\"__main__\", alter_sys=True\n        )\n        tracker_mock.assert_called_with(\n            destination=FileDestination(\"memray-foobar.0.bin\", overwrite=False),\n            native_traces=False,\n        )\n\n    def test_run_with_native_mode(\n        self, getpid_mock, runpy_mock, tracker_mock, validate_mock\n    ):\n        getpid_mock.return_value = 0\n        assert 0 == main([\"run\", \"--native\", \"-m\", \"foobar\"])\n        runpy_mock.run_module.assert_called_with(\n            \"foobar\", run_name=\"__main__\", alter_sys=True\n        )\n        tracker_mock.assert_called_with(\n            destination=FileDestination(\"memray-foobar.0.bin\", overwrite=False),\n            native_traces=True,\n        )\n\n    def test_run_with_pymalloc_tracing(\n        self, getpid_mock, runpy_mock, tracker_mock, validate_mock\n    ):\n        getpid_mock.return_value = 0\n        assert 0 == main([\"run\", \"--trace-python-allocators\", \"-m\", \"foobar\"])\n        runpy_mock.run_module.assert_called_with(\n            \"foobar\", run_name=\"__main__\", alter_sys=True\n        )\n        tracker_mock.assert_called_with(\n            destination=FileDestination(\"memray-foobar.0.bin\", overwrite=False),\n            native_traces=False,\n            trace_python_allocators=True,\n        )\n\n    def test_run_override_output(\n        self, getpid_mock, runpy_mock, tracker_mock, validate_mock\n    ):\n        assert 0 == main([\"run\", \"--output\", \"my_output\", \"-m\", \"foobar\"])\n        runpy_mock.run_module.assert_called_with(\n            \"foobar\", run_name=\"__main__\", alter_sys=True\n        )\n        tracker_mock.assert_called_with(\n            destination=FileDestination(\"my_output\", overwrite=False),\n            native_traces=False,\n        )\n\n    def test_run_overwrite_output_file(\n        self, getpid_mock, runpy_mock, tracker_mock, validate_mock\n    ):\n        assert 0 == main([\"run\", \"-o\", \"my_output\", \"-f\", \"-m\", \"foobar\"])\n        runpy_mock.run_module.assert_called_with(\n            \"foobar\", run_name=\"__main__\", alter_sys=True\n        )\n        tracker_mock.assert_called_with(\n            destination=FileDestination(\"my_output\", overwrite=True),\n            native_traces=False,\n        )\n\n    def test_run_module(self, getpid_mock, runpy_mock, tracker_mock, validate_mock):\n        assert 0 == main([\"run\", \"-m\", \"foobar\"])\n        runpy_mock.run_module.assert_called_with(\n            \"foobar\", run_name=\"__main__\", alter_sys=True\n        )\n\n    def test_run_cmd_is_validated(\n        self, getpid_mock, runpy_mock, tracker_mock, validate_mock\n    ):\n        with patch.object(RunCommand, \"validate_target_file\"):\n            assert 0 == main([\"run\", \"-c\", \"x = [i for i in range(10)]\"])\n            with pytest.raises(SyntaxError):\n                main([\"run\", \"-c\", \"[i for i in range(10)\"])\n\n    def test_run_cmd(self, getpid_mock, runpy_mock, tracker_mock, validate_mock):\n        with patch(\"memray.commands.run.exec\") as mock_exec:\n            assert 0 == main([\"run\", \"-c\", \"x = 10; y = abs(-10)\"])\n            assert not runpy_mock.called\n            mock_exec.assert_called_with(\n                \"x = 10; y = abs(-10)\", {\"__name__\": \"__main__\"}\n            )\n\n    def test_run_file(self, getpid_mock, runpy_mock, tracker_mock, validate_mock):\n        with patch.object(RunCommand, \"validate_target_file\"):\n            assert 0 == main([\"run\", \"foobar.py\", \"arg1\", \"arg2\"])\n        runpy_mock.run_path.assert_called_with(\"foobar.py\", run_name=\"__main__\")\n\n    def test_run_relative_file(\n        self, getpid_mock, runpy_mock, tracker_mock, validate_mock\n    ):\n        getpid_mock.return_value = 0\n        with patch.object(RunCommand, \"validate_target_file\"):\n            assert 0 == main([\"run\", \"./directory/foobar.py\", \"arg1\", \"arg2\"])\n        runpy_mock.run_path.assert_called_with(\n            \"./directory/foobar.py\",\n            run_name=\"__main__\",\n        )\n        tracker_mock.assert_called_with(\n            destination=FileDestination(\n                \"./directory/memray-foobar.py.0.bin\", overwrite=False\n            ),\n            native_traces=False,\n        )\n\n    @patch(\"memray.commands.run.subprocess.Popen\")\n    @patch(\"memray.commands.run.LiveCommand\")\n    def test_run_with_live(\n        self,\n        live_command_mock,\n        popen_mock,\n        getpid_mock,\n        runpy_mock,\n        tracker_mock,\n        validate_mock,\n    ):\n        getpid_mock.return_value = 0\n        popen_mock().__enter__().returncode = 0\n        with patch(\"memray.commands.run._get_free_port\", return_value=1234):\n            assert 0 == main([\"run\", \"--live\", \"./directory/foobar.py\", \"arg1\", \"arg2\"])\n        popen_mock.assert_called_with(\n            [\n                sys.executable,\n                \"-c\",\n                \"from memray.commands.run import _child_process;\"\n                \"_child_process(1234,False,False,False,False,False,\"\n                \"'./directory/foobar.py',['arg1', 'arg2'])\",\n            ],\n            stderr=-1,\n            stdout=-3,\n            text=True,\n        )\n        live_command_mock().start_live_interface.assert_called_with(\n            1234,\n            cmdline_override=\"./directory/foobar.py arg1 arg2\",\n        )\n\n    @patch(\"memray.commands.run.subprocess.Popen\")\n    @patch(\"memray.commands.run.LiveCommand\")\n    def test_run_with_live_and_trace_python_allocators(\n        self,\n        live_command_mock,\n        popen_mock,\n        getpid_mock,\n        runpy_mock,\n        tracker_mock,\n        validate_mock,\n    ):\n        getpid_mock.return_value = 0\n        popen_mock().__enter__().returncode = 0\n        with patch(\"memray.commands.run._get_free_port\", return_value=1234):\n            assert 0 == main(\n                [\n                    \"run\",\n                    \"--live\",\n                    \"--trace-python-allocators\",\n                    \"./directory/foobar.py\",\n                    \"arg1\",\n                    \"arg2\",\n                ]\n            )\n        popen_mock.assert_called_with(\n            [\n                sys.executable,\n                \"-c\",\n                \"from memray.commands.run import _child_process;\"\n                \"_child_process(1234,False,True,False,False,False,\"\n                \"'./directory/foobar.py',['arg1', 'arg2'])\",\n            ],\n            stderr=-1,\n            stdout=-3,\n            text=True,\n        )\n        live_command_mock().start_live_interface.assert_called_with(\n            1234,\n            cmdline_override=\"./directory/foobar.py arg1 arg2\",\n        )\n\n    def test_run_with_live_remote(\n        self, getpid_mock, runpy_mock, tracker_mock, validate_mock\n    ):\n        getpid_mock.return_value = 0\n        with patch(\"memray.commands.run._get_free_port\", return_value=1234):\n            assert 0 == main(\n                [\"run\", \"--live-remote\", \"./directory/foobar.py\", \"arg1\", \"arg2\"]\n            )\n        runpy_mock.run_path.assert_called_with(\n            \"./directory/foobar.py\",\n            run_name=\"__main__\",\n        )\n        tracker_mock.assert_called_with(\n            destination=SocketDestination(server_port=1234, address=\"127.0.0.1\"),\n            native_traces=False,\n        )\n\n    def test_run_with_live_remote_and_live_port(\n        self, getpid_mock, runpy_mock, tracker_mock, validate_mock\n    ):\n        getpid_mock.return_value = 0\n        assert 0 == main(\n            [\n                \"run\",\n                \"--live-remote\",\n                \"--live-port=1111\",\n                \"./directory/foobar.py\",\n                \"arg1\",\n                \"arg2\",\n            ]\n        )\n        runpy_mock.run_path.assert_called_with(\n            \"./directory/foobar.py\",\n            run_name=\"__main__\",\n        )\n        tracker_mock.assert_called_with(\n            destination=SocketDestination(server_port=1111, address=\"127.0.0.1\"),\n            native_traces=False,\n        )\n\n    def test_run_with_live_port_but_not_live_remote(\n        self, getpid_mock, runpy_mock, tracker_mock, validate_mock, capsys\n    ):\n        with pytest.raises(SystemExit):\n            main([\"run\", \"--live-port\", \"1234\", \"./directory/foobar.py\"])\n\n        captured = capsys.readouterr()\n        assert \"The --live-port argument requires --live-remote\" in captured.err\n\n    def test_run_with_follow_fork(\n        self,\n        getpid_mock,\n        runpy_mock,\n        tracker_mock,\n        validate_mock,\n    ):\n        getpid_mock.return_value = 0\n        assert 0 == main([\"run\", \"--follow-fork\", \"-m\", \"foobar\"])\n        runpy_mock.run_module.assert_called_with(\n            \"foobar\", run_name=\"__main__\", alter_sys=True\n        )\n        tracker_mock.assert_called_with(\n            destination=FileDestination(\"memray-foobar.0.bin\", overwrite=False),\n            native_traces=False,\n            follow_fork=True,\n        )\n\n    def test_run_with_follow_fork_and_live_mode(\n        self, getpid_mock, runpy_mock, tracker_mock, validate_mock, capsys\n    ):\n        with pytest.raises(SystemExit):\n            main([\"run\", \"--live\", \"--follow-fork\", \"./directory/foobar.py\"])\n\n        captured = capsys.readouterr()\n        assert \"--follow-fork cannot be used with\" in captured.err\n\n    def test_run_with_follow_fork_and_live_remote_mode(\n        self, getpid_mock, runpy_mock, tracker_mock, validate_mock, capsys\n    ):\n        with pytest.raises(SystemExit):\n            main([\"run\", \"--live-remote\", \"--follow-fork\", \"./directory/foobar.py\"])\n\n        captured = capsys.readouterr()\n        assert \"--follow-fork cannot be used with\" in captured.err\n\n    def test_run_with_trace_python_allocators_and_live_remote_mode(\n        self, getpid_mock, runpy_mock, tracker_mock, validate_mock, capsys\n    ):\n        getpid_mock.return_value = 0\n        with patch(\"memray.commands.run._get_free_port\", return_value=1234):\n            assert 0 == main(\n                [\n                    \"run\",\n                    \"--live-remote\",\n                    \"--trace-python-allocators\",\n                    \"./directory/foobar.py\",\n                    \"arg1\",\n                    \"arg2\",\n                ]\n            )\n        runpy_mock.run_path.assert_called_with(\n            \"./directory/foobar.py\",\n            run_name=\"__main__\",\n        )\n        tracker_mock.assert_called_with(\n            destination=SocketDestination(server_port=1234, address=\"127.0.0.1\"),\n            native_traces=False,\n            trace_python_allocators=True,\n        )\n\n\nclass TestFlamegraphSubCommand:\n    @staticmethod\n    def get_prepared_parser():\n        parser = argparse.ArgumentParser()\n        command = FlamegraphCommand()\n        command.prepare_parser(parser)\n\n        return command, parser\n\n    def test_parser_rejects_no_arguments(self):\n        # GIVEN\n        _, parser = self.get_prepared_parser()\n\n        # WHEN / THEN\n        with pytest.raises(SystemExit):\n            parser.parse_args([])\n\n    def test_parser_rejects_when_no_results_provided(self):\n        # GIVEN\n        _, parser = self.get_prepared_parser()\n\n        # WHEN / THEN\n        with pytest.raises(SystemExit):\n            parser.parse_args([\"--output\", \"output.html\"])\n\n    def test_parser_accepts_single_argument(self):\n        # GIVEN\n        _, parser = self.get_prepared_parser()\n\n        # WHEN\n        namespace = parser.parse_args([\"results.txt\"])\n\n        # THEN\n        assert namespace.results == \"results.txt\"\n        assert namespace.output is None\n        assert namespace.show_memory_leaks is False\n\n    def test_parser_accepts_short_form_output_1(self):\n        # GIVEN\n        _, parser = self.get_prepared_parser()\n\n        # WHEN\n        namespace = parser.parse_args([\"results.txt\", \"-o\", \"output.html\"])\n\n        # THEN\n        assert namespace.results == \"results.txt\"\n        assert namespace.output == \"output.html\"\n        assert namespace.show_memory_leaks is False\n\n    def test_parser_accepts_short_form_output_2(self):\n        # GIVEN\n        _, parser = self.get_prepared_parser()\n\n        # WHEN\n        namespace = parser.parse_args([\"-o\", \"output.html\", \"results.txt\"])\n\n        # THEN\n        assert namespace.results == \"results.txt\"\n        assert namespace.output == \"output.html\"\n        assert namespace.show_memory_leaks is False\n\n    def test_parser_accepts_long_form_output_1(self):\n        # GIVEN\n        _, parser = self.get_prepared_parser()\n\n        # WHEN\n        namespace = parser.parse_args([\"results.txt\", \"--output\", \"output.html\"])\n\n        # THEN\n        assert namespace.results == \"results.txt\"\n        assert namespace.output == \"output.html\"\n        assert namespace.show_memory_leaks is False\n\n    def test_parser_accepts_long_form_output_2(self):\n        # GIVEN\n        _, parser = self.get_prepared_parser()\n\n        # WHEN\n        namespace = parser.parse_args([\"--output\", \"output.html\", \"results.txt\"])\n\n        # THEN\n        assert namespace.results == \"results.txt\"\n        assert namespace.output == \"output.html\"\n        assert namespace.show_memory_leaks is False\n\n    def test_parser_takes_memory_leaks_as_a_flag(self):\n        # GIVEN\n        _, parser = self.get_prepared_parser()\n\n        # WHEN\n        namespace = parser.parse_args(\n            [\"results.txt\", \"--leaks\", \"--output\", \"output.html\"]\n        )\n\n        # THEN\n        assert namespace.results == \"results.txt\"\n        assert namespace.output == \"output.html\"\n        assert namespace.show_memory_leaks is True\n\n    def test_parser_takes_force_flag(self):\n        # GIVEN\n        _, parser = self.get_prepared_parser()\n\n        # WHEN\n        namespace = parser.parse_args(\n            [\"results.txt\", \"--force\", \"--output\", \"output.html\"]\n        )\n\n        # THEN\n        assert namespace.results == \"results.txt\"\n        assert namespace.output == \"output.html\"\n        assert namespace.force is True\n\n\n@pytest.mark.parametrize(\n    \"input, expected, factory\",\n    (\n        (\"result.bin\", \"memray-flamegraph-result.html\", FlamegraphCommand),\n        (\"/tmp/result.bin\", \"/tmp/memray-flamegraph-result.html\", FlamegraphCommand),\n        (\"../result.bin\", \"../memray-flamegraph-result.html\", FlamegraphCommand),\n        (\n            \"memray-json.tool.0.bin\",\n            \"memray-flamegraph-json.tool.0.html\",\n            FlamegraphCommand,\n        ),\n        (\n            \"/tmp/memray-json.tool.0.bin\",\n            \"/tmp/memray-flamegraph-json.tool.0.html\",\n            FlamegraphCommand,\n        ),\n        (\n            \"../memray-json.tool.0.bin\",\n            \"../memray-flamegraph-json.tool.0.html\",\n            FlamegraphCommand,\n        ),\n        (\"memray-json.tool.0.bin\", \"memray-table-json.tool.0.html\", TableCommand),\n        (\"my-result.bin\", \"memray-table-my-result.html\", TableCommand),\n        (\"../my-result.bin\", \"../memray-table-my-result.html\", TableCommand),\n    ),\n)\ndef test_determine_output(input, expected, factory):\n    # GIVEN\n    command = factory()\n\n    # WHEN/THEN\n    assert command.determine_output_filename(Path(input)) == Path(expected)\n\n\nclass TestTreeSubCommand:\n    @staticmethod\n    def get_prepared_parser():\n        parser = argparse.ArgumentParser()\n        command = TreeCommand()\n        command.prepare_parser(parser)\n\n        return command, parser\n\n    def test_parser_rejects_no_arguments(self):\n        # GIVEN\n        _, parser = self.get_prepared_parser()\n\n        # WHEN / THEN\n        with pytest.raises(SystemExit):\n            parser.parse_args([])\n\n    def test_parser_rejects_when_no_results_provided(self):\n        # GIVEN\n        _, parser = self.get_prepared_parser()\n\n        # WHEN / THEN\n        with pytest.raises(SystemExit):\n            parser.parse_args([\"--biggest_allocs\", \"5\"])\n\n    def test_parser_accepts_single_argument(self):\n        # GIVEN\n        _, parser = self.get_prepared_parser()\n\n        # WHEN\n        namespace = parser.parse_args([\"results.txt\"])\n\n        # THEN\n        assert namespace.results == \"results.txt\"\n        assert namespace.biggest_allocs == 200\n\n    def test_parser_acceps_biggest_allocs_short_form(self):\n        # GIVEN\n        _, parser = self.get_prepared_parser()\n\n        # WHEN\n        namespace = parser.parse_args([\"results.txt\", \"-b\", \"5\"])\n\n        # THEN\n        assert namespace.results == \"results.txt\"\n        assert namespace.biggest_allocs == 5\n\n    def test_parser_acceps_biggest_allocs_long_form(self):\n        # GIVEN\n        _, parser = self.get_prepared_parser()\n\n        # WHEN\n        namespace = parser.parse_args([\"results.txt\", \"--biggest-allocs\", \"5\"])\n\n        # THEN\n        assert namespace.results == \"results.txt\"\n        assert namespace.biggest_allocs == 5\n\n\nclass TestTableSubCommand:\n    @staticmethod\n    def get_prepared_parser():\n        parser = argparse.ArgumentParser()\n        command = TableCommand()\n        command.prepare_parser(parser)\n\n        return command, parser\n\n    def test_parser_rejects_no_arguments(self):\n        # GIVEN\n        _, parser = self.get_prepared_parser()\n\n        # WHEN / THEN\n        with pytest.raises(SystemExit):\n            parser.parse_args([])\n\n    def test_parser_rejects_when_no_results_provided(self):\n        # GIVEN\n        _, parser = self.get_prepared_parser()\n\n        # WHEN / THEN\n        with pytest.raises(SystemExit):\n            parser.parse_args([\"--leaks\"])\n\n    def test_parser_accepts_single_argument(self):\n        # GIVEN\n        _, parser = self.get_prepared_parser()\n\n        # WHEN\n        namespace = parser.parse_args([\"results.txt\"])\n\n        # THEN\n        assert namespace.results == \"results.txt\"\n        assert namespace.show_memory_leaks is False\n\n    def test_parser_accepts_short_form_output_1(self):\n        # GIVEN\n        _, parser = self.get_prepared_parser()\n\n        # WHEN\n        namespace = parser.parse_args([\"results.txt\", \"-o\", \"output.html\"])\n\n        # THEN\n        assert namespace.results == \"results.txt\"\n        assert namespace.output == \"output.html\"\n        assert namespace.show_memory_leaks is False\n\n    def test_parser_accepts_short_form_output_2(self):\n        # GIVEN\n        _, parser = self.get_prepared_parser()\n\n        # WHEN\n        namespace = parser.parse_args([\"-o\", \"output.html\", \"results.txt\"])\n\n        # THEN\n        assert namespace.results == \"results.txt\"\n        assert namespace.output == \"output.html\"\n        assert namespace.show_memory_leaks is False\n\n    def test_parser_accepts_long_form_output_1(self):\n        # GIVEN\n        _, parser = self.get_prepared_parser()\n\n        # WHEN\n        namespace = parser.parse_args([\"results.txt\", \"--output\", \"output.html\"])\n\n        # THEN\n        assert namespace.results == \"results.txt\"\n        assert namespace.output == \"output.html\"\n        assert namespace.show_memory_leaks is False\n\n    def test_parser_accepts_long_form_output_2(self):\n        # GIVEN\n        _, parser = self.get_prepared_parser()\n\n        # WHEN\n        namespace = parser.parse_args([\"--output\", \"output.html\", \"results.txt\"])\n\n        # THEN\n        assert namespace.results == \"results.txt\"\n        assert namespace.output == \"output.html\"\n        assert namespace.show_memory_leaks is False\n\n    def test_parser_takes_memory_leaks_as_a_flag(self):\n        # GIVEN\n        _, parser = self.get_prepared_parser()\n\n        # WHEN\n        namespace = parser.parse_args(\n            [\"results.txt\", \"--leaks\", \"--output\", \"output.html\"]\n        )\n\n        # THEN\n        assert namespace.results == \"results.txt\"\n        assert namespace.output == \"output.html\"\n        assert namespace.show_memory_leaks is True\n\n    def test_parser_takes_force_flag(self):\n        # GIVEN\n        _, parser = self.get_prepared_parser()\n\n        # WHEN\n        namespace = parser.parse_args(\n            [\"results.txt\", \"--force\", \"--output\", \"output.html\"]\n        )\n\n        # THEN\n        assert namespace.results == \"results.txt\"\n        assert namespace.output == \"output.html\"\n        assert namespace.force is True\n\n\nclass TestSummarySubCommand:\n    @staticmethod\n    def get_prepared_parser():\n        parser = argparse.ArgumentParser()\n        command = SummaryCommand()\n        command.prepare_parser(parser)\n\n        return command, parser\n\n    def test_parser_rejects_no_arguments(self):\n        # GIVEN\n        _, parser = self.get_prepared_parser()\n\n        # WHEN / THEN\n        with pytest.raises(SystemExit):\n            parser.parse_args([])\n\n    def test_parser_accepts_single_argument(self):\n        # GIVEN\n        _, parser = self.get_prepared_parser()\n\n        # WHEN\n        namespace = parser.parse_args([\"results.txt\"])\n\n        # THEN\n        assert namespace.results == \"results.txt\"\n        assert namespace.sort_column == 1\n        assert namespace.max_rows is None\n\n    def test_parser_accepts_sort_column_long_form(self):\n        # GIVEN\n        _, parser = self.get_prepared_parser()\n\n        # WHEN\n        namespace = parser.parse_args([\"results.txt\", \"--sort-column\", \"2\"])\n\n        # THEN\n        assert namespace.results == \"results.txt\"\n        assert namespace.sort_column == 2\n        assert namespace.max_rows is None\n\n    def test_parser_accepts_sort_column_sort_form(self):\n        # GIVEN\n        _, parser = self.get_prepared_parser()\n\n        # WHEN\n        namespace = parser.parse_args([\"results.txt\", \"-s\", \"2\"])\n\n        # THEN\n        assert namespace.results == \"results.txt\"\n        assert namespace.sort_column == 2\n        assert namespace.max_rows is None\n\n    @pytest.mark.parametrize(\"column\", [0, 12])\n    def test_parser_rejects_sort_column_incorrect_values(self, column):\n        # GIVEN\n        command, parser = self.get_prepared_parser()\n\n        # WHEN\n        args = parser.parse_args([\"results.txt\", \"--sort-column\", str(column)])\n        # THEN\n        with pytest.raises(SystemExit):\n            command.run(args, parser)\n\n    def test_parser_accepts_max_rows_long_form(self):\n        # GIVEN\n        _, parser = self.get_prepared_parser()\n\n        # WHEN\n        namespace = parser.parse_args([\"results.txt\", \"--max-rows\", \"2\"])\n\n        # THEN\n        assert namespace.results == \"results.txt\"\n        assert namespace.sort_column == 1\n        assert namespace.max_rows == 2\n\n    def test_parser_accepts_max_rows_sort_form(self):\n        # GIVEN\n        _, parser = self.get_prepared_parser()\n\n        # WHEN\n        namespace = parser.parse_args([\"results.txt\", \"-r\", \"2\"])\n\n        # THEN\n        assert namespace.results == \"results.txt\"\n        assert namespace.sort_column == 1\n        assert namespace.max_rows == 2\n\n\nclass TestStatsSubCommand:\n    @staticmethod\n    def get_prepared_parser():\n        parser = argparse.ArgumentParser()\n        command = StatsCommand()\n        command.prepare_parser(parser)\n\n        return command, parser\n\n    def test_parser_rejects_no_arguments(self):\n        # GIVEN\n        _, parser = self.get_prepared_parser()\n\n        # WHEN / THEN\n        with pytest.raises(SystemExit):\n            parser.parse_args([])\n\n    def test_parser_accepts_single_argument(self):\n        # GIVEN\n        _, parser = self.get_prepared_parser()\n\n        # WHEN\n        namespace = parser.parse_args([\"results.txt\"])\n\n        # THEN\n        assert namespace.results == \"results.txt\"\n        assert namespace.num_largest == 5\n\n    def test_parser_accepts_valid_num_largest_allocators(self):\n        # GIVEN\n        _, parser = self.get_prepared_parser()\n\n        # WHEN\n        namespace = parser.parse_args([\"-n\", \"3\", \"results.txt\"])\n\n        # THEN\n        assert namespace.results == \"results.txt\"\n        assert namespace.num_largest == 3\n\n    def test_parser_rejects_invalid_num_largest_allocators(self):\n        # GIVEN\n        _, parser = self.get_prepared_parser()\n\n        # WHEN / THEN\n        with pytest.raises(SystemExit):\n            parser.parse_args([\"-n\", \"-1\", \"results.txt\"])\n\n\nclass TestTransformSubCommand:\n    @staticmethod\n    def get_prepared_parser():\n        parser = argparse.ArgumentParser()\n        command = TransformCommand()\n        command.prepare_parser(parser)\n\n        return command, parser\n\n    def test_parser_rejects_no_arguments(self):\n        # GIVEN\n        _, parser = self.get_prepared_parser()\n\n        # WHEN / THEN\n        with pytest.raises(SystemExit):\n            parser.parse_args([])\n\n    def test_parser_rejects_when_no_results_provided(self):\n        # GIVEN\n        _, parser = self.get_prepared_parser()\n\n        # WHEN / THEN\n        with pytest.raises(SystemExit):\n            parser.parse_args([\"gprof2dot\", \"--leaks\"])\n\n    def test_parser_invalid_format(self):\n        # GIVEN\n        _, parser = self.get_prepared_parser()\n\n        # WHEN / THEN\n        with pytest.raises(SystemExit):\n            parser.parse_args([\"blech\"])\n\n    def test_parser_accepts_single_argument_with_format(self):\n        # GIVEN\n        _, parser = self.get_prepared_parser()\n\n        # WHEN\n        namespace = parser.parse_args([\"gprof2dot\", \"results.txt\"])\n\n        # THEN\n        assert namespace.results == \"results.txt\"\n        assert namespace.format == \"gprof2dot\"\n        assert namespace.show_memory_leaks is False\n\n    def test_parser_accepts_short_form_output_1(self):\n        # GIVEN\n        _, parser = self.get_prepared_parser()\n\n        # WHEN\n        namespace = parser.parse_args([\"gprof2dot\", \"results.txt\", \"-o\", \"output.html\"])\n\n        # THEN\n        assert namespace.results == \"results.txt\"\n        assert namespace.output == \"output.html\"\n        assert namespace.show_memory_leaks is False\n        assert namespace.format == \"gprof2dot\"\n\n    def test_parser_accepts_short_form_output_2(self):\n        # GIVEN\n        _, parser = self.get_prepared_parser()\n\n        # WHEN\n        namespace = parser.parse_args([\"gprof2dot\", \"-o\", \"output.html\", \"results.txt\"])\n\n        # THEN\n        assert namespace.results == \"results.txt\"\n        assert namespace.output == \"output.html\"\n        assert namespace.show_memory_leaks is False\n        assert namespace.format == \"gprof2dot\"\n\n    def test_parser_accepts_long_form_output_1(self):\n        # GIVEN\n        _, parser = self.get_prepared_parser()\n\n        # WHEN\n        namespace = parser.parse_args(\n            [\"gprof2dot\", \"results.txt\", \"--output\", \"output.html\"]\n        )\n\n        # THEN\n        assert namespace.results == \"results.txt\"\n        assert namespace.output == \"output.html\"\n        assert namespace.show_memory_leaks is False\n        assert namespace.format == \"gprof2dot\"\n\n    def test_parser_accepts_long_form_output_2(self):\n        # GIVEN\n        _, parser = self.get_prepared_parser()\n\n        # WHEN\n        namespace = parser.parse_args(\n            [\"gprof2dot\", \"--output\", \"output.html\", \"results.txt\"]\n        )\n\n        # THEN\n        assert namespace.results == \"results.txt\"\n        assert namespace.output == \"output.html\"\n        assert namespace.show_memory_leaks is False\n        assert namespace.format == \"gprof2dot\"\n\n    def test_parser_takes_memory_leaks_as_a_flag(self):\n        # GIVEN\n        _, parser = self.get_prepared_parser()\n\n        # WHEN\n        namespace = parser.parse_args(\n            [\"gprof2dot\", \"results.txt\", \"--leaks\", \"--output\", \"output.html\"]\n        )\n\n        # THEN\n        assert namespace.results == \"results.txt\"\n        assert namespace.output == \"output.html\"\n        assert namespace.show_memory_leaks is True\n        assert namespace.format == \"gprof2dot\"\n\n    def test_parser_takes_force_flag(self):\n        # GIVEN\n        _, parser = self.get_prepared_parser()\n\n        # WHEN\n        namespace = parser.parse_args(\n            [\"gprof2dot\", \"results.txt\", \"--force\", \"--output\", \"output.html\"]\n        )\n\n        # THEN\n        assert namespace.results == \"results.txt\"\n        assert namespace.output == \"output.html\"\n        assert namespace.force is True\n        assert namespace.format == \"gprof2dot\"\n"
  },
  {
    "path": "tests/unit/test_flamegraph_reporter.py",
    "content": "import sys\n\nfrom memray import AllocatorType\nfrom memray import FileReader\nfrom memray import Tracker\nfrom memray._test import MemoryAllocator\nfrom memray.reporters.flamegraph import MAX_STACKS\nfrom memray.reporters.flamegraph import FlameGraphReporter\nfrom tests.utils import MockAllocationRecord\nfrom tests.utils import filter_relevant_allocations\n\n\ndef packed_data_to_tree(packed_data):\n    \"\"\"Python implementation of packedDataToTree in flamegraph.js\"\"\"\n    strings, nodes, unique_threads = (\n        packed_data[\"strings\"],\n        packed_data[\"nodes\"],\n        packed_data[\"unique_threads\"],\n    )\n\n    if not len(nodes):\n        return {}\n\n    node_objects = [\n        {\n            \"name\": strings[nodes[\"name\"][i]],\n            \"location\": [\n                strings[nodes[\"function\"][i]],\n                strings[nodes[\"filename\"][i]],\n                nodes[\"lineno\"][i],\n            ],\n            \"value\": nodes[\"value\"][i],\n            \"children\": nodes[\"children\"][i],\n            \"n_allocations\": nodes[\"n_allocations\"][i],\n            \"thread_id\": strings[nodes[\"thread_id\"][i]],\n            \"interesting\": nodes[\"interesting\"][i] != 0,\n            \"import_system\": nodes[\"import_system\"][i] != 0,\n        }\n        for i in range(len(nodes[\"name\"]))\n    ]\n\n    for node in node_objects:\n        node[\"children\"] = [node_objects[idx] for idx in node[\"children\"]]\n\n    root = node_objects[0]\n    root[\"unique_threads\"] = [strings[tid] for tid in unique_threads]\n    return root\n\n\ndef get_packed_trees(packed_data):\n    strings, nodes, inverted_no_imports_nodes, unique_threads = (\n        packed_data[\"strings\"],\n        packed_data[\"nodes\"],\n        packed_data[\"inverted_no_imports_nodes\"],\n        packed_data[\"unique_threads\"],\n    )\n\n    root = packed_data_to_tree(\n        {\"nodes\": nodes, \"strings\": strings, \"unique_threads\": unique_threads}\n    )\n    root_inverted_import_system = packed_data_to_tree(\n        {\n            \"nodes\": inverted_no_imports_nodes,\n            \"strings\": strings,\n            \"unique_threads\": unique_threads,\n        }\n    )\n\n    return [root, root_inverted_import_system]\n\n\nclass TestFlameGraphReporter:\n    def test_works_with_no_allocations(self):\n        reporter = FlameGraphReporter.from_snapshot(\n            [], memory_records=[], native_traces=False\n        )\n        tree, inverted_import_system_tree = get_packed_trees(reporter.data)\n        assert inverted_import_system_tree == {}\n        assert tree[\"name\"] == \"<root>\"\n        assert tree[\"value\"] == 0\n        assert tree[\"children\"] == []\n\n    def test_inverted_works_with_no_allocations(self):\n        reporter = FlameGraphReporter.from_snapshot(\n            [], memory_records=[], native_traces=False, inverted=True\n        )\n        tree, inverted_import_system_tree = get_packed_trees(reporter.data)\n        assert tree[\"name\"] == \"<root>\"\n        assert tree[\"value\"] == 0\n        assert tree[\"children\"] == []\n        assert tree == inverted_import_system_tree\n\n    def test_works_with_single_call(self):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"me\", \"fun.py\", 12),\n                    (\"parent\", \"fun.py\", 8),\n                    (\"grandparent\", \"fun.py\", 4),\n                ],\n            ),\n        ]\n\n        # WHEN\n        reporter = FlameGraphReporter.from_snapshot(\n            peak_allocations, memory_records=[], native_traces=False\n        )\n\n        tree, inverted_import_system_tree = get_packed_trees(reporter.data)\n\n        # THEN\n        assert inverted_import_system_tree == {}\n\n        assert {\n            \"name\": \"<root>\",\n            \"thread_id\": \"0x0\",\n            \"location\": [\"&lt;tracker&gt;\", \"<b>memray</b>\", 0],\n            \"value\": 1024,\n            \"n_allocations\": 1,\n            \"unique_threads\": [\"0x1\"],\n            \"interesting\": True,\n            \"import_system\": False,\n            \"children\": [\n                {\n                    \"name\": \"grandparent at fun.py:4\",\n                    \"thread_id\": \"0x1\",\n                    \"location\": [\"grandparent\", \"fun.py\", 4],\n                    \"value\": 1024,\n                    \"n_allocations\": 1,\n                    \"interesting\": True,\n                    \"import_system\": False,\n                    \"children\": [\n                        {\n                            \"name\": \"parent at fun.py:8\",\n                            \"thread_id\": \"0x1\",\n                            \"location\": [\"parent\", \"fun.py\", 8],\n                            \"value\": 1024,\n                            \"n_allocations\": 1,\n                            \"interesting\": True,\n                            \"import_system\": False,\n                            \"children\": [\n                                {\n                                    \"name\": \"me at fun.py:12\",\n                                    \"thread_id\": \"0x1\",\n                                    \"location\": [\"me\", \"fun.py\", 12],\n                                    \"value\": 1024,\n                                    \"children\": [],\n                                    \"interesting\": True,\n                                    \"import_system\": False,\n                                    \"n_allocations\": 1,\n                                }\n                            ],\n                        }\n                    ],\n                }\n            ],\n        } == tree\n\n    def test_inverted_works_with_single_call(self):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"me\", \"fun.py\", 12),\n                    (\"parent\", \"fun.py\", 8),\n                    (\"grandparent\", \"fun.py\", 4),\n                ],\n            ),\n        ]\n\n        # WHEN\n        reporter = FlameGraphReporter.from_snapshot(\n            peak_allocations, memory_records=[], native_traces=False, inverted=True\n        )\n\n        tree, inverted_import_system_tree = get_packed_trees(reporter.data)\n\n        # THEN\n        assert {\n            \"name\": \"<root>\",\n            \"thread_id\": \"0x0\",\n            \"location\": [\"&lt;tracker&gt;\", \"<b>memray</b>\", 0],\n            \"value\": 1024,\n            \"n_allocations\": 1,\n            \"unique_threads\": [\"0x1\"],\n            \"interesting\": True,\n            \"import_system\": False,\n            \"children\": [\n                {\n                    \"name\": \"me at fun.py:12\",\n                    \"thread_id\": \"0x1\",\n                    \"location\": [\"me\", \"fun.py\", 12],\n                    \"value\": 1024,\n                    \"interesting\": True,\n                    \"import_system\": False,\n                    \"n_allocations\": 1,\n                    \"children\": [\n                        {\n                            \"name\": \"parent at fun.py:8\",\n                            \"thread_id\": \"0x1\",\n                            \"location\": [\"parent\", \"fun.py\", 8],\n                            \"value\": 1024,\n                            \"n_allocations\": 1,\n                            \"interesting\": True,\n                            \"import_system\": False,\n                            \"children\": [\n                                {\n                                    \"name\": \"grandparent at fun.py:4\",\n                                    \"thread_id\": \"0x1\",\n                                    \"location\": [\"grandparent\", \"fun.py\", 4],\n                                    \"value\": 1024,\n                                    \"n_allocations\": 1,\n                                    \"interesting\": True,\n                                    \"import_system\": False,\n                                    \"children\": [],\n                                }\n                            ],\n                        }\n                    ],\n                }\n            ],\n        } == tree\n\n        assert tree == inverted_import_system_tree\n\n    def test_uses_hybrid_stack_for_native_traces(self):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _hybrid_stack=[\n                    (\"me\", \"fun.py\", 12),\n                    (\"parent\", \"fun.pyx\", 8),\n                    (\"grandparent\", \"fun.c\", 4),\n                ],\n            ),\n        ]\n\n        # WHEN\n        reporter = FlameGraphReporter.from_snapshot(\n            peak_allocations, memory_records=[], native_traces=True\n        )\n\n        tree, inverted_import_system_tree = get_packed_trees(reporter.data)\n\n        # THEN\n        assert inverted_import_system_tree == {}\n        assert {\n            \"name\": \"<root>\",\n            \"thread_id\": \"0x0\",\n            \"location\": [\"&lt;tracker&gt;\", \"<b>memray</b>\", 0],\n            \"value\": 1024,\n            \"n_allocations\": 1,\n            \"unique_threads\": [\"0x1\"],\n            \"interesting\": True,\n            \"import_system\": False,\n            \"children\": [\n                {\n                    \"name\": \"grandparent at fun.c:4\",\n                    \"thread_id\": \"0x1\",\n                    \"location\": [\"grandparent\", \"fun.c\", 4],\n                    \"value\": 1024,\n                    \"n_allocations\": 1,\n                    \"interesting\": True,\n                    \"import_system\": False,\n                    \"children\": [\n                        {\n                            \"name\": \"parent at fun.pyx:8\",\n                            \"thread_id\": \"0x1\",\n                            \"location\": [\"parent\", \"fun.pyx\", 8],\n                            \"value\": 1024,\n                            \"n_allocations\": 1,\n                            \"interesting\": True,\n                            \"import_system\": False,\n                            \"children\": [\n                                {\n                                    \"name\": \"me at fun.py:12\",\n                                    \"thread_id\": \"0x1\",\n                                    \"location\": [\"me\", \"fun.py\", 12],\n                                    \"value\": 1024,\n                                    \"children\": [],\n                                    \"interesting\": True,\n                                    \"import_system\": False,\n                                    \"n_allocations\": 1,\n                                }\n                            ],\n                        }\n                    ],\n                }\n            ],\n        } == tree\n\n    def test_inverted_uses_hybrid_stack_for_native_traces(self):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _hybrid_stack=[\n                    (\"me\", \"fun.py\", 12),\n                    (\"parent\", \"fun.pyx\", 8),\n                    (\"grandparent\", \"fun.c\", 4),\n                ],\n            ),\n        ]\n\n        # WHEN\n        reporter = FlameGraphReporter.from_snapshot(\n            peak_allocations, memory_records=[], native_traces=True, inverted=True\n        )\n\n        tree, inverted_import_system_tree = get_packed_trees(reporter.data)\n\n        # THEN\n        assert {\n            \"name\": \"<root>\",\n            \"thread_id\": \"0x0\",\n            \"location\": [\"&lt;tracker&gt;\", \"<b>memray</b>\", 0],\n            \"value\": 1024,\n            \"n_allocations\": 1,\n            \"unique_threads\": [\"0x1\"],\n            \"interesting\": True,\n            \"import_system\": False,\n            \"children\": [\n                {\n                    \"name\": \"me at fun.py:12\",\n                    \"thread_id\": \"0x1\",\n                    \"location\": [\"me\", \"fun.py\", 12],\n                    \"value\": 1024,\n                    \"interesting\": True,\n                    \"import_system\": False,\n                    \"n_allocations\": 1,\n                    \"children\": [\n                        {\n                            \"name\": \"parent at fun.pyx:8\",\n                            \"thread_id\": \"0x1\",\n                            \"location\": [\"parent\", \"fun.pyx\", 8],\n                            \"value\": 1024,\n                            \"n_allocations\": 1,\n                            \"interesting\": True,\n                            \"import_system\": False,\n                            \"children\": [\n                                {\n                                    \"name\": \"grandparent at fun.c:4\",\n                                    \"thread_id\": \"0x1\",\n                                    \"location\": [\"grandparent\", \"fun.c\", 4],\n                                    \"value\": 1024,\n                                    \"n_allocations\": 1,\n                                    \"interesting\": True,\n                                    \"import_system\": False,\n                                    \"children\": [],\n                                }\n                            ],\n                        }\n                    ],\n                }\n            ],\n        } == tree\n\n        assert inverted_import_system_tree == tree\n\n    def test_works_with_multiple_stacks_from_same_caller(self):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"me\", \"fun.py\", 12),\n                    (\"parent\", \"fun.py\", 8),\n                    (\"grandparent\", \"fun.py\", 4),\n                ],\n            ),\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"sibling\", \"fun.py\", 16),\n                    (\"parent\", \"fun.py\", 8),\n                    (\"grandparent\", \"fun.py\", 4),\n                ],\n            ),\n        ]\n\n        # WHEN\n        reporter = FlameGraphReporter.from_snapshot(\n            peak_allocations, memory_records=[], native_traces=False\n        )\n\n        tree, inverted_import_system_tree = get_packed_trees(reporter.data)\n\n        # THEN\n        assert inverted_import_system_tree == {}\n        assert {\n            \"name\": \"<root>\",\n            \"thread_id\": \"0x0\",\n            \"location\": [\"&lt;tracker&gt;\", \"<b>memray</b>\", 0],\n            \"value\": 2048,\n            \"n_allocations\": 2,\n            \"unique_threads\": [\"0x1\"],\n            \"interesting\": True,\n            \"import_system\": False,\n            \"children\": [\n                {\n                    \"name\": \"grandparent at fun.py:4\",\n                    \"thread_id\": \"0x1\",\n                    \"location\": [\"grandparent\", \"fun.py\", 4],\n                    \"value\": 2048,\n                    \"n_allocations\": 2,\n                    \"interesting\": True,\n                    \"import_system\": False,\n                    \"children\": [\n                        {\n                            \"name\": \"parent at fun.py:8\",\n                            \"thread_id\": \"0x1\",\n                            \"location\": [\"parent\", \"fun.py\", 8],\n                            \"value\": 2048,\n                            \"n_allocations\": 2,\n                            \"interesting\": True,\n                            \"import_system\": False,\n                            \"children\": [\n                                {\n                                    \"name\": \"me at fun.py:12\",\n                                    \"thread_id\": \"0x1\",\n                                    \"location\": [\"me\", \"fun.py\", 12],\n                                    \"value\": 1024,\n                                    \"n_allocations\": 1,\n                                    \"interesting\": True,\n                                    \"import_system\": False,\n                                    \"children\": [],\n                                },\n                                {\n                                    \"name\": \"sibling at fun.py:16\",\n                                    \"thread_id\": \"0x1\",\n                                    \"location\": [\"sibling\", \"fun.py\", 16],\n                                    \"value\": 1024,\n                                    \"n_allocations\": 1,\n                                    \"interesting\": True,\n                                    \"import_system\": False,\n                                    \"children\": [],\n                                },\n                            ],\n                        }\n                    ],\n                }\n            ],\n        } == tree\n\n    def test_sanity_check_with_real_allocations(self, tmp_path):\n        # GIVEN\n        allocator = MemoryAllocator()\n        output = tmp_path / \"test.bin\"\n        with Tracker(output):\n            allocator.valloc(4096)\n            allocator.free()\n\n        peak_allocations = filter_relevant_allocations(\n            FileReader(output).get_high_watermark_allocation_records()\n        )\n\n        # WHEN\n        reporter = FlameGraphReporter.from_snapshot(\n            peak_allocations, memory_records=[], native_traces=False\n        )\n\n        tree, inverted_import_system_tree = get_packed_trees(reporter.data)\n\n        # THEN\n        assert inverted_import_system_tree == {}\n        assert tree[\"name\"] == \"<root>\"\n        assert tree[\"value\"] == 4096\n\n        assert isinstance(tree[\"children\"], list)\n        assert len(tree[\"children\"]) == 1\n\n        child = tree[\"children\"][0]\n        assert child[\"name\"] == \"            allocator.valloc(4096)\\n\"\n\n    def test_inverted_sanity_check_with_real_allocations(self, tmp_path):\n        # GIVEN\n        allocator = MemoryAllocator()\n\n        output = tmp_path / \"test.bin\"\n\n        with Tracker(output):\n            allocator.valloc(4096)\n\n            allocator.free()\n\n        peak_allocations = filter_relevant_allocations(\n            FileReader(output).get_high_watermark_allocation_records()\n        )\n\n        # WHEN\n        reporter = FlameGraphReporter.from_snapshot(\n            peak_allocations, memory_records=[], native_traces=False, inverted=True\n        )\n\n        tree, inverted_import_system_tree = get_packed_trees(reporter.data)\n\n        # THEN\n        assert tree == inverted_import_system_tree\n        assert tree[\"name\"] == \"<root>\"\n        assert tree[\"value\"] == 4096\n        assert isinstance(tree[\"children\"], list)\n        assert len(tree[\"children\"]) == 1\n        child = tree[\"children\"][0]\n        assert child[\"name\"] == \"        return self.allocator.valloc(size)\\n\"\n        assert len(child[\"children\"]) == 1\n        assert child[\"children\"][0][\"name\"] == \"            allocator.valloc(4096)\\n\"\n\n    def test_works_with_multiple_stacks_from_same_caller_two_frames_above(self):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"me\", \"fun.py\", 12),\n                    (\"parent_one\", \"fun.py\", 8),\n                    (\"grandparent\", \"fun.py\", 4),\n                ],\n            ),\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"sibling\", \"fun.py\", 16),\n                    (\"parent_two\", \"fun.py\", 10),\n                    (\"grandparent\", \"fun.py\", 4),\n                ],\n            ),\n        ]\n\n        # WHEN\n        reporter = FlameGraphReporter.from_snapshot(\n            peak_allocations, memory_records=[], native_traces=False\n        )\n\n        tree, inverted_import_system_tree = get_packed_trees(reporter.data)\n\n        # THEN\n        assert inverted_import_system_tree == {}\n        assert {\n            \"name\": \"<root>\",\n            \"thread_id\": \"0x0\",\n            \"location\": [\"&lt;tracker&gt;\", \"<b>memray</b>\", 0],\n            \"value\": 2048,\n            \"n_allocations\": 2,\n            \"unique_threads\": [\"0x1\"],\n            \"interesting\": True,\n            \"import_system\": False,\n            \"children\": [\n                {\n                    \"name\": \"grandparent at fun.py:4\",\n                    \"thread_id\": \"0x1\",\n                    \"location\": [\"grandparent\", \"fun.py\", 4],\n                    \"value\": 2048,\n                    \"n_allocations\": 2,\n                    \"interesting\": True,\n                    \"import_system\": False,\n                    \"children\": [\n                        {\n                            \"name\": \"parent_one at fun.py:8\",\n                            \"thread_id\": \"0x1\",\n                            \"location\": [\"parent_one\", \"fun.py\", 8],\n                            \"value\": 1024,\n                            \"n_allocations\": 1,\n                            \"interesting\": True,\n                            \"import_system\": False,\n                            \"children\": [\n                                {\n                                    \"name\": \"me at fun.py:12\",\n                                    \"thread_id\": \"0x1\",\n                                    \"location\": [\"me\", \"fun.py\", 12],\n                                    \"value\": 1024,\n                                    \"n_allocations\": 1,\n                                    \"interesting\": True,\n                                    \"import_system\": False,\n                                    \"children\": [],\n                                }\n                            ],\n                        },\n                        {\n                            \"name\": \"parent_two at fun.py:10\",\n                            \"thread_id\": \"0x1\",\n                            \"location\": [\"parent_two\", \"fun.py\", 10],\n                            \"value\": 1024,\n                            \"n_allocations\": 1,\n                            \"interesting\": True,\n                            \"import_system\": False,\n                            \"children\": [\n                                {\n                                    \"name\": \"sibling at fun.py:16\",\n                                    \"thread_id\": \"0x1\",\n                                    \"location\": [\"sibling\", \"fun.py\", 16],\n                                    \"value\": 1024,\n                                    \"n_allocations\": 1,\n                                    \"interesting\": True,\n                                    \"import_system\": False,\n                                    \"children\": [],\n                                }\n                            ],\n                        },\n                    ],\n                }\n            ],\n        } == tree\n\n    def test_inverted_works_with_multiple_stacks_from_same_caller_two_frames_above(\n        self,\n    ):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"me\", \"fun.py\", 12),\n                    (\"parent_one\", \"fun.py\", 8),\n                    (\"grandparent\", \"fun.py\", 4),\n                ],\n            ),\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"sibling\", \"fun.py\", 16),\n                    (\"parent_two\", \"fun.py\", 10),\n                    (\"grandparent\", \"fun.py\", 4),\n                ],\n            ),\n        ]\n\n        # WHEN\n        reporter = FlameGraphReporter.from_snapshot(\n            peak_allocations, memory_records=[], native_traces=False, inverted=True\n        )\n\n        tree, inverted_import_system_tree = get_packed_trees(reporter.data)\n\n        # THEN\n        assert tree == inverted_import_system_tree\n        assert {\n            \"name\": \"<root>\",\n            \"thread_id\": \"0x0\",\n            \"location\": [\"&lt;tracker&gt;\", \"<b>memray</b>\", 0],\n            \"value\": 2048,\n            \"n_allocations\": 2,\n            \"unique_threads\": [\"0x1\"],\n            \"interesting\": True,\n            \"import_system\": False,\n            \"children\": [\n                {\n                    \"name\": \"me at fun.py:12\",\n                    \"thread_id\": \"0x1\",\n                    \"location\": [\"me\", \"fun.py\", 12],\n                    \"value\": 1024,\n                    \"n_allocations\": 1,\n                    \"interesting\": True,\n                    \"import_system\": False,\n                    \"children\": [\n                        {\n                            \"name\": \"parent_one at fun.py:8\",\n                            \"thread_id\": \"0x1\",\n                            \"location\": [\"parent_one\", \"fun.py\", 8],\n                            \"value\": 1024,\n                            \"n_allocations\": 1,\n                            \"interesting\": True,\n                            \"import_system\": False,\n                            \"children\": [\n                                {\n                                    \"name\": \"grandparent at fun.py:4\",\n                                    \"thread_id\": \"0x1\",\n                                    \"location\": [\"grandparent\", \"fun.py\", 4],\n                                    \"value\": 1024,\n                                    \"n_allocations\": 1,\n                                    \"interesting\": True,\n                                    \"import_system\": False,\n                                    \"children\": [],\n                                }\n                            ],\n                        }\n                    ],\n                },\n                {\n                    \"name\": \"sibling at fun.py:16\",\n                    \"thread_id\": \"0x1\",\n                    \"location\": [\"sibling\", \"fun.py\", 16],\n                    \"value\": 1024,\n                    \"n_allocations\": 1,\n                    \"interesting\": True,\n                    \"import_system\": False,\n                    \"children\": [\n                        {\n                            \"name\": \"parent_two at fun.py:10\",\n                            \"thread_id\": \"0x1\",\n                            \"location\": [\"parent_two\", \"fun.py\", 10],\n                            \"value\": 1024,\n                            \"n_allocations\": 1,\n                            \"interesting\": True,\n                            \"import_system\": False,\n                            \"children\": [\n                                {\n                                    \"name\": \"grandparent at fun.py:4\",\n                                    \"thread_id\": \"0x1\",\n                                    \"location\": [\"grandparent\", \"fun.py\", 4],\n                                    \"value\": 1024,\n                                    \"n_allocations\": 1,\n                                    \"interesting\": True,\n                                    \"import_system\": False,\n                                    \"children\": [],\n                                }\n                            ],\n                        }\n                    ],\n                },\n            ],\n        } == tree\n\n    def test_works_with_recursive_calls(self):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"one\", \"recursive.py\", 9),\n                    (\"two\", \"recursive.py\", 20),\n                    (\"one\", \"recursive.py\", 10),\n                    (\"two\", \"recursive.py\", 20),\n                    (\"one\", \"recursive.py\", 10),\n                    (\"two\", \"recursive.py\", 20),\n                    (\"main\", \"recursive.py\", 5),\n                ],\n            ),\n        ]\n\n        # WHEN\n        reporter = FlameGraphReporter.from_snapshot(\n            peak_allocations, memory_records=[], native_traces=False\n        )\n\n        tree, inverted_import_system_tree = get_packed_trees(reporter.data)\n\n        # THEN\n        assert inverted_import_system_tree == {}\n        assert {\n            \"name\": \"<root>\",\n            \"thread_id\": \"0x0\",\n            \"location\": [\"&lt;tracker&gt;\", \"<b>memray</b>\", 0],\n            \"value\": 1024,\n            \"n_allocations\": 1,\n            \"unique_threads\": [\"0x1\"],\n            \"interesting\": True,\n            \"import_system\": False,\n            \"children\": [\n                {\n                    \"name\": \"main at recursive.py:5\",\n                    \"thread_id\": \"0x1\",\n                    \"location\": [\"main\", \"recursive.py\", 5],\n                    \"value\": 1024,\n                    \"n_allocations\": 1,\n                    \"interesting\": True,\n                    \"import_system\": False,\n                    \"children\": [\n                        {\n                            \"name\": \"two at recursive.py:20\",\n                            \"thread_id\": \"0x1\",\n                            \"location\": [\"two\", \"recursive.py\", 20],\n                            \"value\": 1024,\n                            \"n_allocations\": 1,\n                            \"interesting\": True,\n                            \"import_system\": False,\n                            \"children\": [\n                                {\n                                    \"name\": \"one at recursive.py:10\",\n                                    \"thread_id\": \"0x1\",\n                                    \"location\": [\"one\", \"recursive.py\", 10],\n                                    \"value\": 1024,\n                                    \"n_allocations\": 1,\n                                    \"interesting\": True,\n                                    \"import_system\": False,\n                                    \"children\": [\n                                        {\n                                            \"name\": \"two at recursive.py:20\",\n                                            \"thread_id\": \"0x1\",\n                                            \"location\": [\"two\", \"recursive.py\", 20],\n                                            \"value\": 1024,\n                                            \"n_allocations\": 1,\n                                            \"interesting\": True,\n                                            \"import_system\": False,\n                                            \"children\": [\n                                                {\n                                                    \"name\": \"one at recursive.py:10\",\n                                                    \"thread_id\": \"0x1\",\n                                                    \"location\": [\n                                                        \"one\",\n                                                        \"recursive.py\",\n                                                        10,\n                                                    ],\n                                                    \"value\": 1024,\n                                                    \"n_allocations\": 1,\n                                                    \"interesting\": True,\n                                                    \"import_system\": False,\n                                                    \"children\": [\n                                                        {\n                                                            \"name\": \"two at recursive.py:20\",  # noqa\n                                                            \"thread_id\": \"0x1\",\n                                                            \"location\": [\n                                                                \"two\",\n                                                                \"recursive.py\",\n                                                                20,\n                                                            ],\n                                                            \"value\": 1024,\n                                                            \"n_allocations\": 1,\n                                                            \"interesting\": True,\n                                                            \"import_system\": False,\n                                                            \"children\": [\n                                                                {\n                                                                    \"name\": \"one at recursive.py:9\",  # noqa\n                                                                    \"thread_id\": \"0x1\",\n                                                                    \"location\": [\n                                                                        \"one\",\n                                                                        \"recursive.py\",\n                                                                        9,\n                                                                    ],\n                                                                    \"value\": 1024,\n                                                                    \"n_allocations\": 1,\n                                                                    \"interesting\": True,\n                                                                    \"import_system\": False,\n                                                                    \"children\": [],\n                                                                }\n                                                            ],\n                                                        }\n                                                    ],\n                                                }\n                                            ],\n                                        }\n                                    ],\n                                }\n                            ],\n                        }\n                    ],\n                }\n            ],\n        } == tree\n\n    def test_inverted_works_with_recursive_calls(self):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"one\", \"recursive.py\", 9),\n                    (\"two\", \"recursive.py\", 20),\n                    (\"one\", \"recursive.py\", 10),\n                    (\"two\", \"recursive.py\", 20),\n                    (\"one\", \"recursive.py\", 10),\n                    (\"two\", \"recursive.py\", 20),\n                    (\"main\", \"recursive.py\", 5),\n                ],\n            ),\n        ]\n\n        # WHEN\n\n        reporter = FlameGraphReporter.from_snapshot(\n            peak_allocations, memory_records=[], native_traces=False, inverted=True\n        )\n\n        tree, inverted_import_system_tree = get_packed_trees(reporter.data)\n\n        # THEN\n        assert tree == inverted_import_system_tree\n        grandchildren = [\n            {\n                \"name\": \"two at recursive.py:20\",\n                \"location\": [\"two\", \"recursive.py\", 20],\n                \"value\": 1024,\n                \"n_allocations\": 1,\n                \"thread_id\": \"0x1\",\n                \"interesting\": True,\n                \"import_system\": False,\n                \"children\": [\n                    {\n                        \"name\": \"one at recursive.py:10\",\n                        \"location\": [\"one\", \"recursive.py\", 10],\n                        \"value\": 1024,\n                        \"n_allocations\": 1,\n                        \"thread_id\": \"0x1\",\n                        \"interesting\": True,\n                        \"import_system\": False,\n                        \"children\": [\n                            {\n                                \"name\": \"two at recursive.py:20\",\n                                \"location\": [\"two\", \"recursive.py\", 20],\n                                \"value\": 1024,\n                                \"n_allocations\": 1,\n                                \"thread_id\": \"0x1\",\n                                \"interesting\": True,\n                                \"import_system\": False,\n                                \"children\": [\n                                    {\n                                        \"name\": \"one at recursive.py:10\",\n                                        \"location\": [\n                                            \"one\",\n                                            \"recursive.py\",\n                                            10,\n                                        ],\n                                        \"value\": 1024,\n                                        \"n_allocations\": 1,\n                                        \"thread_id\": \"0x1\",\n                                        \"interesting\": True,\n                                        \"import_system\": False,\n                                        \"children\": [\n                                            {\n                                                \"name\": \"two at recursive.py:20\",\n                                                \"location\": [\n                                                    \"two\",\n                                                    \"recursive.py\",\n                                                    20,\n                                                ],\n                                                \"value\": 1024,\n                                                \"n_allocations\": 1,\n                                                \"thread_id\": \"0x1\",\n                                                \"interesting\": True,\n                                                \"import_system\": False,\n                                                \"children\": [\n                                                    {\n                                                        \"name\": \"main at recursive.py:5\",\n                                                        \"location\": [\n                                                            \"main\",\n                                                            \"recursive.py\",\n                                                            5,\n                                                        ],\n                                                        \"value\": 1024,\n                                                        \"children\": [],\n                                                        \"n_allocations\": 1,\n                                                        \"thread_id\": \"0x1\",\n                                                        \"interesting\": True,\n                                                        \"import_system\": False,\n                                                    }\n                                                ],\n                                            }\n                                        ],\n                                    }\n                                ],\n                            }\n                        ],\n                    }\n                ],\n            }\n        ]\n        children = [\n            {\n                \"name\": \"one at recursive.py:9\",\n                \"location\": [\"one\", \"recursive.py\", 9],\n                \"value\": 1024,\n                \"n_allocations\": 1,\n                \"thread_id\": \"0x1\",\n                \"interesting\": True,\n                \"import_system\": False,\n                \"children\": grandchildren,\n            }\n        ]\n        assert {\n            \"name\": \"<root>\",\n            \"location\": [\"&lt;tracker&gt;\", \"<b>memray</b>\", 0],\n            \"value\": 1024,\n            \"n_allocations\": 1,\n            \"thread_id\": \"0x0\",\n            \"interesting\": True,\n            \"import_system\": False,\n            \"unique_threads\": [\"0x1\"],\n            \"children\": children,\n        } == tree\n\n    def test_works_with_multiple_top_level_nodes(self):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"baz2\", \"/src/lel.py\", 18),\n                    (\"bar2\", \"/src/lel.py\", 15),\n                    (\"foo2\", \"/src/lel.py\", 12),\n                ],\n            ),\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"baz1\", \"/src/lel.py\", 8),\n                    (\"bar1\", \"/src/lel.py\", 5),\n                    (\"foo1\", \"/src/lel.py\", 2),\n                ],\n            ),\n        ]\n\n        # WHEN\n        reporter = FlameGraphReporter.from_snapshot(\n            peak_allocations, memory_records=[], native_traces=False\n        )\n\n        tree, inverted_import_system_tree = get_packed_trees(reporter.data)\n\n        # THEN\n        assert inverted_import_system_tree == {}\n        assert {\n            \"name\": \"<root>\",\n            \"thread_id\": \"0x0\",\n            \"location\": [\"&lt;tracker&gt;\", \"<b>memray</b>\", 0],\n            \"value\": 2048,\n            \"n_allocations\": 2,\n            \"unique_threads\": [\"0x1\"],\n            \"interesting\": True,\n            \"import_system\": False,\n            \"children\": [\n                {\n                    \"name\": \"foo2 at /src/lel.py:12\",\n                    \"thread_id\": \"0x1\",\n                    \"location\": [\"foo2\", \"/src/lel.py\", 12],\n                    \"value\": 1024,\n                    \"n_allocations\": 1,\n                    \"interesting\": True,\n                    \"import_system\": False,\n                    \"children\": [\n                        {\n                            \"name\": \"bar2 at /src/lel.py:15\",\n                            \"thread_id\": \"0x1\",\n                            \"location\": [\"bar2\", \"/src/lel.py\", 15],\n                            \"value\": 1024,\n                            \"n_allocations\": 1,\n                            \"interesting\": True,\n                            \"import_system\": False,\n                            \"children\": [\n                                {\n                                    \"name\": \"baz2 at /src/lel.py:18\",\n                                    \"thread_id\": \"0x1\",\n                                    \"location\": [\"baz2\", \"/src/lel.py\", 18],\n                                    \"value\": 1024,\n                                    \"n_allocations\": 1,\n                                    \"interesting\": True,\n                                    \"import_system\": False,\n                                    \"children\": [],\n                                }\n                            ],\n                        }\n                    ],\n                },\n                {\n                    \"name\": \"foo1 at /src/lel.py:2\",\n                    \"thread_id\": \"0x1\",\n                    \"location\": [\"foo1\", \"/src/lel.py\", 2],\n                    \"value\": 1024,\n                    \"n_allocations\": 1,\n                    \"interesting\": True,\n                    \"import_system\": False,\n                    \"children\": [\n                        {\n                            \"name\": \"bar1 at /src/lel.py:5\",\n                            \"thread_id\": \"0x1\",\n                            \"location\": [\"bar1\", \"/src/lel.py\", 5],\n                            \"value\": 1024,\n                            \"n_allocations\": 1,\n                            \"interesting\": True,\n                            \"import_system\": False,\n                            \"children\": [\n                                {\n                                    \"name\": \"baz1 at /src/lel.py:8\",\n                                    \"thread_id\": \"0x1\",\n                                    \"location\": [\"baz1\", \"/src/lel.py\", 8],\n                                    \"value\": 1024,\n                                    \"n_allocations\": 1,\n                                    \"interesting\": True,\n                                    \"import_system\": False,\n                                    \"children\": [],\n                                }\n                            ],\n                        }\n                    ],\n                },\n            ],\n        } == tree\n\n    def test_inverted_works_with_multiple_top_level_nodes_with_merge(self):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"baz2\", \"/src/lel.py\", 18),\n                    (\"bar2\", \"/src/lel.py\", 15),\n                    (\"foo2\", \"/src/lel.py\", 12),\n                ],\n            ),\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"baz1\", \"/src/lel.py\", 8),\n                    (\"bar1\", \"/src/lel.py\", 5),\n                    (\"foo1\", \"/src/lel.py\", 2),\n                ],\n            ),\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"baz1\", \"/src/lel.py\", 8),\n                    (\"bar2\", \"/src/lel.py\", 10),\n                    (\"foo2\", \"/src/lel.py\", 14),\n                ],\n            ),\n        ]\n\n        # WHEN\n        reporter = FlameGraphReporter.from_snapshot(\n            peak_allocations, memory_records=[], native_traces=False, inverted=True\n        )\n\n        tree, inverted_import_system_tree = get_packed_trees(reporter.data)\n\n        # THEN\n        assert tree == inverted_import_system_tree\n        assert {\n            \"name\": \"<root>\",\n            \"location\": [\"&lt;tracker&gt;\", \"<b>memray</b>\", 0],\n            \"value\": 3072,\n            \"n_allocations\": 3,\n            \"thread_id\": \"0x0\",\n            \"interesting\": True,\n            \"import_system\": False,\n            \"unique_threads\": [\"0x1\"],\n            \"children\": [\n                {\n                    \"name\": \"baz2 at /src/lel.py:18\",\n                    \"location\": [\"baz2\", \"/src/lel.py\", 18],\n                    \"value\": 1024,\n                    \"n_allocations\": 1,\n                    \"thread_id\": \"0x1\",\n                    \"interesting\": True,\n                    \"import_system\": False,\n                    \"children\": [\n                        {\n                            \"name\": \"bar2 at /src/lel.py:15\",\n                            \"location\": [\"bar2\", \"/src/lel.py\", 15],\n                            \"value\": 1024,\n                            \"n_allocations\": 1,\n                            \"thread_id\": \"0x1\",\n                            \"interesting\": True,\n                            \"import_system\": False,\n                            \"children\": [\n                                {\n                                    \"name\": \"foo2 at /src/lel.py:12\",\n                                    \"location\": [\"foo2\", \"/src/lel.py\", 12],\n                                    \"value\": 1024,\n                                    \"children\": [],\n                                    \"n_allocations\": 1,\n                                    \"thread_id\": \"0x1\",\n                                    \"interesting\": True,\n                                    \"import_system\": False,\n                                }\n                            ],\n                        }\n                    ],\n                },\n                {\n                    \"name\": \"baz1 at /src/lel.py:8\",\n                    \"location\": [\"baz1\", \"/src/lel.py\", 8],\n                    \"value\": 2048,\n                    \"n_allocations\": 2,\n                    \"thread_id\": \"0x1\",\n                    \"interesting\": True,\n                    \"import_system\": False,\n                    \"children\": [\n                        {\n                            \"name\": \"bar1 at /src/lel.py:5\",\n                            \"location\": [\"bar1\", \"/src/lel.py\", 5],\n                            \"value\": 1024,\n                            \"n_allocations\": 1,\n                            \"thread_id\": \"0x1\",\n                            \"interesting\": True,\n                            \"import_system\": False,\n                            \"children\": [\n                                {\n                                    \"name\": \"foo1 at /src/lel.py:2\",\n                                    \"location\": [\"foo1\", \"/src/lel.py\", 2],\n                                    \"value\": 1024,\n                                    \"children\": [],\n                                    \"n_allocations\": 1,\n                                    \"thread_id\": \"0x1\",\n                                    \"interesting\": True,\n                                    \"import_system\": False,\n                                }\n                            ],\n                        },\n                        {\n                            \"name\": \"bar2 at /src/lel.py:10\",\n                            \"location\": [\"bar2\", \"/src/lel.py\", 10],\n                            \"value\": 1024,\n                            \"n_allocations\": 1,\n                            \"thread_id\": \"0x1\",\n                            \"interesting\": True,\n                            \"import_system\": False,\n                            \"children\": [\n                                {\n                                    \"name\": \"foo2 at /src/lel.py:14\",\n                                    \"location\": [\"foo2\", \"/src/lel.py\", 14],\n                                    \"value\": 1024,\n                                    \"children\": [],\n                                    \"n_allocations\": 1,\n                                    \"thread_id\": \"0x1\",\n                                    \"interesting\": True,\n                                    \"import_system\": False,\n                                }\n                            ],\n                        },\n                    ],\n                },\n            ],\n        } == tree\n\n    def test_inverted_works_with_one_top_level_node(self):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"baz1\", \"/src/lel.py\", 8),\n                    (\"bar2\", \"/src/lel.py\", 15),\n                    (\"foo2\", \"/src/lel.py\", 12),\n                ],\n            ),\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"baz1\", \"/src/lel.py\", 8),\n                    (\"bar1\", \"/src/lel.py\", 5),\n                    (\"foo1\", \"/src/lel.py\", 2),\n                ],\n            ),\n        ]\n\n        # WHEN\n        reporter = FlameGraphReporter.from_snapshot(\n            peak_allocations, memory_records=[], native_traces=False, inverted=True\n        )\n\n        tree, inverted_import_system_tree = get_packed_trees(reporter.data)\n\n        # THEN\n        assert tree == inverted_import_system_tree\n        assert {\n            \"name\": \"<root>\",\n            \"location\": [\"&lt;tracker&gt;\", \"<b>memray</b>\", 0],\n            \"value\": 2048,\n            \"n_allocations\": 2,\n            \"thread_id\": \"0x0\",\n            \"interesting\": True,\n            \"import_system\": False,\n            \"unique_threads\": [\"0x1\"],\n            \"children\": [\n                {\n                    \"name\": \"baz1 at /src/lel.py:8\",\n                    \"location\": [\"baz1\", \"/src/lel.py\", 8],\n                    \"value\": 2048,\n                    \"n_allocations\": 2,\n                    \"thread_id\": \"0x1\",\n                    \"interesting\": True,\n                    \"import_system\": False,\n                    \"children\": [\n                        {\n                            \"name\": \"bar2 at /src/lel.py:15\",\n                            \"location\": [\"bar2\", \"/src/lel.py\", 15],\n                            \"value\": 1024,\n                            \"n_allocations\": 1,\n                            \"thread_id\": \"0x1\",\n                            \"interesting\": True,\n                            \"import_system\": False,\n                            \"children\": [\n                                {\n                                    \"name\": \"foo2 at /src/lel.py:12\",\n                                    \"location\": [\"foo2\", \"/src/lel.py\", 12],\n                                    \"value\": 1024,\n                                    \"n_allocations\": 1,\n                                    \"thread_id\": \"0x1\",\n                                    \"interesting\": True,\n                                    \"import_system\": False,\n                                    \"children\": [],\n                                }\n                            ],\n                        },\n                        {\n                            \"name\": \"bar1 at /src/lel.py:5\",\n                            \"location\": [\"bar1\", \"/src/lel.py\", 5],\n                            \"value\": 1024,\n                            \"n_allocations\": 1,\n                            \"thread_id\": \"0x1\",\n                            \"interesting\": True,\n                            \"import_system\": False,\n                            \"children\": [\n                                {\n                                    \"name\": \"foo1 at /src/lel.py:2\",\n                                    \"location\": [\"foo1\", \"/src/lel.py\", 2],\n                                    \"value\": 1024,\n                                    \"n_allocations\": 1,\n                                    \"thread_id\": \"0x1\",\n                                    \"interesting\": True,\n                                    \"import_system\": False,\n                                    \"children\": [],\n                                }\n                            ],\n                        },\n                    ],\n                }\n            ],\n        } == tree\n\n    def test_works_with_split_threads(self):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"baz2\", \"/src/lel.py\", 18),\n                    (\"bar2\", \"/src/lel.py\", 15),\n                    (\"foo2\", \"/src/lel.py\", 12),\n                ],\n            ),\n            MockAllocationRecord(\n                tid=2,\n                address=0x2000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"baz2\", \"/src/lel.py\", 18),\n                    (\"bar2\", \"/src/lel.py\", 15),\n                    (\"foo2\", \"/src/lel.py\", 12),\n                ],\n            ),\n        ]\n\n        # WHEN\n        reporter = FlameGraphReporter.from_snapshot(\n            peak_allocations, memory_records=[], native_traces=False\n        )\n\n        tree, inverted_import_system_tree = get_packed_trees(reporter.data)\n\n        # THEN\n        assert inverted_import_system_tree == {}\n        assert {\n            \"name\": \"<root>\",\n            \"thread_id\": \"0x0\",\n            \"location\": [\"&lt;tracker&gt;\", \"<b>memray</b>\", 0],\n            \"value\": 2048,\n            \"n_allocations\": 2,\n            \"unique_threads\": [\"0x1\", \"0x2\"],\n            \"interesting\": True,\n            \"import_system\": False,\n            \"children\": [\n                {\n                    \"name\": \"foo2 at /src/lel.py:12\",\n                    \"thread_id\": \"0x1\",\n                    \"location\": [\"foo2\", \"/src/lel.py\", 12],\n                    \"value\": 1024,\n                    \"n_allocations\": 1,\n                    \"interesting\": True,\n                    \"import_system\": False,\n                    \"children\": [\n                        {\n                            \"name\": \"bar2 at /src/lel.py:15\",\n                            \"thread_id\": \"0x1\",\n                            \"location\": [\"bar2\", \"/src/lel.py\", 15],\n                            \"value\": 1024,\n                            \"n_allocations\": 1,\n                            \"interesting\": True,\n                            \"import_system\": False,\n                            \"children\": [\n                                {\n                                    \"name\": \"baz2 at /src/lel.py:18\",\n                                    \"thread_id\": \"0x1\",\n                                    \"location\": [\"baz2\", \"/src/lel.py\", 18],\n                                    \"value\": 1024,\n                                    \"n_allocations\": 1,\n                                    \"interesting\": True,\n                                    \"import_system\": False,\n                                    \"children\": [],\n                                }\n                            ],\n                        }\n                    ],\n                },\n                {\n                    \"name\": \"foo2 at /src/lel.py:12\",\n                    \"thread_id\": \"0x2\",\n                    \"location\": [\"foo2\", \"/src/lel.py\", 12],\n                    \"value\": 1024,\n                    \"n_allocations\": 1,\n                    \"interesting\": True,\n                    \"import_system\": False,\n                    \"children\": [\n                        {\n                            \"name\": \"bar2 at /src/lel.py:15\",\n                            \"thread_id\": \"0x2\",\n                            \"location\": [\"bar2\", \"/src/lel.py\", 15],\n                            \"value\": 1024,\n                            \"n_allocations\": 1,\n                            \"interesting\": True,\n                            \"import_system\": False,\n                            \"children\": [\n                                {\n                                    \"name\": \"baz2 at /src/lel.py:18\",\n                                    \"thread_id\": \"0x2\",\n                                    \"location\": [\"baz2\", \"/src/lel.py\", 18],\n                                    \"value\": 1024,\n                                    \"n_allocations\": 1,\n                                    \"interesting\": True,\n                                    \"import_system\": False,\n                                    \"children\": [],\n                                }\n                            ],\n                        }\n                    ],\n                },\n            ],\n        } == tree\n\n    def test_inverted_works_with_split_threads(self):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"baz2\", \"/src/lel.py\", 18),\n                    (\"bar2\", \"/src/lel.py\", 15),\n                    (\"foo2\", \"/src/lel.py\", 12),\n                ],\n            ),\n            MockAllocationRecord(\n                tid=2,\n                address=0x2000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"baz2\", \"/src/lel.py\", 18),\n                    (\"bar2\", \"/src/lel.py\", 15),\n                    (\"foo2\", \"/src/lel.py\", 12),\n                ],\n            ),\n        ]\n\n        # WHEN\n        reporter = FlameGraphReporter.from_snapshot(\n            peak_allocations, memory_records=[], native_traces=False, inverted=True\n        )\n\n        tree, inverted_import_system_tree = get_packed_trees(reporter.data)\n\n        # THEN\n        assert tree == inverted_import_system_tree\n        assert {\n            \"name\": \"<root>\",\n            \"thread_id\": \"0x0\",\n            \"location\": [\"&lt;tracker&gt;\", \"<b>memray</b>\", 0],\n            \"value\": 2048,\n            \"n_allocations\": 2,\n            \"unique_threads\": [\"0x1\", \"0x2\"],\n            \"interesting\": True,\n            \"import_system\": False,\n            \"children\": [\n                {\n                    \"name\": \"baz2 at /src/lel.py:18\",\n                    \"thread_id\": \"0x1\",\n                    \"location\": [\"baz2\", \"/src/lel.py\", 18],\n                    \"value\": 1024,\n                    \"n_allocations\": 1,\n                    \"interesting\": True,\n                    \"import_system\": False,\n                    \"children\": [\n                        {\n                            \"name\": \"bar2 at /src/lel.py:15\",\n                            \"thread_id\": \"0x1\",\n                            \"location\": [\"bar2\", \"/src/lel.py\", 15],\n                            \"value\": 1024,\n                            \"n_allocations\": 1,\n                            \"interesting\": True,\n                            \"import_system\": False,\n                            \"children\": [\n                                {\n                                    \"name\": \"foo2 at /src/lel.py:12\",\n                                    \"thread_id\": \"0x1\",\n                                    \"location\": [\"foo2\", \"/src/lel.py\", 12],\n                                    \"value\": 1024,\n                                    \"n_allocations\": 1,\n                                    \"interesting\": True,\n                                    \"import_system\": False,\n                                    \"children\": [],\n                                }\n                            ],\n                        }\n                    ],\n                },\n                {\n                    \"name\": \"baz2 at /src/lel.py:18\",\n                    \"thread_id\": \"0x2\",\n                    \"location\": [\"baz2\", \"/src/lel.py\", 18],\n                    \"value\": 1024,\n                    \"n_allocations\": 1,\n                    \"interesting\": True,\n                    \"import_system\": False,\n                    \"children\": [\n                        {\n                            \"name\": \"bar2 at /src/lel.py:15\",\n                            \"thread_id\": \"0x2\",\n                            \"location\": [\"bar2\", \"/src/lel.py\", 15],\n                            \"value\": 1024,\n                            \"n_allocations\": 1,\n                            \"interesting\": True,\n                            \"import_system\": False,\n                            \"children\": [\n                                {\n                                    \"name\": \"foo2 at /src/lel.py:12\",\n                                    \"thread_id\": \"0x2\",\n                                    \"location\": [\"foo2\", \"/src/lel.py\", 12],\n                                    \"value\": 1024,\n                                    \"n_allocations\": 1,\n                                    \"interesting\": True,\n                                    \"import_system\": False,\n                                    \"children\": [],\n                                }\n                            ],\n                        }\n                    ],\n                },\n            ],\n        } == tree\n\n    def test_works_with_merged_threads(self):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=-1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"baz2\", \"/src/lel.py\", 18),\n                    (\"bar2\", \"/src/lel.py\", 15),\n                    (\"foo2\", \"/src/lel.py\", 12),\n                ],\n            ),\n            MockAllocationRecord(\n                tid=-1,\n                address=0x2000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"baz2\", \"/src/lel.py\", 18),\n                    (\"bar2\", \"/src/lel.py\", 15),\n                    (\"foo2\", \"/src/lel.py\", 12),\n                ],\n            ),\n        ]\n\n        # WHEN\n        reporter = FlameGraphReporter.from_snapshot(\n            peak_allocations, memory_records=[], native_traces=False\n        )\n\n        tree, inverted_import_system_tree = get_packed_trees(reporter.data)\n\n        # THEN\n        assert inverted_import_system_tree == {}\n        assert {\n            \"name\": \"<root>\",\n            \"thread_id\": \"0x0\",\n            \"location\": [\"&lt;tracker&gt;\", \"<b>memray</b>\", 0],\n            \"value\": 2048,\n            \"n_allocations\": 2,\n            \"unique_threads\": [\"merged thread\"],\n            \"interesting\": True,\n            \"import_system\": False,\n            \"children\": [\n                {\n                    \"name\": \"foo2 at /src/lel.py:12\",\n                    \"thread_id\": \"merged thread\",\n                    \"location\": [\"foo2\", \"/src/lel.py\", 12],\n                    \"value\": 2048,\n                    \"n_allocations\": 2,\n                    \"interesting\": True,\n                    \"import_system\": False,\n                    \"children\": [\n                        {\n                            \"name\": \"bar2 at /src/lel.py:15\",\n                            \"thread_id\": \"merged thread\",\n                            \"location\": [\"bar2\", \"/src/lel.py\", 15],\n                            \"value\": 2048,\n                            \"n_allocations\": 2,\n                            \"interesting\": True,\n                            \"import_system\": False,\n                            \"children\": [\n                                {\n                                    \"name\": \"baz2 at /src/lel.py:18\",\n                                    \"thread_id\": \"merged thread\",\n                                    \"location\": [\"baz2\", \"/src/lel.py\", 18],\n                                    \"value\": 2048,\n                                    \"n_allocations\": 2,\n                                    \"interesting\": True,\n                                    \"import_system\": False,\n                                    \"children\": [],\n                                }\n                            ],\n                        }\n                    ],\n                },\n            ],\n        } == tree\n\n    def test_inverted_works_with_merged_threads(self):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=-1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"baz2\", \"/src/lel.py\", 18),\n                    (\"bar2\", \"/src/lel.py\", 15),\n                    (\"foo2\", \"/src/lel.py\", 12),\n                ],\n            ),\n            MockAllocationRecord(\n                tid=-1,\n                address=0x2000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"baz2\", \"/src/lel.py\", 18),\n                    (\"bar2\", \"/src/lel.py\", 15),\n                    (\"foo2\", \"/src/lel.py\", 12),\n                ],\n            ),\n        ]\n\n        # WHEN\n        reporter = FlameGraphReporter.from_snapshot(\n            peak_allocations, memory_records=[], native_traces=False, inverted=True\n        )\n\n        tree, inverted_import_system_tree = get_packed_trees(reporter.data)\n\n        # THEN\n        tree == inverted_import_system_tree\n        assert {\n            \"name\": \"<root>\",\n            \"thread_id\": \"0x0\",\n            \"location\": [\"&lt;tracker&gt;\", \"<b>memray</b>\", 0],\n            \"value\": 2048,\n            \"n_allocations\": 2,\n            \"unique_threads\": [\"merged thread\"],\n            \"interesting\": True,\n            \"import_system\": False,\n            \"children\": [\n                {\n                    \"name\": \"baz2 at /src/lel.py:18\",\n                    \"thread_id\": \"merged thread\",\n                    \"location\": [\"baz2\", \"/src/lel.py\", 18],\n                    \"value\": 2048,\n                    \"n_allocations\": 2,\n                    \"interesting\": True,\n                    \"import_system\": False,\n                    \"children\": [\n                        {\n                            \"name\": \"bar2 at /src/lel.py:15\",\n                            \"thread_id\": \"merged thread\",\n                            \"location\": [\"bar2\", \"/src/lel.py\", 15],\n                            \"value\": 2048,\n                            \"n_allocations\": 2,\n                            \"interesting\": True,\n                            \"import_system\": False,\n                            \"children\": [\n                                {\n                                    \"name\": \"foo2 at /src/lel.py:12\",\n                                    \"thread_id\": \"merged thread\",\n                                    \"location\": [\"foo2\", \"/src/lel.py\", 12],\n                                    \"value\": 2048,\n                                    \"n_allocations\": 2,\n                                    \"interesting\": True,\n                                    \"import_system\": False,\n                                    \"children\": [],\n                                }\n                            ],\n                        }\n                    ],\n                },\n            ],\n        } == tree\n\n    def test_drops_cpython_frames(self):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"me\", \"fun.py\", 12),\n                    (\"parent\", \"fun.py\", 8),\n                    (\"PyObject_Call\", \"/src/python/python3.8/Python/ceval.c\", 4),\n                    (\n                        \"PyCFunction_Call\",\n                        \"/src/python/python3.8/Objects/call.c\",\n                        1,\n                    ),\n                ],\n            ),\n        ]\n\n        # WHEN\n        reporter = FlameGraphReporter.from_snapshot(\n            peak_allocations, memory_records=[], native_traces=False\n        )\n\n        tree, inverted_import_system_tree = get_packed_trees(reporter.data)\n\n        # THEN\n        assert inverted_import_system_tree == {}\n        assert {\n            \"name\": \"<root>\",\n            \"thread_id\": \"0x0\",\n            \"location\": [\"&lt;tracker&gt;\", \"<b>memray</b>\", 0],\n            \"value\": 1024,\n            \"n_allocations\": 1,\n            \"unique_threads\": [\"0x1\"],\n            \"interesting\": True,\n            \"import_system\": False,\n            \"children\": [\n                {\n                    \"name\": \"parent at fun.py:8\",\n                    \"thread_id\": \"0x1\",\n                    \"location\": [\"parent\", \"fun.py\", 8],\n                    \"value\": 1024,\n                    \"n_allocations\": 1,\n                    \"interesting\": True,\n                    \"import_system\": False,\n                    \"children\": [\n                        {\n                            \"name\": \"me at fun.py:12\",\n                            \"thread_id\": \"0x1\",\n                            \"location\": [\"me\", \"fun.py\", 12],\n                            \"value\": 1024,\n                            \"children\": [],\n                            \"interesting\": True,\n                            \"import_system\": False,\n                            \"n_allocations\": 1,\n                        }\n                    ],\n                }\n            ],\n        } == tree\n\n    def test_inverted_drops_cpython_frames(self):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"me\", \"fun.py\", 12),\n                    (\"parent\", \"fun.py\", 8),\n                    (\"PyObject_Call\", \"/src/python/python3.8/Python/ceval.c\", 4),\n                    (\n                        \"PyCFunction_Call\",\n                        \"/src/python/python3.8/Objects/call.c\",\n                        1,\n                    ),\n                ],\n            ),\n        ]\n\n        # WHEN\n        reporter = FlameGraphReporter.from_snapshot(\n            peak_allocations, memory_records=[], native_traces=False, inverted=True\n        )\n\n        tree, inverted_import_system_tree = get_packed_trees(reporter.data)\n\n        # THEN\n        assert tree == inverted_import_system_tree\n        assert {\n            \"name\": \"<root>\",\n            \"thread_id\": \"0x0\",\n            \"location\": [\"&lt;tracker&gt;\", \"<b>memray</b>\", 0],\n            \"value\": 1024,\n            \"n_allocations\": 1,\n            \"unique_threads\": [\"0x1\"],\n            \"interesting\": True,\n            \"import_system\": False,\n            \"children\": [\n                {\n                    \"name\": \"me at fun.py:12\",\n                    \"thread_id\": \"0x1\",\n                    \"location\": [\"me\", \"fun.py\", 12],\n                    \"value\": 1024,\n                    \"interesting\": True,\n                    \"import_system\": False,\n                    \"n_allocations\": 1,\n                    \"children\": [\n                        {\n                            \"name\": \"parent at fun.py:8\",\n                            \"thread_id\": \"0x1\",\n                            \"location\": [\"parent\", \"fun.py\", 8],\n                            \"value\": 1024,\n                            \"n_allocations\": 1,\n                            \"interesting\": True,\n                            \"import_system\": False,\n                            \"children\": [],\n                        }\n                    ],\n                }\n            ],\n        } == tree\n\n    def test_very_deep_call_is_limited(self):\n        # GIVEN\n        n_frames = sys.getrecursionlimit() * 2\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[(f\"func_{i}\", \"fun.py\", i) for i in range(n_frames, 0, -1)],\n            ),\n        ]\n\n        # WHEN\n        reporter = FlameGraphReporter.from_snapshot(\n            peak_allocations, memory_records=[], native_traces=False\n        )\n\n        tree, inverted_import_system_tree = get_packed_trees(reporter.data)\n\n        # THEN\n        assert inverted_import_system_tree == {}\n\n        current_depth = 0\n        current_node = tree[\"children\"][0]\n        while current_node[\"children\"]:\n            current_depth += 1\n            assert len(current_node[\"children\"]) == 1\n            name = current_node[\"name\"]\n            assert name == f\"func_{current_depth} at fun.py:{current_depth}\"\n            current_node = current_node[\"children\"][0]\n\n        assert current_depth == MAX_STACKS + 1\n        assert current_node == {\n            \"children\": [],\n            \"location\": [\"...\", \"...\", 0],\n            \"n_allocations\": 1,\n            \"interesting\": True,\n            \"import_system\": False,\n            \"name\": \"<STACK TOO DEEP>\",\n            \"thread_id\": \"0x1\",\n            \"value\": 1024,\n        }\n\n    def test_inverted_very_deep_call_is_limited(self):\n        # GIVEN\n        n_frames = sys.getrecursionlimit() * 2\n\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[(f\"func_{i}\", \"fun.py\", i) for i in range(n_frames, 0, -1)],\n            ),\n        ]\n\n        # WHEN\n        reporter = FlameGraphReporter.from_snapshot(\n            peak_allocations, memory_records=[], native_traces=False, inverted=True\n        )\n\n        tree, _ = get_packed_trees(reporter.data)\n\n        # THEN\n        current_depth = n_frames\n\n        current_node = tree[\"children\"][0]\n\n        while current_node[\"children\"]:\n            assert len(current_node[\"children\"]) == 1\n\n            name = current_node[\"name\"]\n\n            assert name == f\"func_{current_depth} at fun.py:{current_depth}\"\n\n            current_node = current_node[\"children\"][0]\n\n            current_depth -= 1\n\n        assert (n_frames - current_depth) == MAX_STACKS + 1\n\n        assert current_node == {\n            \"children\": [],\n            \"location\": [\"...\", \"...\", 0],\n            \"n_allocations\": 1,\n            \"interesting\": True,\n            \"import_system\": False,\n            \"name\": \"<STACK TOO DEEP>\",\n            \"thread_id\": \"0x1\",\n            \"value\": 1024,\n        }\n\n    def test_single_importlib_frame_is_detected(self):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"me\", \"<frozen importlib>\", 4),\n                ],\n            ),\n        ]\n\n        # WHEN\n        reporter = FlameGraphReporter.from_snapshot(\n            peak_allocations, memory_records=[], native_traces=False\n        )\n\n        tree, inverted_import_system_tree = get_packed_trees(reporter.data)\n\n        # THEN\n        assert inverted_import_system_tree == {}\n        assert {\n            \"children\": [\n                {\n                    \"children\": [],\n                    \"import_system\": True,\n                    \"interesting\": False,\n                    \"location\": [\"me\", \"&lt;frozen importlib&gt;\", 4],\n                    \"n_allocations\": 1,\n                    \"name\": \"me at <frozen importlib>:4\",\n                    \"thread_id\": \"0x1\",\n                    \"value\": 1024,\n                }\n            ],\n            \"import_system\": False,\n            \"interesting\": True,\n            \"location\": [\"&lt;tracker&gt;\", \"<b>memray</b>\", 0],\n            \"n_allocations\": 1,\n            \"name\": \"<root>\",\n            \"thread_id\": \"0x0\",\n            \"unique_threads\": [\"0x1\"],\n            \"value\": 1024,\n        } == tree\n\n    def test_inverted_single_importlib_frame_is_detected(self):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"me\", \"<frozen importlib>\", 4),\n                ],\n            ),\n        ]\n\n        # WHEN\n        reporter = FlameGraphReporter.from_snapshot(\n            peak_allocations, memory_records=[], native_traces=False, inverted=True\n        )\n\n        tree, inverted_import_system_tree = get_packed_trees(reporter.data)\n\n        # THEN\n        assert {\n            \"children\": [\n                {\n                    \"children\": [],\n                    \"import_system\": False,\n                    \"interesting\": False,\n                    \"location\": [\"me\", \"&lt;frozen importlib&gt;\", 4],\n                    \"n_allocations\": 1,\n                    \"name\": \"me at <frozen importlib>:4\",\n                    \"thread_id\": \"0x1\",\n                    \"value\": 1024,\n                }\n            ],\n            \"import_system\": False,\n            \"interesting\": True,\n            \"location\": [\"&lt;tracker&gt;\", \"<b>memray</b>\", 0],\n            \"n_allocations\": 1,\n            \"name\": \"<root>\",\n            \"thread_id\": \"0x0\",\n            \"unique_threads\": [\"0x1\"],\n            \"value\": 1024,\n        } == tree\n\n        assert {\n            \"children\": [],\n            \"import_system\": False,\n            \"interesting\": True,\n            \"location\": [\"&lt;tracker&gt;\", \"<b>memray</b>\", 0],\n            \"n_allocations\": 1,\n            \"name\": \"<root>\",\n            \"thread_id\": \"0x0\",\n            \"unique_threads\": [\"0x1\"],\n            \"value\": 1024,\n        } == inverted_import_system_tree\n\n    def test_importlib_full_stack_is_detected(self):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"me\", \"fun.py\", 12),\n                    (\"parent\", \"fun.py\", 8),\n                    (\"grandparent\", \"<frozen importlib>\", 4),\n                ],\n            ),\n        ]\n\n        # WHEN\n        reporter = FlameGraphReporter.from_snapshot(\n            peak_allocations, memory_records=[], native_traces=False\n        )\n\n        tree, inverted_import_system_tree = get_packed_trees(reporter.data)\n\n        # THEN\n        assert inverted_import_system_tree == {}\n        assert {\n            \"children\": [\n                {\n                    \"children\": [\n                        {\n                            \"children\": [\n                                {\n                                    \"children\": [],\n                                    \"import_system\": True,\n                                    \"interesting\": True,\n                                    \"location\": [\"me\", \"fun.py\", 12],\n                                    \"n_allocations\": 1,\n                                    \"name\": \"me at fun.py:12\",\n                                    \"thread_id\": \"0x1\",\n                                    \"value\": 1024,\n                                }\n                            ],\n                            \"import_system\": True,\n                            \"interesting\": True,\n                            \"location\": [\"parent\", \"fun.py\", 8],\n                            \"n_allocations\": 1,\n                            \"name\": \"parent at fun.py:8\",\n                            \"thread_id\": \"0x1\",\n                            \"value\": 1024,\n                        }\n                    ],\n                    \"import_system\": True,\n                    \"interesting\": False,\n                    \"location\": [\"grandparent\", \"&lt;frozen importlib&gt;\", 4],\n                    \"n_allocations\": 1,\n                    \"name\": \"grandparent at <frozen importlib>:4\",\n                    \"thread_id\": \"0x1\",\n                    \"value\": 1024,\n                }\n            ],\n            \"import_system\": False,\n            \"interesting\": True,\n            \"location\": [\"&lt;tracker&gt;\", \"<b>memray</b>\", 0],\n            \"n_allocations\": 1,\n            \"name\": \"<root>\",\n            \"thread_id\": \"0x0\",\n            \"unique_threads\": [\"0x1\"],\n            \"value\": 1024,\n        } == tree\n\n    def test_inverted_importlib_full_stack_is_detected(self):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"me\", \"fun.py\", 12),\n                    (\"parent\", \"fun.py\", 8),\n                    (\"grandparent\", \"<frozen importlib>\", 4),\n                ],\n            ),\n        ]\n\n        # WHEN\n        reporter = FlameGraphReporter.from_snapshot(\n            peak_allocations, memory_records=[], native_traces=False, inverted=True\n        )\n\n        tree, inverted_import_system_tree = get_packed_trees(reporter.data)\n\n        # THEN\n        assert {\n            \"name\": \"<root>\",\n            \"location\": [\"&lt;tracker&gt;\", \"<b>memray</b>\", 0],\n            \"value\": 1024,\n            \"n_allocations\": 1,\n            \"thread_id\": \"0x0\",\n            \"interesting\": True,\n            \"import_system\": False,\n            \"unique_threads\": [\"0x1\"],\n            \"children\": [\n                {\n                    \"name\": \"me at fun.py:12\",\n                    \"location\": [\"me\", \"fun.py\", 12],\n                    \"value\": 1024,\n                    \"n_allocations\": 1,\n                    \"thread_id\": \"0x1\",\n                    \"interesting\": True,\n                    \"import_system\": False,\n                    \"children\": [\n                        {\n                            \"name\": \"parent at fun.py:8\",\n                            \"location\": [\"parent\", \"fun.py\", 8],\n                            \"value\": 1024,\n                            \"n_allocations\": 1,\n                            \"thread_id\": \"0x1\",\n                            \"interesting\": True,\n                            \"import_system\": False,\n                            \"children\": [\n                                {\n                                    \"name\": \"grandparent at <frozen importlib>:4\",\n                                    \"location\": [\n                                        \"grandparent\",\n                                        \"&lt;frozen importlib&gt;\",\n                                        4,\n                                    ],\n                                    \"value\": 1024,\n                                    \"n_allocations\": 1,\n                                    \"thread_id\": \"0x1\",\n                                    \"interesting\": False,\n                                    \"import_system\": False,\n                                    \"children\": [],\n                                }\n                            ],\n                        }\n                    ],\n                }\n            ],\n        } == tree\n\n        assert {\n            \"name\": \"<root>\",\n            \"location\": [\"&lt;tracker&gt;\", \"<b>memray</b>\", 0],\n            \"value\": 1024,\n            \"n_allocations\": 1,\n            \"thread_id\": \"0x0\",\n            \"interesting\": True,\n            \"import_system\": False,\n            \"unique_threads\": [\"0x1\"],\n            \"children\": [],\n        } == inverted_import_system_tree\n\n    def test_importlib_partial_stack_is_detected(self):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"me\", \"fun.py\", 12),\n                    (\"parent\", \"<frozen importlib>\", 8),\n                    (\"grandparent\", \"fun.py\", 4),\n                    (\"grandgrandparent\", \"fun.py\", 4),\n                ],\n            ),\n        ]\n\n        # WHEN\n        reporter = FlameGraphReporter.from_snapshot(\n            peak_allocations, memory_records=[], native_traces=False\n        )\n\n        tree, inverted_import_system_tree = get_packed_trees(reporter.data)\n\n        # THEN\n        assert inverted_import_system_tree == {}\n        assert {\n            \"children\": [\n                {\n                    \"children\": [\n                        {\n                            \"children\": [\n                                {\n                                    \"children\": [\n                                        {\n                                            \"children\": [],\n                                            \"import_system\": True,\n                                            \"interesting\": True,\n                                            \"location\": [\"me\", \"fun.py\", 12],\n                                            \"n_allocations\": 1,\n                                            \"name\": \"me at \" \"fun.py:12\",\n                                            \"thread_id\": \"0x1\",\n                                            \"value\": 1024,\n                                        }\n                                    ],\n                                    \"import_system\": True,\n                                    \"interesting\": False,\n                                    \"location\": [\n                                        \"parent\",\n                                        \"&lt;frozen \" \"importlib&gt;\",\n                                        8,\n                                    ],\n                                    \"n_allocations\": 1,\n                                    \"name\": \"parent at <frozen \" \"importlib>:8\",\n                                    \"thread_id\": \"0x1\",\n                                    \"value\": 1024,\n                                }\n                            ],\n                            \"import_system\": False,\n                            \"interesting\": True,\n                            \"location\": [\"grandparent\", \"fun.py\", 4],\n                            \"n_allocations\": 1,\n                            \"name\": \"grandparent at fun.py:4\",\n                            \"thread_id\": \"0x1\",\n                            \"value\": 1024,\n                        }\n                    ],\n                    \"import_system\": False,\n                    \"interesting\": True,\n                    \"location\": [\"grandgrandparent\", \"fun.py\", 4],\n                    \"n_allocations\": 1,\n                    \"name\": \"grandgrandparent at fun.py:4\",\n                    \"thread_id\": \"0x1\",\n                    \"value\": 1024,\n                }\n            ],\n            \"import_system\": False,\n            \"interesting\": True,\n            \"location\": [\"&lt;tracker&gt;\", \"<b>memray</b>\", 0],\n            \"n_allocations\": 1,\n            \"name\": \"<root>\",\n            \"thread_id\": \"0x0\",\n            \"unique_threads\": [\"0x1\"],\n            \"value\": 1024,\n        } == tree\n\n    def test_inverted_importlib_partial_stack_is_detected(self):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"me\", \"fun.py\", 12),\n                    (\"parent\", \"<frozen importlib>\", 8),\n                    (\"grandparent\", \"fun.py\", 4),\n                    (\"grandgrandparent\", \"fun.py\", 4),\n                ],\n            ),\n        ]\n\n        # WHEN\n        reporter = FlameGraphReporter.from_snapshot(\n            peak_allocations, memory_records=[], native_traces=False, inverted=True\n        )\n\n        tree, inverted_import_system_tree = get_packed_trees(reporter.data)\n\n        # THEN\n        assert {\n            \"name\": \"<root>\",\n            \"location\": [\"&lt;tracker&gt;\", \"<b>memray</b>\", 0],\n            \"value\": 1024,\n            \"n_allocations\": 1,\n            \"thread_id\": \"0x0\",\n            \"interesting\": True,\n            \"import_system\": False,\n            \"unique_threads\": [\"0x1\"],\n            \"children\": [\n                {\n                    \"name\": \"me at fun.py:12\",\n                    \"location\": [\"me\", \"fun.py\", 12],\n                    \"value\": 1024,\n                    \"n_allocations\": 1,\n                    \"thread_id\": \"0x1\",\n                    \"interesting\": True,\n                    \"import_system\": False,\n                    \"children\": [\n                        {\n                            \"name\": \"parent at <frozen importlib>:8\",\n                            \"location\": [\"parent\", \"&lt;frozen importlib&gt;\", 8],\n                            \"value\": 1024,\n                            \"n_allocations\": 1,\n                            \"thread_id\": \"0x1\",\n                            \"interesting\": False,\n                            \"import_system\": False,\n                            \"children\": [\n                                {\n                                    \"name\": \"grandparent at fun.py:4\",\n                                    \"location\": [\"grandparent\", \"fun.py\", 4],\n                                    \"value\": 1024,\n                                    \"n_allocations\": 1,\n                                    \"thread_id\": \"0x1\",\n                                    \"interesting\": True,\n                                    \"import_system\": False,\n                                    \"children\": [\n                                        {\n                                            \"name\": \"grandgrandparent at fun.py:4\",\n                                            \"location\": [\n                                                \"grandgrandparent\",\n                                                \"fun.py\",\n                                                4,\n                                            ],\n                                            \"value\": 1024,\n                                            \"n_allocations\": 1,\n                                            \"thread_id\": \"0x1\",\n                                            \"interesting\": True,\n                                            \"import_system\": False,\n                                            \"children\": [],\n                                        }\n                                    ],\n                                }\n                            ],\n                        }\n                    ],\n                }\n            ],\n        } == tree\n\n        assert {\n            \"name\": \"<root>\",\n            \"location\": [\"&lt;tracker&gt;\", \"<b>memray</b>\", 0],\n            \"value\": 1024,\n            \"n_allocations\": 1,\n            \"thread_id\": \"0x0\",\n            \"interesting\": True,\n            \"import_system\": False,\n            \"unique_threads\": [\"0x1\"],\n            \"children\": [\n                {\n                    \"name\": \"grandparent at fun.py:4\",\n                    \"location\": [\"grandparent\", \"fun.py\", 4],\n                    \"value\": 1024,\n                    \"n_allocations\": 1,\n                    \"thread_id\": \"0x1\",\n                    \"interesting\": True,\n                    \"import_system\": False,\n                    \"children\": [\n                        {\n                            \"name\": \"grandgrandparent at fun.py:4\",\n                            \"location\": [\n                                \"grandgrandparent\",\n                                \"fun.py\",\n                                4,\n                            ],\n                            \"value\": 1024,\n                            \"n_allocations\": 1,\n                            \"thread_id\": \"0x1\",\n                            \"interesting\": True,\n                            \"import_system\": False,\n                            \"children\": [],\n                        }\n                    ],\n                }\n            ],\n        } == inverted_import_system_tree\n\n    def test_two_branches_first_is_importlib(self):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"me\", \"fun.py\", 12),\n                    (\"parent_one\", \"<frozen importlib>\", 8),\n                    (\"grandparent\", \"fun.py\", 4),\n                ],\n            ),\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"sibling\", \"fun.py\", 16),\n                    (\"parent_two\", \"fun.py\", 10),\n                    (\"grandparent\", \"fun.py\", 4),\n                ],\n            ),\n        ]\n\n        # WHEN\n        reporter = FlameGraphReporter.from_snapshot(\n            peak_allocations, memory_records=[], native_traces=False\n        )\n\n        tree, inverted_import_system_tree = get_packed_trees(reporter.data)\n\n        # THEN\n        assert inverted_import_system_tree == {}\n        assert {\n            \"children\": [\n                {\n                    \"children\": [\n                        {\n                            \"children\": [\n                                {\n                                    \"children\": [],\n                                    \"import_system\": True,\n                                    \"interesting\": True,\n                                    \"location\": [\"me\", \"fun.py\", 12],\n                                    \"n_allocations\": 1,\n                                    \"name\": \"me at fun.py:12\",\n                                    \"thread_id\": \"0x1\",\n                                    \"value\": 1024,\n                                }\n                            ],\n                            \"import_system\": True,\n                            \"interesting\": False,\n                            \"location\": [\"parent_one\", \"&lt;frozen importlib&gt;\", 8],\n                            \"n_allocations\": 1,\n                            \"name\": \"parent_one at <frozen importlib>:8\",\n                            \"thread_id\": \"0x1\",\n                            \"value\": 1024,\n                        },\n                        {\n                            \"children\": [\n                                {\n                                    \"children\": [],\n                                    \"import_system\": False,\n                                    \"interesting\": True,\n                                    \"location\": [\"sibling\", \"fun.py\", 16],\n                                    \"n_allocations\": 1,\n                                    \"name\": \"sibling at fun.py:16\",\n                                    \"thread_id\": \"0x1\",\n                                    \"value\": 1024,\n                                }\n                            ],\n                            \"import_system\": False,\n                            \"interesting\": True,\n                            \"location\": [\"parent_two\", \"fun.py\", 10],\n                            \"n_allocations\": 1,\n                            \"name\": \"parent_two at fun.py:10\",\n                            \"thread_id\": \"0x1\",\n                            \"value\": 1024,\n                        },\n                    ],\n                    \"import_system\": False,\n                    \"interesting\": True,\n                    \"location\": [\"grandparent\", \"fun.py\", 4],\n                    \"n_allocations\": 2,\n                    \"name\": \"grandparent at fun.py:4\",\n                    \"thread_id\": \"0x1\",\n                    \"value\": 2048,\n                }\n            ],\n            \"import_system\": False,\n            \"interesting\": True,\n            \"location\": [\"&lt;tracker&gt;\", \"<b>memray</b>\", 0],\n            \"n_allocations\": 2,\n            \"name\": \"<root>\",\n            \"thread_id\": \"0x0\",\n            \"unique_threads\": [\"0x1\"],\n            \"value\": 2048,\n        } == tree\n\n    def test_inverted_two_branches_first_is_importlib(self):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"me\", \"fun.py\", 12),\n                    (\"parent_one\", \"<frozen importlib>\", 8),\n                    (\"grandparent\", \"fun.py\", 4),\n                ],\n            ),\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"sibling\", \"fun.py\", 16),\n                    (\"parent_two\", \"fun.py\", 10),\n                    (\"grandparent\", \"fun.py\", 4),\n                ],\n            ),\n        ]\n\n        # WHEN\n        reporter = FlameGraphReporter.from_snapshot(\n            peak_allocations, memory_records=[], native_traces=False, inverted=True\n        )\n\n        tree, inverted_import_system_tree = get_packed_trees(reporter.data)\n\n        # THEN\n        assert {\n            \"import_system\": False,\n            \"interesting\": True,\n            \"location\": [\"&lt;tracker&gt;\", \"<b>memray</b>\", 0],\n            \"n_allocations\": 2,\n            \"name\": \"<root>\",\n            \"thread_id\": \"0x0\",\n            \"unique_threads\": [\"0x1\"],\n            \"value\": 2048,\n            \"children\": [\n                {\n                    \"import_system\": False,\n                    \"interesting\": True,\n                    \"location\": [\"me\", \"fun.py\", 12],\n                    \"n_allocations\": 1,\n                    \"name\": \"me at fun.py:12\",\n                    \"thread_id\": \"0x1\",\n                    \"value\": 1024,\n                    \"children\": [\n                        {\n                            \"import_system\": False,\n                            \"interesting\": False,\n                            \"location\": [\"parent_one\", \"&lt;frozen importlib&gt;\", 8],\n                            \"n_allocations\": 1,\n                            \"name\": \"parent_one at <frozen importlib>:8\",\n                            \"thread_id\": \"0x1\",\n                            \"value\": 1024,\n                            \"children\": [\n                                {\n                                    \"import_system\": False,\n                                    \"interesting\": True,\n                                    \"location\": [\"grandparent\", \"fun.py\", 4],\n                                    \"n_allocations\": 1,\n                                    \"name\": \"grandparent at fun.py:4\",\n                                    \"thread_id\": \"0x1\",\n                                    \"value\": 1024,\n                                    \"children\": [],\n                                }\n                            ],\n                        }\n                    ],\n                },\n                {\n                    \"import_system\": False,\n                    \"interesting\": True,\n                    \"location\": [\"sibling\", \"fun.py\", 16],\n                    \"n_allocations\": 1,\n                    \"name\": \"sibling at fun.py:16\",\n                    \"thread_id\": \"0x1\",\n                    \"value\": 1024,\n                    \"children\": [\n                        {\n                            \"import_system\": False,\n                            \"interesting\": True,\n                            \"location\": [\"parent_two\", \"fun.py\", 10],\n                            \"n_allocations\": 1,\n                            \"name\": \"parent_two at fun.py:10\",\n                            \"thread_id\": \"0x1\",\n                            \"value\": 1024,\n                            \"children\": [\n                                {\n                                    \"import_system\": False,\n                                    \"interesting\": True,\n                                    \"location\": [\"grandparent\", \"fun.py\", 4],\n                                    \"n_allocations\": 1,\n                                    \"name\": \"grandparent at fun.py:4\",\n                                    \"thread_id\": \"0x1\",\n                                    \"value\": 1024,\n                                    \"children\": [],\n                                }\n                            ],\n                        }\n                    ],\n                },\n            ],\n        } == tree\n\n        assert {\n            \"import_system\": False,\n            \"interesting\": True,\n            \"location\": [\"&lt;tracker&gt;\", \"<b>memray</b>\", 0],\n            \"n_allocations\": 2,\n            \"name\": \"<root>\",\n            \"thread_id\": \"0x0\",\n            \"unique_threads\": [\"0x1\"],\n            \"value\": 2048,\n            \"children\": [\n                {\n                    \"import_system\": False,\n                    \"interesting\": True,\n                    \"location\": [\"grandparent\", \"fun.py\", 4],\n                    \"n_allocations\": 1,\n                    \"name\": \"grandparent at fun.py:4\",\n                    \"thread_id\": \"0x1\",\n                    \"value\": 1024,\n                    \"children\": [],\n                },\n                {\n                    \"import_system\": False,\n                    \"interesting\": True,\n                    \"location\": [\"sibling\", \"fun.py\", 16],\n                    \"n_allocations\": 1,\n                    \"name\": \"sibling at fun.py:16\",\n                    \"thread_id\": \"0x1\",\n                    \"value\": 1024,\n                    \"children\": [\n                        {\n                            \"import_system\": False,\n                            \"interesting\": True,\n                            \"location\": [\"parent_two\", \"fun.py\", 10],\n                            \"n_allocations\": 1,\n                            \"name\": \"parent_two at fun.py:10\",\n                            \"thread_id\": \"0x1\",\n                            \"value\": 1024,\n                            \"children\": [\n                                {\n                                    \"import_system\": False,\n                                    \"interesting\": True,\n                                    \"location\": [\"grandparent\", \"fun.py\", 4],\n                                    \"n_allocations\": 1,\n                                    \"name\": \"grandparent at fun.py:4\",\n                                    \"thread_id\": \"0x1\",\n                                    \"value\": 1024,\n                                    \"children\": [],\n                                }\n                            ],\n                        }\n                    ],\n                },\n            ],\n        } == inverted_import_system_tree\n\n    def test_two_branches_second_is_importlib(self):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"sibling\", \"fun.py\", 16),\n                    (\"parent_two\", \"fun.py\", 10),\n                    (\"grandparent\", \"fun.py\", 4),\n                ],\n            ),\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"me\", \"fun.py\", 12),\n                    (\"parent_one\", \"<frozen importlib>\", 8),\n                    (\"grandparent\", \"fun.py\", 4),\n                ],\n            ),\n        ]\n\n        # WHEN\n        reporter = FlameGraphReporter.from_snapshot(\n            peak_allocations, memory_records=[], native_traces=False\n        )\n\n        tree, inverted_import_system_tree = get_packed_trees(reporter.data)\n\n        # THEN\n        assert inverted_import_system_tree == {}\n        assert {\n            \"children\": [\n                {\n                    \"children\": [\n                        {\n                            \"children\": [\n                                {\n                                    \"children\": [],\n                                    \"import_system\": False,\n                                    \"interesting\": True,\n                                    \"location\": [\"sibling\", \"fun.py\", 16],\n                                    \"n_allocations\": 1,\n                                    \"name\": \"sibling at fun.py:16\",\n                                    \"thread_id\": \"0x1\",\n                                    \"value\": 1024,\n                                }\n                            ],\n                            \"import_system\": False,\n                            \"interesting\": True,\n                            \"location\": [\"parent_two\", \"fun.py\", 10],\n                            \"n_allocations\": 1,\n                            \"name\": \"parent_two at fun.py:10\",\n                            \"thread_id\": \"0x1\",\n                            \"value\": 1024,\n                        },\n                        {\n                            \"children\": [\n                                {\n                                    \"children\": [],\n                                    \"import_system\": True,\n                                    \"interesting\": True,\n                                    \"location\": [\"me\", \"fun.py\", 12],\n                                    \"n_allocations\": 1,\n                                    \"name\": \"me at fun.py:12\",\n                                    \"thread_id\": \"0x1\",\n                                    \"value\": 1024,\n                                }\n                            ],\n                            \"import_system\": True,\n                            \"interesting\": False,\n                            \"location\": [\"parent_one\", \"&lt;frozen importlib&gt;\", 8],\n                            \"n_allocations\": 1,\n                            \"name\": \"parent_one at <frozen importlib>:8\",\n                            \"thread_id\": \"0x1\",\n                            \"value\": 1024,\n                        },\n                    ],\n                    \"import_system\": False,\n                    \"interesting\": True,\n                    \"location\": [\"grandparent\", \"fun.py\", 4],\n                    \"n_allocations\": 2,\n                    \"name\": \"grandparent at fun.py:4\",\n                    \"thread_id\": \"0x1\",\n                    \"value\": 2048,\n                }\n            ],\n            \"import_system\": False,\n            \"interesting\": True,\n            \"location\": [\"&lt;tracker&gt;\", \"<b>memray</b>\", 0],\n            \"n_allocations\": 2,\n            \"name\": \"<root>\",\n            \"thread_id\": \"0x0\",\n            \"unique_threads\": [\"0x1\"],\n            \"value\": 2048,\n        } == tree\n\n    def test_inverted_two_branches_second_is_importlib(self):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"sibling\", \"fun.py\", 16),\n                    (\"parent_two\", \"fun.py\", 10),\n                    (\"grandparent\", \"fun.py\", 4),\n                ],\n            ),\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"me\", \"fun.py\", 12),\n                    (\"parent_one\", \"<frozen importlib>\", 8),\n                    (\"grandparent\", \"fun.py\", 4),\n                ],\n            ),\n        ]\n\n        # WHEN\n        reporter = FlameGraphReporter.from_snapshot(\n            peak_allocations, memory_records=[], native_traces=False, inverted=True\n        )\n\n        tree, inverted_import_system_tree = get_packed_trees(reporter.data)\n\n        # THEN\n        assert {\n            \"name\": \"<root>\",\n            \"location\": [\"&lt;tracker&gt;\", \"<b>memray</b>\", 0],\n            \"value\": 2048,\n            \"n_allocations\": 2,\n            \"thread_id\": \"0x0\",\n            \"interesting\": True,\n            \"import_system\": False,\n            \"unique_threads\": [\"0x1\"],\n            \"children\": [\n                {\n                    \"name\": \"sibling at fun.py:16\",\n                    \"location\": [\"sibling\", \"fun.py\", 16],\n                    \"value\": 1024,\n                    \"n_allocations\": 1,\n                    \"thread_id\": \"0x1\",\n                    \"interesting\": True,\n                    \"import_system\": False,\n                    \"children\": [\n                        {\n                            \"name\": \"parent_two at fun.py:10\",\n                            \"location\": [\"parent_two\", \"fun.py\", 10],\n                            \"value\": 1024,\n                            \"n_allocations\": 1,\n                            \"thread_id\": \"0x1\",\n                            \"interesting\": True,\n                            \"import_system\": False,\n                            \"children\": [\n                                {\n                                    \"name\": \"grandparent at fun.py:4\",\n                                    \"location\": [\"grandparent\", \"fun.py\", 4],\n                                    \"value\": 1024,\n                                    \"children\": [],\n                                    \"n_allocations\": 1,\n                                    \"thread_id\": \"0x1\",\n                                    \"interesting\": True,\n                                    \"import_system\": False,\n                                }\n                            ],\n                        }\n                    ],\n                },\n                {\n                    \"name\": \"me at fun.py:12\",\n                    \"location\": [\"me\", \"fun.py\", 12],\n                    \"value\": 1024,\n                    \"n_allocations\": 1,\n                    \"thread_id\": \"0x1\",\n                    \"interesting\": True,\n                    \"import_system\": False,\n                    \"children\": [\n                        {\n                            \"name\": \"parent_one at <frozen importlib>:8\",\n                            \"location\": [\"parent_one\", \"&lt;frozen importlib&gt;\", 8],\n                            \"value\": 1024,\n                            \"n_allocations\": 1,\n                            \"thread_id\": \"0x1\",\n                            \"interesting\": False,\n                            \"import_system\": False,\n                            \"children\": [\n                                {\n                                    \"name\": \"grandparent at fun.py:4\",\n                                    \"location\": [\"grandparent\", \"fun.py\", 4],\n                                    \"value\": 1024,\n                                    \"children\": [],\n                                    \"n_allocations\": 1,\n                                    \"thread_id\": \"0x1\",\n                                    \"interesting\": True,\n                                    \"import_system\": False,\n                                }\n                            ],\n                        }\n                    ],\n                },\n            ],\n        } == tree\n\n        assert {\n            \"name\": \"<root>\",\n            \"location\": [\"&lt;tracker&gt;\", \"<b>memray</b>\", 0],\n            \"value\": 2048,\n            \"n_allocations\": 2,\n            \"thread_id\": \"0x0\",\n            \"interesting\": True,\n            \"import_system\": False,\n            \"unique_threads\": [\"0x1\"],\n            \"children\": [\n                {\n                    \"name\": \"sibling at fun.py:16\",\n                    \"location\": [\"sibling\", \"fun.py\", 16],\n                    \"value\": 1024,\n                    \"n_allocations\": 1,\n                    \"thread_id\": \"0x1\",\n                    \"interesting\": True,\n                    \"import_system\": False,\n                    \"children\": [\n                        {\n                            \"name\": \"parent_two at fun.py:10\",\n                            \"location\": [\"parent_two\", \"fun.py\", 10],\n                            \"value\": 1024,\n                            \"n_allocations\": 1,\n                            \"thread_id\": \"0x1\",\n                            \"interesting\": True,\n                            \"import_system\": False,\n                            \"children\": [\n                                {\n                                    \"name\": \"grandparent at fun.py:4\",\n                                    \"location\": [\"grandparent\", \"fun.py\", 4],\n                                    \"value\": 1024,\n                                    \"children\": [],\n                                    \"n_allocations\": 1,\n                                    \"thread_id\": \"0x1\",\n                                    \"interesting\": True,\n                                    \"import_system\": False,\n                                }\n                            ],\n                        }\n                    ],\n                },\n                {\n                    \"name\": \"grandparent at fun.py:4\",\n                    \"location\": [\"grandparent\", \"fun.py\", 4],\n                    \"value\": 1024,\n                    \"children\": [],\n                    \"n_allocations\": 1,\n                    \"thread_id\": \"0x1\",\n                    \"interesting\": True,\n                    \"import_system\": False,\n                },\n            ],\n        } == inverted_import_system_tree\n\n    def test_two_branches_both_are_importlib(self):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"me\", \"fun.py\", 12),\n                    (\"parent_one\", \"fun.py\", 8),\n                    (\"grandparent\", \"<frozen importlib>\", 4),\n                ],\n            ),\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"sibling\", \"fun.py\", 16),\n                    (\"parent_two\", \"fun.py\", 10),\n                    (\"grandparent\", \"<frozen importlib>\", 4),\n                ],\n            ),\n        ]\n\n        # WHEN\n        reporter = FlameGraphReporter.from_snapshot(\n            peak_allocations, memory_records=[], native_traces=False\n        )\n\n        tree, inverted_import_system_tree = get_packed_trees(reporter.data)\n\n        # THEN\n        assert inverted_import_system_tree == {}\n        assert {\n            \"children\": [\n                {\n                    \"children\": [\n                        {\n                            \"children\": [\n                                {\n                                    \"children\": [],\n                                    \"import_system\": True,\n                                    \"interesting\": True,\n                                    \"location\": [\"me\", \"fun.py\", 12],\n                                    \"n_allocations\": 1,\n                                    \"name\": \"me at fun.py:12\",\n                                    \"thread_id\": \"0x1\",\n                                    \"value\": 1024,\n                                }\n                            ],\n                            \"import_system\": True,\n                            \"interesting\": True,\n                            \"location\": [\"parent_one\", \"fun.py\", 8],\n                            \"n_allocations\": 1,\n                            \"name\": \"parent_one at fun.py:8\",\n                            \"thread_id\": \"0x1\",\n                            \"value\": 1024,\n                        },\n                        {\n                            \"children\": [\n                                {\n                                    \"children\": [],\n                                    \"import_system\": True,\n                                    \"interesting\": True,\n                                    \"location\": [\"sibling\", \"fun.py\", 16],\n                                    \"n_allocations\": 1,\n                                    \"name\": \"sibling at fun.py:16\",\n                                    \"thread_id\": \"0x1\",\n                                    \"value\": 1024,\n                                }\n                            ],\n                            \"import_system\": True,\n                            \"interesting\": True,\n                            \"location\": [\"parent_two\", \"fun.py\", 10],\n                            \"n_allocations\": 1,\n                            \"name\": \"parent_two at fun.py:10\",\n                            \"thread_id\": \"0x1\",\n                            \"value\": 1024,\n                        },\n                    ],\n                    \"import_system\": True,\n                    \"interesting\": False,\n                    \"location\": [\"grandparent\", \"&lt;frozen importlib&gt;\", 4],\n                    \"n_allocations\": 2,\n                    \"name\": \"grandparent at <frozen importlib>:4\",\n                    \"thread_id\": \"0x1\",\n                    \"value\": 2048,\n                }\n            ],\n            \"import_system\": False,\n            \"interesting\": True,\n            \"location\": [\"&lt;tracker&gt;\", \"<b>memray</b>\", 0],\n            \"n_allocations\": 2,\n            \"name\": \"<root>\",\n            \"thread_id\": \"0x0\",\n            \"unique_threads\": [\"0x1\"],\n            \"value\": 2048,\n        } == tree\n\n    def test_inverted_two_branches_both_are_importlib(self):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"me\", \"fun.py\", 12),\n                    (\"parent_one\", \"fun.py\", 8),\n                    (\"grandparent\", \"<frozen importlib>\", 4),\n                ],\n            ),\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"sibling\", \"fun.py\", 16),\n                    (\"parent_two\", \"fun.py\", 10),\n                    (\"grandparent\", \"<frozen importlib>\", 4),\n                ],\n            ),\n        ]\n\n        # WHEN\n        reporter = FlameGraphReporter.from_snapshot(\n            peak_allocations, memory_records=[], native_traces=False, inverted=True\n        )\n\n        tree, inverted_import_system_tree = get_packed_trees(reporter.data)\n        # THEN\n        assert {\n            \"name\": \"<root>\",\n            \"location\": [\"&lt;tracker&gt;\", \"<b>memray</b>\", 0],\n            \"value\": 2048,\n            \"n_allocations\": 2,\n            \"thread_id\": \"0x0\",\n            \"interesting\": True,\n            \"import_system\": False,\n            \"unique_threads\": [\"0x1\"],\n            \"children\": [\n                {\n                    \"name\": \"me at fun.py:12\",\n                    \"location\": [\"me\", \"fun.py\", 12],\n                    \"value\": 1024,\n                    \"n_allocations\": 1,\n                    \"thread_id\": \"0x1\",\n                    \"interesting\": True,\n                    \"import_system\": False,\n                    \"children\": [\n                        {\n                            \"name\": \"parent_one at fun.py:8\",\n                            \"location\": [\"parent_one\", \"fun.py\", 8],\n                            \"value\": 1024,\n                            \"n_allocations\": 1,\n                            \"thread_id\": \"0x1\",\n                            \"interesting\": True,\n                            \"import_system\": False,\n                            \"children\": [\n                                {\n                                    \"name\": \"grandparent at <frozen importlib>:4\",\n                                    \"location\": [\n                                        \"grandparent\",\n                                        \"&lt;frozen importlib&gt;\",\n                                        4,\n                                    ],\n                                    \"n_allocations\": 1,\n                                    \"thread_id\": \"0x1\",\n                                    \"interesting\": False,\n                                    \"import_system\": False,\n                                    \"value\": 1024,\n                                    \"children\": [],\n                                }\n                            ],\n                        }\n                    ],\n                },\n                {\n                    \"name\": \"sibling at fun.py:16\",\n                    \"location\": [\"sibling\", \"fun.py\", 16],\n                    \"value\": 1024,\n                    \"n_allocations\": 1,\n                    \"thread_id\": \"0x1\",\n                    \"interesting\": True,\n                    \"import_system\": False,\n                    \"children\": [\n                        {\n                            \"name\": \"parent_two at fun.py:10\",\n                            \"location\": [\"parent_two\", \"fun.py\", 10],\n                            \"value\": 1024,\n                            \"n_allocations\": 1,\n                            \"thread_id\": \"0x1\",\n                            \"interesting\": True,\n                            \"import_system\": False,\n                            \"children\": [\n                                {\n                                    \"name\": \"grandparent at <frozen importlib>:4\",\n                                    \"location\": [\n                                        \"grandparent\",\n                                        \"&lt;frozen importlib&gt;\",\n                                        4,\n                                    ],\n                                    \"n_allocations\": 1,\n                                    \"thread_id\": \"0x1\",\n                                    \"interesting\": False,\n                                    \"import_system\": False,\n                                    \"value\": 1024,\n                                    \"children\": [],\n                                }\n                            ],\n                        }\n                    ],\n                },\n            ],\n        } == tree\n\n        assert {\n            \"name\": \"<root>\",\n            \"location\": [\"&lt;tracker&gt;\", \"<b>memray</b>\", 0],\n            \"value\": 2048,\n            \"n_allocations\": 2,\n            \"thread_id\": \"0x0\",\n            \"interesting\": True,\n            \"import_system\": False,\n            \"unique_threads\": [\"0x1\"],\n            \"children\": [],\n        } == inverted_import_system_tree\n"
  },
  {
    "path": "tests/unit/test_frame_tools.py",
    "content": "import pytest\n\nfrom memray.reporters.frame_tools import is_cpython_internal\nfrom memray.reporters.frame_tools import is_frame_from_import_system\nfrom memray.reporters.frame_tools import is_frame_interesting\n\n\nclass TestFrameFiltering:\n    @pytest.mark.parametrize(\n        \"frame, expected\",\n        [\n            [\n                (\n                    \"_PyEval_EvalFrameDefault\",\n                    \"/src/python/python3.8/Python/ceval.c\",\n                    100,\n                ),\n                True,\n            ],\n            [\n                (\"_PyEvalSomeFunc\", \"/src/python/python3.8/Python/ceval.c\", 100),\n                True,\n            ],\n            [(\"VectorCall\", \"/src/python/python3.8/Python/ceval.c\", 100), True],\n            [(\"proxy_call\", \"/src/python/python3.8/Python/ceval.c\", 100), True],\n            [\n                (\n                    \"function_code_fastcall\",\n                    \"/src/python/python3.8/Modules/gcmodule.c\",\n                    100,\n                ),\n                True,\n            ],\n            # Python 3.14 tail call interpreter LLVM-generated functions\n            [\n                (\n                    \"_TAIL_CALL_INSTRUMENTED_CALL.llvm.10282351651392433962\",\n                    \"/src/python/python3.14/Python/ceval.c\",\n                    100,\n                ),\n                True,\n            ],\n            [\n                (\n                    \"_TAIL_CALL_POP_TOP.llvm.123456789\",\n                    \"/src/python/python3.14/Python/ceval.c\",\n                    50,\n                ),\n                True,\n            ],\n            [(\"somefunc\", \"myapp.py\", 100), False],\n            [(\"function_code_fastcall\", \"myapp.py\", 100), False],\n            # _TAIL_CALL_ pattern should not match without .llvm.\n            [\n                (\"_TAIL_CALL_SOMETHING\", \"/src/python/python3.14/Python/ceval.c\", 100),\n                False,\n            ],\n            # _TAIL_CALL_ pattern should not match in non-CPython files\n            [(\"_TAIL_CALL_SOMETHING.llvm.123\", \"myapp.py\", 100), False],\n        ],\n    )\n    def test_cpython_internal_calls(self, frame, expected):\n        # GIVEN/WHEN/THEN\n        assert is_cpython_internal(frame) is expected\n\n    @pytest.mark.parametrize(\n        \"frame, expected\",\n        [\n            [(\"somefunc\", \"runpy.py\", 100), False],\n            [\n                (\n                    \"_PyEval_EvalFrameDefault\",\n                    \"/src/python/python3.8/Python/ceval.c\",\n                    100,\n                ),\n                False,\n            ],\n            # Python 3.14 tail call interpreter frames should not be interesting\n            [\n                (\n                    \"_TAIL_CALL_INSTRUMENTED_CALL.llvm.10282351651392433962\",\n                    \"/src/python/python3.14/Python/ceval.c\",\n                    100,\n                ),\n                False,\n            ],\n            [\n                (\n                    \"PyArg_ParseTuple\",\n                    \"/src/python/python3.8/Python/ceval.c\",\n                    100,\n                ),\n                True,\n            ],\n            [(\"somefunc\", \"myapp.py\", 100), True],\n            [\n                (\n                    \"_PyEval_CompileCode\",\n                    \"/src/python/python3.8/Include/code.h\",\n                    100,\n                ),\n                False,\n            ],\n        ],\n    )\n    def test_frame_interesting(self, frame, expected):\n        # GIVEN/WHEN/THEN\n        assert is_frame_interesting(frame) is expected\n\n    @pytest.mark.parametrize(\n        \"frame, expected\",\n        [\n            [(\"somefunc\", \"runpy.py\", 100), False],\n            [\n                (\n                    \"_PyEval_EvalFrameDefault\",\n                    \"/src/python/python3.8/Python/ceval.c\",\n                    100,\n                ),\n                False,\n            ],\n            [(\"somefunc\", \"<frozen importlib._blabla>\", 100), True],\n            [(\"somefunc\", \"<frozen something else>\", 13), False],\n            [(\"somefunc\", \"<frozen importlib>\", 23), True],\n            [(\"somefunc\", \"<frozen something._blich>\", 11), False],\n            [(\"somefunc\", \"ceval.c\", 11), False],\n            [(\"import_name\", \"ceval.c\", 131), True],\n            [(\"import_from\", \"ceval.c\", 21), True],\n            [(\"import_all_from\", \"ceval.c\", 1), True],\n            [(\"import_name\", \"otherfile.c\", 14), False],\n            [(\"import_from\", \"otherfile.c\", 13), False],\n            [(\"import_all_from\", \"otherfile.c\", 12), False],\n        ],\n    )\n    def test_is_frame_from_import_system(self, frame, expected):\n        # GIVEN/WHEN/THEN\n        assert is_frame_from_import_system(frame) is expected\n"
  },
  {
    "path": "tests/unit/test_high_water_mark_aggregator.py",
    "content": "from dataclasses import dataclass\n\nfrom memray import AllocatorType\nfrom memray._memray import HighWaterMarkAggregatorTestHarness\nfrom memray._memray import Interval\n\nCALLOC = AllocatorType.CALLOC\nMALLOC = AllocatorType.MALLOC\nVALLOC = AllocatorType.VALLOC\nFREE = AllocatorType.FREE\nMMAP = AllocatorType.MMAP\nMUNMAP = AllocatorType.MUNMAP\n\n\n@dataclass(frozen=True)\nclass Contribution:\n    n_allocations_in_high_water_mark: int\n    bytes_in_high_water_mark: int\n    n_allocations_leaked: int\n    bytes_leaked: int\n\n\n@dataclass(frozen=True)\nclass Location:\n    tid: int\n    native_frame_id: int\n    frame_index: int\n    native_segment_generation: int\n\n\ndef contribution_by_location_and_allocator(allocations):\n    ret = {}\n    for alloc in allocations:\n        loc = Location(**{k: alloc[k] for k in Location.__dataclass_fields__.keys()})\n        contribution = Contribution(\n            **{k: alloc[k] for k in Contribution.__dataclass_fields__.keys()}\n        )\n        key = loc, alloc[\"allocator\"]\n        assert key not in ret\n        ret[key] = contribution\n    return ret\n\n\ndef test_no_allocations_at_start():\n    # GIVEN\n    tester = HighWaterMarkAggregatorTestHarness()\n\n    # WHEN\n    # THEN\n    assert 0 == tester.get_current_heap_size()\n    assert [] == tester.get_allocations()\n    assert [0] == list(tester.high_water_mark_bytes_by_snapshot())\n    assert [] == list(tester.get_temporal_allocations())\n\n\ndef test_one_allocation_is_both_high_water_mark_and_leaked():\n    # GIVEN\n    tester = HighWaterMarkAggregatorTestHarness()\n    loc = Location(\n        tid=1,\n        native_frame_id=4,\n        frame_index=5,\n        native_segment_generation=6,\n    )\n    allocator = AllocatorType.CALLOC\n\n    # WHEN\n    tester.add_allocation(**loc.__dict__, allocator=allocator, address=4096, size=1234)\n\n    # THEN\n    assert 1234 == tester.get_current_heap_size()\n    contributions = contribution_by_location_and_allocator(tester.get_allocations())\n    assert contributions[(loc, allocator)] == Contribution(1, 1234, 1, 1234)\n    assert len(contributions) == 1\n\n\ndef test_one_freed_allocation_is_high_water_mark_but_not_leaked():\n    # GIVEN\n    tester = HighWaterMarkAggregatorTestHarness()\n    loc = Location(\n        tid=1,\n        native_frame_id=4,\n        frame_index=5,\n        native_segment_generation=6,\n    )\n    allocator = AllocatorType.CALLOC\n\n    # WHEN\n    tester.add_allocation(**loc.__dict__, allocator=allocator, address=4096, size=1234)\n    tester.add_allocation(\n        **loc.__dict__, allocator=AllocatorType.FREE, address=4096, size=0\n    )\n\n    # THEN\n    assert 0 == tester.get_current_heap_size()\n    contributions = contribution_by_location_and_allocator(tester.get_allocations())\n    assert contributions[(loc, allocator)] == Contribution(1, 1234, 0, 0)\n    assert len(contributions) == 1\n\n\ndef test_zero_byte_allocation():\n    # GIVEN\n    tester = HighWaterMarkAggregatorTestHarness()\n    loc = Location(\n        tid=1,\n        native_frame_id=4,\n        frame_index=5,\n        native_segment_generation=6,\n    )\n    allocator = AllocatorType.CALLOC\n\n    # WHEN\n    tester.add_allocation(**loc.__dict__, allocator=allocator, address=4096, size=1234)\n    tester.add_allocation(**loc.__dict__, allocator=allocator, address=8192, size=0)\n\n    # THEN\n    assert 1234 == tester.get_current_heap_size()\n    contributions = contribution_by_location_and_allocator(tester.get_allocations())\n    assert contributions[(loc, allocator)] == Contribution(2, 1234, 2, 1234)\n    assert len(contributions) == 1\n\n\ndef test_freeing_one_of_two_high_water_mark_allocations_at_the_same_location():\n    # GIVEN\n    tester = HighWaterMarkAggregatorTestHarness()\n    loc = Location(\n        tid=1,\n        native_frame_id=4,\n        frame_index=5,\n        native_segment_generation=6,\n    )\n    allocator = AllocatorType.CALLOC\n\n    # WHEN\n    tester.add_allocation(**loc.__dict__, allocator=allocator, address=4096, size=1234)\n    tester.add_allocation(**loc.__dict__, allocator=allocator, address=8192, size=4321)\n    tester.add_allocation(\n        **loc.__dict__, allocator=AllocatorType.FREE, address=4096, size=0\n    )\n\n    # THEN\n    assert 4321 == tester.get_current_heap_size()\n    contributions = contribution_by_location_and_allocator(tester.get_allocations())\n    assert contributions[(loc, allocator)] == Contribution(2, 1234 + 4321, 1, 4321)\n    assert len(contributions) == 1\n\n\ndef test_freeing_one_of_two_high_water_mark_allocations_at_different_locations():\n    # GIVEN\n    tester = HighWaterMarkAggregatorTestHarness()\n    loc1 = Location(\n        tid=1,\n        native_frame_id=4,\n        frame_index=5,\n        native_segment_generation=6,\n    )\n    loc2 = Location(\n        tid=2,\n        native_frame_id=8,\n        frame_index=10,\n        native_segment_generation=12,\n    )\n    allocator = AllocatorType.CALLOC\n\n    # WHEN\n    tester.add_allocation(**loc1.__dict__, allocator=allocator, address=4096, size=1234)\n    tester.add_allocation(**loc2.__dict__, allocator=allocator, address=8192, size=4321)\n    tester.add_allocation(\n        **loc1.__dict__, allocator=AllocatorType.FREE, address=4096, size=0\n    )\n\n    # THEN\n    assert 4321 == tester.get_current_heap_size()\n    contributions = contribution_by_location_and_allocator(tester.get_allocations())\n    assert contributions[(loc1, allocator)] == Contribution(1, 1234, 0, 0)\n    assert contributions[(loc2, allocator)] == Contribution(1, 4321, 1, 4321)\n    assert len(contributions) == 2\n\n\ndef test_allocation_freed_before_high_water_mark():\n    # GIVEN\n    tester = HighWaterMarkAggregatorTestHarness()\n    loc = Location(\n        tid=1,\n        native_frame_id=4,\n        frame_index=5,\n        native_segment_generation=6,\n    )\n    allocator = AllocatorType.CALLOC\n\n    # WHEN\n    tester.add_allocation(**loc.__dict__, allocator=allocator, address=4096, size=1234)\n    tester.add_allocation(\n        **loc.__dict__, allocator=AllocatorType.FREE, address=4096, size=0\n    )\n    tester.add_allocation(**loc.__dict__, allocator=allocator, address=8192, size=4321)\n\n    # THEN\n    assert 4321 == tester.get_current_heap_size()\n    contributions = contribution_by_location_and_allocator(tester.get_allocations())\n    assert contributions[(loc, allocator)] == Contribution(1, 4321, 1, 4321)\n    assert len(contributions) == 1\n\n\ndef test_allocation_made_and_leaked_after_high_water_mark():\n    # GIVEN\n    tester = HighWaterMarkAggregatorTestHarness()\n    loc1 = Location(\n        tid=1,\n        native_frame_id=4,\n        frame_index=5,\n        native_segment_generation=6,\n    )\n    loc2 = Location(\n        tid=2,\n        native_frame_id=8,\n        frame_index=10,\n        native_segment_generation=12,\n    )\n    allocator = AllocatorType.CALLOC\n\n    # WHEN\n    tester.add_allocation(**loc1.__dict__, allocator=allocator, address=8192, size=4321)\n    tester.add_allocation(\n        **loc1.__dict__, allocator=AllocatorType.FREE, address=8192, size=0\n    )\n    tester.add_allocation(**loc2.__dict__, allocator=allocator, address=4096, size=1234)\n\n    # THEN\n    assert 1234 == tester.get_current_heap_size()\n    contributions = contribution_by_location_and_allocator(tester.get_allocations())\n    assert contributions[(loc1, allocator)] == Contribution(1, 4321, 0, 0)\n    assert contributions[(loc2, allocator)] == Contribution(0, 0, 1, 1234)\n    assert len(contributions) == 2\n\n\ndef test_allocation_made_and_freed_after_high_water_mark():\n    # GIVEN\n    tester = HighWaterMarkAggregatorTestHarness()\n    loc1 = Location(\n        tid=1,\n        native_frame_id=4,\n        frame_index=5,\n        native_segment_generation=6,\n    )\n    loc2 = Location(\n        tid=2,\n        native_frame_id=8,\n        frame_index=10,\n        native_segment_generation=12,\n    )\n    allocator = AllocatorType.CALLOC\n\n    # WHEN\n    tester.add_allocation(**loc1.__dict__, allocator=allocator, address=8192, size=4321)\n    tester.add_allocation(\n        **loc1.__dict__, allocator=AllocatorType.FREE, address=8192, size=0\n    )\n    tester.add_allocation(**loc2.__dict__, allocator=allocator, address=4096, size=1234)\n    tester.add_allocation(\n        **loc2.__dict__, allocator=AllocatorType.FREE, address=4096, size=0\n    )\n\n    # THEN\n    assert 0 == tester.get_current_heap_size()\n    contributions = contribution_by_location_and_allocator(tester.get_allocations())\n    assert contributions[(loc1, allocator)] == Contribution(1, 4321, 0, 0)\n    assert len(contributions) == 1\n\n\ndef test_allocation_made_and_freed_between_high_water_marks():\n    # GIVEN\n    tester = HighWaterMarkAggregatorTestHarness()\n    loc1 = Location(\n        tid=1,\n        native_frame_id=4,\n        frame_index=5,\n        native_segment_generation=6,\n    )\n    loc2 = Location(\n        tid=2,\n        native_frame_id=8,\n        frame_index=10,\n        native_segment_generation=12,\n    )\n    allocator = AllocatorType.CALLOC\n\n    # WHEN\n    tester.add_allocation(**loc1.__dict__, allocator=allocator, address=8192, size=4321)\n    tester.add_allocation(\n        **loc1.__dict__, allocator=AllocatorType.FREE, address=8192, size=0\n    )\n    tester.add_allocation(**loc2.__dict__, allocator=allocator, address=4096, size=1234)\n    tester.add_allocation(\n        **loc2.__dict__, allocator=AllocatorType.FREE, address=4096, size=0\n    )\n    tester.add_allocation(**loc1.__dict__, allocator=allocator, address=8192, size=4321)\n    tester.add_allocation(\n        **loc1.__dict__, allocator=AllocatorType.FREE, address=8192, size=0\n    )\n\n    # THEN\n    assert 0 == tester.get_current_heap_size()\n    contributions = contribution_by_location_and_allocator(tester.get_allocations())\n    assert contributions[(loc1, allocator)] == Contribution(1, 4321, 0, 0)\n    assert len(contributions) == 1\n\n\ndef test_allocation_made_between_high_water_marks_and_freed_after_high_water_mark():\n    # GIVEN\n    tester = HighWaterMarkAggregatorTestHarness()\n    loc1 = Location(\n        tid=1,\n        native_frame_id=4,\n        frame_index=5,\n        native_segment_generation=6,\n    )\n    loc2 = Location(\n        tid=2,\n        native_frame_id=8,\n        frame_index=10,\n        native_segment_generation=12,\n    )\n    allocator = AllocatorType.CALLOC\n\n    # WHEN\n    tester.add_allocation(**loc1.__dict__, allocator=allocator, address=8192, size=4321)\n    tester.add_allocation(\n        **loc1.__dict__, allocator=AllocatorType.FREE, address=8192, size=0\n    )\n    tester.add_allocation(**loc2.__dict__, allocator=allocator, address=4096, size=1234)\n    tester.add_allocation(**loc1.__dict__, allocator=allocator, address=8192, size=4321)\n    tester.add_allocation(\n        **loc1.__dict__, allocator=AllocatorType.FREE, address=8192, size=0\n    )\n    tester.add_allocation(\n        **loc2.__dict__, allocator=AllocatorType.FREE, address=4096, size=0\n    )\n\n    # THEN\n    assert 0 == tester.get_current_heap_size()\n    contributions = contribution_by_location_and_allocator(tester.get_allocations())\n    assert contributions[(loc1, allocator)] == Contribution(1, 4321, 0, 0)\n    assert contributions[(loc2, allocator)] == Contribution(1, 1234, 0, 0)\n    assert len(contributions) == 2\n\n\ndef test_allocation_made_between_high_water_marks_and_leaked():\n    # GIVEN\n    tester = HighWaterMarkAggregatorTestHarness()\n    loc1 = Location(\n        tid=1,\n        native_frame_id=4,\n        frame_index=5,\n        native_segment_generation=6,\n    )\n    loc2 = Location(\n        tid=2,\n        native_frame_id=8,\n        frame_index=10,\n        native_segment_generation=12,\n    )\n    allocator = AllocatorType.CALLOC\n\n    # WHEN\n    tester.add_allocation(**loc1.__dict__, allocator=allocator, address=8192, size=4321)\n    tester.add_allocation(\n        **loc1.__dict__, allocator=AllocatorType.FREE, address=8192, size=0\n    )\n    tester.add_allocation(**loc2.__dict__, allocator=allocator, address=4096, size=1234)\n    tester.add_allocation(**loc1.__dict__, allocator=allocator, address=8192, size=4321)\n\n    # THEN\n    assert 1234 + 4321 == tester.get_current_heap_size()\n    contributions = contribution_by_location_and_allocator(tester.get_allocations())\n    assert contributions[(loc1, allocator)] == Contribution(1, 4321, 1, 4321)\n    assert contributions[(loc2, allocator)] == Contribution(1, 1234, 1, 1234)\n    assert len(contributions) == 2\n\n\ndef test_different_allocators_at_one_location():\n    # GIVEN\n    tester = HighWaterMarkAggregatorTestHarness()\n    loc = Location(\n        tid=1,\n        native_frame_id=4,\n        frame_index=5,\n        native_segment_generation=6,\n    )\n\n    # WHEN\n    tester.add_allocation(\n        **loc.__dict__, allocator=AllocatorType.MALLOC, address=4096, size=1234\n    )\n    tester.add_allocation(\n        **loc.__dict__, allocator=AllocatorType.VALLOC, address=8192, size=4321\n    )\n\n    # THEN\n    assert 1234 + 4321 == tester.get_current_heap_size()\n    contributions = contribution_by_location_and_allocator(tester.get_allocations())\n    assert contributions[(loc, AllocatorType.MALLOC)] == Contribution(1, 1234, 1, 1234)\n    assert contributions[(loc, AllocatorType.VALLOC)] == Contribution(1, 4321, 1, 4321)\n    assert len(contributions) == 2\n\n\ndef test_same_stack_in_different_threads():\n    # GIVEN\n    tester = HighWaterMarkAggregatorTestHarness()\n    loc1 = Location(\n        tid=1,\n        native_frame_id=40,\n        frame_index=50,\n        native_segment_generation=60,\n    )\n    loc2 = Location(\n        tid=2,\n        native_frame_id=40,\n        frame_index=50,\n        native_segment_generation=60,\n    )\n\n    # WHEN\n    tester.add_allocation(\n        **loc1.__dict__, allocator=AllocatorType.MALLOC, address=4096, size=1234\n    )\n    tester.add_allocation(\n        **loc2.__dict__, allocator=AllocatorType.MALLOC, address=8192, size=2468\n    )\n\n    # THEN\n    assert 1234 + 2468 == tester.get_current_heap_size()\n    contributions = contribution_by_location_and_allocator(tester.get_allocations())\n    assert contributions[(loc1, AllocatorType.MALLOC)] == Contribution(1, 1234, 1, 1234)\n    assert contributions[(loc2, AllocatorType.MALLOC)] == Contribution(1, 2468, 1, 2468)\n    assert len(contributions) == 2\n\n\ndef test_completely_freed_range():\n    # GIVEN\n    tester = HighWaterMarkAggregatorTestHarness()\n    loc = Location(\n        tid=1,\n        native_frame_id=4,\n        frame_index=5,\n        native_segment_generation=6,\n    )\n    allocator = AllocatorType.MMAP\n\n    # WHEN\n    tester.add_allocation(**loc.__dict__, allocator=allocator, address=4096, size=1234)\n    tester.add_allocation(\n        **loc.__dict__, allocator=AllocatorType.MUNMAP, address=4096, size=1234\n    )\n\n    # THEN\n    assert 0 == tester.get_current_heap_size()\n    contributions = contribution_by_location_and_allocator(tester.get_allocations())\n    assert contributions[(loc, allocator)] == Contribution(1, 1234, 0, 0)\n    assert len(contributions) == 1\n\n\ndef test_shrunk_range():\n    # GIVEN\n    tester = HighWaterMarkAggregatorTestHarness()\n    loc = Location(\n        tid=1,\n        native_frame_id=4,\n        frame_index=5,\n        native_segment_generation=6,\n    )\n    allocator = AllocatorType.MMAP\n\n    # WHEN\n    tester.add_allocation(**loc.__dict__, allocator=allocator, address=4096, size=1234)\n    tester.add_allocation(\n        **loc.__dict__, allocator=AllocatorType.MUNMAP, address=4096, size=1000\n    )\n\n    # THEN\n    assert 234 == tester.get_current_heap_size()\n    contributions = contribution_by_location_and_allocator(tester.get_allocations())\n    assert contributions[(loc, allocator)] == Contribution(1, 1234, 1, 234)\n    assert len(contributions) == 1\n\n\ndef test_shrunk_then_freed_range():\n    # GIVEN\n    tester = HighWaterMarkAggregatorTestHarness()\n    loc = Location(\n        tid=1,\n        native_frame_id=4,\n        frame_index=5,\n        native_segment_generation=6,\n    )\n    allocator = AllocatorType.MMAP\n\n    # WHEN\n    tester.add_allocation(**loc.__dict__, allocator=allocator, address=4096, size=1234)\n    tester.add_allocation(\n        **loc.__dict__, allocator=AllocatorType.MUNMAP, address=4096 + 1000, size=234\n    )\n    tester.add_allocation(\n        **loc.__dict__, allocator=AllocatorType.MUNMAP, address=4096, size=1000\n    )\n\n    # THEN\n    assert 0 == tester.get_current_heap_size()\n    contributions = contribution_by_location_and_allocator(tester.get_allocations())\n    assert contributions[(loc, allocator)] == Contribution(1, 1234, 0, 0)\n    assert len(contributions) == 1\n\n\ndef test_split_range():\n    # GIVEN\n    tester = HighWaterMarkAggregatorTestHarness()\n    loc = Location(\n        tid=1,\n        native_frame_id=4,\n        frame_index=5,\n        native_segment_generation=6,\n    )\n    allocator = AllocatorType.MMAP\n\n    # WHEN\n    tester.add_allocation(**loc.__dict__, allocator=allocator, address=4096, size=1234)\n    tester.add_allocation(\n        **loc.__dict__, allocator=AllocatorType.MUNMAP, address=4096 + 100, size=100\n    )\n\n    # THEN\n    assert 1234 - 100 == tester.get_current_heap_size()\n    contributions = contribution_by_location_and_allocator(tester.get_allocations())\n    assert contributions[(loc, allocator)] == Contribution(1, 1234, 2, 1134)\n    assert len(contributions) == 1\n\n\ndef test_split_then_freed_range():\n    # GIVEN\n    tester = HighWaterMarkAggregatorTestHarness()\n    loc = Location(\n        tid=1,\n        native_frame_id=4,\n        frame_index=5,\n        native_segment_generation=6,\n    )\n    allocator = AllocatorType.MMAP\n\n    # WHEN\n    tester.add_allocation(**loc.__dict__, allocator=allocator, address=4096, size=1234)\n    tester.add_allocation(\n        **loc.__dict__, allocator=AllocatorType.MUNMAP, address=4096 + 100, size=100\n    )\n    tester.add_allocation(\n        **loc.__dict__, allocator=AllocatorType.MUNMAP, address=4096, size=1234\n    )\n\n    # THEN\n    assert 0 == tester.get_current_heap_size()\n    contributions = contribution_by_location_and_allocator(tester.get_allocations())\n    assert contributions[(loc, allocator)] == Contribution(1, 1234, 0, 0)\n    assert len(contributions) == 1\n\n\ndef test_reporting_on_true_high_water_mark_that_was_in_a_past_snapshot():\n    # GIVEN\n    tester = HighWaterMarkAggregatorTestHarness()\n    loc1 = Location(\n        tid=1,\n        native_frame_id=4,\n        frame_index=5,\n        native_segment_generation=6,\n    )\n    loc2 = Location(\n        tid=2,\n        native_frame_id=8,\n        frame_index=10,\n        native_segment_generation=12,\n    )\n    allocator = AllocatorType.CALLOC\n\n    # WHEN\n    tester.capture_snapshot()\n    tester.add_allocation(**loc1.__dict__, allocator=allocator, address=8192, size=4321)\n    tester.capture_snapshot()\n    tester.add_allocation(**loc2.__dict__, allocator=allocator, address=4096, size=100)\n    tester.capture_snapshot()\n    tester.add_allocation(\n        **loc1.__dict__, allocator=AllocatorType.FREE, address=8192, size=0\n    )\n    tester.add_allocation(\n        **loc2.__dict__, allocator=AllocatorType.FREE, address=4096, size=0\n    )\n    tester.capture_snapshot()\n    tester.add_allocation(**loc2.__dict__, allocator=allocator, address=4096, size=2000)\n    tester.add_allocation(\n        **loc2.__dict__, allocator=AllocatorType.FREE, address=4096, size=0\n    )\n    tester.add_allocation(**loc1.__dict__, allocator=allocator, address=8192, size=1000)\n\n    # THEN\n    assert 1000 == tester.get_current_heap_size()\n    contributions = contribution_by_location_and_allocator(tester.get_allocations())\n    assert contributions[(loc1, allocator)] == Contribution(1, 4321, 1, 1000)\n    assert contributions[(loc2, allocator)] == Contribution(1, 100, 0, 0)\n    assert len(contributions) == 2\n\n\ndef test_one_allocation_before_first_snapshot():\n    # GIVEN\n    tester = HighWaterMarkAggregatorTestHarness()\n    loc = Location(\n        tid=1,\n        native_frame_id=4,\n        frame_index=5,\n        native_segment_generation=6,\n    )\n\n    # WHEN\n    tester.add_allocation(**loc.__dict__, allocator=CALLOC, address=4096, size=1234)\n\n    # THEN\n    (alloc,) = tester.get_temporal_allocations()\n    assert alloc.allocator == CALLOC\n    assert alloc.stack_id == 5\n    assert alloc.tid == 1\n    assert alloc.intervals == [\n        Interval(0, None, 1, 1234),\n    ]\n\n\ndef test_one_allocation_after_first_snapshot():\n    # GIVEN\n    tester = HighWaterMarkAggregatorTestHarness()\n    loc = Location(\n        tid=1,\n        native_frame_id=4,\n        frame_index=5,\n        native_segment_generation=6,\n    )\n\n    # WHEN\n    tester.capture_snapshot()\n    tester.add_allocation(**loc.__dict__, allocator=CALLOC, address=4096, size=1234)\n\n    # THEN\n    (alloc,) = tester.get_temporal_allocations()\n    assert alloc.allocator == CALLOC\n    assert alloc.stack_id == 5\n    assert alloc.tid == 1\n    assert alloc.intervals == [\n        Interval(1, None, 1, 1234),\n    ]\n\n\ndef test_one_allocation_freed_at_high_water_mark_in_second_snapshot():\n    # GIVEN\n    tester = HighWaterMarkAggregatorTestHarness()\n    loc = Location(\n        tid=1,\n        native_frame_id=4,\n        frame_index=5,\n        native_segment_generation=6,\n    )\n\n    # WHEN\n    tester.add_allocation(**loc.__dict__, allocator=CALLOC, address=4096, size=1234)\n    tester.capture_snapshot()\n    tester.add_allocation(**loc.__dict__, allocator=FREE, address=4096, size=0)\n\n    # THEN\n    (alloc,) = tester.get_temporal_allocations()\n    assert alloc.allocator == CALLOC\n    assert alloc.stack_id == 5\n    assert alloc.tid == 1\n    assert alloc.intervals == [\n        Interval(0, 2, 1, 1234),\n        Interval(2, None, 0, 0),\n    ]\n\n\ndef test_two_allocations_in_different_snapshots():\n    # GIVEN\n    tester = HighWaterMarkAggregatorTestHarness()\n    loc1 = Location(\n        tid=1,\n        native_frame_id=4,\n        frame_index=5,\n        native_segment_generation=6,\n    )\n    loc2 = Location(\n        tid=1,\n        native_frame_id=7,\n        frame_index=8,\n        native_segment_generation=9,\n    )\n\n    # WHEN\n    tester.add_allocation(**loc1.__dict__, allocator=CALLOC, address=4096, size=1234)\n    tester.capture_snapshot()\n    tester.add_allocation(**loc2.__dict__, allocator=CALLOC, address=8192, size=2468)\n\n    # THEN\n    (alloc1, alloc2) = tester.get_temporal_allocations()\n    assert alloc1.allocator == CALLOC\n    assert alloc1.stack_id == 5\n    assert alloc1.tid == 1\n    assert alloc1.intervals == [\n        Interval(0, None, 1, 1234),\n    ]\n\n    assert alloc2.allocator == CALLOC\n    assert alloc2.stack_id == 8\n    assert alloc2.tid == 1\n    assert alloc2.intervals == [\n        Interval(1, None, 1, 2468),\n    ]\n\n\ndef test_one_allocation_freed_before_high_water_mark_in_second_snapshot():\n    # GIVEN\n    tester = HighWaterMarkAggregatorTestHarness()\n    loc1 = Location(\n        tid=1,\n        native_frame_id=4,\n        frame_index=5,\n        native_segment_generation=6,\n    )\n    loc2 = Location(\n        tid=1,\n        native_frame_id=7,\n        frame_index=8,\n        native_segment_generation=9,\n    )\n\n    # WHEN\n    tester.add_allocation(**loc1.__dict__, allocator=CALLOC, address=4096, size=1234)\n    tester.capture_snapshot()\n    tester.add_allocation(**loc1.__dict__, allocator=FREE, address=4096, size=0)\n    tester.add_allocation(**loc2.__dict__, allocator=CALLOC, address=4096, size=2468)\n\n    # THEN\n    (alloc1, alloc2) = tester.get_temporal_allocations()\n    assert alloc1.allocator == CALLOC\n    assert alloc1.stack_id == 5\n    assert alloc1.tid == 1\n    assert alloc1.intervals == [\n        Interval(0, 1, 1, 1234),\n        Interval(1, None, 0, 0),\n    ]\n\n    assert alloc2.allocator == CALLOC\n    assert alloc2.stack_id == 8\n    assert alloc2.tid == 1\n    assert alloc2.intervals == [\n        Interval(1, None, 1, 2468),\n    ]\n\n\ndef test_allocations_freed_over_two_snapshots():\n    # GIVEN\n    tester = HighWaterMarkAggregatorTestHarness()\n    loc = Location(\n        tid=1,\n        native_frame_id=4,\n        frame_index=5,\n        native_segment_generation=6,\n    )\n\n    # WHEN\n    tester.add_allocation(**loc.__dict__, allocator=CALLOC, address=4096, size=1234)\n    tester.add_allocation(**loc.__dict__, allocator=CALLOC, address=8192, size=2468)\n    tester.capture_snapshot()\n    tester.add_allocation(**loc.__dict__, allocator=FREE, address=4096, size=0)\n    tester.capture_snapshot()\n    tester.add_allocation(**loc.__dict__, allocator=FREE, address=8192, size=0)\n    tester.capture_snapshot()\n\n    # THEN\n    (alloc,) = tester.get_temporal_allocations()\n\n    assert alloc.allocator == CALLOC\n    assert alloc.stack_id == 5\n    assert alloc.tid == 1\n    assert alloc.intervals == [\n        Interval(0, 2, 2, 1234 + 2468),\n        Interval(2, 3, 1, 2468),\n        Interval(3, None, 0, 0),\n    ]\n\n\ndef test_allocations_freed_over_two_non_adjacent_snapshots():\n    # GIVEN\n    tester = HighWaterMarkAggregatorTestHarness()\n    loc = Location(\n        tid=1,\n        native_frame_id=4,\n        frame_index=5,\n        native_segment_generation=6,\n    )\n\n    # WHEN\n    tester.add_allocation(**loc.__dict__, allocator=CALLOC, address=4096, size=1234)\n    tester.add_allocation(**loc.__dict__, allocator=CALLOC, address=8192, size=2468)\n    tester.capture_snapshot()\n    tester.capture_snapshot()\n    tester.add_allocation(**loc.__dict__, allocator=FREE, address=4096, size=0)\n    tester.capture_snapshot()\n    tester.capture_snapshot()\n    tester.add_allocation(**loc.__dict__, allocator=FREE, address=8192, size=0)\n    tester.capture_snapshot()\n\n    # THEN\n    (alloc,) = tester.get_temporal_allocations()\n\n    assert alloc.allocator == CALLOC\n    assert alloc.stack_id == 5\n    assert alloc.tid == 1\n    assert alloc.intervals == [\n        Interval(0, 3, 2, 1234 + 2468),\n        Interval(3, 5, 1, 2468),\n        Interval(5, None, 0, 0),\n    ]\n\n\ndef test_allocation_after_high_water_mark_in_current_snapshot():\n    # GIVEN\n    tester = HighWaterMarkAggregatorTestHarness()\n    loc = Location(\n        tid=1,\n        native_frame_id=4,\n        frame_index=5,\n        native_segment_generation=6,\n    )\n\n    # WHEN\n    tester.add_allocation(**loc.__dict__, allocator=CALLOC, address=8192, size=2468)\n    tester.add_allocation(**loc.__dict__, allocator=FREE, address=8192, size=0)\n    tester.add_allocation(**loc.__dict__, allocator=CALLOC, address=8192, size=1234)\n\n    # THEN\n    (alloc,) = tester.get_temporal_allocations()\n\n    assert alloc.allocator == CALLOC\n    assert alloc.stack_id == 5\n    assert alloc.tid == 1\n    assert alloc.intervals == [\n        Interval(0, 1, 1, 2468),\n        Interval(1, None, 1, 1234),\n    ]\n\n\ndef test_allocation_after_high_water_mark_in_historical_snapshot():\n    # GIVEN\n    tester = HighWaterMarkAggregatorTestHarness()\n    loc = Location(\n        tid=1,\n        native_frame_id=4,\n        frame_index=5,\n        native_segment_generation=6,\n    )\n\n    # WHEN\n    tester.add_allocation(**loc.__dict__, allocator=CALLOC, address=8192, size=2468)\n    tester.add_allocation(**loc.__dict__, allocator=FREE, address=8192, size=0)\n    tester.add_allocation(**loc.__dict__, allocator=CALLOC, address=8192, size=1234)\n    tester.capture_snapshot()\n\n    # THEN\n    (alloc,) = tester.get_temporal_allocations()\n\n    assert alloc.allocator == CALLOC\n    assert alloc.stack_id == 5\n    assert alloc.tid == 1\n    assert alloc.intervals == [\n        Interval(0, 1, 1, 2468),\n        Interval(1, None, 1, 1234),\n    ]\n\n\ndef test_allocation_and_deallocation_after_high_water_mark():\n    # GIVEN\n    tester = HighWaterMarkAggregatorTestHarness()\n    loc = Location(\n        tid=1,\n        native_frame_id=4,\n        frame_index=5,\n        native_segment_generation=6,\n    )\n\n    # WHEN\n    tester.add_allocation(**loc.__dict__, allocator=CALLOC, address=8192, size=2468)\n    tester.add_allocation(**loc.__dict__, allocator=CALLOC, address=4096, size=1234)\n    tester.add_allocation(**loc.__dict__, allocator=FREE, address=8192, size=0)\n    tester.add_allocation(**loc.__dict__, allocator=FREE, address=4096, size=0)\n    tester.add_allocation(**loc.__dict__, allocator=CALLOC, address=4096, size=1230)\n    tester.add_allocation(**loc.__dict__, allocator=CALLOC, address=8192, size=2460)\n    tester.add_allocation(**loc.__dict__, allocator=CALLOC, address=0, size=1)\n\n    # THEN\n    (alloc,) = tester.get_temporal_allocations()\n\n    assert alloc.allocator == CALLOC\n    assert alloc.stack_id == 5\n    assert alloc.tid == 1\n    assert alloc.intervals == [\n        Interval(0, 1, 2, 2468 + 1234),\n        Interval(1, None, 3, 1230 + 2460 + 1),\n    ]\n\n\ndef test_allocation_and_deallocation_across_multiple_snapshots():\n    # GIVEN\n    tester = HighWaterMarkAggregatorTestHarness()\n    loc = Location(\n        tid=1,\n        native_frame_id=4,\n        frame_index=5,\n        native_segment_generation=6,\n    )\n\n    # WHEN\n    tester.add_allocation(**loc.__dict__, allocator=CALLOC, address=8192, size=2468)\n    tester.add_allocation(**loc.__dict__, allocator=CALLOC, address=4096, size=1234)\n    tester.add_allocation(**loc.__dict__, allocator=FREE, address=8192, size=0)\n    tester.capture_snapshot()\n    tester.add_allocation(**loc.__dict__, allocator=FREE, address=4096, size=0)\n    tester.add_allocation(**loc.__dict__, allocator=CALLOC, address=4096, size=1230)\n    tester.capture_snapshot()\n    tester.add_allocation(**loc.__dict__, allocator=CALLOC, address=8192, size=2460)\n    tester.add_allocation(**loc.__dict__, allocator=CALLOC, address=0, size=1)\n\n    # THEN\n    (alloc,) = tester.get_temporal_allocations()\n\n    assert alloc.allocator == CALLOC\n    assert alloc.stack_id == 5\n    assert alloc.tid == 1\n    assert alloc.intervals == [\n        Interval(0, 1, 2, 2468 + 1234),\n        Interval(1, 2, 1, 1234),\n        Interval(2, None, 3, 1230 + 2460 + 1),\n    ]\n\n\ndef test_allocation_and_deallocation_across_multiple_snapshots_with_other_allocators():\n    # GIVEN\n    tester = HighWaterMarkAggregatorTestHarness()\n    loc = Location(\n        tid=1,\n        native_frame_id=4,\n        frame_index=5,\n        native_segment_generation=6,\n    )\n\n    # WHEN\n    tester.add_allocation(**loc.__dict__, allocator=CALLOC, address=8192, size=2468)\n    tester.add_allocation(**loc.__dict__, allocator=CALLOC, address=4096, size=1234)\n    tester.add_allocation(**loc.__dict__, allocator=FREE, address=8192, size=0)\n    tester.capture_snapshot()\n    tester.add_allocation(**loc.__dict__, allocator=MALLOC, address=8192, size=1230)\n    tester.capture_snapshot()\n    tester.add_allocation(**loc.__dict__, allocator=VALLOC, address=0, size=1)\n    tester.capture_snapshot()\n    tester.add_allocation(**loc.__dict__, allocator=CALLOC, address=1000, size=42)\n    tester.add_allocation(**loc.__dict__, allocator=FREE, address=8192, size=0)\n\n    # THEN\n    (alloc1, alloc2, alloc3) = tester.get_temporal_allocations()\n\n    assert alloc1.allocator == MALLOC\n    assert alloc1.stack_id == 5\n    assert alloc1.tid == 1\n    assert alloc1.intervals == [\n        Interval(1, 4, 1, 1230),\n        Interval(4, None, 0, 0),\n    ]\n\n    assert alloc2.allocator == CALLOC\n    assert alloc2.stack_id == 5\n    assert alloc2.tid == 1\n    assert alloc2.intervals == [\n        Interval(0, 1, 2, 2468 + 1234),\n        Interval(1, 3, 1, 1234),\n        Interval(3, None, 2, 1234 + 42),\n    ]\n\n    assert alloc3.allocator == VALLOC\n    assert alloc3.stack_id == 5\n    assert alloc3.tid == 1\n    assert alloc3.intervals == [\n        Interval(2, None, 1, 1),\n    ]\n"
  },
  {
    "path": "tests/unit/test_highwatermark_command.py",
    "content": "import os\nimport sys\nfrom pathlib import Path\nfrom unittest.mock import ANY\nfrom unittest.mock import MagicMock\nfrom unittest.mock import Mock\nfrom unittest.mock import call\nfrom unittest.mock import patch\n\nimport pytest\n\nfrom memray._errors import MemrayCommandError\nfrom memray._memray import FileFormat\nfrom memray.commands.common import HighWatermarkCommand\n\n\nclass TestFilenameValidation:\n    def test_fails_when_results_does_not_exist(self, tmp_path):\n        # GIVEN\n        command = HighWatermarkCommand(Mock(), reporter_name=\"reporter\")\n        results = tmp_path / \"results.bin\"\n\n        # WHEN / THEN\n        with pytest.raises(MemrayCommandError, match=\"No such file\"):\n            command.validate_filenames(\n                output=None,\n                results=os.fspath(results),\n            )\n\n    def test_generates_output_name_when_none(self, tmp_path):\n        # GIVEN\n        command = HighWatermarkCommand(Mock(), reporter_name=\"reporter\")\n        results = tmp_path / \"results.bin\"\n        results.touch()\n\n        # WHEN\n        results_file, output_file = command.validate_filenames(\n            output=None,\n            results=os.fspath(results),\n        )\n\n        # THEN\n        assert results_file == results\n        assert output_file == tmp_path / \"memray-reporter-results.html\"\n\n    def test_uses_determine_output_filename_when_output_is_none(self, tmp_path):\n        # GIVEN\n        command = HighWatermarkCommand(Mock(), reporter_name=\"reporter\")\n        results = tmp_path / \"results.bin\"\n        results.touch()\n        command.determine_output_filename = MagicMock(return_value=\"patched.html\")\n\n        # WHEN\n        results_file, output_file = command.validate_filenames(\n            output=None,\n            results=os.fspath(results),\n        )\n\n        # THEN\n        assert results_file == results\n        assert output_file == Path(\"patched.html\")\n        command.determine_output_filename.assert_called_once_with(results_file)\n\n    def test_uses_output_name_as_given(self, tmp_path):\n        # GIVEN\n        command = HighWatermarkCommand(Mock(), reporter_name=\"reporter\")\n        output = tmp_path / \"output.html\"\n        results = tmp_path / \"results.bin\"\n        results.touch()\n\n        # WHEN\n        results_file, output_file = command.validate_filenames(\n            output=os.fspath(output),\n            results=os.fspath(results),\n        )\n\n        # THEN\n        assert results_file == results\n        assert output_file == output\n\n    def test_fails_when_fallback_output_exists(self, tmp_path):\n        # GIVEN\n        command = HighWatermarkCommand(Mock(), reporter_name=\"reporter\")\n        results = tmp_path / \"results.bin\"\n        results.touch()\n        (tmp_path / \"memray-reporter-results.html\").touch()\n\n        # WHEN / THEN\n        with pytest.raises(MemrayCommandError, match=\"File already exists\"):\n            command.validate_filenames(\n                output=None,\n                results=os.fspath(results),\n            )\n\n    def test_succeeds_when_fallback_output_exists_but_can_overwrite(self, tmp_path):\n        # GIVEN\n        command = HighWatermarkCommand(Mock(), reporter_name=\"reporter\")\n        results = tmp_path / \"results.bin\"\n        results.touch()\n        (tmp_path / \"memray-reporter-results.html\").touch()\n\n        # WHEN / THEN\n        results_file, output_file = command.validate_filenames(\n            output=None,\n            results=os.fspath(results),\n            overwrite=True,\n        )\n\n        # THEN\n        assert results_file == results\n        assert output_file is not None\n\n    def test_fails_when_given_output_exists(self, tmp_path):\n        # GIVEN\n        command = HighWatermarkCommand(Mock(), reporter_name=\"reporter\")\n        results = tmp_path / \"results.bin\"\n        results.touch()\n        output = tmp_path / \"output.html\"\n        output.touch()\n\n        # WHEN / THEN\n        with pytest.raises(MemrayCommandError, match=\"File already exists\"):\n            command.validate_filenames(\n                output=output,\n                results=os.fspath(results),\n            )\n\n    def test_succeeds_when_given_output_exists_but_can_overwrite(self, tmp_path):\n        # GIVEN\n        command = HighWatermarkCommand(Mock(), reporter_name=\"reporter\")\n        results = tmp_path / \"results.bin\"\n        results.touch()\n        output = tmp_path / \"output.html\"\n        output.touch()\n\n        # WHEN / THEN\n        results_file, output_file = command.validate_filenames(\n            output=output,\n            results=os.fspath(results),\n            overwrite=True,\n        )\n\n        # THEN\n        assert results_file == results\n        assert output_file == output\n\n\nclass TestReportGeneration:\n    @pytest.mark.parametrize(\"merge_threads\", [True, False])\n    def test_tracker_and_reporter_interactions_for_peak(self, tmp_path, merge_threads):\n        # GIVEN\n        reporter_factory_mock = Mock()\n        command = HighWatermarkCommand(reporter_factory_mock, reporter_name=\"reporter\")\n        result_path = tmp_path / \"results.bin\"\n        output_file = tmp_path / \"output.txt\"\n\n        # WHEN\n        with patch(\"memray.commands.common.FileReader\") as reader_mock:\n            command.write_report(\n                result_path=result_path,\n                output_file=output_file,\n                show_memory_leaks=False,\n                temporary_allocation_threshold=-1,\n                merge_threads=merge_threads,\n            )\n\n        # THEN\n        calls = [\n            call(os.fspath(result_path), report_progress=True),\n            call().metadata.has_native_traces.__bool__(),\n            call().metadata.file_format.__eq__(FileFormat.ALL_ALLOCATIONS)\n            if sys.version_info >= (3, 8, 0)\n            else ANY,\n            call().get_high_watermark_allocation_records(merge_threads=merge_threads),\n            call().get_memory_snapshots(),\n        ]\n        reader_mock.assert_has_calls(calls)\n\n        reporter_factory_mock.assert_called_once()\n        reporter_factory_mock().render.assert_called_once()\n\n    @pytest.mark.parametrize(\"merge_threads\", [True, False])\n    def test_tracker_and_reporter_interactions_for_leak(self, tmp_path, merge_threads):\n        # GIVEN\n        reporter_factory_mock = Mock()\n        command = HighWatermarkCommand(reporter_factory_mock, reporter_name=\"reporter\")\n        result_path = tmp_path / \"results.bin\"\n        output_file = tmp_path / \"output.txt\"\n\n        # WHEN\n        with patch(\"memray.commands.common.FileReader\") as reader_mock:\n            command.write_report(\n                result_path=result_path,\n                output_file=output_file,\n                show_memory_leaks=True,\n                temporary_allocation_threshold=-1,\n                merge_threads=merge_threads,\n            )\n\n        # THEN\n        calls = [\n            call(os.fspath(result_path), report_progress=True),\n            call().metadata.has_native_traces.__bool__(),\n            call().metadata.file_format.__eq__(FileFormat.ALL_ALLOCATIONS)\n            if sys.version_info >= (3, 8, 0)\n            else ANY,\n            call().get_leaked_allocation_records(merge_threads=merge_threads),\n            call().get_memory_snapshots(),\n        ]\n        reader_mock.assert_has_calls(calls)\n\n        reporter_factory_mock.assert_called_once()\n        reporter_factory_mock().render.assert_called_once()\n\n    @pytest.mark.parametrize(\"merge_threads\", [True, False])\n    def test_tracker_and_reporter_interactions_for_temporary_allocations(\n        self, tmp_path, merge_threads\n    ):\n        # GIVEN\n        reporter_factory_mock = Mock()\n        command = HighWatermarkCommand(reporter_factory_mock, reporter_name=\"reporter\")\n        result_path = tmp_path / \"results.bin\"\n        output_file = tmp_path / \"output.txt\"\n\n        # WHEN\n        with patch(\"memray.commands.common.FileReader\") as reader_mock:\n            command.write_report(\n                result_path=result_path,\n                output_file=output_file,\n                show_memory_leaks=False,\n                temporary_allocation_threshold=3,\n                merge_threads=merge_threads,\n            )\n\n        # THEN\n        calls = [\n            call(os.fspath(result_path), report_progress=True),\n            call().metadata.has_native_traces.__bool__(),\n            call().get_temporary_allocation_records(\n                threshold=3, merge_threads=merge_threads\n            ),\n            call().get_memory_snapshots(),\n        ]\n        reader_mock.assert_has_calls(calls)\n\n        reporter_factory_mock.assert_called_once()\n        reporter_factory_mock().render.assert_called_once()\n"
  },
  {
    "path": "tests/unit/test_reader.py",
    "content": "import os\nimport threading\n\nimport pytest\n\nfrom memray import FileDestination\nfrom memray import FileReader\nfrom memray import Tracker\nfrom memray._test import MemoryAllocator\n\n\ndef test_rejects_different_header_magic(tmp_path):\n    # GIVEN\n    output = tmp_path / \"test.bin\"\n    allocator = MemoryAllocator()\n\n    # WHEN\n    # Create a valid allocation record file\n    with Tracker(output):\n        allocator.valloc(1024)\n\n    # Change the header magic (same length as \"memray\")\n    with output.open(\"rb+\") as f:\n        f.write(b\"badxxx\")\n\n    # THEN\n    with pytest.raises(\n        OSError, match=\"does not look like a binary generated by memray\"\n    ):\n        FileReader(output).get_allocation_records()\n\n\ndef test_rejects_different_header_version(tmp_path):\n    # GIVEN\n    output = tmp_path / \"test.bin\"\n    allocator = MemoryAllocator()\n\n    # WHEN\n    # Create a valid allocation record file\n    destination = FileDestination(output, overwrite=False, compress_on_exit=False)\n    with Tracker(destination=destination):\n        allocator.valloc(1024)\n\n    # Change the header version to zero\n    with output.open(\"rb+\") as f:\n        f.seek(7)\n        f.write(b\"\\0\")\n\n    # THEN\n    with pytest.raises(OSError, match=\"incompatible with this version\"):\n        FileReader(output).get_allocation_records()\n\n\ndef test_filereader_fails_to_open_file(tmp_path):\n    \"\"\"This checks that we throw in the FileSource C++ ctor when we fail to open the stream.\"\"\"\n    # GIVEN\n    test_file = tmp_path / \"test.bin\"\n    test_file.touch(mode=000)\n\n    try:\n        test_file.read_text()\n    except OSError:\n        pass\n    else:  # pragma: no cover\n        pytest.skip(\"The current user can ignore file permissions\")\n\n    # WHEN/THEN\n    with pytest.raises(OSError, match=\"Could not open file\"):\n        FileReader(test_file)\n\n\ndef test_read_pid(tmp_path):\n    # GIVEN\n    output = tmp_path / \"test.bin\"\n    allocator = MemoryAllocator()\n\n    # WHEN\n    with Tracker(output):\n        allocator.valloc(1024)\n\n    # THEN\n    assert FileReader(output).metadata.pid == os.getpid()\n\n\ndef test_read_tid(tmp_path):\n    # GIVEN\n    output = tmp_path / \"test.bin\"\n    allocator = MemoryAllocator()\n\n    def func():\n        allocator.valloc(1024)\n\n    # WHEN\n    t = threading.Thread(target=func)\n    with Tracker(output):\n        func()\n        t.start()\n        t.join()\n\n    # THEN\n    reader = FileReader(output)\n    main_tid = reader.metadata.main_thread_id\n    all_allocations = reader.get_allocation_records()\n    all_tids = tuple(allocation.tid for allocation in all_allocations)\n    assert main_tid in set(all_tids)\n    # The main thread should be the first one in the list\n    assert main_tid == all_tids[0]\n"
  },
  {
    "path": "tests/unit/test_stats_reporter.py",
    "content": "import json\nfrom collections import Counter\nfrom datetime import datetime\nfrom typing import List\nfrom typing import Optional\nfrom typing import Tuple\nfrom unittest.mock import patch\n\nimport pytest\n\nfrom memray import AllocatorType as AT\nfrom memray._memray import FileFormat\nfrom memray._metadata import Metadata\nfrom memray._stats import Stats\nfrom memray.reporters.stats import StatsReporter\nfrom memray.reporters.stats import draw_histogram\nfrom memray.reporters.stats import get_histogram_databins\nfrom tests.utils import MockAllocationRecord\n\n\n# data generator for tests\ndef _generate_mock_allocations(\n    count: int,\n    sizes: Optional[List[int]] = None,\n    allocators: Optional[List[AT]] = None,\n    n_allocations: Optional[List[int]] = None,\n    stacks: Optional[List[List[Tuple[str, str, int]]]] = None,\n):  # pragma: no cover\n    if sizes is None:\n        sizes = []\n    if allocators is None:\n        allocators = []\n    if n_allocations is None:\n        n_allocations = []\n    if stacks is None:\n        stacks = []\n\n    sizes.extend([1024] * (count - len(sizes)))\n    sizes = sizes[:count]\n\n    allocators.extend([AT.MALLOC] * (count - len(allocators)))\n    allocators = allocators[:count]\n\n    n_allocations.extend([1] * (count - len(n_allocations)))\n    n_allocations = n_allocations[:count]\n\n    default_stacks_value = [\n        (\"me\", \"fun.py\", 12),\n        (\"parent\", \"fun.py\", 8),\n        (\"grandparent\", \"fun.py\", 4),\n    ]\n    stacks.extend([default_stacks_value] * (count - len(stacks)))\n    stacks = stacks[:count]\n\n    return [\n        MockAllocationRecord(\n            tid=i + 1,\n            address=0x1000000,\n            size=sizes[i],\n            allocator=allocators[i],\n            stack_id=i + 1,\n            n_allocations=n_allocations[i],\n            _stack=stacks[i],\n        )\n        for i in range(count)\n    ]\n\n\n# data generator for tests\n@pytest.fixture(scope=\"module\")\ndef fake_stats():\n    mem_allocation_list = [\n        2500,\n        11000,\n        11000,\n        12000,\n        60000,\n        65000,\n        120000,\n        125000,\n        125000,\n        160000,\n        170000,\n        180000,\n        800000,\n        1500000,\n    ]\n\n    s = Stats(\n        metadata=Metadata(\n            start_time=datetime(2023, 1, 1, 1),\n            end_time=datetime(2023, 1, 1, 2),\n            total_allocations=sum(mem_allocation_list),\n            total_frames=10,\n            peak_memory=max(mem_allocation_list),\n            command_line=\"fake stats\",\n            pid=123456,\n            python_allocator=\"pymalloc\",\n            has_native_traces=False,\n            trace_python_allocators=True,\n            file_format=FileFormat.ALL_ALLOCATIONS,\n            main_thread_id=0x1,\n        ),\n        total_num_allocations=20,\n        total_memory_allocated=sum(mem_allocation_list),\n        peak_memory_allocated=max(mem_allocation_list),\n        allocation_count_by_size=Counter(mem_allocation_list),\n        allocation_count_by_allocator={\n            AT.MALLOC.name: 1013,\n            AT.REALLOC.name: 797,\n            AT.CALLOC.name: 152,\n            AT.MMAP.name: 4,\n        },\n        top_locations_by_count=[\n            ((\"fake_func\", \"fake.py\", 5), 20),\n            ((\"fake_func2\", \"fake.py\", 10), 50),\n            ((\"__main__\", \"fake.py\", 15), 1),\n        ],\n        top_locations_by_size=[\n            ((\"fake_func\", \"fake.py\", 5), 5 * 2**20),\n            ((\"fake_func2\", \"fake.py\", 10), 3 * 2**10),\n            ((\"__main__\", \"fake.py\", 15), 4),\n        ],\n    )\n    return s\n\n\n# tests begin here\ndef test_get_histogram_databins():\n    # GIVEN\n    input_data = Counter(\n        [\n            2500,\n            11000,\n            11000,\n            12000,\n            60000,\n            65000,\n            120000,\n            125000,\n            125000,\n            160000,\n            170000,\n            180000,\n            800000,\n            1500000,\n        ]\n    )\n    expected_output = [\n        (8986, 1),\n        (32299, 3),\n        (116099, 2),\n        (417312, 6),\n        (1500000, 2),\n    ]\n\n    # WHEN\n    actual_output = get_histogram_databins(input_data, bins=5)\n\n    # THEN\n    assert expected_output == actual_output\n\n\ndef test_get_histogram_databins_rounding():\n    \"\"\"Data chosen to provoke a floating point rounding error.\n\n    In particular, so that:\n\n        log(low) + sum([(log(high) - log(low)) / bins] * bins) > log(high)\n    \"\"\"\n    # GIVEN\n    input_data = Counter(\n        [\n            32,\n            1050856,\n        ]\n    )\n    expected_output = [\n        (90, 1),\n        (256, 0),\n        (724, 0),\n        (2049, 0),\n        (5798, 0),\n        (16405, 0),\n        (46411, 0),\n        (131299, 0),\n        (371453, 0),\n        (1050856, 1),\n    ]\n\n    # WHEN\n    actual_output = get_histogram_databins(input_data, bins=10)\n\n    # THEN\n    assert expected_output == actual_output\n\n\ndef test_get_histogram_over_bound():\n    \"\"\"Data chosen to provoke a scenario where the computed allocation exceeds the upper limit.\n\n    In particular, so that:\n        Counter(min((x - low) // step, bins-1) for x in it) will default to placing it in the\n        last bin instead of creating a new record out of range of the bins.\n    \"\"\"\n    input_data = Counter([10000000000, 536, 536, 592, 576, 4486])\n    expected_output = [\n        (2859, 4),\n        (15252, 1),\n        (81360, 0),\n        (434009, 0),\n        (2315167, 0),\n        (12349970, 0),\n        (65879369, 0),\n        (351425246, 0),\n        (1874633954, 0),\n        (10000000000, 1),\n    ]\n\n    # WHEN\n    actual_output = get_histogram_databins(input_data, bins=10)\n\n    # THEN\n    assert expected_output == actual_output\n\n\ndef test_get_histogram_all_allocations_same_size():\n    input_data = Counter([10000000000, 10000000000, 10000000000])\n    expected_output = [\n        (316227, 0),\n        (999999, 0),\n        (3162277, 0),\n        (10000000, 0),\n        (31622776, 0),\n        (100000000, 0),\n        (316227766, 0),\n        (999999999, 0),\n        (3162277660, 0),\n        (10000000000, 3),\n    ]\n\n    # WHEN\n    actual_output = get_histogram_databins(input_data, bins=10)\n\n    # THEN\n    assert expected_output == actual_output\n\n\ndef test_get_histogram_databins_invalid_bins():\n    with pytest.raises(ValueError):\n        _ = get_histogram_databins([], bins=0)  # invalid bins value\n    with pytest.raises(ValueError):\n        _ = get_histogram_databins([], bins=-1)  # invalid bins value\n\n\ndef test_draw_histogram():\n    # GIVEN\n    input_data = Counter(\n        [\n            2500,\n            11000,\n            11000,\n            12000,\n            60000,\n            65000,\n            120000,\n            125000,\n            125000,\n            160000,\n            170000,\n            180000,\n            800000,\n            1500000,\n        ]\n    )\n    expected_output = \"\"\"min: 2.500kB\n\\t----------------------------------------\n\\t< 8.986kB  : 1 ▇▇▇▇▇\n\\t< 32.299kB : 3 ▇▇▇▇▇▇▇▇▇▇▇▇▇\n\\t< 116.099kB: 2 ▇▇▇▇▇▇▇▇▇\n\\t< 417.312kB: 6 ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇\n\\t<=1.500MB  : 2 ▇▇▇▇▇▇▇▇▇\n\\t----------------------------------------\n\\tmax: 1.500MB\"\"\"\n\n    # WHEN\n    actual_output = draw_histogram(input_data, bins=5)\n\n    # THEN\n    assert expected_output == actual_output\n\n\ndef test_draw_histogram_smaller_scale_factor():\n    # GIVEN\n    input_data = Counter(\n        [\n            2500,\n            11000,\n            11000,\n            12000,\n            60000,\n            65000,\n            120000,\n            125000,\n            125000,\n            160000,\n            170000,\n            180000,\n            800000,\n            1500000,\n        ]\n    )\n\n    expected_output = \"\"\"min: 2.500kB\n\\t--------------------\n\\t< 8.986kB  : 1 ▇\n\\t< 32.299kB : 3 ▇▇▇\n\\t< 116.099kB: 2 ▇▇\n\\t< 417.312kB: 6 ▇▇▇▇▇\n\\t<=1.500MB  : 2 ▇▇\n\\t--------------------\n\\tmax: 1.500MB\"\"\"\n\n    # WHEN\n    actual_output = draw_histogram(\n        input_data, bins=5, hist_scale_factor=5\n    )  # setting this to 5\n\n    # THEN\n    assert expected_output == actual_output\n\n\ndef test_draw_histogram_invalid_input():\n    # test#1 - No input data\n    input_data = Counter()\n    actual_output = draw_histogram(input_data, bins=5)\n    assert \"<no data for histogram>\" == actual_output\n\n    # test#2 - Invalid bins value\n    with pytest.raises(ValueError):\n        _ = draw_histogram([100, 200, 300], bins=0)\n\n    # test#3 - Invalid hist_scale_factor value\n    with pytest.raises(ValueError):\n        _ = draw_histogram([100, 200, 300], bins=5, hist_scale_factor=0)\n\n\ndef test_stats_output(fake_stats):\n    reporter = StatsReporter(fake_stats, 5)\n    with patch(\"builtins.print\") as mocked_print:\n        with patch(\"rich.print\", print):\n            reporter.render()\n    expected = (\n        \"📏 [bold]Total allocations:[/]\\n\"\n        \"\\t20\\n\"\n        \"\\n\"\n        \"📦 [bold]Total memory allocated:[/]\\n\"\n        \"\\t3.341MB\\n\"\n        \"\\n\"\n        \"📈 [bold]Peak memory usage:[/]\\n\"\n        \"\\t1.500MB\\n\"\n        \"\\n\"\n        \"📊 [bold]Histogram of allocation size:[/]\\n\"\n        \"\\tmin: 2.500kB\\n\"\n        \"\\t----------------------------------------\\n\"\n        \"\\t< 4.739kB  : 1 ▇▇▇▇▇\\n\"\n        \"\\t< 8.986kB  : 0 \\n\"\n        \"\\t< 17.036kB : 3 ▇▇▇▇▇▇▇▇▇▇▇▇▇\\n\"\n        \"\\t< 32.299kB : 0 \\n\"\n        \"\\t< 61.237kB : 1 ▇▇▇▇▇\\n\"\n        \"\\t< 116.099kB: 1 ▇▇▇▇▇\\n\"\n        \"\\t< 220.113kB: 6 ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇\\n\"\n        \"\\t< 417.312kB: 0 \\n\"\n        \"\\t< 791.181kB: 0 \\n\"\n        \"\\t<=1.500MB  : 2 ▇▇▇▇▇▇▇▇▇\\n\"\n        \"\\t----------------------------------------\\n\"\n        \"\\tmax: 1.500MB\\n\"\n        \"\\n\"\n        \"📂 [bold]Allocator type distribution:[/]\\n\"\n        \"\\t MALLOC: 1013\\n\"\n        \"\\t REALLOC: 797\\n\"\n        \"\\t CALLOC: 152\\n\"\n        \"\\t MMAP: 4\\n\"\n        \"\\n\"\n        \"🥇 [bold]Top 5 largest allocating locations (by size):[/]\\n\"\n        \"\\t- fake_func:fake.py:5 -> 5.243MB\\n\"\n        \"\\t- fake_func2:fake.py:10 -> 3.072kB\\n\"\n        \"\\t- __main__:fake.py:15 -> 4.000B\\n\"\n        \"\\n\"\n        \"🥇 [bold]Top 5 largest allocating locations (by number of allocations):[/]\\n\"\n        \"\\t- fake_func:fake.py:5 -> 20\\n\"\n        \"\\t- fake_func2:fake.py:10 -> 50\\n\"\n        \"\\t- __main__:fake.py:15 -> 1\"\n    )\n    printed = \"\\n\".join(\" \".join(x[0]) for x in mocked_print.call_args_list)\n    assert expected == printed\n\n\ndef test_stats_output_json(fake_stats, tmp_path):\n    output_file = tmp_path / \"json.out\"\n    reporter = StatsReporter(fake_stats, 5)\n    reporter.render(json_output_file=output_file)\n    expected = {\n        \"total_num_allocations\": 20,\n        \"total_bytes_allocated\": 3341500,\n        \"allocation_size_histogram\": [\n            {\"min_bytes\": 0, \"max_bytes\": 4738, \"count\": 1},\n            {\"min_bytes\": 4739, \"max_bytes\": 8985, \"count\": 0},\n            {\"min_bytes\": 8986, \"max_bytes\": 17035, \"count\": 3},\n            {\"min_bytes\": 17036, \"max_bytes\": 32298, \"count\": 0},\n            {\"min_bytes\": 32299, \"max_bytes\": 61236, \"count\": 1},\n            {\"min_bytes\": 61237, \"max_bytes\": 116098, \"count\": 1},\n            {\"min_bytes\": 116099, \"max_bytes\": 220112, \"count\": 6},\n            {\"min_bytes\": 220113, \"max_bytes\": 417311, \"count\": 0},\n            {\"min_bytes\": 417312, \"max_bytes\": 791180, \"count\": 0},\n            {\"min_bytes\": 791181, \"max_bytes\": 1500000, \"count\": 2},\n        ],\n        \"allocator_type_distribution\": {\n            \"MALLOC\": 1013,\n            \"REALLOC\": 797,\n            \"CALLOC\": 152,\n            \"MMAP\": 4,\n        },\n        \"top_allocations_by_size\": [\n            {\"location\": \"fake_func:fake.py:5\", \"size\": 5242880},\n            {\"location\": \"fake_func2:fake.py:10\", \"size\": 3072},\n            {\"location\": \"__main__:fake.py:15\", \"size\": 4},\n        ],\n        \"top_allocations_by_count\": [\n            {\"location\": \"fake_func:fake.py:5\", \"count\": 20},\n            {\"location\": \"fake_func2:fake.py:10\", \"count\": 50},\n            {\"location\": \"__main__:fake.py:15\", \"count\": 1},\n        ],\n        \"metadata\": {\n            \"start_time\": \"2023-01-01 01:00:00\",\n            \"end_time\": \"2023-01-01 02:00:00\",\n            \"total_allocations\": 3341500,\n            \"total_frames\": 10,\n            \"peak_memory\": 1500000,\n            \"command_line\": \"fake stats\",\n            \"pid\": 123456,\n            \"python_allocator\": \"pymalloc\",\n            \"has_native_traces\": False,\n            \"trace_python_allocators\": True,\n            \"file_format\": 0,\n            \"main_thread_id\": 0x1,\n        },\n    }\n    actual = json.loads(output_file.read_text())\n    assert expected == actual\n"
  },
  {
    "path": "tests/unit/test_summary_reporter.py",
    "content": "from io import StringIO\n\nfrom memray import AllocatorType\nfrom memray.reporters.summary import SummaryReporter\nfrom tests.utils import MockAllocationRecord\n\n\ndef test_with_multiple_allocations():\n    # GIVEN\n    snapshot = [\n        MockAllocationRecord(\n            tid=1,\n            address=0x1000000,\n            size=1024 - (4 - i),\n            allocator=AllocatorType.MALLOC,\n            stack_id=1,\n            n_allocations=i + 1,\n            _stack=[\n                (f\"function{i}\", f\"/src/lel_{i}.py\", i),\n                (f\"function{i+1}\", f\"/src/lel_{i+1}.py\", i),\n            ],\n        )\n        for i in range(5)\n    ]\n\n    reporter = SummaryReporter.from_snapshot(snapshot)\n    output = StringIO()\n\n    # WHEN\n    reporter.render(sort_column=1, file=output)\n\n    # THEN\n    expected = [\n        \"┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━┳━━━━━━━┳━━━━━━━┳━━━━━━━┓\",\n        \"┃                                     ┃        ┃ Total ┃       ┃   Own ┃       ┃\",\n        \"┃                                     ┃ <Total ┃ Memo… ┃   Own ┃ Memo… ┃ Allo… ┃\",\n        \"┃ Location                            ┃ Memor… ┃     % ┃ Memo… ┃     % ┃ Count ┃\",\n        \"┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━╇━━━━━━━╇━━━━━━━╇━━━━━━━┩\",\n        \"│ function4 at /src/lel_4.py          │ 2.047… │ 40.0… │ 1.02… │ 20.0… │     9 │\",\n        \"│ function3 at /src/lel_3.py          │ 2.045… │ 40.0… │ 1.02… │ 20.0… │     7 │\",\n        \"│ function2 at /src/lel_2.py          │ 2.043… │ 39.9… │ 1.02… │ 20.0… │     5 │\",\n        \"│ function1 at /src/lel_1.py          │ 2.041… │ 39.9… │ 1.02… │ 19.9… │     3 │\",\n        \"│ function5 at /src/lel_5.py          │ 1.024… │ 20.0… │ 0.00… │ 0.00% │     5 │\",\n        \"│ function0 at /src/lel_0.py          │ 1.020… │ 19.9… │ 1.02… │ 19.9… │     1 │\",\n        \"└─────────────────────────────────────┴────────┴───────┴───────┴───────┴───────┘\",\n    ]\n    actual = [line.rstrip() for line in output.getvalue().splitlines()]\n    assert actual == expected\n\n\ndef test_with_multiple_allocations_and_native_traces():\n    # GIVEN\n    snapshot = [\n        MockAllocationRecord(\n            tid=1,\n            address=0x1000000,\n            size=1024 - (4 - i),\n            allocator=AllocatorType.MALLOC,\n            stack_id=1,\n            n_allocations=i + 1,\n            _stack=[],\n            _hybrid_stack=[\n                (\"me\", \"fun.py\", 12),\n                (\"parent\", \"fun.pyx\", 8),\n                (\"grandparent\", \"fun.c\", 4),\n            ],\n        )\n        for i in range(5)\n    ]\n\n    reporter = SummaryReporter.from_snapshot(snapshot, native=True)\n    output = StringIO()\n\n    # WHEN\n    reporter.render(sort_column=1, file=output)\n\n    # THEN\n    expected = [\n        \"┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━┳━━━━━━━┳━━━━━━━┳━━━━━━━┓\",\n        \"┃                                     ┃        ┃ Total ┃       ┃   Own ┃       ┃\",\n        \"┃                                     ┃ <Total ┃ Memo… ┃   Own ┃ Memo… ┃ Allo… ┃\",\n        \"┃ Location                            ┃ Memor… ┃     % ┃ Memo… ┃     % ┃ Count ┃\",\n        \"┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━╇━━━━━━━╇━━━━━━━╇━━━━━━━┩\",\n        \"│ me at fun.py                        │ 5.110… │ 100.… │ 5.11… │ 100.… │    15 │\",\n        \"│ parent at fun.pyx                   │ 5.110… │ 100.… │ 0.00… │ 0.00% │    15 │\",\n        \"│ grandparent at fun.c                │ 5.110… │ 100.… │ 0.00… │ 0.00% │    15 │\",\n        \"└─────────────────────────────────────┴────────┴───────┴───────┴───────┴───────┘\",\n    ]\n    actual = [line.rstrip() for line in output.getvalue().splitlines()]\n    assert actual == expected\n\n\ndef test_sort_column():\n    # GIVEN\n    snapshot = [\n        MockAllocationRecord(\n            tid=1,\n            address=0x1000000,\n            size=1024 - (4 - i),\n            allocator=AllocatorType.MALLOC,\n            stack_id=1,\n            n_allocations=i + 1,\n            _stack=[\n                (f\"function{i}\", f\"/src/lel_{i}.py\", i),\n                (f\"function{i+1}\", f\"/src/lel_{i+1}.py\", i),\n            ],\n        )\n        for i in range(5)\n    ]\n\n    reporter = SummaryReporter.from_snapshot(snapshot)\n    output = StringIO()\n\n    # WHEN\n    reporter.render(sort_column=3, file=output)\n\n    # THEN\n    expected = [\n        \"┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━┳━━━━━━━┳━━━━━━━┳━━━━━━━┓\",\n        \"┃                                     ┃        ┃ Total ┃       ┃   Own ┃       ┃\",\n        \"┃                                     ┃  Total ┃ Memo… ┃  <Own ┃ Memo… ┃ Allo… ┃\",\n        \"┃ Location                            ┃ Memory ┃     % ┃ Memo… ┃     % ┃ Count ┃\",\n        \"┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━╇━━━━━━━╇━━━━━━━╇━━━━━━━┩\",\n        \"│ function4 at /src/lel_4.py          │ 2.047… │ 40.0… │ 1.02… │ 20.0… │     9 │\",\n        \"│ function3 at /src/lel_3.py          │ 2.045… │ 40.0… │ 1.02… │ 20.0… │     7 │\",\n        \"│ function2 at /src/lel_2.py          │ 2.043… │ 39.9… │ 1.02… │ 20.0… │     5 │\",\n        \"│ function1 at /src/lel_1.py          │ 2.041… │ 39.9… │ 1.02… │ 19.9… │     3 │\",\n        \"│ function0 at /src/lel_0.py          │ 1.020… │ 19.9… │ 1.02… │ 19.9… │     1 │\",\n        \"│ function5 at /src/lel_5.py          │ 1.024… │ 20.0… │ 0.00… │ 0.00% │     5 │\",\n        \"└─────────────────────────────────────┴────────┴───────┴───────┴───────┴───────┘\",\n    ]\n    actual = [line.rstrip() for line in output.getvalue().splitlines()]\n    assert actual == expected\n\n\ndef test_max_rows():\n    # GIVEN\n    snapshot = [\n        MockAllocationRecord(\n            tid=1,\n            address=0x1000000,\n            size=1024 - (4 - i),\n            allocator=AllocatorType.MALLOC,\n            stack_id=1,\n            n_allocations=i + 1,\n            _stack=[\n                (f\"function{i}\", f\"/src/lel_{i}.py\", i),\n                (f\"function{i+1}\", f\"/src/lel_{i+1}.py\", i),\n            ],\n        )\n        for i in range(5)\n    ]\n\n    reporter = SummaryReporter.from_snapshot(snapshot)\n    output = StringIO()\n\n    # WHEN\n    reporter.render(sort_column=1, max_rows=3, file=output)\n\n    # THEN\n    expected = [\n        \"┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━┳━━━━━━━┳━━━━━━━┳━━━━━━━┓\",\n        \"┃                                     ┃        ┃ Total ┃       ┃   Own ┃       ┃\",\n        \"┃                                     ┃ <Total ┃ Memo… ┃   Own ┃ Memo… ┃ Allo… ┃\",\n        \"┃ Location                            ┃ Memor… ┃     % ┃ Memo… ┃     % ┃ Count ┃\",\n        \"┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━╇━━━━━━━╇━━━━━━━╇━━━━━━━┩\",\n        \"│ function4 at /src/lel_4.py          │ 2.047… │ 40.0… │ 1.02… │ 20.0… │     9 │\",\n        \"│ function3 at /src/lel_3.py          │ 2.045… │ 40.0… │ 1.02… │ 20.0… │     7 │\",\n        \"│ function2 at /src/lel_2.py          │ 2.043… │ 39.9… │ 1.02… │ 20.0… │     5 │\",\n        \"└─────────────────────────────────────┴────────┴───────┴───────┴───────┴───────┘\",\n    ]\n    actual = [line.rstrip() for line in output.getvalue().splitlines()]\n    assert actual == expected\n\n\ndef test_non_sequence_iterable():\n    # GIVEN\n    snapshot = (\n        MockAllocationRecord(\n            tid=1,\n            address=0x1000000,\n            size=1024 - (4 - i),\n            allocator=AllocatorType.MALLOC,\n            stack_id=1,\n            n_allocations=i + 1,\n            _stack=[\n                (f\"function{i}\", f\"/src/lel_{i}.py\", i),\n                (f\"function{i+1}\", f\"/src/lel_{i+1}.py\", i),\n            ],\n        )\n        for i in range(5)\n    )\n\n    reporter = SummaryReporter.from_snapshot(snapshot)\n    output = StringIO()\n\n    # WHEN\n    reporter.render(sort_column=1, max_rows=3, file=output)\n\n    # THEN\n    expected = [\n        \"┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━┳━━━━━━━┳━━━━━━━┳━━━━━━━┓\",\n        \"┃                                     ┃        ┃ Total ┃       ┃   Own ┃       ┃\",\n        \"┃                                     ┃ <Total ┃ Memo… ┃   Own ┃ Memo… ┃ Allo… ┃\",\n        \"┃ Location                            ┃ Memor… ┃     % ┃ Memo… ┃     % ┃ Count ┃\",\n        \"┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━╇━━━━━━━╇━━━━━━━╇━━━━━━━┩\",\n        \"│ function4 at /src/lel_4.py          │ 2.047… │ 40.0… │ 1.02… │ 20.0… │     9 │\",\n        \"│ function3 at /src/lel_3.py          │ 2.045… │ 40.0… │ 1.02… │ 20.0… │     7 │\",\n        \"│ function2 at /src/lel_2.py          │ 2.043… │ 39.9… │ 1.02… │ 20.0… │     5 │\",\n        \"└─────────────────────────────────────┴────────┴───────┴───────┴───────┴───────┘\",\n    ]\n    actual = [line.rstrip() for line in output.getvalue().splitlines()]\n    assert actual == expected\n"
  },
  {
    "path": "tests/unit/test_table_reporter.py",
    "content": "from memray import AllocatorType\nfrom memray.reporters.table import TableReporter\nfrom tests.utils import MockAllocationRecord\n\n\nclass TestTableReporter:\n    def test_empty_report(self):\n        # GIVEN / WHEN\n        table = TableReporter.from_snapshot([], memory_records=[], native_traces=False)\n\n        # THEN\n        assert table.data == []\n\n    def test_single_allocation(self):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"me\", \"fun.py\", 12),\n                ],\n            ),\n        ]\n\n        # WHEN\n        table = TableReporter.from_snapshot(\n            peak_allocations, memory_records=[], native_traces=False\n        )\n\n        # THEN\n        assert table.data == [\n            {\n                \"tid\": \"0x1\",\n                \"size\": 1024,\n                \"allocator\": \"malloc\",\n                \"n_allocations\": 1,\n                \"stack_trace\": \"me at fun.py:12\",\n            }\n        ]\n\n    def test_single_native_allocation(self):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _hybrid_stack=[\n                    (\"me\", \"fun.c\", 12),\n                ],\n            ),\n        ]\n\n        # WHEN\n        table = TableReporter.from_snapshot(\n            peak_allocations, memory_records=[], native_traces=True\n        )\n\n        # THEN\n        assert table.data == [\n            {\n                \"tid\": \"0x1\",\n                \"size\": 1024,\n                \"allocator\": \"malloc\",\n                \"n_allocations\": 1,\n                \"stack_trace\": \"me at fun.c:12\",\n            }\n        ]\n\n    def test_multiple_allocations(self):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"me\", \"foo.py\", 12),\n                ],\n            ),\n            MockAllocationRecord(\n                tid=1,\n                address=0x1100000,\n                size=2048,\n                allocator=AllocatorType.VALLOC,\n                stack_id=2,\n                n_allocations=10,\n                _stack=[\n                    (\"you\", \"bar.py\", 21),\n                ],\n            ),\n        ]\n\n        # WHEN\n        table = TableReporter.from_snapshot(\n            peak_allocations, memory_records=[], native_traces=False\n        )\n\n        # THEN\n        assert table.data == [\n            {\n                \"tid\": \"0x1\",\n                \"size\": 1024,\n                \"allocator\": \"malloc\",\n                \"n_allocations\": 1,\n                \"stack_trace\": \"me at foo.py:12\",\n            },\n            {\n                \"tid\": \"0x1\",\n                \"size\": 2048,\n                \"allocator\": \"valloc\",\n                \"n_allocations\": 10,\n                \"stack_trace\": \"you at bar.py:21\",\n            },\n        ]\n\n    def test_empty_stack_trace(self):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[],\n            ),\n        ]\n\n        # WHEN\n        table = TableReporter.from_snapshot(\n            peak_allocations, memory_records=[], native_traces=False\n        )\n\n        # THEN\n        assert table.data == [\n            {\n                \"tid\": \"0x1\",\n                \"size\": 1024,\n                \"allocator\": \"malloc\",\n                \"n_allocations\": 1,\n                \"stack_trace\": \"???\",\n            }\n        ]\n"
  },
  {
    "path": "tests/unit/test_templates.py",
    "content": "from datetime import datetime\n\nimport pytest\n\nfrom memray import Metadata\nfrom memray._memray import FileFormat\nfrom memray.reporters.templates import get_report_title\nfrom memray.reporters.templates import render_report\n\n\n@pytest.mark.parametrize(\n    [\"kind\", \"show_memory_leaks\", \"inverted\", \"expected\"],\n    [\n        (\"flamegraph\", False, False, \"flamegraph report\"),\n        (\"flamegraph\", True, False, \"flamegraph report (memory leaks)\"),\n        (\"table\", False, False, \"table report\"),\n        (\"table\", True, False, \"table report (memory leaks)\"),\n        (\"flamegraph\", False, True, \"inverted flamegraph report\"),\n        (\"flamegraph\", True, True, \"inverted flamegraph report (memory leaks)\"),\n    ],\n)\ndef test_title_for_regular_report(kind, show_memory_leaks, inverted, expected):\n    assert (\n        get_report_title(\n            kind=kind, show_memory_leaks=show_memory_leaks, inverted=inverted\n        )\n        == expected\n    )\n\n\n@pytest.mark.parametrize(\n    \"kind\",\n    [\"flamegraph\", \"table\"],\n)\ndef test_html_report_escaping(kind):\n    \"\"\"Test that command line arguments are properly escaped.\"\"\"\n    # GIVEN\n    metadata = Metadata(\n        start_time=datetime(2024, 1, 1, 0, 0, 0),\n        end_time=datetime(2024, 1, 1, 0, 1, 0),\n        total_allocations=100,\n        total_frames=10,\n        peak_memory=1024,\n        command_line=\"python test.py </code>\",\n        pid=12345,\n        main_thread_id=1,\n        python_allocator=\"pymalloc\",\n        has_native_traces=False,\n        trace_python_allocators=False,\n        file_format=FileFormat.ALL_ALLOCATIONS,\n    )\n\n    # WHEN\n    html_output = render_report(\n        kind=kind,\n        data=[],\n        metadata=metadata,\n        memory_records=[],\n        show_memory_leaks=False,\n        merge_threads=False,\n        inverted=False,\n        no_web=True,\n    )\n\n    # THEN\n    assert html_output.count(\"<code>\") == html_output.count(\"</code>\")\n    assert \"python test.py &lt;/code&gt;\" in html_output\n"
  },
  {
    "path": "tests/unit/test_tracker.py",
    "content": "from pathlib import Path\n\nimport pytest\n\nfrom memray import Tracker\n\n\ndef test_two_trackers_cannot_be_active_at_the_same_time(tmpdir):\n    # GIVEN\n    output = Path(tmpdir) / \"test.bin\"\n    output2 = Path(tmpdir) / \"test2.bin\"\n\n    # WHEN\n    with Tracker(output):\n        # THEN\n        with pytest.raises(RuntimeError):\n            with Tracker(output2):\n                pass\n\n\ndef test_the_same_tracker_cannot_be_activated_twice(tmpdir):\n    # GIVEN\n    output = Path(tmpdir) / \"test.bin\"\n\n    # WHEN\n    tracker = Tracker(output)\n    with tracker:\n        # Remove the file so we are not stopped by the file existence check\n        output.unlink()\n        # THEN\n        with pytest.raises(RuntimeError):\n            with tracker:\n                pass\n"
  },
  {
    "path": "tests/unit/test_transform_reporter.py",
    "content": "import csv\nimport json\nfrom io import StringIO\n\nfrom memray import AllocatorType\nfrom memray.reporters.transform import TransformReporter\nfrom tests.utils import MockAllocationRecord\n\n\nclass TestGprof2DotTransformReporter:\n    def test_empty_report(self):\n        # GIVEN\n        reporter = TransformReporter(\n            [], format=\"gprof2dot\", memory_records=[], native_traces=False\n        )\n        output = StringIO()\n\n        # WHEN\n        reporter.render_as_gprof2dot(output)\n        output.seek(0)\n\n        # THEN\n        output_data = json.loads(output.read())\n        assert output_data == {\n            \"costs\": [{\"description\": \"Memory\", \"unit\": \"bytes\"}],\n            \"events\": [],\n            \"functions\": [],\n            \"version\": 0,\n        }\n\n    def test_single_allocation(self):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"me\", \"fun.py\", 12),\n                ],\n            ),\n        ]\n        output = StringIO()\n\n        reporter = TransformReporter(\n            peak_allocations, format=\"gprof2dot\", memory_records=[], native_traces=False\n        )\n\n        # WHEN\n        reporter.render_as_gprof2dot(output)\n        output.seek(0)\n\n        # THEN\n        output_data = json.loads(output.read())\n        assert output_data == {\n            \"costs\": [{\"description\": \"Memory\", \"unit\": \"bytes\"}],\n            \"events\": [{\"callchain\": [0], \"cost\": [1024]}],\n            \"functions\": [{\"module\": \"fun.py\", \"name\": \"me\"}],\n            \"version\": 0,\n        }\n\n    def test_single_native_allocation(self):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _hybrid_stack=[\n                    (\"me\", \"fun.c\", 12),\n                ],\n            ),\n        ]\n        output = StringIO()\n\n        reporter = TransformReporter(\n            peak_allocations, format=\"gprof2dot\", memory_records=[], native_traces=True\n        )\n\n        # WHEN\n        reporter.render_as_gprof2dot(output)\n        output.seek(0)\n\n        # THEN\n        output_data = json.loads(output.read())\n        assert output_data == {\n            \"costs\": [{\"description\": \"Memory\", \"unit\": \"bytes\"}],\n            \"events\": [{\"callchain\": [0], \"cost\": [1024]}],\n            \"functions\": [{\"module\": \"fun.c\", \"name\": \"me\"}],\n            \"version\": 0,\n        }\n\n    def test_multiple_allocations(self):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"me\", \"foo.py\", 12),\n                ],\n            ),\n            MockAllocationRecord(\n                tid=1,\n                address=0x1100000,\n                size=2048,\n                allocator=AllocatorType.VALLOC,\n                stack_id=2,\n                n_allocations=10,\n                _stack=[\n                    (\"you\", \"bar.py\", 21),\n                ],\n            ),\n        ]\n\n        output = StringIO()\n\n        reporter = TransformReporter(\n            peak_allocations, format=\"gprof2dot\", memory_records=[], native_traces=False\n        )\n\n        # WHEN\n        reporter.render_as_gprof2dot(output)\n        output.seek(0)\n\n        # THEN\n        output_data = json.loads(output.read())\n        assert output_data == {\n            \"costs\": [{\"description\": \"Memory\", \"unit\": \"bytes\"}],\n            \"events\": [\n                {\"callchain\": [0], \"cost\": [1024]},\n                {\"callchain\": [1], \"cost\": [2048]},\n            ],\n            \"functions\": [\n                {\"module\": \"foo.py\", \"name\": \"me\"},\n                {\"module\": \"bar.py\", \"name\": \"you\"},\n            ],\n            \"version\": 0,\n        }\n\n    def test_empty_stack_trace(self):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[],\n            ),\n        ]\n        output = StringIO()\n\n        reporter = TransformReporter(\n            peak_allocations, format=\"gprof2dot\", memory_records=[], native_traces=False\n        )\n\n        # WHEN\n        reporter.render_as_gprof2dot(output)\n        output.seek(0)\n\n        # THEN\n        output_data = json.loads(output.read())\n        assert output_data == {\n            \"costs\": [{\"description\": \"Memory\", \"unit\": \"bytes\"}],\n            \"events\": [],\n            \"functions\": [],\n            \"version\": 0,\n        }\n\n\nclass TestCSVTransformReporter:\n    HEADER = [\n        \"allocator\",\n        \"num_allocations\",\n        \"size\",\n        \"tid\",\n        \"thread_name\",\n        \"stack_trace\",\n    ]\n\n    def test_empty_report(self):\n        # GIVEN\n        reporter = TransformReporter(\n            [], format=\"csv\", memory_records=[], native_traces=False\n        )\n        output = StringIO()\n\n        # WHEN\n        reporter.render_as_csv(output)\n        output.seek(0)\n\n        # THEN\n        header, *output_data = tuple(csv.reader(output))\n        assert header == self.HEADER\n        assert output_data == []\n\n    def test_single_allocation(self):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"me\", \"fun.py\", 12),\n                ],\n            ),\n        ]\n        output = StringIO()\n\n        reporter = TransformReporter(\n            peak_allocations, format=\"csv\", memory_records=[], native_traces=False\n        )\n\n        # WHEN\n        reporter.render_as_csv(output)\n        output.seek(0)\n\n        # THEN\n        header, *output_data = tuple(csv.reader(output))\n        assert header == self.HEADER\n        assert output_data == [[\"MALLOC\", \"1\", \"1024\", \"1\", \"0x1\", \"me;fun.py;12\"]]\n\n    def test_single_native_allocation(self):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _hybrid_stack=[\n                    (\"me\", \"fun.c\", 12),\n                ],\n            ),\n        ]\n        output = StringIO()\n\n        reporter = TransformReporter(\n            peak_allocations, format=\"csv\", memory_records=[], native_traces=True\n        )\n\n        # WHEN\n        reporter.render_as_csv(output)\n        output.seek(0)\n\n        # THEN\n        header, *output_data = tuple(csv.reader(output))\n        assert header == self.HEADER\n        assert output_data == [[\"MALLOC\", \"1\", \"1024\", \"1\", \"0x1\", \"me;fun.c;12\"]]\n\n    def test_multiple_allocations(self):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"me\", \"foo.py\", 12),\n                ],\n            ),\n            MockAllocationRecord(\n                tid=1,\n                address=0x1100000,\n                size=2048,\n                allocator=AllocatorType.VALLOC,\n                stack_id=2,\n                n_allocations=10,\n                _stack=[\n                    (\"you\", \"bar.py\", 21),\n                ],\n            ),\n        ]\n\n        output = StringIO()\n\n        reporter = TransformReporter(\n            peak_allocations, format=\"csv\", memory_records=[], native_traces=False\n        )\n\n        # WHEN\n        reporter.render_as_csv(output)\n        output.seek(0)\n\n        # THEN\n        header, *output_data = tuple(csv.reader(output))\n        assert header == self.HEADER\n        assert output_data == [\n            [\"MALLOC\", \"1\", \"1024\", \"1\", \"0x1\", \"me;foo.py;12\"],\n            [\"VALLOC\", \"10\", \"2048\", \"1\", \"0x1\", \"you;bar.py;21\"],\n        ]\n\n    def test_empty_stack_trace(self):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[],\n            ),\n        ]\n        output = StringIO()\n\n        reporter = TransformReporter(\n            peak_allocations, format=\"csv\", memory_records=[], native_traces=False\n        )\n\n        # WHEN\n        reporter.render_as_csv(output)\n        output.seek(0)\n\n        # THEN\n        header, *output_data = tuple(csv.reader(output))\n        assert header == self.HEADER\n        assert output_data == [[\"MALLOC\", \"1\", \"1024\", \"1\", \"0x1\", \"\"]]\n\n    def test_multiple_stack_frames(self):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"me\", \"foo.py\", 12),\n                    (\"you\", \"bar.py\", 21),\n                ],\n            ),\n        ]\n        output = StringIO()\n\n        reporter = TransformReporter(\n            peak_allocations, format=\"csv\", memory_records=[], native_traces=False\n        )\n\n        # WHEN\n        reporter.render_as_csv(output)\n        output.seek(0)\n\n        # THEN\n        header, *output_data = tuple(csv.reader(output))\n        assert header == self.HEADER\n\n        assert output_data == [\n            [\"MALLOC\", \"1\", \"1024\", \"1\", \"0x1\", \"me;foo.py;12|you;bar.py;21\"]\n        ]\n"
  },
  {
    "path": "tests/unit/test_tree_reporter.py",
    "content": "import asyncio\nfrom dataclasses import dataclass\nfrom textwrap import dedent\nfrom typing import Any\nfrom typing import Awaitable\nfrom typing import Callable\nfrom typing import Dict\nfrom typing import Iterable\nfrom typing import Iterator\nfrom typing import List\nfrom typing import Optional\nfrom typing import Tuple\nfrom unittest.mock import patch\n\nimport pytest\nfrom textual.pilot import Pilot\nfrom textual.widgets import Tree\nfrom textual.widgets.tree import TreeNode\n\nfrom memray import AllocationRecord\nfrom memray import AllocatorType\nfrom memray.reporters.tree import MAX_STACKS\nfrom memray.reporters.tree import Frame\nfrom memray.reporters.tree import TreeReporter\nfrom tests.utils import MockAllocationRecord\nfrom tests.utils import async_run\n\n\nclass TestTreeReporter:\n    def test_works_with_no_allocations(self):\n        reporter = TreeReporter.from_snapshot([], native_traces=False)\n        assert reporter.data == Frame(\n            location=(\"<ROOT>\", \"\", 0),\n            value=0,\n            children={},\n            n_allocations=0,\n            thread_id=\"\",\n            interesting=True,\n        )\n\n    def test_works_with_single_call(self):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"me\", \"fun.py\", 12),\n                    (\"parent\", \"fun.py\", 8),\n                    (\"grandparent\", \"fun.py\", 4),\n                ],\n            ),\n        ]\n\n        # WHEN\n        reporter = TreeReporter.from_snapshot(\n            peak_allocations, native_traces=False, biggest_allocs=5\n        )\n\n        # THEN\n        assert reporter.data == Frame(\n            location=(\"<ROOT>\", \"\", 0),\n            value=1024,\n            children={\n                (\"grandparent\", \"fun.py\", 4): Frame(\n                    location=(\"grandparent\", \"fun.py\", 4),\n                    value=1024,\n                    children={\n                        (\"parent\", \"fun.py\", 8): Frame(\n                            location=(\"parent\", \"fun.py\", 8),\n                            value=1024,\n                            children={\n                                (\"me\", \"fun.py\", 12): Frame(\n                                    location=(\"me\", \"fun.py\", 12),\n                                    value=1024,\n                                    children={},\n                                    n_allocations=1,\n                                    thread_id=\"0x1\",\n                                    interesting=True,\n                                    import_system=False,\n                                )\n                            },\n                            n_allocations=1,\n                            thread_id=\"0x1\",\n                            interesting=True,\n                            import_system=False,\n                        )\n                    },\n                    n_allocations=1,\n                    thread_id=\"0x1\",\n                    interesting=True,\n                    import_system=False,\n                )\n            },\n            n_allocations=1,\n            thread_id=\"\",\n            interesting=True,\n            import_system=False,\n        )\n\n    def test_uses_hybrid_stack_for_native_traces(self):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _hybrid_stack=[\n                    (\"me\", \"fun.py\", 12),\n                    (\"parent\", \"fun.pyx\", 8),\n                    (\"grandparent\", \"fun.c\", 4),\n                ],\n            ),\n        ]\n\n        # WHEN\n        reporter = TreeReporter.from_snapshot(peak_allocations, native_traces=True)\n\n        # THEN\n        assert reporter.data == Frame(\n            location=(\"<ROOT>\", \"\", 0),\n            value=1024,\n            children={\n                (\"grandparent\", \"fun.c\", 4): Frame(\n                    location=(\"grandparent\", \"fun.c\", 4),\n                    value=1024,\n                    children={\n                        (\"parent\", \"fun.pyx\", 8): Frame(\n                            location=(\"parent\", \"fun.pyx\", 8),\n                            value=1024,\n                            children={\n                                (\"me\", \"fun.py\", 12): Frame(\n                                    location=(\"me\", \"fun.py\", 12),\n                                    value=1024,\n                                    children={},\n                                    n_allocations=1,\n                                    thread_id=\"0x1\",\n                                    interesting=True,\n                                    import_system=False,\n                                )\n                            },\n                            n_allocations=1,\n                            thread_id=\"0x1\",\n                            interesting=True,\n                            import_system=False,\n                        )\n                    },\n                    n_allocations=1,\n                    thread_id=\"0x1\",\n                    interesting=True,\n                    import_system=False,\n                )\n            },\n            n_allocations=1,\n            thread_id=\"\",\n            interesting=True,\n            import_system=False,\n        )\n\n    def test_works_with_multiple_stacks_from_same_caller(self):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"me\", \"fun.py\", 12),\n                    (\"parent\", \"fun.py\", 8),\n                    (\"grandparent\", \"fun.py\", 4),\n                ],\n            ),\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"sibling\", \"fun.py\", 16),\n                    (\"parent\", \"fun.py\", 8),\n                    (\"grandparent\", \"fun.py\", 4),\n                ],\n            ),\n        ]\n\n        # WHEN\n        reporter = TreeReporter.from_snapshot(peak_allocations, native_traces=False)\n\n        # THEN\n        assert reporter.data == Frame(\n            location=(\"<ROOT>\", \"\", 0),\n            value=2048,\n            children={\n                (\"grandparent\", \"fun.py\", 4): Frame(\n                    location=(\"grandparent\", \"fun.py\", 4),\n                    value=2048,\n                    children={\n                        (\"parent\", \"fun.py\", 8): Frame(\n                            location=(\"parent\", \"fun.py\", 8),\n                            value=2048,\n                            children={\n                                (\"me\", \"fun.py\", 12): Frame(\n                                    location=(\"me\", \"fun.py\", 12),\n                                    value=1024,\n                                    children={},\n                                    n_allocations=1,\n                                    thread_id=\"0x1\",\n                                    interesting=True,\n                                    import_system=False,\n                                ),\n                                (\"sibling\", \"fun.py\", 16): Frame(\n                                    location=(\"sibling\", \"fun.py\", 16),\n                                    value=1024,\n                                    children={},\n                                    n_allocations=1,\n                                    thread_id=\"0x1\",\n                                    interesting=True,\n                                    import_system=False,\n                                ),\n                            },\n                            n_allocations=2,\n                            thread_id=\"0x1\",\n                            interesting=True,\n                            import_system=False,\n                        )\n                    },\n                    n_allocations=2,\n                    thread_id=\"0x1\",\n                    interesting=True,\n                    import_system=False,\n                )\n            },\n            n_allocations=2,\n            thread_id=\"\",\n            interesting=True,\n            import_system=False,\n        )\n\n    def test_works_with_multiple_stacks_from_same_caller_two_frames_above(self):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"me\", \"fun.py\", 12),\n                    (\"parent_one\", \"fun.py\", 8),\n                    (\"grandparent\", \"fun.py\", 4),\n                ],\n            ),\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"sibling\", \"fun.py\", 16),\n                    (\"parent_two\", \"fun.py\", 10),\n                    (\"grandparent\", \"fun.py\", 4),\n                ],\n            ),\n        ]\n\n        # WHEN\n        reporter = TreeReporter.from_snapshot(peak_allocations, native_traces=False)\n\n        # THEN\n        assert reporter.data == Frame(\n            location=(\"<ROOT>\", \"\", 0),\n            value=2048,\n            children={\n                (\"grandparent\", \"fun.py\", 4): Frame(\n                    location=(\"grandparent\", \"fun.py\", 4),\n                    value=2048,\n                    children={\n                        (\"parent_one\", \"fun.py\", 8): Frame(\n                            location=(\"parent_one\", \"fun.py\", 8),\n                            value=1024,\n                            children={\n                                (\"me\", \"fun.py\", 12): Frame(\n                                    location=(\"me\", \"fun.py\", 12),\n                                    value=1024,\n                                    children={},\n                                    n_allocations=1,\n                                    thread_id=\"0x1\",\n                                    interesting=True,\n                                    import_system=False,\n                                )\n                            },\n                            n_allocations=1,\n                            thread_id=\"0x1\",\n                            interesting=True,\n                            import_system=False,\n                        ),\n                        (\"parent_two\", \"fun.py\", 10): Frame(\n                            location=(\"parent_two\", \"fun.py\", 10),\n                            value=1024,\n                            children={\n                                (\"sibling\", \"fun.py\", 16): Frame(\n                                    location=(\"sibling\", \"fun.py\", 16),\n                                    value=1024,\n                                    children={},\n                                    n_allocations=1,\n                                    thread_id=\"0x1\",\n                                    interesting=True,\n                                    import_system=False,\n                                )\n                            },\n                            n_allocations=1,\n                            thread_id=\"0x1\",\n                            interesting=True,\n                            import_system=False,\n                        ),\n                    },\n                    n_allocations=2,\n                    thread_id=\"0x1\",\n                    interesting=True,\n                    import_system=False,\n                )\n            },\n            n_allocations=2,\n            thread_id=\"\",\n            interesting=True,\n            import_system=False,\n        )\n\n    def test_works_with_recursive_calls(self):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"one\", \"recursive.py\", 9),\n                    (\"two\", \"recursive.py\", 20),\n                    (\"one\", \"recursive.py\", 10),\n                    (\"two\", \"recursive.py\", 20),\n                    (\"one\", \"recursive.py\", 10),\n                    (\"two\", \"recursive.py\", 20),\n                    (\"main\", \"recursive.py\", 5),\n                ],\n            ),\n        ]\n\n        # WHEN\n        reporter = TreeReporter.from_snapshot(peak_allocations, native_traces=False)\n\n        # THEN\n        assert reporter.data == Frame(\n            location=(\"<ROOT>\", \"\", 0),\n            value=1024,\n            children={\n                (\"main\", \"recursive.py\", 5): Frame(\n                    location=(\"main\", \"recursive.py\", 5),\n                    value=1024,\n                    children={\n                        (\"two\", \"recursive.py\", 20): Frame(\n                            location=(\"two\", \"recursive.py\", 20),\n                            value=1024,\n                            children={\n                                (\"one\", \"recursive.py\", 10): Frame(\n                                    location=(\"one\", \"recursive.py\", 10),\n                                    value=1024,\n                                    children={\n                                        (\"two\", \"recursive.py\", 20): Frame(\n                                            location=(\"two\", \"recursive.py\", 20),\n                                            value=1024,\n                                            children={\n                                                (\"one\", \"recursive.py\", 10): Frame(\n                                                    location=(\n                                                        \"one\",\n                                                        \"recursive.py\",\n                                                        10,\n                                                    ),\n                                                    value=1024,\n                                                    children={\n                                                        (\n                                                            \"two\",\n                                                            \"recursive.py\",\n                                                            20,\n                                                        ): Frame(\n                                                            location=(\n                                                                \"two\",\n                                                                \"recursive.py\",\n                                                                20,\n                                                            ),\n                                                            value=1024,\n                                                            children={\n                                                                (\n                                                                    \"one\",\n                                                                    \"recursive.py\",\n                                                                    9,\n                                                                ): Frame(\n                                                                    location=(\n                                                                        \"one\",\n                                                                        \"recursive.py\",\n                                                                        9,\n                                                                    ),\n                                                                    value=1024,\n                                                                    children={},\n                                                                    n_allocations=1,\n                                                                    thread_id=\"0x1\",\n                                                                    interesting=True,\n                                                                    import_system=False,\n                                                                )\n                                                            },\n                                                            n_allocations=1,\n                                                            thread_id=\"0x1\",\n                                                            interesting=True,\n                                                            import_system=False,\n                                                        )\n                                                    },\n                                                    n_allocations=1,\n                                                    thread_id=\"0x1\",\n                                                    interesting=True,\n                                                    import_system=False,\n                                                )\n                                            },\n                                            n_allocations=1,\n                                            thread_id=\"0x1\",\n                                            interesting=True,\n                                            import_system=False,\n                                        )\n                                    },\n                                    n_allocations=1,\n                                    thread_id=\"0x1\",\n                                    interesting=True,\n                                    import_system=False,\n                                )\n                            },\n                            n_allocations=1,\n                            thread_id=\"0x1\",\n                            interesting=True,\n                            import_system=False,\n                        )\n                    },\n                    n_allocations=1,\n                    thread_id=\"0x1\",\n                    interesting=True,\n                    import_system=False,\n                )\n            },\n            n_allocations=1,\n            thread_id=\"\",\n            interesting=True,\n            import_system=False,\n        )\n\n    def test_works_with_multiple_top_level_nodes(self):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"baz2\", \"/src/lel.py\", 18),\n                    (\"bar2\", \"/src/lel.py\", 15),\n                    (\"foo2\", \"/src/lel.py\", 12),\n                ],\n            ),\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"baz1\", \"/src/lel.py\", 8),\n                    (\"bar1\", \"/src/lel.py\", 5),\n                    (\"foo1\", \"/src/lel.py\", 2),\n                ],\n            ),\n        ]\n\n        # WHEN\n        reporter = TreeReporter.from_snapshot(peak_allocations, native_traces=False)\n\n        # THEN\n        assert reporter.data == Frame(\n            location=(\"<ROOT>\", \"\", 0),\n            value=2048,\n            children={\n                (\"foo2\", \"/src/lel.py\", 12): Frame(\n                    location=(\"foo2\", \"/src/lel.py\", 12),\n                    value=1024,\n                    children={\n                        (\"bar2\", \"/src/lel.py\", 15): Frame(\n                            location=(\"bar2\", \"/src/lel.py\", 15),\n                            value=1024,\n                            children={\n                                (\"baz2\", \"/src/lel.py\", 18): Frame(\n                                    location=(\"baz2\", \"/src/lel.py\", 18),\n                                    value=1024,\n                                    children={},\n                                    n_allocations=1,\n                                    thread_id=\"0x1\",\n                                    interesting=True,\n                                    import_system=False,\n                                )\n                            },\n                            n_allocations=1,\n                            thread_id=\"0x1\",\n                            interesting=True,\n                            import_system=False,\n                        )\n                    },\n                    n_allocations=1,\n                    thread_id=\"0x1\",\n                    interesting=True,\n                    import_system=False,\n                ),\n                (\"foo1\", \"/src/lel.py\", 2): Frame(\n                    location=(\"foo1\", \"/src/lel.py\", 2),\n                    value=1024,\n                    children={\n                        (\"bar1\", \"/src/lel.py\", 5): Frame(\n                            location=(\"bar1\", \"/src/lel.py\", 5),\n                            value=1024,\n                            children={\n                                (\"baz1\", \"/src/lel.py\", 8): Frame(\n                                    location=(\"baz1\", \"/src/lel.py\", 8),\n                                    value=1024,\n                                    children={},\n                                    n_allocations=1,\n                                    thread_id=\"0x1\",\n                                    interesting=True,\n                                    import_system=False,\n                                )\n                            },\n                            n_allocations=1,\n                            thread_id=\"0x1\",\n                            interesting=True,\n                            import_system=False,\n                        )\n                    },\n                    n_allocations=1,\n                    thread_id=\"0x1\",\n                    interesting=True,\n                    import_system=False,\n                ),\n            },\n            n_allocations=2,\n            thread_id=\"\",\n            interesting=True,\n            import_system=False,\n        )\n\n    def test_works_with_split_threads(self):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"baz2\", \"/src/lel.py\", 18),\n                    (\"bar2\", \"/src/lel.py\", 15),\n                    (\"foo2\", \"/src/lel.py\", 12),\n                ],\n            ),\n            MockAllocationRecord(\n                tid=2,\n                address=0x2000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"baz2\", \"/src/lel.py\", 18),\n                    (\"bar2\", \"/src/lel.py\", 15),\n                    (\"foo2\", \"/src/lel.py\", 12),\n                ],\n            ),\n        ]\n\n        # WHEN\n        reporter = TreeReporter.from_snapshot(peak_allocations, native_traces=False)\n\n        # THEN\n        assert reporter.data == Frame(\n            location=(\"<ROOT>\", \"\", 0),\n            value=2048,\n            children={\n                (\"foo2\", \"/src/lel.py\", 12): Frame(\n                    location=(\"foo2\", \"/src/lel.py\", 12),\n                    value=2048,\n                    children={\n                        (\"bar2\", \"/src/lel.py\", 15): Frame(\n                            location=(\"bar2\", \"/src/lel.py\", 15),\n                            value=2048,\n                            children={\n                                (\"baz2\", \"/src/lel.py\", 18): Frame(\n                                    location=(\"baz2\", \"/src/lel.py\", 18),\n                                    value=2048,\n                                    children={},\n                                    n_allocations=2,\n                                    thread_id=\"0x2\",\n                                    interesting=True,\n                                    import_system=False,\n                                )\n                            },\n                            n_allocations=2,\n                            thread_id=\"0x2\",\n                            interesting=True,\n                            import_system=False,\n                        )\n                    },\n                    n_allocations=2,\n                    thread_id=\"0x2\",\n                    interesting=True,\n                    import_system=False,\n                )\n            },\n            n_allocations=2,\n            thread_id=\"\",\n            interesting=True,\n            import_system=False,\n        )\n\n    def test_works_with_merged_threads(self):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=-1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"baz2\", \"/src/lel.py\", 18),\n                    (\"bar2\", \"/src/lel.py\", 15),\n                    (\"foo2\", \"/src/lel.py\", 12),\n                ],\n            ),\n            MockAllocationRecord(\n                tid=-1,\n                address=0x2000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"baz2\", \"/src/lel.py\", 18),\n                    (\"bar2\", \"/src/lel.py\", 15),\n                    (\"foo2\", \"/src/lel.py\", 12),\n                ],\n            ),\n        ]\n\n        # WHEN\n        reporter = TreeReporter.from_snapshot(peak_allocations, native_traces=False)\n\n        # THEN\n        assert reporter.data == Frame(\n            location=(\"<ROOT>\", \"\", 0),\n            value=2048,\n            children={\n                (\"foo2\", \"/src/lel.py\", 12): Frame(\n                    location=(\"foo2\", \"/src/lel.py\", 12),\n                    value=2048,\n                    children={\n                        (\"bar2\", \"/src/lel.py\", 15): Frame(\n                            location=(\"bar2\", \"/src/lel.py\", 15),\n                            value=2048,\n                            children={\n                                (\"baz2\", \"/src/lel.py\", 18): Frame(\n                                    location=(\"baz2\", \"/src/lel.py\", 18),\n                                    value=2048,\n                                    children={},\n                                    n_allocations=2,\n                                    thread_id=\"merged thread\",\n                                    interesting=True,\n                                    import_system=False,\n                                )\n                            },\n                            n_allocations=2,\n                            thread_id=\"merged thread\",\n                            interesting=True,\n                            import_system=False,\n                        )\n                    },\n                    n_allocations=2,\n                    thread_id=\"merged thread\",\n                    interesting=True,\n                    import_system=False,\n                )\n            },\n            n_allocations=2,\n            thread_id=\"\",\n            interesting=True,\n            import_system=False,\n        )\n\n    def test_drops_cpython_frames(self):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"me\", \"fun.py\", 12),\n                    (\"parent\", \"fun.py\", 8),\n                    (\"PyObject_Call\", \"/src/python/python3.8/Python/ceval.c\", 4),\n                    (\n                        \"PyCFunction_Call\",\n                        \"/src/python/python3.8/Objects/call.c\",\n                        1,\n                    ),\n                ],\n            ),\n        ]\n\n        # WHEN\n        reporter = TreeReporter.from_snapshot(peak_allocations, native_traces=False)\n\n        # THEN\n        assert reporter.data == Frame(\n            location=(\"<ROOT>\", \"\", 0),\n            value=1024,\n            children={\n                (\"parent\", \"fun.py\", 8): Frame(\n                    location=(\"parent\", \"fun.py\", 8),\n                    value=1024,\n                    children={\n                        (\"me\", \"fun.py\", 12): Frame(\n                            location=(\"me\", \"fun.py\", 12),\n                            value=1024,\n                            children={},\n                            n_allocations=1,\n                            thread_id=\"0x1\",\n                            interesting=True,\n                            import_system=False,\n                        )\n                    },\n                    n_allocations=1,\n                    thread_id=\"0x1\",\n                    interesting=True,\n                    import_system=False,\n                )\n            },\n            n_allocations=1,\n            thread_id=\"\",\n            interesting=True,\n            import_system=False,\n        )\n\n\n@dataclass(frozen=True)\nclass TreeElement:\n    label: str\n    children: List[\"TreeElement\"]\n    allow_expand: bool\n    is_expanded: bool\n\n\ndef tree_to_dict(tree: TreeNode):\n    return TreeElement(\n        str(tree.label),\n        [tree_to_dict(child) for child in tree.children],\n        tree.allow_expand,\n        tree.is_expanded,\n    )\n\n\nclass TestTreeTui:\n    def test_no_allocations(self):\n        # GIVEN\n        peak_allocations = []\n\n        reporter = TreeReporter.from_snapshot(\n            peak_allocations, native_traces=False, biggest_allocs=3\n        )\n        app = reporter.get_app()\n\n        # WHEN\n        async def run_test():\n            async with app.run_test() as pilot:\n                await pilot.pause()\n                return app.screen.query_one(Tree).root\n\n        root = async_run(run_test())\n\n        # THEN\n        assert tree_to_dict(root) == TreeElement(\n            label=\"<No allocations>\", children=[], is_expanded=True, allow_expand=True\n        )\n\n    def test_single_chain_is_expanded(self):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"me\", \"fun.py\", 12),\n                    (\"parent\", \"fun.py\", 8),\n                    (\"grandparent\", \"fun.py\", 4),\n                ],\n            ),\n        ]\n\n        reporter = TreeReporter.from_snapshot(\n            peak_allocations, native_traces=False, biggest_allocs=3\n        )\n        app = reporter.get_app()\n\n        # WHEN\n        async def run_test():\n            async with app.run_test() as pilot:\n                await pilot.pause()\n                return app.screen.query_one(Tree).root\n\n        root = async_run(run_test())\n\n        # THEN\n        assert tree_to_dict(root) == TreeElement(\n            label=\"📂 1.024kB (100.00 %) <ROOT>\",\n            children=[\n                TreeElement(\n                    label=\"📂 1.024kB (100.00 %) grandparent  fun.py:4\",\n                    children=[\n                        TreeElement(\n                            label=\"📂 1.024kB (100.00 %) parent  fun.py:8\",\n                            children=[\n                                TreeElement(\n                                    label=\"📄 1.024kB (100.00 %) me  fun.py:12\",\n                                    children=[],\n                                    allow_expand=False,\n                                    is_expanded=True,\n                                )\n                            ],\n                            allow_expand=True,\n                            is_expanded=True,\n                        )\n                    ],\n                    allow_expand=True,\n                    is_expanded=True,\n                )\n            ],\n            allow_expand=True,\n            is_expanded=True,\n        )\n\n    def test_only_biggest_chain_is_expanded(self):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024 * 4,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"me\", \"fun.py\", 12),\n                    (\"parent\", \"fun.py\", 8),\n                    (\"grandparent\", \"fun.py\", 4),\n                ],\n            ),\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024 * 3,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"me2\", \"fun2.py\", 12),\n                    (\"parent2\", \"fun2.py\", 8),\n                    (\"grandparent2\", \"fun2.py\", 4),\n                ],\n            ),\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024 * 3,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"child2\", \"fun2.py\", 22),\n                    (\"me2\", \"fun2.py\", 12),\n                    (\"parent2\", \"fun2.py\", 8),\n                    (\"grandparent2\", \"fun2.py\", 4),\n                ],\n            ),\n        ]\n\n        reporter = TreeReporter.from_snapshot(\n            peak_allocations, native_traces=False, biggest_allocs=3\n        )\n        app = reporter.get_app()\n\n        # WHEN\n        async def run_test():\n            async with app.run_test() as pilot:\n                await pilot.pause()\n                return app.screen.query_one(Tree).root\n\n        root = async_run(run_test())\n\n        # THEN\n        assert tree_to_dict(root) == TreeElement(\n            label=\"📂 10.240kB (100.00 %) <ROOT>\",\n            children=[\n                TreeElement(\n                    label=\"📂 6.144kB (60.00 %) grandparent2  fun2.py:4\",\n                    children=[\n                        TreeElement(\n                            label=\"📂 6.144kB (60.00 %) parent2  fun2.py:8\",\n                            children=[\n                                TreeElement(\n                                    label=\"📂 6.144kB (60.00 %) me2  fun2.py:12\",\n                                    children=[\n                                        TreeElement(\n                                            label=\"📄 3.072kB (30.00 %) child2  fun2.py:22\",\n                                            children=[],\n                                            allow_expand=False,\n                                            is_expanded=True,\n                                        )\n                                    ],\n                                    allow_expand=True,\n                                    is_expanded=True,\n                                )\n                            ],\n                            allow_expand=True,\n                            is_expanded=True,\n                        )\n                    ],\n                    allow_expand=True,\n                    is_expanded=True,\n                ),\n                TreeElement(\n                    label=\"📂 4.096kB (40.00 %) grandparent  fun.py:4\",\n                    children=[\n                        TreeElement(\n                            label=\"📂 4.096kB (40.00 %) parent  fun.py:8\",\n                            children=[\n                                TreeElement(\n                                    label=\"📄 4.096kB (40.00 %) me  fun.py:12\",\n                                    children=[],\n                                    allow_expand=False,\n                                    is_expanded=False,\n                                )\n                            ],\n                            allow_expand=True,\n                            is_expanded=False,\n                        )\n                    ],\n                    allow_expand=True,\n                    is_expanded=False,\n                ),\n            ],\n            allow_expand=True,\n            is_expanded=True,\n        )\n\n    def test_show_uninteresting_system(self):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"me\", \"foo.py\", 12),\n                    (\"parent\", \"runpy.py\", 8),\n                    (\"grandparent\", \"runpy.py\", 4),\n                ],\n            ),\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024 * 10,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"me2\", \"fun2.py\", 12),\n                    (\"parent2\", \"fun2.py\", 8),\n                    (\"grandparent2\", \"fun2.py\", 4),\n                ],\n            ),\n        ]\n\n        reporter = TreeReporter.from_snapshot(\n            peak_allocations, native_traces=False, biggest_allocs=3\n        )\n        app = reporter.get_app()\n\n        # WHEN\n        async def run_test():\n            async with app.run_test() as pilot:\n                await pilot.pause()\n                tree = app.screen.query_one(Tree)\n                first_tree = tree_to_dict(tree.root)\n                await pilot.press(\"u\")\n                await pilot.pause()\n                second_tree = tree_to_dict(tree.root)\n                return first_tree, second_tree\n\n        first_tree, second_tree = async_run(run_test())\n\n        # THEN\n        assert first_tree == TreeElement(\n            label=\"📂 11.264kB (100.00 %) <ROOT>\",\n            children=[\n                TreeElement(\n                    label=\"📂 10.240kB (90.91 %) grandparent2  fun2.py:4\",\n                    children=[\n                        TreeElement(\n                            label=\"📂 10.240kB (90.91 %) parent2  fun2.py:8\",\n                            children=[\n                                TreeElement(\n                                    label=\"📄 10.240kB (90.91 %) me2  fun2.py:12\",\n                                    children=[],\n                                    allow_expand=False,\n                                    is_expanded=True,\n                                )\n                            ],\n                            allow_expand=True,\n                            is_expanded=True,\n                        )\n                    ],\n                    allow_expand=True,\n                    is_expanded=True,\n                ),\n                TreeElement(\n                    label=\"📄 1.024kB (9.09 %) me  foo.py:12\",\n                    children=[],\n                    allow_expand=False,\n                    is_expanded=False,\n                ),\n            ],\n            allow_expand=True,\n            is_expanded=True,\n        )\n        assert second_tree == TreeElement(\n            label=\"📂 11.264kB (100.00 %) <ROOT>\",\n            children=[\n                TreeElement(\n                    label=\"📂 10.240kB (90.91 %) grandparent2  fun2.py:4\",\n                    children=[\n                        TreeElement(\n                            label=\"📂 10.240kB (90.91 %) parent2  fun2.py:8\",\n                            children=[\n                                TreeElement(\n                                    label=\"📄 10.240kB (90.91 %) me2  fun2.py:12\",\n                                    children=[],\n                                    allow_expand=False,\n                                    is_expanded=True,\n                                )\n                            ],\n                            allow_expand=True,\n                            is_expanded=True,\n                        )\n                    ],\n                    allow_expand=True,\n                    is_expanded=True,\n                ),\n                TreeElement(\n                    label=\"📂 1.024kB (9.09 %) grandparent  runpy.py:4\",\n                    children=[\n                        TreeElement(\n                            label=\"📂 1.024kB (9.09 %) parent  runpy.py:8\",\n                            children=[\n                                TreeElement(\n                                    label=\"📄 1.024kB (9.09 %) me  foo.py:12\",\n                                    children=[],\n                                    allow_expand=False,\n                                    is_expanded=False,\n                                )\n                            ],\n                            allow_expand=True,\n                            is_expanded=False,\n                        )\n                    ],\n                    allow_expand=True,\n                    is_expanded=False,\n                ),\n            ],\n            allow_expand=True,\n            is_expanded=True,\n        )\n\n    def test_show_uninteresting_idempotency(self):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"me\", \"foo.py\", 12),\n                    (\"parent\", \"runpy.py\", 8),\n                    (\"grandparent\", \"runpy.py\", 4),\n                ],\n            ),\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024 * 10,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"me2\", \"fun2.py\", 12),\n                    (\"parent2\", \"fun2.py\", 8),\n                    (\"grandparent2\", \"fun2.py\", 4),\n                ],\n            ),\n        ]\n\n        reporter = TreeReporter.from_snapshot(\n            peak_allocations, native_traces=False, biggest_allocs=3\n        )\n        app = reporter.get_app()\n\n        # WHEN\n        async def run_test():\n            async with app.run_test() as pilot:\n                await pilot.pause()\n                tree = app.screen.query_one(Tree)\n                first_tree = tree_to_dict(tree.root)\n                await pilot.press(\"i\")\n                await pilot.pause()\n                await pilot.press(\"i\")\n                await pilot.pause()\n                second_tree = tree_to_dict(tree.root)\n                return first_tree, second_tree\n\n        first_tree, second_tree = async_run(run_test())\n\n        # THEN\n        assert first_tree == second_tree\n\n    def test_uninteresting_leaves(self):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"parent\", \"runpy.py\", 8),\n                    (\"grandparent\", \"runpy.py\", 4),\n                    (\"me\", \"foo.py\", 12),\n                ],\n            ),\n        ]\n\n        reporter = TreeReporter.from_snapshot(\n            peak_allocations, native_traces=False, biggest_allocs=3\n        )\n        app = reporter.get_app()\n\n        # WHEN\n        async def run_test():\n            async with app.run_test() as pilot:\n                await pilot.pause()\n                tree = app.screen.query_one(Tree)\n                return tree.root\n\n        root = async_run(run_test())\n\n        # THEN\n\n        assert tree_to_dict(root) == TreeElement(\n            label=\"📂 1.024kB (100.00 %) <ROOT>\",\n            children=[\n                TreeElement(\n                    label=\"📄 1.024kB (100.00 %) me  foo.py:12\",\n                    children=[],\n                    allow_expand=False,\n                    is_expanded=True,\n                )\n            ],\n            allow_expand=True,\n            is_expanded=True,\n        )\n\n    def test_hide_import_system(self):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"me\", \"<frozen importlib>\", 12),\n                    (\"parent\", \"<frozen importlib>\", 8),\n                    (\"grandparent\", \"<frozen importlib>\", 4),\n                ],\n            ),\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024 * 10,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"me2\", \"fun2.py\", 12),\n                    (\"parent2\", \"fun2.py\", 8),\n                    (\"grandparent2\", \"fun2.py\", 4),\n                ],\n            ),\n        ]\n\n        reporter = TreeReporter.from_snapshot(\n            peak_allocations, native_traces=False, biggest_allocs=3\n        )\n        app = reporter.get_app()\n\n        # WHEN\n        async def run_test():\n            async with app.run_test() as pilot:\n                await pilot.pause()\n                tree = app.screen.query_one(Tree)\n                first_tree = tree_to_dict(tree.root)\n                await pilot.press(\"i\")\n                await pilot.pause()\n                second_tree = tree_to_dict(tree.root)\n                return first_tree, second_tree\n\n        first_tree, second_tree = async_run(run_test())\n\n        # THEN\n        assert first_tree == TreeElement(\n            label=\"📂 11.264kB (100.00 %) <ROOT>\",\n            children=[\n                TreeElement(\n                    label=\"📂 10.240kB (90.91 %) grandparent2  fun2.py:4\",\n                    children=[\n                        TreeElement(\n                            label=\"📂 10.240kB (90.91 %) parent2  fun2.py:8\",\n                            children=[\n                                TreeElement(\n                                    label=\"📄 10.240kB (90.91 %) me2  fun2.py:12\",\n                                    children=[],\n                                    allow_expand=False,\n                                    is_expanded=True,\n                                )\n                            ],\n                            allow_expand=True,\n                            is_expanded=True,\n                        )\n                    ],\n                    allow_expand=True,\n                    is_expanded=True,\n                )\n            ],\n            allow_expand=True,\n            is_expanded=True,\n        )\n        assert second_tree == TreeElement(\n            label=\"📂 11.264kB (100.00 %) <ROOT>\",\n            children=[\n                TreeElement(\n                    label=\"📂 10.240kB (90.91 %) grandparent2  fun2.py:4\",\n                    children=[\n                        TreeElement(\n                            label=\"📂 10.240kB (90.91 %) parent2  fun2.py:8\",\n                            children=[\n                                TreeElement(\n                                    label=\"📄 10.240kB (90.91 %) me2  fun2.py:12\",\n                                    children=[],\n                                    allow_expand=False,\n                                    is_expanded=True,\n                                )\n                            ],\n                            allow_expand=True,\n                            is_expanded=True,\n                        )\n                    ],\n                    allow_expand=True,\n                    is_expanded=True,\n                )\n            ],\n            allow_expand=True,\n            is_expanded=True,\n        )\n\n    def test_hide_import_system_idempotency(self):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"me\", \"<frozen importlib>\", 12),\n                    (\"parent\", \"<frozen importlib>\", 8),\n                    (\"grandparent\", \"<frozen importlib>\", 4),\n                ],\n            ),\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024 * 10,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"me2\", \"fun2.py\", 12),\n                    (\"parent2\", \"fun2.py\", 8),\n                    (\"grandparent2\", \"fun2.py\", 4),\n                ],\n            ),\n        ]\n\n        reporter = TreeReporter.from_snapshot(\n            peak_allocations, native_traces=False, biggest_allocs=3\n        )\n        app = reporter.get_app()\n\n        # WHEN\n        async def run_test():\n            async with app.run_test() as pilot:\n                await pilot.pause()\n                tree = app.screen.query_one(Tree)\n                first_tree = tree_to_dict(tree.root)\n                await pilot.press(\"i\")\n                await pilot.pause()\n                await pilot.press(\"i\")\n                await pilot.pause()\n                second_tree = tree_to_dict(tree.root)\n                return first_tree, second_tree\n\n        first_tree, second_tree = async_run(run_test())\n\n        # THEN\n        assert first_tree == second_tree\n\n    def test_expand_linear_chain(self):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"me\", \"fun.py\", 12),\n                    (\"parent\", \"fun.py\", 8),\n                    (\"grandparent\", \"fun.py\", 4),\n                ],\n            ),\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024 * 10,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"me2\", \"fun2.py\", 12),\n                    (\"parent2\", \"fun2.py\", 8),\n                    (\"grandparent2\", \"fun2.py\", 4),\n                ],\n            ),\n        ]\n\n        reporter = TreeReporter.from_snapshot(\n            peak_allocations, native_traces=False, biggest_allocs=3\n        )\n        app = reporter.get_app()\n\n        # WHEN\n        async def run_test():\n            async with app.run_test() as pilot:\n                await pilot.pause()\n                tree = app.screen.query_one(Tree)\n                child = tree.root.children[1]\n                # From Textual 0.73 on, Tree.select_node toggles the node's expanded\n                # state. The new Tree.move_cursor method selects without expanding.\n                getattr(tree, \"move_cursor\", tree.select_node)(child)\n                await pilot.press(\"e\")\n                await pilot.pause()\n                return tree.root\n\n        root = async_run(run_test())\n\n        # THEN\n        assert tree_to_dict(root) == TreeElement(\n            label=\"📂 11.264kB (100.00 %) <ROOT>\",\n            children=[\n                TreeElement(\n                    label=\"📂 10.240kB (90.91 %) grandparent2  fun2.py:4\",\n                    children=[\n                        TreeElement(\n                            label=\"📂 10.240kB (90.91 %) parent2  fun2.py:8\",\n                            children=[\n                                TreeElement(\n                                    label=\"📄 10.240kB (90.91 %) me2  fun2.py:12\",\n                                    children=[],\n                                    allow_expand=False,\n                                    is_expanded=True,\n                                )\n                            ],\n                            allow_expand=True,\n                            is_expanded=True,\n                        )\n                    ],\n                    allow_expand=True,\n                    is_expanded=True,\n                ),\n                TreeElement(\n                    label=\"📂 1.024kB (9.09 %) grandparent  fun.py:4\",\n                    children=[\n                        TreeElement(\n                            label=\"📂 1.024kB (9.09 %) parent  fun.py:8\",\n                            children=[\n                                TreeElement(\n                                    label=\"📄 1.024kB (9.09 %) me  fun.py:12\",\n                                    children=[],\n                                    allow_expand=False,\n                                    is_expanded=True,\n                                )\n                            ],\n                            allow_expand=True,\n                            is_expanded=True,\n                        )\n                    ],\n                    allow_expand=True,\n                    is_expanded=True,\n                ),\n            ],\n            allow_expand=True,\n            is_expanded=True,\n        )\n\n    def test_very_deep_call_is_limited(self):\n        # GIVEN\n        n_frames = MAX_STACKS + 50\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[(f\"func_{i}\", \"fun.py\", i) for i in range(n_frames, 0, -1)],\n            ),\n        ]\n\n        reporter = TreeReporter.from_snapshot(peak_allocations, native_traces=False)\n        app = reporter.get_app()\n\n        # WHEN\n        async def run_test():\n            async with app.run_test() as pilot:\n                await pilot.pause()\n                return app.screen.query_one(Tree).root\n\n        root = async_run(run_test())\n\n        assert str(root.label) == \"📂 1.024kB (100.00 %) <ROOT>\"\n        assert len(root.children) == 1\n        current_node = root.children[0]\n        for i in range(1, MAX_STACKS + 2):\n            assert f\"func_{i}\" in str(current_node.label)\n            assert len(current_node.children) == 1\n            current_node = current_node.children[0]\n        assert not current_node.children\n\n    def test_render_runs_the_app(self):\n        # GIVEN\n        with patch(\"memray.reporters.tree.TreeReporter.get_app\") as get_app:\n            reporter = TreeReporter.from_snapshot([], native_traces=False)\n            # WHEN\n            reporter.render()\n\n        # THEN\n        get_app.return_value.run.assert_called()\n\n\n@pytest.fixture\ndef compare(monkeypatch, tmp_path, snap_compare):\n    def compare_impl(\n        allocations: Iterator[AllocationRecord],\n        press: Iterable[str] = (),\n        terminal_size: Tuple[int, int] = (120, 60),\n        run_before: Optional[Callable[[Pilot], Optional[Awaitable[None]]]] = None,\n        native: bool = False,\n        biggest_allocs: Optional[int] = None,\n    ):\n        from_snapshot_kwargs: Dict[str, Any] = {\"native_traces\": native}\n        if biggest_allocs is not None:\n            from_snapshot_kwargs[\"biggest_allocs\"] = biggest_allocs\n        reporter = TreeReporter.from_snapshot(allocations, **from_snapshot_kwargs)\n        app = reporter.get_app()\n\n        try:\n            asyncio.get_event_loop()\n        except RuntimeError:\n            asyncio.set_event_loop(asyncio.new_event_loop())\n\n        return snap_compare(\n            app,\n            press=press,\n            terminal_size=terminal_size,\n            run_before=run_before,\n        )\n\n    yield compare_impl\n\n\nclass TestTUILooks:\n    def test_basic(self, compare):\n        # GIVEN\n        code = dedent(\n            \"\"\"\\\n        import itertools\n        def generate_primes():\n            numbers = itertools.count(2)\n            while True:\n                prime = next(numbers)\n                yield prime\n                numbers = filter(lambda x, prime=prime: x % prime, numbers)\n        \"\"\"\n        )\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"me\", \"fun.py\", 12),\n                    (\"parent\", \"fun.py\", 8),\n                    (\"grandparent\", \"fun.py\", 4),\n                ],\n            ),\n        ]\n\n        # WHEN / THEN\n        with patch(\"linecache.getlines\") as getlines:\n            getlines.return_value = code.splitlines()\n            assert compare(peak_allocations, press=[])\n\n    def test_basic_node_selected_not_leaf(self, compare):\n        # GIVEN\n        code = dedent(\n            \"\"\"\\\n        import itertools\n        def generate_primes():\n            numbers = itertools.count(2)\n            while True:\n                prime = next(numbers)\n                yield prime\n                numbers = filter(lambda x, prime=prime: x % prime, numbers)\n        \"\"\"\n        )\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"me\", \"fun.py\", 12),\n                    (\"parent\", \"fun.py\", 8),\n                    (\"grandparent\", \"fun.py\", 4),\n                ],\n            ),\n        ]\n\n        # WHEN / THEN\n        with patch(\"linecache.getlines\") as getlines:\n            getlines.return_value = code.splitlines()\n            assert compare(peak_allocations, press=[*[\"down\"] * 2])\n\n    def test_basic_node_selected_leaf(self, compare):\n        # GIVEN\n        code = dedent(\n            \"\"\"\\\n        import itertools\n        def generate_primes():\n            numbers = itertools.count(2)\n            while True:\n                prime = next(numbers)\n                yield prime\n                numbers = filter(lambda x, prime=prime: x % prime, numbers)\n        \"\"\"\n        )\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"me\", \"fun.py\", 12),\n                    (\"parent\", \"fun.py\", 8),\n                    (\"grandparent\", \"fun.py\", 4),\n                ],\n            ),\n        ]\n\n        # WHEN / THEN\n        with patch(\"linecache.getlines\") as getlines:\n            getlines.return_value = code.splitlines()\n            assert compare(peak_allocations, press=[*[\"down\"] * 3])\n\n    def test_two_chains(self, compare):\n        # GIVEN\n        code = dedent(\n            \"\"\"\\\n        import itertools\n        def generate_primes():\n            numbers = itertools.count(2)\n            while True:\n                prime = next(numbers)\n                yield prime\n                numbers = filter(lambda x, prime=prime: x % prime, numbers)\n        \"\"\"\n        )\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"me\", \"fun.py\", 12),\n                    (\"parent\", \"fun.py\", 8),\n                    (\"grandparent\", \"fun.py\", 4),\n                ],\n            ),\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024 * 10,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"me2\", \"fun2.py\", 12),\n                    (\"parent2\", \"fun2.py\", 8),\n                    (\"grandparent2\", \"fun2.py\", 4),\n                ],\n            ),\n        ]\n\n        # WHEN / THEN\n        with patch(\"linecache.getlines\") as getlines:\n            getlines.return_value = code.splitlines()\n            assert compare(peak_allocations, press=[])\n\n    def test_two_chains_after_expanding_second(self, compare):\n        # GIVEN\n        code = dedent(\n            \"\"\"\\\n        import itertools\n        def generate_primes():\n            numbers = itertools.count(2)\n            while True:\n                prime = next(numbers)\n                yield prime\n                numbers = filter(lambda x, prime=prime: x % prime, numbers)\n        \"\"\"\n        )\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"a\", \"fun.py\", 1),\n                    (\"b\", \"fun.py\", 2),\n                    (\"c\", \"fun.py\", 3),\n                    (\"d\", \"fun.py\", 4),\n                    (\"e\", \"fun.py\", 5),\n                ],\n            ),\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024 * 10,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"me2\", \"fun2.py\", 12),\n                    (\"parent2\", \"fun2.py\", 8),\n                    (\"grandparent2\", \"fun2.py\", 4),\n                ],\n            ),\n        ]\n\n        # WHEN / THEN\n        with patch(\"linecache.getlines\") as getlines:\n            getlines.return_value = code.splitlines()\n            assert compare(peak_allocations, press=[*[\"down\"] * 4, \"e\"])\n\n    def test_hide_import_system(self, compare):\n        # GIVEN\n        code = dedent(\n            \"\"\"\\\n        import itertools\n        def generate_primes():\n            numbers = itertools.count(2)\n            while True:\n                prime = next(numbers)\n                yield prime\n                numbers = filter(lambda x, prime=prime: x % prime, numbers)\n        \"\"\"\n        )\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"a0\", \"some other frame\", 4),\n                    (\"a\", \"<frozen importlib>\", 1),\n                    (\"b\", \"<frozen importlib>\", 2),\n                    (\"c\", \"<frozen importlib>\", 3),\n                    (\"d\", \"<frozen importlib>\", 4),\n                    (\"e\", \"<frozen importlib>\", 5),\n                ],\n            ),\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024 * 10,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"me2\", \"fun2.py\", 12),\n                    (\"parent2\", \"fun2.py\", 8),\n                    (\"grandparent2\", \"fun2.py\", 4),\n                ],\n            ),\n        ]\n\n        # WHEN / THEN\n        with patch(\"linecache.getlines\") as getlines:\n            getlines.return_value = code.splitlines()\n            assert compare(peak_allocations, press=[\"i\"])\n\n    def test_show_uninteresting(self, compare):\n        # GIVEN\n        code = dedent(\n            \"\"\"\\\n        import itertools\n        def generate_primes():\n            numbers = itertools.count(2)\n            while True:\n                prime = next(numbers)\n                yield prime\n                numbers = filter(lambda x, prime=prime: x % prime, numbers)\n        \"\"\"\n        )\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024 * 10,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"me2\", \"fun2.py\", 12),\n                    (\"parent2\", \"fun2.py\", 8),\n                    (\"grandparent2\", \"fun2.py\", 4),\n                ],\n            ),\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"a0\", \"some other frame\", 4),\n                    (\"a\", \"runpy.py\", 1),\n                    (\"b\", \"runpy.py\", 2),\n                    (\"c\", \"runpy.py\", 3),\n                    (\"d\", \"runpy.py\", 4),\n                    (\"e\", \"runpy.py\", 5),\n                ],\n            ),\n        ]\n\n        # WHEN / THEN\n        with patch(\"linecache.getlines\") as getlines:\n            getlines.return_value = code.splitlines()\n            assert compare(peak_allocations, press=[\"u\"])\n\n    def test_show_uninteresting_and_hide_import_system(self, compare):\n        # GIVEN\n        code = dedent(\n            \"\"\"\\\n        import itertools\n        def generate_primes():\n            numbers = itertools.count(2)\n            while True:\n                prime = next(numbers)\n                yield prime\n                numbers = filter(lambda x, prime=prime: x % prime, numbers)\n        \"\"\"\n        )\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024 * 10,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"B\", \"some other frame\", 4),\n                    (\"d\", \"<frozen importlib>\", 3),\n                    (\"e\", \"<frozen importlib>\", 4),\n                    (\"A\", \"some other frame\", 4),\n                    (\"a\", \"runpy.py\", 1),\n                    (\"b\", \"runpy.py\", 2),\n                    (\"c\", \"runpy.py\", 5),\n                ],\n            ),\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"me2\", \"fun2.py\", 12),\n                    (\"parent2\", \"fun2.py\", 8),\n                    (\"grandparent2\", \"fun2.py\", 4),\n                ],\n            ),\n        ]\n\n        # WHEN / THEN\n        with patch(\"linecache.getlines\") as getlines:\n            getlines.return_value = code.splitlines()\n            assert compare(peak_allocations, press=[\"u\", \"i\"])\n\n    def test_select_screen(self, tmp_path, compare):\n        # GIVEN\n        code = dedent(\n            \"\"\"\\\n        import itertools\n        def generate_primes():\n            numbers = itertools.count(2)\n            while True:\n                prime = next(numbers)\n                yield prime\n                numbers = filter(lambda x, prime=prime: x % prime, numbers)\n        \"\"\"\n        )\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"me2\", \"func2.py\", 4),\n                    (\"parent2\", \"fun2.py\", 8),\n                    (\"grandparent2\", \"fun2.py\", 4),\n                ],\n            ),\n        ]\n        # WHEN / THEN\n        with patch(\"linecache.getlines\") as getlines:\n            getlines.return_value = code.splitlines()\n            assert compare(peak_allocations, press=[*[\"down\"] * 3])\n\n    def test_allocations_of_different_sizes(self, compare):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=65,\n                allocator=AllocatorType.MALLOC,\n                stack_id=j,\n                n_allocations=1,\n                _stack=[(f\"func{i}\", f\"fun{i}.py\", i) for i in range(1, 51)][:j][::-1],\n            )\n            for j in range(1, 51)\n        ]\n\n        # WHEN / THEN\n        with patch(\"linecache.getlines\") as getlines:\n            getlines.return_value = []\n            assert compare(peak_allocations, press=[], terminal_size=(350, 100))\n\n    def test_biggest_allocations(self, compare):\n        # GIVEN\n        peak_allocations = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=index * 1024,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (f\"function_{index}\", \"fun.py\", 12),\n                ],\n            )\n            for index in range(1000)\n        ]\n\n        # WHEN / THEN\n        with patch(\"linecache.getlines\") as getlines:\n            getlines.return_value = []\n            assert compare(\n                peak_allocations,\n                press=[\"end\"],\n                biggest_allocs=10,\n                terminal_size=(200, 40),\n            )\n"
  },
  {
    "path": "tests/unit/test_tui_reporter.py",
    "content": "import asyncio\nimport datetime\nfrom io import StringIO\nfrom typing import Awaitable\nfrom typing import Callable\nfrom typing import Dict\nfrom typing import Iterable\nfrom typing import List\nfrom typing import Optional\nfrom typing import Tuple\nfrom typing import cast\n\nimport pytest\nfrom rich import print as rprint\nfrom textual.app import App\nfrom textual.coordinate import Coordinate\nfrom textual.pilot import Pilot\nfrom textual.widget import Widget\nfrom textual.widgets import DataTable\nfrom textual.widgets import Label\n\nimport memray.reporters.tui\nfrom memray import AllocationRecord\nfrom memray import AllocatorType\nfrom memray.reporters.tui import Location\nfrom memray.reporters.tui import MemoryGraph\nfrom memray.reporters.tui import Snapshot\nfrom memray.reporters.tui import SnapshotFetched\nfrom memray.reporters.tui import TUIApp\nfrom memray.reporters.tui import aggregate_allocations\nfrom tests.utils import MockAllocationRecord\nfrom tests.utils import async_run\n\n\nclass MockApp(TUIApp):\n    CSS_PATH = None  # type: ignore\n\n    def __init__(self, *args, disable_update_thread=True, **kwargs):\n        super().__init__(*args, **kwargs)\n        if disable_update_thread:\n            # Make the update thread return immediately when started\n            self._update_thread.cancel()\n\n    def add_mock_snapshot(\n        self,\n        snapshot: List[MockAllocationRecord],\n        disconnected: bool = False,\n        native: bool = True,\n    ) -> None:\n        records = cast(List[AllocationRecord], snapshot)\n        self.post_message(\n            SnapshotFetched(\n                Snapshot(\n                    heap_size=sum(record.size for record in records),\n                    records=records,\n                    records_by_location=aggregate_allocations(\n                        cast(List[AllocationRecord], records), native_traces=native\n                    ),\n                ),\n                disconnected,\n            )\n        )\n\n    def add_mock_snapshots(\n        self,\n        snapshots: List[List[MockAllocationRecord]],\n        disconnect_after_last: bool = True,\n        native: bool = True,\n    ) -> None:\n        for i, snapshot in enumerate(snapshots):\n            disconnected = i == len(snapshots) - 1 and disconnect_after_last\n            self.add_mock_snapshot(snapshot, disconnected=disconnected, native=native)\n\n\nclass MockReader:\n    def __init__(\n        self,\n        snapshots: List[List[MockAllocationRecord]],\n        has_native_traces: bool = True,\n        pid: Optional[int] = None,\n        command_line: Optional[str] = None,\n    ):\n        self._snapshots = cast(List[List[AllocationRecord]], snapshots)\n        self._next_snapshot = 0\n        self.is_active = True\n        self.command_line = command_line\n        self.pid = pid\n        self.has_native_traces = has_native_traces\n\n    def get_current_snapshot(\n        self, *, merge_threads: bool\n    ) -> Iterable[AllocationRecord]:\n        assert isinstance(merge_threads, bool)  # ignore unused argument\n        assert self.is_active\n        snapshot = self._snapshots[self._next_snapshot]\n        self._next_snapshot += 1\n        self.is_active = self._next_snapshot < len(self._snapshots)\n        return snapshot\n\n\n@pytest.fixture\ndef compare(monkeypatch, tmp_path, snap_compare):\n    monkeypatch.setattr(memray.reporters.tui, \"datetime\", FakeDatetime)\n\n    def compare_impl(\n        cmdline_override: Optional[str] = None,\n        press: Iterable[str] = (),\n        terminal_size: Tuple[int, int] = (80, 24),\n        run_before: Optional[Callable[[Pilot], Optional[Awaitable[None]]]] = None,\n        native: bool = True,\n    ):\n        async def run_before_wrapper(pilot) -> None:\n            if run_before is not None:\n                result = run_before(pilot)\n                if result is not None:\n                    await result\n\n            await pilot.pause()\n            await pilot.pause(0.2)\n            header = pilot.app.screen.query_one(\"Header\")\n            header.last_update = header.start + datetime.timedelta(seconds=42)\n\n        app = MockApp(\n            MockReader([], has_native_traces=native),\n            cmdline_override=cmdline_override,\n        )\n\n        try:\n            asyncio.get_event_loop()\n        except RuntimeError:\n            asyncio.set_event_loop(asyncio.new_event_loop())\n\n        return snap_compare(\n            app,\n            press=press,\n            terminal_size=terminal_size,\n            run_before=run_before_wrapper,\n        )\n\n    yield compare_impl\n\n\ndef render_widget(widget: Widget) -> str:\n    output = StringIO()\n    content = getattr(widget, \"renderable\", None)\n    if content is None:\n        content = widget.content  # type: ignore\n    assert content is not None\n    rprint(content, file=output)\n    return output.getvalue()\n\n\ndef extract_label_text(app: App) -> Dict[str, str]:\n    return {\n        label.id: render_widget(label)\n        for label in app.screen.query(Label)\n        if label.id is not None\n    }\n\n\ndef mock_allocation(\n    stack: Optional[List[Tuple[str, str, int]]] = None,\n    tid: int = 1,\n    address: int = 0,\n    size: int = 1024,\n    allocator: AllocatorType = AllocatorType.MALLOC,\n    stack_id: int = 0,\n    n_allocations: int = 1,\n    thread_name: str = \"\",\n):\n    hybrid_stack = stack\n\n    if hybrid_stack is not None:\n        stack = [\n            (func, filename, lineno)\n            for func, filename, lineno in hybrid_stack\n            if filename.endswith(\".py\")\n        ]\n\n    return MockAllocationRecord(\n        tid=tid,\n        address=address,\n        size=size,\n        allocator=allocator,\n        stack_id=stack_id,\n        n_allocations=n_allocations,\n        thread_name=thread_name,\n        _stack=stack,\n        _hybrid_stack=hybrid_stack,\n    )\n\n\nSHORT_SNAPSHOTS = [\n    [\n        mock_allocation(\n            stack=[\n                (\"malloc\", \"malloc.c\", 1234),\n                (\"f1\", \"f.py\", 16),\n                (\"parent\", \"fun.py\", 8),\n                (\"grandparent\", \"fun.py\", 4),\n            ],\n        ),\n    ],\n    [\n        mock_allocation(\n            stack=[\n                (\"malloc\", \"malloc.c\", 1234),\n                (\"f1\", \"f.py\", 16),\n                (\"parent\", \"fun.py\", 8),\n                (\"grandparent\", \"fun.py\", 4),\n            ],\n        ),\n        mock_allocation(\n            stack=[\n                (\"malloc\", \"malloc.c\", 1234),\n                (\"f2\", \"f.py\", 32),\n                (\"parent\", \"fun.py\", 8),\n                (\"grandparent\", \"fun.py\", 4),\n            ],\n        ),\n        mock_allocation(\n            stack=[\n                (\"malloc\", \"malloc.c\", 1234),\n                (\"f2\", \"f.py\", 32),\n                (\"parent\", \"fun.py\", 8),\n                (\"grandparent\", \"fun.py\", 4),\n            ],\n        ),\n    ],\n]\n\n\nLONG_SNAPSHOTS = [\n    [\n        mock_allocation(\n            stack=[\n                (\"malloc\", \"malloc.c\", 1234),\n                (\"f1\", \"f.py\", 16),\n                (\"parent\", \"fun.py\", 8),\n                (\"grandparent\", \"fun.py\", 4),\n            ],\n        ),\n    ],\n    [\n        mock_allocation(\n            stack=[\n                (\"malloc\", \"malloc.c\", 1234),\n                (\"f1\", \"f.py\", 16),\n                (\"parent\", \"fun.py\", 8),\n                (\"grandparent\", \"fun.py\", 4),\n            ],\n        ),\n        mock_allocation(\n            stack=[\n                (\"malloc\", \"malloc.c\", 1234),\n                (\"f2\", \"f.py\", 32),\n                (\"parent\", \"fun.py\", 8),\n                (\"grandparent\", \"fun.py\", 4),\n            ],\n        ),\n        mock_allocation(\n            size=333,\n            stack=[\n                (\"malloc\", \"malloc.c\", 1234),\n                *[(f\"something{i}\", \"something.py\", i) for i in range(20)],\n                (\"f2\", \"f.py\", 32),\n                (\"parent\", \"fun.py\", 8),\n                (\"grandparent\", \"fun.py\", 4),\n            ],\n        ),\n    ],\n]\n\n\nclass FakeDatetime(datetime.datetime):\n    @classmethod\n    def now(cls):\n        return cls(2023, 10, 13, 12)\n\n\nclass TestGraph:\n    def test_empty(self):\n        # GIVEN\n\n        plot = MemoryGraph(max_data_points=50)\n\n        # WHEN\n\n        graph = tuple(plot.render_line(i).text for i in range(plot._height))\n\n        # THEN\n\n        assert plot._maxval == 1.0\n        assert plot._minval == 0.0\n        assert graph == (\" \" * 50, \" \" * 50, \" \" * 50, \" \" * 50)\n\n    def test_size_of_graph(self):\n        # GIVEN\n        size = 36\n        rows = 10\n\n        plot = MemoryGraph(max_data_points=size, height=rows)\n\n        # WHEN\n\n        for point in range(50):\n            plot.add_value(point)\n        graph = tuple(plot.render_line(i).text for i in range(plot._height))\n\n        # THEN\n\n        assert len(graph) == rows\n        assert all(len(line) == size for line in graph)\n\n    def test_one_point_lower_than_max(self):\n        # GIVEN\n\n        plot = MemoryGraph(max_data_points=50)\n\n        # WHEN\n\n        plot.add_value(0.5)\n        graph = tuple(plot.render_line(i).text for i in range(plot._height))\n\n        # THEN\n\n        assert plot._maxval == 1.0\n        assert plot._minval == 0.0\n        assert graph == (\n            \"                                                  \",\n            \"                                                  \",\n            \"                                                 ▐\",\n            \"                                                 ▐\",\n        )\n\n    def test_one_point_bigger_than_max(self):\n        # GIVEN\n\n        plot = MemoryGraph(max_data_points=50)\n\n        # WHEN\n\n        plot.add_value(500.0)\n        graph = tuple(plot.render_line(i).text for i in range(plot._height))\n\n        # THEN\n\n        assert plot._maxval == 500.0\n        assert plot._minval == 0\n        assert graph == (\n            \"                                                 ▐\",\n            \"                                                 ▐\",\n            \"                                                 ▐\",\n            \"                                                 ▐\",\n        )\n\n    def test_one_point_bigger_than_max_after_resize(self):\n        # GIVEN\n\n        plot = MemoryGraph(max_data_points=50)\n\n        # WHEN\n        plot.add_value(1000)\n        for _ in range(50 * 2):\n            plot.add_value(0)\n        plot.add_value(500.0)\n\n        graph = tuple(plot.render_line(i).text for i in range(plot._height))\n\n        # THEN\n\n        assert plot._maxval == 1000.0\n        assert plot._minval == 0\n        assert graph == (\n            \"                                                  \",\n            \"                                                  \",\n            \"                                                 ▐\",\n            \"                                                 ▐\",\n        )\n\n    def test_multiple_points(self):\n        # GIVEN\n\n        plot = MemoryGraph(max_data_points=50)\n        plot.add_value(100.0)\n        for _ in range(50 * 2):\n            plot.add_value(0)\n\n        # WHEN\n\n        for point in range(50):\n            plot.add_value(point)\n\n        graph = tuple(plot.render_line(i).text for i in range(plot._height))\n\n        # THEN\n\n        assert plot._maxval == 100.0\n        assert plot._minval == 0\n        assert graph == (\n            \"                                                  \",\n            \"                                                  \",\n            \"                                      ▄▄▄▄▄▄██████\",\n            \"                         ▗▄▄▄▄▄▟██████████████████\",\n        )\n\n    def test_multiple_points_scattered(self):\n        # GIVEN\n\n        plot = MemoryGraph(max_data_points=50)\n        plot.add_value(100.0)\n        for _ in range(50 * 2):\n            plot.add_value(0)\n\n        # WHEN\n        plot.add_value(100)\n        plot.add_value(15)\n        plot.add_value(30)\n        plot.add_value(75)\n\n        graph = tuple(plot.render_line(i).text for i in range(plot._height))\n\n        # THEN\n\n        assert plot._maxval == 100.0\n        assert plot._minval == 0\n\n        assert graph == (\n            \"                                                ▌ \",\n            \"                                                ▌▐\",\n            \"                                                ▌▟\",\n            \"                                                ██\",\n        )\n\n\n@pytest.mark.parametrize(\"native_traces\", [False, True])\ndef test_update_thread(native_traces):\n    \"\"\"Test that our update thread posts the expected messages to our app.\"\"\"\n    # GIVEN\n    snapshots = SHORT_SNAPSHOTS\n    reader = MockReader(snapshots, native_traces)\n    messages = []\n    all_messages_received = asyncio.Event()\n\n    class MessageInterceptingApp(MockApp):\n        def __init__(self, reader):\n            super().__init__(reader, poll_interval=0.01, disable_update_thread=False)\n\n        def on_snapshot_fetched(self, message):\n            messages.append(message)\n            if message.disconnected:\n                all_messages_received.set()\n\n    app = MessageInterceptingApp(reader)\n\n    # WHEN\n    async def run_test():\n        async with app.run_test() as pilot:\n            await all_messages_received.wait()\n            await pilot.pause()\n\n    async_run(run_test())\n\n    # THEN\n    assert len(messages) == len(snapshots)\n    for i, message in enumerate(messages):\n        last_message = i == len(messages) - 1\n        assert message.disconnected is last_message\n        assert message.snapshot.heap_size == sum(a.size for a in snapshots[i])\n        assert message.snapshot.records == snapshots[i]\n        assert message.snapshot.records_by_location == aggregate_allocations(\n            message.snapshot.records,\n            native_traces=native_traces,\n        )\n\n\n@pytest.mark.parametrize(\n    \"pid, display_val\",\n    [\n        pytest.param(999, \"PID: 999\", id=\"Known PID\"),\n        pytest.param(None, \"PID: ???\", id=\"Unknown PID\"),\n    ],\n)\ndef test_pid_display(pid, display_val):\n    # GIVEN\n    reader = MockReader([], pid=pid)\n    app = MockApp(reader)\n    labels = {}\n\n    # WHEN\n    async def run_test():\n        async with app.run_test() as pilot:\n            await pilot.pause()\n            labels.update(extract_label_text(pilot.app))\n\n    async_run(run_test())\n\n    # THEN\n    assert labels[\"pid\"].rstrip() == display_val\n\n\n@pytest.mark.parametrize(\n    \"command_line, display_val\",\n    [\n        pytest.param(\"foo bar baz\", \"CMD: foo bar baz\", id=\"Known command\"),\n        pytest.param(\n            \"/path/to/foo bar baz\",\n            \"CMD: /path/to/foo bar baz\",\n            id=\"Known command with path\",\n        ),\n        pytest.param(\n            \"/path/to/memray bar baz\",\n            \"CMD: memray bar baz\",\n            id=\"Memray script with path\",\n        ),\n        pytest.param(\n            \"/path/to/memray/__main__.py bar baz\",\n            \"CMD: memray bar baz\",\n            id=\"Memray module with path\",\n        ),\n        pytest.param(None, \"CMD: ???\", id=\"Unknown command\"),\n    ],\n)\ndef test_command_line_display(command_line, display_val):\n    # GIVEN\n    reader = MockReader([], command_line=command_line)\n    app = MockApp(reader)\n    labels = {}\n\n    # WHEN\n    async def run_test():\n        async with app.run_test() as pilot:\n            await pilot.pause()\n            labels.update(extract_label_text(pilot.app))\n\n    async_run(run_test())\n\n    # THEN\n    assert labels[\"cmd\"].rstrip() == display_val\n\n\ndef test_header_with_no_snapshots():\n    # GIVEN\n    reader = MockReader([])\n    app = MockApp(reader)\n    labels = {}\n\n    # WHEN\n    async def run_test():\n        async with app.run_test() as pilot:\n            await pilot.pause()\n            labels.update(extract_label_text(pilot.app))\n\n    async_run(run_test())\n\n    # THEN\n    assert labels[\"tid\"].split() == \"TID: *\".split()\n    assert labels[\"thread\"].split() == \"All threads\".split()\n    assert labels[\"samples\"].split() == \"Samples: 0\".split()\n\n\ndef test_header_with_empty_snapshot():\n    # GIVEN\n    reader = MockReader([])\n    app = MockApp(reader)\n    labels = {}\n\n    # WHEN\n    async def run_test():\n        async with app.run_test() as pilot:\n            app.add_mock_snapshot([])\n            await pilot.pause()\n            labels.update(extract_label_text(pilot.app))\n\n    async_run(run_test())\n\n    # THEN\n    assert labels[\"tid\"].split() == \"TID: *\".split()\n    assert labels[\"thread\"].split() == \"All threads\".split()\n    assert labels[\"samples\"].split() == \"Samples: 1\".split()\n\n\ndef test_sorting():\n    \"\"\"Test that our sort keys correctly sort the data table\"\"\"\n    # GIVEN\n    snapshot = [\n        mock_allocation(\n            size=10,\n            n_allocations=5,\n            stack=[(\"a\", \"a.py\", 1)],\n        ),\n        mock_allocation(\n            size=50,\n            n_allocations=1,\n            stack=[(\"b\", \"b.py\", 1)],\n        ),\n        mock_allocation(\n            size=100,\n            n_allocations=2,\n            stack=[(\"c\", \"c.py\", 1), (\"b\", \"b.py\", 1)],\n        ),\n        mock_allocation(\n            size=25,\n            n_allocations=4,\n            stack=[(\"d\", \"d.py\", 1)],\n        ),\n    ]\n\n    own_order = \"cbda\"\n    total_order = \"bcda\"\n    allocations_order = \"adbc\"\n\n    reader = MockReader([])\n    app = MockApp(reader)\n    order_by_key = {}\n\n    # WHEN\n    async def run_test():\n        async with app.run_test() as pilot:\n            app.add_mock_snapshot(snapshot)\n            await pilot.pause()\n\n            datatable = pilot.app.screen.query_one(DataTable)\n            function_col_key = datatable.ordered_columns[0].key\n\n            for key in (\"\", \"o\", \"a\", \"t\"):\n                await pilot.press(key)\n                order_by_key[key] = \"\".join(\n                    datatable.get_cell(row.key, function_col_key).plain\n                    for row in datatable.ordered_rows\n                )\n\n    async_run(run_test())\n\n    # THEN\n    assert order_by_key[\"\"] == total_order\n    assert order_by_key[\"o\"] == own_order\n    assert order_by_key[\"a\"] == allocations_order\n    assert order_by_key[\"t\"] == total_order\n\n\ndef test_switching_threads():\n    \"\"\"Test that we can switch which thread is displayed\"\"\"\n    # GIVEN\n    thread_names = [\"Thread A\", \"\", \"Thread C\"]\n    thread_labels = [\n        \"Thread 1 of 3 (Thread A)\",\n        \"Thread 2 of 3\",\n        \"Thread 3 of 3 (Thread C)\",\n    ]\n    snapshot = [\n        mock_allocation(\n            tid=1,\n            stack=[(\"a\", \"a.py\", 1)],\n            thread_name=thread_names[0],\n        ),\n        mock_allocation(\n            tid=2,\n            stack=[(\"b\", \"b.py\", 1)],\n            thread_name=thread_names[1],\n        ),\n        mock_allocation(\n            tid=3,\n            stack=[(\"c\", \"c.py\", 1)],\n            thread_name=thread_names[2],\n        ),\n    ]\n\n    reader = MockReader([])\n    app = MockApp(reader)\n    functions = []\n    tids = []\n    threads = []\n\n    # WHEN\n    async def run_test():\n        async with app.run_test() as pilot:\n            app.add_mock_snapshot(snapshot)\n            await pilot.pause()\n\n            datatable = pilot.app.screen.query_one(DataTable)\n\n            for key in (\"m\", \">\", \">\", \">\", \"<\", \"<\", \"<\"):\n                await pilot.press(key)\n                functions.append(datatable.get_cell_at(Coordinate(0, 0)).plain)\n                labels = extract_label_text(app)\n                tids.append(\" \".join(labels[\"tid\"].split()))\n                threads.append(\" \".join(labels[\"thread\"].split()))\n\n    async_run(run_test())\n\n    # THEN\n    order = [0, 1, 2, 0, 2, 1, 0]\n    assert functions == [\"abc\"[i] for i in order]\n    assert tids == [f\"TID: {hex(i+1)}\" for i in order]\n    assert threads == [thread_labels[i] for i in order]\n\n\ndef test_merge_mode_new_threads():\n    \"\"\"Test that the 'All threads' is still displayed when a new thread is created.\"\"\"\n    # GIVEN\n    snapshot = [\n        mock_allocation(\n            tid=1,\n            stack=[(\"a\", \"a.py\", 1)],\n        ),\n        mock_allocation(\n            tid=2,\n            stack=[(\"b\", \"b.py\", 1)],\n        ),\n        mock_allocation(\n            tid=3,\n            stack=[(\"c\", \"c.py\", 1)],\n        ),\n    ]\n    new_thread = mock_allocation(tid=4, stack=[(\"d\", \"d.py\", 1)])\n\n    reader = MockReader([])\n    app = MockApp(reader)\n    label = []\n\n    # WHEN\n    async def run_test():\n        async with app.run_test() as pilot:\n            await pilot.press(\"m\")\n            app.add_mock_snapshot(snapshot)\n            await pilot.pause()\n\n            await pilot.press(\"m\")\n            app.add_mock_snapshot(snapshot + [new_thread])\n            await pilot.pause()\n            label.append(extract_label_text(app)[\"thread\"])\n\n    async_run(run_test())\n\n    # THEN\n    assert label == [\"All threads\\n\"]\n\n\ndef test_merging_allocations_from_all_threads():\n    \"\"\"Test that we can display allocations from all threads\"\"\"\n    # GIVEN\n    snapshot = [\n        mock_allocation(\n            tid=1,\n            size=1024,\n            stack=[(\"a\", \"a.py\", 1)],\n        ),\n        mock_allocation(\n            tid=2,\n            size=2 * 1024,\n            stack=[(\"b\", \"b.py\", 1)],\n        ),\n        mock_allocation(\n            tid=3,\n            size=3 * 1024,\n            stack=[(\"c\", \"c.py\", 1)],\n        ),\n    ]\n\n    reader = MockReader([])\n    app = MockApp(reader)\n    functions = []\n    tids = []\n    threads = []\n\n    # WHEN\n    async def run_test():\n        async with app.run_test() as pilot:\n            app.add_mock_snapshot(snapshot)\n            await pilot.pause()\n\n            datatable = pilot.app.screen.query_one(DataTable)\n\n            for key in (\"m\", \">\", \"m\", \"<\", \"m\", \"<\"):\n                await pilot.press(key)\n                functions.append(datatable.get_cell_at(Coordinate(0, 0)).plain)\n                labels = extract_label_text(app)\n                tids.append(\" \".join(labels[\"tid\"].split()))\n                threads.append(\" \".join(labels[\"thread\"].split()))\n\n    async_run(run_test())\n\n    # THEN\n    order = [0, 1, 2, 2, 1, 0]\n    merged = [False, False, True, True, False, False]\n    assert functions == [\"abc\"[i] for i in order]\n    assert tids == [\n        \"TID: *\" if all else f\"TID: {hex(i+1)}\" for i, all in zip(order, merged)\n    ]\n    assert threads == [\n        \"All threads\" if all else f\"Thread {i+1} of 3\" for i, all in zip(order, merged)\n    ]\n\n\n@pytest.mark.parametrize(\n    \"terminal_size, press, snapshots\",\n    [\n        pytest.param(\n            (80, 24), [], SHORT_SNAPSHOTS, id=\"narrow-terminal-short-snapshots\"\n        ),\n        pytest.param(\n            (80, 24),\n            [\"tab\"],\n            LONG_SNAPSHOTS,\n            id=\"narrow-terminal-focus-header-long-snapshots\",\n        ),\n        pytest.param((120, 24), [], LONG_SNAPSHOTS, id=\"wide-terminal-long-snapshots\"),\n        pytest.param(\n            (200, 24), [], SHORT_SNAPSHOTS, id=\"very-wide-terminal-short-snapshots\"\n        ),\n    ],\n)\ndef test_tui_basic(terminal_size, press, snapshots, compare):\n    async def run_before(pilot) -> None:\n        pilot.app.add_mock_snapshots(snapshots)\n\n    assert compare(\n        press=press,\n        run_before=run_before,\n        terminal_size=terminal_size,\n    )\n\n\n@pytest.mark.parametrize(\n    \"terminal_size, disconnected\",\n    [\n        pytest.param((50, 24), False, id=\"narrow-terminal-connected\"),\n        pytest.param((50, 24), True, id=\"narrow-terminal-disconnected\"),\n        pytest.param((81, 24), True, id=\"wider-terminal\"),\n    ],\n)\ndef test_tui_pause(terminal_size, disconnected, compare):\n    async def run_before(pilot: Pilot) -> None:\n        app = cast(MockApp, pilot.app)\n        app.add_mock_snapshot(SHORT_SNAPSHOTS[0])\n        await pilot.pause()\n        await pilot.press(\"space\")\n        await pilot.press(\"tab\")\n        await pilot.pause()\n        app.add_mock_snapshot(SHORT_SNAPSHOTS[1], disconnected=disconnected)\n\n    assert compare(\n        run_before=run_before,\n        terminal_size=terminal_size,\n    )\n\n\ndef test_tui_gradient(compare):\n    snapshot = [\n        mock_allocation(\n            stack=[(f\"function{j}\", f\"/abc/lel_{j}.py\", i) for j in range(i, -1, -1)],\n            size=1024 + 10 * i,\n            n_allocations=1,\n        )\n        for i in range(0, 30)\n    ]\n\n    async def run_before(pilot) -> None:\n        pilot.app.add_mock_snapshots([snapshot], native=False)\n\n    assert compare(run_before=run_before, terminal_size=(125, 40), native=False)\n\n\nclass TestAggregateResults:\n    def test_simple_allocations(self):\n        # GIVEN\n        mock_allocation_records = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=10,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=2,\n                _stack=[\n                    (\"me\", \"fun.py\", 12),\n                    (\"parent\", \"fun.py\", 8),\n                    (\"grandparent\", \"fun.py\", 4),\n                ],\n            ),\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=20,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"sibling\", \"fun.py\", 16),\n                    (\"parent\", \"fun.py\", 8),\n                    (\"grandparent\", \"fun.py\", 4),\n                ],\n            ),\n        ]\n        allocation_records = cast(List[AllocationRecord], mock_allocation_records)\n\n        # WHEN\n        result = aggregate_allocations(allocation_records)\n\n        # THEN\n        grandparent = result[Location(function=\"grandparent\", file=\"fun.py\")]\n        assert grandparent.own_memory == 0\n        assert grandparent.total_memory == 30\n        assert grandparent.n_allocations == 3\n\n        me = result[Location(function=\"me\", file=\"fun.py\")]\n        assert me.own_memory == 10\n        assert me.total_memory == 10\n        assert me.n_allocations == 2\n\n        parent = result[Location(function=\"parent\", file=\"fun.py\")]\n        assert parent.own_memory == 0\n        assert parent.total_memory == 30\n        assert parent.n_allocations == 3\n\n    def test_missing_frames(self):\n        # GIVEN\n        mock_allocation_records = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=10,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=2,\n                _stack=[],\n            ),\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=20,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _stack=[\n                    (\"sibling\", \"fun.py\", 16),\n                    (\"parent\", \"fun.py\", 8),\n                    (\"grandparent\", \"fun.py\", 4),\n                ],\n            ),\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=30,\n                allocator=AllocatorType.MALLOC,\n                stack_id=2,\n                n_allocations=1,\n                _stack=[],\n            ),\n        ]\n        allocation_records = cast(List[AllocationRecord], mock_allocation_records)\n\n        # WHEN\n        result = aggregate_allocations(allocation_records)\n\n        # THEN\n        grandparent = result[Location(function=\"grandparent\", file=\"fun.py\")]\n        assert grandparent.own_memory == 0\n        assert grandparent.total_memory == 20\n        assert grandparent.n_allocations == 1\n\n        me = result[Location(function=\"???\", file=\"???\")]\n        assert me.own_memory == 40\n        assert me.total_memory == 40\n        assert me.n_allocations == 3\n\n    def test_native_frames(self):\n        # GIVEN\n        mock_allocation_records = [\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=10,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=2,\n                _stack=[],\n                _hybrid_stack=[],\n            ),\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=20,\n                allocator=AllocatorType.MALLOC,\n                stack_id=1,\n                n_allocations=1,\n                _hybrid_stack=[\n                    (\"sibling\", \"fun.c\", 16),\n                    (\"parent\", \"fun.py\", 8),\n                    (\"grandparent\", \"fun.py\", 4),\n                ],\n            ),\n            MockAllocationRecord(\n                tid=1,\n                address=0x1000000,\n                size=30,\n                allocator=AllocatorType.MALLOC,\n                stack_id=2,\n                n_allocations=1,\n                _hybrid_stack=[],\n            ),\n        ]\n        allocation_records = cast(List[AllocationRecord], mock_allocation_records)\n\n        # WHEN\n        result = aggregate_allocations(allocation_records, native_traces=True)\n\n        # THEN\n        grandparent = result[Location(function=\"grandparent\", file=\"fun.py\")]\n        assert grandparent.own_memory == 0\n        assert grandparent.total_memory == 20\n        assert grandparent.n_allocations == 1\n\n        me = result[Location(function=\"???\", file=\"???\")]\n        assert me.own_memory == 40\n        assert me.total_memory == 40\n        assert me.n_allocations == 3\n\n\ndef test_merge_threads(compare):\n    async def run_before(pilot: Pilot) -> None:\n        snapshot = [\n            mock_allocation(\n                tid=1,\n                stack=[(\"a\", \"a.py\", 1)],\n            ),\n            mock_allocation(\n                tid=2,\n                stack=[(\"b\", \"b.py\", 1)],\n            ),\n            mock_allocation(\n                tid=3,\n                stack=[(\"c\", \"c.py\", 1)],\n            ),\n        ]\n        app = cast(MockApp, pilot.app)\n        await pilot.press(\"m\")\n        app.add_mock_snapshot(snapshot)\n        await pilot.pause()\n        await pilot.press(\"m\")\n        await pilot.pause()\n        app.add_mock_snapshot(snapshot)\n\n    assert compare(\n        run_before=run_before,\n        terminal_size=(150, 24),\n    )\n\n\ndef test_unmerge_threads(compare):\n    async def run_before(pilot: Pilot) -> None:\n        snapshot = [\n            mock_allocation(\n                tid=1,\n                stack=[(\"a\", \"a.py\", 1)],\n            ),\n            mock_allocation(\n                tid=2,\n                stack=[(\"b\", \"b.py\", 1)],\n            ),\n            mock_allocation(\n                tid=3,\n                stack=[(\"c\", \"c.py\", 1)],\n            ),\n        ]\n        app = cast(MockApp, pilot.app)\n        app.add_mock_snapshot(snapshot)\n        await pilot.press(\"m\")\n        await pilot.pause()\n        await pilot.press(\">\")\n        await pilot.press(\"m\")\n        await pilot.press(\">\")\n        await pilot.press(\"m\")\n        await pilot.pause()\n        app.add_mock_snapshot(snapshot)\n\n    assert compare(\n        run_before=run_before,\n        terminal_size=(150, 24),\n    )\n"
  },
  {
    "path": "tests/utils.py",
    "content": "\"\"\"Utilities / Helpers for writing tests.\"\"\"\nimport asyncio\nimport sys\nfrom contextlib import contextmanager\nfrom dataclasses import dataclass\nfrom typing import List\nfrom typing import Optional\nfrom typing import Tuple\n\nimport pytest\n\nfrom memray import AllocatorType\n\n\ndef filter_relevant_allocations(records, ranged=False):\n    addresses = set()\n    filter_allocations = [AllocatorType.VALLOC]\n    filter_deallocations = [AllocatorType.FREE]\n    if ranged:\n        filter_allocations.append(AllocatorType.MMAP)\n        filter_deallocations.append(AllocatorType.MUNMAP)\n    for record in records:\n        if record.allocator in filter_allocations:\n            yield record\n            addresses.add(record.address)\n        elif record.allocator in filter_deallocations:\n            if record.address in addresses:\n                yield record\n            addresses.discard(record.address)\n\n\ndef filter_relevant_pymalloc_allocations(records, size):\n    addresses = set()\n    filter_allocations = [\n        AllocatorType.PYMALLOC_MALLOC,\n        AllocatorType.PYMALLOC_REALLOC,\n        AllocatorType.PYMALLOC_CALLOC,\n    ]\n    filter_deallocations = [AllocatorType.PYMALLOC_FREE]\n    for record in records:\n        if record.allocator in filter_allocations and record.size == size:\n            yield record\n            addresses.add(record.address)\n        elif record.allocator in filter_deallocations:\n            if record.address in addresses:\n                yield record\n            addresses.discard(record.address)\n\n\nskip_if_macos = pytest.mark.skipif(\n    sys.platform == \"darwin\", reason=\"does not run on macOS\"\n)\n\n\n@dataclass\nclass MockAllocationRecord:\n    \"\"\"Mimics :py:class:`memray._memray.AllocationRecord`.\"\"\"\n\n    tid: int\n    address: int\n    size: int\n    allocator: AllocatorType\n    stack_id: int\n    n_allocations: int\n    _stack: Optional[List[Tuple[str, str, int]]] = None\n    _hybrid_stack: Optional[List[Tuple[str, str, int]]] = None\n    thread_name: str = \"\"\n\n    @staticmethod\n    def __get_stack_trace(stack, max_stacks):\n        if max_stacks == 0:\n            return stack\n        else:\n            return stack[:max_stacks]\n\n    def stack_trace(self, max_stacks=0):\n        if self._stack is None:\n            raise AssertionError(\"did not expect a call to `stack_trace`\")\n        return self.__get_stack_trace(self._stack, max_stacks)\n\n    def hybrid_stack_trace(self, max_stacks=0):\n        if self._hybrid_stack is None:\n            raise AssertionError(\"did not expect a call to `hybrid_stack_trace`\")\n        return self.__get_stack_trace(self._hybrid_stack, max_stacks)\n\n\n@contextmanager\ndef run_without_tracer():\n    \"\"\"Fixture to run a test without custom tracer or profiling.\"\"\"\n    prev_trace = sys.gettrace()\n    prev_profile = sys.getprofile()\n    sys.settrace(None)\n    sys.setprofile(None)\n    try:\n        yield\n    finally:\n        sys.settrace(prev_trace)\n        sys.setprofile(prev_profile)\n\n\ndef async_run(coro):\n    # This technique shamelessly cribbed from Textual itself...\n    # `asyncio.get_event_loop()` is deprecated since Python 3.10:\n    asyncio_get_event_loop_is_deprecated = sys.version_info >= (3, 10, 0)\n\n    if asyncio_get_event_loop_is_deprecated:\n        # N.B. This doesn't work with Python<3.10, as we end up with 2 event loops:\n        return asyncio.run(coro)\n    else:\n        # pragma: no cover\n        # However, this works with Python<3.10:\n        event_loop = asyncio.get_event_loop()\n        return event_loop.run_until_complete(coro)\n"
  },
  {
    "path": "valgrind.supp",
    "content": "{\n   <binary_write_warning>\n   Memcheck:Param\n   write(buf)\n   fun:write\n   ...\n}\n{\n   <binary_write_warning>\n   Memcheck:Param\n   write(buf)\n   fun:__write_nocancel\n   ...\n}\n\n# Any problems in Py_Initialize are before the Memray module has even\n# been imported, and so aren't something we need to think about.\n{\n   <invalid_read_in_py_initialize>\n   Memcheck:Addr32\n   ...\n   fun:Py_Initialize*\n   ...\n}\n{\n   <jump_depending_on_uninitialized_memory_in_py_initialize>\n   Memcheck:Cond\n   ...\n   fun:Py_Initialize*\n   ...\n}\n\n# Valgrind is now reporting leaks in the `readline` module, but\n# these are certainly not relevant to Memray.\n{\n   <ignore_leaks_in_readline_module>\n   Memcheck:Leak\n   match-leak-kinds: definite\n   ...\n   fun:PyInit_readline\n   ...\n}\n\n# CPython does not deallocate multitude of immortal objects\n# and this confuses valgrind. For this, we want to suppress\n# all traces that are not 'definite lost' that originated from\n# raw malloc/calloc/realloc.\n\n{\n   <cpython_possible_leaks_with_malloc>\n   Memcheck:Leak\n   match-leak-kinds: possible\n   fun:malloc\n   ...\n}\n{\n   <cpython_possible_leaks_with_realloc>\n   Memcheck:Leak\n   match-leak-kinds: possible\n   fun:realloc\n   ...\n}\n{\n   <cpython_possible_leaks_with_realloc>\n   Memcheck:Leak\n   match-leak-kinds: possible\n   fun:calloc\n   ...\n}\n{\n   <initialize_interpreter>\n   Memcheck:Leak\n   match-leak-kinds: definite\n   ...\n   fun:*pycore_interp_init*\n   ...\n}\n{\n   <marshall_cached_objects>\n   Memcheck:Leak\n   match-leak-kinds: definite\n   ...\n   fun:marshal_loads\n   ...\n}\n{\n   <cpython_unicode_false_branch_warning>\n   Memcheck:Cond\n   fun:PyUnicode_Decode\n   ...\n}\n\n# Cpython cached objects\n\n{\n   <cached_code_object>\n   Memcheck:Leak\n   match-leak-kinds: definite\n   ...\n   fun:PyEval_EvalCodeEx\n   ...\n   fun:*memray*Tracker___cinit__\n   ...\n}\n\n{\n   <cached_code_key>\n   Memcheck:Leak\n   match-leak-kinds: definite\n   ...\n   fun:_PyCode_ConstantKey\n   ...\n   fun:_PyAST_Compile\n   ...\n}\n\n\n# Cython cache\n\n{\n   <cython_cached_constants>\n   Memcheck:Leak\n   ...\n   fun:*__Pyx_InitCachedConstants*\n   ...\n}\n\n# Tls variables\n\n{\n  dtv-addr-tail\n  Memcheck:Leak\n  match-leak-kinds: possible,reachable\n  fun:*\n  fun:tls_get_addr_tail*\n  fun:__tls_get_addr\n}\n{\n  dtv-addr-resize\n  Memcheck:Leak\n  match-leak-kinds: possible,reachable\n  fun:*\n  fun:_dl_resize_dtv\n  fun:_dl_update_slotinfo\n  fun:update_get_addr\n  fun:__tls_get_addr\n}\n{\n  dtv-addr-init\n  Memcheck:Leak\n  match-leak-kinds: possible,reachable\n  fun:*\n  fun:allocate_dtv_entry\n  fun:allocate_and_init\n  fun:tls_get_addr_tail*\n  fun:__tls_get_addr\n}\n\n# Atomics\n\n{\n   <tracker_atomic_load>\n   Helgrind:Race\n   fun:load\n   fun:operator bool\n   fun:*Tracker*trackDeallocation*\n   ...\n}\n{\n   <tracker_track_deallocation>\n   Helgrind:Race\n   ...\n   fun:*Tracker*trackDeallocation*\n   ...\n   fun:__libc_thread_freeres\n   ...\n}\n{\n   <background_thread_recursion_guard_destruction>\n   Helgrind:Race\n   fun:operator()\n   fun:*Tracker*BackgroundThread*\n   ...\n}\n{\n   <background_thread_stop_lock_destruction>\n   Helgrind:UnlockForeign\n   ...\n   fun:~scoped_lock\n   fun:*BackgroundThread*stop*\n   ...\n}\n{\n   <background_thread_condition_var>\n   Helgrind:Race\n   fun:*BackgroundThread*stop*\n   ...\n}\n{\n   <insert_a_suppression_name_here>\n   Helgrind:Misc\n   ...\n   fun:*BackgroundThread*stop*\n   ...\n}\n{\n   <tracker_atomic_load>\n   Helgrind:Race\n   fun:load\n   fun:operator bool\n   ...\n   fun:__libc_thread_freeres\n   fun:start_thread\n   obj:*\n}\n{\n   <tracker_atomic_store>\n   Helgrind:Race\n   fun:store\n   fun:operator=\n   fun:operator=\n   fun:*TrackerD1Ev\n   ...\n}\n{\n   <tracker_atomic_store>\n   Helgrind:Race\n   fun:store\n   fun:operator=\n   fun:operator=\n   ...\n   fun:__pyx_*Tracker*__enter__\n   ...\n}\n{\n   <socket_atomic_store>\n   Helgrind:Race\n   fun:store\n   fun:operator=\n   fun:operator=\n   ...\n   fun:*memray*BackgroundSocketReaderD1Ev*\n   ...\n}\n{\n   <socket_atomic_load>\n   Helgrind:Race\n   fun:load\n   fun:operator bool\n   fun:*memray*BackgroundSocketReade*backgroundThreadWorkerEv*\n}\n{\n   <socket_source_atomic_load>\n   Helgrind:Race\n   fun:load\n   fun:operator bool\n   fun:*SocketSource*\n   ...\n}\n{\n   <socket_source_atomic_store>\n   Helgrind:Race\n   fun:store\n   fun:operator=\n   fun:operator=\n   fun:_close\n   fun:*memray*SocketSource*close*\n   ...\n}\n{\n   <socket_buffer_atomic_load>\n   Helgrind:Race\n   fun:load\n   fun:operator bool\n   fun:*memray*SocketBuf*underflowEv\n   ...\n}\n\n# Condition variables\n\n{\n   <condition_variable_wait>\n   Helgrind:Misc\n   ...\n   fun:*pthread_cond_*wait*\n}\n{\n   <condition_variable_notify>\n   Helgrind:Misc\n   ...\n   fun:*condition_variable*notify*\n}\n{\n   <condition_variable_wait_until>\n   Helgrind:Race\n   fun:wait_until*\n   fun:wait_for*\n   ...\n}\n\n{\n   <insert_a_suppression_name_here>\n   Helgrind:Race\n   fun:*Tracker*BackgroundThread*start*\n   ...\n   fun:start_thread\n   fun:clone\n}\n\n# Python GIL false positives\n\n{\n   <take_gil>\n   Helgrind:Race\n   ...\n   fun:take_gil*\n   ...\n}\n{\n   <drop_gil>\n   Helgrind:Race\n   ...\n   fun:drop_gil\n   ...\n}\n{\n   <interpreter_thread_management>\n   Helgrind:Race\n   fun:*PyEval_EvalFrame*\n   ...\n}\n{\n   <interpreter_thread_management>\n   Helgrind:Race\n   fun:eval_frame_handle_pending\n   fun:*PyEval_EvalFrame*\n   ...\n}\n{\n   <interpreter_thread_management>\n   Helgrind:Race\n   fun:store\n   fun:operator=\n   fun:operator=\n   fun:deactivate\n   ...\n}\n\n# Helgrind false positives\n\n# Helgrind warns if a condition variable is signalled while the lock is not\n# held, but pthreads explicitly allow this case. Memray is doing this when\n# stopping the background thread that collects RSS info, and CPython does this\n# for the GIL.\n{\n   <signalling_cond_var_with_mutex_unlocked>\n   Helgrind:Dubious\n   ...\n   obj:*\n}\n\n# libunwind\n\n# `validate_mem` checks whether a memory region is both mapped and readable. It\n# uses `mincore` to ensure the relevant pages are mapped, and then reads from\n# them using `write` (which reads from a user-supplied buf). It ignores the\n# bytes that are read, and just wants to see if there's an EFAULT when reading.\n# This could happen after an `mprotect` with PROT_NONE, for instance.\n{\n   <libunwind_validate_mem>\n   Memcheck:Param\n   write(buf)\n   ...\n   fun:validate_mem\n}\n{\n   <libunwind_backtrace>\n   Memcheck:Param\n   write(buf)\n   ...\n   fun:backtrace\n   fun:fill\n   ...\n}\n{\n   <libunwind_backtrace_msync>\n   Memcheck:Param\n   msync(start)\n   ...\n   fun:backtrace\n   fun:fill\n   ...\n}\n{\n   <insert_a_suppression_name_here>\n   Memcheck:Cond\n   ...\n   fun:backtrace\n   fun:fill\n   ...\n}\n\n# libc\n\n{\n   <dlopen_is_drunk_go_home>\n   Memcheck:Leak\n   match-leak-kinds: definite\n   fun:malloc\n   ...\n   fun:_dl_catch_exception\n   ...\n   fun:_dl_open\n   ...\n}\n\n{\n   <dlopen_is_drunk_go_home_now_with_calloc>\n   Memcheck:Leak\n   match-leak-kinds: definite\n   fun:calloc\n   ...\n   fun:_dl_catch_exception\n   ...\n   fun:_dl_open\n   ...\n}\n\n\n{\n   <dlopen_mutex_invalid_argument>\n   Helgrind:Misc\n   ...\n   fun:_dl_fini\n   fun:__run_exit_handlers\n   ...\n}\n"
  },
  {
    "path": "webpack.config.js",
    "content": "const path = require(\"path\");\nconst TerserPlugin = require(\"terser-webpack-plugin\");\nconst CopyWebpackPlugin = require(\"copy-webpack-plugin\");\n\nmodule.exports = {\n  mode: \"production\",\n  entry: {\n    flamegraph_common: \"./src/memray/reporters/assets/flamegraph_common.js\",\n    flamegraph: \"./src/memray/reporters/assets/flamegraph.js\",\n    temporal_flamegraph: \"./src/memray/reporters/assets/temporal_flamegraph.js\",\n    table: \"./src/memray/reporters/assets/table.js\",\n  },\n  output: {\n    path: path.resolve(\"src/memray/reporters/templates/assets\"),\n    filename: \"[name].js\",\n  },\n  externals: {\n    _: \"lodash\",\n  },\n  optimization: {\n    minimize: true,\n    minimizer: [\n      new TerserPlugin({\n        extractComments: false,\n      }),\n    ],\n  },\n  plugins: [\n    new CopyWebpackPlugin({\n      patterns: [\n        {\n          from: \"node_modules/bootstrap/dist/css/bootstrap.min.css\",\n          to: \"vendor/bootstrap.min.css\",\n        },\n        {\n          from: \"node_modules/jquery/dist/jquery.min.js\",\n          to: \"vendor/jquery.min.js\",\n        },\n        {\n          from: \"node_modules/popper.js/dist/umd/popper.min.js\",\n          to: \"vendor/popper.min.js\",\n        },\n        {\n          from: \"node_modules/bootstrap/dist/js/bootstrap.min.js\",\n          to: \"vendor/bootstrap.min.js\",\n        },\n        {\n          from: \"node_modules/lodash/lodash.min.js\",\n          to: \"vendor/lodash.min.js\",\n        },\n        {\n          from: \"node_modules/plotly.js-dist-min/plotly.min.js\",\n          to: \"vendor/plotly.min.js\",\n        },\n        {\n          from: \"node_modules/d3/dist/d3.min.js\",\n          to: \"vendor/d3.min.js\",\n        },\n        {\n          from: \"node_modules/d3-scale-chromatic/dist/d3-scale-chromatic.min.js\",\n          to: \"vendor/d3-scale-chromatic.min.js\",\n        },\n        {\n          from: \"node_modules/d3-flame-graph/dist/d3-flamegraph.min.js\",\n          to: \"vendor/d3-flamegraph.min.js\",\n        },\n        {\n          from: \"node_modules/datatables.net/js/jquery.dataTables.min.js\",\n          to: \"vendor/jquery.dataTables.min.js\",\n        },\n        {\n          from: \"node_modules/datatables.net-bs4/js/dataTables.bootstrap4.min.js\",\n          to: \"vendor/dataTables.bootstrap4.min.js\",\n        },\n      ],\n    }),\n  ],\n};\n"
  }
]