diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 326e8a2873..33082b8bc7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -120,16 +120,16 @@ jobs: uses: actions/cache@v1 with: path: thirdparty - key: ci-cmake-${{ runner.OS }}-thirdparty-v1.10.13-r1 + key: ci-cmake-${{ runner.OS }}-thirdparty-v1.10.14-r1 - name: Install dependencies (Windows) if: runner.os == 'Windows' shell: powershell run: | if (!(Test-Path thirdparty/win-libs-vc14-x64)) { $wc = New-Object System.Net.WebClient - $wc.DownloadFile("https://www.panda3d.org/download/panda3d-1.10.13/panda3d-1.10.13-tools-win64.zip", "thirdparty-tools.zip") + $wc.DownloadFile("https://www.panda3d.org/download/panda3d-1.10.14/panda3d-1.10.14-tools-win64.zip", "thirdparty-tools.zip") Expand-Archive -Path thirdparty-tools.zip - Move-Item -Path thirdparty-tools/panda3d-1.10.13/thirdparty -Destination . + Move-Item -Path thirdparty-tools/panda3d-1.10.14/thirdparty -Destination . } - name: ccache (non-Windows) @@ -308,6 +308,38 @@ jobs: $PYTHON_EXECUTABLE -m pytest ../tests --cov=. # END B + - name: Setup Python (Python 3.12) + if: contains(matrix.python, 'YES') + uses: actions/setup-python@v4 + with: + python-version: '3.12' + - name: Configure (Python 3.12) + if: contains(matrix.python, 'YES') + working-directory: build + shell: bash + run: > + cmake -DWANT_PYTHON_VERSION=3.12 -DHAVE_PYTHON=YES + -DPython_FIND_REGISTRY=NEVER -DPython_ROOT="$pythonLocation" . + - name: Build (Python 3.12) + if: contains(matrix.python, 'YES') + # BEGIN A + working-directory: build + run: cmake --build . --config ${{ matrix.config }} --parallel 4 + # END A + - name: Test (Python 3.12) + # BEGIN B + if: contains(matrix.python, 'YES') + working-directory: build + shell: bash + env: + PYTHONPATH: ${{ matrix.config }} + run: | + PYTHON_EXECUTABLE=$(grep 'Python_EXECUTABLE:' CMakeCache.txt | sed 's/.*=//') + $PYTHON_EXECUTABLE -m pip install -r ../requirements-test.txt + export COVERAGE_FILE=.coverage.$RANDOM LLVM_PROFILE_FILE=$PWD/pid-%p.profraw + $PYTHON_EXECUTABLE -m pytest ../tests --cov=. + # END B + - name: Upload coverage reports if: always() && matrix.config == 'Coverage' working-directory: build @@ -343,9 +375,9 @@ jobs: shell: powershell run: | $wc = New-Object System.Net.WebClient - $wc.DownloadFile("https://www.panda3d.org/download/panda3d-1.10.13/panda3d-1.10.13-tools-win64.zip", "thirdparty-tools.zip") + $wc.DownloadFile("https://www.panda3d.org/download/panda3d-1.10.14/panda3d-1.10.14-tools-win64.zip", "thirdparty-tools.zip") Expand-Archive -Path thirdparty-tools.zip - Move-Item -Path thirdparty-tools/panda3d-1.10.13/thirdparty -Destination . + Move-Item -Path thirdparty-tools/panda3d-1.10.14/thirdparty -Destination . - name: Get thirdparty packages (macOS) if: runner.os == 'macOS' run: | @@ -356,21 +388,18 @@ jobs: (cd thirdparty/darwin-libs-a && rm -rf rocket) - name: Set up Python 3.12 - if: matrix.os != 'windows-2019' uses: actions/setup-python@v4 with: python-version: '3.12' - name: Build Python 3.12 - if: matrix.os != 'windows-2019' shell: bash run: | python makepanda/makepanda.py --git-commit=${{github.sha}} --outputdir=built --everything --no-eigen --python-incdir="$pythonLocation/include" --python-libdir="$pythonLocation/lib" --verbose --threads=4 --windows-sdk=10 - name: Test Python 3.12 - if: matrix.os != 'windows-2019' shell: bash run: | python -m pip install -r requirements-test.txt - PYTHONPATH=built LD_LIBRARY_PATH=built/lib DYLD_LIBRARY_PATH=built/lib python -m pytest + PYTHONPATH=built LD_LIBRARY_PATH=built/lib:$pythonLocation/lib DYLD_LIBRARY_PATH=built/lib python -m pytest - name: Set up Python 3.11 uses: actions/setup-python@v4 @@ -384,7 +413,7 @@ jobs: shell: bash run: | python -m pip install -r requirements-test.txt - PYTHONPATH=built LD_LIBRARY_PATH=built/lib DYLD_LIBRARY_PATH=built/lib python -m pytest + PYTHONPATH=built LD_LIBRARY_PATH=built/lib:$pythonLocation/lib DYLD_LIBRARY_PATH=built/lib python -m pytest - name: Set up Python 3.10 uses: actions/setup-python@v4 @@ -398,7 +427,7 @@ jobs: shell: bash run: | python -m pip install -r requirements-test.txt - PYTHONPATH=built LD_LIBRARY_PATH=built/lib DYLD_LIBRARY_PATH=built/lib python -m pytest + PYTHONPATH=built LD_LIBRARY_PATH=built/lib:$pythonLocation/lib DYLD_LIBRARY_PATH=built/lib python -m pytest - name: Set up Python 3.9 uses: actions/setup-python@v4 @@ -412,7 +441,7 @@ jobs: shell: bash run: | python -m pip install -r requirements-test.txt - PYTHONPATH=built LD_LIBRARY_PATH=built/lib DYLD_LIBRARY_PATH=built/lib python -m pytest + PYTHONPATH=built LD_LIBRARY_PATH=built/lib:$pythonLocation/lib DYLD_LIBRARY_PATH=built/lib python -m pytest - name: Set up Python 3.8 uses: actions/setup-python@v4 @@ -426,8 +455,38 @@ jobs: shell: bash run: | python -m pip install -r requirements-test.txt - PYTHONPATH=built LD_LIBRARY_PATH=built/lib DYLD_LIBRARY_PATH=built/lib python -m pytest + PYTHONPATH=built LD_LIBRARY_PATH=built/lib:$pythonLocation/lib DYLD_LIBRARY_PATH=built/lib python -m pytest - name: Make installer run: | python makepanda/makepackage.py --verbose --lzma + + emscripten: + if: "!contains(github.event.head_commit.message, '[skip ci]') && !contains(github.event.head_commit.message, '[ci skip]')" + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v1 + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install build-essential ninja-build bison flex + + - name: Build Host Interrogate + shell: bash + run: | + mkdir -p host-build + cmake -S . -B host-build -DBUILD_DIRECT=OFF -DBUILD_PANDA=OFF -DBUILD_PANDATOOL=OFF -DBUILD_CONTRIB=OFF -DBUILD_DTOOL=ON -DBUILD_MODELS=OFF -DBUILD_SHARED_LIBS=OFF -DINTERROGATE_PYTHON_INTERFACE=OFF + cmake --build host-build --config Standard --parallel 4 + echo host-build/bin >> $GITHUB_PATH + + - name: Setup emsdk + uses: mymindstorm/setup-emsdk@v14 + with: + version: 3.1.51 + actions-cache-folder: 'emsdk-cache' + + - name: Build for Emscripten + shell: bash + run: | + python3 makepanda/makepanda.py --git-commit=${{github.sha}} --target emscripten --outputdir=built --everything --no-python --verbose --threads=4 diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml deleted file mode 100644 index c612c782f3..0000000000 --- a/.github/workflows/lint.yml +++ /dev/null @@ -1,39 +0,0 @@ -name: Lint -on: [pull_request] - -jobs: - clang-tidy: - runs-on: ubuntu-20.04 - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 2 - - name: Install clang-tidy - run: | - sudo apt-get update - sudo apt-get install -y clang-tidy build-essential pkg-config libpng-dev libjpeg-dev libtiff-dev zlib1g-dev libssl-dev libx11-dev libgl1-mesa-dev libxrandr-dev libxxf86dga-dev libxcursor-dev libfreetype6-dev libvorbis-dev libeigen3-dev libopenal-dev libode-dev libbullet-dev libgtk-3-dev libassimp-dev libopenexr-dev - - name: Prepare compile_commands.json - run: | - cmake -B build -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_UNITY_BUILD=OFF -DHAVE_PYTHON=OFF -DINTERROGATE_PYTHON_INTERFACE=OFF - - name: Copy prebuilt files - run: | - for fn in **/*.prebuilt; do - echo mkdir -p $(dirname "cmake/$fn"); - echo cp "$fn" "cmake/${fn%.*}"; - done - - name: Create results directory - run: | - mkdir clang-tidy-result - - name: Analyze - run: | - git diff -U0 HEAD^ | clang-tidy-diff -p1 -path build -export-fixes clang-tidy-result/fixes.yml - - name: Save PR metadata - run: | - echo ${{ github.event.number }} > clang-tidy-result/pr-id.txt - echo ${{ github.event.pull_request.head.repo.full_name }} > clang-tidy-result/pr-head-repo.txt - echo ${{ github.event.pull_request.head.ref }} > clang-tidy-result/pr-head-ref.txt - - name: Upload results - uses: actions/upload-artifact@v2 - with: - name: clang-tidy-result - path: clang-tidy-result/ diff --git a/.github/workflows/review.yml b/.github/workflows/review.yml deleted file mode 100644 index 512faa51d6..0000000000 --- a/.github/workflows/review.yml +++ /dev/null @@ -1,77 +0,0 @@ -name: Post PR Review - -on: - workflow_run: - workflows: ["Lint"] - types: [completed] - -jobs: - clang-tidy-results: - # Trigger the job only if the previous (insecure) workflow completed successfully - if: ${{ github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.conclusion == 'success' }} - runs-on: ubuntu-20.04 - steps: - - name: Download analysis results - uses: actions/github-script@v3.1.0 - with: - script: | - let artifacts = await github.actions.listWorkflowRunArtifacts({ - owner: context.repo.owner, - repo: context.repo.repo, - run_id: ${{ github.event.workflow_run.id }}, - }); - let matchArtifact = artifacts.data.artifacts.filter((artifact) => { - return artifact.name == "clang-tidy-result" - })[0]; - let download = await github.actions.downloadArtifact({ - owner: context.repo.owner, - repo: context.repo.repo, - artifact_id: matchArtifact.id, - archive_format: "zip", - }); - let fs = require("fs"); - fs.writeFileSync("${{github.workspace}}/clang-tidy-result.zip", Buffer.from(download.data)); - - name: Set environment variables - run: | - mkdir clang-tidy-result - unzip clang-tidy-result.zip -d clang-tidy-result - echo "pr_id=$(cat clang-tidy-result/pr-id.txt)" >> $GITHUB_ENV - echo "pr_head_repo=$(cat clang-tidy-result/pr-head-repo.txt)" >> $GITHUB_ENV - echo "pr_head_ref=$(cat clang-tidy-result/pr-head-ref.txt)" >> $GITHUB_ENV - - uses: actions/checkout@v2 - with: - repository: ${{ env.pr_head_repo }} - ref: ${{ env.pr_head_ref }} - persist-credentials: false - - name: Redownload analysis results - uses: actions/github-script@v3.1.0 - with: - script: | - let artifacts = await github.actions.listWorkflowRunArtifacts({ - owner: context.repo.owner, - repo: context.repo.repo, - run_id: ${{github.event.workflow_run.id}}, - }); - let matchArtifact = artifacts.data.artifacts.filter((artifact) => { - return artifact.name == "clang-tidy-result" - })[0]; - let download = await github.actions.downloadArtifact({ - owner: context.repo.owner, - repo: context.repo.repo, - artifact_id: matchArtifact.id, - archive_format: "zip", - }); - let fs = require("fs"); - fs.writeFileSync("${{github.workspace}}/clang-tidy-result.zip", Buffer.from(download.data)); - - name: Extract analysis results - run: | - mkdir clang-tidy-result - unzip clang-tidy-result.zip -d clang-tidy-result - - name: Run clang-tidy-pr-comments action - uses: platisd/clang-tidy-pr-comments@master - with: - github_token: ${{ github.token }} - clang_tidy_fixes: clang-tidy-result/fixes.yml - pull_request_id: ${{ env.pr_id }} - request_changes: true - suggestions_per_comment: 10 diff --git a/README.md b/README.md index 2d9a2f4519..d6468943c6 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ Installing Panda3D ================== The latest Panda3D SDK can be downloaded from -[this page](https://www.panda3d.org/download/sdk-1-10-13/). +[this page](https://www.panda3d.org/download/sdk-1-10-14/). If you are familiar with installing Python packages, you can use the following command: @@ -64,8 +64,8 @@ depending on whether you are on a 32-bit or 64-bit system, or you can [click here](https://github.com/rdb/panda3d-thirdparty) for instructions on building them from source. -- https://www.panda3d.org/download/panda3d-1.10.13/panda3d-1.10.13-tools-win64.zip -- https://www.panda3d.org/download/panda3d-1.10.13/panda3d-1.10.13-tools-win32.zip +- https://www.panda3d.org/download/panda3d-1.10.14/panda3d-1.10.14-tools-win64.zip +- https://www.panda3d.org/download/panda3d-1.10.14/panda3d-1.10.14-tools-win32.zip After acquiring these dependencies, you can build Panda3D from the command prompt using the following command. Change the `--msvc-version` option based diff --git a/cmake/install/Panda3DConfig.cmake b/cmake/install/Panda3DConfig.cmake index b062bcb175..ad39f864cd 100644 --- a/cmake/install/Panda3DConfig.cmake +++ b/cmake/install/Panda3DConfig.cmake @@ -103,6 +103,11 @@ # Panda3D::OpenGLES2::pandagles2 # # +# TinyDisplay - Support for software rendering. +# +# Panda3D::TinyDisplay::p3tinydisplay +# +# # Vision - Support for vision processing. # # Panda3D::Vision::p3vision @@ -126,7 +131,7 @@ set(_panda_components Bullet ODE FFmpeg OpenAL FMOD - OpenGL DX9 OpenGLES1 OpenGLES2 + OpenGL DX9 OpenGLES1 OpenGLES2 TinyDisplay Vision VRPN ) diff --git a/cmake/macros/Interrogate.cmake b/cmake/macros/Interrogate.cmake index eb441e4b13..eea12f9568 100644 --- a/cmake/macros/Interrogate.cmake +++ b/cmake/macros/Interrogate.cmake @@ -341,10 +341,15 @@ function(add_python_module module) # Keep command lines short file(RELATIVE_PATH workdir_rel "${CMAKE_CURRENT_BINARY_DIR}" "${workdir_abs}") + get_target_property(target_module "${target}" IGATE_MODULE) + if(NOT target_module) + set(target_module "${module}") + endif() + interrogate_sources(${target} "${workdir_abs}/${target}_igate.cxx" "${workdir_abs}/${target}.in" - "-python-native;-module;${module}") + "-python-native;-module;${target_module}") get_target_property(target_extensions "${target}" IGATE_EXTENSIONS) list(APPEND infiles_rel "${workdir_rel}/${target}.in") @@ -359,7 +364,7 @@ function(add_python_module module) make_directory "${CMAKE_CURRENT_BINARY_DIR}/${PANDA_CFG_INTDIR}" COMMAND host_interrogate_module -oc "${CMAKE_CURRENT_BINARY_DIR}/${PANDA_CFG_INTDIR}/${module}_module.cxx" - -module ${modname} -library ${modname} + -module ${module} -library ${modname} ${import_flags} ${INTERROGATE_MODULE_OPTIONS} ${IMOD_FLAGS} ${infiles_rel} diff --git a/contrib/src/sceneeditor/seCameraControl.py b/contrib/src/sceneeditor/seCameraControl.py index 17bcedaf36..df49f7453c 100644 --- a/contrib/src/sceneeditor/seCameraControl.py +++ b/contrib/src/sceneeditor/seCameraControl.py @@ -281,10 +281,7 @@ class DirectCameraControl(DirectObject): angle = getCrankAngle(state.coaCenter) deltaAngle = angle - state.lastAngle state.lastAngle = angle - if base.config.GetBool('temp-hpr-fix',0): - self.camManipRef.setHpr(self.camManipRef, 0, 0, deltaAngle) - else: - self.camManipRef.setHpr(self.camManipRef, 0, 0, -deltaAngle) + self.camManipRef.setHpr(self.camManipRef, 0, 0, deltaAngle) SEditor.camera.setTransform(self.camManipRef, wrt) return Task.cont diff --git a/contrib/src/sceneeditor/seManipulation.py b/contrib/src/sceneeditor/seManipulation.py index a20a323749..c801ec66e5 100644 --- a/contrib/src/sceneeditor/seManipulation.py +++ b/contrib/src/sceneeditor/seManipulation.py @@ -324,10 +324,7 @@ class DirectManipulationControl(DirectObject): if self.rotateAxis == 'x': SEditor.widget.setP(SEditor.widget, deltaAngle) elif self.rotateAxis == 'y': - if base.config.GetBool('temp-hpr-fix',0): - SEditor.widget.setR(SEditor.widget, deltaAngle) - else: - SEditor.widget.setR(SEditor.widget, -deltaAngle) + SEditor.widget.setR(SEditor.widget, deltaAngle) elif self.rotateAxis == 'z': SEditor.widget.setH(SEditor.widget, deltaAngle) # Record crank angle for next time around @@ -456,10 +453,7 @@ class DirectManipulationControl(DirectObject): deltaAngle = angle - state.lastAngle state.lastAngle = angle # Mouse motion edge to edge of display region results in one full turn - if base.config.GetBool('temp-hpr-fix',0): - relHpr(SEditor.widget, SEditor.camera, 0, 0, -deltaAngle) - else: - relHpr(SEditor.widget, SEditor.camera, 0, 0, deltaAngle) + relHpr(SEditor.widget, SEditor.camera, 0, 0, -deltaAngle) def scale3D(self, state): # Scale the selected node based upon up down mouse motion diff --git a/direct/src/cluster/ClusterClient.py b/direct/src/cluster/ClusterClient.py index e5c0b7ba6a..e0735c6f6f 100644 --- a/direct/src/cluster/ClusterClient.py +++ b/direct/src/cluster/ClusterClient.py @@ -2,14 +2,16 @@ from panda3d.core import ( ClockObject, - ConnectionWriter, Point3, - QueuedConnectionManager, - QueuedConnectionReader, VBase3, Vec3, decomposeMatrix, ) +from panda3d.net import ( + ConnectionWriter, + QueuedConnectionManager, + QueuedConnectionReader, +) from .ClusterMsgs import ( CLUSTER_DAEMON_PORT, CLUSTER_NAMED_MOVEMENT_DONE, diff --git a/direct/src/cluster/ClusterMsgs.py b/direct/src/cluster/ClusterMsgs.py index 299e6cb43f..91e3716c86 100644 --- a/direct/src/cluster/ClusterMsgs.py +++ b/direct/src/cluster/ClusterMsgs.py @@ -3,7 +3,7 @@ # This module is intended to supply routines and dataformats common to # both ClusterClient and ClusterServer. -from panda3d.core import NetDatagram +from panda3d.net import NetDatagram from direct.distributed.PyDatagram import PyDatagram from direct.distributed.PyDatagramIterator import PyDatagramIterator import time diff --git a/direct/src/cluster/ClusterServer.py b/direct/src/cluster/ClusterServer.py index 5d62146cc1..7842c34097 100644 --- a/direct/src/cluster/ClusterServer.py +++ b/direct/src/cluster/ClusterServer.py @@ -1,12 +1,14 @@ from panda3d.core import ( ClockObject, + Vec3, +) +from panda3d.net import ( ConnectionWriter, NetAddress, PointerToConnection, QueuedConnectionListener, QueuedConnectionManager, QueuedConnectionReader, - Vec3, ) from .ClusterMsgs import ( CLUSTER_CAM_FRUSTUM, diff --git a/direct/src/dcparser/dcClass_ext.cxx b/direct/src/dcparser/dcClass_ext.cxx index 4661722492..44ab8f27bb 100644 --- a/direct/src/dcparser/dcClass_ext.cxx +++ b/direct/src/dcparser/dcClass_ext.cxx @@ -46,9 +46,7 @@ void Extension:: set_class_def(PyObject *class_def) { PythonClassDefsImpl *defs = do_get_defs(); - Py_XINCREF(class_def); - Py_XDECREF(defs->_class_def); - defs->_class_def = class_def; + Py_XSETREF(defs->_class_def, Py_XNewRef(class_def)); } /** @@ -58,13 +56,11 @@ set_class_def(PyObject *class_def) { PyObject *Extension:: get_class_def() const { if (!has_class_def()) { - Py_INCREF(Py_None); - return Py_None; + return Py_NewRef(Py_None); } PythonClassDefsImpl *defs = do_get_defs(); - Py_INCREF(defs->_class_def); - return defs->_class_def; + return Py_NewRef(defs->_class_def); } /** @@ -85,9 +81,7 @@ void Extension:: set_owner_class_def(PyObject *owner_class_def) { PythonClassDefsImpl *defs = do_get_defs(); - Py_XINCREF(owner_class_def); - Py_XDECREF(defs->_owner_class_def); - defs->_owner_class_def = owner_class_def; + Py_XSETREF(defs->_owner_class_def, Py_XNewRef(owner_class_def)); } /** @@ -97,13 +91,11 @@ set_owner_class_def(PyObject *owner_class_def) { PyObject *Extension:: get_owner_class_def() const { if (!has_owner_class_def()) { - Py_INCREF(Py_None); - return Py_None; + return Py_NewRef(Py_None); } PythonClassDefsImpl *defs = do_get_defs(); - Py_INCREF(defs->_owner_class_def); - return defs->_owner_class_def; + return Py_NewRef(defs->_owner_class_def); } /** diff --git a/direct/src/dcparser/dcPacker_ext.cxx b/direct/src/dcparser/dcPacker_ext.cxx index 3338ee6e88..276a2dd7f9 100644 --- a/direct/src/dcparser/dcPacker_ext.cxx +++ b/direct/src/dcparser/dcPacker_ext.cxx @@ -173,8 +173,7 @@ unpack_object() { switch (pack_type) { case PT_invalid: - object = Py_None; - Py_INCREF(object); + object = Py_NewRef(Py_None); _this->unpack_skip(); break; diff --git a/direct/src/dist/FreezeTool.py b/direct/src/dist/FreezeTool.py index 3a1b6487b8..678f8c0888 100644 --- a/direct/src/dist/FreezeTool.py +++ b/direct/src/dist/FreezeTool.py @@ -1334,7 +1334,7 @@ class Freezer: self.mf.load_module(mdef.moduleName, fp, pathname, stuff) else: stuff = ("", "rb", _PY_SOURCE) - if mdef.text: + if mdef.text is not None: fp = io.StringIO(mdef.text) else: fp = open(pathname, 'rb') @@ -1948,6 +1948,9 @@ class Freezer: if self.platform.startswith('win'): # We don't use mmap on Windows. Align just for good measure. blob_align = 32 + elif self.platform.endswith('_aarch64') or self.platform.endswith('_arm64'): + # Most arm64 operating systems are configured with 16 KiB pages. + blob_align = 16384 else: # Align to page size, so that it can be mmapped. blob_align = 4096 diff --git a/direct/src/dist/_dist_hooks.py b/direct/src/dist/_dist_hooks.py new file mode 100644 index 0000000000..a611c35dbc --- /dev/null +++ b/direct/src/dist/_dist_hooks.py @@ -0,0 +1,16 @@ +# This module should not import Panda3D modules globally as it contains hooks +# that may be invoked by setuptools even when Panda3D is not used. If the +# Panda3D installation is broken, it should not affect other applications. + +__all__ = ('finalize_distribution_options', ) + + +def finalize_distribution_options(dist): + """Entry point for compatibility with setuptools>=61, see #1394.""" + + options = dist.get_option_dict('build_apps') + if options.get('gui_apps') or options.get('console_apps'): + # Make sure this is set to avoid auto-discovery taking place. + if getattr(dist.metadata, 'py_modules', None) is None and \ + getattr(dist.metadata, 'packages', None) is None: + dist.py_modules = [] diff --git a/direct/src/dist/commands.py b/direct/src/dist/commands.py index 9ee83736cf..505e57697b 100644 --- a/direct/src/dist/commands.py +++ b/direct/src/dist/commands.py @@ -23,6 +23,7 @@ from . import FreezeTool from . import pefile from . import installers from .icon import Icon +from ._dist_hooks import finalize_distribution_options import panda3d.core as p3d @@ -54,10 +55,16 @@ def _register_python_loaders(): _register_python_loaders.done = True - registry = p3d.LoaderFileTypeRegistry.getGlobalPtr() + from importlib.metadata import entry_points - import pkg_resources - for entry_point in pkg_resources.iter_entry_points('panda3d.loaders'): + eps = entry_points() + if isinstance(eps, dict): # Python 3.8 and 3.9 + loaders = eps.get('panda3d.loaders', ()) + else: + loaders = eps.select(group='panda3d.loaders') + + registry = p3d.LoaderFileTypeRegistry.get_global_ptr() + for entry_point in loaders: registry.register_deferred_type(entry_point) @@ -465,8 +472,10 @@ class build_apps(setuptools.Command): if self.bam_model_extensions: for ext in self.bam_model_extensions: ext = '.' + ext.lstrip('.') - assert ext not in self.file_handlers, \ - 'Extension {} occurs in both file_handlers and bam_model_extensions!'.format(ext) + handler = self.file_handlers.get(ext) + if handler != _model_to_bam: + assert handler is None, \ + 'Extension {} occurs in both file_handlers and bam_model_extensions!'.format(ext) self.file_handlers[ext] = _model_to_bam tmp = self.default_file_handlers.copy() @@ -1698,7 +1707,7 @@ class bdist_apps(setuptools.Command): setattr(self, opt, None) def finalize_options(self): - import pkg_resources + from importlib.metadata import entry_points # We need to massage the inputs a bit in case they came from a # setup.cfg file. @@ -1712,11 +1721,17 @@ class bdist_apps(setuptools.Command): self.signing_certificate = os.path.abspath(self.signing_certificate) self.signing_private_key = os.path.abspath(self.signing_private_key) + eps = entry_points() + if isinstance(eps, dict): # Python 3.8 and 3.9 + installer_eps = eps.get('panda3d.bdist_apps.installers', ()) + else: + installer_eps = eps.select(group='panda3d.bdist_apps.installers') + tmp = self.DEFAULT_INSTALLER_FUNCS.copy() tmp.update(self.installer_functions) tmp.update({ entrypoint.name: entrypoint.load() - for entrypoint in pkg_resources.iter_entry_points('panda3d.bdist_apps.installers') + for entrypoint in installer_eps }) self.installer_functions = tmp @@ -1759,14 +1774,3 @@ class bdist_apps(setuptools.Command): continue self.installer_functions[installer](self, basename, build_dir) - - -def finalize_distribution_options(dist): - """Entry point for compatibility with setuptools>=61, see #1394.""" - - options = dist.get_option_dict('build_apps') - if options.get('gui_apps') or options.get('console_apps'): - # Make sure this is set to avoid auto-discovery taking place. - if getattr(dist.metadata, 'py_modules', None) is None and \ - getattr(dist.metadata, 'packages', None) is None: - dist.py_modules = [] diff --git a/direct/src/distributed/ServerRepository.py b/direct/src/distributed/ServerRepository.py index 58ffc5dde7..3ae6e90f6d 100644 --- a/direct/src/distributed/ServerRepository.py +++ b/direct/src/distributed/ServerRepository.py @@ -4,19 +4,21 @@ from panda3d.core import ( ConfigVariableBool, ConfigVariableDouble, ConfigVariableInt, - ConnectionWriter, DatagramIterator, Filename, + TPLow, + UniqueIdAllocator, + VirtualFileSystem, + getModelPath, +) +from panda3d.net import ( + ConnectionWriter, NetAddress, NetDatagram, PointerToConnection, QueuedConnectionListener, QueuedConnectionManager, QueuedConnectionReader, - TPLow, - UniqueIdAllocator, - VirtualFileSystem, - getModelPath, ) from panda3d.direct import DCFile from direct.distributed.MsgTypesCMU import ( diff --git a/direct/src/distributed/cConnectionRepository.cxx b/direct/src/distributed/cConnectionRepository.cxx index a6e23ba1df..d7db58cde3 100644 --- a/direct/src/distributed/cConnectionRepository.cxx +++ b/direct/src/distributed/cConnectionRepository.cxx @@ -750,9 +750,9 @@ handle_update_field() { // while we call the update method--otherwise, the update method might // get into trouble if it tried to delete the object from the doId2do // map. - Py_INCREF(distobj); - invoke_extension(dclass).receive_update(distobj, _di); - Py_DECREF(distobj); + PyObject *distobj_ref = Py_NewRef(distobj); + invoke_extension(dclass).receive_update(distobj_ref, _di); + Py_DECREF(distobj_ref); if (PyErr_Occurred()) { #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS) @@ -827,12 +827,12 @@ handle_update_field_owner() { // raised while we call the update method--otherwise, the update // method might get into trouble if it tried to delete the object from // the doId2do map. - Py_INCREF(distobjOV); + PyObject *distobjOV_ref = Py_NewRef(distobjOV); // make a copy of the datagram iterator so that we can use the main // iterator for the non-owner update DatagramIterator _odi(_di); - invoke_extension(dclass).receive_update(distobjOV, _odi); - Py_DECREF(distobjOV); + invoke_extension(dclass).receive_update(distobjOV_ref, _odi); + Py_DECREF(distobjOV_ref); if (PyErr_Occurred()) { #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS) @@ -871,9 +871,9 @@ handle_update_field_owner() { // while we call the update method--otherwise, the update method might // get into trouble if it tried to delete the object from the doId2do // map. - Py_INCREF(distobj); - invoke_extension(dclass).receive_update(distobj, _di); - Py_DECREF(distobj); + PyObject *distobj_ref = Py_NewRef(distobj); + invoke_extension(dclass).receive_update(distobj_ref, _di); + Py_DECREF(distobj_ref); if (PyErr_Occurred()) { #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS) diff --git a/direct/src/gui/DirectGuiBase.py b/direct/src/gui/DirectGuiBase.py index f9bbb5b5f8..1782cd58cf 100644 --- a/direct/src/gui/DirectGuiBase.py +++ b/direct/src/gui/DirectGuiBase.py @@ -229,7 +229,12 @@ class DirectGuiBase(DirectObject.DirectObject): del keywords[name] else: # Use optionDefs value - optionInfo[name] = [default, default, function] + value = default + if isinstance(value, list): + value = list(value) + elif isinstance(value, dict): + value = dict(value) + optionInfo[name] = [default, value, function] elif optionInfo[name][FUNCTION] is None: # Only override function if not defined by derived class optionInfo[name][FUNCTION] = function diff --git a/direct/src/interval/LerpInterval.py b/direct/src/interval/LerpInterval.py index ae218fe0f2..e303b3a5d1 100644 --- a/direct/src/interval/LerpInterval.py +++ b/direct/src/interval/LerpInterval.py @@ -841,8 +841,12 @@ class LerpFunctionInterval(Interval.Interval): self.extraArgs = extraArgs # Generate unique name if necessary if name is None: + if hasattr(function, '__name__'): + name = function.__name__ + else: + name = '<' + function.__class__.__name__ + '>' name = ('LerpFunctionInterval-%s-%d' % - (function.__name__, + (name, LerpFunctionInterval.lerpFunctionIntervalNum)) LerpFunctionInterval.lerpFunctionIntervalNum += 1 else: diff --git a/direct/src/interval/cInterval_ext.cxx b/direct/src/interval/cInterval_ext.cxx index 1225bae004..f61571b696 100644 --- a/direct/src/interval/cInterval_ext.cxx +++ b/direct/src/interval/cInterval_ext.cxx @@ -24,7 +24,7 @@ extern struct Dtool_PyTypedObject Dtool_CInterval; /** * Yields continuously until the interval is done. */ -static PyObject *gen_next(PyObject *self) { +static PyObject *gen_next_c_interval(PyObject *self) { const CInterval *ival; if (!Dtool_Call_ExtractThisPointer(self, Dtool_CInterval, (void **)&ival)) { return nullptr; @@ -32,8 +32,7 @@ static PyObject *gen_next(PyObject *self) { if (ival->get_state() != CInterval::S_final) { // Try again next frame. - Py_INCREF(Py_None); - return Py_None; + return Py_NewRef(Py_None); } else { PyErr_SetNone(PyExc_StopIteration); @@ -55,7 +54,7 @@ __await__(PyObject *self) { // we call this via Python. PyObject *result = PyObject_CallMethod(self, "start", nullptr); Py_XDECREF(result); - return Dtool_NewGenerator(self, &gen_next); + return Dtool_NewGenerator(self, &gen_next_c_interval); } #endif // HAVE_PYTHON diff --git a/direct/src/showbase/Loader.py b/direct/src/showbase/Loader.py index 3aad55647a..141c71a368 100644 --- a/direct/src/showbase/Loader.py +++ b/direct/src/showbase/Loader.py @@ -25,6 +25,7 @@ from panda3d.core import Loader as PandaLoader from direct.directnotify.DirectNotifyGlobal import directNotify from direct.showbase.DirectObject import DirectObject import warnings +import sys # You can specify a phaseChecker callback to check # a modelPath to see if it is being loaded in the correct @@ -151,16 +152,17 @@ class Loader(DirectObject): if not ConfigVariableBool('loader-support-entry-points', True): return - import importlib - try: - pkg_resources = importlib.import_module('pkg_resources') - except ImportError: - pkg_resources = None + from importlib.metadata import entry_points + eps = entry_points() + if sys.version_info < (3, 10): + loaders = eps.get('panda3d.loaders', ()) + else: + loaders = eps.select(group='panda3d.loaders') - if pkg_resources: + if loaders: registry = LoaderFileTypeRegistry.getGlobalPtr() - for entry_point in pkg_resources.iter_entry_points('panda3d.loaders'): + for entry_point in loaders: registry.register_deferred_type(entry_point) cls._loadedPythonFileTypes = True diff --git a/direct/src/showbase/ShowBaseGlobal.py b/direct/src/showbase/ShowBaseGlobal.py index 3e656c045f..4cd4e8623b 100644 --- a/direct/src/showbase/ShowBaseGlobal.py +++ b/direct/src/showbase/ShowBaseGlobal.py @@ -64,8 +64,6 @@ hidden = NodePath("hidden") loader: Loader -direct: "DirectSession" - # Set direct notify categories now that we have config directNotify.setDconfigLevels() diff --git a/direct/src/showbase/extend_frozen.c b/direct/src/showbase/extend_frozen.c index 1a562f8a63..2fc4fc7a6c 100644 --- a/direct/src/showbase/extend_frozen.c +++ b/direct/src/showbase/extend_frozen.c @@ -147,14 +147,12 @@ py_is_frozen_module(PyObject *self, PyObject *args) { i = 0; while (PyImport_FrozenModules[i].name != NULL) { if (strcmp(PyImport_FrozenModules[i].name, name) == 0) { - Py_INCREF(Py_True); - return Py_True; + Py_RETURN_TRUE; } ++i; } - Py_INCREF(Py_False); - return Py_False; + Py_RETURN_FALSE; } /* diff --git a/direct/src/tkpanels/Inspector.py b/direct/src/tkpanels/Inspector.py index 29bebcf16f..51e448f30d 100644 --- a/direct/src/tkpanels/Inspector.py +++ b/direct/src/tkpanels/Inspector.py @@ -11,6 +11,7 @@ so that I can just type: ``inspect(anObject)`` any time. See :ref:`inspection-utilities` for more information. """ +from __future__ import annotations __all__ = ['inspect', 'inspectorFor', 'Inspector', 'ModuleInspector', 'ClassInspector', 'InstanceInspector', 'FunctionInspector', 'InstanceMethodInspector', 'CodeInspector', 'ComplexInspector', 'DictionaryInspector', 'SequenceInspector', 'SliceInspector', 'InspectorWindow'] @@ -31,7 +32,7 @@ def inspect(anObject): ### private -_InspectorMap: "dict[str, str]" +_InspectorMap: dict[str, str] def inspectorFor(anObject): diff --git a/direct/src/wxwidgets/WxPandaShell.py b/direct/src/wxwidgets/WxPandaShell.py index 09e15add96..853be93206 100755 --- a/direct/src/wxwidgets/WxPandaShell.py +++ b/direct/src/wxwidgets/WxPandaShell.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import wx from wx.lib.agw import fourwaysplitter as FWS @@ -9,8 +11,6 @@ from direct.task.TaskManagerGlobal import taskMgr from .WxAppShell import WxAppShell from .ViewPort import Viewport, ViewportManager -from typing import Optional - ID_FOUR_VIEW = 401 ID_TOP_VIEW = 402 ID_FRONT_VIEW = 403 @@ -27,7 +27,7 @@ class WxPandaShell(WxAppShell): copyright = ('Copyright 2010 Disney Online Studios.' + '\nAll Rights Reserved.') - MENU_TEXTS: dict[int, tuple[str, Optional[str]]] = { + MENU_TEXTS: dict[int, tuple[str, str | None]] = { ID_FOUR_VIEW: ("Four Views", None), ID_TOP_VIEW: ("Top View", None), ID_FRONT_VIEW: ("Front View", None), diff --git a/direct/src/wxwidgets/WxSlider.py b/direct/src/wxwidgets/WxSlider.py index 5f504c8896..d92a28e206 100755 --- a/direct/src/wxwidgets/WxSlider.py +++ b/direct/src/wxwidgets/WxSlider.py @@ -16,7 +16,7 @@ class WxSlider(wx.Slider): self.maxValue = maxValue self.minValue = minValue - intVal = 100.0 / (self.maxValue - self.minValue) * (value - self.minValue) + intVal = int(100.0 / (self.maxValue - self.minValue) * (value - self.minValue)) intMin = 0 intMax = 100 @@ -35,33 +35,37 @@ class WxSlider(wx.Slider): textSize, wx.TE_CENTER | wx.TE_PROCESS_ENTER) self.textValue.Disable() - newPos = (pos[0], pos[1] + 20) + pos = (pos[0], pos[1] + 20) else: newStyle = wx.SL_VERTICAL - newPos = (pos[0], pos[1] + 40) + pos = (pos[0], pos[1] + 40) if style & wx.SL_AUTOTICKS: newStyle |= wx.SL_AUTOTICKS - wx.Slider.__init__(self, parent, id, intVal, intMin, intMax, newPos, size, style=newStyle) + wx.Slider.__init__(self, parent, id, intVal, intMin, intMax, pos, size, style=newStyle) self.Disable() def GetValue(self): # overriding wx.Slider.GetValue() - #return (wx.Slider.GetValue(self) * (self.maxValue - self.minValue) / 100.0 + self.minValue) - return float(self.textValue.GetValue()) # [gjeon] since the value from the slider is not as precise as the value entered by the user + if self.textValue is not None: # Horizontal with labels + return float(self.textValue.GetValue()) # [gjeon] since the value from the slider is not as precise as the value entered by the user + else: + return (wx.Slider.GetValue(self) * (self.maxValue - self.minValue) / 100.0 + self.minValue) def SetValue(self, value): # overriding wx.Slider.SetValue() - self.textValue.SetValue("%.2f" % value) + if self.textValue is not None: + self.textValue.SetValue("%.2f" % value) intVal = 100.0 / (self.maxValue - self.minValue) * (value - self.minValue) wx.Slider.SetValue(self, intVal) def onChange(self, event): # update textValue from slider - self.textValue.Clear() - floatVal = wx.Slider.GetValue(self) * (self.maxValue - self.minValue) / 100.0 + self.minValue - self.textValue.WriteText("%.2f" % floatVal) + if self.textValue is not None: + self.textValue.Clear() + floatVal = wx.Slider.GetValue(self) * (self.maxValue - self.minValue) / 100.0 + self.minValue + self.textValue.WriteText("%.2f" % floatVal) if self.updateCB: # callback function sould receive event as the argument self.updateCB(event) event.Skip() @@ -82,13 +86,14 @@ class WxSlider(wx.Slider): def Disable(self): # overriding wx.Slider.Disable() wx.Slider.Disable(self) - self.textValue.Disable() + if self.textValue is not None: + self.textValue.Disable() def Enable(self): # overriding wx.Slider.Enable() wx.Slider.Enable(self) self.Bind(wx.EVT_SLIDER, self.onChange) - if not self.textValue is None: + if self.textValue is not None: self.textValue.Enable() self.textValue.Bind(wx.EVT_TEXT_ENTER, self.onEnter) diff --git a/doc/ReleaseNotes b/doc/ReleaseNotes index 2707d324d9..97a15ddbe8 100644 --- a/doc/ReleaseNotes +++ b/doc/ReleaseNotes @@ -1,3 +1,93 @@ +----------------------- RELEASE 1.10.14 ----------------------- + +This release adds support for Python 3.12 and furthermore contains significant +bug fixes, and also implements some missing features in the shader generator. + +API +* Accept bytes object in DatagramOutputFile.write_header() +* Add missing clear_color() method to CardMaker +* Add file_version properties to BamFile and BamWriter, mirroring BamReader +* Add missing method for getting current display mode index (#1550) + +Shader Generator +* Add support for perspective points (#1440) +* Implement remaining missing TexGenAttrib modes (#1437) +* Fix support for hardware point sprites +* Support missing texture types: cube map arrays, 1D arrays, buffer textures + +Rendering +* Add texconst_i input for Cg shaders to access TexGenAttrib constants +* Fix bug when same texture is used with different TexGenAttrib modes +* OpenGL 3.2+/ES: Correctly handle 4-component texcoords in default shader +* DX9: fix bugs setting some kinds of shader inputs +* OpenGL: guard against exceeding max supported vertex attribute stride +* Add missing handling for 1D array textures in Cg shaders +* OpenGL: improve handling of SM5 Cg shaders +* Fix p3d_LightModel.ambient not updating properly +* Work around wireframe rendering bug in Panfrost drivers +* Fix assertion error when preparing texture fails +* Fix image load/store support in GLES 3.1 (set gl-immutable-texture-storage) + +Windowing +* Windows: Fix issues switching fullscreen while maximized (#1469) +* macOS: Fix undecorated setting ignored when switching back to windowed mode +* macOS: Fix window sizing bug when simultaneously changing undecorated +* macOS: Fix black bar when switching to fullscreen with Z-Order set to Top +* macOS: Squelch secure restorable state warning on macOS 14 "Sonoma" +* X11: Fix crash on shutdown when using custom cursor +* EGL: Fix invalid operation error when using headless pbuffer +* EGL: Add support for resizing (offscreen) pbuffers +* Windows: Message loop is no longer disabled when using tk with threaded draw +* Windows: Fix handling of invalid raw mouse devices + +Deployment +* Fix crash when running executable built with Python 3.11 (#1423) +* Fix for thirdparty packages that use delvewheel (#1492) +* Strip .abi3.so suffix from libraries +* Silently ignore missing hidden imports +* Add missing hidden imports for setuptools and shapely +* Show better error message when targeting no-longer-supported platforms +* Fix issues running pfreeze on macOS +* Fix crash using on arm64 systems with 16 KiB pages (eg. Asahi Linux) +* Fix error using bam_model_extensions with bdist_apps + +Pipeline +* Support reading .bmp files with RLE8 compression +* Fix wrong magfilter being written by egg-palettize (#1585) +* Fix memory leaks when writing TIFF files +* Fix hang in .egg loader when `` used with `` (#1515) +* Add assimp-disable-extensions config var (see #1537) +* Fix assert/crash when reading multiple recorders from bam file (#1561) + +Build +* Add support for building with Python 3.12 +* macOS .dmg are now built as HFS+ for 10.9 compatibility (#1502) +* Don't use RTTI features in headers when building with `-fno-rtti` +* Fix some new compiler warnings +* Fix compile errors with some versions of png.h +* Work around GCC 13.2 bug compiling interrogate-generated code (#1580) +* Support building with LibreSSL on Windows (#1503) +* Fix some issues in anticipation of Python 3.13+ (#1523, #1526) +* More robust parsing of version in setup.cfg (incl. #1539) +* Avoid using deprecated distutils module (#1549) +* Add _d suffix to .pyd files when building debug build on Windows (#1566) + +Miscellaneous +* Fix bug causing textures to sometimes be randomly downloaded +* Fix PStats Python profiling exception when using metaclasses (#1505) +* Fix segfault when ConnectionRepository is verbose (#1430) +* Fix broken minusnode icon in dmodels (#1449) +* Fix wrong delete operator in ARToolKit +* Fix crash when encountering corruption in OpenAL stream (#1452) +* Fix SimpleHashMap error reporting at static init time +* Fix assorted code issues, typos, and Python 2-isms in direct tree +* Code size reductions for interrogate-generated bindings +* Assorted docstring corrections and additions +* Interrogate supports explicit cls parameter for static methods +* Interrogate: fix enum scope issue +* Don't assume presence of softspace attribute on files in directnotify +* Use importlib.metadata (not pkg_resources) for entry points in Python 3.8+ + ----------------------- RELEASE 1.10.13 ----------------------- This is a significant release containing many important bug fixes and a couple diff --git a/dtool/Config.cmake b/dtool/Config.cmake index 3d8ca9272f..d269b62e3e 100644 --- a/dtool/Config.cmake +++ b/dtool/Config.cmake @@ -30,10 +30,15 @@ if(DEFINED CMAKE_CXX_FLAGS_COVERAGE) endif() # Are we building with static or dynamic linking? +if(EMSCRIPTEN OR WASI) + set(_default_shared OFF) +else() + set(_default_shared ON) +endif() option(BUILD_SHARED_LIBS "Causes subpackages to be built separately -- setup for dynamic linking. Utilities/tools/binaries/etc are then dynamically linked to the -libraries instead of being statically linked." ON) +libraries instead of being statically linked." ${_default_shared}) option(BUILD_METALIBS "Should we build 'metalibs' -- fewer, larger libraries that contain the bulk @@ -448,10 +453,10 @@ on DirectX rendering." OFF) mark_as_advanced(SUPPORT_FIXED_FUNCTION) # Should build tinydisplay? -#option(HAVE_TINYDISPLAY -# "Builds TinyDisplay, a light software renderer based on TinyGL, -#that is built into Panda. TinyDisplay is not as full-featured as Mesa -#but is many times faster." ON) +option(HAVE_TINYDISPLAY + "Builds TinyDisplay, a light software renderer based on TinyGL, +that is built into Panda. TinyDisplay is not as full-featured as Mesa +but is many times faster." ON) # Is SDL installed, and where? set(Threads_FIND_QUIETLY TRUE) # Fix for builtin FindSDL @@ -561,12 +566,18 @@ set(THREADS_LIBRARIES "${CMAKE_THREAD_LIBS_INIT}") set(HAVE_POSIX_THREADS ${CMAKE_USE_PTHREADS_INIT}) # Add basic use flag for threading +if(EMSCRIPTEN OR WASI) + set(_default_threads OFF) +else() + set(_default_threads ON) +endif() package_option(THREADS "If on, compile Panda3D with threading support. Building in support for threading will enable Panda to take advantage of multiple CPU's if you have them (and if the OS supports kernel threads running on different CPU's), but it will slightly slow down Panda for the single CPU case." + DEFAULT ${_default_threads} IMPORTED_AS Threads::Threads) # Configure debug threads diff --git a/dtool/Package.cmake b/dtool/Package.cmake index 0a0fb8ea39..42758c2702 100644 --- a/dtool/Package.cmake +++ b/dtool/Package.cmake @@ -2,6 +2,9 @@ set(_thirdparty_dir_default "${PROJECT_SOURCE_DIR}/thirdparty") if(NOT IS_DIRECTORY "${_thirdparty_dir_default}") set(_thirdparty_dir_default "") endif() +if(CMAKE_SYSTEM_NAME STREQUAL "WASI") + set(_thirdparty_dir_default "") +endif() set(THIRDPARTY_DIRECTORY "${_thirdparty_dir_default}" CACHE PATH "Optional location of a makepanda-style thirdparty directory. All libraries @@ -257,16 +260,32 @@ if(HAVE_PYTHON) set(_ARCH_DIR ".") elseif(PYTHON_EXECUTABLE) - execute_process( - COMMAND ${PYTHON_EXECUTABLE} - -c "from distutils.sysconfig import get_python_lib; print(get_python_lib(False))" - OUTPUT_VARIABLE _LIB_DIR - OUTPUT_STRIP_TRAILING_WHITESPACE) - execute_process( - COMMAND ${PYTHON_EXECUTABLE} - -c "from distutils.sysconfig import get_python_lib; print(get_python_lib(True))" - OUTPUT_VARIABLE _ARCH_DIR - OUTPUT_STRIP_TRAILING_WHITESPACE) + # Python 3.12 drops the distutils module, so we have to use the newer + # sysconfig module instead. Earlier versions of Python had the newer + # module too, but it was broken in Debian/Ubuntu, see #1230 + if(PYTHON_VERSION_STRING VERSION_LESS "3.12") + execute_process( + COMMAND ${PYTHON_EXECUTABLE} + -c "from distutils.sysconfig import get_python_lib; print(get_python_lib(False))" + OUTPUT_VARIABLE _LIB_DIR + OUTPUT_STRIP_TRAILING_WHITESPACE) + execute_process( + COMMAND ${PYTHON_EXECUTABLE} + -c "from distutils.sysconfig import get_python_lib; print(get_python_lib(True))" + OUTPUT_VARIABLE _ARCH_DIR + OUTPUT_STRIP_TRAILING_WHITESPACE) + else() + execute_process( + COMMAND ${PYTHON_EXECUTABLE} + -c "import sysconfig; print(sysconfig.get_path('purelib'))" + OUTPUT_VARIABLE _LIB_DIR + OUTPUT_STRIP_TRAILING_WHITESPACE) + execute_process( + COMMAND ${PYTHON_EXECUTABLE} + -c "import sysconfig; print(sysconfig.get_path('platlib'))" + OUTPUT_VARIABLE _ARCH_DIR + OUTPUT_STRIP_TRAILING_WHITESPACE) + endif() else() set(_LIB_DIR "") diff --git a/dtool/src/cppparser/cppBison.cxx.prebuilt b/dtool/src/cppparser/cppBison.cxx.prebuilt index ab408c73c5..0d94f44c79 100644 --- a/dtool/src/cppparser/cppBison.cxx.prebuilt +++ b/dtool/src/cppparser/cppBison.cxx.prebuilt @@ -355,241 +355,243 @@ enum yysymbol_kind_t YYSYMBOL_KW_BEGIN_PUBLISH = 53, /* KW_BEGIN_PUBLISH */ YYSYMBOL_KW_BLOCKING = 54, /* KW_BLOCKING */ YYSYMBOL_KW_BOOL = 55, /* KW_BOOL */ - YYSYMBOL_KW_CATCH = 56, /* KW_CATCH */ - YYSYMBOL_KW_CHAR = 57, /* KW_CHAR */ - YYSYMBOL_KW_CHAR8_T = 58, /* KW_CHAR8_T */ - YYSYMBOL_KW_CHAR16_T = 59, /* KW_CHAR16_T */ - YYSYMBOL_KW_CHAR32_T = 60, /* KW_CHAR32_T */ - YYSYMBOL_KW_CLASS = 61, /* KW_CLASS */ - YYSYMBOL_KW_CONST = 62, /* KW_CONST */ - YYSYMBOL_KW_CONSTEVAL = 63, /* KW_CONSTEVAL */ - YYSYMBOL_KW_CONSTEXPR = 64, /* KW_CONSTEXPR */ - YYSYMBOL_KW_CONSTINIT = 65, /* KW_CONSTINIT */ - YYSYMBOL_KW_CONST_CAST = 66, /* KW_CONST_CAST */ - YYSYMBOL_KW_DECLTYPE = 67, /* KW_DECLTYPE */ - YYSYMBOL_KW_DEFAULT = 68, /* KW_DEFAULT */ - YYSYMBOL_KW_DELETE = 69, /* KW_DELETE */ - YYSYMBOL_KW_DOUBLE = 70, /* KW_DOUBLE */ - YYSYMBOL_KW_DYNAMIC_CAST = 71, /* KW_DYNAMIC_CAST */ - YYSYMBOL_KW_ELSE = 72, /* KW_ELSE */ - YYSYMBOL_KW_END_PUBLISH = 73, /* KW_END_PUBLISH */ - YYSYMBOL_KW_ENUM = 74, /* KW_ENUM */ - YYSYMBOL_KW_EXTENSION = 75, /* KW_EXTENSION */ - YYSYMBOL_KW_EXTERN = 76, /* KW_EXTERN */ - YYSYMBOL_KW_EXPLICIT = 77, /* KW_EXPLICIT */ - YYSYMBOL_KW_EXPLICIT_LPAREN = 78, /* KW_EXPLICIT_LPAREN */ - YYSYMBOL_KW_PUBLISHED = 79, /* KW_PUBLISHED */ - YYSYMBOL_KW_FALSE = 80, /* KW_FALSE */ - YYSYMBOL_KW_FINAL = 81, /* KW_FINAL */ - YYSYMBOL_KW_FLOAT = 82, /* KW_FLOAT */ - YYSYMBOL_KW_FRIEND = 83, /* KW_FRIEND */ - YYSYMBOL_KW_FOR = 84, /* KW_FOR */ - YYSYMBOL_KW_GOTO = 85, /* KW_GOTO */ - YYSYMBOL_KW_HAS_VIRTUAL_DESTRUCTOR = 86, /* KW_HAS_VIRTUAL_DESTRUCTOR */ - YYSYMBOL_KW_IF = 87, /* KW_IF */ - YYSYMBOL_KW_INLINE = 88, /* KW_INLINE */ - YYSYMBOL_KW_INT = 89, /* KW_INT */ - YYSYMBOL_KW_IS_ABSTRACT = 90, /* KW_IS_ABSTRACT */ - YYSYMBOL_KW_IS_BASE_OF = 91, /* KW_IS_BASE_OF */ - YYSYMBOL_KW_IS_CLASS = 92, /* KW_IS_CLASS */ - YYSYMBOL_KW_IS_CONSTRUCTIBLE = 93, /* KW_IS_CONSTRUCTIBLE */ - YYSYMBOL_KW_IS_CONVERTIBLE_TO = 94, /* KW_IS_CONVERTIBLE_TO */ - YYSYMBOL_KW_IS_DESTRUCTIBLE = 95, /* KW_IS_DESTRUCTIBLE */ - YYSYMBOL_KW_IS_EMPTY = 96, /* KW_IS_EMPTY */ - YYSYMBOL_KW_IS_ENUM = 97, /* KW_IS_ENUM */ - YYSYMBOL_KW_IS_FINAL = 98, /* KW_IS_FINAL */ - YYSYMBOL_KW_IS_FUNDAMENTAL = 99, /* KW_IS_FUNDAMENTAL */ - YYSYMBOL_KW_IS_POD = 100, /* KW_IS_POD */ - YYSYMBOL_KW_IS_POLYMORPHIC = 101, /* KW_IS_POLYMORPHIC */ - YYSYMBOL_KW_IS_STANDARD_LAYOUT = 102, /* KW_IS_STANDARD_LAYOUT */ - YYSYMBOL_KW_IS_TRIVIAL = 103, /* KW_IS_TRIVIAL */ - YYSYMBOL_KW_IS_TRIVIALLY_COPYABLE = 104, /* KW_IS_TRIVIALLY_COPYABLE */ - YYSYMBOL_KW_IS_UNION = 105, /* KW_IS_UNION */ - YYSYMBOL_KW_LONG = 106, /* KW_LONG */ - YYSYMBOL_KW_MAKE_MAP_KEYS_SEQ = 107, /* KW_MAKE_MAP_KEYS_SEQ */ - YYSYMBOL_KW_MAKE_MAP_PROPERTY = 108, /* KW_MAKE_MAP_PROPERTY */ - YYSYMBOL_KW_MAKE_PROPERTY = 109, /* KW_MAKE_PROPERTY */ - YYSYMBOL_KW_MAKE_PROPERTY2 = 110, /* KW_MAKE_PROPERTY2 */ - YYSYMBOL_KW_MAKE_SEQ = 111, /* KW_MAKE_SEQ */ - YYSYMBOL_KW_MAKE_SEQ_PROPERTY = 112, /* KW_MAKE_SEQ_PROPERTY */ - YYSYMBOL_KW_MUTABLE = 113, /* KW_MUTABLE */ - YYSYMBOL_KW_NAMESPACE = 114, /* KW_NAMESPACE */ - YYSYMBOL_KW_NEW = 115, /* KW_NEW */ - YYSYMBOL_KW_NOEXCEPT = 116, /* KW_NOEXCEPT */ - YYSYMBOL_KW_NOEXCEPT_LPAREN = 117, /* KW_NOEXCEPT_LPAREN */ - YYSYMBOL_KW_NULLPTR = 118, /* KW_NULLPTR */ - YYSYMBOL_KW_OPERATOR = 119, /* KW_OPERATOR */ - YYSYMBOL_KW_OVERRIDE = 120, /* KW_OVERRIDE */ - YYSYMBOL_KW_PRIVATE = 121, /* KW_PRIVATE */ - YYSYMBOL_KW_PROTECTED = 122, /* KW_PROTECTED */ - YYSYMBOL_KW_PUBLIC = 123, /* KW_PUBLIC */ - YYSYMBOL_KW_REGISTER = 124, /* KW_REGISTER */ - YYSYMBOL_KW_REINTERPRET_CAST = 125, /* KW_REINTERPRET_CAST */ - YYSYMBOL_KW_RETURN = 126, /* KW_RETURN */ - YYSYMBOL_KW_SHORT = 127, /* KW_SHORT */ - YYSYMBOL_KW_SIGNED = 128, /* KW_SIGNED */ - YYSYMBOL_KW_SIZEOF = 129, /* KW_SIZEOF */ - YYSYMBOL_KW_STATIC = 130, /* KW_STATIC */ - YYSYMBOL_KW_STATIC_ASSERT = 131, /* KW_STATIC_ASSERT */ - YYSYMBOL_KW_STATIC_CAST = 132, /* KW_STATIC_CAST */ - YYSYMBOL_KW_STRUCT = 133, /* KW_STRUCT */ - YYSYMBOL_KW_TEMPLATE = 134, /* KW_TEMPLATE */ - YYSYMBOL_KW_THREAD_LOCAL = 135, /* KW_THREAD_LOCAL */ - YYSYMBOL_KW_THROW = 136, /* KW_THROW */ - YYSYMBOL_KW_TRUE = 137, /* KW_TRUE */ - YYSYMBOL_KW_TRY = 138, /* KW_TRY */ - YYSYMBOL_KW_TYPEDEF = 139, /* KW_TYPEDEF */ - YYSYMBOL_KW_TYPEID = 140, /* KW_TYPEID */ - YYSYMBOL_KW_TYPENAME = 141, /* KW_TYPENAME */ - YYSYMBOL_KW_UNDERLYING_TYPE = 142, /* KW_UNDERLYING_TYPE */ - YYSYMBOL_KW_UNION = 143, /* KW_UNION */ - YYSYMBOL_KW_UNSIGNED = 144, /* KW_UNSIGNED */ - YYSYMBOL_KW_USING = 145, /* KW_USING */ - YYSYMBOL_KW_VIRTUAL = 146, /* KW_VIRTUAL */ - YYSYMBOL_KW_VOID = 147, /* KW_VOID */ - YYSYMBOL_KW_VOLATILE = 148, /* KW_VOLATILE */ - YYSYMBOL_KW_WCHAR_T = 149, /* KW_WCHAR_T */ - YYSYMBOL_KW_WHILE = 150, /* KW_WHILE */ - YYSYMBOL_START_CPP = 151, /* START_CPP */ - YYSYMBOL_START_CONST_EXPR = 152, /* START_CONST_EXPR */ - YYSYMBOL_START_TYPE = 153, /* START_TYPE */ - YYSYMBOL_154_ = 154, /* '{' */ - YYSYMBOL_155_ = 155, /* ',' */ - YYSYMBOL_156_ = 156, /* ';' */ - YYSYMBOL_157_ = 157, /* ':' */ - YYSYMBOL_158_ = 158, /* '=' */ - YYSYMBOL_159_ = 159, /* '?' */ - YYSYMBOL_160_ = 160, /* '|' */ - YYSYMBOL_161_ = 161, /* '^' */ - YYSYMBOL_162_ = 162, /* '&' */ - YYSYMBOL_163_ = 163, /* '<' */ - YYSYMBOL_164_ = 164, /* '>' */ - YYSYMBOL_165_ = 165, /* '+' */ - YYSYMBOL_166_ = 166, /* '-' */ - YYSYMBOL_167_ = 167, /* '*' */ - YYSYMBOL_168_ = 168, /* '/' */ - YYSYMBOL_169_ = 169, /* '%' */ - YYSYMBOL_170_ = 170, /* '~' */ - YYSYMBOL_171_ = 171, /* '.' */ - YYSYMBOL_172_ = 172, /* '(' */ - YYSYMBOL_173_ = 173, /* '[' */ - YYSYMBOL_174_ = 174, /* ')' */ - YYSYMBOL_175_ = 175, /* '}' */ - YYSYMBOL_176_ = 176, /* '!' */ - YYSYMBOL_177_ = 177, /* ']' */ - YYSYMBOL_YYACCEPT = 178, /* $accept */ - YYSYMBOL_grammar = 179, /* grammar */ - YYSYMBOL_cpp = 180, /* cpp */ - YYSYMBOL_181_1 = 181, /* $@1 */ - YYSYMBOL_constructor_inits = 182, /* constructor_inits */ - YYSYMBOL_constructor_init = 183, /* constructor_init */ - YYSYMBOL_extern_c = 184, /* extern_c */ - YYSYMBOL_185_2 = 185, /* $@2 */ - YYSYMBOL_declaration = 186, /* declaration */ - YYSYMBOL_friend_declaration = 187, /* friend_declaration */ - YYSYMBOL_188_3 = 188, /* $@3 */ - YYSYMBOL_storage_class = 189, /* storage_class */ - YYSYMBOL_optional_attributes = 190, /* optional_attributes */ - YYSYMBOL_attribute_specifiers = 191, /* attribute_specifiers */ - YYSYMBOL_attribute_specifier = 192, /* attribute_specifier */ - YYSYMBOL_type_like_declaration = 193, /* type_like_declaration */ - YYSYMBOL_194_4 = 194, /* $@4 */ - YYSYMBOL_195_5 = 195, /* $@5 */ - YYSYMBOL_multiple_instance_identifiers = 196, /* multiple_instance_identifiers */ - YYSYMBOL_typedef_declaration = 197, /* typedef_declaration */ - YYSYMBOL_198_6 = 198, /* $@6 */ - YYSYMBOL_typedef_instance_identifiers = 199, /* typedef_instance_identifiers */ - YYSYMBOL_constructor_prototype = 200, /* constructor_prototype */ - YYSYMBOL_201_7 = 201, /* $@7 */ - YYSYMBOL_202_8 = 202, /* $@8 */ - YYSYMBOL_203_9 = 203, /* $@9 */ - YYSYMBOL_function_prototype = 204, /* function_prototype */ - YYSYMBOL_205_10 = 205, /* $@10 */ - YYSYMBOL_206_11 = 206, /* $@11 */ - YYSYMBOL_207_12 = 207, /* $@12 */ - YYSYMBOL_208_13 = 208, /* $@13 */ - YYSYMBOL_209_14 = 209, /* $@14 */ - YYSYMBOL_function_post = 210, /* function_post */ - YYSYMBOL_function_operator = 211, /* function_operator */ - YYSYMBOL_more_template_declaration = 212, /* more_template_declaration */ - YYSYMBOL_template_declaration = 213, /* template_declaration */ - YYSYMBOL_214_15 = 214, /* $@15 */ - YYSYMBOL_template_formal_parameters = 215, /* template_formal_parameters */ - YYSYMBOL_template_nonempty_formal_parameters = 216, /* template_nonempty_formal_parameters */ - YYSYMBOL_typename_keyword = 217, /* typename_keyword */ - YYSYMBOL_template_formal_parameter = 218, /* template_formal_parameter */ - YYSYMBOL_template_formal_parameter_type = 219, /* template_formal_parameter_type */ - YYSYMBOL_instance_identifier = 220, /* instance_identifier */ - YYSYMBOL_221_16 = 221, /* $@16 */ - YYSYMBOL_instance_identifier_and_maybe_trailing_return_type = 222, /* instance_identifier_and_maybe_trailing_return_type */ - YYSYMBOL_maybe_trailing_return_type = 223, /* maybe_trailing_return_type */ - YYSYMBOL_maybe_comma_identifier = 224, /* maybe_comma_identifier */ - YYSYMBOL_function_parameter_list = 225, /* function_parameter_list */ - YYSYMBOL_function_parameters = 226, /* function_parameters */ - YYSYMBOL_formal_parameter_list = 227, /* formal_parameter_list */ - YYSYMBOL_formal_parameters = 228, /* formal_parameters */ - YYSYMBOL_template_parameter_maybe_initialize = 229, /* template_parameter_maybe_initialize */ - YYSYMBOL_maybe_initialize = 230, /* maybe_initialize */ - YYSYMBOL_maybe_initialize_or_constructor_body = 231, /* maybe_initialize_or_constructor_body */ - YYSYMBOL_maybe_initialize_or_function_body = 232, /* maybe_initialize_or_function_body */ - YYSYMBOL_structure_init = 233, /* structure_init */ - YYSYMBOL_structure_init_body = 234, /* structure_init_body */ - YYSYMBOL_function_parameter = 235, /* function_parameter */ - YYSYMBOL_formal_parameter = 236, /* formal_parameter */ - YYSYMBOL_not_paren_formal_parameter_identifier = 237, /* not_paren_formal_parameter_identifier */ - YYSYMBOL_formal_parameter_identifier = 238, /* formal_parameter_identifier */ - YYSYMBOL_parameter_pack_identifier = 239, /* parameter_pack_identifier */ - YYSYMBOL_not_paren_empty_instance_identifier = 240, /* not_paren_empty_instance_identifier */ - YYSYMBOL_empty_instance_identifier = 241, /* empty_instance_identifier */ - YYSYMBOL_type = 242, /* type */ - YYSYMBOL_type_pack = 243, /* type_pack */ - YYSYMBOL_type_decl = 244, /* type_decl */ - YYSYMBOL_predefined_type = 245, /* predefined_type */ - YYSYMBOL_var_type_decl = 246, /* var_type_decl */ - YYSYMBOL_full_type = 247, /* full_type */ - YYSYMBOL_anonymous_struct = 248, /* anonymous_struct */ - YYSYMBOL_249_17 = 249, /* $@17 */ - YYSYMBOL_named_struct = 250, /* named_struct */ - YYSYMBOL_251_18 = 251, /* $@18 */ - YYSYMBOL_maybe_final = 252, /* maybe_final */ - YYSYMBOL_maybe_class_derivation = 253, /* maybe_class_derivation */ - YYSYMBOL_class_derivation = 254, /* class_derivation */ - YYSYMBOL_base_specification = 255, /* base_specification */ - YYSYMBOL_enum = 256, /* enum */ - YYSYMBOL_257_19 = 257, /* $@19 */ - YYSYMBOL_enum_decl = 258, /* enum_decl */ - YYSYMBOL_enum_element_type = 259, /* enum_element_type */ - YYSYMBOL_enum_body_trailing_comma = 260, /* enum_body_trailing_comma */ - YYSYMBOL_enum_body = 261, /* enum_body */ - YYSYMBOL_enum_keyword = 262, /* enum_keyword */ - YYSYMBOL_struct_keyword = 263, /* struct_keyword */ - YYSYMBOL_namespace_declaration = 264, /* namespace_declaration */ - YYSYMBOL_265_20 = 265, /* $@20 */ - YYSYMBOL_266_21 = 266, /* $@21 */ - YYSYMBOL_using_declaration = 267, /* using_declaration */ - YYSYMBOL_simple_type = 268, /* simple_type */ - YYSYMBOL_simple_int_type = 269, /* simple_int_type */ - YYSYMBOL_simple_float_type = 270, /* simple_float_type */ - YYSYMBOL_simple_void_type = 271, /* simple_void_type */ - YYSYMBOL_code = 272, /* code */ - YYSYMBOL_273_22 = 273, /* $@22 */ - YYSYMBOL_code_block = 274, /* code_block */ - YYSYMBOL_element = 275, /* element */ - YYSYMBOL_optional_const_expr = 276, /* optional_const_expr */ - YYSYMBOL_optional_const_expr_comma = 277, /* optional_const_expr_comma */ - YYSYMBOL_const_expr_comma = 278, /* const_expr_comma */ - YYSYMBOL_no_angle_bracket_const_expr = 279, /* no_angle_bracket_const_expr */ - YYSYMBOL_const_expr = 280, /* const_expr */ - YYSYMBOL_const_operand = 281, /* const_operand */ - YYSYMBOL_formal_const_expr = 282, /* formal_const_expr */ - YYSYMBOL_formal_const_operand = 283, /* formal_const_operand */ - YYSYMBOL_capture_list = 284, /* capture_list */ - YYSYMBOL_capture = 285, /* capture */ - YYSYMBOL_class_derivation_name = 286, /* class_derivation_name */ - YYSYMBOL_name = 287, /* name */ - YYSYMBOL_name_no_final = 288, /* name_no_final */ - YYSYMBOL_string_literal = 289, /* string_literal */ - YYSYMBOL_empty = 290 /* empty */ + YYSYMBOL_KW_BUILTIN_VA_LIST = 56, /* KW_BUILTIN_VA_LIST */ + YYSYMBOL_KW_CATCH = 57, /* KW_CATCH */ + YYSYMBOL_KW_CHAR = 58, /* KW_CHAR */ + YYSYMBOL_KW_CHAR8_T = 59, /* KW_CHAR8_T */ + YYSYMBOL_KW_CHAR16_T = 60, /* KW_CHAR16_T */ + YYSYMBOL_KW_CHAR32_T = 61, /* KW_CHAR32_T */ + YYSYMBOL_KW_CLASS = 62, /* KW_CLASS */ + YYSYMBOL_KW_CONST = 63, /* KW_CONST */ + YYSYMBOL_KW_CONSTEVAL = 64, /* KW_CONSTEVAL */ + YYSYMBOL_KW_CONSTEXPR = 65, /* KW_CONSTEXPR */ + YYSYMBOL_KW_CONSTINIT = 66, /* KW_CONSTINIT */ + YYSYMBOL_KW_CONST_CAST = 67, /* KW_CONST_CAST */ + YYSYMBOL_KW_DECLTYPE = 68, /* KW_DECLTYPE */ + YYSYMBOL_KW_DEFAULT = 69, /* KW_DEFAULT */ + YYSYMBOL_KW_DELETE = 70, /* KW_DELETE */ + YYSYMBOL_KW_DOUBLE = 71, /* KW_DOUBLE */ + YYSYMBOL_KW_DYNAMIC_CAST = 72, /* KW_DYNAMIC_CAST */ + YYSYMBOL_KW_ELSE = 73, /* KW_ELSE */ + YYSYMBOL_KW_END_PUBLISH = 74, /* KW_END_PUBLISH */ + YYSYMBOL_KW_ENUM = 75, /* KW_ENUM */ + YYSYMBOL_KW_EXTENSION = 76, /* KW_EXTENSION */ + YYSYMBOL_KW_EXTERN = 77, /* KW_EXTERN */ + YYSYMBOL_KW_EXPLICIT = 78, /* KW_EXPLICIT */ + YYSYMBOL_KW_EXPLICIT_LPAREN = 79, /* KW_EXPLICIT_LPAREN */ + YYSYMBOL_KW_PUBLISHED = 80, /* KW_PUBLISHED */ + YYSYMBOL_KW_FALSE = 81, /* KW_FALSE */ + YYSYMBOL_KW_FINAL = 82, /* KW_FINAL */ + YYSYMBOL_KW_FLOAT = 83, /* KW_FLOAT */ + YYSYMBOL_KW_FRIEND = 84, /* KW_FRIEND */ + YYSYMBOL_KW_FOR = 85, /* KW_FOR */ + YYSYMBOL_KW_GOTO = 86, /* KW_GOTO */ + YYSYMBOL_KW_HAS_VIRTUAL_DESTRUCTOR = 87, /* KW_HAS_VIRTUAL_DESTRUCTOR */ + YYSYMBOL_KW_IF = 88, /* KW_IF */ + YYSYMBOL_KW_INLINE = 89, /* KW_INLINE */ + YYSYMBOL_KW_INT = 90, /* KW_INT */ + YYSYMBOL_KW_IS_ABSTRACT = 91, /* KW_IS_ABSTRACT */ + YYSYMBOL_KW_IS_BASE_OF = 92, /* KW_IS_BASE_OF */ + YYSYMBOL_KW_IS_CLASS = 93, /* KW_IS_CLASS */ + YYSYMBOL_KW_IS_CONSTRUCTIBLE = 94, /* KW_IS_CONSTRUCTIBLE */ + YYSYMBOL_KW_IS_CONVERTIBLE_TO = 95, /* KW_IS_CONVERTIBLE_TO */ + YYSYMBOL_KW_IS_DESTRUCTIBLE = 96, /* KW_IS_DESTRUCTIBLE */ + YYSYMBOL_KW_IS_EMPTY = 97, /* KW_IS_EMPTY */ + YYSYMBOL_KW_IS_ENUM = 98, /* KW_IS_ENUM */ + YYSYMBOL_KW_IS_FINAL = 99, /* KW_IS_FINAL */ + YYSYMBOL_KW_IS_FUNDAMENTAL = 100, /* KW_IS_FUNDAMENTAL */ + YYSYMBOL_KW_IS_POD = 101, /* KW_IS_POD */ + YYSYMBOL_KW_IS_POLYMORPHIC = 102, /* KW_IS_POLYMORPHIC */ + YYSYMBOL_KW_IS_STANDARD_LAYOUT = 103, /* KW_IS_STANDARD_LAYOUT */ + YYSYMBOL_KW_IS_TRIVIAL = 104, /* KW_IS_TRIVIAL */ + YYSYMBOL_KW_IS_TRIVIALLY_COPYABLE = 105, /* KW_IS_TRIVIALLY_COPYABLE */ + YYSYMBOL_KW_IS_UNION = 106, /* KW_IS_UNION */ + YYSYMBOL_KW_LONG = 107, /* KW_LONG */ + YYSYMBOL_KW_MAKE_MAP_KEYS_SEQ = 108, /* KW_MAKE_MAP_KEYS_SEQ */ + YYSYMBOL_KW_MAKE_MAP_PROPERTY = 109, /* KW_MAKE_MAP_PROPERTY */ + YYSYMBOL_KW_MAKE_PROPERTY = 110, /* KW_MAKE_PROPERTY */ + YYSYMBOL_KW_MAKE_PROPERTY2 = 111, /* KW_MAKE_PROPERTY2 */ + YYSYMBOL_KW_MAKE_SEQ = 112, /* KW_MAKE_SEQ */ + YYSYMBOL_KW_MAKE_SEQ_PROPERTY = 113, /* KW_MAKE_SEQ_PROPERTY */ + YYSYMBOL_KW_MUTABLE = 114, /* KW_MUTABLE */ + YYSYMBOL_KW_NAMESPACE = 115, /* KW_NAMESPACE */ + YYSYMBOL_KW_NEW = 116, /* KW_NEW */ + YYSYMBOL_KW_NOEXCEPT = 117, /* KW_NOEXCEPT */ + YYSYMBOL_KW_NOEXCEPT_LPAREN = 118, /* KW_NOEXCEPT_LPAREN */ + YYSYMBOL_KW_NULLPTR = 119, /* KW_NULLPTR */ + YYSYMBOL_KW_OPERATOR = 120, /* KW_OPERATOR */ + YYSYMBOL_KW_OVERRIDE = 121, /* KW_OVERRIDE */ + YYSYMBOL_KW_PRIVATE = 122, /* KW_PRIVATE */ + YYSYMBOL_KW_PROTECTED = 123, /* KW_PROTECTED */ + YYSYMBOL_KW_PUBLIC = 124, /* KW_PUBLIC */ + YYSYMBOL_KW_REGISTER = 125, /* KW_REGISTER */ + YYSYMBOL_KW_REINTERPRET_CAST = 126, /* KW_REINTERPRET_CAST */ + YYSYMBOL_KW_RESTRICT = 127, /* KW_RESTRICT */ + YYSYMBOL_KW_RETURN = 128, /* KW_RETURN */ + YYSYMBOL_KW_SHORT = 129, /* KW_SHORT */ + YYSYMBOL_KW_SIGNED = 130, /* KW_SIGNED */ + YYSYMBOL_KW_SIZEOF = 131, /* KW_SIZEOF */ + YYSYMBOL_KW_STATIC = 132, /* KW_STATIC */ + YYSYMBOL_KW_STATIC_ASSERT = 133, /* KW_STATIC_ASSERT */ + YYSYMBOL_KW_STATIC_CAST = 134, /* KW_STATIC_CAST */ + YYSYMBOL_KW_STRUCT = 135, /* KW_STRUCT */ + YYSYMBOL_KW_TEMPLATE = 136, /* KW_TEMPLATE */ + YYSYMBOL_KW_THREAD_LOCAL = 137, /* KW_THREAD_LOCAL */ + YYSYMBOL_KW_THROW = 138, /* KW_THROW */ + YYSYMBOL_KW_TRUE = 139, /* KW_TRUE */ + YYSYMBOL_KW_TRY = 140, /* KW_TRY */ + YYSYMBOL_KW_TYPEDEF = 141, /* KW_TYPEDEF */ + YYSYMBOL_KW_TYPEID = 142, /* KW_TYPEID */ + YYSYMBOL_KW_TYPENAME = 143, /* KW_TYPENAME */ + YYSYMBOL_KW_UNDERLYING_TYPE = 144, /* KW_UNDERLYING_TYPE */ + YYSYMBOL_KW_UNION = 145, /* KW_UNION */ + YYSYMBOL_KW_UNSIGNED = 146, /* KW_UNSIGNED */ + YYSYMBOL_KW_USING = 147, /* KW_USING */ + YYSYMBOL_KW_VIRTUAL = 148, /* KW_VIRTUAL */ + YYSYMBOL_KW_VOID = 149, /* KW_VOID */ + YYSYMBOL_KW_VOLATILE = 150, /* KW_VOLATILE */ + YYSYMBOL_KW_WCHAR_T = 151, /* KW_WCHAR_T */ + YYSYMBOL_KW_WHILE = 152, /* KW_WHILE */ + YYSYMBOL_START_CPP = 153, /* START_CPP */ + YYSYMBOL_START_CONST_EXPR = 154, /* START_CONST_EXPR */ + YYSYMBOL_START_TYPE = 155, /* START_TYPE */ + YYSYMBOL_156_ = 156, /* '{' */ + YYSYMBOL_157_ = 157, /* ',' */ + YYSYMBOL_158_ = 158, /* ';' */ + YYSYMBOL_159_ = 159, /* ':' */ + YYSYMBOL_160_ = 160, /* '=' */ + YYSYMBOL_161_ = 161, /* '?' */ + YYSYMBOL_162_ = 162, /* '|' */ + YYSYMBOL_163_ = 163, /* '^' */ + YYSYMBOL_164_ = 164, /* '&' */ + YYSYMBOL_165_ = 165, /* '<' */ + YYSYMBOL_166_ = 166, /* '>' */ + YYSYMBOL_167_ = 167, /* '+' */ + YYSYMBOL_168_ = 168, /* '-' */ + YYSYMBOL_169_ = 169, /* '*' */ + YYSYMBOL_170_ = 170, /* '/' */ + YYSYMBOL_171_ = 171, /* '%' */ + YYSYMBOL_172_ = 172, /* '~' */ + YYSYMBOL_173_ = 173, /* '.' */ + YYSYMBOL_174_ = 174, /* '(' */ + YYSYMBOL_175_ = 175, /* '[' */ + YYSYMBOL_176_ = 176, /* ')' */ + YYSYMBOL_177_ = 177, /* '}' */ + YYSYMBOL_178_ = 178, /* '!' */ + YYSYMBOL_179_ = 179, /* ']' */ + YYSYMBOL_YYACCEPT = 180, /* $accept */ + YYSYMBOL_grammar = 181, /* grammar */ + YYSYMBOL_cpp = 182, /* cpp */ + YYSYMBOL_183_1 = 183, /* $@1 */ + YYSYMBOL_constructor_inits = 184, /* constructor_inits */ + YYSYMBOL_constructor_init = 185, /* constructor_init */ + YYSYMBOL_extern_c = 186, /* extern_c */ + YYSYMBOL_187_2 = 187, /* $@2 */ + YYSYMBOL_declaration = 188, /* declaration */ + YYSYMBOL_friend_declaration = 189, /* friend_declaration */ + YYSYMBOL_190_3 = 190, /* $@3 */ + YYSYMBOL_storage_class = 191, /* storage_class */ + YYSYMBOL_optional_attributes = 192, /* optional_attributes */ + YYSYMBOL_attribute_specifiers = 193, /* attribute_specifiers */ + YYSYMBOL_attribute_specifier = 194, /* attribute_specifier */ + YYSYMBOL_type_like_declaration = 195, /* type_like_declaration */ + YYSYMBOL_196_4 = 196, /* $@4 */ + YYSYMBOL_197_5 = 197, /* $@5 */ + YYSYMBOL_multiple_instance_identifiers = 198, /* multiple_instance_identifiers */ + YYSYMBOL_typedef_declaration = 199, /* typedef_declaration */ + YYSYMBOL_200_6 = 200, /* $@6 */ + YYSYMBOL_typedef_instance_identifiers = 201, /* typedef_instance_identifiers */ + YYSYMBOL_constructor_prototype = 202, /* constructor_prototype */ + YYSYMBOL_203_7 = 203, /* $@7 */ + YYSYMBOL_204_8 = 204, /* $@8 */ + YYSYMBOL_205_9 = 205, /* $@9 */ + YYSYMBOL_function_prototype = 206, /* function_prototype */ + YYSYMBOL_207_10 = 207, /* $@10 */ + YYSYMBOL_208_11 = 208, /* $@11 */ + YYSYMBOL_209_12 = 209, /* $@12 */ + YYSYMBOL_210_13 = 210, /* $@13 */ + YYSYMBOL_211_14 = 211, /* $@14 */ + YYSYMBOL_function_post = 212, /* function_post */ + YYSYMBOL_function_operator = 213, /* function_operator */ + YYSYMBOL_more_template_declaration = 214, /* more_template_declaration */ + YYSYMBOL_template_declaration = 215, /* template_declaration */ + YYSYMBOL_216_15 = 216, /* $@15 */ + YYSYMBOL_template_formal_parameters = 217, /* template_formal_parameters */ + YYSYMBOL_template_nonempty_formal_parameters = 218, /* template_nonempty_formal_parameters */ + YYSYMBOL_typename_keyword = 219, /* typename_keyword */ + YYSYMBOL_template_formal_parameter = 220, /* template_formal_parameter */ + YYSYMBOL_template_formal_parameter_type = 221, /* template_formal_parameter_type */ + YYSYMBOL_instance_identifier = 222, /* instance_identifier */ + YYSYMBOL_223_16 = 223, /* $@16 */ + YYSYMBOL_instance_identifier_and_maybe_trailing_return_type = 224, /* instance_identifier_and_maybe_trailing_return_type */ + YYSYMBOL_maybe_trailing_return_type = 225, /* maybe_trailing_return_type */ + YYSYMBOL_maybe_comma_identifier = 226, /* maybe_comma_identifier */ + YYSYMBOL_function_parameter_list = 227, /* function_parameter_list */ + YYSYMBOL_function_parameters = 228, /* function_parameters */ + YYSYMBOL_formal_parameter_list = 229, /* formal_parameter_list */ + YYSYMBOL_formal_parameters = 230, /* formal_parameters */ + YYSYMBOL_template_parameter_maybe_initialize = 231, /* template_parameter_maybe_initialize */ + YYSYMBOL_maybe_initialize = 232, /* maybe_initialize */ + YYSYMBOL_maybe_initialize_or_constructor_body = 233, /* maybe_initialize_or_constructor_body */ + YYSYMBOL_maybe_initialize_or_function_body = 234, /* maybe_initialize_or_function_body */ + YYSYMBOL_structure_init = 235, /* structure_init */ + YYSYMBOL_structure_init_body = 236, /* structure_init_body */ + YYSYMBOL_function_parameter = 237, /* function_parameter */ + YYSYMBOL_formal_parameter = 238, /* formal_parameter */ + YYSYMBOL_not_paren_formal_parameter_identifier = 239, /* not_paren_formal_parameter_identifier */ + YYSYMBOL_formal_parameter_identifier = 240, /* formal_parameter_identifier */ + YYSYMBOL_parameter_pack_identifier = 241, /* parameter_pack_identifier */ + YYSYMBOL_not_paren_empty_instance_identifier = 242, /* not_paren_empty_instance_identifier */ + YYSYMBOL_empty_instance_identifier = 243, /* empty_instance_identifier */ + YYSYMBOL_type = 244, /* type */ + YYSYMBOL_type_pack = 245, /* type_pack */ + YYSYMBOL_type_decl = 246, /* type_decl */ + YYSYMBOL_predefined_type = 247, /* predefined_type */ + YYSYMBOL_var_type_decl = 248, /* var_type_decl */ + YYSYMBOL_full_type = 249, /* full_type */ + YYSYMBOL_anonymous_struct = 250, /* anonymous_struct */ + YYSYMBOL_251_17 = 251, /* $@17 */ + YYSYMBOL_named_struct = 252, /* named_struct */ + YYSYMBOL_253_18 = 253, /* $@18 */ + YYSYMBOL_maybe_final = 254, /* maybe_final */ + YYSYMBOL_maybe_class_derivation = 255, /* maybe_class_derivation */ + YYSYMBOL_class_derivation = 256, /* class_derivation */ + YYSYMBOL_base_specification = 257, /* base_specification */ + YYSYMBOL_enum = 258, /* enum */ + YYSYMBOL_259_19 = 259, /* $@19 */ + YYSYMBOL_enum_decl = 260, /* enum_decl */ + YYSYMBOL_enum_element_type = 261, /* enum_element_type */ + YYSYMBOL_enum_body_trailing_comma = 262, /* enum_body_trailing_comma */ + YYSYMBOL_enum_body = 263, /* enum_body */ + YYSYMBOL_enum_keyword = 264, /* enum_keyword */ + YYSYMBOL_struct_keyword = 265, /* struct_keyword */ + YYSYMBOL_namespace_declaration = 266, /* namespace_declaration */ + YYSYMBOL_267_20 = 267, /* $@20 */ + YYSYMBOL_268_21 = 268, /* $@21 */ + YYSYMBOL_using_declaration = 269, /* using_declaration */ + YYSYMBOL_simple_type = 270, /* simple_type */ + YYSYMBOL_simple_int_type = 271, /* simple_int_type */ + YYSYMBOL_simple_float_type = 272, /* simple_float_type */ + YYSYMBOL_simple_void_type = 273, /* simple_void_type */ + YYSYMBOL_code = 274, /* code */ + YYSYMBOL_275_22 = 275, /* $@22 */ + YYSYMBOL_code_block = 276, /* code_block */ + YYSYMBOL_element = 277, /* element */ + YYSYMBOL_optional_const_expr = 278, /* optional_const_expr */ + YYSYMBOL_optional_const_expr_comma = 279, /* optional_const_expr_comma */ + YYSYMBOL_const_expr_comma = 280, /* const_expr_comma */ + YYSYMBOL_no_angle_bracket_const_expr = 281, /* no_angle_bracket_const_expr */ + YYSYMBOL_const_expr = 282, /* const_expr */ + YYSYMBOL_const_operand = 283, /* const_operand */ + YYSYMBOL_formal_const_expr = 284, /* formal_const_expr */ + YYSYMBOL_formal_const_operand = 285, /* formal_const_operand */ + YYSYMBOL_capture_list = 286, /* capture_list */ + YYSYMBOL_capture = 287, /* capture */ + YYSYMBOL_class_derivation_name = 288, /* class_derivation_name */ + YYSYMBOL_name = 289, /* name */ + YYSYMBOL_name_no_final = 290, /* name_no_final */ + YYSYMBOL_string_literal = 291, /* string_literal */ + YYSYMBOL_empty = 292 /* empty */ }; typedef enum yysymbol_kind_t yysymbol_kind_t; @@ -918,21 +920,21 @@ union yyalloc #endif /* !YYCOPY_NEEDED */ /* YYFINAL -- State number of the termination state. */ -#define YYFINAL 108 +#define YYFINAL 109 /* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 7071 +#define YYLAST 6863 /* YYNTOKENS -- Number of terminals. */ -#define YYNTOKENS 178 +#define YYNTOKENS 180 /* YYNNTS -- Number of nonterminals. */ #define YYNNTS 113 /* YYNRULES -- Number of rules. */ -#define YYNRULES 782 +#define YYNRULES 789 /* YYNSTATES -- Number of states. */ -#define YYNSTATES 1671 +#define YYNSTATES 1678 /* YYMAXUTOK -- Last valid token kind. */ -#define YYMAXUTOK 408 +#define YYMAXUTOK 410 /* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM @@ -949,16 +951,16 @@ static const yytype_uint8 yytranslate[] = 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 176, 2, 2, 2, 169, 162, 2, - 172, 174, 167, 165, 155, 166, 171, 168, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 157, 156, - 163, 158, 164, 159, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 178, 2, 2, 2, 171, 164, 2, + 174, 176, 169, 167, 157, 168, 173, 170, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 159, 158, + 165, 160, 166, 161, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 173, 2, 177, 161, 2, 2, 2, 2, 2, + 2, 175, 2, 179, 163, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 154, 160, 175, 170, 2, 2, 2, + 2, 2, 2, 156, 162, 177, 172, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, @@ -986,92 +988,93 @@ static const yytype_uint8 yytranslate[] = 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, - 145, 146, 147, 148, 149, 150, 151, 152, 153 + 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, + 155 }; #if YYDEBUG /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ static const yytype_int16 yyrline[] = { - 0, 464, 464, 465, 469, 476, 477, 484, 483, 494, - 495, 499, 503, 507, 520, 519, 531, 532, 533, 534, - 535, 536, 537, 550, 559, 563, 571, 575, 579, 600, - 627, 648, 677, 713, 756, 768, 789, 825, 859, 881, - 917, 939, 950, 964, 963, 978, 982, 987, 991, 1002, - 1006, 1010, 1014, 1018, 1027, 1031, 1035, 1039, 1043, 1047, - 1051, 1055, 1059, 1066, 1070, 1075, 1083, 1088, 1096, 1100, - 1108, 1113, 1122, 1121, 1137, 1147, 1146, 1163, 1171, 1179, - 1191, 1208, 1207, 1222, 1237, 1247, 1263, 1262, 1305, 1304, - 1333, 1332, 1370, 1369, 1401, 1400, 1420, 1419, 1441, 1440, - 1473, 1472, 1499, 1512, 1516, 1520, 1524, 1528, 1537, 1541, - 1545, 1549, 1553, 1558, 1563, 1567, 1571, 1578, 1582, 1586, - 1590, 1594, 1598, 1602, 1606, 1610, 1614, 1618, 1622, 1626, - 1630, 1634, 1638, 1642, 1646, 1650, 1654, 1658, 1662, 1666, - 1670, 1674, 1678, 1682, 1686, 1690, 1694, 1698, 1702, 1706, - 1710, 1714, 1718, 1722, 1726, 1730, 1734, 1741, 1742, 1743, - 1747, 1749, 1748, 1756, 1757, 1761, 1762, 1766, 1772, 1781, - 1782, 1786, 1790, 1794, 1798, 1804, 1810, 1816, 1823, 1828, - 1837, 1841, 1846, 1854, 1866, 1870, 1884, 1899, 1904, 1909, - 1914, 1919, 1924, 1929, 1934, 1940, 1939, 1970, 1980, 1990, - 1994, 1998, 2007, 2011, 2019, 2023, 2028, 2032, 2037, 2045, - 2050, 2058, 2062, 2067, 2071, 2076, 2084, 2089, 2097, 2101, - 2108, 2112, 2119, 2123, 2127, 2131, 2135, 2142, 2146, 2150, - 2154, 2158, 2162, 2169, 2170, 2171, 2175, 2178, 2179, 2180, - 2184, 2190, 2197, 2204, 2210, 2217, 2224, 2236, 2240, 2250, - 2254, 2258, 2263, 2268, 2273, 2278, 2283, 2288, 2296, 2300, - 2304, 2309, 2314, 2319, 2324, 2329, 2334, 2339, 2345, 2353, - 2358, 2363, 2368, 2373, 2378, 2383, 2388, 2393, 2398, 2404, - 2412, 2416, 2421, 2426, 2431, 2436, 2441, 2446, 2451, 2456, - 2464, 2468, 2473, 2478, 2483, 2488, 2493, 2498, 2503, 2508, - 2513, 2519, 2526, 2533, 2543, 2547, 2555, 2559, 2563, 2567, - 2571, 2587, 2603, 2612, 2616, 2626, 2633, 2644, 2648, 2656, - 2660, 2664, 2668, 2672, 2688, 2704, 2722, 2731, 2735, 2745, - 2752, 2756, 2764, 2768, 2784, 2800, 2809, 2819, 2826, 2830, - 2838, 2842, 2847, 2851, 2860, 2859, 2884, 2883, 2913, 2914, - 2921, 2922, 2926, 2927, 2931, 2935, 2939, 2943, 2947, 2951, - 2955, 2959, 2963, 2967, 2975, 2974, 2991, 2995, 2999, 3004, - 3012, 3016, 3023, 3024, 3029, 3036, 3037, 3042, 3050, 3054, - 3058, 3065, 3069, 3073, 3081, 3080, 3103, 3102, 3125, 3126, - 3130, 3136, 3143, 3149, 3158, 3159, 3160, 3164, 3168, 3172, - 3176, 3180, 3184, 3188, 3193, 3198, 3203, 3208, 3212, 3217, - 3226, 3231, 3239, 3243, 3247, 3255, 3265, 3265, 3275, 3276, - 3280, 3281, 3282, 3283, 3284, 3285, 3286, 3287, 3288, 3289, - 3290, 3291, 3291, 3291, 3292, 3292, 3292, 3292, 3292, 3293, - 3293, 3293, 3293, 3293, 3294, 3294, 3294, 3295, 3295, 3295, - 3295, 3295, 3296, 3296, 3296, 3296, 3296, 3297, 3297, 3298, - 3298, 3298, 3298, 3298, 3299, 3299, 3299, 3299, 3299, 3300, - 3300, 3300, 3300, 3300, 3301, 3301, 3301, 3301, 3301, 3302, - 3302, 3302, 3302, 3302, 3303, 3303, 3303, 3303, 3303, 3304, - 3304, 3304, 3304, 3304, 3304, 3305, 3305, 3305, 3305, 3305, - 3306, 3306, 3306, 3306, 3307, 3307, 3307, 3307, 3308, 3308, - 3308, 3308, 3308, 3309, 3309, 3309, 3309, 3310, 3310, 3310, - 3310, 3310, 3311, 3311, 3311, 3311, 3312, 3312, 3312, 3312, - 3312, 3313, 3313, 3316, 3316, 3316, 3316, 3316, 3316, 3316, - 3316, 3316, 3316, 3316, 3317, 3317, 3317, 3317, 3317, 3317, - 3317, 3317, 3317, 3317, 3318, 3318, 3322, 3326, 3333, 3337, - 3344, 3348, 3355, 3359, 3363, 3367, 3371, 3375, 3379, 3383, - 3387, 3391, 3395, 3399, 3403, 3407, 3411, 3415, 3419, 3423, - 3427, 3431, 3435, 3439, 3443, 3447, 3451, 3455, 3459, 3463, - 3467, 3471, 3475, 3479, 3483, 3487, 3491, 3495, 3499, 3503, - 3507, 3511, 3519, 3523, 3527, 3531, 3535, 3539, 3543, 3553, - 3563, 3569, 3575, 3581, 3587, 3593, 3599, 3605, 3612, 3619, - 3626, 3633, 3639, 3645, 3649, 3653, 3657, 3661, 3665, 3669, - 3680, 3691, 3695, 3699, 3703, 3707, 3711, 3715, 3719, 3723, - 3727, 3731, 3735, 3739, 3743, 3747, 3751, 3755, 3759, 3763, - 3767, 3771, 3775, 3779, 3783, 3787, 3791, 3795, 3799, 3803, - 3807, 3811, 3815, 3819, 3826, 3830, 3834, 3838, 3842, 3846, - 3850, 3854, 3858, 3864, 3870, 3874, 3881, 3889, 3893, 3897, - 3901, 3905, 3909, 3913, 3917, 3921, 3925, 3929, 3933, 3937, - 3941, 3945, 3949, 3953, 3957, 3971, 3975, 3979, 3983, 3987, - 3991, 3995, 3999, 4003, 4007, 4011, 4015, 4019, 4030, 4041, - 4045, 4049, 4053, 4057, 4061, 4065, 4069, 4073, 4077, 4081, - 4085, 4089, 4093, 4097, 4101, 4105, 4109, 4113, 4117, 4121, - 4125, 4129, 4133, 4137, 4141, 4145, 4149, 4153, 4157, 4161, - 4168, 4172, 4176, 4180, 4184, 4188, 4192, 4196, 4200, 4206, - 4212, 4220, 4224, 4228, 4232, 4239, 4249, 4255, 4261, 4271, - 4283, 4291, 4295, 4325, 4329, 4333, 4337, 4341, 4345, 4351, - 4355, 4359, 4363, 4367, 4378, 4382, 4386, 4390, 4398, 4402, - 4406, 4412, 4423 + 0, 466, 466, 467, 471, 478, 479, 486, 485, 496, + 497, 501, 505, 509, 522, 521, 533, 534, 535, 536, + 537, 538, 539, 552, 561, 565, 573, 577, 581, 602, + 629, 650, 679, 715, 758, 770, 791, 827, 861, 883, + 919, 941, 952, 966, 965, 980, 984, 989, 993, 1004, + 1008, 1012, 1016, 1020, 1029, 1033, 1037, 1041, 1045, 1049, + 1053, 1057, 1061, 1068, 1072, 1077, 1085, 1090, 1098, 1102, + 1110, 1115, 1124, 1123, 1139, 1149, 1148, 1165, 1173, 1181, + 1193, 1210, 1209, 1224, 1239, 1249, 1265, 1264, 1307, 1306, + 1335, 1334, 1372, 1371, 1403, 1402, 1422, 1421, 1443, 1442, + 1475, 1474, 1501, 1514, 1518, 1522, 1526, 1530, 1539, 1543, + 1547, 1551, 1555, 1560, 1565, 1569, 1573, 1580, 1584, 1588, + 1592, 1596, 1600, 1604, 1608, 1612, 1616, 1620, 1624, 1628, + 1632, 1636, 1640, 1644, 1648, 1652, 1656, 1660, 1664, 1668, + 1672, 1676, 1680, 1684, 1688, 1692, 1696, 1700, 1704, 1708, + 1712, 1716, 1720, 1724, 1728, 1732, 1736, 1743, 1744, 1745, + 1749, 1751, 1750, 1758, 1759, 1763, 1764, 1768, 1774, 1783, + 1784, 1788, 1792, 1796, 1800, 1806, 1812, 1818, 1825, 1830, + 1836, 1843, 1852, 1856, 1861, 1869, 1881, 1885, 1899, 1914, + 1919, 1924, 1929, 1934, 1939, 1944, 1949, 1955, 1954, 1985, + 1995, 2005, 2009, 2013, 2022, 2026, 2034, 2038, 2043, 2047, + 2052, 2060, 2065, 2073, 2077, 2082, 2086, 2091, 2099, 2104, + 2112, 2116, 2123, 2127, 2134, 2138, 2142, 2146, 2150, 2157, + 2161, 2165, 2169, 2173, 2177, 2184, 2185, 2186, 2190, 2193, + 2194, 2195, 2199, 2211, 2230, 2234, 2244, 2248, 2252, 2257, + 2262, 2267, 2272, 2277, 2282, 2287, 2295, 2299, 2303, 2308, + 2313, 2318, 2323, 2328, 2333, 2338, 2343, 2349, 2357, 2362, + 2367, 2372, 2377, 2382, 2387, 2392, 2397, 2402, 2407, 2413, + 2421, 2425, 2430, 2435, 2440, 2445, 2450, 2455, 2460, 2465, + 2470, 2478, 2482, 2487, 2492, 2497, 2502, 2507, 2512, 2517, + 2522, 2527, 2532, 2538, 2545, 2552, 2562, 2566, 2574, 2578, + 2582, 2586, 2590, 2606, 2622, 2631, 2635, 2645, 2649, 2656, + 2667, 2671, 2679, 2683, 2687, 2691, 2695, 2711, 2727, 2745, + 2754, 2758, 2768, 2772, 2779, 2783, 2791, 2795, 2811, 2827, + 2836, 2846, 2850, 2857, 2861, 2869, 2873, 2878, 2882, 2891, + 2890, 2915, 2914, 2944, 2945, 2952, 2953, 2957, 2958, 2962, + 2966, 2970, 2974, 2978, 2982, 2986, 2990, 2994, 2998, 3006, + 3005, 3022, 3026, 3030, 3035, 3043, 3047, 3054, 3055, 3060, + 3067, 3068, 3073, 3081, 3085, 3089, 3096, 3100, 3104, 3112, + 3111, 3134, 3133, 3156, 3157, 3161, 3167, 3174, 3180, 3189, + 3190, 3191, 3195, 3199, 3203, 3207, 3211, 3215, 3219, 3224, + 3229, 3234, 3239, 3243, 3248, 3257, 3262, 3270, 3274, 3278, + 3286, 3296, 3296, 3306, 3307, 3311, 3312, 3313, 3314, 3315, + 3316, 3317, 3318, 3319, 3320, 3321, 3322, 3322, 3322, 3323, + 3323, 3323, 3323, 3323, 3324, 3324, 3324, 3324, 3324, 3325, + 3325, 3325, 3326, 3326, 3326, 3326, 3326, 3327, 3327, 3327, + 3327, 3327, 3328, 3328, 3329, 3329, 3329, 3329, 3329, 3330, + 3330, 3330, 3330, 3330, 3330, 3331, 3331, 3331, 3331, 3331, + 3332, 3332, 3332, 3332, 3332, 3333, 3333, 3333, 3333, 3333, + 3334, 3334, 3334, 3334, 3334, 3335, 3335, 3335, 3335, 3335, + 3335, 3336, 3336, 3336, 3336, 3336, 3337, 3337, 3337, 3337, + 3338, 3338, 3338, 3338, 3339, 3339, 3339, 3339, 3339, 3339, + 3340, 3340, 3340, 3340, 3341, 3341, 3341, 3341, 3341, 3342, + 3342, 3342, 3342, 3343, 3343, 3343, 3343, 3343, 3344, 3344, + 3347, 3347, 3347, 3347, 3347, 3347, 3347, 3347, 3347, 3347, + 3347, 3348, 3348, 3348, 3348, 3348, 3348, 3348, 3348, 3348, + 3348, 3349, 3349, 3353, 3357, 3364, 3368, 3375, 3379, 3386, + 3390, 3394, 3398, 3402, 3406, 3410, 3414, 3418, 3422, 3426, + 3430, 3434, 3438, 3442, 3446, 3450, 3454, 3458, 3462, 3466, + 3470, 3474, 3478, 3482, 3486, 3490, 3494, 3498, 3502, 3506, + 3510, 3514, 3518, 3522, 3526, 3530, 3534, 3538, 3542, 3550, + 3554, 3558, 3562, 3566, 3570, 3574, 3584, 3594, 3600, 3606, + 3612, 3618, 3624, 3630, 3636, 3643, 3650, 3657, 3664, 3670, + 3676, 3680, 3684, 3688, 3692, 3696, 3700, 3711, 3722, 3726, + 3730, 3734, 3738, 3742, 3746, 3750, 3754, 3758, 3762, 3766, + 3770, 3774, 3778, 3782, 3786, 3790, 3794, 3798, 3802, 3806, + 3810, 3814, 3818, 3822, 3826, 3830, 3834, 3838, 3842, 3846, + 3850, 3857, 3861, 3865, 3869, 3873, 3877, 3881, 3885, 3889, + 3895, 3901, 3905, 3912, 3920, 3924, 3928, 3932, 3936, 3940, + 3944, 3948, 3952, 3956, 3960, 3964, 3968, 3972, 3976, 3980, + 3984, 3988, 4002, 4006, 4010, 4014, 4018, 4022, 4026, 4030, + 4034, 4038, 4042, 4046, 4050, 4061, 4072, 4076, 4080, 4084, + 4088, 4092, 4096, 4100, 4104, 4108, 4112, 4116, 4120, 4124, + 4128, 4132, 4136, 4140, 4144, 4148, 4152, 4156, 4160, 4164, + 4168, 4172, 4176, 4180, 4184, 4188, 4192, 4199, 4203, 4207, + 4211, 4215, 4219, 4223, 4227, 4231, 4237, 4243, 4251, 4255, + 4259, 4263, 4270, 4280, 4286, 4292, 4302, 4314, 4322, 4326, + 4356, 4360, 4364, 4368, 4372, 4376, 4382, 4386, 4390, 4394, + 4398, 4409, 4413, 4417, 4421, 4429, 4433, 4437, 4443, 4454 }; #endif @@ -1098,43 +1101,45 @@ static const char *const yytname[] = "DIVIDEEQUAL", "MODEQUAL", "PLUSEQUAL", "MINUSEQUAL", "OREQUAL", "ANDEQUAL", "XOREQUAL", "LSHIFTEQUAL", "RSHIFTEQUAL", "ATTR_LEFT", "ATTR_RIGHT", "KW_ALIGNAS", "KW_ALIGNOF", "KW_AUTO", "KW_BEGIN_PUBLISH", - "KW_BLOCKING", "KW_BOOL", "KW_CATCH", "KW_CHAR", "KW_CHAR8_T", - "KW_CHAR16_T", "KW_CHAR32_T", "KW_CLASS", "KW_CONST", "KW_CONSTEVAL", - "KW_CONSTEXPR", "KW_CONSTINIT", "KW_CONST_CAST", "KW_DECLTYPE", - "KW_DEFAULT", "KW_DELETE", "KW_DOUBLE", "KW_DYNAMIC_CAST", "KW_ELSE", - "KW_END_PUBLISH", "KW_ENUM", "KW_EXTENSION", "KW_EXTERN", "KW_EXPLICIT", - "KW_EXPLICIT_LPAREN", "KW_PUBLISHED", "KW_FALSE", "KW_FINAL", "KW_FLOAT", - "KW_FRIEND", "KW_FOR", "KW_GOTO", "KW_HAS_VIRTUAL_DESTRUCTOR", "KW_IF", - "KW_INLINE", "KW_INT", "KW_IS_ABSTRACT", "KW_IS_BASE_OF", "KW_IS_CLASS", - "KW_IS_CONSTRUCTIBLE", "KW_IS_CONVERTIBLE_TO", "KW_IS_DESTRUCTIBLE", - "KW_IS_EMPTY", "KW_IS_ENUM", "KW_IS_FINAL", "KW_IS_FUNDAMENTAL", - "KW_IS_POD", "KW_IS_POLYMORPHIC", "KW_IS_STANDARD_LAYOUT", - "KW_IS_TRIVIAL", "KW_IS_TRIVIALLY_COPYABLE", "KW_IS_UNION", "KW_LONG", + "KW_BLOCKING", "KW_BOOL", "KW_BUILTIN_VA_LIST", "KW_CATCH", "KW_CHAR", + "KW_CHAR8_T", "KW_CHAR16_T", "KW_CHAR32_T", "KW_CLASS", "KW_CONST", + "KW_CONSTEVAL", "KW_CONSTEXPR", "KW_CONSTINIT", "KW_CONST_CAST", + "KW_DECLTYPE", "KW_DEFAULT", "KW_DELETE", "KW_DOUBLE", "KW_DYNAMIC_CAST", + "KW_ELSE", "KW_END_PUBLISH", "KW_ENUM", "KW_EXTENSION", "KW_EXTERN", + "KW_EXPLICIT", "KW_EXPLICIT_LPAREN", "KW_PUBLISHED", "KW_FALSE", + "KW_FINAL", "KW_FLOAT", "KW_FRIEND", "KW_FOR", "KW_GOTO", + "KW_HAS_VIRTUAL_DESTRUCTOR", "KW_IF", "KW_INLINE", "KW_INT", + "KW_IS_ABSTRACT", "KW_IS_BASE_OF", "KW_IS_CLASS", "KW_IS_CONSTRUCTIBLE", + "KW_IS_CONVERTIBLE_TO", "KW_IS_DESTRUCTIBLE", "KW_IS_EMPTY", + "KW_IS_ENUM", "KW_IS_FINAL", "KW_IS_FUNDAMENTAL", "KW_IS_POD", + "KW_IS_POLYMORPHIC", "KW_IS_STANDARD_LAYOUT", "KW_IS_TRIVIAL", + "KW_IS_TRIVIALLY_COPYABLE", "KW_IS_UNION", "KW_LONG", "KW_MAKE_MAP_KEYS_SEQ", "KW_MAKE_MAP_PROPERTY", "KW_MAKE_PROPERTY", "KW_MAKE_PROPERTY2", "KW_MAKE_SEQ", "KW_MAKE_SEQ_PROPERTY", "KW_MUTABLE", "KW_NAMESPACE", "KW_NEW", "KW_NOEXCEPT", "KW_NOEXCEPT_LPAREN", "KW_NULLPTR", "KW_OPERATOR", "KW_OVERRIDE", "KW_PRIVATE", "KW_PROTECTED", - "KW_PUBLIC", "KW_REGISTER", "KW_REINTERPRET_CAST", "KW_RETURN", - "KW_SHORT", "KW_SIGNED", "KW_SIZEOF", "KW_STATIC", "KW_STATIC_ASSERT", - "KW_STATIC_CAST", "KW_STRUCT", "KW_TEMPLATE", "KW_THREAD_LOCAL", - "KW_THROW", "KW_TRUE", "KW_TRY", "KW_TYPEDEF", "KW_TYPEID", - "KW_TYPENAME", "KW_UNDERLYING_TYPE", "KW_UNION", "KW_UNSIGNED", - "KW_USING", "KW_VIRTUAL", "KW_VOID", "KW_VOLATILE", "KW_WCHAR_T", - "KW_WHILE", "START_CPP", "START_CONST_EXPR", "START_TYPE", "'{'", "','", - "';'", "':'", "'='", "'?'", "'|'", "'^'", "'&'", "'<'", "'>'", "'+'", - "'-'", "'*'", "'/'", "'%'", "'~'", "'.'", "'('", "'['", "')'", "'}'", - "'!'", "']'", "$accept", "grammar", "cpp", "$@1", "constructor_inits", - "constructor_init", "extern_c", "$@2", "declaration", - "friend_declaration", "$@3", "storage_class", "optional_attributes", - "attribute_specifiers", "attribute_specifier", "type_like_declaration", - "$@4", "$@5", "multiple_instance_identifiers", "typedef_declaration", - "$@6", "typedef_instance_identifiers", "constructor_prototype", "$@7", - "$@8", "$@9", "function_prototype", "$@10", "$@11", "$@12", "$@13", - "$@14", "function_post", "function_operator", - "more_template_declaration", "template_declaration", "$@15", - "template_formal_parameters", "template_nonempty_formal_parameters", - "typename_keyword", "template_formal_parameter", - "template_formal_parameter_type", "instance_identifier", "$@16", + "KW_PUBLIC", "KW_REGISTER", "KW_REINTERPRET_CAST", "KW_RESTRICT", + "KW_RETURN", "KW_SHORT", "KW_SIGNED", "KW_SIZEOF", "KW_STATIC", + "KW_STATIC_ASSERT", "KW_STATIC_CAST", "KW_STRUCT", "KW_TEMPLATE", + "KW_THREAD_LOCAL", "KW_THROW", "KW_TRUE", "KW_TRY", "KW_TYPEDEF", + "KW_TYPEID", "KW_TYPENAME", "KW_UNDERLYING_TYPE", "KW_UNION", + "KW_UNSIGNED", "KW_USING", "KW_VIRTUAL", "KW_VOID", "KW_VOLATILE", + "KW_WCHAR_T", "KW_WHILE", "START_CPP", "START_CONST_EXPR", "START_TYPE", + "'{'", "','", "';'", "':'", "'='", "'?'", "'|'", "'^'", "'&'", "'<'", + "'>'", "'+'", "'-'", "'*'", "'/'", "'%'", "'~'", "'.'", "'('", "'['", + "')'", "'}'", "'!'", "']'", "$accept", "grammar", "cpp", "$@1", + "constructor_inits", "constructor_init", "extern_c", "$@2", + "declaration", "friend_declaration", "$@3", "storage_class", + "optional_attributes", "attribute_specifiers", "attribute_specifier", + "type_like_declaration", "$@4", "$@5", "multiple_instance_identifiers", + "typedef_declaration", "$@6", "typedef_instance_identifiers", + "constructor_prototype", "$@7", "$@8", "$@9", "function_prototype", + "$@10", "$@11", "$@12", "$@13", "$@14", "function_post", + "function_operator", "more_template_declaration", "template_declaration", + "$@15", "template_formal_parameters", + "template_nonempty_formal_parameters", "typename_keyword", + "template_formal_parameter", "template_formal_parameter_type", + "instance_identifier", "$@16", "instance_identifier_and_maybe_trailing_return_type", "maybe_trailing_return_type", "maybe_comma_identifier", "function_parameter_list", "function_parameters", @@ -1167,12 +1172,12 @@ yysymbol_name (yysymbol_kind_t yysymbol) } #endif -#define YYPACT_NINF (-1070) +#define YYPACT_NINF (-1062) #define yypact_value_is_default(Yyn) \ ((Yyn) == YYPACT_NINF) -#define YYTABLE_NINF (-778) +#define YYTABLE_NINF (-785) #define yytable_value_is_error(Yyn) \ 0 @@ -1181,174 +1186,174 @@ yysymbol_name (yysymbol_kind_t yysymbol) STATE-NUM. */ static const yytype_int16 yypact[] = { - 383, -1070, 4549, 6313, 82, 61, -1070, -1070, -1070, -1070, - -1070, -1070, -1070, -1070, -76, -68, -58, -52, -36, 11, - 32, 76, 80, 85, -1070, -1070, 96, 100, 104, 108, - 126, 137, 148, 159, 165, 168, 171, 179, 182, 194, - 205, 215, 230, 255, 264, 268, 6577, 4549, -1070, -1070, - 303, 279, 302, 3413, 318, -1070, 325, 337, 339, 4549, - 4549, 4549, 4549, 4549, 2336, 1461, 4549, 4426, -1070, 319, - -1070, -1070, -1070, -1070, -1070, -1070, -1070, -1070, -1070, 6432, - 341, -1070, 7, -1070, -1070, 6922, 6200, 6200, -1070, 1698, - 346, -1070, 6200, -1070, -1070, 180, 180, -1070, -1070, -1070, - -1070, -1070, 446, 446, -1070, -1070, -1070, -1070, -1070, 2236, - 354, -67, -1070, 4549, 4549, 6313, 4549, 4549, 4549, 4549, - 4549, 6313, 4549, 6313, 4549, 6313, 4549, 6313, 6313, 6313, - 6313, 6313, 6313, 6313, 6313, 6313, 6313, 6313, 6313, 6313, - 6313, 6313, 6313, 4549, -1070, -1070, 365, 1698, 368, 370, - 446, 446, -1070, 5314, 6313, 4549, 4549, 378, 2336, 63, - 6313, 2336, 4549, 4549, 63, 63, 63, 63, 63, -76, - -58, -52, -36, 11, 32, 80, 96, 104, 2791, 3893, - 5236, 5873, 339, 89, -90, 4426, -1070, -1070, -1070, -1070, - -1070, -1070, -1070, -1070, -1070, -1070, -1070, -1070, 1698, 1698, - -74, 235, -1070, -1070, 63, 4549, 4549, 4549, 4549, 4549, - 4549, 4549, 4549, 4549, 4549, 4549, 4549, 4549, 4549, 4549, - 4549, 4549, 4549, 4549, 4549, 4549, 1698, 3555, 4549, -1070, - -1070, 180, 180, 3697, -1070, -1070, -1070, 6200, -1070, -1070, - -1070, -1070, 6313, -1070, 393, 772, 446, 180, 180, 446, - 446, 223, 398, -1070, 407, -1070, 427, 27, 1243, 1698, - 544, 440, 426, 3124, -1070, 6781, 430, 451, -1070, 434, - 435, 436, 439, 441, 445, 447, 437, 449, 450, 453, - 457, 458, 463, 470, 464, -72, 471, 465, 467, 468, - 473, 476, 483, 484, 485, 492, 493, 495, 498, 4549, - -1070, 6313, 4549, 1698, 1698, -1070, 480, 502, 503, 1698, - 504, 515, 507, 5335, 508, 510, 4549, 4549, -1070, 634, - -1070, 1631, 516, 4549, -1070, -1070, 1957, 4686, 4990, 4990, - 1977, 1977, 1054, 853, 853, -1070, 5629, 5804, 5821, 5883, - 1977, 1977, 277, 277, 63, 63, 63, -1070, -1070, -50, - 2563, -1070, -1070, 513, 5354, 517, 446, 446, 151, 398, - -1070, 398, -1070, 151, 151, -1070, 446, 446, 446, 6214, - 520, 33, -1070, 522, 4549, -1070, -1070, -1070, -1070, -1070, - 2052, 541, -9, -8, -4, 20, -1070, -1070, -1070, 542, - 446, 1698, 1329, -76, -1070, 534, 1698, 538, 543, -1070, - -1070, -1070, 446, 446, -1070, 5373, -1070, 6890, 6890, 6890, - 6890, 6890, -1070, 6890, 2485, 6890, 4549, 559, -1070, 6886, - 546, 547, 551, 553, 555, 556, 6890, 83, 576, 578, - 579, 6890, 6890, 557, 6703, 6890, 6890, 6701, 6890, 6890, - -1070, -1070, -1070, 2773, -1070, -1070, -1070, -1070, -1070, -1070, - -1070, -1070, -1070, -1070, -1070, -1070, -1070, 565, -1070, 567, - -1070, -1070, -1070, -1070, 6313, -1070, 6313, -1070, 6313, -1070, - -1070, -1070, -1070, -1070, -1070, -1070, -1070, -1070, -1070, -1070, - -1070, 5413, 568, 569, -1070, -1070, 573, -1070, -1070, 574, - 4691, 575, -1070, -1070, -1070, -1070, 63, 4426, -1070, 1698, - 235, 43, 6053, -1070, 4426, 4549, -1070, -1070, -1070, -1070, - -1070, 151, 580, 584, 1698, 446, 151, 151, 446, 446, - 581, -1070, 581, 581, 151, 151, 151, 6339, 446, 795, - 355, -1070, -1070, 84, 564, 4426, -1070, 1698, 577, -1070, - -1070, -1070, -1070, 2052, -1070, 674, 1698, -1070, -1070, -1070, - -1070, -1070, -1070, -1070, -1070, 585, 593, 595, -1070, -1070, - 6577, -1070, -1070, 597, 2161, 601, -1070, 594, 4549, 4549, - 4549, 4549, 2336, 4549, 591, 56, -1070, -1070, 4710, -1070, - 319, 598, 3839, -1070, 6313, 446, 2436, 1243, 446, 6074, - 6890, -1070, -1070, -1070, -1070, -1070, -1070, 6890, -1070, -1070, - -1070, 5432, -1070, 6781, 1796, -1070, 1698, 1698, 1698, 1698, - 1698, 1698, -1070, -1070, 1698, -1070, -1070, -1070, -1070, -1070, - 4549, -1070, 5059, -1070, 605, -1070, 5180, -1070, 1698, 1698, - 58, -1070, -1070, 307, 602, 6458, -1070, 1698, -1070, 213, - 617, -1070, 4549, 4549, 603, 604, 607, -1070, -1070, -1070, - 4549, -1070, 4549, -1070, 611, -1070, -1070, -1070, -1070, -1070, - -1070, 4549, -1070, 614, -1070, -1070, 741, 4426, 581, 446, - 446, 151, 581, 581, 151, 151, 4549, -15, 246, 283, - 6432, 795, 355, -1070, 620, 446, 795, 795, 446, 446, - 795, -83, 446, -1070, 621, 1698, 446, 355, 355, 446, - 446, 355, 9, 6053, -1070, -1070, 446, 446, -1070, 635, - 3, -1070, 633, -1070, 742, 6313, 6313, 6313, 626, 6313, - 628, 2336, 88, 6313, 2336, 63, 63, 63, 63, 627, - -48, 63, -1070, -1070, 1877, 4549, 4549, 4549, 4549, 4549, - 4549, 4549, 4549, 4549, 4549, 4549, 4549, 4549, 4549, 4549, - 4549, 4549, 4549, 4549, 4549, 4549, 1698, 3981, 4549, 629, - 5532, 630, -1070, -1070, 645, -1070, -1070, -1070, 6890, -1070, - -1070, 655, 656, 659, 660, 662, 664, 665, 50, 667, - 5254, 6121, 399, 650, 213, -1070, -1070, 668, 670, -1070, - 671, -1070, 49, 6670, 216, -1070, 663, 391, -1070, -1070, - 3271, -1070, -1070, 651, -11, -3, -1070, -1070, -1070, 5, - 150, -1070, 5591, 572, 6551, 683, -1070, 151, -1070, 581, - 581, 581, 661, 669, 672, 673, 795, 355, -83, 9, - 446, 795, 666, 666, 795, 795, 317, 4549, -1070, -1070, - 446, 446, 355, 678, 678, 355, 355, 328, 4549, -1070, - 741, 679, 161, -1070, 2448, 688, 691, -1070, 446, 681, - 692, 694, 4549, 695, 1698, 686, 698, 689, 5610, 4549, - -1070, -1070, -1070, 1957, 4686, 4990, 4990, 1977, 1977, 1054, - 853, 853, -1070, 5648, 5804, 5821, 5883, 1977, 1977, 277, - 277, 63, 63, 63, -1070, -1070, 206, 3143, -1070, -1070, - -1070, 2052, -1070, 87, -1070, 833, 854, 855, 856, 857, - 862, -1070, -1070, 397, 718, -1070, -1070, -1070, -1070, 6174, - -1070, 717, 736, 5128, -1070, 997, -1070, -1070, 54, -1070, - 651, -1070, -1070, 6313, 43, 722, 731, 651, 43, 216, - 732, 446, 216, 216, 446, 446, 51, 446, -1070, 91, - -1070, -1070, -1070, 1698, 101, -1070, 728, -1070, 748, 749, - 4123, 3716, 745, 446, 651, 5058, 651, 446, 446, 651, - -1070, 176, 400, 446, -1070, -1070, -1070, -1070, 6053, -1070, - -1070, 25, 6577, 180, -1070, 581, 446, 43, 43, 43, - -83, 9, -1070, -1070, 795, 666, 666, 666, 744, 740, - 355, -1070, 678, 678, 678, 750, 746, -1070, -1070, 4549, - 2803, 6664, 6679, 1698, 452, -1070, -1070, 906, -1070, 2448, - -1070, -1070, 753, 754, 755, 756, 757, 4691, 758, -1070, - -1070, 63, 4549, -1070, -1070, 635, -1070, -1070, 777, 220, - 779, 780, 781, 785, -1070, 48, -1070, 997, 6859, 6121, - 1698, 769, 783, 446, 997, 997, 446, 446, 997, 17, - 678, -1070, 400, 788, 773, 774, 651, 404, 778, 348, - 446, 216, 775, 775, 216, 216, -1070, 4549, -1070, -1070, - 43, 776, 409, -1070, -62, 797, 798, -1070, 2949, -1070, - -1070, -1070, 4123, 786, 800, 4426, -1070, -1070, 446, 651, - 395, 948, -1070, -1070, -1070, -1070, -1070, -1070, -1070, -1070, - -1070, -1070, -1070, -1070, -1070, -1070, -1070, -1070, -1070, -1070, - -1070, -1070, -1070, -1070, -1070, -1070, -1070, -1070, -1070, -1070, - -1070, -1070, -1070, -1070, -1070, -1070, -1070, -1070, -1070, 790, - 789, -1070, 446, 395, 651, 651, 413, 4549, -1070, 4549, - -1070, 3271, 814, -1070, -1070, 741, 799, -1070, 180, -1070, - 802, -1070, 806, 807, 809, -1070, -1070, 666, 43, 446, - 678, 43, 446, 4142, 2809, -1070, 2809, -1070, 2809, -1070, - -1070, 2809, 2809, 2809, -1070, 217, -1070, 4549, 4549, -1070, - 4549, -1070, 4549, 4426, 284, 962, 964, 828, 975, 817, - -1070, 982, 986, 988, 305, 843, 17, 678, -1070, -1070, - -1070, -1070, -1070, -1070, 6313, 446, 997, 997, 997, 4833, - -1070, -1070, 845, -1070, -1070, -1070, -1070, 418, 830, -1070, - -1070, 216, 775, 775, 775, 43, 826, 832, -1070, -1070, - 1698, 4549, 4549, -1070, -1070, -1070, -1070, -1070, -1070, -1070, - -1070, -1070, -1070, -1070, -1070, -1070, -1070, -1070, -1070, -1070, - -1070, -1070, -1070, -1070, -1070, -1070, -1070, -1070, -1070, -1070, - -1070, -1070, -1070, -1070, -1070, -1070, -1070, -1070, -1070, -1070, - -1070, -1070, -1070, -1070, -1070, -1070, -1070, -1070, -1070, -1070, - -1070, -1070, -1070, -1070, -1070, -1070, -1070, -1070, -1070, -1070, - -1070, -1070, -1070, -1070, -1070, -1070, -1070, -1070, -1070, -1070, - -1070, -1070, -1070, -1070, -1070, -1070, -1070, -1070, -1070, -1070, - -1070, -1070, -1070, -1070, -1070, -1070, -1070, -1070, -1070, -1070, - -1070, -1070, -1070, -1070, -1070, -1070, -1070, -1070, -1070, -1070, - -1070, -1070, -1070, -1070, -1070, -1070, -1070, -1070, -1070, -1070, - -1070, -1070, -1070, -1070, -1070, -1070, -1070, -1070, -1070, -1070, - -1070, -1070, -1070, -1070, -1070, -1070, -1070, -1070, -1070, -1070, - -1070, -1070, -1070, -1070, -1070, -1070, -1070, -1070, -1070, -1070, - -1070, -1070, 840, -1070, 4265, 651, 395, 446, -1070, -1070, - -1070, 395, 395, -1070, 4426, 1329, 846, 3716, 651, 874, - -1070, -1070, -1070, -1070, -1070, -1070, 858, -1070, 859, -1070, - -1070, -1070, -1070, -1070, -1070, -1070, -1070, -1070, 221, 224, - 226, 227, -1070, 860, 242, -1070, 875, 873, 249, 861, - 273, -1070, -1070, -1070, -1070, 997, 865, 868, 877, 878, - 1932, 879, 4833, 4833, 4833, 4833, 4833, 2336, 4833, 5710, - -1070, 651, 6053, 43, 866, -1070, 6053, 43, 775, 870, - 446, -1070, 876, -1070, 881, 871, 2632, -1070, 4123, 4426, - 395, -1070, 886, 446, -1070, -1070, 6053, 6053, 6053, -1070, - -1070, -1070, -1070, -1070, -1070, 892, 1039, 894, 1042, -1070, - 1052, 910, 911, 1058, 913, 6313, 6313, 6313, 6313, 899, - 2336, 131, 6313, 131, 131, 131, 131, 131, 901, 286, - 131, 4833, 4833, 4833, 4833, 4833, 4833, 4833, 4833, 4833, - 4833, 4833, 4833, 4833, 4833, 4833, 4833, 4833, 4833, 4833, - 1698, 4407, 4549, -1070, -1070, 908, -1070, 43, -1070, 915, - -1070, -1070, 6053, -1070, -1070, 1065, -1070, 909, -1070, -1070, - 917, 741, 741, 741, 6053, 6053, -1070, 935, -1070, 919, - 939, -1070, -1070, 288, -1070, 924, 940, 944, 945, 1698, - 936, 947, 4833, -1070, 1180, 5866, 5975, 5975, 2202, 2202, - 1127, 934, 934, -1070, 5691, 5900, 5917, 5926, 536, 536, - 131, 131, 131, -1070, -1070, 297, 3432, -1070, 43, 942, - -1070, 535, -1070, -1070, -1070, 6053, -1070, -1070, -1070, -1070, - -1070, -1070, 1103, 946, 958, 1108, 1111, 966, -1070, 951, - 952, 953, 956, 4936, 954, 131, 4833, -1070, -1070, 6053, - 959, -1070, 535, -1070, -1070, 971, -1070, 960, 298, -1070, - 4549, 4549, 4549, -1070, 4549, 5710, -1070, -1070, 6053, -1070, - 979, 1126, 981, 299, 314, 331, 332, 6053, 741, -1070, - 965, -1070, -1070, -1070, -1070, -1070, 741, -1070, 985, -1070, - -1070 + 188, -1062, 4339, 6032, 93, 349, -1062, -1062, -1062, -1062, + -1062, -1062, -1062, -1062, 81, -70, -59, -43, -23, -2, + 24, 44, 60, 91, -1062, -1062, 92, 100, 109, 143, + 146, 154, 177, 180, 192, 200, 243, 251, 255, 264, + 272, 275, 279, 283, 290, 317, 6228, 4339, -1062, -1062, + 216, 324, 346, 3187, 221, -1062, 351, 368, 387, 4339, + 4339, 4339, 4339, 4339, 2888, 581, 4339, 4754, -1062, 119, + -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, + 6097, 389, -1062, 6, -1062, -1062, 1578, 2508, 2508, -1062, + 5064, 414, -1062, 2508, -1062, -1062, 833, 833, -1062, -1062, + -1062, -1062, -1062, 223, 223, -1062, -1062, -1062, -1062, -1062, + 2565, 416, 274, -1062, 4339, 4339, 6032, 4339, 4339, 4339, + 4339, 4339, 6032, 4339, 6032, 4339, 6032, 4339, 6032, 6032, + 6032, 6032, 6032, 6032, 6032, 6032, 6032, 6032, 6032, 6032, + 6032, 6032, 6032, 6032, 4339, -1062, -1062, -1062, 421, 5064, + 423, 433, 223, 223, -1062, 5284, 6032, 4339, 4339, 453, + 2888, 68, 6032, 2888, 4339, 4339, 68, 68, 68, 68, + 68, 81, -59, -43, -23, -2, 24, 60, 92, 109, + 5288, 6413, 6437, 6513, 387, 376, -36, 4754, -1062, -1062, + -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, + 5064, 5064, -104, 397, -1062, -1062, 68, 4339, 4339, 4339, + 4339, 4339, 4339, 4339, 4339, 4339, 4339, 4339, 4339, 4339, + 4339, 4339, 4339, 4339, 4339, 4339, 4339, 4339, 5064, 3331, + 4339, -1062, -1062, 833, 833, 3475, -1062, -1062, -1062, 2508, + -1062, -1062, -1062, -1062, 6032, -1062, 432, 564, 223, 833, + 833, 833, 223, 223, 59, 462, -1062, 463, -1062, 473, + 87, 2050, 5064, 583, 487, 474, 3037, -1062, 6616, 465, + 500, -1062, 494, 496, 506, 511, 516, 525, 528, 483, + 530, 495, 531, 532, 533, 534, 536, 543, -15, 563, + 551, 556, 562, 566, 567, 568, 572, 573, 576, 582, + 584, 587, 4339, -1062, 6032, 4339, 5064, 5064, -1062, 546, + 589, 590, 5064, 592, 574, 593, 5303, 596, 597, 4339, + 4339, -1062, 732, -1062, 1631, 600, 4339, -1062, -1062, 1881, + 4935, 5120, 5120, 555, 555, 485, 298, 298, -1062, 3642, + 5661, 1606, 1809, 555, 555, 132, 132, 68, 68, 68, + -1062, -1062, 28, 2457, -1062, -1062, 604, 5345, 613, 223, + 223, 1104, 462, -1062, 462, -1062, 462, -1062, 1104, 1104, + -1062, 223, 223, 223, 6713, 621, 30, -1062, 622, 4339, + -1062, -1062, -1062, -1062, -1062, 2131, 634, 3, 41, 57, + 106, -1062, -1062, -1062, 640, 223, 5064, 2062, 81, -1062, + -1062, 628, 5064, 632, 638, -1062, -1062, -1062, 223, 223, + -1062, 5366, -1062, 6713, 6713, 6713, 6713, 6713, -1062, 6713, + 5814, 6713, 4339, 656, -1062, 6656, 644, 645, 646, 647, + 648, 649, 6713, 62, 667, 669, 673, 6713, 6713, 660, + 6551, 6713, 6713, 4685, 6713, 6713, -1062, -1062, -1062, 2526, + -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, + -1062, -1062, -1062, 663, -1062, 664, -1062, -1062, -1062, -1062, + 6032, -1062, 6032, -1062, 6032, -1062, -1062, -1062, -1062, -1062, + -1062, -1062, -1062, -1062, -1062, -1062, -1062, 5385, 665, 671, + -1062, -1062, 666, -1062, -1062, 675, 4483, 678, -1062, -1062, + -1062, -1062, 68, 4754, -1062, 5064, 397, 55, 5806, -1062, + 4754, 4339, -1062, -1062, -1062, -1062, -1062, 1104, 668, 670, + 5064, 223, 1104, 1104, 1104, 223, 223, 674, -1062, 674, + 674, 1104, 1104, 1104, 5889, 6713, 6097, -1062, -1062, 117, + 679, 4754, -1062, 5064, 676, -1062, -1062, -1062, -1062, 2131, + -1062, 763, 5064, -1062, -1062, -1062, -1062, -1062, -1062, -1062, + -1062, 686, 697, 701, -1062, -1062, 6228, -1062, -1062, 702, + 4880, 710, -1062, 695, 4339, 4339, 4339, 4339, 2888, 4339, + 700, 42, -1062, -1062, 5644, -1062, 119, 703, 3619, -1062, + 6032, 223, 2581, 2050, 223, -1062, -1062, -1062, -1062, -1062, + -1062, 6713, -1062, -1062, -1062, 5404, -1062, 6616, 3389, -1062, + 5064, 5064, 5064, 5064, 5064, 5064, -1062, -1062, 5064, -1062, + -1062, -1062, -1062, -1062, 4339, -1062, 5109, -1062, 712, -1062, + 5209, -1062, 5064, 5064, 2, -1062, -1062, 457, 706, 6130, + -1062, 5064, -1062, 224, 723, -1062, 4339, 4339, 709, 711, + 713, -1062, -1062, -1062, 4339, -1062, 4339, -1062, 715, -1062, + -1062, -1062, -1062, -1062, -1062, 4339, -1062, 708, -1062, -1062, + 852, 4754, 674, 223, 223, 1104, 674, 674, 674, 1104, + 1104, 4339, -103, 85, 133, 977, 946, 5806, -1062, -1062, + 223, 223, -1062, 736, 58, -1062, 729, -1062, 844, 6032, + 6032, 6032, 721, 6032, 725, 2888, 95, 6032, 2888, 68, + 68, 68, 68, 726, 101, 68, -1062, -1062, 4863, 4339, + 4339, 4339, 4339, 4339, 4339, 4339, 4339, 4339, 4339, 4339, + 4339, 4339, 4339, 4339, 4339, 4339, 4339, 4339, 4339, 4339, + 5064, 3763, 4339, 727, 5464, 731, -1062, -1062, 746, -1062, + -1062, -1062, 6713, -1062, -1062, 753, 757, 759, 760, 764, + 769, 770, 80, 772, 4506, 5921, 395, 755, 224, -1062, + -1062, 773, 774, -1062, 775, -1062, 22, 6293, 1248, -1062, + 756, 517, -1062, -1062, 2204, -1062, -1062, 704, 124, 183, + -1062, -1062, -1062, 189, 196, -1062, 5565, 365, 6195, 777, + -1062, 1104, -1062, 674, 674, 674, 762, 778, 784, 788, + 765, 223, 977, 977, 977, 223, 223, 977, -81, 223, + -1062, 767, 5064, 223, 946, 946, 946, 223, 223, 946, + 8, 852, 771, 36, -1062, 6311, 791, 794, -1062, 223, + 790, 782, 798, 4339, 801, 5064, 792, 809, 800, 5584, + 4339, -1062, -1062, -1062, 1881, 4935, 5120, 5120, 555, 555, + 485, 298, 298, -1062, 3930, 5661, 1606, 1809, 555, 555, + 132, 132, 68, 68, 68, -1062, -1062, 207, 2907, -1062, + -1062, -1062, 2131, -1062, 98, -1062, 969, 971, 972, 974, + 975, 976, -1062, -1062, 427, 835, -1062, -1062, -1062, -1062, + 5975, -1062, 5975, 825, 838, 6470, -1062, 744, -1062, -1062, + 20, -1062, 704, -1062, -1062, 6032, 55, 820, 829, 704, + 55, 1248, 830, 223, 1248, 1248, 1248, 223, 223, 56, + 223, -1062, 99, -1062, -1062, -1062, 5064, 405, -1062, 826, + -1062, 848, 850, 3907, 4214, 842, 223, 704, 5043, 704, + 223, 223, 704, -1062, 77, 454, 223, -1062, -1062, -1062, + -1062, 5806, -1062, -1062, 14, 6228, 833, -1062, 674, 223, + 55, 55, 55, 223, 977, 837, 837, 837, 977, 977, + 328, 4339, -1062, -1062, 223, 223, 946, 840, 840, 840, + 946, 946, 336, 4339, -1062, -1062, -1062, 4339, 6378, 6393, + 6408, 5064, 498, -1062, -1062, 998, -1062, 6311, -1062, -1062, + 843, 849, 846, 854, 856, 4483, 865, -1062, -1062, 68, + 4339, -1062, -1062, 736, -1062, -1062, 861, 212, 873, 884, + 889, 895, -1062, 43, -1062, 744, 744, 6696, 5921, 5064, + 885, 897, 223, 744, 744, 744, 223, 223, 744, 65, + 840, -1062, 454, 910, 893, 898, 704, 492, 899, 410, + 223, 1248, 901, 901, 901, 1248, 1248, -1062, 4339, -1062, + -1062, 55, 900, 468, -1062, 89, 916, 920, -1062, 2711, + -1062, -1062, -1062, 3907, 902, 923, 4754, -1062, -1062, 223, + 704, 460, 1071, -1062, -1062, -1062, -1062, -1062, -1062, -1062, + -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, + -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, + -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, + 909, 907, -1062, 223, 460, 704, 704, 515, 4339, -1062, + 4339, -1062, 2204, 931, -1062, -1062, 852, 913, -1062, 833, + -1062, 914, -1062, 917, 919, 924, 977, 837, 837, 837, + 918, 911, 946, -1062, 840, 840, 840, 925, 922, 5625, + 1336, -1062, 1336, -1062, 1336, -1062, -1062, 1336, 1336, 1336, + -1062, 102, -1062, 4339, 4339, -1062, 4339, -1062, 4339, 4754, + 134, 1092, 1093, 948, 1097, 932, -1062, 1099, 1106, 1108, + 157, 956, 65, 840, 65, 840, -1062, -1062, -1062, -1062, + -1062, -1062, 6032, 223, 744, 744, 744, 1788, -1062, -1062, + 965, -1062, -1062, -1062, -1062, 523, 951, -1062, -1062, 1248, + 901, 901, 901, 55, 952, 958, -1062, -1062, 5064, 4339, + 4339, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, + -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, + -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, + -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, + -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, + -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, + -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, + -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, + -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, + -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, + -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, + -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, + -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, + -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, + -1062, -1062, 955, -1062, 4051, 704, 460, 223, -1062, -1062, + -1062, 460, 460, -1062, 4754, 2062, 964, 4214, 704, 979, + -1062, -1062, -1062, -1062, -1062, -1062, 837, 55, 223, 840, + 55, 223, -1062, -1062, -1062, -1062, -1062, -1062, -1062, -1062, + 230, 252, 254, 266, -1062, 968, 304, -1062, 990, 991, + 325, 982, 339, -1062, -1062, -1062, -1062, -1062, 744, 978, + 985, 988, 994, 4627, 997, 1788, 1788, 1788, 1788, 1788, + 2888, 1788, 1343, -1062, 704, 5806, 55, 989, -1062, 5806, + 55, 901, 992, 223, -1062, 987, -1062, 993, 996, 2382, + -1062, 3907, 4754, 460, -1062, 999, 223, -1062, -1062, 5806, + 5806, 5806, 1000, -1062, 1001, -1062, -1062, -1062, -1062, -1062, + 1011, 1163, 1016, 1168, -1062, 1170, 1023, 1024, 1174, 1027, + 6032, 6032, 6032, 6032, 1012, 2888, 152, 6032, 152, 152, + 152, 152, 152, 1013, 367, 152, 1788, 1788, 1788, 1788, + 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, + 1788, 1788, 1788, 1788, 1788, 5064, 4195, 4339, -1062, -1062, + 1014, -1062, 55, -1062, 1015, -1062, -1062, 5806, -1062, -1062, + 1172, -1062, 1019, -1062, -1062, 1021, 852, 852, 852, -1062, + -1062, -1062, 1036, -1062, 1026, 1042, -1062, -1062, 369, -1062, + 1028, 1034, 1039, 1041, 5064, 1032, 1043, 1788, -1062, 1911, + 4954, 1257, 1257, 888, 888, 1441, 617, 617, -1062, 1363, + 5678, 5743, 4478, 281, 281, 152, 152, 152, -1062, -1062, + 370, 3205, -1062, 55, 1035, -1062, 3534, -1062, -1062, -1062, + 5806, -1062, -1062, -1062, -1062, 5806, 5806, 1200, 1040, 1054, + 1208, 1209, 1062, -1062, 1047, 1049, 1050, 1051, 4731, 1055, + 152, 1788, -1062, -1062, 5806, 1057, -1062, 3534, -1062, -1062, + -1062, -1062, 1067, -1062, 1058, 371, -1062, 4339, 4339, 4339, + -1062, 4339, 1343, -1062, -1062, 5806, -1062, 1072, 1225, 1078, + 372, 378, 380, 383, 5806, 852, -1062, 1064, -1062, -1062, + -1062, -1062, -1062, 852, -1062, 1083, -1062, -1062 }; /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. @@ -1356,208 +1361,208 @@ static const yytype_int16 yypact[] = means the default is an error. */ static const yytype_int16 yydefact[] = { - 0, 782, 0, 0, 0, 782, 5, 668, 664, 667, - 778, 779, 670, 671, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 666, 672, 0, 0, 0, 0, + 0, 789, 0, 0, 0, 789, 5, 675, 671, 674, + 785, 786, 677, 678, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 673, 679, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 674, 673, - 0, 0, 0, 0, 0, 665, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 782, 0, 3, 602, 669, - 305, 316, 315, 397, 398, 400, 401, 402, 381, 0, - 0, 413, 378, 412, 407, 404, 403, 406, 382, 0, - 0, 383, 405, 415, 399, 782, 782, 4, 307, 308, - 309, 364, 782, 782, 304, 394, 395, 396, 1, 0, - 0, 7, 63, 782, 782, 0, 782, 782, 782, 782, - 782, 0, 782, 0, 782, 0, 782, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 681, 680, + 0, 0, 0, 0, 0, 672, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 789, 0, 3, 609, 676, + 307, 319, 317, 402, 318, 403, 405, 406, 407, 386, + 0, 0, 418, 383, 417, 412, 409, 408, 411, 387, + 0, 0, 388, 410, 420, 404, 789, 789, 4, 309, + 310, 311, 369, 789, 789, 306, 399, 400, 401, 1, + 0, 0, 7, 63, 789, 789, 0, 789, 789, 789, + 789, 789, 0, 789, 0, 789, 0, 789, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 782, 331, 337, 0, 0, 0, 627, - 782, 782, 330, 0, 0, 782, 782, 0, 0, 624, - 0, 0, 782, 782, 636, 634, 633, 635, 632, 305, - 397, 398, 400, 401, 402, 413, 412, 407, 404, 403, - 406, 405, 399, 0, 0, 560, 763, 764, 765, 773, - 766, 769, 767, 771, 770, 768, 772, 752, 753, 0, - 0, 782, 758, 751, 631, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 780, - 781, 782, 782, 0, 379, 380, 414, 404, 409, 408, - 411, 306, 0, 410, 0, 291, 782, 782, 782, 782, - 782, 782, 0, 340, 290, 342, 0, 367, 0, 0, - 0, 68, 70, 0, 6, 782, 0, 559, 558, 0, + 0, 0, 0, 0, 789, 335, 341, 342, 0, 0, + 0, 634, 789, 789, 334, 0, 0, 789, 789, 0, + 0, 631, 0, 0, 789, 789, 643, 641, 640, 642, + 639, 307, 402, 403, 405, 406, 407, 418, 417, 412, + 409, 408, 411, 410, 404, 0, 0, 567, 770, 771, + 772, 780, 773, 776, 774, 778, 777, 775, 779, 759, + 760, 0, 0, 789, 765, 758, 638, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 332, 0, 782, 0, 0, 660, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 663, 756, - 759, 0, 782, 0, 754, 220, 645, 646, 647, 648, - 649, 650, 651, 654, 655, 662, 0, 642, 643, 644, - 652, 653, 640, 641, 637, 638, 639, 661, 659, 0, - 0, 341, 343, 0, 0, 0, 782, 782, 782, 0, - 293, 0, 294, 782, 782, 205, 782, 782, 782, 0, - 0, 206, 209, 63, 782, 782, 774, 775, 776, 777, - 0, 369, 763, 764, 765, 767, 344, 310, 346, 0, - 782, 0, 782, 318, 329, 0, 0, 0, 0, 320, - 321, 322, 782, 782, 317, 0, 22, 782, 782, 782, - 782, 782, 23, 782, 782, 782, 0, 0, 43, 782, - 0, 0, 0, 0, 0, 0, 782, 782, 0, 0, - 0, 782, 782, 0, 782, 782, 782, 0, 782, 782, - 18, 8, 20, 0, 16, 17, 19, 78, 45, 609, - 608, 626, 616, 611, 613, 614, 615, 0, 622, 0, - 621, 677, 610, 678, 0, 680, 0, 681, 0, 684, - 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, - 618, 0, 0, 0, 334, 333, 0, 617, 620, 0, - 623, 0, 629, 630, 619, 612, 603, 561, 757, 0, - 782, 782, 782, 103, 221, 0, 658, 657, 313, 312, - 314, 782, 292, 0, 281, 782, 782, 782, 782, 782, - 297, 280, 296, 295, 782, 782, 782, 0, 782, 782, - 0, 782, 208, 782, 0, 557, 556, 375, 0, 372, - 371, 366, 370, 0, 782, 782, 0, 64, 69, 744, - 740, 743, 746, 747, 212, 0, 0, 0, 742, 748, - 0, 750, 749, 0, 0, 0, 741, 0, 0, 0, - 0, 0, 0, 0, 0, 213, 247, 216, 248, 695, - 745, 63, 0, 319, 0, 782, 367, 0, 782, 782, - 782, 60, 46, 57, 58, 59, 61, 782, 47, 160, - 52, 0, 24, 782, 0, 50, 0, 0, 0, 0, - 0, 0, 56, 782, 0, 27, 26, 25, 54, 49, - 0, 164, 0, 163, 0, 62, 0, 21, 0, 0, - 782, 51, 55, 339, 318, 0, 14, 0, 75, 0, - 338, 72, 0, 0, 0, 0, 0, 335, 336, 628, - 0, 625, 0, 755, 0, 111, 104, 113, 108, 112, - 106, 0, 109, 0, 105, 110, 782, 656, 298, 782, - 782, 782, 283, 284, 782, 782, 782, 0, 0, 0, - 0, 782, 0, 246, 0, 782, 782, 782, 782, 782, - 782, 782, 782, 258, 0, 269, 782, 0, 0, 782, - 782, 0, 782, 782, 207, 210, 782, 782, 365, 311, - 782, 349, 782, 348, 0, 0, 0, 0, 705, 0, - 0, 0, 702, 0, 0, 713, 712, 711, 710, 0, - 0, 709, 71, 215, 782, 0, 0, 0, 0, 0, + 0, 787, 788, 789, 789, 0, 384, 385, 419, 409, + 414, 413, 416, 308, 0, 415, 0, 292, 789, 789, + 789, 789, 789, 789, 789, 0, 345, 291, 347, 0, + 372, 0, 0, 0, 68, 70, 0, 6, 789, 0, + 566, 565, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 67, 325, 369, 323, 66, 48, 782, 44, - 782, 0, 0, 0, 0, 0, 0, 0, 782, 0, - 0, 782, 339, 318, 0, 338, 81, 0, 0, 390, - 0, 86, 90, 0, 782, 782, 0, 0, 416, 227, - 0, 77, 74, 0, 0, 0, 679, 682, 683, 0, - 0, 782, 0, 0, 0, 0, 199, 782, 282, 287, - 286, 285, 0, 0, 0, 0, 782, 0, 782, 782, - 782, 782, 260, 261, 782, 782, 0, 782, 240, 259, - 782, 782, 0, 271, 272, 0, 0, 0, 782, 243, - 782, 299, 376, 345, 0, 0, 351, 350, 782, 0, - 0, 0, 782, 0, 0, 0, 0, 0, 0, 0, - 739, 214, 217, 722, 723, 724, 725, 726, 727, 728, - 731, 732, 738, 0, 719, 720, 721, 729, 730, 717, - 718, 714, 715, 716, 737, 736, 0, 0, 327, 326, - 328, 0, 53, 782, 386, 0, 0, 0, 0, 0, - 0, 388, 384, 0, 0, 181, 182, 183, 169, 0, - 170, 0, 166, 171, 167, 782, 180, 165, 0, 83, - 0, 393, 392, 0, 782, 0, 0, 0, 782, 782, - 0, 782, 782, 782, 782, 782, 0, 782, 249, 782, - 92, 416, 222, 0, 0, 76, 0, 782, 0, 0, - 782, 0, 0, 782, 0, 0, 0, 782, 782, 0, - 73, 782, 782, 782, 606, 605, 607, 604, 782, 107, - 114, 0, 0, 782, 416, 288, 782, 782, 782, 782, - 782, 782, 241, 244, 782, 264, 263, 262, 268, 0, - 0, 270, 275, 274, 273, 279, 0, 300, 373, 0, - 771, 0, 770, 0, 0, 352, 354, 760, 782, 0, - 65, 704, 0, 0, 0, 0, 0, 701, 0, 707, - 708, 696, 0, 735, 734, 324, 389, 782, 0, 0, - 782, 0, 0, 0, 782, 0, 42, 782, 782, 0, - 174, 172, 0, 782, 782, 782, 782, 782, 782, 782, - 178, 82, 782, 0, 0, 0, 0, 0, 0, 0, - 782, 782, 251, 252, 782, 782, 98, 782, 250, 15, - 782, 0, 0, 9, 0, 0, 0, 228, 417, 418, - 230, 231, 782, 0, 234, 236, 233, 229, 782, 0, - 187, 0, 127, 128, 129, 130, 131, 132, 135, 136, - 137, 152, 140, 141, 142, 143, 144, 145, 146, 147, - 148, 149, 150, 151, 156, 155, 139, 138, 124, 126, - 125, 133, 134, 122, 123, 119, 120, 121, 118, 0, - 0, 117, 782, 188, 0, 0, 0, 0, 195, 782, - 197, 0, 0, 79, 184, 782, 0, 115, 782, 200, - 0, 289, 0, 0, 0, 242, 245, 265, 782, 782, - 276, 782, 782, 377, 0, 357, 0, 356, 0, 355, - 761, 0, 0, 0, 762, 782, 353, 0, 0, 706, - 0, 703, 0, 733, 782, 0, 0, 0, 0, 0, - 202, 0, 0, 0, 782, 0, 782, 179, 159, 157, - 162, 158, 168, 175, 0, 782, 782, 782, 782, 0, - 176, 218, 0, 84, 391, 782, 88, 0, 0, 782, - 100, 782, 255, 254, 253, 782, 0, 0, 223, 416, - 0, 782, 782, 225, 226, 420, 421, 425, 422, 430, - 423, 424, 426, 427, 428, 429, 431, 432, 433, 434, - 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, - 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, - 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, - 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, - 475, 476, 477, 478, 479, 480, 481, 482, 483, 505, - 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, - 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, - 504, 506, 507, 508, 509, 510, 511, 512, 513, 514, - 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, - 525, 526, 527, 528, 529, 530, 531, 532, 782, 549, - 550, 551, 542, 554, 538, 539, 537, 544, 545, 533, - 534, 535, 536, 543, 541, 548, 546, 552, 547, 540, - 553, 419, 0, 232, 235, 0, 191, 782, 154, 153, - 185, 190, 189, 194, 198, 782, 0, 221, 0, 0, - 116, 201, 675, 782, 782, 782, 0, 266, 0, 277, - 374, 363, 362, 361, 360, 359, 358, 347, 0, 0, - 0, 0, 387, 0, 0, 34, 203, 0, 0, 0, - 0, 385, 41, 177, 173, 782, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 219, - 562, 0, 782, 782, 0, 94, 782, 782, 256, 0, - 782, 782, 0, 10, 0, 0, 0, 237, 782, 238, - 192, 186, 0, 782, 80, 416, 782, 782, 782, 782, - 782, 699, 698, 700, 697, 0, 0, 0, 0, 28, + 0, 0, 0, 336, 0, 789, 0, 0, 667, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 569, 0, 577, 575, 574, 576, 573, 0, 0, - 572, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 670, 763, 766, 0, 789, 0, 761, 222, 652, + 653, 654, 655, 656, 657, 658, 661, 662, 669, 0, + 649, 650, 651, 659, 660, 647, 648, 644, 645, 646, + 668, 666, 0, 0, 346, 348, 0, 0, 0, 789, + 789, 789, 0, 294, 0, 296, 0, 295, 789, 789, + 207, 789, 789, 789, 789, 0, 208, 211, 63, 789, + 789, 781, 782, 783, 784, 0, 374, 770, 771, 772, + 774, 349, 312, 351, 0, 789, 0, 789, 321, 332, + 333, 0, 0, 0, 0, 323, 324, 325, 789, 789, + 320, 0, 22, 789, 789, 789, 789, 789, 23, 789, + 789, 789, 0, 0, 43, 789, 0, 0, 0, 0, + 0, 0, 789, 789, 0, 0, 0, 789, 789, 0, + 789, 789, 789, 0, 789, 789, 18, 8, 20, 0, + 16, 17, 19, 78, 45, 616, 615, 633, 623, 618, + 620, 621, 622, 0, 629, 0, 628, 684, 617, 685, + 0, 687, 0, 688, 0, 691, 692, 693, 694, 695, + 696, 697, 698, 699, 700, 701, 625, 0, 0, 0, + 338, 337, 0, 624, 627, 0, 630, 0, 636, 637, + 626, 619, 610, 568, 764, 0, 789, 789, 789, 103, + 223, 0, 665, 664, 315, 314, 316, 789, 293, 0, + 281, 789, 789, 789, 789, 789, 789, 299, 280, 298, + 297, 789, 789, 789, 789, 789, 0, 789, 210, 789, + 0, 564, 563, 380, 0, 377, 376, 371, 375, 0, + 789, 789, 0, 64, 69, 751, 747, 750, 753, 754, + 214, 0, 0, 0, 749, 755, 0, 757, 756, 0, + 0, 0, 748, 0, 0, 0, 0, 0, 0, 0, + 0, 215, 244, 218, 245, 702, 752, 63, 0, 322, + 0, 789, 372, 0, 789, 60, 46, 57, 58, 59, + 61, 789, 47, 160, 52, 0, 24, 789, 0, 50, + 0, 0, 0, 0, 0, 0, 56, 789, 0, 27, + 26, 25, 54, 49, 0, 164, 0, 163, 0, 62, + 0, 21, 0, 0, 789, 51, 55, 344, 321, 0, + 14, 0, 75, 0, 343, 72, 0, 0, 0, 0, + 0, 339, 340, 635, 0, 632, 0, 762, 0, 111, + 104, 113, 108, 112, 106, 0, 109, 0, 105, 110, + 789, 663, 300, 789, 789, 789, 283, 285, 284, 789, + 789, 789, 0, 0, 0, 789, 0, 789, 209, 212, + 789, 789, 370, 313, 789, 354, 789, 353, 0, 0, + 0, 0, 712, 0, 0, 0, 709, 0, 0, 720, + 719, 718, 717, 0, 0, 716, 71, 217, 789, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 85, 87, 0, 96, 782, 91, 0, - 782, 257, 782, 224, 13, 11, 555, 0, 782, 193, - 0, 782, 782, 782, 782, 782, 37, 782, 35, 0, - 0, 38, 40, 0, 30, 0, 0, 0, 0, 0, - 0, 0, 0, 601, 586, 587, 588, 589, 590, 591, - 592, 593, 594, 600, 0, 583, 584, 585, 581, 582, - 578, 579, 580, 599, 598, 0, 0, 782, 782, 0, - 782, 99, 93, 12, 239, 782, 676, 303, 302, 301, - 267, 278, 0, 0, 0, 0, 0, 0, 571, 0, - 0, 0, 0, 568, 0, 563, 0, 597, 596, 782, - 0, 782, 101, 196, 203, 0, 29, 0, 0, 31, - 0, 0, 0, 570, 0, 595, 89, 782, 782, 36, - 0, 0, 0, 0, 0, 0, 0, 782, 782, 39, - 0, 32, 566, 565, 567, 564, 782, 95, 0, 97, - 33 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 67, 328, 374, 326, + 66, 48, 789, 44, 789, 0, 0, 0, 0, 0, + 0, 0, 789, 0, 0, 789, 344, 321, 0, 343, + 81, 0, 0, 395, 0, 86, 90, 0, 789, 789, + 0, 0, 421, 229, 0, 77, 74, 0, 0, 0, + 686, 689, 690, 0, 0, 789, 0, 0, 0, 0, + 201, 789, 282, 288, 287, 286, 0, 0, 0, 0, + 0, 789, 789, 789, 789, 789, 789, 789, 789, 789, + 256, 0, 268, 789, 0, 0, 0, 789, 789, 0, + 789, 789, 301, 381, 350, 0, 0, 356, 355, 789, + 0, 0, 0, 789, 0, 0, 0, 0, 0, 0, + 0, 746, 216, 219, 729, 730, 731, 732, 733, 734, + 735, 738, 739, 745, 0, 726, 727, 728, 736, 737, + 724, 725, 721, 722, 723, 744, 743, 0, 0, 330, + 329, 331, 0, 53, 789, 391, 0, 0, 0, 0, + 0, 0, 393, 389, 0, 0, 183, 184, 185, 169, + 0, 170, 0, 0, 166, 171, 167, 789, 182, 165, + 0, 83, 0, 398, 397, 0, 789, 0, 0, 0, + 789, 789, 0, 789, 789, 789, 789, 789, 789, 0, + 789, 246, 789, 92, 421, 224, 0, 0, 76, 0, + 789, 0, 0, 789, 0, 0, 789, 0, 0, 0, + 789, 789, 0, 73, 789, 789, 789, 613, 612, 614, + 611, 789, 107, 114, 0, 0, 789, 421, 289, 789, + 789, 789, 789, 789, 789, 258, 260, 259, 789, 789, + 0, 789, 242, 257, 789, 789, 0, 270, 272, 271, + 0, 0, 0, 789, 243, 302, 378, 0, 778, 0, + 777, 0, 0, 357, 359, 767, 789, 0, 65, 711, + 0, 0, 0, 0, 0, 708, 0, 714, 715, 703, + 0, 742, 741, 327, 394, 789, 0, 0, 789, 0, + 0, 0, 789, 0, 42, 789, 789, 789, 0, 174, + 172, 0, 789, 789, 789, 789, 789, 789, 789, 789, + 178, 82, 789, 0, 0, 0, 0, 0, 0, 0, + 789, 789, 248, 250, 249, 789, 789, 98, 789, 247, + 15, 789, 0, 0, 9, 0, 0, 0, 230, 422, + 423, 232, 233, 789, 0, 236, 238, 235, 231, 789, + 0, 189, 0, 127, 128, 129, 130, 131, 132, 135, + 136, 137, 152, 140, 141, 142, 143, 144, 145, 146, + 147, 148, 149, 150, 151, 156, 155, 139, 138, 124, + 126, 125, 133, 134, 122, 123, 119, 120, 121, 118, + 0, 0, 117, 789, 190, 0, 0, 0, 0, 197, + 789, 199, 0, 0, 79, 186, 789, 0, 115, 789, + 202, 0, 290, 0, 0, 0, 789, 263, 262, 261, + 267, 0, 0, 269, 275, 274, 273, 279, 0, 382, + 0, 362, 0, 361, 0, 360, 768, 0, 0, 0, + 769, 789, 358, 0, 0, 713, 0, 710, 0, 740, + 789, 0, 0, 0, 0, 0, 204, 0, 0, 0, + 789, 0, 789, 179, 789, 181, 159, 157, 162, 158, + 168, 175, 0, 789, 789, 789, 789, 0, 176, 220, + 0, 84, 396, 789, 88, 0, 0, 789, 100, 789, + 253, 252, 251, 789, 0, 0, 225, 421, 0, 789, + 789, 227, 228, 425, 426, 430, 427, 435, 428, 429, + 431, 432, 433, 434, 436, 437, 438, 439, 440, 441, + 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, + 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, + 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, + 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, + 482, 483, 484, 485, 486, 487, 488, 489, 511, 490, + 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, + 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, + 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, + 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, + 532, 533, 534, 535, 536, 537, 538, 539, 789, 556, + 557, 558, 549, 561, 545, 546, 544, 551, 552, 540, + 541, 542, 543, 550, 548, 555, 553, 559, 554, 547, + 560, 424, 0, 234, 237, 0, 193, 789, 154, 153, + 187, 192, 191, 196, 200, 789, 0, 223, 0, 0, + 116, 203, 682, 789, 789, 789, 264, 789, 789, 276, + 789, 789, 379, 368, 367, 366, 365, 364, 363, 352, + 0, 0, 0, 0, 392, 0, 0, 34, 205, 0, + 0, 0, 0, 390, 41, 177, 180, 173, 789, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 221, 569, 0, 789, 789, 0, 94, 789, + 789, 254, 0, 789, 789, 0, 10, 0, 0, 0, + 239, 789, 240, 194, 188, 0, 789, 80, 421, 789, + 789, 789, 0, 265, 0, 277, 706, 705, 707, 704, + 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 576, 0, 584, 582, + 581, 583, 580, 0, 0, 579, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 85, 87, + 0, 96, 789, 91, 0, 789, 255, 789, 226, 13, + 11, 562, 0, 789, 195, 0, 789, 789, 789, 789, + 789, 37, 789, 35, 0, 0, 38, 40, 0, 30, + 0, 0, 0, 0, 0, 0, 0, 0, 608, 593, + 594, 595, 596, 597, 598, 599, 600, 601, 607, 0, + 590, 591, 592, 588, 589, 585, 586, 587, 606, 605, + 0, 0, 789, 789, 0, 789, 99, 93, 12, 241, + 789, 683, 305, 304, 303, 789, 789, 0, 0, 0, + 0, 0, 0, 578, 0, 0, 0, 0, 575, 0, + 570, 0, 604, 603, 789, 0, 789, 101, 198, 266, + 278, 205, 0, 29, 0, 0, 31, 0, 0, 0, + 577, 0, 602, 89, 789, 789, 36, 0, 0, 0, + 0, 0, 0, 0, 789, 789, 39, 0, 32, 573, + 572, 574, 571, 789, 95, 0, 97, 33 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int16 yypgoto[] = { - -1070, -1070, -525, -1070, -1070, -102, -1070, -1070, 540, -420, - -1070, 475, 729, -359, -1070, -419, -1070, -1070, -243, -1070, - -1070, -307, -1070, -1070, -1070, -1070, 532, -1070, -1070, -1070, - -1070, -1070, -485, -1070, -1070, -402, -1070, -1070, -1070, -1070, - 111, 244, -890, -1070, -912, -790, -392, -456, -1070, -229, - -1070, -38, -483, -1070, -755, -1069, -1070, -390, 438, -873, - -496, -486, -41, -75, -69, -63, -237, -540, 545, 154, - -238, -1070, -211, -1070, -1070, -1070, -1070, 156, -200, -1070, - -1070, -515, -1070, -1070, -19, 34, -1070, -1070, -1070, -1070, - -22, -51, -1070, -1070, -929, -1070, -185, -1070, -645, -113, - -7, 327, 1514, -254, 613, -1070, -1070, 863, -925, 1359, - 210, -384, -1 + -1062, -1062, -525, -1062, -1062, 4, -1062, -1062, 636, -428, + -1062, -354, 210, -358, -1062, -426, -1062, -1062, -153, -1062, + -1062, -208, -1062, -1062, -1062, -1062, 620, -1062, -1062, -1062, + -1062, -1062, -448, -1062, -1062, -414, -1062, -1062, -1062, -1062, + 209, -412, -746, -1062, -886, -775, -311, -406, -1062, -142, + -1062, -644, -485, -1062, -731, -1061, -1062, -381, 537, -844, + -643, 258, -39, -96, -77, -57, -236, -539, 633, 156, + -235, -1062, -223, -1062, -1062, -1062, -1062, 257, -222, -1062, + -1062, -521, -1062, -1062, -27, -22, -1062, -1062, -1062, -1062, + -28, -47, -1062, -1062, -898, -1062, -92, -1062, -623, -110, + -60, 571, 1273, 285, 692, -1062, -1062, 943, -822, 1127, + -116, -395, -1 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int16 yydefgoto[] = { - 0, 4, 5, 265, 1082, 1083, 440, 795, 441, 442, - 603, 443, 369, 260, 261, 444, 803, 797, 970, 627, - 930, 1061, 638, 934, 1453, 938, 639, 1080, 1537, 1598, - 1235, 1457, 502, 1142, 1210, 445, 624, 921, 922, 923, - 924, 925, 971, 1395, 972, 815, 1199, 370, 371, 574, - 575, 1220, 324, 955, 801, 1093, 1094, 372, 577, 946, - 832, 843, 252, 253, 95, 96, 640, 149, 641, 97, - 98, 544, 99, 545, 712, 855, 856, 1015, 100, 256, - 101, 541, 537, 538, 102, 103, 446, 1044, 1037, 447, - 104, 105, 106, 107, 956, 957, 1088, 1381, 534, 266, - 267, 1625, 185, 68, 578, 579, 200, 201, 1016, 1017, - 692, 69, 112 + 0, 4, 5, 268, 1073, 1074, 446, 779, 447, 448, + 607, 449, 374, 263, 264, 450, 787, 781, 953, 631, + 912, 1051, 642, 916, 1456, 920, 643, 1071, 1542, 1603, + 1233, 1460, 508, 1133, 1208, 451, 628, 903, 904, 905, + 906, 907, 954, 1395, 955, 799, 1195, 375, 376, 580, + 581, 1218, 327, 938, 785, 1084, 1085, 377, 583, 929, + 975, 987, 255, 256, 96, 97, 644, 151, 645, 98, + 99, 550, 100, 551, 696, 836, 837, 1003, 101, 259, + 102, 547, 543, 544, 103, 104, 452, 1032, 1025, 453, + 105, 106, 107, 108, 939, 940, 1079, 1381, 540, 269, + 270, 1630, 187, 68, 584, 585, 202, 203, 1004, 1005, + 819, 69, 113 }; /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If @@ -1565,1684 +1570,1642 @@ static const yytype_int16 yydefgoto[] = number is the opposite. If YYTABLE_NINF, syntax error. */ static const yytype_int16 yytable[] = { - 6, 269, 576, 271, 272, 273, 274, 275, 580, 277, - 231, 279, 599, 281, 621, 623, 232, 653, 1062, 710, - 718, 255, 1081, 1382, 152, 399, 398, 150, 709, 929, - 298, 822, 548, 691, 238, 239, 240, 376, 377, 378, - 1156, 243, 307, 308, 702, 654, 703, 1067, 532, 314, - 315, 109, 400, 110, 229, 1160, 230, 184, 365, 935, - 1007, -2, 936, 401, 203, 317, 1069, 936, 234, 1072, - 1073, 733, -774, -775, 1100, 323, 1143, -776, 113, 1146, - 151, 321, 108, 466, 318, 1175, 1177, 1179, 778, 264, - 837, 109, 1241, 110, 254, 254, 114, 214, 109, 704, - 110, -777, 467, 322, 115, 317, 109, 317, 110, 109, - 1242, 110, 268, 268, 116, 268, 268, 268, 268, 268, - 117, 268, 744, 268, 506, 268, 870, 238, 239, 240, - 243, 109, 109, 110, 110, 109, 118, 110, 683, 109, - 235, 110, 268, 705, 317, -774, -775, 379, -774, -775, - -776, 184, 317, -776, 268, 268, 351, 352, 676, 823, - 317, 268, 268, 974, 513, 1520, 514, 323, 515, 1085, - 1086, 975, 360, 362, -777, 1219, 1227, -777, 853, 976, - 580, 1150, 848, 119, 380, 828, 238, 714, 533, 483, - 837, 833, 999, 244, 836, 245, 829, 246, 1232, 1157, - 325, 1233, 1234, 1006, 120, 399, 359, 361, 838, 1386, - 814, 734, 844, 516, 789, 847, 937, 1153, 183, 849, - 349, 937, 1205, 1076, 1077, 911, 376, 377, 378, 940, - 254, 254, 400, 941, 226, 227, 228, 613, 365, 121, - 366, 404, 247, 401, 402, 903, 254, 254, 123, 1411, - 373, 1412, 122, 1413, 1391, 1392, 1414, 1415, 1416, 756, - 757, 758, 1036, 316, 448, 109, 1079, 110, 124, 270, - 949, 109, 125, 110, 983, 276, 126, 278, 942, 280, - 127, 282, 283, 284, 285, 286, 287, 288, 289, 290, - 291, 292, 293, 294, 295, 296, 297, 403, 128, 517, - 529, 268, 1530, 1531, 1532, 317, 530, 1223, 306, 129, - 1462, 214, 310, 518, 311, 312, 1008, 520, 519, 1009, - 130, 503, 522, 523, 977, 229, 978, 230, 248, 542, - 990, 131, 109, 1147, 110, 995, 379, 132, 996, 997, - 133, 991, 249, 134, 576, 992, 993, 250, 1148, 1149, - 580, 135, 251, 109, 136, 110, 1002, 521, 1458, 1003, - 1004, 317, 521, 521, 943, 1399, 137, 798, 694, 799, - 695, 800, 696, 536, 539, 1196, 317, 138, 944, 317, - 1033, 317, 317, 945, 399, 367, 1035, 139, 399, 785, - 368, 581, 1417, 323, 1197, 1481, 355, 1486, 1482, 1547, - 1483, 1484, 140, 10, 1490, 11, 448, 448, 448, 448, - 448, 400, 448, 448, 448, 400, 1487, 697, 448, 676, - 824, 404, 401, 1491, 402, 448, 401, 141, 1493, 1059, - 448, 448, 1236, 448, 448, 448, 142, 448, 448, 1060, - 143, 317, 1158, 1616, 223, 224, 225, 1494, 226, 227, - 228, 155, 317, 1651, 317, 482, 676, 825, 681, 1422, - 1573, -102, 1617, -102, 682, -102, 154, 381, 388, 317, - 668, 1627, 1652, 1662, 156, 672, 673, 403, 1064, 791, - 1431, 160, 1068, 677, 678, 679, 317, 317, 1663, 1152, - 837, 998, 542, 1185, 109, 1470, 110, 161, 1167, 325, - 373, 848, 1005, 698, 1396, 1664, 1665, 1165, 1166, 162, - 521, 163, 1194, 233, 1170, 521, 521, 699, 242, 1204, - 1230, 1077, 700, 521, 521, 521, 263, 701, 693, 1045, - 503, 1162, 1163, 1164, 1, 2, 3, 299, 152, 1062, - 301, 150, 302, 6, 713, 951, 1550, 952, 953, 954, - 309, 1206, 655, -102, 798, -102, 799, -102, 1151, 833, - 356, 1207, 836, 1239, 1240, 730, 794, 1148, 1149, 844, - 1520, 374, 847, 1181, 1182, 1183, 1148, 1149, 1228, 1222, - -280, 375, 186, 187, 188, 1148, 1149, 1393, 448, 448, - 1148, 1149, 1454, 390, 151, 391, 448, 656, 392, 657, - 404, 457, 448, 402, 404, 449, 317, 402, 450, 451, - 452, 826, 6, 453, 459, 454, 658, 827, 644, 455, - 645, 456, 646, 458, 1237, 464, 468, 460, 1208, 1209, - 819, 461, 462, 820, 821, 804, 805, 463, 465, 469, - 189, 470, 471, 809, 486, 810, 1211, 472, 659, 498, - 473, 660, 661, 190, 191, 662, 403, 474, 475, 476, - 403, 376, 377, 378, 962, 816, 477, 478, 963, 479, - 521, 663, 480, 521, 521, 536, 487, 488, 490, 491, - 693, 492, 494, 664, 495, 693, 693, 508, 501, 693, - 325, 510, 192, 193, 531, 194, -204, 665, 543, 546, - 195, 325, 196, 1527, 1528, 1529, 582, 1530, 1531, 1532, - 584, 857, 1406, 964, 730, 1408, 602, 585, 606, 607, - 995, 996, 997, 608, 939, 609, 729, 610, 611, 620, - 1002, 1003, 1004, 615, 111, 616, 617, 642, 761, 643, - 1452, 706, 648, 649, 1456, 650, 980, 652, 651, 1024, - 896, 669, 708, -282, 676, 711, 716, 715, 717, 926, - 719, 1607, 1608, 1609, 723, 732, 724, 448, 781, 6, - 965, 379, -211, 802, 792, 814, 985, 806, 807, 1459, - 927, 808, 186, 187, 188, 811, 813, 830, 840, -368, - 854, 858, 152, 948, 6, 150, 764, 388, 862, 966, - 864, 869, 901, 898, 900, 376, 377, 378, 684, 904, - 503, 905, 685, 967, 906, 907, 521, 908, 968, 909, - 910, 912, 928, 969, 931, 693, 932, 325, 325, 933, - 693, 257, 258, 693, 693, 950, 536, 984, 986, 837, - 189, 987, 1018, 1038, 988, 989, 1019, 536, 151, 816, - 542, 848, -289, 190, 191, 1021, 1022, 686, 1023, 1025, - 1027, 268, 1028, 1029, 1039, 1040, 1041, 1042, 1667, 859, - 860, 861, 1043, 863, 1046, 865, 1669, 866, 867, 303, - 304, 1048, 591, 592, 593, 594, 595, 214, 596, 598, - 600, 1049, 192, 193, 605, 194, 1065, 926, 1066, 1070, - 195, 612, 196, 1087, 1090, 1091, 618, 619, 1159, 622, - 625, 626, 1098, 631, 632, 379, 1168, 1169, 1476, 1477, - 1478, 1184, 1171, 1172, 693, 1187, 1188, 1214, 1190, 1189, - 1192, 1191, 1195, 373, 1198, 1201, 1202, 373, 948, 1167, - 1203, 948, 948, 687, 1224, -281, 1226, 1225, 1077, 1170, - 1215, 1238, 1229, 1243, 1244, 1384, 1089, 688, 1387, 1096, - 152, 1383, 689, 150, 1388, 1450, 1389, 690, 1520, 1398, - 816, 325, 1423, 1400, 1424, 358, 1542, 1402, 363, 364, - 1403, 1404, 254, 1405, 1425, 1426, 373, 373, 373, 325, - 325, 1427, 1428, 693, 1554, 1555, 1429, 1535, 1430, 1432, - 1451, 1539, 1455, 1460, 947, 576, 1461, 376, 377, 378, - 1052, 580, 695, 973, 1053, 1467, 151, 6, 221, 222, - 223, 224, 225, 1473, 226, 227, 228, 926, 1475, 1489, - 1488, 1496, 1479, 1480, 1485, 1492, 6, 1495, 1536, 1200, - 1497, 1498, 1502, 6, 1540, 1545, 693, 448, 1556, 1557, - 1558, 1543, 1559, 693, 693, 1601, 1544, 693, 1221, 1054, - 1548, 325, 1560, 1605, 598, 605, 1561, 1562, 1563, 1564, - 948, 1569, 767, 948, 948, 1572, 536, 212, 213, 373, - 1603, 1599, 1597, 1401, 1604, 511, 512, 1063, 214, 1600, - 1612, 1096, 1606, 1614, 1615, 524, 525, 526, 1618, 1525, - 1526, 1527, 1528, 1529, 1619, 1530, 1531, 1532, 1620, 1621, - 1623, 1624, 1629, 1634, 1636, 1632, 1631, 379, 1637, 547, - 1635, 1638, 1639, 1640, 1641, 1642, 1644, 1649, 1464, 1465, - 1643, 586, 587, 1647, 1650, 1659, 1660, 1661, 1463, 1668, - 973, 1670, 1630, 769, 1533, 1055, 1648, 973, 536, 947, - 1518, 1519, 947, 947, 816, 1474, 614, 254, 784, 1056, - 1212, 1520, 1657, 1047, 1057, 1613, 1472, 373, 1433, 1058, - 373, 786, 872, 1466, 973, 1186, 973, 722, 0, 973, - 1418, 1419, 0, 1420, 500, 1421, 1450, 0, 1450, 1450, - 1450, 1450, 1450, 0, 1450, 0, 0, 1512, 1513, 1514, - 1515, 1516, 1517, 1518, 1519, 1221, 0, 0, 0, 0, - 0, 0, 0, 0, 1520, 693, 693, 693, 0, 221, - 222, 223, 224, 225, 503, 226, 227, 228, 503, 0, - 948, 666, 0, 0, 373, 0, 0, 0, 0, 0, - 268, 268, 0, 902, 671, 0, 0, 674, 675, 0, - 0, 0, 0, 382, 383, 384, 0, 1450, 1450, 1450, - 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, 1450, - 1450, 1450, 1450, 1450, 1450, 1450, 973, 0, 0, 0, - 0, 947, 0, 0, 947, 947, 0, 0, 0, 0, - 0, 0, 1525, 1526, 1527, 1528, 1529, 0, 1530, 1531, - 1532, 0, 0, 0, 0, 0, 0, 0, 0, 973, - 0, 189, 0, 0, 762, 0, 0, 766, 1450, 0, - 0, 0, 0, 0, 190, 191, 0, 0, 0, 0, - 0, 0, 549, 550, 551, 10, 0, 11, 552, 553, - 1522, 1523, 1524, 0, 554, 1525, 1526, 1527, 1528, 1529, - 0, 1530, 1531, 1532, 973, 973, 0, 1089, 0, 790, - 0, 0, 0, 385, 193, 0, 194, 0, 1434, 1450, - 0, 195, 1450, 196, 0, 0, 0, 109, 0, 110, - 555, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 581, 556, 0, 386, 817, 818, - 557, 0, 503, 503, 503, 0, 0, 0, 0, 558, - 559, 0, 0, 0, 831, 0, 0, 834, 835, 0, - 0, 839, 0, 0, 202, 842, 0, 0, 845, 846, - 0, 0, 850, 0, 693, 851, 852, 0, 0, 111, - 1509, 947, 0, 0, 560, 0, 0, 561, 241, 562, - 0, 0, 373, 0, 563, 0, 373, 0, 564, 0, - 503, 565, 0, 0, 0, 0, 566, 1096, 262, 567, - 0, 186, 187, 188, 0, 0, 0, 0, 503, 503, + 6, 258, 586, 233, 186, 272, 603, 274, 275, 276, + 277, 278, 625, 280, 627, 282, 582, 284, 154, 152, + 536, 657, 1382, 234, 153, 694, 1052, 702, 693, 1147, + 404, 405, 917, 918, 301, 918, 1072, 911, 554, 240, + 241, 242, 818, 406, 407, 538, 245, 310, 311, 231, + 110, 232, 111, 324, 317, 318, 995, 717, 806, 595, + 596, 597, 598, 599, 205, 600, 602, 604, 236, 1151, + 370, 609, 681, 807, 370, 325, 371, 1059, 616, 326, + 1062, 1063, 1064, 622, 623, -781, 626, 629, 630, 687, + 635, 636, 762, 109, 981, 257, 257, 381, 382, 383, + 186, 658, 216, 110, 116, 111, 110, 110, 111, 111, + 110, 798, 111, 271, 271, 117, 271, 271, 271, 271, + 271, 320, 271, -782, 271, 231, 271, 232, 110, 728, + 111, 118, 688, 240, 241, 242, 245, 354, 355, -783, + 321, 237, 472, 271, 386, 393, 110, 110, 111, 111, + 110, 119, 111, 363, 365, 367, 271, 271, 689, -781, + 773, 473, -781, 271, 271, 110, 216, 111, 326, 352, + 976, 977, 120, 1057, 980, 586, 1171, 1173, 1175, 1141, + 602, 609, 110, 993, 111, 320, 1525, 539, -784, 919, + 1148, 919, 240, 996, 698, 489, 997, -782, 121, 718, + -782, 1091, 328, 1134, 512, 110, 1137, 111, 384, 122, + 362, 364, 366, -783, 405, 112, -783, 1230, 617, 1201, + 185, 1231, 1232, 372, 1144, 1217, 406, 407, 373, 884, + 1067, 1068, 257, 257, 123, 834, 1138, 114, 410, 408, + 981, 228, 229, 230, 409, 1239, 385, 751, 257, 257, + 257, 1139, 1140, 378, 932, 115, 124, 892, 320, 966, + 681, 808, -784, 1240, 1049, -784, 125, 454, 740, 741, + 742, 110, 273, 111, 126, 1024, 1070, 851, 279, 1419, + 281, 320, 283, 127, 285, 286, 287, 288, 289, 290, + 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, + 957, 225, 226, 227, 271, 228, 229, 230, 681, 809, + 1225, 1424, 309, 260, 261, 1525, 313, 128, 314, 315, + 129, 1221, 527, 586, 509, 1535, 1536, 1537, 130, 529, + 530, 1157, 216, 982, 1433, 1158, 1159, 582, 548, 1465, + 320, 1, 2, 3, 1386, 994, 320, 961, 1413, -2, + 1414, 131, 1415, 320, 132, 1416, 1417, 1418, 1161, 958, + 528, 1023, 306, 307, 320, 959, 133, 528, 528, 1192, + 1168, 1399, 960, 454, 134, 188, 189, 190, 542, 545, + 782, 156, 783, 1021, 784, 1461, 162, 320, 1193, 1391, + 1392, 405, 1202, 1204, 769, 405, 587, 110, 883, 111, + 358, 976, 977, 406, 407, 980, 1486, 406, 407, 320, + 1552, 320, 454, 454, 454, 454, 454, 135, 454, 454, + 454, 410, 408, 320, 454, 136, 1149, 409, 1487, 137, + 1488, 454, 267, 10, 191, 11, 454, 454, 138, 454, + 454, 454, 1489, 454, 454, 1234, 139, 192, 193, 140, + 1532, 1533, 1534, 141, 1535, 1536, 1537, 142, 361, 685, + 488, 1491, 368, 369, 143, 223, 224, 225, 226, 227, + 1143, 228, 229, 230, 1076, 1077, 748, 393, 672, 686, + 1492, 1181, 1495, 676, 677, 678, 194, 195, 1035, 196, + 1036, 144, 682, 683, 684, 197, 1498, 198, 157, 1033, + 1190, 1496, 548, 981, 1160, 328, 378, 1200, 214, 215, + 1054, 993, 1167, 1406, 1058, 1499, 528, 1396, 714, 216, + 158, 528, 528, 528, 320, 163, 1621, 320, 1658, 320, + 528, 528, 528, 454, 454, 320, 509, 320, 154, 152, + 320, 963, 164, 1578, 153, 1622, 1632, 1659, 1669, 6, + 697, -102, 319, -102, 1670, -102, 1671, 326, 1435, 1672, + 1436, 165, 778, 235, 1153, 1154, 1155, 1220, 1052, 517, + 518, 1157, 1158, 1159, 188, 189, 190, 213, 214, 215, + 1555, 531, 532, 533, 1228, 1068, 788, 789, 244, 216, + 266, 188, 189, 190, 793, 302, 794, 304, 410, 408, + 454, 359, 410, 408, 409, 553, 454, 305, 409, 1206, + 782, 1207, 783, -102, 1142, -102, 6, -102, 592, 593, + 1177, 1178, 1179, 1209, 1237, 1238, 648, 312, 649, 380, + 650, 775, 395, 191, 1139, 1140, 803, 379, -280, 1473, + 804, 805, 455, 618, 396, 714, 192, 193, 397, 463, + 191, 1525, 223, 224, 225, 226, 227, 320, 228, 229, + 230, 465, 930, 192, 193, 1235, 1139, 1140, 1226, 800, + 456, 956, 457, 934, 528, 935, 936, 937, 528, 528, + 542, 877, 458, 626, 820, 194, 195, 459, 196, 1139, + 1140, 1393, 460, 470, 197, 838, 198, 1139, 1140, 1457, + 921, 461, 194, 195, 462, 196, 464, 466, 467, 468, + 469, 197, 492, 198, 381, 382, 383, 945, 670, 471, + 474, 946, 223, 224, 225, 226, 227, 475, 228, 229, + 230, 675, 476, 1012, 713, 679, 680, 908, 477, -281, + 497, 199, 478, 479, 480, 200, 745, 504, 481, 482, + 201, 454, 483, 6, 381, 382, 383, 1041, 484, 822, + 485, 1042, 968, 486, 909, 493, 494, 947, 496, 498, + 154, 152, 500, 501, 507, 1455, 153, 931, 6, 1459, + 514, 1612, 1613, 1614, 1530, 1531, 1532, 1533, 1534, 516, + 1535, 1536, 1537, 549, 509, 1406, 956, 537, -206, 552, + 528, 746, 588, 956, 750, 930, 590, 1043, 930, 930, + 930, 820, 820, 820, 591, 606, 820, 328, 610, 611, + 612, 613, 614, 615, 948, 384, 619, 1462, 620, 328, + 800, 956, 621, 956, 624, 548, 956, 646, 647, 673, + 654, 652, 271, -282, 774, 695, 246, 653, 247, 681, + 248, 655, 656, 692, 949, 840, 841, 842, 690, 844, + 699, 846, 700, 847, 848, 384, 701, 703, 950, 708, + 1150, 1044, 908, 951, 908, 707, 716, 765, 952, -213, + 776, 786, 797, 801, 802, 790, 798, 791, 835, 792, + 1674, 795, -373, 839, 1045, 843, 249, 831, 1676, 845, + 832, 833, 850, 879, 112, 882, 820, 881, 1046, 885, + 1522, 1523, 1524, 1047, 886, 378, 887, 888, 1048, 378, + 931, 889, 1525, 931, 931, 931, 890, 891, 893, 910, + 933, 913, 914, 967, 973, 915, 984, 154, 152, 1080, + 956, 969, 1087, 153, 830, 930, -290, 1006, 1010, 930, + 930, 1007, 970, 800, 328, 1479, 1480, 1481, 971, 821, + 250, 822, 972, 823, 1011, 257, 1009, 1013, 1015, 378, + 378, 378, 112, 820, 956, 1016, 1017, 820, 820, 1026, + 542, 1027, 1028, 251, 1029, 1030, 1031, 381, 382, 383, + 810, 1037, 542, 1034, 811, 1038, 1055, 252, 1056, 1060, + 586, 1482, 253, 1078, 1484, 6, 1081, 254, 1082, 824, + 908, 1089, 981, 1180, 582, 993, 1547, 1183, 1191, 956, + 956, 974, 1185, 1184, 6, 978, 979, 1196, 1186, 983, + 1194, 6, 1187, 986, 820, 820, 454, 990, 991, 1188, + 812, 1197, 820, 820, 820, 1212, 1198, 820, 1219, 1008, + 1540, 328, 1199, 1401, 1544, 1530, 1531, 1532, 1533, 1534, + 931, 1535, 1536, 1537, 931, 931, 1213, 542, 1222, 1223, + 378, 1053, 1224, 825, 1241, 1227, 1068, 1236, 1242, 1383, + 1384, 1387, 1087, 988, 989, 1388, 1389, 992, 1398, 1400, + 1408, 1402, 1407, 1403, 112, 1404, 826, 1606, 384, 1410, + 1405, 1411, 1425, 1426, 813, 1610, 1427, 1428, 1429, 1430, + 827, 1615, 1616, 930, 1434, 828, 1431, 519, 1432, 520, + 829, 521, 1454, 1420, 1421, 1458, 1422, 814, 1423, 1467, + 1468, 1463, 1470, 1061, 1464, 1478, 1604, 1065, 1066, 542, + 1069, 815, 112, 1476, 1490, 800, 816, 1493, 257, 1494, + 1501, 817, 1500, 1502, 1634, 820, 1090, 1637, 1497, 1503, + 1135, 1136, 1507, 1541, 1548, 1050, 1145, 522, 1545, 1561, + 1549, 1146, 1550, 1562, 1563, 1553, 1559, 1560, 1564, 1152, + 1565, 1566, 1567, 1156, 1568, 1569, 1574, 1608, 1655, 1577, + 1602, 1605, 204, 1617, 1162, 1163, 1609, 1635, 1611, 1620, + 1624, 1219, 1619, 1219, 1623, 1625, 1664, 1626, 1628, 1629, + 1641, 1636, 1643, 820, 820, 820, 1642, 243, 1644, 1645, + 1646, 1647, 509, 1648, 1649, 1656, 509, 1650, 931, 1651, + 1666, 523, 378, 1654, 1657, 1667, 1668, 265, 271, 271, + 1675, 1677, 1466, 753, 1164, 1477, 1538, 1210, 1165, 1166, + 768, 1618, 1214, 1475, 524, 853, 1215, 1216, 381, 382, + 383, 922, 706, 770, 1182, 923, 1469, 506, 525, 956, + 1229, 0, 0, 526, 0, 67, 303, 1520, 1521, 1522, + 1523, 1524, 956, 0, 0, 0, 0, 0, 0, 0, + 0, 1525, 0, 1203, 1205, 0, 0, 0, 0, 1385, + 0, 0, 988, 989, 0, 0, 992, 0, 0, 0, + 0, 924, 0, 0, 0, 0, 0, 0, 0, 0, + 155, 0, 0, 0, 0, 0, 161, 322, 323, 0, + 0, 0, 166, 167, 168, 169, 170, 0, 956, 206, + 0, 0, 0, 1390, 0, 0, 188, 189, 190, 0, + 0, 0, 0, 0, 0, 350, 0, 1080, 0, 1516, + 1517, 1518, 1519, 1520, 1521, 1522, 1523, 1524, 1437, 384, + 0, 0, 0, 0, 360, 925, 0, 1525, 0, 1516, + 1517, 1518, 1519, 1520, 1521, 1522, 1523, 1524, 392, 394, + 1514, 112, 0, 0, 587, 0, 0, 1525, 926, 0, + 112, 0, 509, 509, 509, 191, 378, 0, 0, 378, + 112, 0, 927, 0, 0, 0, 0, 928, 192, 193, + 1409, 0, 0, 1438, 1530, 1531, 1532, 1533, 1534, 0, + 1535, 1536, 1537, 490, 491, 0, 316, 820, 0, 495, + 0, 0, 0, 0, 0, 1514, 0, 0, 0, 0, + 0, 204, 0, 0, 0, 378, 0, 194, 195, 378, + 196, 0, 0, 509, 1523, 1524, 197, 0, 198, 0, + 1087, 0, 1164, 1165, 1166, 1525, 1600, 0, 0, 1001, + 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, + 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, + 349, 0, 1453, 353, 1526, 1527, 1528, 1529, 357, 0, + 1530, 1531, 1532, 1533, 1534, 0, 1535, 1536, 1537, 0, + 0, 0, 1631, 265, 1526, 1527, 1528, 1529, 0, 589, + 1530, 1531, 1532, 1533, 1534, 0, 1535, 1536, 1537, 411, + 0, 378, 0, 0, 509, 0, 0, 0, 0, 0, + 0, 0, 509, 0, 0, 800, 800, 800, 509, 509, + 0, 1196, 0, 0, 0, 0, 0, 0, 0, 0, + 634, 0, 0, 0, 0, 487, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1660, 1661, 1662, + 0, 1663, 502, 503, 0, 0, 0, 1474, 0, 510, + 0, 509, 378, 0, 509, 0, 1513, 0, 1530, 1531, + 1532, 1533, 1534, 0, 1535, 1536, 1537, 0, 1483, 0, + 0, 1485, 0, 0, 209, 210, 211, 212, 213, 214, + 215, 0, 322, 73, 0, 509, 75, 76, 77, 78, + 216, 188, 189, 190, 0, 0, 0, 674, 0, 238, + 0, 0, 541, 509, 0, 0, 1570, 1571, 1572, 1573, + 0, 1575, 0, 1576, 800, 1539, 0, 0, 85, 1543, + 691, 0, 800, 1546, 0, 0, 0, 0, 0, 265, + 0, 0, 0, 0, 0, 239, 1554, 0, 0, 1556, + 1557, 1558, 0, 0, 0, 605, 1409, 0, 0, 0, + 191, 0, 0, 0, 0, 0, 0, 87, 88, 0, + 0, 0, 0, 192, 193, 0, 0, 0, 0, 747, + 749, 0, 0, 0, 93, 0, 0, 0, 1453, 95, + 1453, 1453, 1453, 1453, 1453, 755, 1453, 756, 757, 758, + 759, 760, 761, 0, 0, 763, 0, 0, 0, 0, + 0, 0, 194, 195, 0, 196, 0, 1607, 0, 771, + 772, 197, 0, 198, 0, 0, 0, 0, 780, 502, + 220, 221, 222, 223, 224, 225, 226, 227, 0, 228, + 229, 230, 0, 0, 671, 0, 0, 0, 1452, 0, + 0, 7, 8, 9, 10, 505, 11, 12, 13, 0, + 201, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, + 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, 1453, + 1638, 0, 0, 0, 0, 1639, 1640, 209, 210, 211, + 212, 213, 214, 215, 0, 0, 0, 0, 0, 1439, + 0, 0, 0, 216, 1653, 0, 0, 709, 710, 711, + 712, 0, 715, 0, 0, 1440, 0, 0, 0, 0, + 1441, 744, 1453, 0, 0, 1665, 0, 875, 0, 24, + 25, 0, 0, 0, 1673, 27, 0, 0, 0, 29, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 0, 0, 764, 208, 209, + 210, 211, 212, 213, 214, 215, 0, 48, 0, 49, + 0, 0, 0, 1453, 1442, 216, 1453, 0, 0, 1443, + 0, 0, 1444, 0, 964, 0, 0, 55, 1517, 1518, + 1519, 1520, 1521, 1522, 1523, 1524, 0, 0, 796, 0, + 0, 0, 0, 0, 0, 1525, 0, 0, 0, 985, + 0, 0, 1445, 0, 541, 1446, 1447, 1448, 0, 0, + 1449, 0, 1450, 65, 0, 0, 1451, 0, 0, 0, + 0, 0, 1014, 0, 221, 222, 223, 224, 225, 226, + 227, 849, 228, 229, 230, 0, 0, 0, 0, 0, + 0, 0, 854, 855, 856, 857, 858, 859, 860, 861, + 862, 863, 864, 865, 866, 867, 868, 869, 870, 871, + 872, 873, 874, 0, 1506, 878, 1508, 1509, 1510, 1511, + 1512, 0, 1515, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1040, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 218, 219, 220, 221, 222, 223, 224, + 225, 226, 227, 0, 228, 229, 230, 944, 0, 0, + 387, 388, 389, 1075, 0, 555, 556, 557, 10, 0, + 11, 558, 559, 1527, 1528, 1529, 0, 560, 1530, 1531, + 1532, 1533, 1534, 0, 1535, 1536, 1537, 1579, 1580, 1581, + 1582, 1583, 1584, 1585, 1586, 1587, 1588, 1589, 1590, 1591, + 1592, 1593, 1594, 1595, 1596, 1597, 0, 0, 0, 0, + 110, 0, 111, 561, 0, 0, 0, 0, 0, 191, + 0, 0, 0, 1019, 0, 0, 0, 0, 1176, 562, + 0, 0, 192, 193, 563, 0, 0, 0, 0, 0, + 0, 0, 546, 564, 565, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 568, 0, 1509, 569, 570, 0, 0, 0, 571, - 0, 572, 0, 0, 0, 573, 300, 111, 0, 0, - 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, - 0, 0, 0, 622, 1595, 0, 0, 0, 0, 189, - 0, 0, 0, 0, 0, 0, 373, 0, 0, 503, - 0, 0, 190, 191, 0, 0, 1449, 503, 0, 0, - 816, 816, 816, 0, 0, 0, 1200, 319, 320, 994, - 0, 153, 0, 0, 0, 0, 0, 159, 0, 1000, - 1001, 0, 0, 164, 165, 166, 167, 168, 0, 0, - 204, 192, 193, 0, 194, 347, 0, 1020, 0, 195, - 0, 196, 0, 0, 0, 973, 503, 373, 0, 503, - 0, 1508, 0, 0, 357, 0, 0, 0, 973, 0, - 0, 0, 0, 0, 0, 0, 0, 387, 389, 197, - 0, 0, 0, 198, 0, 0, 0, 0, 199, 0, - 503, 0, 111, 1653, 1654, 1655, 0, 1656, 0, 0, - 0, 186, 187, 188, 0, 0, 503, 0, 0, 1565, - 1566, 1567, 1568, 0, 1570, 0, 1571, 816, 0, 0, - 0, 973, 484, 485, 0, 816, 0, 0, 489, 0, - 1071, 0, 0, 1074, 1075, 313, 1078, 0, 111, 0, - 202, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1099, 0, 0, 0, 1144, 1145, 0, 189, - 0, 0, 1154, 0, 0, 0, 0, 1155, 186, 187, - 188, 0, 190, 191, 0, 1161, 0, 0, 0, 326, - 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, - 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, - 0, 0, 350, 0, 0, 0, 0, 354, 0, 0, - 262, 192, 193, 0, 194, 583, 0, 0, 0, 195, - 0, 196, 0, 0, 0, 0, 189, 1501, 0, 1503, - 1504, 1505, 1506, 1507, 0, 1510, 0, 405, 0, 190, - 191, 0, 1216, 0, 0, 1217, 1218, 0, 0, 0, - 0, 0, 0, 499, 0, 0, 630, 0, 199, 1231, - 0, 0, 0, 0, 0, 0, 186, 187, 188, 0, - 0, 0, 0, 481, 0, 0, 0, 0, 192, 193, - 0, 194, 0, 0, 0, 0, 195, 1385, 196, 0, - 496, 497, 0, 0, 0, 0, 0, 504, 1574, 1575, - 1576, 1577, 1578, 1579, 1580, 1581, 1582, 1583, 1584, 1585, - 1586, 1587, 1588, 1589, 1590, 1591, 1592, 0, 319, 0, - 0, 0, 0, 0, 189, 0, 0, 0, 0, 0, - 0, 1390, 0, 670, 0, 0, 0, 190, 191, 0, - 549, 550, 551, 10, 0, 11, 552, 553, 535, 0, - 0, 0, 871, 0, 0, 0, 707, 0, 1407, 0, - 0, 1409, 0, 0, 0, 262, 0, 0, 0, 0, - 0, 0, 0, 0, 111, 0, 192, 193, 0, 194, - 0, 0, 0, 111, 195, 109, 196, 110, 555, 0, - 601, 0, 0, 111, 0, 7, 8, 9, 10, 0, - 11, 12, 13, 556, 1435, 763, 765, 1499, 557, 0, - 770, 0, 0, 1645, 0, 0, 0, 558, 559, 0, - 0, 0, 0, 771, 0, 772, 773, 774, 775, 776, - 777, 0, 0, 779, 206, 207, 208, 209, 210, 211, - 212, 213, 0, 1436, 0, 0, 0, 787, 788, 0, - 0, 214, 560, 0, 0, 561, 796, 562, 1437, 211, - 212, 213, 563, 1438, 496, 0, 564, 0, 0, 565, - 0, 214, 24, 25, 566, 0, 0, 567, 27, 667, - 0, 0, 29, 30, 31, 32, 33, 34, 35, 36, - 37, 38, 39, 40, 41, 42, 43, 44, 0, 568, - 0, 0, 569, 570, 0, 0, 0, 571, 0, 572, - 48, 0, 49, 573, 841, 0, 0, 1439, 0, 0, - 0, 1440, 0, 540, 1441, 0, 0, 0, 0, 55, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 725, 726, 727, 728, 0, 731, 0, 0, - 0, 0, 0, 0, 1442, 0, 760, 1443, 1444, 1445, - 0, 0, 1446, 0, 1500, 65, 0, 73, 1448, 74, - 75, 76, 77, 0, 0, 894, 1471, 216, 217, 218, - 219, 220, 221, 222, 223, 224, 225, 0, 226, 227, - 228, 0, 0, 0, 780, 0, 0, 0, 0, 0, - 0, 84, 221, 222, 223, 224, 225, 0, 226, 227, - 228, 0, 0, 0, 0, 0, 0, 0, 237, 0, - 0, 0, 0, 0, 549, 550, 551, 10, 0, 11, - 552, 553, 981, 0, 0, 812, 720, 0, 0, 86, - 87, 1534, 0, 0, 0, 1538, 0, 0, 0, 1541, - 535, 0, 0, 0, 0, 0, 92, 0, 0, 0, - 0, 94, 1549, 0, 0, 1551, 1552, 1553, 0, 0, - 0, 0, 555, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1026, 1517, 1518, 1519, 556, 0, 0, - 0, 0, 557, 0, 0, 0, 1520, 0, 868, 0, - 0, 558, 559, 0, 0, 0, 186, 187, 188, 873, - 874, 875, 876, 877, 878, 879, 880, 881, 882, 883, - 884, 885, 886, 887, 888, 889, 890, 891, 892, 893, - 0, 1602, 897, 0, 0, 0, 560, 0, 0, 561, - 0, 562, 1051, 1610, 1611, 0, 563, 0, 0, 0, - 564, 0, 0, 565, 0, 0, 0, 0, 566, 0, - 0, 567, 0, 0, 189, 0, 0, 0, 0, 0, - 0, 0, 1084, 0, 961, 0, 0, 190, 191, 0, - 0, 0, 0, 568, 0, 0, 569, 570, 0, 0, - 0, 571, 0, 721, 1633, 0, 0, 573, 0, 7, - 8, 9, 10, 0, 11, 12, 13, 169, 71, 0, - 0, 535, 0, 0, 0, 0, 192, 193, 1646, 194, - 0, 0, 535, 0, 195, 0, 196, 1525, 1526, 1527, - 1528, 1529, 1180, 1530, 1531, 1532, 0, 1658, 0, 0, - 0, 259, 0, 1031, 0, 0, 1666, 15, 72, 0, - 0, 170, 0, 171, 172, 173, 174, 78, 79, 0, - 0, 0, 21, 80, 0, 0, 175, 23, 0, 1213, - 82, 0, 0, 0, 0, 0, 24, 25, 176, 0, - 0, 0, 27, 0, 0, 177, 29, 30, 31, 32, - 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, - 43, 44, 178, 0, 0, 0, 382, 383, 384, 0, - 0, 46, 0, 47, 48, 0, 49, 0, 186, 187, - 188, 50, 0, 179, 180, 53, 0, 0, 54, 88, - 0, 0, 0, 55, 1095, 0, 56, 89, 90, 91, - 181, 0, 0, 93, 0, 182, 0, 0, 0, 0, - 0, 597, 0, 0, 0, 0, 0, 0, 59, 0, - 0, 60, 61, 62, 189, 0, 63, 0, 64, 65, - 0, 0, 66, 0, 0, 0, 189, 190, 191, 0, - 0, 0, 0, 1173, 0, 0, 0, 0, 0, 190, - 191, 0, 0, 0, 0, 0, 0, 0, 0, 407, - 0, 1031, 0, 0, 0, 0, 1193, 408, 409, 410, - 411, 0, 0, 0, 0, 0, 385, 193, 0, 194, - 413, 414, 415, 416, 195, 0, 196, 0, 192, 1010, - 1011, 1012, 0, 590, 0, 0, 195, 0, 196, 205, - 206, 207, 208, 209, 210, 211, 212, 213, 0, 1013, - 0, 535, 0, 380, 1014, 0, 0, 214, 426, 1084, - 0, 0, 0, 0, 0, 0, 1095, 0, 0, 431, - 0, 0, 0, 0, 0, 432, 0, 0, 0, 434, - 435, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 438, 0, 439, 0, 1245, 1246, 1247, 1248, 1249, - 1250, 1251, 1252, 1253, 1254, 1255, 0, 1256, 1257, 1258, - 1259, 1260, 1261, 1262, 1263, 1264, 1265, 1266, 1267, 0, - 0, 1394, 0, 535, 0, 1397, 1268, 1269, 1270, 1271, - 1272, 1273, 1274, 1275, 1276, 1277, 1278, 1279, 1280, 1281, - 1282, 1283, 1284, 1285, 1286, 0, 0, 1287, 1288, 1289, - 1290, 1291, 1292, 1293, 1294, 1295, 1296, 1297, 1298, 1299, - 1300, 1301, 1302, 1303, 1304, 0, 1305, 0, 1306, 1307, - 1308, 1309, 1310, 1311, 1312, 1313, 1314, 1315, 0, 1316, - 1317, 1318, 215, 216, 217, 218, 219, 220, 221, 222, - 223, 224, 225, 0, 226, 227, 228, 0, 1319, 0, - 507, 0, 0, 0, 0, 1320, 1321, 1322, 1323, 1324, - 1325, 1326, 1327, 1328, 1329, 1330, 1331, 1332, 1333, 1334, - 1335, 1336, 1337, 1338, 1339, 1340, 1341, 1342, 1343, 1344, - 1345, 1346, 1347, 1348, 1349, 1350, 1351, 1352, 1353, 1354, - 1355, 1356, 1357, 633, 634, 0, 1358, 1359, 1360, 1361, - 1362, 1363, 1364, 1365, 1366, 1367, 1368, 1369, 1370, 1371, - 1372, 1373, 1374, 1375, 1376, 1377, 1378, 1546, 1379, 1380, - 0, 0, 0, 186, 187, 188, 0, 0, 0, 186, - 187, 188, 0, 0, 0, 394, 0, 0, 73, 0, - 74, 75, 76, 77, 78, 0, 0, 0, 0, 0, - 395, 0, 0, 81, 0, 0, 73, 82, 74, 75, - 76, 77, 0, 0, 0, 83, 0, 0, 0, 0, - 0, 236, 84, 0, 0, 0, 0, 0, 0, 0, - 0, 189, 0, 0, 0, 0, 0, 189, 0, 85, - 84, 0, 0, 0, 190, 191, 0, 0, 0, 1593, - 190, 191, 635, 0, 0, 0, 0, 237, 1469, 0, - 86, 87, 0, 0, 0, 0, 88, 0, 0, 0, - 0, 0, 0, 0, 396, 397, 91, 92, 86, 87, - 93, 0, 94, 192, 193, 0, 194, 636, 1622, 192, - 193, 195, 194, 196, 0, 92, 0, 195, 0, 196, - 94, 0, 0, 637, 1013, 0, 0, 0, 0, 1174, - 1013, 0, 1245, 1246, 1247, 1248, 1249, 1250, 1251, 1252, - 1253, 1254, 1255, 143, 1256, 1257, 1258, 1259, 1260, 1261, - 1262, 1263, 1264, 1265, 1266, 1267, 0, 0, 0, 0, - 0, 0, 1095, 1268, 1269, 1270, 1271, 1272, 1273, 1274, - 1275, 1276, 1277, 1278, 1279, 1280, 1281, 1282, 1283, 1284, - 1285, 1286, 0, 0, 1287, 1288, 1289, 1290, 1291, 1292, - 1293, 1294, 1295, 1296, 1297, 1298, 1299, 1300, 1301, 1302, - 1303, 1304, 0, 1305, 0, 1306, 1307, 1308, 1309, 1310, - 1311, 1312, 1313, 1314, 1315, 0, 1316, 1317, 1318, 0, - 0, 0, 0, 0, 0, 0, 1596, 0, 0, 0, - 0, 0, 0, 0, 0, 1319, 0, 0, 0, 0, - 0, 0, 1320, 1321, 1322, 1323, 1324, 1325, 1326, 1327, - 1328, 1329, 1330, 1331, 1332, 1333, 1334, 1335, 1336, 1337, - 1338, 1339, 1340, 1341, 1342, 1343, 1344, 1345, 1346, 1347, - 1348, 1349, 1350, 1351, 1352, 1353, 1354, 1355, 1356, 1357, - 0, 0, 0, 1358, 1359, 1360, 1361, 1362, 1363, 1364, - 1365, 1366, 1367, 1368, 1369, 1370, 1371, 1372, 1373, 1374, - 1375, 1376, 1377, 1378, 0, 1379, 1380, 7, 8, 9, - 10, 0, 11, 12, 13, 393, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 205, - 206, 207, 208, 209, 210, 211, 212, 213, 0, 0, - 0, 0, 0, 0, 0, 15, 394, 214, 0, 170, - 0, 171, 172, 173, 174, 78, 0, 0, 0, 0, - 21, 395, 0, 0, 175, 23, 0, 0, 82, 0, - 0, 0, 0, 0, 24, 25, 176, 0, 0, 0, - 27, 0, 0, 177, 29, 30, 31, 32, 33, 34, - 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, - 178, 0, 0, 0, 0, 0, 0, 0, 0, 46, - 0, 47, 48, 0, 49, 0, 0, 0, 0, 50, - 0, 179, 180, 53, 0, 0, 54, 88, 0, 0, - 0, 55, 0, 0, 56, 396, 397, 91, 181, 0, - 0, 93, 0, 182, 7, 8, 9, 10, 0, 11, - 12, 13, 14, 0, 0, 0, 59, 0, 0, 60, - 61, 62, 0, 0, 63, 0, 64, 65, 0, 0, - 66, 0, 215, 216, 217, 218, 219, 220, 221, 222, - 223, 224, 225, 0, 226, 227, 228, 0, 0, 0, - 1034, 0, 15, 0, 0, 0, 16, 0, 17, 18, - 19, 20, 0, 0, 0, 0, 0, 21, 0, 958, - 959, 22, 23, 0, 0, 0, 0, 0, 0, 0, - 0, 24, 25, 26, 0, 0, 0, 27, 0, 0, - 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, - 38, 39, 40, 41, 42, 43, 44, 45, 0, 0, - 0, 0, 0, 0, 0, 0, 46, 0, 47, 48, - 0, 49, 0, 0, 0, 0, 50, 0, 51, 52, - 53, 0, 0, 54, 0, 0, 0, 0, 55, 0, - 0, 56, 0, 0, 0, 57, 7, 8, 9, 10, - 58, 11, 12, 13, 14, 960, 0, 0, 157, 0, - 0, 0, 0, 59, 0, 0, 60, 61, 62, 0, - 0, 63, 0, 64, 65, 0, 0, 66, 205, 206, - 207, 208, 209, 210, 211, 212, 213, 0, 0, 0, - 0, 0, 0, 0, 15, 0, 214, 0, 16, 0, - 17, 18, 19, 20, 0, 0, 0, 0, 0, 21, - 0, 0, 0, 22, 23, 0, 0, 0, 0, 0, - 0, 0, 0, 24, 25, 26, 0, 0, 0, 27, - 0, 0, 28, 29, 30, 31, 32, 33, 34, 35, - 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, - 0, 0, 0, 0, 0, 0, 0, 0, 46, 0, - 47, 48, 0, 49, 0, 0, 0, 0, 50, 0, - 51, 52, 53, 0, 0, 54, 0, 0, 0, 0, - 55, 0, 0, 56, 0, 0, 0, 57, 7, 8, - 9, 10, 58, 11, 12, 13, 14, 0, 0, 0, - 0, 0, 0, 0, 0, 59, 0, 0, 60, 61, - 62, 0, 0, 63, 0, 158, 65, 0, 0, 66, - 0, 215, 216, 217, 218, 219, 220, 221, 222, 223, - 224, 225, 0, 226, 227, 228, 15, 0, 0, 1628, - 16, 0, 17, 18, 19, 20, 0, 0, 0, 0, - 0, 21, 0, 0, 0, 22, 23, 0, 0, 0, - 0, 0, 0, 0, 0, 24, 25, 26, 0, 0, - 0, 27, 0, 0, 28, 29, 30, 31, 32, 33, + 0, 0, 0, 0, 0, 0, 1211, 0, 0, 0, + 0, 390, 195, 0, 196, 0, 0, 0, 566, 0, + 197, 567, 198, 568, 0, 0, 73, 0, 569, 75, + 76, 77, 78, 570, 0, 0, 571, 0, 0, 0, + 0, 572, 1652, 0, 573, 0, 391, 7, 8, 9, + 10, 0, 11, 12, 13, 14, 1086, 0, 0, 0, + 0, 85, 0, 0, 0, 0, 574, 0, 0, 575, + 576, 0, 0, 0, 577, 0, 578, 0, 239, 0, + 579, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 541, 15, 0, 0, 0, 16, + 87, 88, 17, 18, 19, 20, 541, 0, 0, 0, + 1169, 21, 0, 941, 942, 22, 23, 93, 0, 0, + 0, 0, 95, 0, 0, 24, 25, 26, 1019, 0, + 0, 27, 0, 1189, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 0, 0, 0, 0, 0, 0, 0, 0, 46, 0, 47, 48, 0, 49, 0, 0, 0, 0, - 50, 0, 51, 52, 53, 0, 0, 54, 0, 0, - 0, 0, 55, 0, 0, 56, 0, 0, 0, 57, - 7, 8, 9, 10, 58, 11, 12, 13, 14, 0, - 0, 0, 0, 0, 0, 0, 0, 59, 0, 0, - 60, 61, 62, 0, 0, 63, 0, 64, 65, 348, - 0, 66, 205, 206, 207, 208, 209, 210, 211, 212, - 213, 0, 0, 0, 0, 0, 0, 0, 15, 353, - 214, 0, 16, 0, 17, 18, 19, 20, 0, 0, - 0, 0, 0, 21, 0, 0, 0, 22, 23, 0, - 0, 0, 0, 0, 0, 0, 0, 24, 25, 26, - 0, 0, 0, 27, 0, 0, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, - 42, 43, 44, 45, 0, 0, 0, 0, 0, 0, - 0, 0, 46, 0, 47, 48, 0, 49, 0, 0, - 0, 0, 50, 0, 51, 52, 53, 0, 0, 54, - 0, 0, 0, 0, 55, 0, 0, 56, 0, 0, + 50, 0, 0, 51, 52, 53, 0, 0, 54, 0, + 0, 541, 0, 55, 0, 0, 56, 0, 0, 0, + 57, 0, 0, 0, 0, 58, 1086, 0, 0, 0, + 943, 0, 0, 0, 0, 1075, 0, 0, 59, 0, + 0, 60, 61, 62, 0, 0, 63, 0, 64, 65, + 0, 0, 66, 0, 0, 1243, 1244, 1245, 1246, 1247, + 1248, 1249, 1250, 1251, 1252, 1253, 0, 1254, 1255, 1256, + 1257, 1258, 1259, 1260, 1261, 1262, 1263, 1264, 1265, 0, + 0, 1394, 0, 541, 0, 1397, 1266, 1267, 1268, 1269, + 1270, 1271, 1272, 1273, 1274, 1275, 1276, 1277, 1278, 1279, + 1280, 1281, 1282, 1283, 1284, 0, 0, 1285, 1286, 1287, + 1288, 1289, 1290, 1291, 1292, 1293, 1294, 1295, 1296, 1297, + 1298, 1299, 1300, 1301, 1302, 1303, 0, 1304, 0, 1305, + 1306, 1307, 1308, 1309, 1310, 1311, 1312, 1313, 1314, 0, + 1315, 1316, 1317, 207, 208, 209, 210, 211, 212, 213, + 214, 215, 0, 0, 0, 0, 0, 0, 0, 1318, + 0, 216, 0, 0, 0, 0, 1319, 1320, 1321, 1322, + 1323, 1324, 1325, 1326, 1327, 1328, 1329, 1330, 1331, 1332, + 1333, 1334, 1335, 1336, 1337, 1338, 1339, 1340, 1341, 1342, + 1343, 1344, 1345, 1346, 1347, 1348, 1349, 1350, 1351, 1352, + 1353, 1354, 1355, 1356, 1357, 0, 637, 638, 1358, 1359, + 1360, 1361, 1362, 1363, 1364, 1365, 1366, 1367, 1368, 1369, + 1370, 1371, 1372, 1373, 1374, 1375, 1376, 1377, 1378, 1551, + 1379, 1380, 0, 73, 0, 0, 75, 76, 77, 78, + 0, 0, 0, 0, 0, 188, 189, 190, 399, 0, + 0, 73, 400, 0, 75, 76, 77, 78, 79, 0, + 0, 387, 388, 389, 401, 0, 0, 82, 85, 0, + 0, 83, 0, 0, 0, 0, 0, 0, 0, 84, + 0, 0, 0, 0, 0, 239, 85, 0, 217, 218, + 219, 220, 221, 222, 223, 224, 225, 226, 227, 0, + 228, 229, 230, 86, 191, 0, 513, 87, 88, 0, + 0, 0, 0, 0, 0, 0, 639, 192, 193, 0, + 191, 0, 0, 0, 93, 87, 88, 1472, 0, 95, + 0, 89, 1598, 192, 193, 0, 0, 0, 0, 402, + 403, 92, 93, 0, 0, 94, 0, 95, 0, 0, + 0, 0, 640, 0, 0, 0, 194, 195, 0, 196, + 0, 0, 0, 0, 0, 197, 0, 198, 641, 0, + 0, 1627, 390, 195, 0, 196, 0, 0, 0, 0, + 0, 197, 262, 198, 1243, 1244, 1245, 1246, 1247, 1248, + 1249, 1250, 1251, 1252, 1253, 0, 1254, 1255, 1256, 1257, + 1258, 1259, 1260, 1261, 1262, 1263, 1264, 1265, 0, 0, + 385, 0, 0, 0, 1086, 1266, 1267, 1268, 1269, 1270, + 1271, 1272, 1273, 1274, 1275, 1276, 1277, 1278, 1279, 1280, + 1281, 1282, 1283, 1284, 0, 0, 1285, 1286, 1287, 1288, + 1289, 1290, 1291, 1292, 1293, 1294, 1295, 1296, 1297, 1298, + 1299, 1300, 1301, 1302, 1303, 0, 1304, 0, 1305, 1306, + 1307, 1308, 1309, 1310, 1311, 1312, 1313, 1314, 0, 1315, + 1316, 1317, 0, 0, 0, 0, 0, 0, 0, 0, + 1601, 0, 0, 0, 0, 0, 0, 0, 1318, 0, + 0, 0, 0, 0, 0, 1319, 1320, 1321, 1322, 1323, + 1324, 1325, 1326, 1327, 1328, 1329, 1330, 1331, 1332, 1333, + 1334, 1335, 1336, 1337, 1338, 1339, 1340, 1341, 1342, 1343, + 1344, 1345, 1346, 1347, 1348, 1349, 1350, 1351, 1352, 1353, + 1354, 1355, 1356, 1357, 0, 0, 0, 1358, 1359, 1360, + 1361, 1362, 1363, 1364, 1365, 1366, 1367, 1368, 1369, 1370, + 1371, 1372, 1373, 1374, 1375, 1376, 1377, 1378, 0, 1379, + 1380, 7, 8, 9, 10, 0, 11, 12, 13, 171, + 71, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 207, 208, 209, 210, 211, 212, 213, + 214, 215, 0, 0, 0, 0, 0, 0, 0, 15, + 72, 216, 0, 172, 74, 0, 173, 174, 175, 176, + 79, 80, 0, 0, 0, 21, 81, 0, 0, 177, + 23, 0, 0, 83, 0, 0, 0, 0, 0, 24, + 25, 178, 0, 0, 0, 27, 0, 0, 179, 29, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 180, 0, 0, 0, 0, + 0, 0, 0, 0, 46, 0, 47, 48, 0, 49, + 0, 0, 0, 0, 50, 0, 0, 181, 182, 53, + 0, 0, 54, 89, 0, 0, 0, 55, 0, 0, + 56, 90, 91, 92, 183, 0, 0, 94, 0, 184, + 7, 8, 9, 10, 0, 11, 12, 13, 398, 0, + 0, 0, 59, 0, 0, 60, 61, 62, 0, 0, + 63, 0, 64, 65, 0, 0, 66, 0, 217, 218, + 219, 220, 221, 222, 223, 224, 225, 226, 227, 0, + 228, 229, 230, 0, 0, 0, 1022, 0, 15, 399, + 0, 0, 172, 400, 0, 173, 174, 175, 176, 79, + 0, 0, 0, 0, 21, 401, 0, 0, 177, 23, + 0, 0, 83, 0, 0, 0, 0, 0, 24, 25, + 178, 0, 0, 0, 27, 0, 0, 179, 29, 30, + 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 180, 0, 0, 0, 0, 0, + 0, 0, 0, 46, 0, 47, 48, 0, 49, 0, + 0, 0, 0, 50, 0, 0, 181, 182, 53, 0, + 0, 54, 89, 0, 0, 0, 55, 0, 0, 56, + 402, 403, 92, 183, 0, 0, 94, 0, 184, 0, + 7, 8, 9, 10, 0, 11, 12, 13, 14, 0, + 0, 59, 159, 0, 60, 61, 62, 0, 0, 63, + 0, 64, 65, 0, 0, 66, 0, 0, 0, 0, + 0, 207, 208, 209, 210, 211, 212, 213, 214, 215, + 0, 0, 0, 0, 0, 0, 0, 0, 15, 216, + 0, 0, 16, 0, 0, 17, 18, 19, 20, 0, + 0, 0, 0, 0, 21, 0, 0, 0, 22, 23, + 0, 0, 0, 0, 0, 0, 0, 0, 24, 25, + 26, 0, 0, 0, 27, 0, 0, 28, 29, 30, + 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 0, 0, 0, 0, 0, + 0, 0, 0, 46, 0, 47, 48, 0, 49, 0, + 0, 0, 0, 50, 0, 0, 51, 52, 53, 0, + 0, 54, 0, 0, 0, 0, 55, 0, 0, 56, + 0, 0, 0, 57, 7, 8, 9, 10, 58, 11, + 12, 13, 14, 0, 0, 0, 0, 0, 0, 0, + 0, 59, 0, 0, 60, 61, 62, 0, 0, 63, + 0, 160, 65, 0, 0, 66, 217, 218, 219, 220, + 221, 222, 223, 224, 225, 226, 227, 0, 228, 229, + 230, 0, 15, 0, 1633, 0, 16, 0, 0, 17, + 18, 19, 20, 0, 0, 0, 0, 0, 21, 188, + 189, 190, 22, 23, 0, 0, 0, 0, 0, 0, + 0, 0, 24, 25, 26, 0, 0, 0, 27, 0, + 0, 28, 29, 30, 31, 32, 33, 34, 35, 36, + 37, 38, 39, 40, 41, 42, 43, 44, 45, 0, + 0, 0, 0, 0, 0, 0, 0, 46, 0, 47, + 48, 0, 49, 0, 0, 0, 0, 50, 191, 0, + 51, 52, 53, 0, 0, 54, 0, 0, 0, 0, + 55, 192, 193, 56, 0, 0, 0, 57, 7, 8, + 9, 10, 58, 11, 12, 13, 14, 0, 0, 0, + 0, 0, 0, 0, 0, 59, 0, 0, 60, 61, + 62, 0, 0, 63, 0, 64, 65, 351, 0, 66, + 194, 195, 0, 196, 0, 0, 0, 0, 0, 197, + 0, 198, 0, 0, 0, 0, 15, 356, 0, 0, + 16, 0, 0, 17, 18, 19, 20, 0, 0, 0, + 0, 0, 21, 0, 0, 754, 22, 23, 0, 0, + 0, 659, 0, 0, 0, 0, 24, 25, 26, 0, + 0, 0, 27, 0, 0, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, + 43, 44, 45, 0, 0, 0, 0, 0, 0, 0, + 0, 46, 0, 47, 48, 0, 49, 660, 0, 661, + 0, 50, 0, 0, 51, 52, 53, 0, 0, 54, + 0, 0, 0, 0, 55, 0, 662, 56, 0, 0, 0, 57, 7, 8, 9, 10, 58, 11, 12, 13, 14, 0, 0, 0, 0, 0, 0, 0, 0, 59, - 0, 0, 60, 61, 62, 0, 0, 63, 0, 64, - 65, 0, 1097, 66, 0, 215, 216, 217, 218, 219, - 220, 221, 222, 223, 224, 225, 0, 226, 227, 228, - 15, 759, 0, 0, 16, 0, 17, 18, 19, 20, - 0, 0, 0, 0, 0, 21, 0, 0, 0, 22, - 23, 0, 0, 0, 0, 0, 0, 0, 0, 24, - 25, 26, 0, 0, 0, 27, 0, 0, 28, 29, - 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, - 40, 41, 42, 43, 44, 45, 0, 0, 73, 0, - 74, 75, 76, 77, 46, 0, 47, 48, 0, 49, - 0, 0, 0, 0, 50, 0, 51, 52, 53, 0, - 0, 54, 0, 0, 0, 0, 55, 0, 0, 56, - 0, 0, 84, 57, 7, 8, 9, 10, 58, 11, - 12, 13, 14, 0, 0, 0, 0, 0, 0, 237, - 0, 59, 0, 0, 60, 61, 62, 0, 0, 63, - 0, 64, 65, 0, 0, 66, 0, 0, 0, 0, - 86, 87, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 15, 0, 0, 0, 16, 92, 17, 18, - 19, 20, 94, 0, 0, 0, 0, 21, 0, 0, - 0, 22, 23, 0, 0, 0, 0, 0, 0, 0, - 0, 24, 25, 26, 0, 155, 0, 27, 0, 0, - 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, - 38, 39, 40, 41, 42, 43, 44, 45, 0, 0, - 0, 0, 0, 0, 0, 0, 46, 0, 47, 48, - 0, 49, 0, 0, 0, 0, 50, 0, 51, 52, + 0, 0, 60, 61, 62, 0, 0, 63, 663, 64, + 65, 664, 665, 66, 0, 666, 0, 0, 207, 208, + 209, 210, 211, 212, 213, 214, 215, 0, 0, 0, + 15, 743, 667, 0, 16, 0, 216, 17, 18, 19, + 20, 0, 0, 0, 668, 0, 21, 0, 0, 0, + 22, 23, 0, 0, 0, 0, 0, 0, 669, 0, + 24, 25, 26, 0, 0, 0, 27, 0, 0, 28, + 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 0, 0, 0, + 0, 0, 0, 0, 0, 46, 0, 47, 48, 0, + 49, 0, 0, 0, 0, 50, 0, 0, 51, 52, 53, 0, 0, 54, 0, 0, 0, 0, 55, 0, 0, 56, 0, 0, 0, 57, 7, 8, 9, 10, 58, 11, 12, 13, 14, 0, 0, 0, 0, 0, 0, 0, 0, 59, 0, 0, 60, 61, 62, 0, - 0, 63, 0, 64, 65, 895, 0, 66, 205, 206, - 207, 208, 209, 210, 211, 212, 213, 0, 0, 0, - 0, 0, 0, 0, 15, 0, 214, 0, 16, 0, - 17, 18, 19, 20, 0, 0, 0, 0, 0, 21, - 0, 0, 0, 22, 23, 0, 0, 0, 0, 0, - 0, 0, 0, 24, 25, 26, 0, 0, 0, 27, - 0, 0, 28, 29, 30, 31, 32, 33, 34, 35, - 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, - 0, 0, 0, 0, 0, 0, 0, 0, 46, 0, - 47, 48, 0, 49, 0, 0, 0, 0, 50, 0, + 0, 63, 0, 64, 65, 0, 0, 66, 0, 0, + 0, 511, 0, 217, 218, 219, 220, 221, 222, 223, + 224, 225, 226, 227, 15, 228, 229, 230, 16, 0, + 0, 17, 18, 19, 20, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 22, 23, 0, 0, 0, 0, + 0, 0, 0, 0, 24, 25, 26, 0, 0, 0, + 27, 0, 0, 28, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 0, 0, 0, 0, 0, 0, 0, 0, 46, + 0, 47, 48, 0, 49, 0, 0, 0, 0, 50, + 0, 0, 51, 52, 53, 0, 0, 54, 0, 0, + 0, 0, 55, 0, 0, 56, 0, 0, 0, 57, + 7, 8, 9, 10, 58, 11, 12, 13, 14, 0, + 0, 0, 0, 0, 0, 0, 0, 59, 0, 0, + 60, 61, 62, 0, 0, 63, 0, 64, 65, 876, + 0, 66, 0, 0, 0, 0, 207, 208, 209, 210, + 211, 212, 213, 214, 215, 0, 0, 0, 15, 0, + 0, 0, 16, 0, 216, 17, 18, 19, 20, 0, + 0, 0, 0, 0, 21, 0, 0, 0, 22, 23, + 0, 0, 0, 0, 0, 0, 0, 0, 24, 25, + 26, 0, 0, 0, 27, 0, 0, 28, 29, 30, + 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 0, 0, 0, 0, 0, + 0, 0, 0, 46, 0, 47, 48, 0, 49, 0, + 0, 0, 0, 50, 0, 0, 51, 52, 53, 0, + 0, 54, 0, 0, 0, 0, 55, 0, 0, 56, + 0, 0, 0, 57, 7, 8, 9, 10, 58, 11, + 12, 13, 14, 1083, 0, 0, 0, 0, 0, 0, + 0, 59, 0, 0, 60, 61, 62, 0, 0, 63, + 0, 64, 65, 0, 0, 66, 0, 0, 0, 1020, + 0, 217, 218, 219, 220, 221, 222, 223, 224, 225, + 226, 227, 15, 228, 229, 230, 16, 0, 0, 17, + 18, 19, 20, 0, 0, 0, 0, 0, 21, 0, + 0, 0, 22, 23, 0, 0, 0, 0, 0, 0, + 0, 0, 24, 25, 26, 0, 0, 0, 27, 0, + 0, 28, 29, 30, 31, 32, 33, 34, 35, 36, + 37, 38, 39, 40, 41, 42, 43, 44, 45, 0, + 0, 0, 0, 0, 0, 0, 0, 46, 0, 47, + 48, 0, 49, 0, 0, 0, 0, 50, 0, 0, 51, 52, 53, 0, 0, 54, 0, 0, 0, 0, 55, 0, 0, 56, 0, 0, 0, 57, 7, 8, - 9, 10, 58, 11, 12, 13, 14, 1092, 0, 0, + 9, 10, 58, 11, 12, 13, 14, 1471, 0, 0, 0, 0, 0, 0, 0, 59, 0, 0, 60, 61, - 62, 0, 0, 63, 0, 64, 65, 1410, 0, 66, - 0, 215, 216, 217, 218, 219, 220, 221, 222, 223, - 224, 225, 0, 226, 227, 228, 15, 0, 0, 0, - 16, 0, 17, 18, 19, 20, 0, 0, 0, 0, - 0, 21, 0, 0, 0, 22, 23, 0, 0, 0, - 0, 0, 0, 0, 0, 24, 25, 26, 0, 0, - 0, 27, 0, 0, 28, 29, 30, 31, 32, 33, - 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, - 44, 45, 0, 0, 0, 0, 0, 0, 0, 0, - 46, 0, 47, 48, 0, 49, 0, 0, 0, 0, - 50, 0, 51, 52, 53, 0, 0, 54, 0, 0, - 0, 0, 55, 0, 0, 56, 0, 0, 0, 57, - 7, 8, 9, 10, 58, 11, 12, 13, 14, 1468, - 0, 0, 0, 0, 0, 0, 0, 59, 0, 0, - 60, 61, 62, 0, 0, 63, 0, 64, 65, 0, - 0, 66, 205, 206, 207, 208, 209, 210, 211, 212, - 213, 0, 0, 0, 0, 0, 0, 0, 15, 0, - 214, 0, 16, 0, 17, 18, 19, 20, 0, 0, - 0, 0, 0, 21, 0, 0, 0, 22, 23, 0, - 0, 0, 0, 0, 0, 0, 0, 24, 25, 26, - 0, 0, 0, 27, 0, 0, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, - 42, 43, 44, 45, 0, 0, 0, 0, 0, 0, - 0, 0, 46, 0, 47, 48, 0, 49, 0, 0, - 0, 0, 50, 0, 51, 52, 53, 0, 0, 54, + 62, 0, 0, 63, 0, 64, 65, 0, 0, 66, + 207, 208, 209, 210, 211, 212, 213, 214, 215, 0, + 0, 0, 0, 0, 0, 0, 15, 0, 216, 0, + 16, 0, 0, 17, 18, 19, 20, 0, 0, 0, + 0, 0, 21, 0, 0, 0, 22, 23, 0, 0, + 0, 0, 0, 0, 0, 0, 24, 25, 26, 0, + 0, 0, 27, 0, 0, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, + 43, 44, 45, 0, 0, 0, 0, 0, 0, 0, + 0, 46, 0, 47, 48, 0, 49, 0, 0, 0, + 0, 50, 0, 0, 51, 52, 53, 0, 0, 54, 0, 0, 0, 0, 55, 0, 0, 56, 0, 0, 0, 57, 7, 8, 9, 10, 58, 11, 12, 13, 14, 0, 0, 0, 0, 0, 0, 0, 0, 59, 0, 0, 60, 61, 62, 0, 0, 63, 0, 64, - 65, 1594, 0, 66, 0, 215, 216, 217, 218, 219, - 220, 221, 222, 223, 224, 225, 0, 226, 227, 228, - 15, 0, 0, 0, 16, 0, 17, 18, 19, 20, - 0, 0, 0, 0, 0, 21, 0, 0, 0, 22, - 23, 0, 0, 0, 0, 0, 0, 0, 0, 24, - 25, 26, 0, 0, 0, 27, 0, 0, 28, 29, - 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, - 40, 41, 42, 43, 44, 45, 0, 0, 0, 0, - 0, 0, 0, 0, 46, 0, 47, 48, 0, 49, - 0, 0, 0, 0, 50, 0, 51, 52, 53, 0, - 0, 54, 0, 0, 0, 0, 55, 0, 0, 56, - 0, 0, 0, 57, 7, 8, 9, 10, 58, 11, - 12, 13, 14, 0, 207, 208, 209, 210, 211, 212, - 213, 59, 0, 0, 60, 61, 62, 0, 0, 63, - 214, 64, 65, 0, 0, 66, 735, 736, 737, 738, - 739, 740, 741, 742, 743, 0, 0, 0, 0, 0, - 0, 0, 15, 0, 744, 0, 16, 0, 17, 18, - 19, 20, 0, 0, 0, 0, 0, 21, 0, 0, - 0, 22, 23, 0, 0, 0, 0, 0, 0, 0, - 0, 24, 25, 26, 0, 0, 0, 27, 0, 0, - 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, - 38, 39, 40, 41, 42, 43, 44, 45, 0, 0, - 0, 0, 0, 0, 0, 0, 46, 0, 47, 48, - 0, 49, 0, 0, 0, 0, 50, 0, 51, 52, + 65, 1599, 1088, 66, 0, 217, 218, 219, 220, 221, + 222, 223, 224, 225, 226, 227, 0, 228, 229, 230, + 15, 0, 0, 0, 16, 0, 0, 17, 18, 19, + 20, 0, 0, 0, 0, 0, 21, 0, 0, 0, + 22, 23, 0, 0, 0, 0, 0, 0, 0, 0, + 24, 25, 26, 0, 0, 0, 27, 0, 0, 28, + 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 0, 0, 0, + 0, 0, 0, 0, 0, 46, 0, 47, 48, 0, + 49, 0, 0, 0, 0, 50, 0, 0, 51, 52, 53, 0, 0, 54, 0, 0, 0, 0, 55, 0, 0, 56, 0, 0, 0, 57, 7, 8, 9, 10, - 58, 11, 12, 13, 0, 0, 216, 217, 218, 219, - 220, 221, 222, 223, 224, 225, 0, 226, 227, 228, - 0, 63, 0, 64, 65, 0, 0, 66, 0, 745, - 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, - 0, 756, 757, 758, 1436, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1437, - 0, 0, 0, 0, 1438, 0, 0, 0, 0, 0, - 0, 0, 0, 24, 25, 0, 0, 0, 0, 27, - 0, 0, 0, 29, 30, 31, 32, 33, 34, 35, - 36, 37, 38, 39, 40, 41, 42, 43, 44, 7, - 8, 9, 10, 0, 11, 12, 13, 0, 0, 0, - 0, 48, 0, 49, 0, 0, 0, 0, 1439, 0, - 0, 0, 1440, 0, 0, 1441, 0, 0, 0, 0, - 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1436, 0, 0, - 0, 0, 0, 0, 0, 1442, 0, 0, 1443, 1444, - 1445, 0, 1437, 1446, 0, 1447, 65, 1438, 0, 1448, - 209, 210, 211, 212, 213, 0, 24, 25, 0, 0, - 0, 0, 27, 0, 214, 0, 29, 30, 31, 32, - 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, - 43, 44, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 48, 0, 49, 0, 0, 0, - 0, 1439, 0, 0, 1101, 1440, 0, 0, 1441, 633, - 634, 0, 0, 55, 1102, 1103, 1104, 1105, 1106, 1107, - 1108, 1109, 1110, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1111, 0, 1112, 1113, 1114, 1115, 1116, 1117, - 1118, 1119, 1120, 1121, 1122, 1123, 1446, 0, 1447, 65, - 0, 394, 1448, 0, 73, 0, 74, 75, 76, 77, - 78, 0, 0, 0, 0, 0, 395, 1124, 0, 81, - 0, 0, 0, 82, 0, 0, 0, 0, 186, 187, - 188, 83, 0, 1050, 0, 0, 0, 0, 84, 0, - 0, 0, 0, 219, 220, 221, 222, 223, 224, 225, - 0, 226, 227, 228, 0, 85, 0, 0, 0, 0, - 0, 0, 0, 1125, 0, 0, 0, 0, 635, 0, - 0, 0, 0, 0, 0, 0, 86, 87, 0, 0, - 782, 783, 88, 0, 0, 0, 189, 0, 0, 0, - 396, 397, 91, 92, 0, 0, 93, 0, 94, 190, - 191, 0, 0, 1126, 0, 0, 1127, 0, 1128, 1129, - 1130, 1131, 1132, 1133, 1134, 1135, 1136, 1137, 1138, 637, - 1139, 1140, 394, 0, 1141, 73, 0, 74, 75, 76, - 77, 78, 0, 0, 0, 0, 0, 395, 192, 193, - 81, 194, 0, 0, 82, 0, 195, 0, 196, 0, - 0, 0, 83, 0, 0, 0, 0, 0, 0, 84, - 205, 206, 207, 208, 209, 210, 211, 212, 213, 0, - 0, 0, 0, 0, 0, 0, 85, 0, 214, 0, - 0, 73, 0, 74, 75, 76, 77, 0, 0, 635, - 0, 0, 0, 0, 0, 0, 0, 86, 87, 0, - 0, 0, 0, 88, 0, 0, 0, 0, 0, 0, - 0, 396, 397, 91, 92, 84, 0, 93, 0, 94, - 205, 206, 207, 208, 209, 210, 211, 212, 213, 0, - 0, 0, 237, 0, 0, 0, 0, 0, 214, 0, - 637, 205, 206, 207, 208, 209, 210, 211, 212, 213, - 0, 0, 0, 86, 87, 0, 0, 0, 0, 214, - 205, 206, 207, 208, 209, 210, 211, 212, 213, 0, - 92, 0, 0, 0, 0, 94, 0, 0, 214, 205, - 206, 207, 208, 209, 210, 211, 212, 213, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 214, 156, 913, - 0, 0, 0, 215, 216, 217, 218, 219, 220, 221, - 222, 223, 224, 225, 0, 226, 227, 228, 914, 205, - 206, 207, 208, 209, 210, 211, 212, 213, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 214, 205, 206, - 207, 208, 209, 210, 211, 212, 213, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 214, 0, 0, 0, - 0, 0, 0, 215, 216, 217, 218, 219, 220, 221, - 222, 223, 224, 225, 0, 226, 227, 228, 305, 0, - 0, 0, 0, 0, 215, 216, 217, 218, 219, 220, - 221, 222, 223, 224, 225, 0, 226, 227, 228, 493, - 0, 0, 0, 215, 216, 217, 218, 219, 220, 221, - 222, 223, 224, 225, 0, 226, 227, 228, 509, 0, - 0, 0, 215, 216, 217, 218, 219, 220, 221, 222, - 223, 224, 225, 0, 226, 227, 228, 588, 205, 206, - 207, 208, 209, 210, 211, 212, 213, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 214, 0, 0, 0, - 0, 0, 215, 216, 217, 218, 219, 220, 221, 222, - 223, 224, 225, 0, 226, 227, 228, 647, 0, 0, - 0, 215, 216, 217, 218, 219, 220, 221, 222, 223, - 224, 225, 0, 226, 227, 228, 768, 205, 206, 207, - 208, 209, 210, 211, 212, 213, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 214, 205, 206, 207, 208, - 209, 210, 211, 212, 213, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 214, 205, 206, 207, 208, 209, - 210, 211, 212, 213, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 214, 205, 206, 207, 208, 209, 210, - 211, 212, 213, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 214, 0, 0, 0, 0, 0, 0, 0, - 0, 215, 216, 217, 218, 219, 220, 221, 222, 223, - 224, 225, 0, 226, 227, 228, 899, 1511, 1512, 1513, - 1514, 1515, 1516, 1517, 1518, 1519, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1520, 1511, 1512, 1513, 1514, - 1515, 1516, 1517, 1518, 1519, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1520, 0, 0, 0, 0, 0, - 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, - 225, 0, 226, 227, 228, 979, 0, 0, 0, 215, - 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, - 0, 226, 227, 228, 1030, 0, 505, 0, 215, 216, - 217, 218, 219, 220, 221, 222, 223, 224, 225, 0, - 226, 227, 228, 0, 0, 1032, 0, 215, 216, 217, - 218, 219, 220, 221, 222, 223, 224, 225, 0, 226, - 227, 228, 207, 208, 209, 210, 211, 212, 213, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 214, 207, - 208, 209, 210, 211, 212, 213, 0, 0, 1626, 0, - 1521, 1522, 1523, 1524, 0, 214, 1525, 1526, 1527, 1528, - 1529, 0, 1530, 1531, 1532, 0, 0, 0, 0, 1521, - 1522, 1523, 1524, 0, 0, 1525, 1526, 1527, 1528, 1529, - 0, 1530, 1531, 1532, 1513, 1514, 1515, 1516, 1517, 1518, - 1519, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1520, 207, 208, 209, 210, 211, 212, 213, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 214, 1513, 1514, - 1515, 1516, 1517, 1518, 1519, 0, 0, 0, 73, 0, - 74, 75, 76, 77, 1520, 1513, 1514, 1515, 1516, 1517, - 1518, 1519, 0, 0, 1513, 1514, 1515, 1516, 1517, 1518, - 1519, 1520, 0, 0, 0, 0, 0, 0, 0, 0, - 1520, 0, 84, 0, 0, 217, 218, 219, 220, 221, - 222, 223, 224, 225, 0, 226, 227, 228, 0, 237, - 0, 0, 0, 218, 219, 220, 221, 222, 223, 224, - 225, 0, 226, 227, 228, 1515, 1516, 1517, 1518, 1519, - 86, 87, 0, 0, 0, 0, 0, 0, 0, 1520, - 0, 0, 0, 0, 0, 0, 0, 92, 0, 0, - 0, 0, 94, 0, 0, 0, 1522, 1523, 1524, 0, - 0, 1525, 1526, 1527, 1528, 1529, 0, 1530, 1531, 1532, - 0, 0, 0, 0, 0, 162, 219, 220, 221, 222, - 223, 224, 225, 0, 226, 227, 228, 0, 0, 0, - 0, 1523, 1524, 0, 0, 1525, 1526, 1527, 1528, 1529, - 655, 1530, 1531, 1532, 0, 0, 0, 0, 0, 1524, - 597, 0, 1525, 1526, 1527, 1528, 1529, 0, 1530, 1531, - 1532, 1525, 1526, 1527, 1528, 1529, 0, 1530, 1531, 1532, - 0, 109, 0, 110, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 656, 0, 657, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 407, 0, - 0, 915, 916, 917, 658, 0, 408, 409, 410, 411, - 1525, 1526, 1527, 1528, 1529, 0, 1530, 1531, 1532, 413, - 589, 415, 416, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 590, 0, 0, 0, 659, 0, 0, 660, - 661, 0, 0, 662, 0, 0, 73, 0, 74, 75, - 76, 77, 918, 919, 915, 916, 917, 426, 0, 663, - 0, 81, 0, 0, 0, 0, 0, 0, 431, 0, - 0, 664, 0, 83, 432, 0, 0, 0, 0, 435, - 84, 0, 0, 0, 0, 665, 0, 0, 0, 0, - 438, 0, 439, 0, 0, 70, 71, 85, 0, 73, - 0, 74, 75, 76, 77, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 81, 0, 0, 0, 86, 87, - 0, 0, 0, 0, 0, 73, 83, 74, 75, 76, - 77, 0, 920, 84, 0, 92, 72, 0, 93, 73, - 94, 74, 75, 76, 77, 78, 527, 0, 0, 0, - 85, 80, 0, 0, 81, 0, 0, 0, 82, 84, - 0, 0, 0, 0, 0, 0, 83, 0, 0, 0, - 0, 86, 87, 84, 0, 0, 237, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 92, 0, - 85, 93, 0, 94, 70, 71, 0, 86, 87, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 528, 0, - 0, 86, 87, 0, 92, 0, 0, 88, 0, 94, - 70, 71, 0, 0, 0, 89, 90, 91, 92, 0, - 0, 93, 0, 94, 0, 72, 0, 0, 73, 0, - 74, 75, 76, 77, 78, 79, 0, 0, 0, 0, - 80, 0, 0, 81, 0, 0, 0, 82, 0, 0, - 0, 72, 0, 0, 73, 83, 74, 75, 76, 77, - 78, 0, 84, 0, 0, 0, 80, 0, 0, 81, - 0, 0, 0, 82, 0, 0, 0, 0, 0, 85, - 0, 83, 0, 0, 0, 0, 0, 0, 84, 0, + 58, 11, 12, 13, 14, 0, 1518, 1519, 1520, 1521, + 1522, 1523, 1524, 59, 0, 0, 60, 61, 62, 0, + 0, 63, 1525, 64, 65, 0, 0, 66, 0, 0, + 0, 0, 207, 208, 209, 210, 211, 212, 213, 214, + 215, 0, 0, 0, 15, 0, 0, 0, 16, 0, + 216, 17, 18, 19, 20, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 22, 23, 0, 0, 0, 0, + 0, 0, 0, 0, 24, 25, 26, 0, 0, 0, + 27, 0, 0, 28, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 0, 0, 0, 0, 0, 0, 0, 0, 46, + 0, 47, 48, 0, 49, 0, 0, 0, 0, 50, + 0, 0, 51, 52, 53, 0, 0, 54, 0, 0, + 0, 0, 55, 0, 0, 56, 0, 0, 0, 57, + 7, 8, 9, 10, 58, 11, 12, 13, 0, 0, + 0, 0, 1504, 0, 0, 1530, 1531, 1532, 1533, 1534, + 0, 1535, 1536, 1537, 0, 63, 0, 64, 65, 0, + 0, 66, 0, 894, 0, 0, 0, 217, 218, 219, + 220, 221, 222, 223, 224, 225, 226, 227, 1439, 228, + 229, 230, 895, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1440, 188, 189, 190, 0, 1441, + 0, 0, 0, 0, 0, 0, 0, 0, 24, 25, + 0, 0, 0, 0, 27, 0, 0, 0, 29, 30, + 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 7, 8, 9, 10, 0, 11, + 12, 13, 0, 0, 0, 0, 48, 0, 49, 0, + 0, 0, 0, 1442, 191, 0, 0, 0, 1443, 0, + 632, 1444, 0, 0, 0, 0, 55, 192, 193, 0, + 207, 208, 209, 210, 211, 212, 213, 214, 215, 0, + 0, 0, 1439, 0, 0, 0, 0, 0, 216, 0, + 0, 1445, 0, 0, 1446, 1447, 1448, 0, 1440, 1449, + 633, 1505, 65, 1441, 0, 1451, 194, 195, 0, 196, + 0, 0, 24, 25, 0, 197, 0, 198, 27, 0, + 0, 0, 29, 30, 31, 32, 33, 34, 35, 36, + 37, 38, 39, 40, 41, 42, 43, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 86, 87, 0, 70, 71, 85, 88, 0, 0, 0, - 0, 0, 0, 0, 89, 90, 91, 92, 0, 0, - 93, 0, 94, 680, 0, 0, 86, 87, 0, 70, - 0, 0, 88, 0, 0, 0, 0, 0, 0, 0, - 89, 90, 91, 92, 72, 0, 93, 73, 94, 74, - 75, 76, 77, 78, 0, 0, 0, 0, 0, 80, - 0, 0, 81, 0, 0, 0, 82, 0, 0, 0, - 72, 0, 0, 73, 83, 74, 75, 76, 77, 78, - 793, 84, 0, 0, 0, 80, 0, 0, 81, 0, - 0, 0, 82, 0, 0, 0, 0, 0, 85, 0, - 83, 0, 0, 0, 0, 0, 0, 84, 0, 0, + 48, 0, 49, 0, 0, 0, 0, 1442, 0, 0, + 0, 0, 1443, 0, 0, 1444, 555, 556, 557, 10, + 55, 11, 558, 559, 0, 0, 0, 0, 852, 0, + 0, 0, 0, 555, 556, 557, 10, 0, 11, 558, + 559, 0, 0, 0, 0, 704, 0, 0, 0, 0, + 0, 0, 0, 1449, 0, 1450, 65, 0, 0, 1451, + 0, 110, 0, 111, 561, 217, 218, 219, 220, 221, + 222, 223, 224, 225, 226, 227, 0, 228, 229, 230, + 562, 561, 0, 0, 0, 563, 0, 0, 0, 0, + 0, 0, 0, 0, 564, 565, 0, 562, 0, 0, + 0, 0, 563, 209, 210, 211, 212, 213, 214, 215, + 0, 564, 565, 0, 0, 0, 0, 0, 0, 216, + 0, 0, 1518, 1519, 1520, 1521, 1522, 1523, 1524, 566, + 0, 0, 567, 0, 568, 0, 0, 0, 1525, 569, + 0, 0, 0, 0, 570, 0, 566, 571, 0, 567, + 0, 568, 572, 0, 0, 573, 569, 0, 0, 0, + 0, 570, 0, 0, 571, 0, 0, 0, 0, 572, + 0, 0, 573, 0, 0, 0, 0, 574, 0, 0, + 575, 576, 0, 0, 0, 577, 0, 578, 0, 0, + 0, 579, 0, 0, 574, 0, 0, 575, 576, 1092, + 0, 0, 577, 0, 705, 0, 0, 0, 579, 1093, + 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, 0, 0, + 0, 0, 0, 0, 188, 189, 190, 1102, 0, 1103, + 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, + 1114, 0, 0, 0, 0, 0, 0, 218, 219, 220, + 221, 222, 223, 224, 225, 226, 227, 0, 228, 229, + 230, 0, 0, 1115, 0, 0, 1527, 1528, 1529, 637, + 638, 1530, 1531, 1532, 1533, 1534, 0, 1535, 1536, 1537, + 0, 0, 0, 191, 0, 0, 0, 0, 0, 0, + 211, 212, 213, 214, 215, 0, 192, 193, 0, 0, + 0, 0, 0, 0, 216, 0, 0, 0, 0, 1116, + 0, 399, 0, 0, 73, 400, 0, 75, 76, 77, + 78, 79, 0, 0, 0, 0, 0, 401, 0, 0, + 82, 0, 0, 0, 83, 194, 195, 0, 196, 0, + 0, 0, 84, 0, 197, 0, 198, 0, 0, 85, + 1117, 0, 0, 1118, 0, 1119, 1120, 1121, 1122, 1123, + 1124, 1125, 1126, 1127, 1128, 1129, 86, 1130, 1131, 766, + 767, 1132, 0, 0, 0, 0, 0, 0, 0, 639, + 0, 0, 0, 0, 0, 0, 0, 0, 87, 88, + 0, 0, 0, 0, 89, 0, 0, 0, 0, 0, + 0, 0, 402, 403, 92, 93, 0, 0, 94, 0, + 95, 399, 0, 0, 73, 400, 0, 75, 76, 77, + 78, 79, 0, 0, 0, 0, 0, 401, 0, 0, + 82, 641, 0, 0, 83, 221, 222, 223, 224, 225, + 226, 227, 84, 228, 229, 230, 0, 0, 0, 85, + 207, 208, 209, 210, 211, 212, 213, 214, 215, 0, + 0, 0, 0, 0, 0, 0, 86, 0, 216, 207, + 208, 209, 210, 211, 212, 213, 214, 215, 0, 639, + 0, 0, 0, 0, 0, 0, 0, 216, 87, 88, + 0, 0, 0, 73, 89, 0, 75, 76, 77, 78, + 0, 0, 402, 403, 92, 93, 0, 0, 94, 238, + 95, 207, 208, 209, 210, 211, 212, 213, 214, 215, + 0, 0, 0, 0, 0, 0, 0, 0, 85, 216, + 0, 641, 207, 208, 209, 210, 211, 212, 213, 214, + 215, 0, 0, 0, 0, 239, 0, 0, 0, 0, + 216, 207, 208, 209, 210, 211, 212, 213, 214, 215, + 0, 0, 0, 0, 0, 0, 0, 87, 88, 216, + 207, 208, 209, 210, 211, 212, 213, 214, 215, 0, + 0, 0, 0, 0, 93, 0, 0, 0, 216, 95, + 0, 0, 0, 0, 0, 217, 218, 219, 220, 221, + 222, 223, 224, 225, 226, 227, 0, 228, 229, 230, + 308, 0, 144, 0, 217, 218, 219, 220, 221, 222, + 223, 224, 225, 226, 227, 0, 228, 229, 230, 499, + 207, 208, 209, 210, 211, 212, 213, 214, 215, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 216, 0, + 0, 0, 0, 0, 0, 0, 217, 218, 219, 220, + 221, 222, 223, 224, 225, 226, 227, 0, 228, 229, + 230, 515, 0, 0, 0, 0, 0, 217, 218, 219, + 220, 221, 222, 223, 224, 225, 226, 227, 0, 228, + 229, 230, 594, 0, 0, 0, 217, 218, 219, 220, + 221, 222, 223, 224, 225, 226, 227, 0, 228, 229, + 230, 651, 0, 0, 0, 217, 218, 219, 220, 221, + 222, 223, 224, 225, 226, 227, 0, 228, 229, 230, + 752, 207, 208, 209, 210, 211, 212, 213, 214, 215, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 216, + 207, 208, 209, 210, 211, 212, 213, 214, 215, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 216, 0, + 0, 0, 0, 0, 0, 217, 218, 219, 220, 221, + 222, 223, 224, 225, 226, 227, 0, 228, 229, 230, + 880, 207, 208, 209, 210, 211, 212, 213, 214, 215, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 216, + 719, 720, 721, 722, 723, 724, 725, 726, 727, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 728, 209, + 210, 211, 212, 213, 214, 215, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 216, 1518, 1519, 1520, 1521, + 1522, 1523, 1524, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1525, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 217, 218, 219, 220, + 221, 222, 223, 224, 225, 226, 227, 0, 228, 229, + 230, 962, 0, 0, 0, 217, 218, 219, 220, 221, + 222, 223, 224, 225, 226, 227, 0, 228, 229, 230, + 1018, 1518, 1519, 1520, 1521, 1522, 1523, 1524, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1525, 0, 0, + 0, 0, 1412, 0, 0, 0, 217, 218, 219, 220, + 221, 222, 223, 224, 225, 226, 227, 0, 228, 229, + 230, 0, 0, 0, 0, 729, 730, 731, 732, 733, + 734, 735, 736, 737, 738, 739, 0, 740, 741, 742, + 601, 0, 0, 659, 219, 220, 221, 222, 223, 224, + 225, 226, 227, 0, 228, 229, 230, 0, 0, 0, + 0, 1528, 1529, 0, 0, 1530, 1531, 1532, 1533, 1534, + 0, 1535, 1536, 1537, 110, 0, 111, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 413, 660, + 0, 661, 0, 0, 0, 0, 0, 414, 415, 416, + 417, 0, 0, 0, 0, 0, 0, 0, 662, 0, + 419, 420, 421, 422, 0, 601, 0, 0, 0, 0, + 0, 0, 0, 535, 0, 0, 0, 1529, 0, 0, + 1530, 1531, 1532, 1533, 1534, 0, 1535, 1536, 1537, 0, + 663, 0, 0, 664, 665, 0, 0, 666, 432, 0, + 0, 896, 897, 898, 0, 0, 0, 0, 0, 437, + 0, 0, 0, 413, 667, 0, 438, 0, 0, 0, + 440, 441, 414, 415, 416, 417, 668, 0, 0, 0, + 0, 0, 444, 0, 445, 419, 534, 421, 422, 0, + 669, 0, 0, 0, 0, 0, 73, 0, 535, 75, + 76, 77, 78, 899, 900, 896, 897, 898, 0, 0, + 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 432, 84, 0, 0, 0, 0, 0, + 0, 85, 0, 0, 437, 0, 0, 0, 0, 0, + 0, 438, 0, 0, 0, 0, 441, 0, 86, 0, + 73, 0, 0, 75, 76, 77, 78, 444, 0, 445, + 0, 0, 0, 70, 71, 0, 82, 0, 0, 0, + 87, 88, 0, 0, 0, 0, 0, 0, 84, 0, + 0, 0, 0, 0, 901, 85, 0, 93, 0, 0, + 94, 902, 95, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 86, 0, 72, 0, 0, 73, 74, 0, + 75, 76, 77, 78, 79, 80, 0, 0, 0, 0, + 81, 0, 0, 82, 87, 88, 0, 83, 70, 71, + 0, 0, 0, 0, 0, 84, 0, 0, 0, 0, + 0, 93, 85, 0, 94, 0, 95, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, - 87, 0, 144, 0, 85, 88, 0, 0, 0, 0, - 0, 0, 0, 89, 90, 91, 92, 0, 0, 93, - 0, 94, 0, 0, 0, 86, 87, 0, 144, 0, - 0, 88, 0, 0, 0, 0, 0, 0, 0, 89, - 90, 91, 92, 145, 0, 93, 73, 94, 74, 75, - 76, 77, 78, 982, 0, 0, 0, 0, 146, 0, - 0, 81, 0, 0, 0, 82, 0, 0, 0, 145, - 0, 0, 73, 83, 74, 75, 76, 77, 78, 0, - 84, 0, 0, 0, 146, 0, 0, 81, 0, 0, - 0, 82, 0, 0, 0, 0, 0, 85, 0, 83, - 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, - 0, 0, 0, 0, 186, 187, 188, 0, 86, 87, - 0, 70, 0, 85, 88, 0, 0, 0, 0, 186, - 187, 188, 147, 148, 91, 92, 0, 0, 93, 0, - 94, 0, 0, 0, 86, 87, 0, 0, 0, 0, - 88, 186, 187, 188, 0, 0, 0, 0, 147, 148, - 91, 92, 72, 0, 93, 73, 94, 74, 75, 76, - 77, 78, 189, 0, 0, 0, 0, 80, 0, 0, - 81, 0, 0, 0, 82, 190, 191, 189, 0, 0, - 0, 0, 83, 0, 0, 0, 0, 407, 0, 84, - 190, 191, 0, 0, 0, 408, 409, 410, 411, 189, - 0, 0, 0, 0, 0, 628, 85, 0, 413, 589, - 415, 416, 190, 191, 192, 193, 418, 194, 0, 0, - 0, 590, 195, 0, 196, 0, 0, 86, 87, 192, - 193, 0, 194, 88, 0, 1013, 0, 195, 0, 196, - 1176, 89, 90, 91, 92, 629, 426, 93, 0, 94, - 1013, 192, 193, 0, 194, 1178, 0, 431, 0, 195, - 0, 196, 0, 432, 406, 407, 0, 0, 435, 0, - 0, 0, 0, 408, 409, 410, 411, 0, 437, 438, - 0, 439, 0, 0, 412, 0, 413, 414, 415, 416, - 417, 0, 0, 0, 418, 0, -161, 0, 0, 419, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 420, 421, - 422, 423, 424, 425, 426, 427, 0, 0, 0, 0, - 0, 0, 428, 429, 430, 431, 0, 0, 0, 0, - 0, 432, 433, 407, 0, 434, 435, 0, 0, 0, - 436, 408, 409, 410, 411, 0, 437, 438, 0, 439, - 0, 0, 0, 0, 413, 414, 415, 416, 0, 0, - 407, 0, 418, 0, 407, 0, 0, 590, 408, 409, - 410, 411, 408, 409, 410, 411, 0, 0, 0, 0, - 0, 413, 589, 415, 416, 413, 589, 415, 416, 0, - 0, 0, 426, 0, 590, 0, 0, 73, 590, 74, - 75, 76, 77, 431, 0, 0, 0, 0, 0, 432, - 0, 0, 236, 434, 435, 0, 0, 0, 0, 426, - 604, 0, 0, 426, 437, 438, 0, 439, 0, 0, - 431, 84, 0, 0, 431, 0, 432, 0, 0, 0, - 432, 435, 0, 0, 0, 435, 0, 0, 237, 0, - 0, 0, 438, 0, 439, 0, 438, 0, 439, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, - 87, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 92, 0, 0, 0, - 0, 94 + 0, 70, 0, 0, 0, 0, 0, 0, 0, 72, + 0, 0, 73, 74, 0, 75, 76, 77, 78, 79, + 0, 87, 88, 0, 0, 81, 0, 89, 82, 0, + 0, 0, 83, 0, 0, 90, 91, 92, 93, 0, + 84, 94, 72, 95, 0, 73, 74, 85, 75, 76, + 77, 78, 79, 777, 0, 0, 0, 0, 81, 0, + 0, 82, 0, 0, 86, 83, 145, 0, 0, 0, + 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, + 85, 0, 0, 0, 0, 0, 87, 88, 0, 0, + 0, 0, 89, 0, 0, 0, 0, 86, 0, 145, + 90, 91, 92, 93, 0, 0, 94, 146, 95, 0, + 73, 147, 0, 75, 76, 77, 78, 79, 965, 87, + 88, 0, 0, 148, 0, 89, 82, 0, 0, 0, + 83, 0, 0, 90, 91, 92, 93, 0, 84, 94, + 146, 95, 0, 73, 147, 85, 75, 76, 77, 78, + 79, 0, 0, 0, 0, 0, 148, 0, 0, 82, + 0, 0, 86, 83, 70, 0, 0, 0, 0, 0, + 0, 84, 0, 0, 0, 0, 0, 0, 85, 0, + 0, 188, 189, 190, 87, 88, 0, 0, 0, 0, + 89, 0, 0, 0, 0, 86, 0, 0, 149, 150, + 92, 93, 0, 0, 94, 72, 95, 0, 73, 74, + 0, 75, 76, 77, 78, 79, 0, 87, 88, 0, + 0, 81, 0, 89, 82, 0, 0, 0, 83, 0, + 0, 149, 150, 92, 93, 0, 84, 94, 0, 95, + 191, 0, 0, 85, 0, 0, 0, 0, 188, 189, + 190, 0, 0, 192, 193, 0, 0, 0, 0, 0, + 86, 0, 0, 188, 189, 190, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 188, 189, + 190, 0, 87, 88, 0, 0, 0, 0, 89, 0, + 0, 0, 194, 998, 999, 1000, 90, 91, 92, 93, + 0, 197, 94, 198, 95, 0, 0, 191, 0, 0, + 0, 0, 0, 0, 1001, 0, 0, 0, 0, 1002, + 192, 193, 191, 0, 0, 0, 0, 0, 73, 0, + 0, 75, 76, 77, 78, 192, 193, 191, 0, 0, + 188, 189, 190, 0, 0, 1039, 0, 0, 0, 0, + 192, 193, 73, 0, 0, 75, 76, 77, 78, 194, + 195, 0, 196, 85, 0, 0, 0, 0, 197, 0, + 198, 0, 0, 0, 194, 195, 0, 196, 0, 0, + 239, 1001, 0, 197, 0, 198, 1170, 85, 0, 194, + 195, 0, 196, 0, 0, 0, 1001, 0, 197, 191, + 198, 1172, 87, 88, 239, 0, 0, 0, 0, 0, + 0, 1001, 192, 193, 0, 0, 1174, 0, 0, 93, + 0, 0, 0, 0, 95, 0, 87, 88, 73, 0, + 0, 75, 76, 77, 78, 0, 0, 0, 0, 0, + 0, 0, 0, 93, 0, 0, 0, 157, 95, 0, + 0, 194, 195, 0, 196, 0, 0, 0, 0, 0, + 197, 0, 198, 85, 0, 413, 0, 0, 0, 0, + 0, 158, 0, 0, 414, 415, 416, 417, 0, 0, + 239, 0, 0, 0, 0, 0, 0, 419, 534, 421, + 422, 0, 0, 0, 0, 424, 0, 0, 0, 0, + 535, 0, 87, 88, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, + 0, 0, 0, 0, 95, 432, 0, 0, 0, 412, + 413, 0, 0, 0, 0, 0, 437, 0, 0, 414, + 415, 416, 417, 438, 0, 0, 0, 164, 441, 0, + 418, 0, 419, 420, 421, 422, 423, 0, 443, 444, + 424, 445, 0, 0, 0, 425, 0, 0, 0, 0, + 413, 0, 0, 0, 0, 0, -161, 0, 0, 414, + 415, 416, 417, 0, 426, 427, 428, 429, 430, 431, + 432, 433, 419, 534, 421, 422, 0, 0, 434, 435, + 436, 437, 0, 0, 0, 535, 0, 0, 438, 439, + 413, 0, 440, 441, 0, 0, 0, 442, 0, 414, + 415, 416, 417, 443, 444, 0, 445, 413, 0, 0, + 432, 608, 419, 420, 421, 422, 414, 415, 416, 417, + 424, 437, 0, 0, 0, 535, 0, 0, 438, 419, + 534, 421, 422, 441, 0, 0, 0, 0, 0, 0, + 0, 0, 535, 0, 444, 0, 445, 0, 0, 0, + 432, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 437, 0, 0, 0, 0, 0, 432, 438, 0, + 0, 0, 440, 441, 0, 0, 0, 0, 437, 0, + 0, 0, 0, 443, 444, 438, 445, 0, 0, 0, + 441, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 444, 0, 445 }; static const yytype_int16 yycheck[] = { - 1, 114, 392, 116, 117, 118, 119, 120, 392, 122, - 79, 124, 414, 126, 434, 434, 79, 500, 930, 544, - 560, 96, 951, 1092, 46, 263, 263, 46, 543, 784, - 143, 676, 391, 529, 85, 86, 87, 10, 11, 12, - 15, 92, 155, 156, 530, 501, 531, 937, 15, 162, - 163, 48, 263, 50, 6, 984, 8, 64, 15, 10, - 850, 0, 13, 263, 65, 155, 939, 13, 61, 942, - 943, 15, 81, 81, 964, 158, 966, 81, 154, 969, - 46, 155, 0, 155, 174, 1010, 1011, 1012, 613, 156, - 173, 48, 154, 50, 95, 96, 172, 34, 48, 15, - 50, 81, 174, 177, 172, 155, 48, 155, 50, 48, - 172, 50, 113, 114, 172, 116, 117, 118, 119, 120, - 172, 122, 34, 124, 174, 126, 174, 178, 179, 180, - 181, 48, 48, 50, 50, 48, 172, 50, 528, 48, - 133, 50, 143, 533, 155, 154, 154, 120, 157, 157, - 154, 158, 155, 157, 155, 156, 231, 232, 173, 174, - 155, 162, 163, 174, 13, 34, 15, 158, 17, 68, - 69, 174, 247, 248, 154, 158, 1066, 157, 175, 174, - 564, 971, 173, 172, 157, 681, 237, 546, 155, 302, - 173, 687, 837, 13, 690, 15, 682, 17, 1071, 174, - 201, 1074, 1075, 848, 172, 443, 247, 248, 691, 1099, - 34, 155, 698, 62, 156, 701, 167, 972, 64, 702, - 227, 167, 174, 172, 173, 175, 10, 11, 12, 13, - 231, 232, 443, 17, 171, 172, 173, 154, 15, 163, - 17, 263, 62, 443, 263, 770, 247, 248, 163, 1174, - 251, 1176, 172, 1178, 1144, 1145, 1181, 1182, 1183, 171, - 172, 173, 175, 174, 265, 48, 175, 50, 172, 115, - 795, 48, 172, 50, 814, 121, 172, 123, 62, 125, - 172, 127, 128, 129, 130, 131, 132, 133, 134, 135, - 136, 137, 138, 139, 140, 141, 142, 263, 172, 148, - 369, 302, 171, 172, 173, 155, 369, 1062, 154, 172, - 1239, 34, 158, 162, 160, 161, 155, 358, 167, 158, - 172, 322, 363, 364, 174, 6, 811, 8, 148, 380, - 826, 172, 48, 157, 50, 831, 120, 172, 834, 835, - 172, 827, 162, 172, 734, 828, 829, 167, 172, 173, - 734, 172, 172, 48, 172, 50, 842, 358, 1231, 845, - 846, 155, 363, 364, 148, 1155, 172, 154, 13, 156, - 15, 158, 17, 374, 375, 155, 155, 172, 162, 155, - 174, 155, 155, 167, 622, 162, 901, 172, 626, 626, - 167, 392, 175, 158, 174, 174, 242, 155, 174, 1468, - 174, 174, 172, 6, 155, 8, 407, 408, 409, 410, - 411, 622, 413, 414, 415, 626, 174, 62, 419, 173, - 174, 443, 622, 174, 443, 426, 626, 172, 155, 925, - 431, 432, 1077, 434, 435, 436, 172, 438, 439, 925, - 172, 155, 982, 155, 167, 168, 169, 174, 171, 172, - 173, 172, 155, 155, 155, 301, 173, 174, 527, 175, - 174, 154, 174, 156, 527, 158, 163, 257, 258, 155, - 511, 174, 174, 174, 172, 516, 517, 443, 934, 172, - 175, 163, 938, 524, 525, 526, 155, 155, 174, 972, - 173, 174, 543, 1018, 48, 1385, 50, 172, 994, 500, - 501, 173, 174, 148, 1149, 174, 174, 990, 991, 172, - 511, 172, 1037, 172, 1000, 516, 517, 162, 172, 1044, - 172, 173, 167, 524, 525, 526, 172, 172, 529, 913, - 531, 987, 988, 989, 151, 152, 153, 172, 560, 1451, - 172, 560, 172, 544, 545, 154, 1475, 156, 157, 158, - 172, 1047, 17, 154, 154, 156, 156, 158, 158, 1055, - 167, 1047, 1058, 154, 155, 572, 635, 172, 173, 1055, - 34, 173, 1058, 121, 122, 123, 172, 173, 174, 1062, - 173, 154, 10, 11, 12, 172, 173, 174, 589, 590, - 172, 173, 174, 49, 560, 155, 597, 62, 172, 64, - 622, 164, 603, 622, 626, 175, 155, 626, 174, 174, - 174, 680, 613, 174, 164, 174, 81, 680, 464, 174, - 466, 174, 468, 174, 1080, 155, 155, 174, 1048, 1048, - 671, 174, 174, 674, 675, 642, 643, 174, 174, 174, - 68, 174, 174, 650, 164, 652, 1048, 174, 113, 15, - 174, 116, 117, 81, 82, 120, 622, 174, 174, 174, - 626, 10, 11, 12, 13, 666, 174, 174, 17, 174, - 671, 136, 174, 674, 675, 676, 174, 174, 174, 164, - 681, 174, 174, 148, 174, 686, 687, 174, 172, 690, - 691, 174, 120, 121, 174, 123, 174, 162, 157, 157, - 128, 702, 130, 167, 168, 169, 172, 171, 172, 173, - 172, 712, 1168, 62, 721, 1171, 157, 174, 172, 172, - 1216, 1217, 1218, 172, 793, 172, 572, 172, 172, 172, - 1216, 1217, 1218, 157, 5, 157, 157, 172, 584, 172, - 1225, 177, 174, 174, 1229, 172, 174, 172, 174, 862, - 757, 167, 175, 173, 173, 81, 163, 172, 163, 781, - 163, 1551, 1552, 1553, 163, 174, 172, 768, 163, 770, - 119, 120, 174, 156, 172, 34, 817, 174, 174, 1235, - 781, 174, 10, 11, 12, 174, 172, 167, 167, 154, - 157, 49, 814, 794, 795, 814, 586, 587, 172, 148, - 172, 174, 157, 174, 174, 10, 11, 12, 13, 154, - 811, 155, 17, 162, 155, 155, 817, 155, 167, 155, - 155, 154, 172, 172, 156, 826, 156, 828, 829, 158, - 831, 102, 103, 834, 835, 172, 837, 154, 177, 173, - 68, 172, 154, 10, 172, 172, 155, 848, 814, 850, - 901, 173, 173, 81, 82, 174, 164, 62, 164, 164, - 174, 862, 164, 174, 10, 10, 10, 10, 1658, 715, - 716, 717, 10, 719, 156, 721, 1666, 723, 724, 150, - 151, 164, 407, 408, 409, 410, 411, 34, 413, 414, - 415, 155, 120, 121, 419, 123, 174, 919, 167, 167, - 128, 426, 130, 175, 156, 156, 431, 432, 983, 434, - 435, 436, 167, 438, 439, 120, 172, 177, 1403, 1404, - 1405, 15, 172, 177, 925, 172, 172, 158, 172, 174, - 172, 174, 155, 934, 155, 155, 155, 938, 939, 1435, - 155, 942, 943, 148, 156, 173, 172, 174, 173, 1435, - 167, 175, 174, 156, 156, 155, 957, 162, 10, 960, - 982, 175, 167, 982, 174, 1219, 177, 172, 34, 155, - 971, 972, 10, 174, 10, 246, 1461, 175, 249, 250, - 174, 174, 983, 174, 156, 10, 987, 988, 989, 990, - 991, 174, 10, 994, 1479, 1480, 10, 1453, 10, 156, - 155, 1457, 172, 177, 794, 1395, 174, 10, 11, 12, - 13, 1395, 15, 803, 17, 175, 982, 1018, 165, 166, - 167, 168, 169, 177, 171, 172, 173, 1049, 154, 156, - 155, 163, 174, 174, 174, 174, 1037, 172, 172, 1040, - 163, 163, 163, 1044, 174, 174, 1047, 1048, 156, 10, - 156, 175, 10, 1054, 1055, 1540, 175, 1058, 1059, 62, - 174, 1062, 10, 1548, 589, 590, 156, 156, 10, 156, - 1071, 172, 597, 1074, 1075, 174, 1077, 23, 24, 1080, - 15, 1537, 174, 1158, 175, 356, 357, 933, 34, 174, - 155, 1092, 175, 174, 155, 366, 367, 368, 174, 165, - 166, 167, 168, 169, 164, 171, 172, 173, 164, 164, - 174, 164, 1597, 10, 156, 1600, 174, 120, 10, 390, - 174, 10, 156, 172, 172, 172, 172, 156, 1241, 1242, - 174, 402, 403, 174, 174, 156, 10, 156, 1240, 174, - 930, 156, 1598, 603, 1451, 148, 1631, 937, 1149, 939, - 23, 24, 942, 943, 1155, 1398, 427, 1158, 626, 162, - 1049, 34, 1647, 919, 167, 1557, 1395, 1168, 1206, 172, - 1171, 626, 734, 1358, 964, 1019, 966, 564, -1, 969, - 1187, 1188, -1, 1190, 321, 1192, 1440, -1, 1442, 1443, - 1444, 1445, 1446, -1, 1448, -1, -1, 17, 18, 19, - 20, 21, 22, 23, 24, 1206, -1, -1, -1, -1, - -1, -1, -1, -1, 34, 1216, 1217, 1218, -1, 165, - 166, 167, 168, 169, 1225, 171, 172, 173, 1229, -1, - 1231, 502, -1, -1, 1235, -1, -1, -1, -1, -1, - 1241, 1242, -1, 768, 515, -1, -1, 518, 519, -1, - -1, -1, -1, 10, 11, 12, -1, 1511, 1512, 1513, - 1514, 1515, 1516, 1517, 1518, 1519, 1520, 1521, 1522, 1523, - 1524, 1525, 1526, 1527, 1528, 1529, 1066, -1, -1, -1, - -1, 1071, -1, -1, 1074, 1075, -1, -1, -1, -1, - -1, -1, 165, 166, 167, 168, 169, -1, 171, 172, - 173, -1, -1, -1, -1, -1, -1, -1, -1, 1099, - -1, 68, -1, -1, 585, -1, -1, 588, 1572, -1, - -1, -1, -1, -1, 81, 82, -1, -1, -1, -1, - -1, -1, 3, 4, 5, 6, -1, 8, 9, 10, - 160, 161, 162, -1, 15, 165, 166, 167, 168, 169, - -1, 171, 172, 173, 1144, 1145, -1, 1358, -1, 630, - -1, -1, -1, 120, 121, -1, 123, -1, 1214, 1623, - -1, 128, 1626, 130, -1, -1, -1, 48, -1, 50, - 51, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 1395, 66, -1, 154, 669, 670, - 71, -1, 1403, 1404, 1405, -1, -1, -1, -1, 80, - 81, -1, -1, -1, 685, -1, -1, 688, 689, -1, - -1, 692, -1, -1, 65, 696, -1, -1, 699, 700, - -1, -1, 703, -1, 1435, 706, 707, -1, -1, 710, - 1447, 1231, -1, -1, 115, -1, -1, 118, 89, 120, - -1, -1, 1453, -1, 125, -1, 1457, -1, 129, -1, - 1461, 132, -1, -1, -1, -1, 137, 1468, 109, 140, - -1, 10, 11, 12, -1, -1, -1, -1, 1479, 1480, + 1, 97, 397, 80, 64, 115, 420, 117, 118, 119, + 120, 121, 440, 123, 440, 125, 397, 127, 46, 46, + 374, 506, 1083, 80, 46, 550, 912, 566, 549, 15, + 266, 266, 10, 13, 144, 13, 934, 768, 396, 86, + 87, 88, 685, 266, 266, 15, 93, 157, 158, 6, + 48, 8, 50, 157, 164, 165, 831, 15, 681, 413, + 414, 415, 416, 417, 65, 419, 420, 421, 62, 967, + 15, 425, 175, 176, 15, 179, 17, 921, 432, 160, + 924, 925, 926, 437, 438, 82, 440, 441, 442, 537, + 444, 445, 617, 0, 175, 96, 97, 10, 11, 12, + 160, 507, 34, 48, 174, 50, 48, 48, 50, 50, + 48, 34, 50, 114, 115, 174, 117, 118, 119, 120, + 121, 157, 123, 82, 125, 6, 127, 8, 48, 34, + 50, 174, 15, 180, 181, 182, 183, 233, 234, 82, + 176, 135, 157, 144, 260, 261, 48, 48, 50, 50, + 48, 174, 50, 249, 250, 251, 157, 158, 539, 156, + 158, 176, 159, 164, 165, 48, 34, 50, 160, 229, + 813, 814, 174, 919, 817, 570, 998, 999, 1000, 954, + 534, 535, 48, 175, 50, 157, 34, 157, 82, 169, + 176, 169, 239, 157, 552, 305, 160, 156, 174, 157, + 159, 947, 203, 949, 176, 48, 952, 50, 121, 165, + 249, 250, 251, 156, 449, 5, 159, 1061, 156, 176, + 64, 1065, 1066, 164, 955, 160, 449, 449, 169, 754, + 174, 175, 233, 234, 174, 177, 159, 156, 266, 266, + 175, 173, 174, 175, 266, 156, 159, 601, 249, 250, + 251, 174, 175, 254, 779, 174, 165, 177, 157, 798, + 175, 176, 156, 174, 907, 159, 174, 268, 173, 174, + 175, 48, 116, 50, 174, 177, 177, 176, 122, 177, + 124, 157, 126, 174, 128, 129, 130, 131, 132, 133, + 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, + 176, 169, 170, 171, 305, 173, 174, 175, 175, 176, + 1056, 177, 156, 103, 104, 34, 160, 174, 162, 163, + 174, 1052, 361, 718, 325, 173, 174, 175, 174, 368, + 369, 974, 34, 818, 177, 978, 979, 718, 385, 1237, + 157, 153, 154, 155, 1090, 830, 157, 795, 1170, 0, + 1172, 174, 1174, 157, 174, 1177, 1178, 1179, 981, 176, + 361, 882, 152, 153, 157, 176, 174, 368, 369, 157, + 993, 1146, 176, 374, 174, 10, 11, 12, 379, 380, + 156, 165, 158, 176, 160, 1229, 165, 157, 176, 1135, + 1136, 626, 1035, 1036, 630, 630, 397, 48, 752, 50, + 244, 1044, 1045, 626, 626, 1048, 176, 630, 630, 157, + 1471, 157, 413, 414, 415, 416, 417, 174, 419, 420, + 421, 449, 449, 157, 425, 174, 965, 449, 176, 174, + 176, 432, 158, 6, 69, 8, 437, 438, 174, 440, + 441, 442, 176, 444, 445, 1068, 174, 82, 83, 174, + 169, 170, 171, 174, 173, 174, 175, 174, 248, 536, + 304, 157, 252, 253, 174, 167, 168, 169, 170, 171, + 955, 173, 174, 175, 69, 70, 592, 593, 517, 536, + 176, 1006, 157, 522, 523, 524, 121, 122, 900, 124, + 902, 174, 531, 532, 533, 130, 157, 132, 174, 894, + 1025, 176, 549, 175, 176, 506, 507, 1032, 23, 24, + 916, 175, 176, 1156, 920, 176, 517, 1140, 578, 34, + 174, 522, 523, 524, 157, 174, 157, 157, 157, 157, + 531, 532, 533, 534, 535, 157, 537, 157, 566, 566, + 157, 176, 174, 176, 566, 176, 176, 176, 176, 550, + 551, 156, 176, 158, 176, 160, 176, 160, 1202, 176, + 1204, 174, 639, 174, 970, 971, 972, 1052, 1454, 359, + 360, 1214, 1215, 1216, 10, 11, 12, 22, 23, 24, + 1478, 371, 372, 373, 174, 175, 646, 647, 174, 34, + 174, 10, 11, 12, 654, 174, 656, 174, 626, 626, + 601, 169, 630, 630, 626, 395, 607, 174, 630, 1037, + 156, 1037, 158, 156, 160, 158, 617, 160, 408, 409, + 122, 123, 124, 1037, 156, 157, 470, 174, 472, 156, + 474, 174, 49, 69, 174, 175, 675, 175, 175, 1385, + 679, 680, 177, 433, 157, 705, 82, 83, 174, 166, + 69, 34, 167, 168, 169, 170, 171, 157, 173, 174, + 175, 166, 778, 82, 83, 1071, 174, 175, 176, 670, + 176, 787, 176, 156, 675, 158, 159, 160, 679, 680, + 681, 741, 176, 1037, 685, 121, 122, 176, 124, 174, + 175, 176, 176, 157, 130, 696, 132, 174, 175, 176, + 777, 176, 121, 122, 176, 124, 176, 176, 176, 176, + 176, 130, 166, 132, 10, 11, 12, 13, 508, 176, + 157, 17, 167, 168, 169, 170, 171, 176, 173, 174, + 175, 521, 176, 843, 578, 525, 526, 765, 176, 175, + 166, 160, 176, 176, 176, 164, 590, 15, 176, 176, + 169, 752, 176, 754, 10, 11, 12, 13, 176, 15, + 176, 17, 801, 176, 765, 176, 176, 63, 176, 176, + 798, 798, 176, 176, 174, 1223, 798, 778, 779, 1227, + 176, 1556, 1557, 1558, 167, 168, 169, 170, 171, 176, + 173, 174, 175, 159, 795, 1438, 912, 176, 176, 159, + 801, 591, 174, 919, 594, 921, 174, 63, 924, 925, + 926, 812, 813, 814, 176, 159, 817, 818, 174, 174, + 174, 174, 174, 174, 120, 121, 159, 1233, 159, 830, + 831, 947, 159, 949, 174, 882, 952, 174, 174, 169, + 174, 176, 843, 175, 634, 82, 13, 176, 15, 175, + 17, 176, 174, 177, 150, 699, 700, 701, 179, 703, + 174, 705, 165, 707, 708, 121, 165, 165, 164, 174, + 966, 127, 900, 169, 902, 165, 176, 165, 174, 176, + 174, 158, 174, 673, 674, 176, 34, 176, 159, 176, + 1665, 176, 156, 49, 150, 174, 63, 687, 1673, 174, + 690, 691, 176, 176, 694, 159, 907, 176, 164, 156, + 22, 23, 24, 169, 157, 916, 157, 157, 174, 920, + 921, 157, 34, 924, 925, 926, 157, 157, 156, 174, + 174, 158, 158, 156, 169, 160, 169, 965, 965, 940, + 1056, 179, 943, 965, 686, 1061, 175, 156, 166, 1065, + 1066, 157, 174, 954, 955, 1403, 1404, 1405, 174, 13, + 127, 15, 174, 17, 166, 966, 176, 166, 176, 970, + 971, 972, 762, 974, 1090, 166, 176, 978, 979, 10, + 981, 10, 10, 150, 10, 10, 10, 10, 11, 12, + 13, 166, 993, 158, 17, 157, 176, 164, 169, 169, + 1395, 1407, 169, 177, 1410, 1006, 158, 174, 158, 63, + 1038, 169, 175, 15, 1395, 175, 1464, 174, 157, 1135, + 1136, 811, 176, 174, 1025, 815, 816, 1028, 174, 819, + 157, 1032, 176, 823, 1035, 1036, 1037, 827, 828, 174, + 63, 157, 1043, 1044, 1045, 160, 157, 1048, 1049, 839, + 1456, 1052, 157, 1149, 1460, 167, 168, 169, 170, 171, + 1061, 173, 174, 175, 1065, 1066, 169, 1068, 158, 176, + 1071, 915, 174, 127, 158, 176, 175, 177, 158, 177, + 157, 10, 1083, 825, 826, 176, 179, 829, 157, 176, + 179, 177, 174, 176, 884, 176, 150, 1545, 121, 174, + 176, 179, 10, 10, 127, 1553, 158, 10, 176, 10, + 164, 1559, 1560, 1229, 158, 169, 10, 13, 10, 15, + 174, 17, 157, 1183, 1184, 174, 1186, 150, 1188, 1239, + 1240, 179, 177, 923, 176, 156, 1542, 927, 928, 1140, + 930, 164, 932, 179, 176, 1146, 169, 157, 1149, 158, + 165, 174, 174, 165, 1602, 1156, 946, 1605, 176, 165, + 950, 951, 165, 174, 177, 907, 956, 63, 176, 158, + 177, 961, 176, 10, 158, 176, 176, 176, 10, 969, + 10, 158, 158, 973, 10, 158, 174, 15, 1636, 176, + 176, 176, 65, 157, 984, 985, 177, 1603, 177, 157, + 166, 1202, 176, 1204, 176, 166, 1654, 166, 176, 166, + 10, 176, 158, 1214, 1215, 1216, 176, 90, 10, 10, + 158, 174, 1223, 174, 174, 158, 1227, 176, 1229, 174, + 158, 127, 1233, 176, 176, 10, 158, 110, 1239, 1240, + 176, 158, 1238, 607, 986, 1398, 1454, 1038, 990, 991, + 630, 1562, 1042, 1395, 150, 718, 1046, 1047, 10, 11, + 12, 13, 570, 630, 1007, 17, 1358, 324, 164, 1385, + 1060, -1, -1, 169, -1, 2, 149, 20, 21, 22, + 23, 24, 1398, -1, -1, -1, -1, -1, -1, -1, + -1, 34, -1, 1035, 1036, -1, -1, -1, -1, 1089, + -1, -1, 1044, 1045, -1, -1, 1048, -1, -1, -1, + -1, 63, -1, -1, -1, -1, -1, -1, -1, -1, + 47, -1, -1, -1, -1, -1, 53, 200, 201, -1, + -1, -1, 59, 60, 61, 62, 63, -1, 1454, 66, + -1, -1, -1, 1133, -1, -1, 10, 11, 12, -1, + -1, -1, -1, -1, -1, 228, -1, 1358, -1, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 1212, 121, + -1, -1, -1, -1, 247, 127, -1, 34, -1, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 261, 262, + 1450, 1181, -1, -1, 1395, -1, -1, 34, 150, -1, + 1190, -1, 1403, 1404, 1405, 69, 1407, -1, -1, 1410, + 1200, -1, 164, -1, -1, -1, -1, 169, 82, 83, + 1162, -1, -1, 1213, 167, 168, 169, 170, 171, -1, + 173, 174, 175, 306, 307, -1, 163, 1438, -1, 312, + -1, -1, -1, -1, -1, 1505, -1, -1, -1, -1, + -1, 324, -1, -1, -1, 1456, -1, 121, 122, 1460, + 124, -1, -1, 1464, 23, 24, 130, -1, 132, -1, + 1471, -1, 1214, 1215, 1216, 34, 1536, -1, -1, 143, + 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, + 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, + 227, -1, 1217, 230, 161, 162, 163, 164, 235, -1, + 167, 168, 169, 170, 171, -1, 173, 174, 175, -1, + -1, -1, 159, 396, 161, 162, 163, 164, -1, 402, + 167, 168, 169, 170, 171, -1, 173, 174, 175, 266, + -1, 1542, -1, -1, 1545, -1, -1, -1, -1, -1, + -1, -1, 1553, -1, -1, 1556, 1557, 1558, 1559, 1560, + -1, 1562, -1, -1, -1, -1, -1, -1, -1, -1, + 443, -1, -1, -1, -1, 302, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 1647, 1648, 1649, + -1, 1651, 319, 320, -1, -1, -1, 1387, -1, 326, + -1, 1602, 1603, -1, 1605, -1, 1450, -1, 167, 168, + 169, 170, 171, -1, 173, 174, 175, -1, 1408, -1, + -1, 1411, -1, -1, 18, 19, 20, 21, 22, 23, + 24, -1, 505, 55, -1, 1636, 58, 59, 60, 61, + 34, 10, 11, 12, -1, -1, -1, 520, -1, 71, + -1, -1, 379, 1654, -1, -1, 1500, 1501, 1502, 1503, + -1, 1505, -1, 1507, 1665, 1455, -1, -1, 90, 1459, + 543, -1, 1673, 1463, -1, -1, -1, -1, -1, 552, + -1, -1, -1, -1, -1, 107, 1476, -1, -1, 1479, + 1480, 1481, -1, -1, -1, 422, 1438, -1, -1, -1, + 69, -1, -1, -1, -1, -1, -1, 129, 130, -1, + -1, -1, -1, 82, 83, -1, -1, -1, -1, 592, + 593, -1, -1, -1, 146, -1, -1, -1, 1443, 151, + 1445, 1446, 1447, 1448, 1449, 608, 1451, 610, 611, 612, + 613, 614, 615, -1, -1, 618, -1, -1, -1, -1, + -1, -1, 121, 122, -1, 124, -1, 1547, -1, 632, + 633, 130, -1, 132, -1, -1, -1, -1, 641, 496, + 164, 165, 166, 167, 168, 169, 170, 171, -1, 173, + 174, 175, -1, -1, 511, -1, -1, -1, 1217, -1, + -1, 3, 4, 5, 6, 164, 8, 9, 10, -1, + 169, 1516, 1517, 1518, 1519, 1520, 1521, 1522, 1523, 1524, + 1525, 1526, 1527, 1528, 1529, 1530, 1531, 1532, 1533, 1534, + 1610, -1, -1, -1, -1, 1615, 1616, 18, 19, 20, + 21, 22, 23, 24, -1, -1, -1, -1, -1, 51, + -1, -1, -1, 34, 1634, -1, -1, 574, 575, 576, + 577, -1, 579, -1, -1, 67, -1, -1, -1, -1, + 72, 588, 1577, -1, -1, 1655, -1, 740, -1, 81, + 82, -1, -1, -1, 1664, 87, -1, -1, -1, 91, + 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, + 102, 103, 104, 105, 106, -1, -1, 624, 17, 18, + 19, 20, 21, 22, 23, 24, -1, 119, -1, 121, + -1, -1, -1, 1628, 126, 34, 1631, -1, -1, 131, + -1, -1, 134, -1, 797, -1, -1, 139, 17, 18, + 19, 20, 21, 22, 23, 24, -1, -1, 665, -1, + -1, -1, -1, -1, -1, 34, -1, -1, -1, 822, + -1, -1, 164, -1, 681, 167, 168, 169, -1, -1, + 172, -1, 174, 175, -1, -1, 178, -1, -1, -1, + -1, -1, 845, -1, 165, 166, 167, 168, 169, 170, + 171, 708, 173, 174, 175, -1, -1, -1, -1, -1, + -1, -1, 719, 720, 721, 722, 723, 724, 725, 726, + 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, + 737, 738, 739, -1, 1443, 742, 1445, 1446, 1447, 1448, + 1449, -1, 1451, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 905, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 162, 163, 164, 165, 166, 167, 168, + 169, 170, 171, -1, 173, 174, 175, 784, -1, -1, + 10, 11, 12, 936, -1, 3, 4, 5, 6, -1, + 8, 9, 10, 162, 163, 164, -1, 15, 167, 168, + 169, 170, 171, -1, 173, 174, 175, 1516, 1517, 1518, + 1519, 1520, 1521, 1522, 1523, 1524, 1525, 1526, 1527, 1528, + 1529, 1530, 1531, 1532, 1533, 1534, -1, -1, -1, -1, + 48, -1, 50, 51, -1, -1, -1, -1, -1, 69, + -1, -1, -1, 850, -1, -1, -1, -1, 1001, 67, + -1, -1, 82, 83, 72, -1, -1, -1, -1, -1, + -1, -1, 11, 81, 82, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 162, -1, 1500, 165, 166, -1, -1, -1, 170, - -1, 172, -1, -1, -1, 176, 147, 778, -1, -1, - -1, -1, -1, -1, -1, -1, 2, -1, -1, -1, - -1, -1, -1, 1048, 1531, -1, -1, -1, -1, 68, - -1, -1, -1, -1, -1, -1, 1537, -1, -1, 1540, - -1, -1, 81, 82, -1, -1, 1219, 1548, -1, -1, - 1551, 1552, 1553, -1, -1, -1, 1557, 198, 199, 830, - -1, 47, -1, -1, -1, -1, -1, 53, -1, 840, - 841, -1, -1, 59, 60, 61, 62, 63, -1, -1, - 66, 120, 121, -1, 123, 226, -1, 858, -1, 128, - -1, 130, -1, -1, -1, 1385, 1597, 1598, -1, 1600, - -1, 1447, -1, -1, 245, -1, -1, -1, 1398, -1, - -1, -1, -1, -1, -1, -1, -1, 258, 259, 158, - -1, -1, -1, 162, -1, -1, -1, -1, 167, -1, - 1631, -1, 903, 1640, 1641, 1642, -1, 1644, -1, -1, - -1, 10, 11, 12, -1, -1, 1647, -1, -1, 1495, - 1496, 1497, 1498, -1, 1500, -1, 1502, 1658, -1, -1, - -1, 1451, 303, 304, -1, 1666, -1, -1, 309, -1, - 941, -1, -1, 944, 945, 161, 947, -1, 949, -1, - 321, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 963, -1, -1, -1, 967, 968, -1, 68, - -1, -1, 973, -1, -1, -1, -1, 978, 10, 11, - 12, -1, 81, 82, -1, 986, -1, -1, -1, 205, - 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, - 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, - -1, -1, 228, -1, -1, -1, -1, 233, -1, -1, - 391, 120, 121, -1, 123, 396, -1, -1, -1, 128, - -1, 130, -1, -1, -1, -1, 68, 1440, -1, 1442, - 1443, 1444, 1445, 1446, -1, 1448, -1, 263, -1, 81, - 82, -1, 1053, -1, -1, 1056, 1057, -1, -1, -1, - -1, -1, -1, 162, -1, -1, 437, -1, 167, 1070, - -1, -1, -1, -1, -1, -1, 10, 11, 12, -1, - -1, -1, -1, 299, -1, -1, -1, -1, 120, 121, - -1, 123, -1, -1, -1, -1, 128, 1098, 130, -1, - 316, 317, -1, -1, -1, -1, -1, 323, 1511, 1512, - 1513, 1514, 1515, 1516, 1517, 1518, 1519, 1520, 1521, 1522, - 1523, 1524, 1525, 1526, 1527, 1528, 1529, -1, 499, -1, - -1, -1, -1, -1, 68, -1, -1, -1, -1, -1, - -1, 1142, -1, 514, -1, -1, -1, 81, 82, -1, - 3, 4, 5, 6, -1, 8, 9, 10, 374, -1, - -1, -1, 15, -1, -1, -1, 537, -1, 1169, -1, - -1, 1172, -1, -1, -1, 546, -1, -1, -1, -1, - -1, -1, -1, -1, 1185, -1, 120, 121, -1, 123, - -1, -1, -1, 1194, 128, 48, 130, 50, 51, -1, - 416, -1, -1, 1204, -1, 3, 4, 5, 6, -1, - 8, 9, 10, 66, 1215, 586, 587, 15, 71, -1, - 154, -1, -1, 1626, -1, -1, -1, 80, 81, -1, - -1, -1, -1, 604, -1, 606, 607, 608, 609, 610, - 611, -1, -1, 614, 17, 18, 19, 20, 21, 22, - 23, 24, -1, 51, -1, -1, -1, 628, 629, -1, - -1, 34, 115, -1, -1, 118, 637, 120, 66, 22, - 23, 24, 125, 71, 490, -1, 129, -1, -1, 132, - -1, 34, 80, 81, 137, -1, -1, 140, 86, 505, - -1, -1, 90, 91, 92, 93, 94, 95, 96, 97, - 98, 99, 100, 101, 102, 103, 104, 105, -1, 162, - -1, -1, 165, 166, -1, -1, -1, 170, -1, 172, - 118, -1, 120, 176, 695, -1, -1, 125, -1, -1, - -1, 129, -1, 11, 132, -1, -1, -1, -1, 137, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 568, 569, 570, 571, -1, 573, -1, -1, - -1, -1, -1, -1, 162, -1, 582, 165, 166, 167, - -1, -1, 170, -1, 172, 173, -1, 55, 176, 57, - 58, 59, 60, -1, -1, 756, 1387, 160, 161, 162, - 163, 164, 165, 166, 167, 168, 169, -1, 171, 172, - 173, -1, -1, -1, 620, -1, -1, -1, -1, -1, - -1, 89, 165, 166, 167, 168, 169, -1, 171, 172, - 173, -1, -1, -1, -1, -1, -1, -1, 106, -1, - -1, -1, -1, -1, 3, 4, 5, 6, -1, 8, - 9, 10, 813, -1, -1, 661, 15, -1, -1, 127, - 128, 1452, -1, -1, -1, 1456, -1, -1, -1, 1460, - 676, -1, -1, -1, -1, -1, 144, -1, -1, -1, - -1, 149, 1473, -1, -1, 1476, 1477, 1478, -1, -1, - -1, -1, 51, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 864, 22, 23, 24, 66, -1, -1, - -1, -1, 71, -1, -1, -1, 34, -1, 724, -1, - -1, 80, 81, -1, -1, -1, 10, 11, 12, 735, - 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, - 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, - -1, 1542, 758, -1, -1, -1, 115, -1, -1, 118, - -1, 120, 923, 1554, 1555, -1, 125, -1, -1, -1, - 129, -1, -1, 132, -1, -1, -1, -1, 137, -1, - -1, 140, -1, -1, 68, -1, -1, -1, -1, -1, - -1, -1, 953, -1, 800, -1, -1, 81, 82, -1, - -1, -1, -1, 162, -1, -1, 165, 166, -1, -1, - -1, 170, -1, 172, 1605, -1, -1, 176, -1, 3, - 4, 5, 6, -1, 8, 9, 10, 11, 12, -1, - -1, 837, -1, -1, -1, -1, 120, 121, 1629, 123, - -1, -1, 848, -1, 128, -1, 130, 165, 166, 167, - 168, 169, 1013, 171, 172, 173, -1, 1648, -1, -1, - -1, 145, -1, 869, -1, -1, 1657, 51, 52, -1, - -1, 55, -1, 57, 58, 59, 60, 61, 62, -1, - -1, -1, 66, 67, -1, -1, 70, 71, -1, 1050, - 74, -1, -1, -1, -1, -1, 80, 81, 82, -1, - -1, -1, 86, -1, -1, 89, 90, 91, 92, 93, - 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, - 104, 105, 106, -1, -1, -1, 10, 11, 12, -1, - -1, 115, -1, 117, 118, -1, 120, -1, 10, 11, - 12, 125, -1, 127, 128, 129, -1, -1, 132, 133, - -1, -1, -1, 137, 960, -1, 140, 141, 142, 143, - 144, -1, -1, 147, -1, 149, -1, -1, -1, -1, - -1, 6, -1, -1, -1, -1, -1, -1, 162, -1, - -1, 165, 166, 167, 68, -1, 170, -1, 172, 173, - -1, -1, 176, -1, -1, -1, 68, 81, 82, -1, - -1, -1, -1, 1009, -1, -1, -1, -1, -1, 81, - 82, -1, -1, -1, -1, -1, -1, -1, -1, 54, - -1, 1027, -1, -1, -1, -1, 1032, 62, 63, 64, - 65, -1, -1, -1, -1, -1, 120, 121, -1, 123, - 75, 76, 77, 78, 128, -1, 130, -1, 120, 121, - 122, 123, -1, 88, -1, -1, 128, -1, 130, 16, - 17, 18, 19, 20, 21, 22, 23, 24, -1, 141, - -1, 1077, -1, 157, 146, -1, -1, 34, 113, 1240, - -1, -1, -1, -1, -1, -1, 1092, -1, -1, 124, - -1, -1, -1, -1, -1, 130, -1, -1, -1, 134, - 135, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 146, -1, 148, -1, 3, 4, 5, 6, 7, + -1, -1, -1, -1, -1, -1, 1039, -1, -1, -1, + -1, 121, 122, -1, 124, -1, -1, -1, 116, -1, + 130, 119, 132, 121, -1, -1, 55, -1, 126, 58, + 59, 60, 61, 131, -1, -1, 134, -1, -1, -1, + -1, 139, 1631, -1, 142, -1, 156, 3, 4, 5, + 6, -1, 8, 9, 10, 11, 943, -1, -1, -1, + -1, 90, -1, -1, -1, -1, 164, -1, -1, 167, + 168, -1, -1, -1, 172, -1, 174, -1, 107, -1, + 178, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 981, 51, -1, -1, -1, 55, + 129, 130, 58, 59, 60, 61, 993, -1, -1, -1, + 997, 67, -1, 69, 70, 71, 72, 146, -1, -1, + -1, -1, 151, -1, -1, 81, 82, 83, 1015, -1, + -1, 87, -1, 1020, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, + 106, 107, -1, -1, -1, -1, -1, -1, -1, -1, + 116, -1, 118, 119, -1, 121, -1, -1, -1, -1, + 126, -1, -1, 129, 130, 131, -1, -1, 134, -1, + -1, 1068, -1, 139, -1, -1, 142, -1, -1, -1, + 146, -1, -1, -1, -1, 151, 1083, -1, -1, -1, + 156, -1, -1, -1, -1, 1238, -1, -1, 164, -1, + -1, 167, 168, 169, -1, -1, 172, -1, 174, 175, + -1, -1, 178, -1, -1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, -1, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, -1, - -1, 1147, -1, 1149, -1, 1151, 34, 35, 36, 37, + -1, 1138, -1, 1140, -1, 1142, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, -1, -1, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, - 68, 69, 70, 71, 72, -1, 74, -1, 76, 77, - 78, 79, 80, 81, 82, 83, 84, 85, -1, 87, - 88, 89, 159, 160, 161, 162, 163, 164, 165, 166, - 167, 168, 169, -1, 171, 172, 173, -1, 106, -1, - 177, -1, -1, -1, -1, 113, 114, 115, 116, 117, + 68, 69, 70, 71, 72, 73, -1, 75, -1, 77, + 78, 79, 80, 81, 82, 83, 84, 85, 86, -1, + 88, 89, 90, 16, 17, 18, 19, 20, 21, 22, + 23, 24, -1, -1, -1, -1, -1, -1, -1, 107, + -1, 34, -1, -1, -1, -1, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, - 148, 149, 150, 10, 11, -1, 154, 155, 156, 157, + 148, 149, 150, 151, 152, -1, 10, 11, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, - -1, -1, -1, 10, 11, 12, -1, -1, -1, 10, - 11, 12, -1, -1, -1, 52, -1, -1, 55, -1, - 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, - 67, -1, -1, 70, -1, -1, 55, 74, 57, 58, - 59, 60, -1, -1, -1, 82, -1, -1, -1, -1, - -1, 70, 89, -1, -1, -1, -1, -1, -1, -1, - -1, 68, -1, -1, -1, -1, -1, 68, -1, 106, - 89, -1, -1, -1, 81, 82, -1, -1, -1, 1530, - 81, 82, 119, -1, -1, -1, -1, 106, 1384, -1, - 127, 128, -1, -1, -1, -1, 133, -1, -1, -1, - -1, -1, -1, -1, 141, 142, 143, 144, 127, 128, - 147, -1, 149, 120, 121, -1, 123, 154, 1569, 120, - 121, 128, 123, 130, -1, 144, -1, 128, -1, 130, - 149, -1, -1, 170, 141, -1, -1, -1, -1, 146, - 141, -1, 3, 4, 5, 6, 7, 8, 9, 10, - 11, 12, 13, 172, 15, 16, 17, 18, 19, 20, - 21, 22, 23, 24, 25, 26, -1, -1, -1, -1, - -1, -1, 1468, 34, 35, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, - 51, 52, -1, -1, 55, 56, 57, 58, 59, 60, - 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, - 71, 72, -1, 74, -1, 76, 77, 78, 79, 80, - 81, 82, 83, 84, 85, -1, 87, 88, 89, -1, - -1, -1, -1, -1, -1, -1, 1532, -1, -1, -1, - -1, -1, -1, -1, -1, 106, -1, -1, -1, -1, - -1, -1, 113, 114, 115, 116, 117, 118, 119, 120, - 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, - 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, - 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, - -1, -1, -1, 154, 155, 156, 157, 158, 159, 160, - 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, - 171, 172, 173, 174, -1, 176, 177, 3, 4, 5, - 6, -1, 8, 9, 10, 11, -1, -1, -1, -1, + 178, 179, -1, 55, -1, -1, 58, 59, 60, 61, + -1, -1, -1, -1, -1, 10, 11, 12, 52, -1, + -1, 55, 56, -1, 58, 59, 60, 61, 62, -1, + -1, 10, 11, 12, 68, -1, -1, 71, 90, -1, + -1, 75, -1, -1, -1, -1, -1, -1, -1, 83, + -1, -1, -1, -1, -1, 107, 90, -1, 161, 162, + 163, 164, 165, 166, 167, 168, 169, 170, 171, -1, + 173, 174, 175, 107, 69, -1, 179, 129, 130, -1, + -1, -1, -1, -1, -1, -1, 120, 82, 83, -1, + 69, -1, -1, -1, 146, 129, 130, 1384, -1, 151, + -1, 135, 1535, 82, 83, -1, -1, -1, -1, 143, + 144, 145, 146, -1, -1, 149, -1, 151, -1, -1, + -1, -1, 156, -1, -1, -1, 121, 122, -1, 124, + -1, -1, -1, -1, -1, 130, -1, 132, 172, -1, + -1, 1574, 121, 122, -1, 124, -1, -1, -1, -1, + -1, 130, 147, 132, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 13, -1, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 24, 25, 26, -1, -1, + 159, -1, -1, -1, 1471, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, 52, -1, -1, 55, 56, 57, 58, + 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, + 69, 70, 71, 72, 73, -1, 75, -1, 77, 78, + 79, 80, 81, 82, 83, 84, 85, 86, -1, 88, + 89, 90, -1, -1, -1, -1, -1, -1, -1, -1, + 1537, -1, -1, -1, -1, -1, -1, -1, 107, -1, + -1, -1, -1, -1, -1, 114, 115, 116, 117, 118, + 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, + 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, + 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, + 149, 150, 151, 152, -1, -1, -1, 156, 157, 158, + 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, + 169, 170, 171, 172, 173, 174, 175, 176, -1, 178, + 179, 3, 4, 5, 6, -1, 8, 9, 10, 11, + 12, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 16, - 17, 18, 19, 20, 21, 22, 23, 24, -1, -1, - -1, -1, -1, -1, -1, 51, 52, 34, -1, 55, - -1, 57, 58, 59, 60, 61, -1, -1, -1, -1, - 66, 67, -1, -1, 70, 71, -1, -1, 74, -1, - -1, -1, -1, -1, 80, 81, 82, -1, -1, -1, - 86, -1, -1, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, - 106, -1, -1, -1, -1, -1, -1, -1, -1, 115, - -1, 117, 118, -1, 120, -1, -1, -1, -1, 125, - -1, 127, 128, 129, -1, -1, 132, 133, -1, -1, - -1, 137, -1, -1, 140, 141, 142, 143, 144, -1, - -1, 147, -1, 149, 3, 4, 5, 6, -1, 8, - 9, 10, 11, -1, -1, -1, 162, -1, -1, 165, - 166, 167, -1, -1, 170, -1, 172, 173, -1, -1, - 176, -1, 159, 160, 161, 162, 163, 164, 165, 166, - 167, 168, 169, -1, 171, 172, 173, -1, -1, -1, - 177, -1, 51, -1, -1, -1, 55, -1, 57, 58, - 59, 60, -1, -1, -1, -1, -1, 66, -1, 68, - 69, 70, 71, -1, -1, -1, -1, -1, -1, -1, - -1, 80, 81, 82, -1, -1, -1, 86, -1, -1, - 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, - 99, 100, 101, 102, 103, 104, 105, 106, -1, -1, - -1, -1, -1, -1, -1, -1, 115, -1, 117, 118, - -1, 120, -1, -1, -1, -1, 125, -1, 127, 128, - 129, -1, -1, 132, -1, -1, -1, -1, 137, -1, - -1, 140, -1, -1, -1, 144, 3, 4, 5, 6, - 149, 8, 9, 10, 11, 154, -1, -1, 15, -1, - -1, -1, -1, 162, -1, -1, 165, 166, 167, -1, - -1, 170, -1, 172, 173, -1, -1, 176, 16, 17, - 18, 19, 20, 21, 22, 23, 24, -1, -1, -1, - -1, -1, -1, -1, 51, -1, 34, -1, 55, -1, - 57, 58, 59, 60, -1, -1, -1, -1, -1, 66, - -1, -1, -1, 70, 71, -1, -1, -1, -1, -1, - -1, -1, -1, 80, 81, 82, -1, -1, -1, 86, - -1, -1, 89, 90, 91, 92, 93, 94, 95, 96, - 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, - -1, -1, -1, -1, -1, -1, -1, -1, 115, -1, - 117, 118, -1, 120, -1, -1, -1, -1, 125, -1, - 127, 128, 129, -1, -1, 132, -1, -1, -1, -1, - 137, -1, -1, 140, -1, -1, -1, 144, 3, 4, - 5, 6, 149, 8, 9, 10, 11, -1, -1, -1, - -1, -1, -1, -1, -1, 162, -1, -1, 165, 166, - 167, -1, -1, 170, -1, 172, 173, -1, -1, 176, - -1, 159, 160, 161, 162, 163, 164, 165, 166, 167, - 168, 169, -1, 171, 172, 173, 51, -1, -1, 177, - 55, -1, 57, 58, 59, 60, -1, -1, -1, -1, - -1, 66, -1, -1, -1, 70, 71, -1, -1, -1, - -1, -1, -1, -1, -1, 80, 81, 82, -1, -1, - -1, 86, -1, -1, 89, 90, 91, 92, 93, 94, - 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, - 105, 106, -1, -1, -1, -1, -1, -1, -1, -1, - 115, -1, 117, 118, -1, 120, -1, -1, -1, -1, - 125, -1, 127, 128, 129, -1, -1, 132, -1, -1, - -1, -1, 137, -1, -1, 140, -1, -1, -1, 144, - 3, 4, 5, 6, 149, 8, 9, 10, 11, -1, - -1, -1, -1, -1, -1, -1, -1, 162, -1, -1, - 165, 166, 167, -1, -1, 170, -1, 172, 173, 174, - -1, 176, 16, 17, 18, 19, 20, 21, 22, 23, - 24, -1, -1, -1, -1, -1, -1, -1, 51, 52, - 34, -1, 55, -1, 57, 58, 59, 60, -1, -1, - -1, -1, -1, 66, -1, -1, -1, 70, 71, -1, - -1, -1, -1, -1, -1, -1, -1, 80, 81, 82, - -1, -1, -1, 86, -1, -1, 89, 90, 91, 92, + -1, -1, -1, 16, 17, 18, 19, 20, 21, 22, + 23, 24, -1, -1, -1, -1, -1, -1, -1, 51, + 52, 34, -1, 55, 56, -1, 58, 59, 60, 61, + 62, 63, -1, -1, -1, 67, 68, -1, -1, 71, + 72, -1, -1, 75, -1, -1, -1, -1, -1, 81, + 82, 83, -1, -1, -1, 87, -1, -1, 90, 91, + 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, + 102, 103, 104, 105, 106, 107, -1, -1, -1, -1, + -1, -1, -1, -1, 116, -1, 118, 119, -1, 121, + -1, -1, -1, -1, 126, -1, -1, 129, 130, 131, + -1, -1, 134, 135, -1, -1, -1, 139, -1, -1, + 142, 143, 144, 145, 146, -1, -1, 149, -1, 151, + 3, 4, 5, 6, -1, 8, 9, 10, 11, -1, + -1, -1, 164, -1, -1, 167, 168, 169, -1, -1, + 172, -1, 174, 175, -1, -1, 178, -1, 161, 162, + 163, 164, 165, 166, 167, 168, 169, 170, 171, -1, + 173, 174, 175, -1, -1, -1, 179, -1, 51, 52, + -1, -1, 55, 56, -1, 58, 59, 60, 61, 62, + -1, -1, -1, -1, 67, 68, -1, -1, 71, 72, + -1, -1, 75, -1, -1, -1, -1, -1, 81, 82, + 83, -1, -1, -1, 87, -1, -1, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, - 103, 104, 105, 106, -1, -1, -1, -1, -1, -1, - -1, -1, 115, -1, 117, 118, -1, 120, -1, -1, - -1, -1, 125, -1, 127, 128, 129, -1, -1, 132, - -1, -1, -1, -1, 137, -1, -1, 140, -1, -1, - -1, 144, 3, 4, 5, 6, 149, 8, 9, 10, - 11, -1, -1, -1, -1, -1, -1, -1, -1, 162, - -1, -1, 165, 166, 167, -1, -1, 170, -1, 172, - 173, -1, 156, 176, -1, 159, 160, 161, 162, 163, - 164, 165, 166, 167, 168, 169, -1, 171, 172, 173, - 51, 52, -1, -1, 55, -1, 57, 58, 59, 60, - -1, -1, -1, -1, -1, 66, -1, -1, -1, 70, - 71, -1, -1, -1, -1, -1, -1, -1, -1, 80, - 81, 82, -1, -1, -1, 86, -1, -1, 89, 90, - 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, - 101, 102, 103, 104, 105, 106, -1, -1, 55, -1, - 57, 58, 59, 60, 115, -1, 117, 118, -1, 120, - -1, -1, -1, -1, 125, -1, 127, 128, 129, -1, - -1, 132, -1, -1, -1, -1, 137, -1, -1, 140, - -1, -1, 89, 144, 3, 4, 5, 6, 149, 8, - 9, 10, 11, -1, -1, -1, -1, -1, -1, 106, - -1, 162, -1, -1, 165, 166, 167, -1, -1, 170, - -1, 172, 173, -1, -1, 176, -1, -1, -1, -1, - 127, 128, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 51, -1, -1, -1, 55, 144, 57, 58, - 59, 60, 149, -1, -1, -1, -1, 66, -1, -1, - -1, 70, 71, -1, -1, -1, -1, -1, -1, -1, - -1, 80, 81, 82, -1, 172, -1, 86, -1, -1, - 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, - 99, 100, 101, 102, 103, 104, 105, 106, -1, -1, - -1, -1, -1, -1, -1, -1, 115, -1, 117, 118, - -1, 120, -1, -1, -1, -1, 125, -1, 127, 128, - 129, -1, -1, 132, -1, -1, -1, -1, 137, -1, - -1, 140, -1, -1, -1, 144, 3, 4, 5, 6, - 149, 8, 9, 10, 11, -1, -1, -1, -1, -1, - -1, -1, -1, 162, -1, -1, 165, 166, 167, -1, - -1, 170, -1, 172, 173, 174, -1, 176, 16, 17, - 18, 19, 20, 21, 22, 23, 24, -1, -1, -1, - -1, -1, -1, -1, 51, -1, 34, -1, 55, -1, - 57, 58, 59, 60, -1, -1, -1, -1, -1, 66, - -1, -1, -1, 70, 71, -1, -1, -1, -1, -1, - -1, -1, -1, 80, 81, 82, -1, -1, -1, 86, - -1, -1, 89, 90, 91, 92, 93, 94, 95, 96, - 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, - -1, -1, -1, -1, -1, -1, -1, -1, 115, -1, - 117, 118, -1, 120, -1, -1, -1, -1, 125, -1, - 127, 128, 129, -1, -1, 132, -1, -1, -1, -1, - 137, -1, -1, 140, -1, -1, -1, 144, 3, 4, - 5, 6, 149, 8, 9, 10, 11, 154, -1, -1, - -1, -1, -1, -1, -1, 162, -1, -1, 165, 166, - 167, -1, -1, 170, -1, 172, 173, 155, -1, 176, - -1, 159, 160, 161, 162, 163, 164, 165, 166, 167, - 168, 169, -1, 171, 172, 173, 51, -1, -1, -1, - 55, -1, 57, 58, 59, 60, -1, -1, -1, -1, - -1, 66, -1, -1, -1, 70, 71, -1, -1, -1, - -1, -1, -1, -1, -1, 80, 81, 82, -1, -1, - -1, 86, -1, -1, 89, 90, 91, 92, 93, 94, - 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, - 105, 106, -1, -1, -1, -1, -1, -1, -1, -1, - 115, -1, 117, 118, -1, 120, -1, -1, -1, -1, - 125, -1, 127, 128, 129, -1, -1, 132, -1, -1, - -1, -1, 137, -1, -1, 140, -1, -1, -1, 144, - 3, 4, 5, 6, 149, 8, 9, 10, 11, 154, - -1, -1, -1, -1, -1, -1, -1, 162, -1, -1, - 165, 166, 167, -1, -1, 170, -1, 172, 173, -1, - -1, 176, 16, 17, 18, 19, 20, 21, 22, 23, - 24, -1, -1, -1, -1, -1, -1, -1, 51, -1, - 34, -1, 55, -1, 57, 58, 59, 60, -1, -1, - -1, -1, -1, 66, -1, -1, -1, 70, 71, -1, - -1, -1, -1, -1, -1, -1, -1, 80, 81, 82, - -1, -1, -1, 86, -1, -1, 89, 90, 91, 92, + 103, 104, 105, 106, 107, -1, -1, -1, -1, -1, + -1, -1, -1, 116, -1, 118, 119, -1, 121, -1, + -1, -1, -1, 126, -1, -1, 129, 130, 131, -1, + -1, 134, 135, -1, -1, -1, 139, -1, -1, 142, + 143, 144, 145, 146, -1, -1, 149, -1, 151, -1, + 3, 4, 5, 6, -1, 8, 9, 10, 11, -1, + -1, 164, 15, -1, 167, 168, 169, -1, -1, 172, + -1, 174, 175, -1, -1, 178, -1, -1, -1, -1, + -1, 16, 17, 18, 19, 20, 21, 22, 23, 24, + -1, -1, -1, -1, -1, -1, -1, -1, 51, 34, + -1, -1, 55, -1, -1, 58, 59, 60, 61, -1, + -1, -1, -1, -1, 67, -1, -1, -1, 71, 72, + -1, -1, -1, -1, -1, -1, -1, -1, 81, 82, + 83, -1, -1, -1, 87, -1, -1, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, - 103, 104, 105, 106, -1, -1, -1, -1, -1, -1, - -1, -1, 115, -1, 117, 118, -1, 120, -1, -1, - -1, -1, 125, -1, 127, 128, 129, -1, -1, 132, - -1, -1, -1, -1, 137, -1, -1, 140, -1, -1, - -1, 144, 3, 4, 5, 6, 149, 8, 9, 10, - 11, -1, -1, -1, -1, -1, -1, -1, -1, 162, - -1, -1, 165, 166, 167, -1, -1, 170, -1, 172, - 173, 174, -1, 176, -1, 159, 160, 161, 162, 163, - 164, 165, 166, 167, 168, 169, -1, 171, 172, 173, - 51, -1, -1, -1, 55, -1, 57, 58, 59, 60, - -1, -1, -1, -1, -1, 66, -1, -1, -1, 70, - 71, -1, -1, -1, -1, -1, -1, -1, -1, 80, - 81, 82, -1, -1, -1, 86, -1, -1, 89, 90, + 103, 104, 105, 106, 107, -1, -1, -1, -1, -1, + -1, -1, -1, 116, -1, 118, 119, -1, 121, -1, + -1, -1, -1, 126, -1, -1, 129, 130, 131, -1, + -1, 134, -1, -1, -1, -1, 139, -1, -1, 142, + -1, -1, -1, 146, 3, 4, 5, 6, 151, 8, + 9, 10, 11, -1, -1, -1, -1, -1, -1, -1, + -1, 164, -1, -1, 167, 168, 169, -1, -1, 172, + -1, 174, 175, -1, -1, 178, 161, 162, 163, 164, + 165, 166, 167, 168, 169, 170, 171, -1, 173, 174, + 175, -1, 51, -1, 179, -1, 55, -1, -1, 58, + 59, 60, 61, -1, -1, -1, -1, -1, 67, 10, + 11, 12, 71, 72, -1, -1, -1, -1, -1, -1, + -1, -1, 81, 82, 83, -1, -1, -1, 87, -1, + -1, 90, 91, 92, 93, 94, 95, 96, 97, 98, + 99, 100, 101, 102, 103, 104, 105, 106, 107, -1, + -1, -1, -1, -1, -1, -1, -1, 116, -1, 118, + 119, -1, 121, -1, -1, -1, -1, 126, 69, -1, + 129, 130, 131, -1, -1, 134, -1, -1, -1, -1, + 139, 82, 83, 142, -1, -1, -1, 146, 3, 4, + 5, 6, 151, 8, 9, 10, 11, -1, -1, -1, + -1, -1, -1, -1, -1, 164, -1, -1, 167, 168, + 169, -1, -1, 172, -1, 174, 175, 176, -1, 178, + 121, 122, -1, 124, -1, -1, -1, -1, -1, 130, + -1, 132, -1, -1, -1, -1, 51, 52, -1, -1, + 55, -1, -1, 58, 59, 60, 61, -1, -1, -1, + -1, -1, 67, -1, -1, 156, 71, 72, -1, -1, + -1, 17, -1, -1, -1, -1, 81, 82, 83, -1, + -1, -1, 87, -1, -1, 90, 91, 92, 93, 94, + 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, + 105, 106, 107, -1, -1, -1, -1, -1, -1, -1, + -1, 116, -1, 118, 119, -1, 121, 63, -1, 65, + -1, 126, -1, -1, 129, 130, 131, -1, -1, 134, + -1, -1, -1, -1, 139, -1, 82, 142, -1, -1, + -1, 146, 3, 4, 5, 6, 151, 8, 9, 10, + 11, -1, -1, -1, -1, -1, -1, -1, -1, 164, + -1, -1, 167, 168, 169, -1, -1, 172, 114, 174, + 175, 117, 118, 178, -1, 121, -1, -1, 16, 17, + 18, 19, 20, 21, 22, 23, 24, -1, -1, -1, + 51, 52, 138, -1, 55, -1, 34, 58, 59, 60, + 61, -1, -1, -1, 150, -1, 67, -1, -1, -1, + 71, 72, -1, -1, -1, -1, -1, -1, 164, -1, + 81, 82, 83, -1, -1, -1, 87, -1, -1, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, - 101, 102, 103, 104, 105, 106, -1, -1, -1, -1, - -1, -1, -1, -1, 115, -1, 117, 118, -1, 120, - -1, -1, -1, -1, 125, -1, 127, 128, 129, -1, - -1, 132, -1, -1, -1, -1, 137, -1, -1, 140, - -1, -1, -1, 144, 3, 4, 5, 6, 149, 8, - 9, 10, 11, -1, 18, 19, 20, 21, 22, 23, - 24, 162, -1, -1, 165, 166, 167, -1, -1, 170, - 34, 172, 173, -1, -1, 176, 16, 17, 18, 19, - 20, 21, 22, 23, 24, -1, -1, -1, -1, -1, - -1, -1, 51, -1, 34, -1, 55, -1, 57, 58, - 59, 60, -1, -1, -1, -1, -1, 66, -1, -1, - -1, 70, 71, -1, -1, -1, -1, -1, -1, -1, - -1, 80, 81, 82, -1, -1, -1, 86, -1, -1, - 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, + 101, 102, 103, 104, 105, 106, 107, -1, -1, -1, + -1, -1, -1, -1, -1, 116, -1, 118, 119, -1, + 121, -1, -1, -1, -1, 126, -1, -1, 129, 130, + 131, -1, -1, 134, -1, -1, -1, -1, 139, -1, + -1, 142, -1, -1, -1, 146, 3, 4, 5, 6, + 151, 8, 9, 10, 11, -1, -1, -1, -1, -1, + -1, -1, -1, 164, -1, -1, 167, 168, 169, -1, + -1, 172, -1, 174, 175, -1, -1, 178, -1, -1, + -1, 159, -1, 161, 162, 163, 164, 165, 166, 167, + 168, 169, 170, 171, 51, 173, 174, 175, 55, -1, + -1, 58, 59, 60, 61, -1, -1, -1, -1, -1, + 67, -1, -1, -1, 71, 72, -1, -1, -1, -1, + -1, -1, -1, -1, 81, 82, 83, -1, -1, -1, + 87, -1, -1, 90, 91, 92, 93, 94, 95, 96, + 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, + 107, -1, -1, -1, -1, -1, -1, -1, -1, 116, + -1, 118, 119, -1, 121, -1, -1, -1, -1, 126, + -1, -1, 129, 130, 131, -1, -1, 134, -1, -1, + -1, -1, 139, -1, -1, 142, -1, -1, -1, 146, + 3, 4, 5, 6, 151, 8, 9, 10, 11, -1, + -1, -1, -1, -1, -1, -1, -1, 164, -1, -1, + 167, 168, 169, -1, -1, 172, -1, 174, 175, 176, + -1, 178, -1, -1, -1, -1, 16, 17, 18, 19, + 20, 21, 22, 23, 24, -1, -1, -1, 51, -1, + -1, -1, 55, -1, 34, 58, 59, 60, 61, -1, + -1, -1, -1, -1, 67, -1, -1, -1, 71, 72, + -1, -1, -1, -1, -1, -1, -1, -1, 81, 82, + 83, -1, -1, -1, 87, -1, -1, 90, 91, 92, + 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, + 103, 104, 105, 106, 107, -1, -1, -1, -1, -1, + -1, -1, -1, 116, -1, 118, 119, -1, 121, -1, + -1, -1, -1, 126, -1, -1, 129, 130, 131, -1, + -1, 134, -1, -1, -1, -1, 139, -1, -1, 142, + -1, -1, -1, 146, 3, 4, 5, 6, 151, 8, + 9, 10, 11, 156, -1, -1, -1, -1, -1, -1, + -1, 164, -1, -1, 167, 168, 169, -1, -1, 172, + -1, 174, 175, -1, -1, 178, -1, -1, -1, 159, + -1, 161, 162, 163, 164, 165, 166, 167, 168, 169, + 170, 171, 51, 173, 174, 175, 55, -1, -1, 58, + 59, 60, 61, -1, -1, -1, -1, -1, 67, -1, + -1, -1, 71, 72, -1, -1, -1, -1, -1, -1, + -1, -1, 81, 82, 83, -1, -1, -1, 87, -1, + -1, 90, 91, 92, 93, 94, 95, 96, 97, 98, + 99, 100, 101, 102, 103, 104, 105, 106, 107, -1, + -1, -1, -1, -1, -1, -1, -1, 116, -1, 118, + 119, -1, 121, -1, -1, -1, -1, 126, -1, -1, + 129, 130, 131, -1, -1, 134, -1, -1, -1, -1, + 139, -1, -1, 142, -1, -1, -1, 146, 3, 4, + 5, 6, 151, 8, 9, 10, 11, 156, -1, -1, + -1, -1, -1, -1, -1, 164, -1, -1, 167, 168, + 169, -1, -1, 172, -1, 174, 175, -1, -1, 178, + 16, 17, 18, 19, 20, 21, 22, 23, 24, -1, + -1, -1, -1, -1, -1, -1, 51, -1, 34, -1, + 55, -1, -1, 58, 59, 60, 61, -1, -1, -1, + -1, -1, 67, -1, -1, -1, 71, 72, -1, -1, + -1, -1, -1, -1, -1, -1, 81, 82, 83, -1, + -1, -1, 87, -1, -1, 90, 91, 92, 93, 94, + 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, + 105, 106, 107, -1, -1, -1, -1, -1, -1, -1, + -1, 116, -1, 118, 119, -1, 121, -1, -1, -1, + -1, 126, -1, -1, 129, 130, 131, -1, -1, 134, + -1, -1, -1, -1, 139, -1, -1, 142, -1, -1, + -1, 146, 3, 4, 5, 6, 151, 8, 9, 10, + 11, -1, -1, -1, -1, -1, -1, -1, -1, 164, + -1, -1, 167, 168, 169, -1, -1, 172, -1, 174, + 175, 176, 158, 178, -1, 161, 162, 163, 164, 165, + 166, 167, 168, 169, 170, 171, -1, 173, 174, 175, + 51, -1, -1, -1, 55, -1, -1, 58, 59, 60, + 61, -1, -1, -1, -1, -1, 67, -1, -1, -1, + 71, 72, -1, -1, -1, -1, -1, -1, -1, -1, + 81, 82, 83, -1, -1, -1, 87, -1, -1, 90, + 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, + 101, 102, 103, 104, 105, 106, 107, -1, -1, -1, + -1, -1, -1, -1, -1, 116, -1, 118, 119, -1, + 121, -1, -1, -1, -1, 126, -1, -1, 129, 130, + 131, -1, -1, 134, -1, -1, -1, -1, 139, -1, + -1, 142, -1, -1, -1, 146, 3, 4, 5, 6, + 151, 8, 9, 10, 11, -1, 18, 19, 20, 21, + 22, 23, 24, 164, -1, -1, 167, 168, 169, -1, + -1, 172, 34, 174, 175, -1, -1, 178, -1, -1, + -1, -1, 16, 17, 18, 19, 20, 21, 22, 23, + 24, -1, -1, -1, 51, -1, -1, -1, 55, -1, + 34, 58, 59, 60, 61, -1, -1, -1, -1, -1, + 67, -1, -1, -1, 71, 72, -1, -1, -1, -1, + -1, -1, -1, -1, 81, 82, 83, -1, -1, -1, + 87, -1, -1, 90, 91, 92, 93, 94, 95, 96, + 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, + 107, -1, -1, -1, -1, -1, -1, -1, -1, 116, + -1, 118, 119, -1, 121, -1, -1, -1, -1, 126, + -1, -1, 129, 130, 131, -1, -1, 134, -1, -1, + -1, -1, 139, -1, -1, 142, -1, -1, -1, 146, + 3, 4, 5, 6, 151, 8, 9, 10, -1, -1, + -1, -1, 15, -1, -1, 167, 168, 169, 170, 171, + -1, 173, 174, 175, -1, 172, -1, 174, 175, -1, + -1, 178, -1, 157, -1, -1, -1, 161, 162, 163, + 164, 165, 166, 167, 168, 169, 170, 171, 51, 173, + 174, 175, 176, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 67, 10, 11, 12, -1, 72, + -1, -1, -1, -1, -1, -1, -1, -1, 81, 82, + -1, -1, -1, -1, 87, -1, -1, -1, 91, 92, + 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, + 103, 104, 105, 106, 3, 4, 5, 6, -1, 8, + 9, 10, -1, -1, -1, -1, 119, -1, 121, -1, + -1, -1, -1, 126, 69, -1, -1, -1, 131, -1, + 75, 134, -1, -1, -1, -1, 139, 82, 83, -1, + 16, 17, 18, 19, 20, 21, 22, 23, 24, -1, + -1, -1, 51, -1, -1, -1, -1, -1, 34, -1, + -1, 164, -1, -1, 167, 168, 169, -1, 67, 172, + 115, 174, 175, 72, -1, 178, 121, 122, -1, 124, + -1, -1, 81, 82, -1, 130, -1, 132, 87, -1, + -1, -1, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, -1, -1, - -1, -1, -1, -1, -1, -1, 115, -1, 117, 118, - -1, 120, -1, -1, -1, -1, 125, -1, 127, 128, - 129, -1, -1, 132, -1, -1, -1, -1, 137, -1, - -1, 140, -1, -1, -1, 144, 3, 4, 5, 6, - 149, 8, 9, 10, -1, -1, 160, 161, 162, 163, - 164, 165, 166, 167, 168, 169, -1, 171, 172, 173, - -1, 170, -1, 172, 173, -1, -1, 176, -1, 159, - 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, - -1, 171, 172, 173, 51, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 66, - -1, -1, -1, -1, 71, -1, -1, -1, -1, -1, - -1, -1, -1, 80, 81, -1, -1, -1, -1, 86, - -1, -1, -1, 90, 91, 92, 93, 94, 95, 96, - 97, 98, 99, 100, 101, 102, 103, 104, 105, 3, - 4, 5, 6, -1, 8, 9, 10, -1, -1, -1, - -1, 118, -1, 120, -1, -1, -1, -1, 125, -1, - -1, -1, 129, -1, -1, 132, -1, -1, -1, -1, - 137, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 51, -1, -1, - -1, -1, -1, -1, -1, 162, -1, -1, 165, 166, - 167, -1, 66, 170, -1, 172, 173, 71, -1, 176, - 20, 21, 22, 23, 24, -1, 80, 81, -1, -1, - -1, -1, 86, -1, 34, -1, 90, 91, 92, 93, - 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, - 104, 105, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 118, -1, 120, -1, -1, -1, - -1, 125, -1, -1, 6, 129, -1, -1, 132, 10, - 11, -1, -1, 137, 16, 17, 18, 19, 20, 21, - 22, 23, 24, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 34, -1, 36, 37, 38, 39, 40, 41, - 42, 43, 44, 45, 46, 47, 170, -1, 172, 173, - -1, 52, 176, -1, 55, -1, 57, 58, 59, 60, - 61, -1, -1, -1, -1, -1, 67, 69, -1, 70, - -1, -1, -1, 74, -1, -1, -1, -1, 10, 11, - 12, 82, -1, 15, -1, -1, -1, -1, 89, -1, - -1, -1, -1, 163, 164, 165, 166, 167, 168, 169, - -1, 171, 172, 173, -1, 106, -1, -1, -1, -1, - -1, -1, -1, 115, -1, -1, -1, -1, 119, -1, - -1, -1, -1, -1, -1, -1, 127, 128, -1, -1, - 10, 11, 133, -1, -1, -1, 68, -1, -1, -1, - 141, 142, 143, 144, -1, -1, 147, -1, 149, 81, - 82, -1, -1, 155, -1, -1, 158, -1, 160, 161, - 162, 163, 164, 165, 166, 167, 168, 169, 170, 170, - 172, 173, 52, -1, 176, 55, -1, 57, 58, 59, - 60, 61, -1, -1, -1, -1, -1, 67, 120, 121, - 70, 123, -1, -1, 74, -1, 128, -1, 130, -1, - -1, -1, 82, -1, -1, -1, -1, -1, -1, 89, - 16, 17, 18, 19, 20, 21, 22, 23, 24, -1, - -1, -1, -1, -1, -1, -1, 106, -1, 34, -1, - -1, 55, -1, 57, 58, 59, 60, -1, -1, 119, - -1, -1, -1, -1, -1, -1, -1, 127, 128, -1, - -1, -1, -1, 133, -1, -1, -1, -1, -1, -1, - -1, 141, 142, 143, 144, 89, -1, 147, -1, 149, - 16, 17, 18, 19, 20, 21, 22, 23, 24, -1, - -1, -1, 106, -1, -1, -1, -1, -1, 34, -1, - 170, 16, 17, 18, 19, 20, 21, 22, 23, 24, - -1, -1, -1, 127, 128, -1, -1, -1, -1, 34, - 16, 17, 18, 19, 20, 21, 22, 23, 24, -1, - 144, -1, -1, -1, -1, 149, -1, -1, 34, 16, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 119, -1, 121, -1, -1, -1, -1, 126, -1, -1, + -1, -1, 131, -1, -1, 134, 3, 4, 5, 6, + 139, 8, 9, 10, -1, -1, -1, -1, 15, -1, + -1, -1, -1, 3, 4, 5, 6, -1, 8, 9, + 10, -1, -1, -1, -1, 15, -1, -1, -1, -1, + -1, -1, -1, 172, -1, 174, 175, -1, -1, 178, + -1, 48, -1, 50, 51, 161, 162, 163, 164, 165, + 166, 167, 168, 169, 170, 171, -1, 173, 174, 175, + 67, 51, -1, -1, -1, 72, -1, -1, -1, -1, + -1, -1, -1, -1, 81, 82, -1, 67, -1, -1, + -1, -1, 72, 18, 19, 20, 21, 22, 23, 24, + -1, 81, 82, -1, -1, -1, -1, -1, -1, 34, + -1, -1, 18, 19, 20, 21, 22, 23, 24, 116, + -1, -1, 119, -1, 121, -1, -1, -1, 34, 126, + -1, -1, -1, -1, 131, -1, 116, 134, -1, 119, + -1, 121, 139, -1, -1, 142, 126, -1, -1, -1, + -1, 131, -1, -1, 134, -1, -1, -1, -1, 139, + -1, -1, 142, -1, -1, -1, -1, 164, -1, -1, + 167, 168, -1, -1, -1, 172, -1, 174, -1, -1, + -1, 178, -1, -1, 164, -1, -1, 167, 168, 6, + -1, -1, 172, -1, 174, -1, -1, -1, 178, 16, 17, 18, 19, 20, 21, 22, 23, 24, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 34, 172, 155, - -1, -1, -1, 159, 160, 161, 162, 163, 164, 165, - 166, 167, 168, 169, -1, 171, 172, 173, 174, 16, - 17, 18, 19, 20, 21, 22, 23, 24, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 34, 16, 17, - 18, 19, 20, 21, 22, 23, 24, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 34, -1, -1, -1, - -1, -1, -1, 159, 160, 161, 162, 163, 164, 165, - 166, 167, 168, 169, -1, 171, 172, 173, 174, -1, - -1, -1, -1, -1, 159, 160, 161, 162, 163, 164, - 165, 166, 167, 168, 169, -1, 171, 172, 173, 174, - -1, -1, -1, 159, 160, 161, 162, 163, 164, 165, - 166, 167, 168, 169, -1, 171, 172, 173, 174, -1, - -1, -1, 159, 160, 161, 162, 163, 164, 165, 166, - 167, 168, 169, -1, 171, 172, 173, 174, 16, 17, - 18, 19, 20, 21, 22, 23, 24, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 34, -1, -1, -1, - -1, -1, 159, 160, 161, 162, 163, 164, 165, 166, - 167, 168, 169, -1, 171, 172, 173, 174, -1, -1, - -1, 159, 160, 161, 162, 163, 164, 165, 166, 167, - 168, 169, -1, 171, 172, 173, 174, 16, 17, 18, + -1, -1, -1, -1, 10, 11, 12, 34, -1, 36, + 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, + 47, -1, -1, -1, -1, -1, -1, 162, 163, 164, + 165, 166, 167, 168, 169, 170, 171, -1, 173, 174, + 175, -1, -1, 70, -1, -1, 162, 163, 164, 10, + 11, 167, 168, 169, 170, 171, -1, 173, 174, 175, + -1, -1, -1, 69, -1, -1, -1, -1, -1, -1, + 20, 21, 22, 23, 24, -1, 82, 83, -1, -1, + -1, -1, -1, -1, 34, -1, -1, -1, -1, 116, + -1, 52, -1, -1, 55, 56, -1, 58, 59, 60, + 61, 62, -1, -1, -1, -1, -1, 68, -1, -1, + 71, -1, -1, -1, 75, 121, 122, -1, 124, -1, + -1, -1, 83, -1, 130, -1, 132, -1, -1, 90, + 157, -1, -1, 160, -1, 162, 163, 164, 165, 166, + 167, 168, 169, 170, 171, 172, 107, 174, 175, 10, + 11, 178, -1, -1, -1, -1, -1, -1, -1, 120, + -1, -1, -1, -1, -1, -1, -1, -1, 129, 130, + -1, -1, -1, -1, 135, -1, -1, -1, -1, -1, + -1, -1, 143, 144, 145, 146, -1, -1, 149, -1, + 151, 52, -1, -1, 55, 56, -1, 58, 59, 60, + 61, 62, -1, -1, -1, -1, -1, 68, -1, -1, + 71, 172, -1, -1, 75, 165, 166, 167, 168, 169, + 170, 171, 83, 173, 174, 175, -1, -1, -1, 90, + 16, 17, 18, 19, 20, 21, 22, 23, 24, -1, + -1, -1, -1, -1, -1, -1, 107, -1, 34, 16, + 17, 18, 19, 20, 21, 22, 23, 24, -1, 120, + -1, -1, -1, -1, -1, -1, -1, 34, 129, 130, + -1, -1, -1, 55, 135, -1, 58, 59, 60, 61, + -1, -1, 143, 144, 145, 146, -1, -1, 149, 71, + 151, 16, 17, 18, 19, 20, 21, 22, 23, 24, + -1, -1, -1, -1, -1, -1, -1, -1, 90, 34, + -1, 172, 16, 17, 18, 19, 20, 21, 22, 23, + 24, -1, -1, -1, -1, 107, -1, -1, -1, -1, + 34, 16, 17, 18, 19, 20, 21, 22, 23, 24, + -1, -1, -1, -1, -1, -1, -1, 129, 130, 34, + 16, 17, 18, 19, 20, 21, 22, 23, 24, -1, + -1, -1, -1, -1, 146, -1, -1, -1, 34, 151, + -1, -1, -1, -1, -1, 161, 162, 163, 164, 165, + 166, 167, 168, 169, 170, 171, -1, 173, 174, 175, + 176, -1, 174, -1, 161, 162, 163, 164, 165, 166, + 167, 168, 169, 170, 171, -1, 173, 174, 175, 176, + 16, 17, 18, 19, 20, 21, 22, 23, 24, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 34, -1, + -1, -1, -1, -1, -1, -1, 161, 162, 163, 164, + 165, 166, 167, 168, 169, 170, 171, -1, 173, 174, + 175, 176, -1, -1, -1, -1, -1, 161, 162, 163, + 164, 165, 166, 167, 168, 169, 170, 171, -1, 173, + 174, 175, 176, -1, -1, -1, 161, 162, 163, 164, + 165, 166, 167, 168, 169, 170, 171, -1, 173, 174, + 175, 176, -1, -1, -1, 161, 162, 163, 164, 165, + 166, 167, 168, 169, 170, 171, -1, 173, 174, 175, + 176, 16, 17, 18, 19, 20, 21, 22, 23, 24, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 34, + 16, 17, 18, 19, 20, 21, 22, 23, 24, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 34, -1, + -1, -1, -1, -1, -1, 161, 162, 163, 164, 165, + 166, 167, 168, 169, 170, 171, -1, 173, 174, 175, + 176, 16, 17, 18, 19, 20, 21, 22, 23, 24, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 34, + 16, 17, 18, 19, 20, 21, 22, 23, 24, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 34, 18, 19, 20, 21, 22, 23, 24, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 34, 16, 17, 18, 19, - 20, 21, 22, 23, 24, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 34, 16, 17, 18, 19, 20, - 21, 22, 23, 24, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 34, 16, 17, 18, 19, 20, 21, + -1, -1, -1, -1, -1, 34, 18, 19, 20, 21, 22, 23, 24, -1, -1, -1, -1, -1, -1, -1, -1, -1, 34, -1, -1, -1, -1, -1, -1, -1, - -1, 159, 160, 161, 162, 163, 164, 165, 166, 167, - 168, 169, -1, 171, 172, 173, 174, 16, 17, 18, - 19, 20, 21, 22, 23, 24, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 34, 16, 17, 18, 19, - 20, 21, 22, 23, 24, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 34, -1, -1, -1, -1, -1, - 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, - 169, -1, 171, 172, 173, 174, -1, -1, -1, 159, - 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, - -1, 171, 172, 173, 174, -1, 157, -1, 159, 160, - 161, 162, 163, 164, 165, 166, 167, 168, 169, -1, - 171, 172, 173, -1, -1, 157, -1, 159, 160, 161, - 162, 163, 164, 165, 166, 167, 168, 169, -1, 171, - 172, 173, 18, 19, 20, 21, 22, 23, 24, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 34, 18, - 19, 20, 21, 22, 23, 24, -1, -1, 157, -1, - 159, 160, 161, 162, -1, 34, 165, 166, 167, 168, - 169, -1, 171, 172, 173, -1, -1, -1, -1, 159, - 160, 161, 162, -1, -1, 165, 166, 167, 168, 169, - -1, 171, 172, 173, 18, 19, 20, 21, 22, 23, - 24, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 34, 18, 19, 20, 21, 22, 23, 24, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 34, 18, 19, - 20, 21, 22, 23, 24, -1, -1, -1, 55, -1, - 57, 58, 59, 60, 34, 18, 19, 20, 21, 22, - 23, 24, -1, -1, 18, 19, 20, 21, 22, 23, - 24, 34, -1, -1, -1, -1, -1, -1, -1, -1, - 34, -1, 89, -1, -1, 161, 162, 163, 164, 165, - 166, 167, 168, 169, -1, 171, 172, 173, -1, 106, - -1, -1, -1, 162, 163, 164, 165, 166, 167, 168, - 169, -1, 171, 172, 173, 20, 21, 22, 23, 24, - 127, 128, -1, -1, -1, -1, -1, -1, -1, 34, - -1, -1, -1, -1, -1, -1, -1, 144, -1, -1, - -1, -1, 149, -1, -1, -1, 160, 161, 162, -1, - -1, 165, 166, 167, 168, 169, -1, 171, 172, 173, - -1, -1, -1, -1, -1, 172, 163, 164, 165, 166, - 167, 168, 169, -1, 171, 172, 173, -1, -1, -1, - -1, 161, 162, -1, -1, 165, 166, 167, 168, 169, - 17, 171, 172, 173, -1, -1, -1, -1, -1, 162, - 6, -1, 165, 166, 167, 168, 169, -1, 171, 172, - 173, 165, 166, 167, 168, 169, -1, 171, 172, 173, - -1, 48, -1, 50, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 62, -1, 64, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 54, -1, - -1, 10, 11, 12, 81, -1, 62, 63, 64, 65, - 165, 166, 167, 168, 169, -1, 171, 172, 173, 75, - 76, 77, 78, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 88, -1, -1, -1, 113, -1, -1, 116, - 117, -1, -1, 120, -1, -1, 55, -1, 57, 58, - 59, 60, 61, 62, 10, 11, 12, 113, -1, 136, - -1, 70, -1, -1, -1, -1, -1, -1, 124, -1, - -1, 148, -1, 82, 130, -1, -1, -1, -1, 135, - 89, -1, -1, -1, -1, 162, -1, -1, -1, -1, - 146, -1, 148, -1, -1, 11, 12, 106, -1, 55, - -1, 57, 58, 59, 60, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 70, -1, -1, -1, 127, 128, - -1, -1, -1, -1, -1, 55, 82, 57, 58, 59, - 60, -1, 141, 89, -1, 144, 52, -1, 147, 55, - 149, 57, 58, 59, 60, 61, 62, -1, -1, -1, - 106, 67, -1, -1, 70, -1, -1, -1, 74, 89, - -1, -1, -1, -1, -1, -1, 82, -1, -1, -1, - -1, 127, 128, 89, -1, -1, 106, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 144, -1, - 106, 147, -1, 149, 11, 12, -1, 127, 128, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 124, -1, - -1, 127, 128, -1, 144, -1, -1, 133, -1, 149, - 11, 12, -1, -1, -1, 141, 142, 143, 144, -1, - -1, 147, -1, 149, -1, 52, -1, -1, 55, -1, - 57, 58, 59, 60, 61, 62, -1, -1, -1, -1, - 67, -1, -1, 70, -1, -1, -1, 74, -1, -1, - -1, 52, -1, -1, 55, 82, 57, 58, 59, 60, - 61, -1, 89, -1, -1, -1, 67, -1, -1, 70, - -1, -1, -1, 74, -1, -1, -1, -1, -1, 106, - -1, 82, -1, -1, -1, -1, -1, -1, 89, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 127, 128, -1, 11, 12, 106, 133, -1, -1, -1, - -1, -1, -1, -1, 141, 142, 143, 144, -1, -1, - 147, -1, 149, 124, -1, -1, 127, 128, -1, 11, - -1, -1, 133, -1, -1, -1, -1, -1, -1, -1, - 141, 142, 143, 144, 52, -1, 147, 55, 149, 57, - 58, 59, 60, 61, -1, -1, -1, -1, -1, 67, - -1, -1, 70, -1, -1, -1, 74, -1, -1, -1, - 52, -1, -1, 55, 82, 57, 58, 59, 60, 61, - 62, 89, -1, -1, -1, 67, -1, -1, 70, -1, - -1, -1, 74, -1, -1, -1, -1, -1, 106, -1, - 82, -1, -1, -1, -1, -1, -1, 89, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 127, - 128, -1, 11, -1, 106, 133, -1, -1, -1, -1, - -1, -1, -1, 141, 142, 143, 144, -1, -1, 147, - -1, 149, -1, -1, -1, 127, 128, -1, 11, -1, - -1, 133, -1, -1, -1, -1, -1, -1, -1, 141, - 142, 143, 144, 52, -1, 147, 55, 149, 57, 58, - 59, 60, 61, 62, -1, -1, -1, -1, 67, -1, - -1, 70, -1, -1, -1, 74, -1, -1, -1, 52, - -1, -1, 55, 82, 57, 58, 59, 60, 61, -1, - 89, -1, -1, -1, 67, -1, -1, 70, -1, -1, - -1, 74, -1, -1, -1, -1, -1, 106, -1, 82, - -1, -1, -1, -1, -1, -1, 89, -1, -1, -1, - -1, -1, -1, -1, 10, 11, 12, -1, 127, 128, - -1, 11, -1, 106, 133, -1, -1, -1, -1, 10, - 11, 12, 141, 142, 143, 144, -1, -1, 147, -1, - 149, -1, -1, -1, 127, 128, -1, -1, -1, -1, - 133, 10, 11, 12, -1, -1, -1, -1, 141, 142, - 143, 144, 52, -1, 147, 55, 149, 57, 58, 59, - 60, 61, 68, -1, -1, -1, -1, 67, -1, -1, - 70, -1, -1, -1, 74, 81, 82, 68, -1, -1, - -1, -1, 82, -1, -1, -1, -1, 54, -1, 89, - 81, 82, -1, -1, -1, 62, 63, 64, 65, 68, - -1, -1, -1, -1, -1, 74, 106, -1, 75, 76, - 77, 78, 81, 82, 120, 121, 83, 123, -1, -1, - -1, 88, 128, -1, 130, -1, -1, 127, 128, 120, - 121, -1, 123, 133, -1, 141, -1, 128, -1, 130, - 146, 141, 142, 143, 144, 114, 113, 147, -1, 149, - 141, 120, 121, -1, 123, 146, -1, 124, -1, 128, - -1, 130, -1, 130, 53, 54, -1, -1, 135, -1, - -1, -1, -1, 62, 63, 64, 65, -1, 145, 146, - -1, 148, -1, -1, 73, -1, 75, 76, 77, 78, - 79, -1, -1, -1, 83, -1, 163, -1, -1, 88, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 107, 108, - 109, 110, 111, 112, 113, 114, -1, -1, -1, -1, - -1, -1, 121, 122, 123, 124, -1, -1, -1, -1, - -1, 130, 131, 54, -1, 134, 135, -1, -1, -1, - 139, 62, 63, 64, 65, -1, 145, 146, -1, 148, - -1, -1, -1, -1, 75, 76, 77, 78, -1, -1, - 54, -1, 83, -1, 54, -1, -1, 88, 62, 63, - 64, 65, 62, 63, 64, 65, -1, -1, -1, -1, - -1, 75, 76, 77, 78, 75, 76, 77, 78, -1, - -1, -1, 113, -1, 88, -1, -1, 55, 88, 57, - 58, 59, 60, 124, -1, -1, -1, -1, -1, 130, - -1, -1, 70, 134, 135, -1, -1, -1, -1, 113, - 114, -1, -1, 113, 145, 146, -1, 148, -1, -1, - 124, 89, -1, -1, 124, -1, 130, -1, -1, -1, - 130, 135, -1, -1, -1, 135, -1, -1, 106, -1, - -1, -1, 146, -1, 148, -1, 146, -1, 148, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 127, - 128, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 144, -1, -1, -1, - -1, 149 + -1, -1, -1, -1, -1, -1, 161, 162, 163, 164, + 165, 166, 167, 168, 169, 170, 171, -1, 173, 174, + 175, 176, -1, -1, -1, 161, 162, 163, 164, 165, + 166, 167, 168, 169, 170, 171, -1, 173, 174, 175, + 176, 18, 19, 20, 21, 22, 23, 24, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 34, -1, -1, + -1, -1, 157, -1, -1, -1, 161, 162, 163, 164, + 165, 166, 167, 168, 169, 170, 171, -1, 173, 174, + 175, -1, -1, -1, -1, 161, 162, 163, 164, 165, + 166, 167, 168, 169, 170, 171, -1, 173, 174, 175, + 6, -1, -1, 17, 163, 164, 165, 166, 167, 168, + 169, 170, 171, -1, 173, 174, 175, -1, -1, -1, + -1, 163, 164, -1, -1, 167, 168, 169, 170, 171, + -1, 173, 174, 175, 48, -1, 50, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 54, 63, + -1, 65, -1, -1, -1, -1, -1, 63, 64, 65, + 66, -1, -1, -1, -1, -1, -1, -1, 82, -1, + 76, 77, 78, 79, -1, 6, -1, -1, -1, -1, + -1, -1, -1, 89, -1, -1, -1, 164, -1, -1, + 167, 168, 169, 170, 171, -1, 173, 174, 175, -1, + 114, -1, -1, 117, 118, -1, -1, 121, 114, -1, + -1, 10, 11, 12, -1, -1, -1, -1, -1, 125, + -1, -1, -1, 54, 138, -1, 132, -1, -1, -1, + 136, 137, 63, 64, 65, 66, 150, -1, -1, -1, + -1, -1, 148, -1, 150, 76, 77, 78, 79, -1, + 164, -1, -1, -1, -1, -1, 55, -1, 89, 58, + 59, 60, 61, 62, 63, 10, 11, 12, -1, -1, + -1, -1, 71, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 114, 83, -1, -1, -1, -1, -1, + -1, 90, -1, -1, 125, -1, -1, -1, -1, -1, + -1, 132, -1, -1, -1, -1, 137, -1, 107, -1, + 55, -1, -1, 58, 59, 60, 61, 148, -1, 150, + -1, -1, -1, 11, 12, -1, 71, -1, -1, -1, + 129, 130, -1, -1, -1, -1, -1, -1, 83, -1, + -1, -1, -1, -1, 143, 90, -1, 146, -1, -1, + 149, 150, 151, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 107, -1, 52, -1, -1, 55, 56, -1, + 58, 59, 60, 61, 62, 63, -1, -1, -1, -1, + 68, -1, -1, 71, 129, 130, -1, 75, 11, 12, + -1, -1, -1, -1, -1, 83, -1, -1, -1, -1, + -1, 146, 90, -1, 149, -1, 151, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 107, + -1, 11, -1, -1, -1, -1, -1, -1, -1, 52, + -1, -1, 55, 56, -1, 58, 59, 60, 61, 62, + -1, 129, 130, -1, -1, 68, -1, 135, 71, -1, + -1, -1, 75, -1, -1, 143, 144, 145, 146, -1, + 83, 149, 52, 151, -1, 55, 56, 90, 58, 59, + 60, 61, 62, 63, -1, -1, -1, -1, 68, -1, + -1, 71, -1, -1, 107, 75, 11, -1, -1, -1, + -1, -1, -1, 83, -1, -1, -1, -1, -1, -1, + 90, -1, -1, -1, -1, -1, 129, 130, -1, -1, + -1, -1, 135, -1, -1, -1, -1, 107, -1, 11, + 143, 144, 145, 146, -1, -1, 149, 52, 151, -1, + 55, 56, -1, 58, 59, 60, 61, 62, 63, 129, + 130, -1, -1, 68, -1, 135, 71, -1, -1, -1, + 75, -1, -1, 143, 144, 145, 146, -1, 83, 149, + 52, 151, -1, 55, 56, 90, 58, 59, 60, 61, + 62, -1, -1, -1, -1, -1, 68, -1, -1, 71, + -1, -1, 107, 75, 11, -1, -1, -1, -1, -1, + -1, 83, -1, -1, -1, -1, -1, -1, 90, -1, + -1, 10, 11, 12, 129, 130, -1, -1, -1, -1, + 135, -1, -1, -1, -1, 107, -1, -1, 143, 144, + 145, 146, -1, -1, 149, 52, 151, -1, 55, 56, + -1, 58, 59, 60, 61, 62, -1, 129, 130, -1, + -1, 68, -1, 135, 71, -1, -1, -1, 75, -1, + -1, 143, 144, 145, 146, -1, 83, 149, -1, 151, + 69, -1, -1, 90, -1, -1, -1, -1, 10, 11, + 12, -1, -1, 82, 83, -1, -1, -1, -1, -1, + 107, -1, -1, 10, 11, 12, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 10, 11, + 12, -1, 129, 130, -1, -1, -1, -1, 135, -1, + -1, -1, 121, 122, 123, 124, 143, 144, 145, 146, + -1, 130, 149, 132, 151, -1, -1, 69, -1, -1, + -1, -1, -1, -1, 143, -1, -1, -1, -1, 148, + 82, 83, 69, -1, -1, -1, -1, -1, 55, -1, + -1, 58, 59, 60, 61, 82, 83, 69, -1, -1, + 10, 11, 12, -1, -1, 15, -1, -1, -1, -1, + 82, 83, 55, -1, -1, 58, 59, 60, 61, 121, + 122, -1, 124, 90, -1, -1, -1, -1, 130, -1, + 132, -1, -1, -1, 121, 122, -1, 124, -1, -1, + 107, 143, -1, 130, -1, 132, 148, 90, -1, 121, + 122, -1, 124, -1, -1, -1, 143, -1, 130, 69, + 132, 148, 129, 130, 107, -1, -1, -1, -1, -1, + -1, 143, 82, 83, -1, -1, 148, -1, -1, 146, + -1, -1, -1, -1, 151, -1, 129, 130, 55, -1, + -1, 58, 59, 60, 61, -1, -1, -1, -1, -1, + -1, -1, -1, 146, -1, -1, -1, 174, 151, -1, + -1, 121, 122, -1, 124, -1, -1, -1, -1, -1, + 130, -1, 132, 90, -1, 54, -1, -1, -1, -1, + -1, 174, -1, -1, 63, 64, 65, 66, -1, -1, + 107, -1, -1, -1, -1, -1, -1, 76, 77, 78, + 79, -1, -1, -1, -1, 84, -1, -1, -1, -1, + 89, -1, 129, 130, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 146, + -1, -1, -1, -1, 151, 114, -1, -1, -1, 53, + 54, -1, -1, -1, -1, -1, 125, -1, -1, 63, + 64, 65, 66, 132, -1, -1, -1, 174, 137, -1, + 74, -1, 76, 77, 78, 79, 80, -1, 147, 148, + 84, 150, -1, -1, -1, 89, -1, -1, -1, -1, + 54, -1, -1, -1, -1, -1, 165, -1, -1, 63, + 64, 65, 66, -1, 108, 109, 110, 111, 112, 113, + 114, 115, 76, 77, 78, 79, -1, -1, 122, 123, + 124, 125, -1, -1, -1, 89, -1, -1, 132, 133, + 54, -1, 136, 137, -1, -1, -1, 141, -1, 63, + 64, 65, 66, 147, 148, -1, 150, 54, -1, -1, + 114, 115, 76, 77, 78, 79, 63, 64, 65, 66, + 84, 125, -1, -1, -1, 89, -1, -1, 132, 76, + 77, 78, 79, 137, -1, -1, -1, -1, -1, -1, + -1, -1, 89, -1, 148, -1, 150, -1, -1, -1, + 114, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 125, -1, -1, -1, -1, -1, 114, 132, -1, + -1, -1, 136, 137, -1, -1, -1, -1, 125, -1, + -1, -1, -1, 147, 148, 132, 150, -1, -1, -1, + 137, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 148, -1, 150 }; /* YYSTOS[STATE-NUM] -- The symbol kind of the accessing symbol of state STATE-NUM. */ static const yytype_int16 yystos[] = { - 0, 151, 152, 153, 179, 180, 290, 3, 4, 5, - 6, 8, 9, 10, 11, 51, 55, 57, 58, 59, - 60, 66, 70, 71, 80, 81, 82, 86, 89, 90, - 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, - 101, 102, 103, 104, 105, 106, 115, 117, 118, 120, - 125, 127, 128, 129, 132, 137, 140, 144, 149, 162, - 165, 166, 167, 170, 172, 173, 176, 280, 281, 289, - 11, 12, 52, 55, 57, 58, 59, 60, 61, 62, - 67, 70, 74, 82, 89, 106, 127, 128, 133, 141, - 142, 143, 144, 147, 149, 242, 243, 247, 248, 250, - 256, 258, 262, 263, 268, 269, 270, 271, 0, 48, - 50, 190, 290, 154, 172, 172, 172, 172, 172, 172, - 172, 163, 172, 163, 172, 172, 172, 172, 172, 172, - 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, - 172, 172, 172, 172, 11, 52, 67, 141, 142, 245, - 262, 263, 268, 280, 163, 172, 172, 15, 172, 280, - 163, 172, 172, 172, 280, 280, 280, 280, 280, 11, - 55, 57, 58, 59, 60, 70, 82, 89, 106, 127, - 128, 144, 149, 247, 278, 280, 10, 11, 12, 68, - 81, 82, 120, 121, 123, 128, 130, 158, 162, 167, - 284, 285, 287, 290, 280, 16, 17, 18, 19, 20, - 21, 22, 23, 24, 34, 159, 160, 161, 162, 163, - 164, 165, 166, 167, 168, 169, 171, 172, 173, 6, - 8, 242, 243, 172, 61, 133, 70, 106, 269, 269, - 269, 287, 172, 269, 13, 15, 17, 62, 148, 162, - 167, 172, 240, 241, 290, 241, 257, 190, 190, 145, - 191, 192, 287, 172, 156, 181, 277, 278, 290, 277, - 247, 277, 277, 277, 277, 277, 247, 277, 247, 277, - 247, 277, 247, 247, 247, 247, 247, 247, 247, 247, - 247, 247, 247, 247, 247, 247, 247, 247, 277, 172, - 287, 172, 172, 190, 190, 174, 247, 277, 277, 172, - 247, 247, 247, 280, 277, 277, 174, 155, 174, 287, - 287, 155, 177, 158, 230, 290, 280, 280, 280, 280, - 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, - 280, 280, 280, 280, 280, 280, 280, 287, 174, 278, - 280, 241, 241, 52, 280, 247, 167, 287, 190, 240, - 241, 240, 241, 190, 190, 15, 17, 162, 167, 190, - 225, 226, 235, 290, 173, 154, 10, 11, 12, 120, - 157, 288, 10, 11, 12, 120, 154, 287, 288, 287, - 49, 155, 172, 11, 52, 67, 141, 142, 244, 248, - 250, 256, 262, 263, 268, 280, 53, 54, 62, 63, - 64, 65, 73, 75, 76, 77, 78, 79, 83, 88, - 107, 108, 109, 110, 111, 112, 113, 114, 121, 122, - 123, 124, 130, 131, 134, 135, 139, 145, 146, 148, - 184, 186, 187, 189, 193, 213, 264, 267, 290, 175, - 174, 174, 174, 174, 174, 174, 174, 164, 174, 164, - 174, 174, 174, 174, 155, 174, 155, 174, 155, 174, + 0, 153, 154, 155, 181, 182, 292, 3, 4, 5, + 6, 8, 9, 10, 11, 51, 55, 58, 59, 60, + 61, 67, 71, 72, 81, 82, 83, 87, 90, 91, + 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, + 102, 103, 104, 105, 106, 107, 116, 118, 119, 121, + 126, 129, 130, 131, 134, 139, 142, 146, 151, 164, + 167, 168, 169, 172, 174, 175, 178, 282, 283, 291, + 11, 12, 52, 55, 56, 58, 59, 60, 61, 62, + 63, 68, 71, 75, 83, 90, 107, 129, 130, 135, + 143, 144, 145, 146, 149, 151, 244, 245, 249, 250, + 252, 258, 260, 264, 265, 270, 271, 272, 273, 0, + 48, 50, 192, 292, 156, 174, 174, 174, 174, 174, + 174, 174, 165, 174, 165, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, - 174, 280, 247, 277, 287, 287, 164, 174, 174, 287, - 174, 164, 174, 174, 174, 174, 280, 280, 15, 162, - 285, 172, 210, 290, 280, 157, 174, 177, 174, 174, - 174, 190, 190, 13, 15, 17, 62, 148, 162, 167, - 240, 290, 240, 240, 190, 190, 190, 62, 124, 242, - 243, 174, 15, 155, 276, 280, 290, 260, 261, 290, - 11, 259, 269, 157, 249, 251, 157, 190, 191, 3, - 4, 5, 9, 10, 15, 51, 66, 71, 80, 81, - 115, 118, 120, 125, 129, 132, 137, 140, 162, 165, - 166, 170, 172, 176, 227, 228, 235, 236, 282, 283, - 289, 290, 172, 287, 172, 174, 190, 190, 174, 76, - 88, 189, 189, 189, 189, 189, 189, 6, 189, 213, - 189, 280, 157, 188, 114, 189, 172, 172, 172, 172, - 172, 172, 189, 154, 190, 157, 157, 157, 189, 189, - 172, 187, 189, 193, 214, 189, 189, 197, 74, 114, - 287, 189, 189, 10, 11, 119, 154, 170, 200, 204, - 244, 246, 172, 172, 247, 247, 247, 174, 174, 174, - 172, 174, 172, 230, 225, 17, 62, 64, 81, 113, - 116, 117, 120, 136, 148, 162, 190, 280, 240, 167, - 287, 190, 240, 240, 190, 190, 173, 240, 240, 240, - 124, 242, 243, 235, 13, 17, 62, 148, 162, 167, - 172, 238, 288, 290, 13, 15, 17, 62, 148, 162, - 167, 172, 239, 210, 15, 235, 177, 287, 175, 259, - 180, 81, 252, 290, 191, 172, 163, 163, 245, 163, - 15, 172, 282, 163, 172, 280, 280, 280, 280, 247, - 278, 280, 174, 15, 155, 16, 17, 18, 19, 20, - 21, 22, 23, 24, 34, 159, 160, 161, 162, 163, - 164, 165, 166, 167, 168, 169, 171, 172, 173, 52, - 280, 247, 190, 287, 288, 287, 190, 189, 174, 186, - 154, 287, 287, 287, 287, 287, 287, 287, 180, 287, - 280, 163, 10, 11, 204, 244, 246, 287, 287, 156, - 190, 172, 172, 62, 242, 185, 287, 195, 154, 156, - 158, 232, 156, 194, 278, 278, 174, 174, 174, 278, - 278, 174, 280, 172, 34, 223, 290, 190, 190, 240, - 240, 240, 276, 174, 174, 174, 242, 243, 238, 239, - 167, 190, 238, 238, 190, 190, 238, 173, 230, 190, - 167, 287, 190, 239, 239, 190, 190, 239, 173, 230, - 190, 190, 190, 175, 157, 253, 254, 290, 49, 247, - 247, 247, 172, 247, 172, 247, 247, 247, 280, 174, - 174, 15, 236, 280, 280, 280, 280, 280, 280, 280, - 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, - 280, 280, 280, 280, 287, 174, 278, 280, 174, 174, - 174, 157, 189, 180, 154, 155, 155, 155, 155, 155, - 155, 175, 154, 155, 174, 10, 11, 12, 61, 62, - 141, 215, 216, 217, 218, 219, 268, 290, 172, 232, - 198, 156, 156, 158, 201, 10, 13, 167, 203, 242, - 13, 17, 62, 148, 162, 167, 237, 288, 290, 180, - 172, 154, 156, 157, 158, 231, 272, 273, 68, 69, - 154, 280, 13, 17, 62, 119, 148, 162, 167, 172, - 196, 220, 222, 288, 174, 174, 174, 174, 210, 174, - 174, 287, 62, 245, 154, 240, 177, 172, 172, 172, - 238, 239, 230, 230, 190, 238, 238, 238, 174, 276, - 190, 190, 239, 239, 239, 174, 276, 223, 155, 158, - 121, 122, 123, 141, 146, 255, 286, 287, 154, 155, - 190, 174, 164, 164, 277, 164, 287, 174, 164, 174, - 174, 280, 157, 174, 177, 259, 175, 266, 10, 10, - 10, 10, 10, 10, 265, 289, 156, 219, 164, 155, - 15, 287, 13, 17, 62, 148, 162, 167, 172, 238, - 239, 199, 222, 247, 225, 174, 167, 220, 225, 237, - 167, 190, 237, 237, 190, 190, 172, 173, 190, 175, - 205, 272, 182, 183, 287, 68, 69, 175, 274, 290, - 156, 156, 154, 233, 234, 280, 290, 156, 167, 190, - 220, 6, 16, 17, 18, 19, 20, 21, 22, 23, - 24, 34, 36, 37, 38, 39, 40, 41, 42, 43, - 44, 45, 46, 47, 69, 115, 155, 158, 160, 161, - 162, 163, 164, 165, 166, 167, 168, 169, 170, 172, - 173, 176, 211, 220, 190, 190, 220, 157, 172, 173, - 223, 158, 230, 232, 190, 190, 15, 174, 245, 241, - 272, 190, 225, 225, 225, 230, 230, 238, 172, 177, - 239, 172, 177, 280, 146, 286, 146, 286, 146, 286, - 287, 121, 122, 123, 15, 180, 255, 172, 172, 174, - 172, 174, 172, 280, 180, 155, 155, 174, 155, 224, - 290, 155, 155, 155, 180, 174, 238, 239, 187, 193, - 212, 213, 218, 287, 158, 167, 190, 190, 190, 158, - 229, 290, 230, 232, 156, 174, 172, 220, 174, 174, - 172, 190, 237, 237, 237, 208, 276, 225, 175, 154, - 155, 154, 172, 156, 156, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 15, 16, 17, 18, - 19, 20, 21, 22, 23, 24, 25, 26, 34, 35, - 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, - 46, 47, 48, 49, 50, 51, 52, 55, 56, 57, - 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, - 68, 69, 70, 71, 72, 74, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 87, 88, 89, 106, - 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, - 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, - 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, - 143, 144, 145, 146, 147, 148, 149, 150, 154, 155, - 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, - 166, 167, 168, 169, 170, 171, 172, 173, 174, 176, - 177, 275, 233, 175, 155, 190, 220, 10, 174, 177, - 190, 220, 220, 174, 280, 221, 276, 280, 155, 223, - 174, 241, 175, 174, 174, 174, 225, 190, 225, 190, - 155, 286, 286, 286, 286, 286, 286, 175, 278, 278, - 278, 278, 175, 10, 10, 156, 10, 174, 10, 10, - 10, 175, 156, 229, 247, 190, 51, 66, 71, 125, - 129, 132, 162, 165, 166, 167, 170, 172, 176, 279, - 281, 155, 210, 202, 174, 172, 210, 209, 237, 225, - 177, 174, 272, 183, 277, 277, 274, 175, 154, 280, - 220, 190, 227, 177, 196, 154, 210, 210, 210, 174, - 174, 174, 174, 174, 174, 174, 155, 174, 155, 156, - 155, 174, 174, 155, 174, 172, 163, 163, 163, 15, - 172, 279, 163, 279, 279, 279, 279, 279, 247, 278, - 279, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 34, 159, 160, 161, 162, 165, 166, 167, 168, 169, - 171, 172, 173, 199, 190, 225, 172, 206, 190, 225, - 174, 190, 210, 175, 175, 174, 175, 233, 174, 190, - 272, 190, 190, 190, 210, 210, 156, 10, 156, 10, - 10, 156, 156, 10, 156, 247, 247, 247, 247, 172, - 247, 247, 174, 174, 279, 279, 279, 279, 279, 279, - 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, - 279, 279, 279, 287, 174, 278, 280, 174, 207, 225, - 174, 210, 190, 15, 175, 210, 175, 223, 223, 223, - 190, 190, 155, 224, 174, 155, 155, 174, 174, 164, - 164, 164, 287, 174, 164, 279, 157, 174, 177, 210, - 225, 174, 210, 190, 10, 174, 156, 10, 10, 156, - 172, 172, 172, 174, 172, 279, 190, 174, 210, 156, - 174, 155, 174, 278, 278, 278, 278, 210, 190, 156, - 10, 156, 174, 174, 174, 174, 190, 223, 174, 223, - 156 + 174, 174, 174, 174, 174, 11, 52, 56, 68, 143, + 144, 247, 264, 265, 270, 282, 165, 174, 174, 15, + 174, 282, 165, 174, 174, 174, 282, 282, 282, 282, + 282, 11, 55, 58, 59, 60, 61, 71, 83, 90, + 107, 129, 130, 146, 151, 249, 280, 282, 10, 11, + 12, 69, 82, 83, 121, 122, 124, 130, 132, 160, + 164, 169, 286, 287, 289, 292, 282, 16, 17, 18, + 19, 20, 21, 22, 23, 24, 34, 161, 162, 163, + 164, 165, 166, 167, 168, 169, 170, 171, 173, 174, + 175, 6, 8, 244, 245, 174, 62, 135, 71, 107, + 271, 271, 271, 289, 174, 271, 13, 15, 17, 63, + 127, 150, 164, 169, 174, 242, 243, 292, 243, 259, + 192, 192, 147, 193, 194, 289, 174, 158, 183, 279, + 280, 292, 279, 249, 279, 279, 279, 279, 279, 249, + 279, 249, 279, 249, 279, 249, 249, 249, 249, 249, + 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, + 249, 279, 174, 289, 174, 174, 192, 192, 176, 249, + 279, 279, 174, 249, 249, 249, 282, 279, 279, 176, + 157, 176, 289, 289, 157, 179, 160, 232, 292, 282, + 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, + 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, + 289, 176, 280, 282, 243, 243, 52, 282, 249, 169, + 289, 192, 242, 243, 242, 243, 242, 243, 192, 192, + 15, 17, 164, 169, 192, 227, 228, 237, 292, 175, + 156, 10, 11, 12, 121, 159, 290, 10, 11, 12, + 121, 156, 289, 290, 289, 49, 157, 174, 11, 52, + 56, 68, 143, 144, 246, 250, 252, 258, 264, 265, + 270, 282, 53, 54, 63, 64, 65, 66, 74, 76, + 77, 78, 79, 80, 84, 89, 108, 109, 110, 111, + 112, 113, 114, 115, 122, 123, 124, 125, 132, 133, + 136, 137, 141, 147, 148, 150, 186, 188, 189, 191, + 195, 215, 266, 269, 292, 177, 176, 176, 176, 176, + 176, 176, 176, 166, 176, 166, 176, 176, 176, 176, + 157, 176, 157, 176, 157, 176, 176, 176, 176, 176, + 176, 176, 176, 176, 176, 176, 176, 282, 249, 279, + 289, 289, 166, 176, 176, 289, 176, 166, 176, 176, + 176, 176, 282, 282, 15, 164, 287, 174, 212, 292, + 282, 159, 176, 179, 176, 176, 176, 192, 192, 13, + 15, 17, 63, 127, 150, 164, 169, 242, 292, 242, + 242, 192, 192, 192, 77, 89, 191, 176, 15, 157, + 278, 282, 292, 262, 263, 292, 11, 261, 271, 159, + 251, 253, 159, 192, 193, 3, 4, 5, 9, 10, + 15, 51, 67, 72, 81, 82, 116, 119, 121, 126, + 131, 134, 139, 142, 164, 167, 168, 172, 174, 178, + 229, 230, 237, 238, 284, 285, 291, 292, 174, 289, + 174, 176, 192, 192, 176, 191, 191, 191, 191, 191, + 191, 6, 191, 215, 191, 282, 159, 190, 115, 191, + 174, 174, 174, 174, 174, 174, 191, 156, 192, 159, + 159, 159, 191, 191, 174, 189, 191, 195, 216, 191, + 191, 199, 75, 115, 289, 191, 191, 10, 11, 120, + 156, 172, 202, 206, 246, 248, 174, 174, 249, 249, + 249, 176, 176, 176, 174, 176, 174, 232, 227, 17, + 63, 65, 82, 114, 117, 118, 121, 138, 150, 164, + 192, 282, 242, 169, 289, 192, 242, 242, 242, 192, + 192, 175, 242, 242, 242, 244, 245, 212, 15, 237, + 179, 289, 177, 261, 182, 82, 254, 292, 193, 174, + 165, 165, 247, 165, 15, 174, 284, 165, 174, 282, + 282, 282, 282, 249, 280, 282, 176, 15, 157, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 34, 161, + 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, + 173, 174, 175, 52, 282, 249, 192, 289, 290, 289, + 192, 191, 176, 188, 156, 289, 289, 289, 289, 289, + 289, 289, 182, 289, 282, 165, 10, 11, 206, 246, + 248, 289, 289, 158, 192, 174, 174, 63, 244, 187, + 289, 197, 156, 158, 160, 234, 158, 196, 280, 280, + 176, 176, 176, 280, 280, 176, 282, 174, 34, 225, + 292, 192, 192, 242, 242, 242, 278, 176, 176, 176, + 13, 17, 63, 127, 150, 164, 169, 174, 240, 290, + 292, 13, 15, 17, 63, 127, 150, 164, 169, 174, + 241, 192, 192, 192, 177, 159, 255, 256, 292, 49, + 249, 249, 249, 174, 249, 174, 249, 249, 249, 282, + 176, 176, 15, 238, 282, 282, 282, 282, 282, 282, + 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, + 282, 282, 282, 282, 282, 289, 176, 280, 282, 176, + 176, 176, 159, 191, 182, 156, 157, 157, 157, 157, + 157, 157, 177, 156, 157, 176, 10, 11, 12, 62, + 63, 143, 150, 217, 218, 219, 220, 221, 270, 292, + 174, 234, 200, 158, 158, 160, 203, 10, 13, 169, + 205, 244, 13, 17, 63, 127, 150, 164, 169, 239, + 290, 292, 182, 174, 156, 158, 159, 160, 233, 274, + 275, 69, 70, 156, 282, 13, 17, 63, 120, 150, + 164, 169, 174, 198, 222, 224, 290, 176, 176, 176, + 176, 212, 176, 176, 289, 63, 247, 156, 242, 179, + 174, 174, 174, 169, 192, 240, 240, 240, 192, 192, + 240, 175, 232, 192, 169, 289, 192, 241, 241, 241, + 192, 192, 241, 175, 232, 225, 157, 160, 122, 123, + 124, 143, 148, 257, 288, 289, 156, 157, 192, 176, + 166, 166, 279, 166, 289, 176, 166, 176, 176, 282, + 159, 176, 179, 261, 177, 268, 10, 10, 10, 10, + 10, 10, 267, 291, 158, 221, 221, 166, 157, 15, + 289, 13, 17, 63, 127, 150, 164, 169, 174, 240, + 241, 201, 224, 249, 227, 176, 169, 222, 227, 239, + 169, 192, 239, 239, 239, 192, 192, 174, 175, 192, + 177, 207, 274, 184, 185, 289, 69, 70, 177, 276, + 292, 158, 158, 156, 235, 236, 282, 292, 158, 169, + 192, 222, 6, 16, 17, 18, 19, 20, 21, 22, + 23, 24, 34, 36, 37, 38, 39, 40, 41, 42, + 43, 44, 45, 46, 47, 70, 116, 157, 160, 162, + 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, + 174, 175, 178, 213, 222, 192, 192, 222, 159, 174, + 175, 225, 160, 232, 234, 192, 192, 15, 176, 247, + 243, 274, 192, 227, 227, 227, 192, 240, 240, 240, + 176, 278, 192, 192, 241, 241, 241, 176, 278, 282, + 148, 288, 148, 288, 148, 288, 289, 122, 123, 124, + 15, 182, 257, 174, 174, 176, 174, 176, 174, 282, + 182, 157, 157, 176, 157, 226, 292, 157, 157, 157, + 182, 176, 240, 241, 240, 241, 189, 195, 214, 215, + 220, 289, 160, 169, 192, 192, 192, 160, 231, 292, + 232, 234, 158, 176, 174, 222, 176, 176, 174, 192, + 239, 239, 239, 210, 278, 227, 177, 156, 157, 156, + 174, 158, 158, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 34, 35, 36, 37, + 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, + 70, 71, 72, 73, 75, 77, 78, 79, 80, 81, + 82, 83, 84, 85, 86, 88, 89, 90, 107, 114, + 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, + 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, + 145, 146, 147, 148, 149, 150, 151, 152, 156, 157, + 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, + 168, 169, 170, 171, 172, 173, 174, 175, 176, 178, + 179, 277, 235, 177, 157, 192, 222, 10, 176, 179, + 192, 222, 222, 176, 282, 223, 278, 282, 157, 225, + 176, 243, 177, 176, 176, 176, 240, 174, 179, 241, + 174, 179, 157, 288, 288, 288, 288, 288, 288, 177, + 280, 280, 280, 280, 177, 10, 10, 158, 10, 176, + 10, 10, 10, 177, 158, 231, 231, 249, 192, 51, + 67, 72, 126, 131, 134, 164, 167, 168, 169, 172, + 174, 178, 281, 283, 157, 212, 204, 176, 174, 212, + 211, 239, 227, 179, 176, 274, 185, 279, 279, 276, + 177, 156, 282, 222, 192, 229, 179, 198, 156, 212, + 212, 212, 227, 192, 227, 192, 176, 176, 176, 176, + 176, 157, 176, 157, 158, 157, 176, 176, 157, 176, + 174, 165, 165, 165, 15, 174, 281, 165, 281, 281, + 281, 281, 281, 249, 280, 281, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 34, 161, 162, 163, 164, + 167, 168, 169, 170, 171, 173, 174, 175, 201, 192, + 227, 174, 208, 192, 227, 176, 192, 212, 177, 177, + 176, 177, 235, 176, 192, 274, 192, 192, 192, 176, + 176, 158, 10, 158, 10, 10, 158, 158, 10, 158, + 249, 249, 249, 249, 174, 249, 249, 176, 176, 281, + 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, + 281, 281, 281, 281, 281, 281, 281, 281, 289, 176, + 280, 282, 176, 209, 227, 176, 212, 192, 15, 177, + 212, 177, 225, 225, 225, 212, 212, 157, 226, 176, + 157, 157, 176, 176, 166, 166, 166, 289, 176, 166, + 281, 159, 176, 179, 212, 227, 176, 212, 192, 192, + 192, 10, 176, 158, 10, 10, 158, 174, 174, 174, + 176, 174, 281, 192, 176, 212, 158, 176, 157, 176, + 280, 280, 280, 280, 212, 192, 158, 10, 158, 176, + 176, 176, 176, 192, 225, 176, 225, 158 }; /* YYR1[RULE-NUM] -- Symbol kind of the left-hand side of rule RULE-NUM. */ static const yytype_int16 yyr1[] = { - 0, 178, 179, 179, 179, 180, 180, 181, 180, 182, - 182, 183, 183, 183, 185, 184, 186, 186, 186, 186, - 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, - 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, - 186, 186, 186, 188, 187, 189, 189, 189, 189, 189, - 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, - 189, 189, 189, 190, 190, 190, 190, 190, 191, 191, - 192, 192, 194, 193, 193, 195, 193, 193, 193, 196, - 196, 198, 197, 197, 199, 199, 201, 200, 202, 200, - 203, 200, 205, 204, 206, 204, 207, 204, 208, 204, - 209, 204, 204, 210, 210, 210, 210, 210, 210, 210, - 210, 210, 210, 210, 210, 210, 210, 211, 211, 211, - 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, - 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, - 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, - 211, 211, 211, 211, 211, 211, 211, 212, 212, 212, - 213, 214, 213, 213, 213, 215, 215, 216, 216, 217, - 217, 218, 218, 218, 218, 218, 218, 218, 218, 218, - 219, 219, 219, 219, 220, 220, 220, 220, 220, 220, - 220, 220, 220, 220, 220, 221, 220, 222, 222, 223, - 223, 223, 224, 224, 225, 225, 225, 225, 225, 226, - 226, 227, 227, 227, 227, 227, 228, 228, 229, 229, - 230, 230, 231, 231, 231, 231, 231, 232, 232, 232, - 232, 232, 232, 233, 233, 233, 234, 234, 234, 234, - 235, 235, 235, 235, 235, 235, 235, 236, 236, 237, - 237, 237, 237, 237, 237, 237, 237, 237, 238, 238, - 238, 238, 238, 238, 238, 238, 238, 238, 238, 239, - 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, - 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, + 0, 180, 181, 181, 181, 182, 182, 183, 182, 184, + 184, 185, 185, 185, 187, 186, 188, 188, 188, 188, + 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, + 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, + 188, 188, 188, 190, 189, 191, 191, 191, 191, 191, + 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, + 191, 191, 191, 192, 192, 192, 192, 192, 193, 193, + 194, 194, 196, 195, 195, 197, 195, 195, 195, 198, + 198, 200, 199, 199, 201, 201, 203, 202, 204, 202, + 205, 202, 207, 206, 208, 206, 209, 206, 210, 206, + 211, 206, 206, 212, 212, 212, 212, 212, 212, 212, + 212, 212, 212, 212, 212, 212, 212, 213, 213, 213, + 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, + 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, + 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, + 213, 213, 213, 213, 213, 213, 213, 214, 214, 214, + 215, 216, 215, 215, 215, 217, 217, 218, 218, 219, + 219, 220, 220, 220, 220, 220, 220, 220, 220, 220, + 220, 220, 221, 221, 221, 221, 222, 222, 222, 222, + 222, 222, 222, 222, 222, 222, 222, 223, 222, 224, + 224, 225, 225, 225, 226, 226, 227, 227, 227, 227, + 227, 228, 228, 229, 229, 229, 229, 229, 230, 230, + 231, 231, 232, 232, 233, 233, 233, 233, 233, 234, + 234, 234, 234, 234, 234, 235, 235, 235, 236, 236, + 236, 236, 237, 237, 238, 238, 239, 239, 239, 239, + 239, 239, 239, 239, 239, 239, 240, 240, 240, 240, + 240, 240, 240, 240, 240, 240, 240, 240, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, - 241, 241, 241, 241, 242, 242, 242, 242, 242, 242, - 242, 242, 242, 242, 242, 242, 243, 244, 244, 244, - 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, - 245, 245, 245, 245, 245, 245, 245, 245, 246, 246, - 247, 247, 247, 247, 249, 248, 251, 250, 252, 252, - 253, 253, 254, 254, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 257, 256, 258, 258, 258, 258, - 259, 259, 260, 260, 260, 261, 261, 261, 262, 262, - 262, 263, 263, 263, 265, 264, 266, 264, 264, 264, - 267, 267, 267, 267, 268, 268, 268, 269, 269, 269, - 269, 269, 269, 269, 269, 269, 269, 269, 269, 269, - 269, 269, 270, 270, 270, 271, 273, 272, 274, 274, - 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, - 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, - 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, - 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, - 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, - 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, - 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, - 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, - 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, - 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, - 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, - 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, - 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, - 275, 275, 275, 275, 275, 275, 276, 276, 277, 277, - 278, 278, 279, 279, 279, 279, 279, 279, 279, 279, - 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, - 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, - 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, - 279, 279, 280, 280, 280, 280, 280, 280, 280, 280, - 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, - 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, - 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, - 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, - 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, - 280, 280, 280, 280, 281, 281, 281, 281, 281, 281, + 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, + 242, 243, 243, 243, 243, 243, 243, 243, 243, 243, + 243, 243, 243, 243, 243, 243, 244, 244, 244, 244, + 244, 244, 244, 244, 244, 244, 244, 244, 244, 245, + 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, + 246, 246, 246, 246, 247, 247, 247, 247, 247, 247, + 247, 247, 247, 248, 248, 249, 249, 249, 249, 251, + 250, 253, 252, 254, 254, 255, 255, 256, 256, 257, + 257, 257, 257, 257, 257, 257, 257, 257, 257, 259, + 258, 260, 260, 260, 260, 261, 261, 262, 262, 262, + 263, 263, 263, 264, 264, 264, 265, 265, 265, 267, + 266, 268, 266, 266, 266, 269, 269, 269, 269, 270, + 270, 270, 271, 271, 271, 271, 271, 271, 271, 271, + 271, 271, 271, 271, 271, 271, 271, 272, 272, 272, + 273, 275, 274, 276, 276, 277, 277, 277, 277, 277, + 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, + 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, + 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, + 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, + 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, + 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, + 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, + 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, + 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, + 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, + 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, + 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, + 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, + 277, 277, 277, 278, 278, 279, 279, 280, 280, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, - 281, 281, 281, 281, 281, 282, 282, 282, 282, 282, + 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, + 281, 281, 281, 281, 281, 281, 281, 281, 281, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, + 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, + 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, + 282, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, - 283, 284, 284, 284, 284, 284, 285, 285, 285, 285, - 286, 286, 286, 287, 287, 287, 287, 287, 287, 287, - 287, 287, 287, 287, 288, 288, 288, 288, 289, 289, - 289, 289, 290 + 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, + 283, 283, 284, 284, 284, 284, 284, 284, 284, 284, + 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, + 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, + 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, + 284, 284, 284, 284, 284, 284, 284, 285, 285, 285, + 285, 285, 285, 285, 285, 285, 285, 285, 286, 286, + 286, 286, 286, 287, 287, 287, 287, 288, 288, 288, + 289, 289, 289, 289, 289, 289, 289, 289, 289, 289, + 289, 290, 290, 290, 290, 291, 291, 291, 291, 292 }; /* YYR2[RULE-NUM] -- Number of symbols on the right-hand side of rule RULE-NUM. */ @@ -3266,30 +3229,31 @@ static const yytype_int8 yyr2[] = 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 2, 0, 6, 2, 2, 1, 1, 1, 3, 1, 1, 1, 2, 4, 2, 3, 3, 4, 2, 3, - 1, 1, 1, 1, 2, 3, 4, 2, 2, 3, - 3, 3, 4, 5, 3, 0, 7, 2, 3, 1, - 3, 4, 1, 2, 1, 1, 1, 3, 2, 1, - 3, 1, 1, 1, 3, 2, 1, 3, 1, 2, - 1, 2, 1, 3, 5, 3, 3, 1, 3, 3, - 3, 3, 4, 1, 1, 2, 1, 3, 3, 5, - 4, 5, 6, 4, 5, 6, 3, 1, 1, 1, - 2, 2, 2, 3, 3, 3, 4, 5, 1, 2, - 2, 2, 3, 3, 3, 4, 5, 8, 3, 1, - 3, 2, 2, 3, 3, 3, 4, 5, 8, 3, - 1, 1, 3, 2, 2, 3, 3, 3, 4, 5, - 1, 1, 3, 2, 2, 3, 3, 3, 4, 5, - 6, 11, 11, 11, 1, 1, 2, 1, 1, 1, - 3, 5, 4, 4, 4, 1, 1, 1, 1, 2, - 1, 1, 1, 3, 5, 3, 4, 4, 4, 1, - 1, 1, 2, 3, 3, 4, 4, 1, 1, 1, - 2, 3, 2, 3, 0, 6, 0, 9, 1, 1, - 1, 1, 2, 3, 1, 2, 2, 2, 3, 3, - 3, 3, 3, 3, 0, 5, 4, 2, 5, 3, - 1, 1, 1, 4, 6, 1, 3, 5, 1, 2, - 2, 1, 1, 1, 0, 7, 0, 7, 4, 5, - 3, 6, 4, 4, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, - 2, 2, 1, 1, 2, 1, 0, 2, 1, 2, + 4, 3, 1, 1, 1, 1, 2, 3, 4, 2, + 2, 3, 3, 3, 4, 5, 3, 0, 7, 2, + 3, 1, 3, 4, 1, 2, 1, 1, 1, 3, + 2, 1, 3, 1, 1, 1, 3, 2, 1, 3, + 1, 2, 1, 2, 1, 3, 5, 3, 3, 1, + 3, 3, 3, 3, 4, 1, 1, 2, 1, 3, + 3, 5, 5, 5, 1, 1, 1, 2, 2, 2, + 2, 3, 3, 3, 4, 5, 1, 2, 2, 2, + 2, 3, 3, 3, 4, 5, 8, 3, 1, 3, + 2, 2, 2, 3, 3, 3, 4, 5, 8, 3, + 1, 1, 3, 2, 2, 2, 3, 3, 3, 4, + 5, 1, 1, 3, 2, 2, 2, 3, 3, 3, + 4, 5, 6, 11, 11, 11, 1, 1, 2, 1, + 1, 1, 3, 5, 4, 4, 4, 1, 1, 1, + 1, 1, 2, 1, 1, 1, 3, 5, 3, 4, + 4, 4, 1, 1, 1, 1, 2, 3, 3, 4, + 4, 1, 1, 1, 1, 2, 3, 2, 3, 0, + 6, 0, 9, 1, 1, 1, 1, 2, 3, 1, + 2, 2, 2, 3, 3, 3, 3, 3, 3, 0, + 5, 4, 2, 5, 3, 1, 1, 1, 4, 6, + 1, 3, 5, 1, 2, 2, 1, 1, 1, 0, + 7, 0, 7, 4, 5, 3, 6, 4, 4, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 2, 2, 2, 2, 1, 1, 2, + 1, 0, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -3303,30 +3267,29 @@ static const yytype_int8 yyr2[] = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, - 1, 3, 1, 4, 7, 7, 7, 7, 4, 2, - 5, 4, 2, 2, 2, 2, 2, 2, 3, 3, + 1, 1, 3, 1, 1, 1, 1, 1, 3, 1, + 4, 7, 7, 7, 7, 4, 2, 5, 4, 2, + 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 5, 4, 4, 3, 3, - 3, 3, 1, 4, 7, 7, 7, 7, 4, 4, + 3, 3, 5, 4, 4, 3, 3, 3, 3, 1, + 4, 7, 7, 7, 7, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 2, 5, 4, 2, 5, 4, - 4, 2, 2, 2, 2, 2, 2, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 5, 4, 4, 3, - 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 9, 12, 4, 4, 6, - 4, 4, 6, 6, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 1, 4, 7, 7, 7, - 7, 4, 2, 5, 4, 2, 5, 4, 4, 2, + 4, 2, 5, 4, 2, 5, 4, 4, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 4, 4, 3, 3, 3, 3, + 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 9, 12, 4, 4, 6, 4, 4, 6, + 6, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 1, 4, 7, 7, 7, 7, 4, 2, + 5, 4, 2, 5, 4, 4, 2, 2, 2, 2, + 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 5, 4, 4, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 2, 4, 2, 3, 1, 2, - 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 4, 2, 3, 1, 2, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 2, 2, 0 + 1, 1, 1, 1, 1, 1, 1, 2, 2, 0 }; @@ -3911,90 +3874,90 @@ yyreduce: switch (yyn) { case 3: /* grammar: START_CONST_EXPR const_expr */ -#line 466 "dtool/src/cppparser/cppBison.yxx" +#line 468 "dtool/src/cppparser/cppBison.yxx" { current_expr = (yyvsp[0].u.expr); } -#line 3919 "built/tmp/cppBison.yxx.c" +#line 3882 "built/tmp/cppBison.yxx.c" break; case 4: /* grammar: START_TYPE full_type */ -#line 470 "dtool/src/cppparser/cppBison.yxx" +#line 472 "dtool/src/cppparser/cppBison.yxx" { current_type = (yyvsp[0].u.type); } -#line 3927 "built/tmp/cppBison.yxx.c" +#line 3890 "built/tmp/cppBison.yxx.c" break; case 6: /* cpp: cpp optional_attributes ';' */ -#line 478 "dtool/src/cppparser/cppBison.yxx" +#line 480 "dtool/src/cppparser/cppBison.yxx" { if (!(yyvsp[-1].attr_list).is_empty()) { current_scope->add_declaration(new CPPDeclaration((yylsp[-1]).file, (yyvsp[-1].attr_list)), global_scope, current_lexer, (yylsp[-1])); } } -#line 3937 "built/tmp/cppBison.yxx.c" +#line 3900 "built/tmp/cppBison.yxx.c" break; case 7: /* $@1: %empty */ -#line 484 "dtool/src/cppparser/cppBison.yxx" +#line 486 "dtool/src/cppparser/cppBison.yxx" { current_attributes = (yyvsp[0].attr_list); } -#line 3945 "built/tmp/cppBison.yxx.c" +#line 3908 "built/tmp/cppBison.yxx.c" break; case 8: /* cpp: cpp optional_attributes $@1 declaration */ -#line 488 "dtool/src/cppparser/cppBison.yxx" +#line 490 "dtool/src/cppparser/cppBison.yxx" { current_attributes = CPPAttributeList(); } -#line 3953 "built/tmp/cppBison.yxx.c" +#line 3916 "built/tmp/cppBison.yxx.c" break; case 11: /* constructor_init: name '(' optional_const_expr_comma ')' */ -#line 500 "dtool/src/cppparser/cppBison.yxx" +#line 502 "dtool/src/cppparser/cppBison.yxx" { delete (yyvsp[-1].u.expr); } -#line 3961 "built/tmp/cppBison.yxx.c" +#line 3924 "built/tmp/cppBison.yxx.c" break; case 12: /* constructor_init: name '(' optional_const_expr_comma ')' ELLIPSIS */ -#line 504 "dtool/src/cppparser/cppBison.yxx" +#line 506 "dtool/src/cppparser/cppBison.yxx" { delete (yyvsp[-2].u.expr); } -#line 3969 "built/tmp/cppBison.yxx.c" +#line 3932 "built/tmp/cppBison.yxx.c" break; case 13: /* constructor_init: name '{' optional_const_expr_comma '}' */ -#line 508 "dtool/src/cppparser/cppBison.yxx" +#line 510 "dtool/src/cppparser/cppBison.yxx" { delete (yyvsp[-1].u.expr); } -#line 3977 "built/tmp/cppBison.yxx.c" +#line 3940 "built/tmp/cppBison.yxx.c" break; case 14: /* $@2: %empty */ -#line 520 "dtool/src/cppparser/cppBison.yxx" +#line 522 "dtool/src/cppparser/cppBison.yxx" { push_storage_class((current_storage_class & ~CPPInstance::SC_c_binding) | ((yyvsp[-1].u.integer) & CPPInstance::SC_c_binding)); } -#line 3986 "built/tmp/cppBison.yxx.c" +#line 3949 "built/tmp/cppBison.yxx.c" break; case 15: /* extern_c: storage_class '{' $@2 cpp '}' */ -#line 525 "dtool/src/cppparser/cppBison.yxx" +#line 527 "dtool/src/cppparser/cppBison.yxx" { pop_storage_class(); } -#line 3994 "built/tmp/cppBison.yxx.c" +#line 3957 "built/tmp/cppBison.yxx.c" break; case 22: /* declaration: KW_BEGIN_PUBLISH */ -#line 538 "dtool/src/cppparser/cppBison.yxx" +#line 540 "dtool/src/cppparser/cppBison.yxx" { if (publish_nest_level != 0) { yyerror("Unclosed __begin_publish", publish_loc); @@ -4007,11 +3970,11 @@ yyreduce: publish_nest_level++; current_scope->set_current_vis(V_published); } -#line 4011 "built/tmp/cppBison.yxx.c" +#line 3974 "built/tmp/cppBison.yxx.c" break; case 23: /* declaration: KW_END_PUBLISH */ -#line 551 "dtool/src/cppparser/cppBison.yxx" +#line 553 "dtool/src/cppparser/cppBison.yxx" { if (publish_nest_level != 1) { yyerror("Unmatched __end_publish", (yylsp[0])); @@ -4020,19 +3983,19 @@ yyreduce: } publish_nest_level = 0; } -#line 4024 "built/tmp/cppBison.yxx.c" +#line 3987 "built/tmp/cppBison.yxx.c" break; case 24: /* declaration: KW_PUBLISHED ':' */ -#line 560 "dtool/src/cppparser/cppBison.yxx" +#line 562 "dtool/src/cppparser/cppBison.yxx" { current_scope->set_current_vis(V_published); } -#line 4032 "built/tmp/cppBison.yxx.c" +#line 3995 "built/tmp/cppBison.yxx.c" break; case 25: /* declaration: KW_PUBLIC ':' */ -#line 564 "dtool/src/cppparser/cppBison.yxx" +#line 566 "dtool/src/cppparser/cppBison.yxx" { if (publish_nest_level > 0) { current_scope->set_current_vis(V_published); @@ -4040,27 +4003,27 @@ yyreduce: current_scope->set_current_vis(V_public); } } -#line 4044 "built/tmp/cppBison.yxx.c" +#line 4007 "built/tmp/cppBison.yxx.c" break; case 26: /* declaration: KW_PROTECTED ':' */ -#line 572 "dtool/src/cppparser/cppBison.yxx" +#line 574 "dtool/src/cppparser/cppBison.yxx" { current_scope->set_current_vis(V_protected); } -#line 4052 "built/tmp/cppBison.yxx.c" +#line 4015 "built/tmp/cppBison.yxx.c" break; case 27: /* declaration: KW_PRIVATE ':' */ -#line 576 "dtool/src/cppparser/cppBison.yxx" +#line 578 "dtool/src/cppparser/cppBison.yxx" { current_scope->set_current_vis(V_private); } -#line 4060 "built/tmp/cppBison.yxx.c" +#line 4023 "built/tmp/cppBison.yxx.c" break; case 28: /* declaration: KW_MAKE_PROPERTY '(' name ',' IDENTIFIER maybe_comma_identifier ')' ';' */ -#line 580 "dtool/src/cppparser/cppBison.yxx" +#line 582 "dtool/src/cppparser/cppBison.yxx" { CPPDeclaration *getter = (yyvsp[-3].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); if (getter == nullptr || getter->get_subtype() != CPPDeclaration::ST_function_group) { @@ -4081,11 +4044,11 @@ yyreduce: current_scope->add_declaration(make_property, global_scope, current_lexer, (yylsp[-7])); } } -#line 4085 "built/tmp/cppBison.yxx.c" +#line 4048 "built/tmp/cppBison.yxx.c" break; case 29: /* declaration: KW_MAKE_PROPERTY '(' name ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ')' ';' */ -#line 601 "dtool/src/cppparser/cppBison.yxx" +#line 603 "dtool/src/cppparser/cppBison.yxx" { CPPDeclaration *getter = (yyvsp[-6].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); if (getter == nullptr || getter->get_subtype() != CPPDeclaration::ST_function_group) { @@ -4112,11 +4075,11 @@ yyreduce: current_scope->add_declaration(make_property, global_scope, current_lexer, (yylsp[-10])); } } -#line 4116 "built/tmp/cppBison.yxx.c" +#line 4079 "built/tmp/cppBison.yxx.c" break; case 30: /* declaration: KW_MAKE_SEQ_PROPERTY '(' name ',' IDENTIFIER ',' IDENTIFIER ')' ';' */ -#line 628 "dtool/src/cppparser/cppBison.yxx" +#line 630 "dtool/src/cppparser/cppBison.yxx" { CPPDeclaration *length_getter = (yyvsp[-4].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); if (length_getter == nullptr || length_getter->get_subtype() != CPPDeclaration::ST_function_group) { @@ -4137,11 +4100,11 @@ yyreduce: current_scope->add_declaration(make_property, global_scope, current_lexer, (yylsp[-8])); } } -#line 4141 "built/tmp/cppBison.yxx.c" +#line 4104 "built/tmp/cppBison.yxx.c" break; case 31: /* declaration: KW_MAKE_SEQ_PROPERTY '(' name ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ')' ';' */ -#line 649 "dtool/src/cppparser/cppBison.yxx" +#line 651 "dtool/src/cppparser/cppBison.yxx" { CPPDeclaration *length_getter = (yyvsp[-6].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); if (length_getter == nullptr || length_getter->get_subtype() != CPPDeclaration::ST_function_group) { @@ -4170,11 +4133,11 @@ yyreduce: current_scope->add_declaration(make_property, global_scope, current_lexer, (yylsp[-10])); } } -#line 4174 "built/tmp/cppBison.yxx.c" +#line 4137 "built/tmp/cppBison.yxx.c" break; case 32: /* declaration: KW_MAKE_SEQ_PROPERTY '(' name ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ')' ';' */ -#line 678 "dtool/src/cppparser/cppBison.yxx" +#line 680 "dtool/src/cppparser/cppBison.yxx" { CPPDeclaration *length_getter = (yyvsp[-8].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); if (length_getter == nullptr || length_getter->get_subtype() != CPPDeclaration::ST_function_group) { @@ -4210,11 +4173,11 @@ yyreduce: current_scope->add_declaration(make_property, global_scope, current_lexer, (yylsp[-12])); } } -#line 4214 "built/tmp/cppBison.yxx.c" +#line 4177 "built/tmp/cppBison.yxx.c" break; case 33: /* declaration: KW_MAKE_SEQ_PROPERTY '(' name ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ')' ';' */ -#line 714 "dtool/src/cppparser/cppBison.yxx" +#line 716 "dtool/src/cppparser/cppBison.yxx" { CPPDeclaration *length_getter = (yyvsp[-10].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); if (length_getter == nullptr || length_getter->get_subtype() != CPPDeclaration::ST_function_group) { @@ -4257,11 +4220,11 @@ yyreduce: current_scope->add_declaration(make_property, global_scope, current_lexer, (yylsp[-14])); } } -#line 4261 "built/tmp/cppBison.yxx.c" +#line 4224 "built/tmp/cppBison.yxx.c" break; case 34: /* declaration: KW_MAKE_MAP_PROPERTY '(' name ',' IDENTIFIER ')' ';' */ -#line 757 "dtool/src/cppparser/cppBison.yxx" +#line 759 "dtool/src/cppparser/cppBison.yxx" { CPPDeclaration *getter = (yyvsp[-2].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); if (getter == nullptr || getter->get_subtype() != CPPDeclaration::ST_function_group) { @@ -4273,11 +4236,11 @@ yyreduce: current_scope->add_declaration(make_property, global_scope, current_lexer, (yylsp[-6])); } } -#line 4277 "built/tmp/cppBison.yxx.c" +#line 4240 "built/tmp/cppBison.yxx.c" break; case 35: /* declaration: KW_MAKE_MAP_PROPERTY '(' name ',' IDENTIFIER ',' IDENTIFIER ')' ';' */ -#line 769 "dtool/src/cppparser/cppBison.yxx" +#line 771 "dtool/src/cppparser/cppBison.yxx" { CPPDeclaration *getter = (yyvsp[-2].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); if (getter == nullptr || getter->get_subtype() != CPPDeclaration::ST_function_group) { @@ -4298,11 +4261,11 @@ yyreduce: current_scope->add_declaration(make_property, global_scope, current_lexer, (yylsp[-8])); } } -#line 4302 "built/tmp/cppBison.yxx.c" +#line 4265 "built/tmp/cppBison.yxx.c" break; case 36: /* declaration: KW_MAKE_MAP_PROPERTY '(' name ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER maybe_comma_identifier ')' ';' */ -#line 790 "dtool/src/cppparser/cppBison.yxx" +#line 792 "dtool/src/cppparser/cppBison.yxx" { CPPDeclaration *getter = (yyvsp[-5].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); if (getter == nullptr || getter->get_subtype() != CPPDeclaration::ST_function_group) { @@ -4338,11 +4301,11 @@ yyreduce: current_scope->add_declaration(make_property, global_scope, current_lexer, (yylsp[-11])); } } -#line 4342 "built/tmp/cppBison.yxx.c" +#line 4305 "built/tmp/cppBison.yxx.c" break; case 37: /* declaration: KW_MAKE_MAP_KEYS_SEQ '(' name ',' IDENTIFIER ',' IDENTIFIER ')' ';' */ -#line 826 "dtool/src/cppparser/cppBison.yxx" +#line 828 "dtool/src/cppparser/cppBison.yxx" { CPPDeclaration *length_getter = (yyvsp[-4].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); if (length_getter == nullptr || length_getter->get_subtype() != CPPDeclaration::ST_function_group) { @@ -4376,11 +4339,11 @@ yyreduce: } } } -#line 4380 "built/tmp/cppBison.yxx.c" +#line 4343 "built/tmp/cppBison.yxx.c" break; case 38: /* declaration: KW_MAKE_PROPERTY2 '(' name ',' IDENTIFIER ',' IDENTIFIER ')' ';' */ -#line 860 "dtool/src/cppparser/cppBison.yxx" +#line 862 "dtool/src/cppparser/cppBison.yxx" { CPPDeclaration *getter = (yyvsp[-2].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); if (getter == nullptr || getter->get_subtype() != CPPDeclaration::ST_function_group) { @@ -4402,11 +4365,11 @@ yyreduce: current_scope->add_declaration(make_property, global_scope, current_lexer, (yylsp[-8])); } } -#line 4406 "built/tmp/cppBison.yxx.c" +#line 4369 "built/tmp/cppBison.yxx.c" break; case 39: /* declaration: KW_MAKE_PROPERTY2 '(' name ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ')' ';' */ -#line 882 "dtool/src/cppparser/cppBison.yxx" +#line 884 "dtool/src/cppparser/cppBison.yxx" { CPPDeclaration *getter = (yyvsp[-6].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); if (getter == nullptr || getter->get_subtype() != CPPDeclaration::ST_function_group) { @@ -4442,11 +4405,11 @@ yyreduce: current_scope->add_declaration(make_property, global_scope, current_lexer, (yylsp[-12])); } } -#line 4446 "built/tmp/cppBison.yxx.c" +#line 4409 "built/tmp/cppBison.yxx.c" break; case 40: /* declaration: KW_MAKE_SEQ '(' name ',' IDENTIFIER ',' IDENTIFIER ')' ';' */ -#line 918 "dtool/src/cppparser/cppBison.yxx" +#line 920 "dtool/src/cppparser/cppBison.yxx" { CPPDeclaration *length_getter = (yyvsp[-4].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); if (length_getter == nullptr || length_getter->get_subtype() != CPPDeclaration::ST_function_group) { @@ -4468,11 +4431,11 @@ yyreduce: current_scope->add_declaration(make_seq, global_scope, current_lexer, (yylsp[-8])); } } -#line 4472 "built/tmp/cppBison.yxx.c" +#line 4435 "built/tmp/cppBison.yxx.c" break; case 41: /* declaration: KW_STATIC_ASSERT '(' const_expr ',' string_literal ')' ';' */ -#line 940 "dtool/src/cppparser/cppBison.yxx" +#line 942 "dtool/src/cppparser/cppBison.yxx" { CPPExpression::Result result = (yyvsp[-4].u.expr)->evaluate(); if (result._type == CPPExpression::RT_error) { @@ -4483,11 +4446,11 @@ yyreduce: yywarning("static_assert failed: " + str.str(), (yylsp[-4])); } } -#line 4487 "built/tmp/cppBison.yxx.c" +#line 4450 "built/tmp/cppBison.yxx.c" break; case 42: /* declaration: KW_STATIC_ASSERT '(' const_expr ')' ';' */ -#line 951 "dtool/src/cppparser/cppBison.yxx" +#line 953 "dtool/src/cppparser/cppBison.yxx" { // This alternative version of static_assert was introduced in C++17. CPPExpression::Result result = (yyvsp[-2].u.expr)->evaluate(); @@ -4497,55 +4460,55 @@ yyreduce: yywarning("static_assert failed", (yylsp[-2])); } } -#line 4501 "built/tmp/cppBison.yxx.c" +#line 4464 "built/tmp/cppBison.yxx.c" break; case 43: /* $@3: %empty */ -#line 964 "dtool/src/cppparser/cppBison.yxx" +#line 966 "dtool/src/cppparser/cppBison.yxx" { CPPScope *new_scope = new CPPScope(current_scope, CPPNameComponent("temp"), V_public); push_scope(new_scope); } -#line 4511 "built/tmp/cppBison.yxx.c" +#line 4474 "built/tmp/cppBison.yxx.c" break; case 44: /* friend_declaration: KW_FRIEND $@3 declaration */ -#line 970 "dtool/src/cppparser/cppBison.yxx" +#line 972 "dtool/src/cppparser/cppBison.yxx" { delete current_scope; pop_scope(); } -#line 4520 "built/tmp/cppBison.yxx.c" +#line 4483 "built/tmp/cppBison.yxx.c" break; case 45: /* storage_class: empty */ -#line 979 "dtool/src/cppparser/cppBison.yxx" +#line 981 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.integer) = 0; } -#line 4528 "built/tmp/cppBison.yxx.c" +#line 4491 "built/tmp/cppBison.yxx.c" break; case 46: /* storage_class: KW_CONST storage_class */ -#line 983 "dtool/src/cppparser/cppBison.yxx" +#line 985 "dtool/src/cppparser/cppBison.yxx" { // This isn't really a storage class, but it helps with parsing. (yyval.u.integer) = (yyvsp[0].u.integer) | (int)CPPInstance::SC_const; } -#line 4537 "built/tmp/cppBison.yxx.c" +#line 4500 "built/tmp/cppBison.yxx.c" break; case 47: /* storage_class: KW_EXTERN storage_class */ -#line 988 "dtool/src/cppparser/cppBison.yxx" +#line 990 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.integer) = (yyvsp[0].u.integer) | (int)CPPInstance::SC_extern; } -#line 4545 "built/tmp/cppBison.yxx.c" +#line 4508 "built/tmp/cppBison.yxx.c" break; case 48: /* storage_class: KW_EXTERN SIMPLE_STRING storage_class */ -#line 992 "dtool/src/cppparser/cppBison.yxx" +#line 994 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.integer) = (yyvsp[0].u.integer) | (int)CPPInstance::SC_extern; if ((yyvsp[-1].str) == "C") { @@ -4556,43 +4519,43 @@ yyreduce: yywarning("Ignoring unknown linkage type \"" + (yyvsp[-1].str) + "\"", (yylsp[-1])); } } -#line 4560 "built/tmp/cppBison.yxx.c" +#line 4523 "built/tmp/cppBison.yxx.c" break; case 49: /* storage_class: KW_STATIC storage_class */ -#line 1003 "dtool/src/cppparser/cppBison.yxx" +#line 1005 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.integer) = (yyvsp[0].u.integer) | (int)CPPInstance::SC_static; } -#line 4568 "built/tmp/cppBison.yxx.c" +#line 4531 "built/tmp/cppBison.yxx.c" break; case 50: /* storage_class: KW_INLINE storage_class */ -#line 1007 "dtool/src/cppparser/cppBison.yxx" +#line 1009 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.integer) = (yyvsp[0].u.integer) | (int)CPPInstance::SC_inline; } -#line 4576 "built/tmp/cppBison.yxx.c" +#line 4539 "built/tmp/cppBison.yxx.c" break; case 51: /* storage_class: KW_VIRTUAL storage_class */ -#line 1011 "dtool/src/cppparser/cppBison.yxx" +#line 1013 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.integer) = (yyvsp[0].u.integer) | (int)CPPInstance::SC_virtual; } -#line 4584 "built/tmp/cppBison.yxx.c" +#line 4547 "built/tmp/cppBison.yxx.c" break; case 52: /* storage_class: KW_EXPLICIT storage_class */ -#line 1015 "dtool/src/cppparser/cppBison.yxx" +#line 1017 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.integer) = (yyvsp[0].u.integer) | (int)CPPInstance::SC_explicit; } -#line 4592 "built/tmp/cppBison.yxx.c" +#line 4555 "built/tmp/cppBison.yxx.c" break; case 53: /* storage_class: KW_EXPLICIT_LPAREN const_expr ')' storage_class */ -#line 1019 "dtool/src/cppparser/cppBison.yxx" +#line 1021 "dtool/src/cppparser/cppBison.yxx" { CPPExpression::Result result = (yyvsp[-2].u.expr)->evaluate(); if (result._type == CPPExpression::RT_error) { @@ -4601,100 +4564,100 @@ yyreduce: (yyval.u.integer) = (yyvsp[0].u.integer) | (int)CPPInstance::SC_explicit; } } -#line 4605 "built/tmp/cppBison.yxx.c" +#line 4568 "built/tmp/cppBison.yxx.c" break; case 54: /* storage_class: KW_REGISTER storage_class */ -#line 1028 "dtool/src/cppparser/cppBison.yxx" +#line 1030 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.integer) = (yyvsp[0].u.integer) | (int)CPPInstance::SC_register; } -#line 4613 "built/tmp/cppBison.yxx.c" +#line 4576 "built/tmp/cppBison.yxx.c" break; case 55: /* storage_class: KW_VOLATILE storage_class */ -#line 1032 "dtool/src/cppparser/cppBison.yxx" +#line 1034 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.integer) = (yyvsp[0].u.integer) | (int)CPPInstance::SC_volatile; } -#line 4621 "built/tmp/cppBison.yxx.c" +#line 4584 "built/tmp/cppBison.yxx.c" break; case 56: /* storage_class: KW_MUTABLE storage_class */ -#line 1036 "dtool/src/cppparser/cppBison.yxx" +#line 1038 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.integer) = (yyvsp[0].u.integer) | (int)CPPInstance::SC_mutable; } -#line 4629 "built/tmp/cppBison.yxx.c" +#line 4592 "built/tmp/cppBison.yxx.c" break; case 57: /* storage_class: KW_CONSTEVAL storage_class */ -#line 1040 "dtool/src/cppparser/cppBison.yxx" +#line 1042 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.integer) = (yyvsp[0].u.integer) | (int)CPPInstance::SC_consteval; } -#line 4637 "built/tmp/cppBison.yxx.c" +#line 4600 "built/tmp/cppBison.yxx.c" break; case 58: /* storage_class: KW_CONSTEXPR storage_class */ -#line 1044 "dtool/src/cppparser/cppBison.yxx" +#line 1046 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.integer) = (yyvsp[0].u.integer) | (int)CPPInstance::SC_constexpr; } -#line 4645 "built/tmp/cppBison.yxx.c" +#line 4608 "built/tmp/cppBison.yxx.c" break; case 59: /* storage_class: KW_CONSTINIT storage_class */ -#line 1048 "dtool/src/cppparser/cppBison.yxx" +#line 1050 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.integer) = (yyvsp[0].u.integer) | (int)CPPInstance::SC_constinit; } -#line 4653 "built/tmp/cppBison.yxx.c" +#line 4616 "built/tmp/cppBison.yxx.c" break; case 60: /* storage_class: KW_BLOCKING storage_class */ -#line 1052 "dtool/src/cppparser/cppBison.yxx" +#line 1054 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.integer) = (yyvsp[0].u.integer) | (int)CPPInstance::SC_blocking; } -#line 4661 "built/tmp/cppBison.yxx.c" +#line 4624 "built/tmp/cppBison.yxx.c" break; case 61: /* storage_class: KW_EXTENSION storage_class */ -#line 1056 "dtool/src/cppparser/cppBison.yxx" +#line 1058 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.integer) = (yyvsp[0].u.integer) | (int)CPPInstance::SC_extension; } -#line 4669 "built/tmp/cppBison.yxx.c" +#line 4632 "built/tmp/cppBison.yxx.c" break; case 62: /* storage_class: KW_THREAD_LOCAL storage_class */ -#line 1060 "dtool/src/cppparser/cppBison.yxx" +#line 1062 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.integer) = (yyvsp[0].u.integer) | (int)CPPInstance::SC_thread_local; } -#line 4677 "built/tmp/cppBison.yxx.c" +#line 4640 "built/tmp/cppBison.yxx.c" break; case 63: /* optional_attributes: empty */ -#line 1067 "dtool/src/cppparser/cppBison.yxx" +#line 1069 "dtool/src/cppparser/cppBison.yxx" { (yyval.attr_list) = CPPAttributeList(); } -#line 4685 "built/tmp/cppBison.yxx.c" +#line 4648 "built/tmp/cppBison.yxx.c" break; case 64: /* optional_attributes: ATTR_LEFT attribute_specifiers ATTR_RIGHT optional_attributes */ -#line 1071 "dtool/src/cppparser/cppBison.yxx" +#line 1073 "dtool/src/cppparser/cppBison.yxx" { (yyval.attr_list) = (yyvsp[-2].attr_list); (yyval.attr_list).add_attributes_from((yyvsp[0].attr_list)); } -#line 4694 "built/tmp/cppBison.yxx.c" +#line 4657 "built/tmp/cppBison.yxx.c" break; case 65: /* optional_attributes: ATTR_LEFT KW_USING name ':' attribute_specifiers ATTR_RIGHT optional_attributes */ -#line 1076 "dtool/src/cppparser/cppBison.yxx" +#line 1078 "dtool/src/cppparser/cppBison.yxx" { (yyval.attr_list) = (yyvsp[-2].attr_list); for (CPPAttributeList::Attribute &attr : (yyval.attr_list)._attributes) { @@ -4702,64 +4665,64 @@ yyreduce: } (yyval.attr_list).add_attributes_from((yyvsp[0].attr_list)); } -#line 4706 "built/tmp/cppBison.yxx.c" +#line 4669 "built/tmp/cppBison.yxx.c" break; case 66: /* optional_attributes: KW_ALIGNAS '(' const_expr ')' optional_attributes */ -#line 1084 "dtool/src/cppparser/cppBison.yxx" +#line 1086 "dtool/src/cppparser/cppBison.yxx" { (yyval.attr_list) = (yyvsp[0].attr_list); (yyval.attr_list).add_alignas((yyvsp[-2].u.expr)->as_expression()); } -#line 4715 "built/tmp/cppBison.yxx.c" +#line 4678 "built/tmp/cppBison.yxx.c" break; case 67: /* optional_attributes: KW_ALIGNAS '(' type_decl ')' optional_attributes */ -#line 1089 "dtool/src/cppparser/cppBison.yxx" +#line 1091 "dtool/src/cppparser/cppBison.yxx" { (yyval.attr_list) = (yyvsp[0].attr_list); (yyval.attr_list).add_alignas((yyvsp[-2].u.decl)->as_type()); } -#line 4724 "built/tmp/cppBison.yxx.c" +#line 4687 "built/tmp/cppBison.yxx.c" break; case 68: /* attribute_specifiers: attribute_specifier */ -#line 1097 "dtool/src/cppparser/cppBison.yxx" +#line 1099 "dtool/src/cppparser/cppBison.yxx" { (yyval.attr_list) = (yyvsp[0].attr_list); } -#line 4732 "built/tmp/cppBison.yxx.c" +#line 4695 "built/tmp/cppBison.yxx.c" break; case 69: /* attribute_specifiers: attribute_specifier ',' attribute_specifiers */ -#line 1101 "dtool/src/cppparser/cppBison.yxx" +#line 1103 "dtool/src/cppparser/cppBison.yxx" { (yyval.attr_list) = (yyvsp[-2].attr_list); (yyval.attr_list).add_attributes_from((yyvsp[0].attr_list)); } -#line 4741 "built/tmp/cppBison.yxx.c" +#line 4704 "built/tmp/cppBison.yxx.c" break; case 70: /* attribute_specifier: name */ -#line 1109 "dtool/src/cppparser/cppBison.yxx" +#line 1111 "dtool/src/cppparser/cppBison.yxx" { (yyval.attr_list) = CPPAttributeList(); (yyval.attr_list).add_attribute((yyvsp[0].u.identifier)); } -#line 4750 "built/tmp/cppBison.yxx.c" +#line 4713 "built/tmp/cppBison.yxx.c" break; case 71: /* attribute_specifier: name '(' formal_parameter_list ')' */ -#line 1114 "dtool/src/cppparser/cppBison.yxx" +#line 1116 "dtool/src/cppparser/cppBison.yxx" { (yyval.attr_list) = CPPAttributeList(); (yyval.attr_list).add_attribute((yyvsp[-3].u.identifier)); } -#line 4759 "built/tmp/cppBison.yxx.c" +#line 4722 "built/tmp/cppBison.yxx.c" break; case 72: /* $@4: %empty */ -#line 1122 "dtool/src/cppparser/cppBison.yxx" +#line 1124 "dtool/src/cppparser/cppBison.yxx" { // We don't need to push/pop type, because we can't nest // type_like_declaration. @@ -4770,19 +4733,19 @@ yyreduce: } push_storage_class((yyvsp[-1].u.integer)); } -#line 4774 "built/tmp/cppBison.yxx.c" +#line 4737 "built/tmp/cppBison.yxx.c" break; case 73: /* type_like_declaration: storage_class var_type_decl $@4 multiple_instance_identifiers */ -#line 1133 "dtool/src/cppparser/cppBison.yxx" +#line 1135 "dtool/src/cppparser/cppBison.yxx" { pop_storage_class(); } -#line 4782 "built/tmp/cppBison.yxx.c" +#line 4745 "built/tmp/cppBison.yxx.c" break; case 74: /* type_like_declaration: storage_class type_decl ';' */ -#line 1138 "dtool/src/cppparser/cppBison.yxx" +#line 1140 "dtool/src/cppparser/cppBison.yxx" { // We don't really care about the storage class here. In fact, it's // not actually legal to define a class or struct using a particular @@ -4791,11 +4754,11 @@ yyreduce: current_scope->add_declaration((yyvsp[-1].u.decl), global_scope, current_lexer, (yylsp[-1])); } -#line 4795 "built/tmp/cppBison.yxx.c" +#line 4758 "built/tmp/cppBison.yxx.c" break; case 75: /* $@5: %empty */ -#line 1147 "dtool/src/cppparser/cppBison.yxx" +#line 1149 "dtool/src/cppparser/cppBison.yxx" { if ((yyvsp[0].u.instance) != nullptr) { // Push the scope so that the initializers can make use of things defined @@ -4804,11 +4767,11 @@ yyreduce: (yyvsp[0].u.instance)->_storage_class |= (current_storage_class | (yyvsp[-1].u.integer)); } } -#line 4808 "built/tmp/cppBison.yxx.c" +#line 4771 "built/tmp/cppBison.yxx.c" break; case 76: /* type_like_declaration: storage_class constructor_prototype $@5 maybe_initialize_or_constructor_body */ -#line 1156 "dtool/src/cppparser/cppBison.yxx" +#line 1158 "dtool/src/cppparser/cppBison.yxx" { if ((yyvsp[-2].u.instance) != nullptr) { pop_scope(); @@ -4816,11 +4779,11 @@ yyreduce: (yyvsp[-2].u.instance)->set_initializer((yyvsp[0].u.expr)); } } -#line 4820 "built/tmp/cppBison.yxx.c" +#line 4783 "built/tmp/cppBison.yxx.c" break; case 77: /* type_like_declaration: storage_class function_prototype maybe_initialize_or_function_body */ -#line 1164 "dtool/src/cppparser/cppBison.yxx" +#line 1166 "dtool/src/cppparser/cppBison.yxx" { if ((yyvsp[-1].u.instance) != nullptr) { (yyvsp[-1].u.instance)->_storage_class |= (current_storage_class | (yyvsp[-2].u.integer)); @@ -4828,11 +4791,11 @@ yyreduce: (yyvsp[-1].u.instance)->set_initializer((yyvsp[0].u.expr)); } } -#line 4832 "built/tmp/cppBison.yxx.c" +#line 4795 "built/tmp/cppBison.yxx.c" break; case 79: /* multiple_instance_identifiers: instance_identifier_and_maybe_trailing_return_type maybe_initialize_or_function_body */ -#line 1180 "dtool/src/cppparser/cppBison.yxx" +#line 1182 "dtool/src/cppparser/cppBison.yxx" { if (current_storage_class & CPPInstance::SC_const) { (yyvsp[-1].u.inst_ident)->add_modifier(IIT_const); @@ -4844,11 +4807,11 @@ yyreduce: inst->set_initializer((yyvsp[0].u.expr)); current_scope->add_declaration(inst, global_scope, current_lexer, (yylsp[-1])); } -#line 4848 "built/tmp/cppBison.yxx.c" +#line 4811 "built/tmp/cppBison.yxx.c" break; case 80: /* multiple_instance_identifiers: instance_identifier_and_maybe_trailing_return_type maybe_initialize ',' multiple_instance_identifiers */ -#line 1192 "dtool/src/cppparser/cppBison.yxx" +#line 1194 "dtool/src/cppparser/cppBison.yxx" { if (current_storage_class & CPPInstance::SC_const) { (yyvsp[-3].u.inst_ident)->add_modifier(IIT_const); @@ -4860,11 +4823,11 @@ yyreduce: inst->set_initializer((yyvsp[-2].u.expr)); current_scope->add_declaration(inst, global_scope, current_lexer, (yylsp[-3])); } -#line 4864 "built/tmp/cppBison.yxx.c" +#line 4827 "built/tmp/cppBison.yxx.c" break; case 81: /* $@6: %empty */ -#line 1208 "dtool/src/cppparser/cppBison.yxx" +#line 1210 "dtool/src/cppparser/cppBison.yxx" { // We don't need to push/pop type, because we can't nest // multiple_var_declarations. @@ -4875,19 +4838,19 @@ yyreduce: } push_storage_class((yyvsp[-1].u.integer)); } -#line 4879 "built/tmp/cppBison.yxx.c" +#line 4842 "built/tmp/cppBison.yxx.c" break; case 82: /* typedef_declaration: storage_class var_type_decl $@6 typedef_instance_identifiers */ -#line 1219 "dtool/src/cppparser/cppBison.yxx" +#line 1221 "dtool/src/cppparser/cppBison.yxx" { pop_storage_class(); } -#line 4887 "built/tmp/cppBison.yxx.c" +#line 4850 "built/tmp/cppBison.yxx.c" break; case 83: /* typedef_declaration: storage_class function_prototype maybe_initialize_or_function_body */ -#line 1223 "dtool/src/cppparser/cppBison.yxx" +#line 1225 "dtool/src/cppparser/cppBison.yxx" { if ((yyvsp[-1].u.instance) != nullptr) { CPPInstance *inst = (yyvsp[-1].u.instance)->as_instance(); @@ -4899,11 +4862,11 @@ yyreduce: } } } -#line 4903 "built/tmp/cppBison.yxx.c" +#line 4866 "built/tmp/cppBison.yxx.c" break; case 84: /* typedef_instance_identifiers: instance_identifier_and_maybe_trailing_return_type maybe_initialize_or_function_body */ -#line 1238 "dtool/src/cppparser/cppBison.yxx" +#line 1240 "dtool/src/cppparser/cppBison.yxx" { if (current_storage_class & CPPInstance::SC_const) { (yyvsp[-1].u.inst_ident)->add_modifier(IIT_const); @@ -4913,11 +4876,11 @@ yyreduce: CPPTypedefType *typedef_type = new CPPTypedefType(target_type, (yyvsp[-1].u.inst_ident), current_scope, (yylsp[-1]).file); current_scope->add_declaration(CPPType::new_type(typedef_type), global_scope, current_lexer, (yylsp[-1])); } -#line 4917 "built/tmp/cppBison.yxx.c" +#line 4880 "built/tmp/cppBison.yxx.c" break; case 85: /* typedef_instance_identifiers: instance_identifier_and_maybe_trailing_return_type maybe_initialize ',' typedef_instance_identifiers */ -#line 1248 "dtool/src/cppparser/cppBison.yxx" +#line 1250 "dtool/src/cppparser/cppBison.yxx" { if (current_storage_class & CPPInstance::SC_const) { (yyvsp[-3].u.inst_ident)->add_modifier(IIT_const); @@ -4927,11 +4890,11 @@ yyreduce: CPPTypedefType *typedef_type = new CPPTypedefType(target_type, (yyvsp[-3].u.inst_ident), current_scope, (yylsp[-3]).file); current_scope->add_declaration(CPPType::new_type(typedef_type), global_scope, current_lexer, (yylsp[-3])); } -#line 4931 "built/tmp/cppBison.yxx.c" +#line 4894 "built/tmp/cppBison.yxx.c" break; case 86: /* $@7: %empty */ -#line 1263 "dtool/src/cppparser/cppBison.yxx" +#line 1265 "dtool/src/cppparser/cppBison.yxx" { // Create a scope for this function. CPPScope *scope = new CPPScope((yyvsp[-1].u.identifier)->get_scope(current_scope, global_scope), @@ -4944,11 +4907,11 @@ yyreduce: push_scope(scope); } -#line 4948 "built/tmp/cppBison.yxx.c" +#line 4911 "built/tmp/cppBison.yxx.c" break; case 87: /* constructor_prototype: IDENTIFIER '(' $@7 function_parameter_list ')' function_post optional_attributes */ -#line 1276 "dtool/src/cppparser/cppBison.yxx" +#line 1278 "dtool/src/cppparser/cppBison.yxx" { CPPScope *scope = (yyvsp[-6].u.identifier)->get_scope(current_scope, global_scope); CPPType *type; @@ -4975,11 +4938,11 @@ yyreduce: (yyval.u.instance) = new CPPInstance(type, ii, 0, (yylsp[-6]).file); } -#line 4979 "built/tmp/cppBison.yxx.c" +#line 4942 "built/tmp/cppBison.yxx.c" break; case 88: /* $@8: %empty */ -#line 1305 "dtool/src/cppparser/cppBison.yxx" +#line 1307 "dtool/src/cppparser/cppBison.yxx" { // Create a scope for this function. CPPScope *scope = new CPPScope((yyvsp[-2].u.identifier)->get_scope(current_scope, global_scope), @@ -4992,11 +4955,11 @@ yyreduce: push_scope(scope); } -#line 4996 "built/tmp/cppBison.yxx.c" +#line 4959 "built/tmp/cppBison.yxx.c" break; case 89: /* constructor_prototype: TYPENAME_IDENTIFIER '(' IDENTIFIER ')' '(' $@8 function_parameter_list ')' function_post optional_attributes */ -#line 1318 "dtool/src/cppparser/cppBison.yxx" +#line 1320 "dtool/src/cppparser/cppBison.yxx" { pop_scope(); CPPType *type = (yyvsp[-9].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); @@ -5011,11 +4974,11 @@ yyreduce: (yyval.u.instance) = new CPPInstance(type, ii, 0, (yylsp[-9]).file); } -#line 5015 "built/tmp/cppBison.yxx.c" +#line 4978 "built/tmp/cppBison.yxx.c" break; case 90: /* $@9: %empty */ -#line 1333 "dtool/src/cppparser/cppBison.yxx" +#line 1335 "dtool/src/cppparser/cppBison.yxx" { // Create a scope for this function. CPPScope *scope = new CPPScope((yyvsp[-1].u.identifier)->get_scope(current_scope, global_scope), @@ -5028,11 +4991,11 @@ yyreduce: push_scope(scope); } -#line 5032 "built/tmp/cppBison.yxx.c" +#line 4995 "built/tmp/cppBison.yxx.c" break; case 91: /* constructor_prototype: TYPENAME_IDENTIFIER '(' $@9 function_parameter_list ')' function_post optional_attributes */ -#line 1346 "dtool/src/cppparser/cppBison.yxx" +#line 1348 "dtool/src/cppparser/cppBison.yxx" { pop_scope(); CPPType *type; @@ -5051,19 +5014,19 @@ yyreduce: (yyval.u.instance) = new CPPInstance(type, ii, 0, (yylsp[-6]).file); } -#line 5055 "built/tmp/cppBison.yxx.c" +#line 5018 "built/tmp/cppBison.yxx.c" break; case 92: /* $@10: %empty */ -#line 1370 "dtool/src/cppparser/cppBison.yxx" +#line 1372 "dtool/src/cppparser/cppBison.yxx" { push_scope((yyvsp[-1].u.identifier)->get_scope(current_scope, global_scope)); } -#line 5063 "built/tmp/cppBison.yxx.c" +#line 5026 "built/tmp/cppBison.yxx.c" break; case 93: /* function_prototype: '~' name '(' $@10 function_parameter_list ')' function_post optional_attributes */ -#line 1374 "dtool/src/cppparser/cppBison.yxx" +#line 1376 "dtool/src/cppparser/cppBison.yxx" { pop_scope(); if ((yyvsp[-6].u.identifier)->is_scoped()) { @@ -5083,19 +5046,19 @@ yyreduce: (yyval.u.instance) = new CPPInstance(type, ii, 0, (yylsp[-6]).file); } } -#line 5087 "built/tmp/cppBison.yxx.c" +#line 5050 "built/tmp/cppBison.yxx.c" break; case 94: /* $@11: %empty */ -#line 1401 "dtool/src/cppparser/cppBison.yxx" +#line 1403 "dtool/src/cppparser/cppBison.yxx" { push_scope((yyvsp[-2].u.inst_ident)->get_scope(current_scope, global_scope)); } -#line 5095 "built/tmp/cppBison.yxx.c" +#line 5058 "built/tmp/cppBison.yxx.c" break; case 95: /* function_prototype: TYPENAME_IDENTIFIER '(' '*' instance_identifier ')' '(' $@11 function_parameter_list ')' function_post optional_attributes maybe_trailing_return_type */ -#line 1405 "dtool/src/cppparser/cppBison.yxx" +#line 1407 "dtool/src/cppparser/cppBison.yxx" { pop_scope(); CPPType *type = (yyvsp[-11].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); @@ -5110,19 +5073,19 @@ yyreduce: ii->add_attributes(current_attributes); (yyval.u.instance) = new CPPInstance(type, ii, 0, (yylsp[-11]).file); } -#line 5114 "built/tmp/cppBison.yxx.c" +#line 5077 "built/tmp/cppBison.yxx.c" break; case 96: /* $@12: %empty */ -#line 1420 "dtool/src/cppparser/cppBison.yxx" +#line 1422 "dtool/src/cppparser/cppBison.yxx" { push_scope((yyvsp[-2].u.inst_ident)->get_scope(current_scope, global_scope)); } -#line 5122 "built/tmp/cppBison.yxx.c" +#line 5085 "built/tmp/cppBison.yxx.c" break; case 97: /* function_prototype: TYPENAME_IDENTIFIER '(' SCOPING '*' instance_identifier ')' '(' $@12 function_parameter_list ')' function_post optional_attributes maybe_trailing_return_type */ -#line 1424 "dtool/src/cppparser/cppBison.yxx" +#line 1426 "dtool/src/cppparser/cppBison.yxx" { pop_scope(); CPPType *type = (yyvsp[-12].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); @@ -5137,21 +5100,21 @@ yyreduce: ii->add_attributes(current_attributes); (yyval.u.instance) = new CPPInstance(type, ii, 0, (yylsp[-12]).file); } -#line 5141 "built/tmp/cppBison.yxx.c" +#line 5104 "built/tmp/cppBison.yxx.c" break; case 98: /* $@13: %empty */ -#line 1441 "dtool/src/cppparser/cppBison.yxx" +#line 1443 "dtool/src/cppparser/cppBison.yxx" { if ((yyvsp[-3].u.identifier) != nullptr) { push_scope((yyvsp[-3].u.identifier)->get_scope(current_scope, global_scope)); } } -#line 5151 "built/tmp/cppBison.yxx.c" +#line 5114 "built/tmp/cppBison.yxx.c" break; case 99: /* function_prototype: KW_OPERATOR type not_paren_formal_parameter_identifier '(' $@13 function_parameter_list ')' function_post */ -#line 1447 "dtool/src/cppparser/cppBison.yxx" +#line 1449 "dtool/src/cppparser/cppBison.yxx" { if ((yyvsp[-7].u.identifier) != nullptr) { pop_scope(); @@ -5177,21 +5140,21 @@ yyreduce: (new CPPInstance((yyvsp[-6].u.type), (yyvsp[-5].u.inst_ident), 0, (yylsp[-5]).file), ident, (yyvsp[-2].u.param_list), (yyvsp[0].u.integer)); (yyval.u.instance)->_attributes.add_attributes_from(current_attributes); } -#line 5181 "built/tmp/cppBison.yxx.c" +#line 5144 "built/tmp/cppBison.yxx.c" break; case 100: /* $@14: %empty */ -#line 1473 "dtool/src/cppparser/cppBison.yxx" +#line 1475 "dtool/src/cppparser/cppBison.yxx" { if ((yyvsp[-4].u.identifier) != nullptr) { push_scope((yyvsp[-4].u.identifier)->get_scope(current_scope, global_scope)); } } -#line 5191 "built/tmp/cppBison.yxx.c" +#line 5154 "built/tmp/cppBison.yxx.c" break; case 101: /* function_prototype: KW_OPERATOR KW_CONST type not_paren_formal_parameter_identifier '(' $@14 function_parameter_list ')' function_post */ -#line 1479 "dtool/src/cppparser/cppBison.yxx" +#line 1481 "dtool/src/cppparser/cppBison.yxx" { if ((yyvsp[-8].u.identifier) != nullptr) { pop_scope(); @@ -5208,11 +5171,11 @@ yyreduce: (yyval.u.instance) = CPPInstance::make_typecast_function (new CPPInstance((yyvsp[-6].u.type), (yyvsp[-5].u.inst_ident), 0, (yylsp[-5]).file), ident, (yyvsp[-2].u.param_list), (yyvsp[0].u.integer)); } -#line 5212 "built/tmp/cppBison.yxx.c" +#line 5175 "built/tmp/cppBison.yxx.c" break; case 102: /* function_prototype: IDENTIFIER */ -#line 1500 "dtool/src/cppparser/cppBison.yxx" +#line 1502 "dtool/src/cppparser/cppBison.yxx" { CPPDeclaration *decl = (yyvsp[0].u.identifier)->find_symbol(current_scope, global_scope, current_lexer); @@ -5222,43 +5185,43 @@ yyreduce: (yyval.u.instance) = nullptr; } } -#line 5226 "built/tmp/cppBison.yxx.c" +#line 5189 "built/tmp/cppBison.yxx.c" break; case 103: /* function_post: empty */ -#line 1513 "dtool/src/cppparser/cppBison.yxx" +#line 1515 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.integer) = 0; } -#line 5234 "built/tmp/cppBison.yxx.c" +#line 5197 "built/tmp/cppBison.yxx.c" break; case 104: /* function_post: function_post KW_CONST */ -#line 1517 "dtool/src/cppparser/cppBison.yxx" +#line 1519 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.integer) = (yyvsp[-1].u.integer) | (int)CPPFunctionType::F_const_method; } -#line 5242 "built/tmp/cppBison.yxx.c" +#line 5205 "built/tmp/cppBison.yxx.c" break; case 105: /* function_post: function_post KW_VOLATILE */ -#line 1521 "dtool/src/cppparser/cppBison.yxx" +#line 1523 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.integer) = (yyvsp[-1].u.integer) | (int)CPPFunctionType::F_volatile_method; } -#line 5250 "built/tmp/cppBison.yxx.c" +#line 5213 "built/tmp/cppBison.yxx.c" break; case 106: /* function_post: function_post KW_NOEXCEPT */ -#line 1525 "dtool/src/cppparser/cppBison.yxx" +#line 1527 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.integer) = (yyvsp[-1].u.integer) | (int)CPPFunctionType::F_noexcept; } -#line 5258 "built/tmp/cppBison.yxx.c" +#line 5221 "built/tmp/cppBison.yxx.c" break; case 107: /* function_post: function_post KW_NOEXCEPT_LPAREN const_expr ')' */ -#line 1529 "dtool/src/cppparser/cppBison.yxx" +#line 1531 "dtool/src/cppparser/cppBison.yxx" { CPPExpression::Result result = (yyvsp[-1].u.expr)->evaluate(); if (result._type == CPPExpression::RT_error) { @@ -5267,542 +5230,563 @@ yyreduce: (yyval.u.integer) = (yyvsp[-3].u.integer) | (int)CPPFunctionType::F_noexcept; } } -#line 5271 "built/tmp/cppBison.yxx.c" +#line 5234 "built/tmp/cppBison.yxx.c" break; case 108: /* function_post: function_post KW_FINAL */ -#line 1538 "dtool/src/cppparser/cppBison.yxx" +#line 1540 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.integer) = (yyvsp[-1].u.integer) | (int)CPPFunctionType::F_final; } -#line 5279 "built/tmp/cppBison.yxx.c" +#line 5242 "built/tmp/cppBison.yxx.c" break; case 109: /* function_post: function_post KW_OVERRIDE */ -#line 1542 "dtool/src/cppparser/cppBison.yxx" +#line 1544 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.integer) = (yyvsp[-1].u.integer) | (int)CPPFunctionType::F_override; } -#line 5287 "built/tmp/cppBison.yxx.c" +#line 5250 "built/tmp/cppBison.yxx.c" break; case 110: /* function_post: function_post '&' */ -#line 1546 "dtool/src/cppparser/cppBison.yxx" +#line 1548 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.integer) = (yyvsp[-1].u.integer) | (int)CPPFunctionType::F_lvalue_method; } -#line 5295 "built/tmp/cppBison.yxx.c" +#line 5258 "built/tmp/cppBison.yxx.c" break; case 111: /* function_post: function_post ANDAND */ -#line 1550 "dtool/src/cppparser/cppBison.yxx" +#line 1552 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.integer) = (yyvsp[-1].u.integer) | (int)CPPFunctionType::F_rvalue_method; } -#line 5303 "built/tmp/cppBison.yxx.c" +#line 5266 "built/tmp/cppBison.yxx.c" break; case 112: /* function_post: function_post KW_MUTABLE */ -#line 1554 "dtool/src/cppparser/cppBison.yxx" +#line 1556 "dtool/src/cppparser/cppBison.yxx" { // Used for lambdas, currently ignored. (yyval.u.integer) = (yyvsp[-1].u.integer); } -#line 5312 "built/tmp/cppBison.yxx.c" +#line 5275 "built/tmp/cppBison.yxx.c" break; case 113: /* function_post: function_post KW_CONSTEXPR */ -#line 1559 "dtool/src/cppparser/cppBison.yxx" +#line 1561 "dtool/src/cppparser/cppBison.yxx" { // Used for lambdas in C++17, currently ignored. (yyval.u.integer) = (yyvsp[-1].u.integer); } -#line 5321 "built/tmp/cppBison.yxx.c" +#line 5284 "built/tmp/cppBison.yxx.c" break; case 114: /* function_post: function_post KW_THROW '(' ')' */ -#line 1564 "dtool/src/cppparser/cppBison.yxx" +#line 1566 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.integer) = (yyvsp[-3].u.integer); } -#line 5329 "built/tmp/cppBison.yxx.c" +#line 5292 "built/tmp/cppBison.yxx.c" break; case 115: /* function_post: function_post KW_THROW '(' name ')' */ -#line 1568 "dtool/src/cppparser/cppBison.yxx" +#line 1570 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.integer) = (yyvsp[-4].u.integer); } -#line 5337 "built/tmp/cppBison.yxx.c" +#line 5300 "built/tmp/cppBison.yxx.c" break; case 116: /* function_post: function_post KW_THROW '(' name ELLIPSIS ')' */ -#line 1572 "dtool/src/cppparser/cppBison.yxx" +#line 1574 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.integer) = (yyvsp[-5].u.integer); } -#line 5345 "built/tmp/cppBison.yxx.c" +#line 5308 "built/tmp/cppBison.yxx.c" break; case 117: /* function_operator: '!' */ -#line 1579 "dtool/src/cppparser/cppBison.yxx" +#line 1581 "dtool/src/cppparser/cppBison.yxx" { (yyval.str) = "!"; } -#line 5353 "built/tmp/cppBison.yxx.c" +#line 5316 "built/tmp/cppBison.yxx.c" break; case 118: /* function_operator: '~' */ -#line 1583 "dtool/src/cppparser/cppBison.yxx" +#line 1585 "dtool/src/cppparser/cppBison.yxx" { (yyval.str) = "~"; } -#line 5361 "built/tmp/cppBison.yxx.c" +#line 5324 "built/tmp/cppBison.yxx.c" break; case 119: /* function_operator: '*' */ -#line 1587 "dtool/src/cppparser/cppBison.yxx" +#line 1589 "dtool/src/cppparser/cppBison.yxx" { (yyval.str) = "*"; } -#line 5369 "built/tmp/cppBison.yxx.c" +#line 5332 "built/tmp/cppBison.yxx.c" break; case 120: /* function_operator: '/' */ -#line 1591 "dtool/src/cppparser/cppBison.yxx" +#line 1593 "dtool/src/cppparser/cppBison.yxx" { (yyval.str) = "/"; } -#line 5377 "built/tmp/cppBison.yxx.c" +#line 5340 "built/tmp/cppBison.yxx.c" break; case 121: /* function_operator: '%' */ -#line 1595 "dtool/src/cppparser/cppBison.yxx" +#line 1597 "dtool/src/cppparser/cppBison.yxx" { (yyval.str) = "%"; } -#line 5385 "built/tmp/cppBison.yxx.c" +#line 5348 "built/tmp/cppBison.yxx.c" break; case 122: /* function_operator: '+' */ -#line 1599 "dtool/src/cppparser/cppBison.yxx" +#line 1601 "dtool/src/cppparser/cppBison.yxx" { (yyval.str) = "+"; } -#line 5393 "built/tmp/cppBison.yxx.c" +#line 5356 "built/tmp/cppBison.yxx.c" break; case 123: /* function_operator: '-' */ -#line 1603 "dtool/src/cppparser/cppBison.yxx" +#line 1605 "dtool/src/cppparser/cppBison.yxx" { (yyval.str) = "-"; } -#line 5401 "built/tmp/cppBison.yxx.c" +#line 5364 "built/tmp/cppBison.yxx.c" break; case 124: /* function_operator: '|' */ -#line 1607 "dtool/src/cppparser/cppBison.yxx" +#line 1609 "dtool/src/cppparser/cppBison.yxx" { (yyval.str) = "|"; } -#line 5409 "built/tmp/cppBison.yxx.c" +#line 5372 "built/tmp/cppBison.yxx.c" break; case 125: /* function_operator: '&' */ -#line 1611 "dtool/src/cppparser/cppBison.yxx" +#line 1613 "dtool/src/cppparser/cppBison.yxx" { (yyval.str) = "&"; } -#line 5417 "built/tmp/cppBison.yxx.c" +#line 5380 "built/tmp/cppBison.yxx.c" break; case 126: /* function_operator: '^' */ -#line 1615 "dtool/src/cppparser/cppBison.yxx" +#line 1617 "dtool/src/cppparser/cppBison.yxx" { (yyval.str) = "^"; } -#line 5425 "built/tmp/cppBison.yxx.c" +#line 5388 "built/tmp/cppBison.yxx.c" break; case 127: /* function_operator: OROR */ -#line 1619 "dtool/src/cppparser/cppBison.yxx" +#line 1621 "dtool/src/cppparser/cppBison.yxx" { (yyval.str) = "||"; } -#line 5433 "built/tmp/cppBison.yxx.c" +#line 5396 "built/tmp/cppBison.yxx.c" break; case 128: /* function_operator: ANDAND */ -#line 1623 "dtool/src/cppparser/cppBison.yxx" +#line 1625 "dtool/src/cppparser/cppBison.yxx" { (yyval.str) = "&&"; } -#line 5441 "built/tmp/cppBison.yxx.c" +#line 5404 "built/tmp/cppBison.yxx.c" break; case 129: /* function_operator: EQCOMPARE */ -#line 1627 "dtool/src/cppparser/cppBison.yxx" +#line 1629 "dtool/src/cppparser/cppBison.yxx" { (yyval.str) = "=="; } -#line 5449 "built/tmp/cppBison.yxx.c" +#line 5412 "built/tmp/cppBison.yxx.c" break; case 130: /* function_operator: NECOMPARE */ -#line 1631 "dtool/src/cppparser/cppBison.yxx" +#line 1633 "dtool/src/cppparser/cppBison.yxx" { (yyval.str) = "!="; } -#line 5457 "built/tmp/cppBison.yxx.c" +#line 5420 "built/tmp/cppBison.yxx.c" break; case 131: /* function_operator: LECOMPARE */ -#line 1635 "dtool/src/cppparser/cppBison.yxx" +#line 1637 "dtool/src/cppparser/cppBison.yxx" { (yyval.str) = "<="; } -#line 5465 "built/tmp/cppBison.yxx.c" +#line 5428 "built/tmp/cppBison.yxx.c" break; case 132: /* function_operator: GECOMPARE */ -#line 1639 "dtool/src/cppparser/cppBison.yxx" +#line 1641 "dtool/src/cppparser/cppBison.yxx" { (yyval.str) = ">="; } -#line 5473 "built/tmp/cppBison.yxx.c" +#line 5436 "built/tmp/cppBison.yxx.c" break; case 133: /* function_operator: '<' */ -#line 1643 "dtool/src/cppparser/cppBison.yxx" +#line 1645 "dtool/src/cppparser/cppBison.yxx" { (yyval.str) = "<"; } -#line 5481 "built/tmp/cppBison.yxx.c" +#line 5444 "built/tmp/cppBison.yxx.c" break; case 134: /* function_operator: '>' */ -#line 1647 "dtool/src/cppparser/cppBison.yxx" +#line 1649 "dtool/src/cppparser/cppBison.yxx" { (yyval.str) = ">"; } -#line 5489 "built/tmp/cppBison.yxx.c" +#line 5452 "built/tmp/cppBison.yxx.c" break; case 135: /* function_operator: SPACESHIP */ -#line 1651 "dtool/src/cppparser/cppBison.yxx" +#line 1653 "dtool/src/cppparser/cppBison.yxx" { (yyval.str) = "<=>"; } -#line 5497 "built/tmp/cppBison.yxx.c" +#line 5460 "built/tmp/cppBison.yxx.c" break; case 136: /* function_operator: LSHIFT */ -#line 1655 "dtool/src/cppparser/cppBison.yxx" +#line 1657 "dtool/src/cppparser/cppBison.yxx" { (yyval.str) = "<<"; } -#line 5505 "built/tmp/cppBison.yxx.c" +#line 5468 "built/tmp/cppBison.yxx.c" break; case 137: /* function_operator: RSHIFT */ -#line 1659 "dtool/src/cppparser/cppBison.yxx" +#line 1661 "dtool/src/cppparser/cppBison.yxx" { (yyval.str) = ">>"; } -#line 5513 "built/tmp/cppBison.yxx.c" +#line 5476 "built/tmp/cppBison.yxx.c" break; case 138: /* function_operator: '=' */ -#line 1663 "dtool/src/cppparser/cppBison.yxx" +#line 1665 "dtool/src/cppparser/cppBison.yxx" { (yyval.str) = "="; } -#line 5521 "built/tmp/cppBison.yxx.c" +#line 5484 "built/tmp/cppBison.yxx.c" break; case 139: /* function_operator: ',' */ -#line 1667 "dtool/src/cppparser/cppBison.yxx" +#line 1669 "dtool/src/cppparser/cppBison.yxx" { (yyval.str) = ","; } -#line 5529 "built/tmp/cppBison.yxx.c" +#line 5492 "built/tmp/cppBison.yxx.c" break; case 140: /* function_operator: PLUSPLUS */ -#line 1671 "dtool/src/cppparser/cppBison.yxx" +#line 1673 "dtool/src/cppparser/cppBison.yxx" { (yyval.str) = "++"; } -#line 5537 "built/tmp/cppBison.yxx.c" +#line 5500 "built/tmp/cppBison.yxx.c" break; case 141: /* function_operator: MINUSMINUS */ -#line 1675 "dtool/src/cppparser/cppBison.yxx" +#line 1677 "dtool/src/cppparser/cppBison.yxx" { (yyval.str) = "--"; } -#line 5545 "built/tmp/cppBison.yxx.c" +#line 5508 "built/tmp/cppBison.yxx.c" break; case 142: /* function_operator: TIMESEQUAL */ -#line 1679 "dtool/src/cppparser/cppBison.yxx" +#line 1681 "dtool/src/cppparser/cppBison.yxx" { (yyval.str) = "*="; } -#line 5553 "built/tmp/cppBison.yxx.c" +#line 5516 "built/tmp/cppBison.yxx.c" break; case 143: /* function_operator: DIVIDEEQUAL */ -#line 1683 "dtool/src/cppparser/cppBison.yxx" +#line 1685 "dtool/src/cppparser/cppBison.yxx" { (yyval.str) = "/="; } -#line 5561 "built/tmp/cppBison.yxx.c" +#line 5524 "built/tmp/cppBison.yxx.c" break; case 144: /* function_operator: MODEQUAL */ -#line 1687 "dtool/src/cppparser/cppBison.yxx" +#line 1689 "dtool/src/cppparser/cppBison.yxx" { (yyval.str) = "%="; } -#line 5569 "built/tmp/cppBison.yxx.c" +#line 5532 "built/tmp/cppBison.yxx.c" break; case 145: /* function_operator: PLUSEQUAL */ -#line 1691 "dtool/src/cppparser/cppBison.yxx" +#line 1693 "dtool/src/cppparser/cppBison.yxx" { (yyval.str) = "+="; } -#line 5577 "built/tmp/cppBison.yxx.c" +#line 5540 "built/tmp/cppBison.yxx.c" break; case 146: /* function_operator: MINUSEQUAL */ -#line 1695 "dtool/src/cppparser/cppBison.yxx" +#line 1697 "dtool/src/cppparser/cppBison.yxx" { (yyval.str) = "-="; } -#line 5585 "built/tmp/cppBison.yxx.c" +#line 5548 "built/tmp/cppBison.yxx.c" break; case 147: /* function_operator: OREQUAL */ -#line 1699 "dtool/src/cppparser/cppBison.yxx" +#line 1701 "dtool/src/cppparser/cppBison.yxx" { (yyval.str) = "|="; } -#line 5593 "built/tmp/cppBison.yxx.c" +#line 5556 "built/tmp/cppBison.yxx.c" break; case 148: /* function_operator: ANDEQUAL */ -#line 1703 "dtool/src/cppparser/cppBison.yxx" +#line 1705 "dtool/src/cppparser/cppBison.yxx" { (yyval.str) = "&="; } -#line 5601 "built/tmp/cppBison.yxx.c" +#line 5564 "built/tmp/cppBison.yxx.c" break; case 149: /* function_operator: XOREQUAL */ -#line 1707 "dtool/src/cppparser/cppBison.yxx" +#line 1709 "dtool/src/cppparser/cppBison.yxx" { (yyval.str) = "^="; } -#line 5609 "built/tmp/cppBison.yxx.c" +#line 5572 "built/tmp/cppBison.yxx.c" break; case 150: /* function_operator: LSHIFTEQUAL */ -#line 1711 "dtool/src/cppparser/cppBison.yxx" +#line 1713 "dtool/src/cppparser/cppBison.yxx" { (yyval.str) = "<<="; } -#line 5617 "built/tmp/cppBison.yxx.c" +#line 5580 "built/tmp/cppBison.yxx.c" break; case 151: /* function_operator: RSHIFTEQUAL */ -#line 1715 "dtool/src/cppparser/cppBison.yxx" +#line 1717 "dtool/src/cppparser/cppBison.yxx" { (yyval.str) = ">>="; } -#line 5625 "built/tmp/cppBison.yxx.c" +#line 5588 "built/tmp/cppBison.yxx.c" break; case 152: /* function_operator: POINTSAT */ -#line 1719 "dtool/src/cppparser/cppBison.yxx" +#line 1721 "dtool/src/cppparser/cppBison.yxx" { (yyval.str) = "->"; } -#line 5633 "built/tmp/cppBison.yxx.c" +#line 5596 "built/tmp/cppBison.yxx.c" break; case 153: /* function_operator: '[' ']' */ -#line 1723 "dtool/src/cppparser/cppBison.yxx" +#line 1725 "dtool/src/cppparser/cppBison.yxx" { (yyval.str) = "[]"; } -#line 5641 "built/tmp/cppBison.yxx.c" +#line 5604 "built/tmp/cppBison.yxx.c" break; case 154: /* function_operator: '(' ')' */ -#line 1727 "dtool/src/cppparser/cppBison.yxx" +#line 1729 "dtool/src/cppparser/cppBison.yxx" { (yyval.str) = "()"; } -#line 5649 "built/tmp/cppBison.yxx.c" +#line 5612 "built/tmp/cppBison.yxx.c" break; case 155: /* function_operator: KW_NEW */ -#line 1731 "dtool/src/cppparser/cppBison.yxx" +#line 1733 "dtool/src/cppparser/cppBison.yxx" { (yyval.str) = "new"; } -#line 5657 "built/tmp/cppBison.yxx.c" +#line 5620 "built/tmp/cppBison.yxx.c" break; case 156: /* function_operator: KW_DELETE */ -#line 1735 "dtool/src/cppparser/cppBison.yxx" +#line 1737 "dtool/src/cppparser/cppBison.yxx" { (yyval.str) = "delete"; } -#line 5665 "built/tmp/cppBison.yxx.c" +#line 5628 "built/tmp/cppBison.yxx.c" break; case 161: /* $@15: %empty */ -#line 1749 "dtool/src/cppparser/cppBison.yxx" +#line 1751 "dtool/src/cppparser/cppBison.yxx" { push_scope(new CPPTemplateScope(current_scope)); } -#line 5673 "built/tmp/cppBison.yxx.c" +#line 5636 "built/tmp/cppBison.yxx.c" break; case 162: /* template_declaration: KW_TEMPLATE $@15 '<' template_formal_parameters '>' more_template_declaration */ -#line 1753 "dtool/src/cppparser/cppBison.yxx" +#line 1755 "dtool/src/cppparser/cppBison.yxx" { pop_scope(); } -#line 5681 "built/tmp/cppBison.yxx.c" +#line 5644 "built/tmp/cppBison.yxx.c" break; case 167: /* template_nonempty_formal_parameters: template_formal_parameter */ -#line 1767 "dtool/src/cppparser/cppBison.yxx" +#line 1769 "dtool/src/cppparser/cppBison.yxx" { CPPTemplateScope *ts = current_scope->as_template_scope(); assert(ts != nullptr); ts->add_template_parameter((yyvsp[0].u.decl)); } -#line 5691 "built/tmp/cppBison.yxx.c" +#line 5654 "built/tmp/cppBison.yxx.c" break; case 168: /* template_nonempty_formal_parameters: template_nonempty_formal_parameters ',' template_formal_parameter */ -#line 1773 "dtool/src/cppparser/cppBison.yxx" +#line 1775 "dtool/src/cppparser/cppBison.yxx" { CPPTemplateScope *ts = current_scope->as_template_scope(); assert(ts != nullptr); ts->add_template_parameter((yyvsp[0].u.decl)); } -#line 5701 "built/tmp/cppBison.yxx.c" +#line 5664 "built/tmp/cppBison.yxx.c" break; case 171: /* template_formal_parameter: typename_keyword */ -#line 1787 "dtool/src/cppparser/cppBison.yxx" +#line 1789 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.decl) = CPPType::new_type(new CPPClassTemplateParameter(nullptr)); } -#line 5709 "built/tmp/cppBison.yxx.c" +#line 5672 "built/tmp/cppBison.yxx.c" break; case 172: /* template_formal_parameter: typename_keyword name */ -#line 1791 "dtool/src/cppparser/cppBison.yxx" +#line 1793 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.decl) = CPPType::new_type(new CPPClassTemplateParameter((yyvsp[0].u.identifier))); } -#line 5717 "built/tmp/cppBison.yxx.c" +#line 5680 "built/tmp/cppBison.yxx.c" break; case 173: /* template_formal_parameter: typename_keyword name '=' full_type */ -#line 1795 "dtool/src/cppparser/cppBison.yxx" +#line 1797 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.decl) = CPPType::new_type(new CPPClassTemplateParameter((yyvsp[-2].u.identifier), (yyvsp[0].u.type))); } -#line 5725 "built/tmp/cppBison.yxx.c" +#line 5688 "built/tmp/cppBison.yxx.c" break; case 174: /* template_formal_parameter: typename_keyword ELLIPSIS */ -#line 1799 "dtool/src/cppparser/cppBison.yxx" +#line 1801 "dtool/src/cppparser/cppBison.yxx" { CPPClassTemplateParameter *ctp = new CPPClassTemplateParameter(nullptr); ctp->_packed = true; (yyval.u.decl) = CPPType::new_type(ctp); } -#line 5735 "built/tmp/cppBison.yxx.c" +#line 5698 "built/tmp/cppBison.yxx.c" break; case 175: /* template_formal_parameter: typename_keyword ELLIPSIS name */ -#line 1805 "dtool/src/cppparser/cppBison.yxx" +#line 1807 "dtool/src/cppparser/cppBison.yxx" { CPPClassTemplateParameter *ctp = new CPPClassTemplateParameter((yyvsp[0].u.identifier)); ctp->_packed = true; (yyval.u.decl) = CPPType::new_type(ctp); } -#line 5745 "built/tmp/cppBison.yxx.c" +#line 5708 "built/tmp/cppBison.yxx.c" break; case 176: /* template_formal_parameter: template_formal_parameter_type formal_parameter_identifier template_parameter_maybe_initialize */ -#line 1811 "dtool/src/cppparser/cppBison.yxx" +#line 1813 "dtool/src/cppparser/cppBison.yxx" { CPPInstance *inst = new CPPInstance((yyvsp[-2].u.type), (yyvsp[-1].u.inst_ident), 0, (yylsp[-1]).file); inst->set_initializer((yyvsp[0].u.expr)); (yyval.u.decl) = inst; } -#line 5755 "built/tmp/cppBison.yxx.c" +#line 5718 "built/tmp/cppBison.yxx.c" break; case 177: /* template_formal_parameter: KW_CONST template_formal_parameter_type formal_parameter_identifier template_parameter_maybe_initialize */ -#line 1817 "dtool/src/cppparser/cppBison.yxx" +#line 1819 "dtool/src/cppparser/cppBison.yxx" { (yyvsp[-1].u.inst_ident)->add_modifier(IIT_const); CPPInstance *inst = new CPPInstance((yyvsp[-2].u.type), (yyvsp[-1].u.inst_ident), 0, (yylsp[-1]).file); inst->set_initializer((yyvsp[0].u.expr)); (yyval.u.decl) = inst; } -#line 5766 "built/tmp/cppBison.yxx.c" +#line 5729 "built/tmp/cppBison.yxx.c" break; case 178: /* template_formal_parameter: template_formal_parameter_type parameter_pack_identifier */ -#line 1824 "dtool/src/cppparser/cppBison.yxx" +#line 1826 "dtool/src/cppparser/cppBison.yxx" { CPPInstance *inst = new CPPInstance((yyvsp[-1].u.type), (yyvsp[0].u.inst_ident), 0, (yylsp[0]).file); (yyval.u.decl) = inst; } -#line 5775 "built/tmp/cppBison.yxx.c" +#line 5738 "built/tmp/cppBison.yxx.c" break; case 179: /* template_formal_parameter: KW_CONST template_formal_parameter_type parameter_pack_identifier */ -#line 1829 "dtool/src/cppparser/cppBison.yxx" +#line 1831 "dtool/src/cppparser/cppBison.yxx" { (yyvsp[0].u.inst_ident)->add_modifier(IIT_const); CPPInstance *inst = new CPPInstance((yyvsp[-1].u.type), (yyvsp[0].u.inst_ident), 0, (yylsp[0]).file); (yyval.u.decl) = inst; } -#line 5785 "built/tmp/cppBison.yxx.c" +#line 5748 "built/tmp/cppBison.yxx.c" break; - case 180: /* template_formal_parameter_type: simple_type */ -#line 1838 "dtool/src/cppparser/cppBison.yxx" + case 180: /* template_formal_parameter: KW_VOLATILE template_formal_parameter_type formal_parameter_identifier template_parameter_maybe_initialize */ +#line 1837 "dtool/src/cppparser/cppBison.yxx" +{ + (yyvsp[-1].u.inst_ident)->add_modifier(IIT_volatile); + CPPInstance *inst = new CPPInstance((yyvsp[-2].u.type), (yyvsp[-1].u.inst_ident), 0, (yylsp[-1]).file); + inst->set_initializer((yyvsp[0].u.expr)); + (yyval.u.decl) = inst; +} +#line 5759 "built/tmp/cppBison.yxx.c" + break; + + case 181: /* template_formal_parameter: KW_VOLATILE template_formal_parameter_type parameter_pack_identifier */ +#line 1844 "dtool/src/cppparser/cppBison.yxx" +{ + (yyvsp[0].u.inst_ident)->add_modifier(IIT_volatile); + CPPInstance *inst = new CPPInstance((yyvsp[-1].u.type), (yyvsp[0].u.inst_ident), 0, (yylsp[0]).file); + (yyval.u.decl) = inst; +} +#line 5769 "built/tmp/cppBison.yxx.c" + break; + + case 182: /* template_formal_parameter_type: simple_type */ +#line 1853 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.type) = CPPType::new_type((yyvsp[0].u.simple_type)); } -#line 5793 "built/tmp/cppBison.yxx.c" +#line 5777 "built/tmp/cppBison.yxx.c" break; - case 181: /* template_formal_parameter_type: IDENTIFIER */ -#line 1842 "dtool/src/cppparser/cppBison.yxx" + case 183: /* template_formal_parameter_type: IDENTIFIER */ +#line 1857 "dtool/src/cppparser/cppBison.yxx" { yywarning("Not a type: " + (yyvsp[0].u.identifier)->get_fully_scoped_name(), (yylsp[0])); (yyval.u.type) = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_unknown)); } -#line 5802 "built/tmp/cppBison.yxx.c" +#line 5786 "built/tmp/cppBison.yxx.c" break; - case 182: /* template_formal_parameter_type: TYPENAME_IDENTIFIER */ -#line 1847 "dtool/src/cppparser/cppBison.yxx" + case 184: /* template_formal_parameter_type: TYPENAME_IDENTIFIER */ +#line 1862 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.type) = (yyvsp[0].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); if ((yyval.u.type) == nullptr) { @@ -5810,11 +5794,11 @@ yyreduce: } assert((yyval.u.type) != nullptr); } -#line 5814 "built/tmp/cppBison.yxx.c" +#line 5798 "built/tmp/cppBison.yxx.c" break; - case 183: /* template_formal_parameter_type: TYPEPACK_IDENTIFIER */ -#line 1855 "dtool/src/cppparser/cppBison.yxx" + case 185: /* template_formal_parameter_type: TYPEPACK_IDENTIFIER */ +#line 1870 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.type) = (yyvsp[0].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); if ((yyval.u.type) == nullptr) { @@ -5822,19 +5806,19 @@ yyreduce: } assert((yyval.u.type) != nullptr); } -#line 5826 "built/tmp/cppBison.yxx.c" +#line 5810 "built/tmp/cppBison.yxx.c" break; - case 184: /* instance_identifier: name_no_final optional_attributes */ -#line 1867 "dtool/src/cppparser/cppBison.yxx" + case 186: /* instance_identifier: name_no_final optional_attributes */ +#line 1882 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = new CPPInstanceIdentifier((yyvsp[-1].u.identifier), (yyvsp[0].attr_list)); } -#line 5834 "built/tmp/cppBison.yxx.c" +#line 5818 "built/tmp/cppBison.yxx.c" break; - case 185: /* instance_identifier: KW_OPERATOR function_operator optional_attributes */ -#line 1871 "dtool/src/cppparser/cppBison.yxx" + case 187: /* instance_identifier: KW_OPERATOR function_operator optional_attributes */ +#line 1886 "dtool/src/cppparser/cppBison.yxx" { // For an operator function. We implement this simply by building a // ficticious name for the function; in other respects it's just @@ -5848,11 +5832,11 @@ yyreduce: (yyval.u.inst_ident) = new CPPInstanceIdentifier(ident, (yyvsp[0].attr_list)); } -#line 5852 "built/tmp/cppBison.yxx.c" +#line 5836 "built/tmp/cppBison.yxx.c" break; - case 186: /* instance_identifier: KW_OPERATOR SIMPLE_STRING IDENTIFIER optional_attributes */ -#line 1885 "dtool/src/cppparser/cppBison.yxx" + case 188: /* instance_identifier: KW_OPERATOR SIMPLE_STRING IDENTIFIER optional_attributes */ +#line 1900 "dtool/src/cppparser/cppBison.yxx" { // A C++11 literal operator. if (!(yyvsp[-2].str).empty()) { @@ -5867,83 +5851,83 @@ yyreduce: (yyval.u.inst_ident) = new CPPInstanceIdentifier(ident, (yyvsp[0].attr_list)); } -#line 5871 "built/tmp/cppBison.yxx.c" +#line 5855 "built/tmp/cppBison.yxx.c" break; - case 187: /* instance_identifier: KW_CONST instance_identifier */ -#line 1900 "dtool/src/cppparser/cppBison.yxx" + case 189: /* instance_identifier: KW_CONST instance_identifier */ +#line 1915 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); (yyval.u.inst_ident)->add_modifier(IIT_const); } -#line 5880 "built/tmp/cppBison.yxx.c" +#line 5864 "built/tmp/cppBison.yxx.c" break; - case 188: /* instance_identifier: KW_VOLATILE instance_identifier */ -#line 1905 "dtool/src/cppparser/cppBison.yxx" + case 190: /* instance_identifier: KW_VOLATILE instance_identifier */ +#line 1920 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); (yyval.u.inst_ident)->add_modifier(IIT_volatile); } -#line 5889 "built/tmp/cppBison.yxx.c" +#line 5873 "built/tmp/cppBison.yxx.c" break; - case 189: /* instance_identifier: '*' optional_attributes instance_identifier */ -#line 1910 "dtool/src/cppparser/cppBison.yxx" + case 191: /* instance_identifier: '*' optional_attributes instance_identifier */ +#line 1925 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); (yyval.u.inst_ident)->add_modifier(IIT_pointer, (yyvsp[-1].attr_list)); } -#line 5898 "built/tmp/cppBison.yxx.c" +#line 5882 "built/tmp/cppBison.yxx.c" break; - case 190: /* instance_identifier: '&' optional_attributes instance_identifier */ -#line 1915 "dtool/src/cppparser/cppBison.yxx" + case 192: /* instance_identifier: '&' optional_attributes instance_identifier */ +#line 1930 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); (yyval.u.inst_ident)->add_modifier(IIT_reference, (yyvsp[-1].attr_list)); } -#line 5907 "built/tmp/cppBison.yxx.c" +#line 5891 "built/tmp/cppBison.yxx.c" break; - case 191: /* instance_identifier: ANDAND optional_attributes instance_identifier */ -#line 1920 "dtool/src/cppparser/cppBison.yxx" + case 193: /* instance_identifier: ANDAND optional_attributes instance_identifier */ +#line 1935 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); (yyval.u.inst_ident)->add_modifier(IIT_rvalue_reference, (yyvsp[-1].attr_list)); } -#line 5916 "built/tmp/cppBison.yxx.c" +#line 5900 "built/tmp/cppBison.yxx.c" break; - case 192: /* instance_identifier: SCOPING '*' optional_attributes instance_identifier */ -#line 1925 "dtool/src/cppparser/cppBison.yxx" + case 194: /* instance_identifier: SCOPING '*' optional_attributes instance_identifier */ +#line 1940 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); (yyval.u.inst_ident)->add_scoped_pointer_modifier((yyvsp[-3].u.identifier), (yyvsp[-1].attr_list)); } -#line 5925 "built/tmp/cppBison.yxx.c" +#line 5909 "built/tmp/cppBison.yxx.c" break; - case 193: /* instance_identifier: instance_identifier '[' optional_const_expr ']' optional_attributes */ -#line 1930 "dtool/src/cppparser/cppBison.yxx" + case 195: /* instance_identifier: instance_identifier '[' optional_const_expr ']' optional_attributes */ +#line 1945 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = (yyvsp[-4].u.inst_ident); (yyval.u.inst_ident)->add_array_modifier((yyvsp[-2].u.expr), (yyvsp[0].attr_list)); } -#line 5934 "built/tmp/cppBison.yxx.c" +#line 5918 "built/tmp/cppBison.yxx.c" break; - case 194: /* instance_identifier: '(' instance_identifier ')' */ -#line 1935 "dtool/src/cppparser/cppBison.yxx" + case 196: /* instance_identifier: '(' instance_identifier ')' */ +#line 1950 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = (yyvsp[-1].u.inst_ident); (yyval.u.inst_ident)->add_modifier(IIT_paren); } -#line 5943 "built/tmp/cppBison.yxx.c" +#line 5927 "built/tmp/cppBison.yxx.c" break; - case 195: /* $@16: %empty */ -#line 1940 "dtool/src/cppparser/cppBison.yxx" + case 197: /* $@16: %empty */ +#line 1955 "dtool/src/cppparser/cppBison.yxx" { // Create a scope for this function (in case it is a function) CPPScope *scope = new CPPScope((yyvsp[-1].u.inst_ident)->get_scope(current_scope, global_scope), @@ -5956,11 +5940,11 @@ yyreduce: push_scope(scope); } -#line 5960 "built/tmp/cppBison.yxx.c" +#line 5944 "built/tmp/cppBison.yxx.c" break; - case 196: /* instance_identifier: instance_identifier '(' $@16 formal_parameter_list ')' function_post optional_attributes */ -#line 1953 "dtool/src/cppparser/cppBison.yxx" + case 198: /* instance_identifier: instance_identifier '(' $@16 formal_parameter_list ')' function_post optional_attributes */ +#line 1968 "dtool/src/cppparser/cppBison.yxx" { pop_scope(); (yyval.u.inst_ident) = (yyvsp[-6].u.inst_ident); @@ -5974,11 +5958,11 @@ yyreduce: (yyval.u.inst_ident)->add_func_modifier((yyvsp[-3].u.param_list), (yyvsp[-1].u.integer), nullptr, (yyvsp[0].attr_list)); } } -#line 5978 "built/tmp/cppBison.yxx.c" +#line 5962 "built/tmp/cppBison.yxx.c" break; - case 197: /* instance_identifier_and_maybe_trailing_return_type: instance_identifier maybe_trailing_return_type */ -#line 1971 "dtool/src/cppparser/cppBison.yxx" + case 199: /* instance_identifier_and_maybe_trailing_return_type: instance_identifier maybe_trailing_return_type */ +#line 1986 "dtool/src/cppparser/cppBison.yxx" { // This is handled a bit awkwardly right now. Ideally it'd be wrapped // up in the instance_identifier rule, but then more needs to happen in @@ -5988,909 +5972,913 @@ yyreduce: } (yyval.u.inst_ident) = (yyvsp[-1].u.inst_ident); } -#line 5992 "built/tmp/cppBison.yxx.c" +#line 5976 "built/tmp/cppBison.yxx.c" break; - case 198: /* instance_identifier_and_maybe_trailing_return_type: instance_identifier ':' const_expr */ -#line 1981 "dtool/src/cppparser/cppBison.yxx" + case 200: /* instance_identifier_and_maybe_trailing_return_type: instance_identifier ':' const_expr */ +#line 1996 "dtool/src/cppparser/cppBison.yxx" { // Bitfield definition. (yyvsp[-2].u.inst_ident)->_bit_width = (yyvsp[0].u.expr); (yyval.u.inst_ident) = (yyvsp[-2].u.inst_ident); } -#line 6002 "built/tmp/cppBison.yxx.c" +#line 5986 "built/tmp/cppBison.yxx.c" break; - case 199: /* maybe_trailing_return_type: empty */ -#line 1991 "dtool/src/cppparser/cppBison.yxx" + case 201: /* maybe_trailing_return_type: empty */ +#line 2006 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.type) = nullptr; } -#line 6010 "built/tmp/cppBison.yxx.c" +#line 5994 "built/tmp/cppBison.yxx.c" break; - case 200: /* maybe_trailing_return_type: POINTSAT predefined_type empty_instance_identifier */ -#line 1995 "dtool/src/cppparser/cppBison.yxx" + case 202: /* maybe_trailing_return_type: POINTSAT predefined_type empty_instance_identifier */ +#line 2010 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.type) = (yyvsp[0].u.inst_ident)->unroll_type((yyvsp[-1].u.type)); } -#line 6018 "built/tmp/cppBison.yxx.c" +#line 6002 "built/tmp/cppBison.yxx.c" break; - case 201: /* maybe_trailing_return_type: POINTSAT KW_CONST predefined_type empty_instance_identifier */ -#line 1999 "dtool/src/cppparser/cppBison.yxx" + case 203: /* maybe_trailing_return_type: POINTSAT KW_CONST predefined_type empty_instance_identifier */ +#line 2014 "dtool/src/cppparser/cppBison.yxx" { (yyvsp[0].u.inst_ident)->add_modifier(IIT_const); (yyval.u.type) = (yyvsp[0].u.inst_ident)->unroll_type((yyvsp[-1].u.type)); } +#line 6011 "built/tmp/cppBison.yxx.c" + break; + + case 204: /* maybe_comma_identifier: empty */ +#line 2023 "dtool/src/cppparser/cppBison.yxx" +{ + (yyval.u.identifier) = nullptr; +} +#line 6019 "built/tmp/cppBison.yxx.c" + break; + + case 205: /* maybe_comma_identifier: ',' IDENTIFIER */ +#line 2027 "dtool/src/cppparser/cppBison.yxx" +{ + (yyval.u.identifier) = (yyvsp[0].u.identifier); +} #line 6027 "built/tmp/cppBison.yxx.c" break; - case 202: /* maybe_comma_identifier: empty */ -#line 2008 "dtool/src/cppparser/cppBison.yxx" + case 206: /* function_parameter_list: empty */ +#line 2035 "dtool/src/cppparser/cppBison.yxx" { - (yyval.u.identifier) = nullptr; + (yyval.u.param_list) = new CPPParameterList; } #line 6035 "built/tmp/cppBison.yxx.c" break; - case 203: /* maybe_comma_identifier: ',' IDENTIFIER */ -#line 2012 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.identifier) = (yyvsp[0].u.identifier); -} -#line 6043 "built/tmp/cppBison.yxx.c" - break; - - case 204: /* function_parameter_list: empty */ -#line 2020 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.param_list) = new CPPParameterList; -} -#line 6051 "built/tmp/cppBison.yxx.c" - break; - - case 205: /* function_parameter_list: ELLIPSIS */ -#line 2024 "dtool/src/cppparser/cppBison.yxx" + case 207: /* function_parameter_list: ELLIPSIS */ +#line 2039 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.param_list) = new CPPParameterList; (yyval.u.param_list)->_includes_ellipsis = true; } -#line 6060 "built/tmp/cppBison.yxx.c" +#line 6044 "built/tmp/cppBison.yxx.c" break; - case 206: /* function_parameter_list: function_parameters */ -#line 2029 "dtool/src/cppparser/cppBison.yxx" + case 208: /* function_parameter_list: function_parameters */ +#line 2044 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.param_list) = (yyvsp[0].u.param_list); } -#line 6068 "built/tmp/cppBison.yxx.c" +#line 6052 "built/tmp/cppBison.yxx.c" break; - case 207: /* function_parameter_list: function_parameters ',' ELLIPSIS */ -#line 2033 "dtool/src/cppparser/cppBison.yxx" + case 209: /* function_parameter_list: function_parameters ',' ELLIPSIS */ +#line 2048 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.param_list) = (yyvsp[-2].u.param_list); (yyval.u.param_list)->_includes_ellipsis = true; } -#line 6077 "built/tmp/cppBison.yxx.c" +#line 6061 "built/tmp/cppBison.yxx.c" break; - case 208: /* function_parameter_list: function_parameters ELLIPSIS */ -#line 2038 "dtool/src/cppparser/cppBison.yxx" + case 210: /* function_parameter_list: function_parameters ELLIPSIS */ +#line 2053 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.param_list) = (yyvsp[-1].u.param_list); (yyval.u.param_list)->_includes_ellipsis = true; } -#line 6086 "built/tmp/cppBison.yxx.c" +#line 6070 "built/tmp/cppBison.yxx.c" break; - case 209: /* function_parameters: function_parameter */ -#line 2046 "dtool/src/cppparser/cppBison.yxx" + case 211: /* function_parameters: function_parameter */ +#line 2061 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.param_list) = new CPPParameterList; (yyval.u.param_list)->_parameters.push_back((yyvsp[0].u.instance)); } -#line 6095 "built/tmp/cppBison.yxx.c" +#line 6079 "built/tmp/cppBison.yxx.c" break; - case 210: /* function_parameters: function_parameters ',' function_parameter */ -#line 2051 "dtool/src/cppparser/cppBison.yxx" + case 212: /* function_parameters: function_parameters ',' function_parameter */ +#line 2066 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.param_list) = (yyvsp[-2].u.param_list); (yyval.u.param_list)->_parameters.push_back((yyvsp[0].u.instance)); } -#line 6104 "built/tmp/cppBison.yxx.c" +#line 6088 "built/tmp/cppBison.yxx.c" break; - case 211: /* formal_parameter_list: empty */ -#line 2059 "dtool/src/cppparser/cppBison.yxx" + case 213: /* formal_parameter_list: empty */ +#line 2074 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.param_list) = new CPPParameterList; } -#line 6112 "built/tmp/cppBison.yxx.c" +#line 6096 "built/tmp/cppBison.yxx.c" break; - case 212: /* formal_parameter_list: ELLIPSIS */ -#line 2063 "dtool/src/cppparser/cppBison.yxx" + case 214: /* formal_parameter_list: ELLIPSIS */ +#line 2078 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.param_list) = new CPPParameterList; (yyval.u.param_list)->_includes_ellipsis = true; } -#line 6121 "built/tmp/cppBison.yxx.c" +#line 6105 "built/tmp/cppBison.yxx.c" break; - case 213: /* formal_parameter_list: formal_parameters */ -#line 2068 "dtool/src/cppparser/cppBison.yxx" + case 215: /* formal_parameter_list: formal_parameters */ +#line 2083 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.param_list) = (yyvsp[0].u.param_list); } -#line 6129 "built/tmp/cppBison.yxx.c" +#line 6113 "built/tmp/cppBison.yxx.c" break; - case 214: /* formal_parameter_list: formal_parameters ',' ELLIPSIS */ -#line 2072 "dtool/src/cppparser/cppBison.yxx" + case 216: /* formal_parameter_list: formal_parameters ',' ELLIPSIS */ +#line 2087 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.param_list) = (yyvsp[-2].u.param_list); (yyval.u.param_list)->_includes_ellipsis = true; } -#line 6138 "built/tmp/cppBison.yxx.c" +#line 6122 "built/tmp/cppBison.yxx.c" break; - case 215: /* formal_parameter_list: formal_parameters ELLIPSIS */ -#line 2077 "dtool/src/cppparser/cppBison.yxx" + case 217: /* formal_parameter_list: formal_parameters ELLIPSIS */ +#line 2092 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.param_list) = (yyvsp[-1].u.param_list); (yyval.u.param_list)->_includes_ellipsis = true; } -#line 6147 "built/tmp/cppBison.yxx.c" +#line 6131 "built/tmp/cppBison.yxx.c" break; - case 216: /* formal_parameters: formal_parameter */ -#line 2085 "dtool/src/cppparser/cppBison.yxx" + case 218: /* formal_parameters: formal_parameter */ +#line 2100 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.param_list) = new CPPParameterList; (yyval.u.param_list)->_parameters.push_back((yyvsp[0].u.instance)); } -#line 6156 "built/tmp/cppBison.yxx.c" +#line 6140 "built/tmp/cppBison.yxx.c" break; - case 217: /* formal_parameters: formal_parameters ',' formal_parameter */ -#line 2090 "dtool/src/cppparser/cppBison.yxx" + case 219: /* formal_parameters: formal_parameters ',' formal_parameter */ +#line 2105 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.param_list) = (yyvsp[-2].u.param_list); (yyval.u.param_list)->_parameters.push_back((yyvsp[0].u.instance)); } +#line 6149 "built/tmp/cppBison.yxx.c" + break; + + case 220: /* template_parameter_maybe_initialize: empty */ +#line 2113 "dtool/src/cppparser/cppBison.yxx" +{ + (yyval.u.expr) = nullptr; +} +#line 6157 "built/tmp/cppBison.yxx.c" + break; + + case 221: /* template_parameter_maybe_initialize: '=' no_angle_bracket_const_expr */ +#line 2117 "dtool/src/cppparser/cppBison.yxx" +{ + (yyval.u.expr) = (yyvsp[0].u.expr); +} #line 6165 "built/tmp/cppBison.yxx.c" break; - case 218: /* template_parameter_maybe_initialize: empty */ -#line 2098 "dtool/src/cppparser/cppBison.yxx" + case 222: /* maybe_initialize: empty */ +#line 2124 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = nullptr; } #line 6173 "built/tmp/cppBison.yxx.c" break; - case 219: /* template_parameter_maybe_initialize: '=' no_angle_bracket_const_expr */ -#line 2102 "dtool/src/cppparser/cppBison.yxx" + case 223: /* maybe_initialize: '=' const_expr */ +#line 2128 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = (yyvsp[0].u.expr); } #line 6181 "built/tmp/cppBison.yxx.c" break; - case 220: /* maybe_initialize: empty */ -#line 2109 "dtool/src/cppparser/cppBison.yxx" + case 224: /* maybe_initialize_or_constructor_body: ';' */ +#line 2135 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = nullptr; } #line 6189 "built/tmp/cppBison.yxx.c" break; - case 221: /* maybe_initialize: '=' const_expr */ -#line 2113 "dtool/src/cppparser/cppBison.yxx" + case 225: /* maybe_initialize_or_constructor_body: '{' code '}' */ +#line 2139 "dtool/src/cppparser/cppBison.yxx" { - (yyval.u.expr) = (yyvsp[0].u.expr); + (yyval.u.expr) = nullptr; } #line 6197 "built/tmp/cppBison.yxx.c" break; - case 222: /* maybe_initialize_or_constructor_body: ';' */ -#line 2120 "dtool/src/cppparser/cppBison.yxx" + case 226: /* maybe_initialize_or_constructor_body: ':' constructor_inits '{' code '}' */ +#line 2143 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = nullptr; } #line 6205 "built/tmp/cppBison.yxx.c" break; - case 223: /* maybe_initialize_or_constructor_body: '{' code '}' */ -#line 2124 "dtool/src/cppparser/cppBison.yxx" + case 227: /* maybe_initialize_or_constructor_body: '=' KW_DEFAULT ';' */ +#line 2147 "dtool/src/cppparser/cppBison.yxx" { - (yyval.u.expr) = nullptr; + (yyval.u.expr) = new CPPExpression(CPPExpression::get_default()); } #line 6213 "built/tmp/cppBison.yxx.c" break; - case 224: /* maybe_initialize_or_constructor_body: ':' constructor_inits '{' code '}' */ -#line 2128 "dtool/src/cppparser/cppBison.yxx" + case 228: /* maybe_initialize_or_constructor_body: '=' KW_DELETE ';' */ +#line 2151 "dtool/src/cppparser/cppBison.yxx" { - (yyval.u.expr) = nullptr; + (yyval.u.expr) = new CPPExpression(CPPExpression::get_delete()); } #line 6221 "built/tmp/cppBison.yxx.c" break; - case 225: /* maybe_initialize_or_constructor_body: '=' KW_DEFAULT ';' */ -#line 2132 "dtool/src/cppparser/cppBison.yxx" + case 229: /* maybe_initialize_or_function_body: ';' */ +#line 2158 "dtool/src/cppparser/cppBison.yxx" { - (yyval.u.expr) = new CPPExpression(CPPExpression::get_default()); + (yyval.u.expr) = nullptr; } #line 6229 "built/tmp/cppBison.yxx.c" break; - case 226: /* maybe_initialize_or_constructor_body: '=' KW_DELETE ';' */ -#line 2136 "dtool/src/cppparser/cppBison.yxx" + case 230: /* maybe_initialize_or_function_body: '{' code '}' */ +#line 2162 "dtool/src/cppparser/cppBison.yxx" { - (yyval.u.expr) = new CPPExpression(CPPExpression::get_delete()); + (yyval.u.expr) = nullptr; } #line 6237 "built/tmp/cppBison.yxx.c" break; - case 227: /* maybe_initialize_or_function_body: ';' */ -#line 2143 "dtool/src/cppparser/cppBison.yxx" + case 231: /* maybe_initialize_or_function_body: '=' const_expr ';' */ +#line 2166 "dtool/src/cppparser/cppBison.yxx" { - (yyval.u.expr) = nullptr; + (yyval.u.expr) = (yyvsp[-1].u.expr); } #line 6245 "built/tmp/cppBison.yxx.c" break; - case 228: /* maybe_initialize_or_function_body: '{' code '}' */ -#line 2147 "dtool/src/cppparser/cppBison.yxx" + case 232: /* maybe_initialize_or_function_body: '=' KW_DEFAULT ';' */ +#line 2170 "dtool/src/cppparser/cppBison.yxx" { - (yyval.u.expr) = nullptr; + (yyval.u.expr) = new CPPExpression(CPPExpression::get_default()); } #line 6253 "built/tmp/cppBison.yxx.c" break; - case 229: /* maybe_initialize_or_function_body: '=' const_expr ';' */ -#line 2151 "dtool/src/cppparser/cppBison.yxx" + case 233: /* maybe_initialize_or_function_body: '=' KW_DELETE ';' */ +#line 2174 "dtool/src/cppparser/cppBison.yxx" { - (yyval.u.expr) = (yyvsp[-1].u.expr); + (yyval.u.expr) = new CPPExpression(CPPExpression::get_delete()); } #line 6261 "built/tmp/cppBison.yxx.c" break; - case 230: /* maybe_initialize_or_function_body: '=' KW_DEFAULT ';' */ -#line 2155 "dtool/src/cppparser/cppBison.yxx" + case 234: /* maybe_initialize_or_function_body: '=' '{' structure_init '}' */ +#line 2178 "dtool/src/cppparser/cppBison.yxx" { - (yyval.u.expr) = new CPPExpression(CPPExpression::get_default()); + (yyval.u.expr) = nullptr; } #line 6269 "built/tmp/cppBison.yxx.c" break; - case 231: /* maybe_initialize_or_function_body: '=' KW_DELETE ';' */ -#line 2159 "dtool/src/cppparser/cppBison.yxx" + case 238: /* structure_init_body: const_expr */ +#line 2191 "dtool/src/cppparser/cppBison.yxx" { - (yyval.u.expr) = new CPPExpression(CPPExpression::get_delete()); } -#line 6277 "built/tmp/cppBison.yxx.c" +#line 6276 "built/tmp/cppBison.yxx.c" break; - case 232: /* maybe_initialize_or_function_body: '=' '{' structure_init '}' */ -#line 2163 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = nullptr; -} -#line 6285 "built/tmp/cppBison.yxx.c" - break; - - case 236: /* structure_init_body: const_expr */ -#line 2176 "dtool/src/cppparser/cppBison.yxx" + case 242: /* function_parameter: optional_attributes storage_class type formal_parameter_identifier maybe_initialize */ +#line 2200 "dtool/src/cppparser/cppBison.yxx" { + if ((yyvsp[-3].u.integer) & CPPInstance::SC_const) { + (yyvsp[-1].u.inst_ident)->add_modifier(IIT_const); + } + if ((yyvsp[-3].u.integer) & CPPInstance::SC_volatile) { + (yyvsp[-1].u.inst_ident)->add_modifier(IIT_volatile); + } + (yyvsp[-1].u.inst_ident)->add_attributes((yyvsp[-4].attr_list)); + (yyval.u.instance) = new CPPInstance((yyvsp[-2].u.type), (yyvsp[-1].u.inst_ident), 0, (yylsp[-1]).file); + (yyval.u.instance)->set_initializer((yyvsp[0].u.expr)); } #line 6292 "built/tmp/cppBison.yxx.c" break; - case 240: /* function_parameter: optional_attributes type formal_parameter_identifier maybe_initialize */ -#line 2185 "dtool/src/cppparser/cppBison.yxx" -{ - (yyvsp[-1].u.inst_ident)->add_attributes((yyvsp[-3].attr_list)); - (yyval.u.instance) = new CPPInstance((yyvsp[-2].u.type), (yyvsp[-1].u.inst_ident), 0, (yylsp[-1]).file); - (yyval.u.instance)->set_initializer((yyvsp[0].u.expr)); -} -#line 6302 "built/tmp/cppBison.yxx.c" - break; - - case 241: /* function_parameter: optional_attributes KW_CONST type formal_parameter_identifier maybe_initialize */ -#line 2191 "dtool/src/cppparser/cppBison.yxx" + case 243: /* function_parameter: optional_attributes storage_class type_pack parameter_pack_identifier maybe_initialize */ +#line 2212 "dtool/src/cppparser/cppBison.yxx" { + if ((yyvsp[-3].u.integer) & CPPInstance::SC_const) { + (yyvsp[-1].u.inst_ident)->add_modifier(IIT_const); + } + if ((yyvsp[-3].u.integer) & CPPInstance::SC_volatile) { + (yyvsp[-1].u.inst_ident)->add_modifier(IIT_volatile); + } (yyvsp[-1].u.inst_ident)->add_attributes((yyvsp[-4].attr_list)); - (yyvsp[-1].u.inst_ident)->add_modifier(IIT_const); (yyval.u.instance) = new CPPInstance((yyvsp[-2].u.type), (yyvsp[-1].u.inst_ident), 0, (yylsp[-1]).file); (yyval.u.instance)->set_initializer((yyvsp[0].u.expr)); } -#line 6313 "built/tmp/cppBison.yxx.c" +#line 6308 "built/tmp/cppBison.yxx.c" break; - case 242: /* function_parameter: optional_attributes KW_CONST KW_REGISTER type formal_parameter_identifier maybe_initialize */ -#line 2198 "dtool/src/cppparser/cppBison.yxx" -{ - (yyvsp[-1].u.inst_ident)->add_attributes((yyvsp[-5].attr_list)); - (yyvsp[-1].u.inst_ident)->add_modifier(IIT_const); - (yyval.u.instance) = new CPPInstance((yyvsp[-2].u.type), (yyvsp[-1].u.inst_ident), 0, (yylsp[-2]).file); - (yyval.u.instance)->set_initializer((yyvsp[0].u.expr)); -} -#line 6324 "built/tmp/cppBison.yxx.c" - break; - - case 243: /* function_parameter: optional_attributes type_pack parameter_pack_identifier maybe_initialize */ -#line 2205 "dtool/src/cppparser/cppBison.yxx" -{ - (yyvsp[-1].u.inst_ident)->add_attributes((yyvsp[-3].attr_list)); - (yyval.u.instance) = new CPPInstance((yyvsp[-2].u.type), (yyvsp[-1].u.inst_ident), 0, (yylsp[-1]).file); - (yyval.u.instance)->set_initializer((yyvsp[0].u.expr)); -} -#line 6334 "built/tmp/cppBison.yxx.c" - break; - - case 244: /* function_parameter: optional_attributes KW_CONST type_pack parameter_pack_identifier maybe_initialize */ -#line 2211 "dtool/src/cppparser/cppBison.yxx" -{ - (yyvsp[-1].u.inst_ident)->add_attributes((yyvsp[-4].attr_list)); - (yyvsp[-1].u.inst_ident)->add_modifier(IIT_const); - (yyval.u.instance) = new CPPInstance((yyvsp[-2].u.type), (yyvsp[-1].u.inst_ident), 0, (yylsp[-1]).file); - (yyval.u.instance)->set_initializer((yyvsp[0].u.expr)); -} -#line 6345 "built/tmp/cppBison.yxx.c" - break; - - case 245: /* function_parameter: optional_attributes KW_CONST KW_REGISTER type_pack parameter_pack_identifier maybe_initialize */ -#line 2218 "dtool/src/cppparser/cppBison.yxx" -{ - (yyvsp[-1].u.inst_ident)->add_attributes((yyvsp[-5].attr_list)); - (yyvsp[-1].u.inst_ident)->add_modifier(IIT_const); - (yyval.u.instance) = new CPPInstance((yyvsp[-2].u.type), (yyvsp[-1].u.inst_ident), 0, (yylsp[-2]).file); - (yyval.u.instance)->set_initializer((yyvsp[0].u.expr)); -} -#line 6356 "built/tmp/cppBison.yxx.c" - break; - - case 246: /* function_parameter: optional_attributes KW_REGISTER function_parameter */ -#line 2225 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.instance) = (yyvsp[0].u.instance); - (yyval.u.instance)->_attributes.add_attributes_from((yyvsp[-2].attr_list)); -} -#line 6365 "built/tmp/cppBison.yxx.c" - break; - - case 247: /* formal_parameter: function_parameter */ -#line 2237 "dtool/src/cppparser/cppBison.yxx" + case 244: /* formal_parameter: function_parameter */ +#line 2231 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.instance) = (yyvsp[0].u.instance); } -#line 6373 "built/tmp/cppBison.yxx.c" +#line 6316 "built/tmp/cppBison.yxx.c" break; - case 248: /* formal_parameter: formal_const_expr */ -#line 2241 "dtool/src/cppparser/cppBison.yxx" + case 245: /* formal_parameter: formal_const_expr */ +#line 2235 "dtool/src/cppparser/cppBison.yxx" { CPPType *type = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_parameter)); (yyval.u.instance) = new CPPInstance(type, "expr"); (yyval.u.instance)->set_initializer((yyvsp[0].u.expr)); } -#line 6384 "built/tmp/cppBison.yxx.c" +#line 6327 "built/tmp/cppBison.yxx.c" break; - case 249: /* not_paren_formal_parameter_identifier: empty */ -#line 2251 "dtool/src/cppparser/cppBison.yxx" + case 246: /* not_paren_formal_parameter_identifier: empty */ +#line 2245 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = new CPPInstanceIdentifier(nullptr); } -#line 6392 "built/tmp/cppBison.yxx.c" +#line 6335 "built/tmp/cppBison.yxx.c" break; - case 250: /* not_paren_formal_parameter_identifier: name_no_final optional_attributes */ -#line 2255 "dtool/src/cppparser/cppBison.yxx" + case 247: /* not_paren_formal_parameter_identifier: name_no_final optional_attributes */ +#line 2249 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = new CPPInstanceIdentifier((yyvsp[-1].u.identifier), (yyvsp[0].attr_list)); } -#line 6400 "built/tmp/cppBison.yxx.c" +#line 6343 "built/tmp/cppBison.yxx.c" break; - case 251: /* not_paren_formal_parameter_identifier: KW_CONST not_paren_formal_parameter_identifier */ -#line 2259 "dtool/src/cppparser/cppBison.yxx" + case 248: /* not_paren_formal_parameter_identifier: KW_CONST not_paren_formal_parameter_identifier */ +#line 2253 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); (yyval.u.inst_ident)->add_modifier(IIT_const); } -#line 6409 "built/tmp/cppBison.yxx.c" +#line 6352 "built/tmp/cppBison.yxx.c" break; - case 252: /* not_paren_formal_parameter_identifier: KW_VOLATILE not_paren_formal_parameter_identifier */ -#line 2264 "dtool/src/cppparser/cppBison.yxx" + case 249: /* not_paren_formal_parameter_identifier: KW_VOLATILE not_paren_formal_parameter_identifier */ +#line 2258 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); (yyval.u.inst_ident)->add_modifier(IIT_volatile); } -#line 6418 "built/tmp/cppBison.yxx.c" +#line 6361 "built/tmp/cppBison.yxx.c" break; - case 253: /* not_paren_formal_parameter_identifier: '*' optional_attributes not_paren_formal_parameter_identifier */ -#line 2269 "dtool/src/cppparser/cppBison.yxx" + case 250: /* not_paren_formal_parameter_identifier: KW_RESTRICT not_paren_formal_parameter_identifier */ +#line 2263 "dtool/src/cppparser/cppBison.yxx" +{ + (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); + (yyval.u.inst_ident)->add_modifier(IIT_restrict); +} +#line 6370 "built/tmp/cppBison.yxx.c" + break; + + case 251: /* not_paren_formal_parameter_identifier: '*' optional_attributes not_paren_formal_parameter_identifier */ +#line 2268 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); (yyval.u.inst_ident)->add_modifier(IIT_pointer, (yyvsp[-1].attr_list)); } -#line 6427 "built/tmp/cppBison.yxx.c" +#line 6379 "built/tmp/cppBison.yxx.c" break; - case 254: /* not_paren_formal_parameter_identifier: '&' optional_attributes not_paren_formal_parameter_identifier */ -#line 2274 "dtool/src/cppparser/cppBison.yxx" + case 252: /* not_paren_formal_parameter_identifier: '&' optional_attributes not_paren_formal_parameter_identifier */ +#line 2273 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); (yyval.u.inst_ident)->add_modifier(IIT_reference, (yyvsp[-1].attr_list)); } -#line 6436 "built/tmp/cppBison.yxx.c" +#line 6388 "built/tmp/cppBison.yxx.c" break; - case 255: /* not_paren_formal_parameter_identifier: ANDAND optional_attributes not_paren_formal_parameter_identifier */ -#line 2279 "dtool/src/cppparser/cppBison.yxx" + case 253: /* not_paren_formal_parameter_identifier: ANDAND optional_attributes not_paren_formal_parameter_identifier */ +#line 2278 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); (yyval.u.inst_ident)->add_modifier(IIT_rvalue_reference, (yyvsp[-1].attr_list)); } -#line 6445 "built/tmp/cppBison.yxx.c" +#line 6397 "built/tmp/cppBison.yxx.c" break; - case 256: /* not_paren_formal_parameter_identifier: SCOPING '*' optional_attributes not_paren_formal_parameter_identifier */ -#line 2284 "dtool/src/cppparser/cppBison.yxx" + case 254: /* not_paren_formal_parameter_identifier: SCOPING '*' optional_attributes not_paren_formal_parameter_identifier */ +#line 2283 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); (yyval.u.inst_ident)->add_scoped_pointer_modifier((yyvsp[-3].u.identifier), (yyvsp[-1].attr_list)); } -#line 6454 "built/tmp/cppBison.yxx.c" +#line 6406 "built/tmp/cppBison.yxx.c" break; - case 257: /* not_paren_formal_parameter_identifier: not_paren_formal_parameter_identifier '[' optional_const_expr ']' optional_attributes */ -#line 2289 "dtool/src/cppparser/cppBison.yxx" + case 255: /* not_paren_formal_parameter_identifier: not_paren_formal_parameter_identifier '[' optional_const_expr ']' optional_attributes */ +#line 2288 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = (yyvsp[-4].u.inst_ident); (yyval.u.inst_ident)->add_array_modifier((yyvsp[-2].u.expr), (yyvsp[0].attr_list)); } -#line 6463 "built/tmp/cppBison.yxx.c" +#line 6415 "built/tmp/cppBison.yxx.c" break; - case 258: /* formal_parameter_identifier: empty */ -#line 2297 "dtool/src/cppparser/cppBison.yxx" + case 256: /* formal_parameter_identifier: empty */ +#line 2296 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = new CPPInstanceIdentifier(nullptr); } -#line 6471 "built/tmp/cppBison.yxx.c" +#line 6423 "built/tmp/cppBison.yxx.c" break; - case 259: /* formal_parameter_identifier: name_no_final optional_attributes */ -#line 2301 "dtool/src/cppparser/cppBison.yxx" + case 257: /* formal_parameter_identifier: name_no_final optional_attributes */ +#line 2300 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = new CPPInstanceIdentifier((yyvsp[-1].u.identifier), (yyvsp[0].attr_list)); } -#line 6479 "built/tmp/cppBison.yxx.c" +#line 6431 "built/tmp/cppBison.yxx.c" break; - case 260: /* formal_parameter_identifier: KW_CONST formal_parameter_identifier */ -#line 2305 "dtool/src/cppparser/cppBison.yxx" + case 258: /* formal_parameter_identifier: KW_CONST formal_parameter_identifier */ +#line 2304 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); (yyval.u.inst_ident)->add_modifier(IIT_const); } -#line 6488 "built/tmp/cppBison.yxx.c" +#line 6440 "built/tmp/cppBison.yxx.c" break; - case 261: /* formal_parameter_identifier: KW_VOLATILE formal_parameter_identifier */ -#line 2310 "dtool/src/cppparser/cppBison.yxx" + case 259: /* formal_parameter_identifier: KW_VOLATILE formal_parameter_identifier */ +#line 2309 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); (yyval.u.inst_ident)->add_modifier(IIT_volatile); } -#line 6497 "built/tmp/cppBison.yxx.c" +#line 6449 "built/tmp/cppBison.yxx.c" break; - case 262: /* formal_parameter_identifier: '*' optional_attributes formal_parameter_identifier */ -#line 2315 "dtool/src/cppparser/cppBison.yxx" + case 260: /* formal_parameter_identifier: KW_RESTRICT formal_parameter_identifier */ +#line 2314 "dtool/src/cppparser/cppBison.yxx" +{ + (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); + (yyval.u.inst_ident)->add_modifier(IIT_restrict); +} +#line 6458 "built/tmp/cppBison.yxx.c" + break; + + case 261: /* formal_parameter_identifier: '*' optional_attributes formal_parameter_identifier */ +#line 2319 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); (yyval.u.inst_ident)->add_modifier(IIT_pointer, (yyvsp[-1].attr_list)); } -#line 6506 "built/tmp/cppBison.yxx.c" +#line 6467 "built/tmp/cppBison.yxx.c" break; - case 263: /* formal_parameter_identifier: '&' optional_attributes formal_parameter_identifier */ -#line 2320 "dtool/src/cppparser/cppBison.yxx" + case 262: /* formal_parameter_identifier: '&' optional_attributes formal_parameter_identifier */ +#line 2324 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); (yyval.u.inst_ident)->add_modifier(IIT_reference, (yyvsp[-1].attr_list)); } -#line 6515 "built/tmp/cppBison.yxx.c" +#line 6476 "built/tmp/cppBison.yxx.c" break; - case 264: /* formal_parameter_identifier: ANDAND optional_attributes formal_parameter_identifier */ -#line 2325 "dtool/src/cppparser/cppBison.yxx" + case 263: /* formal_parameter_identifier: ANDAND optional_attributes formal_parameter_identifier */ +#line 2329 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); (yyval.u.inst_ident)->add_modifier(IIT_rvalue_reference, (yyvsp[-1].attr_list)); } -#line 6524 "built/tmp/cppBison.yxx.c" +#line 6485 "built/tmp/cppBison.yxx.c" break; - case 265: /* formal_parameter_identifier: SCOPING '*' optional_attributes formal_parameter_identifier */ -#line 2330 "dtool/src/cppparser/cppBison.yxx" + case 264: /* formal_parameter_identifier: SCOPING '*' optional_attributes formal_parameter_identifier */ +#line 2334 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); (yyval.u.inst_ident)->add_scoped_pointer_modifier((yyvsp[-3].u.identifier), (yyvsp[-1].attr_list)); } -#line 6533 "built/tmp/cppBison.yxx.c" +#line 6494 "built/tmp/cppBison.yxx.c" break; - case 266: /* formal_parameter_identifier: formal_parameter_identifier '[' optional_const_expr ']' optional_attributes */ -#line 2335 "dtool/src/cppparser/cppBison.yxx" + case 265: /* formal_parameter_identifier: formal_parameter_identifier '[' optional_const_expr ']' optional_attributes */ +#line 2339 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = (yyvsp[-4].u.inst_ident); (yyval.u.inst_ident)->add_array_modifier((yyvsp[-2].u.expr), (yyvsp[0].attr_list)); } -#line 6542 "built/tmp/cppBison.yxx.c" +#line 6503 "built/tmp/cppBison.yxx.c" break; - case 267: /* formal_parameter_identifier: '(' formal_parameter_identifier ')' '(' function_parameter_list ')' function_post optional_attributes */ -#line 2340 "dtool/src/cppparser/cppBison.yxx" + case 266: /* formal_parameter_identifier: '(' formal_parameter_identifier ')' '(' function_parameter_list ')' function_post optional_attributes */ +#line 2344 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = (yyvsp[-6].u.inst_ident); (yyval.u.inst_ident)->add_modifier(IIT_paren); (yyval.u.inst_ident)->add_func_modifier((yyvsp[-3].u.param_list), (yyvsp[-1].u.integer), nullptr, (yyvsp[0].attr_list)); } -#line 6552 "built/tmp/cppBison.yxx.c" +#line 6513 "built/tmp/cppBison.yxx.c" break; - case 268: /* formal_parameter_identifier: '(' formal_parameter_identifier ')' */ -#line 2346 "dtool/src/cppparser/cppBison.yxx" + case 267: /* formal_parameter_identifier: '(' formal_parameter_identifier ')' */ +#line 2350 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = (yyvsp[-1].u.inst_ident); (yyval.u.inst_ident)->add_modifier(IIT_paren); } -#line 6561 "built/tmp/cppBison.yxx.c" +#line 6522 "built/tmp/cppBison.yxx.c" break; - case 269: /* parameter_pack_identifier: ELLIPSIS */ -#line 2354 "dtool/src/cppparser/cppBison.yxx" + case 268: /* parameter_pack_identifier: ELLIPSIS */ +#line 2358 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = new CPPInstanceIdentifier(nullptr); (yyval.u.inst_ident)->_packed = true; } -#line 6570 "built/tmp/cppBison.yxx.c" +#line 6531 "built/tmp/cppBison.yxx.c" break; - case 270: /* parameter_pack_identifier: ELLIPSIS name optional_attributes */ -#line 2359 "dtool/src/cppparser/cppBison.yxx" + case 269: /* parameter_pack_identifier: ELLIPSIS name optional_attributes */ +#line 2363 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = new CPPInstanceIdentifier((yyvsp[-1].u.identifier), (yyvsp[0].attr_list)); (yyval.u.inst_ident)->_packed = true; } -#line 6579 "built/tmp/cppBison.yxx.c" +#line 6540 "built/tmp/cppBison.yxx.c" break; - case 271: /* parameter_pack_identifier: KW_CONST parameter_pack_identifier */ -#line 2364 "dtool/src/cppparser/cppBison.yxx" + case 270: /* parameter_pack_identifier: KW_CONST parameter_pack_identifier */ +#line 2368 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); (yyval.u.inst_ident)->add_modifier(IIT_const); } -#line 6588 "built/tmp/cppBison.yxx.c" +#line 6549 "built/tmp/cppBison.yxx.c" break; - case 272: /* parameter_pack_identifier: KW_VOLATILE parameter_pack_identifier */ -#line 2369 "dtool/src/cppparser/cppBison.yxx" + case 271: /* parameter_pack_identifier: KW_VOLATILE parameter_pack_identifier */ +#line 2373 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); (yyval.u.inst_ident)->add_modifier(IIT_volatile); } -#line 6597 "built/tmp/cppBison.yxx.c" +#line 6558 "built/tmp/cppBison.yxx.c" + break; + + case 272: /* parameter_pack_identifier: KW_RESTRICT parameter_pack_identifier */ +#line 2378 "dtool/src/cppparser/cppBison.yxx" +{ + (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); + (yyval.u.inst_ident)->add_modifier(IIT_restrict); +} +#line 6567 "built/tmp/cppBison.yxx.c" break; case 273: /* parameter_pack_identifier: '*' optional_attributes parameter_pack_identifier */ -#line 2374 "dtool/src/cppparser/cppBison.yxx" +#line 2383 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); (yyval.u.inst_ident)->add_modifier(IIT_pointer, (yyvsp[-1].attr_list)); } -#line 6606 "built/tmp/cppBison.yxx.c" +#line 6576 "built/tmp/cppBison.yxx.c" break; case 274: /* parameter_pack_identifier: '&' optional_attributes parameter_pack_identifier */ -#line 2379 "dtool/src/cppparser/cppBison.yxx" +#line 2388 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); (yyval.u.inst_ident)->add_modifier(IIT_reference, (yyvsp[-1].attr_list)); } -#line 6615 "built/tmp/cppBison.yxx.c" +#line 6585 "built/tmp/cppBison.yxx.c" break; case 275: /* parameter_pack_identifier: ANDAND optional_attributes parameter_pack_identifier */ -#line 2384 "dtool/src/cppparser/cppBison.yxx" +#line 2393 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); (yyval.u.inst_ident)->add_modifier(IIT_rvalue_reference, (yyvsp[-1].attr_list)); } -#line 6624 "built/tmp/cppBison.yxx.c" +#line 6594 "built/tmp/cppBison.yxx.c" break; case 276: /* parameter_pack_identifier: SCOPING '*' optional_attributes parameter_pack_identifier */ -#line 2389 "dtool/src/cppparser/cppBison.yxx" +#line 2398 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); (yyval.u.inst_ident)->add_scoped_pointer_modifier((yyvsp[-3].u.identifier), (yyvsp[-1].attr_list)); } -#line 6633 "built/tmp/cppBison.yxx.c" +#line 6603 "built/tmp/cppBison.yxx.c" break; case 277: /* parameter_pack_identifier: parameter_pack_identifier '[' optional_const_expr ']' optional_attributes */ -#line 2394 "dtool/src/cppparser/cppBison.yxx" +#line 2403 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = (yyvsp[-4].u.inst_ident); (yyval.u.inst_ident)->add_array_modifier((yyvsp[-2].u.expr), (yyvsp[0].attr_list)); } -#line 6642 "built/tmp/cppBison.yxx.c" +#line 6612 "built/tmp/cppBison.yxx.c" break; case 278: /* parameter_pack_identifier: '(' parameter_pack_identifier ')' '(' function_parameter_list ')' function_post optional_attributes */ -#line 2399 "dtool/src/cppparser/cppBison.yxx" +#line 2408 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = (yyvsp[-6].u.inst_ident); (yyval.u.inst_ident)->add_modifier(IIT_paren); (yyval.u.inst_ident)->add_func_modifier((yyvsp[-3].u.param_list), (yyvsp[-1].u.integer), nullptr, (yyvsp[0].attr_list)); } -#line 6652 "built/tmp/cppBison.yxx.c" +#line 6622 "built/tmp/cppBison.yxx.c" break; case 279: /* parameter_pack_identifier: '(' parameter_pack_identifier ')' */ -#line 2405 "dtool/src/cppparser/cppBison.yxx" +#line 2414 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = (yyvsp[-1].u.inst_ident); (yyval.u.inst_ident)->add_modifier(IIT_paren); } -#line 6661 "built/tmp/cppBison.yxx.c" +#line 6631 "built/tmp/cppBison.yxx.c" break; case 280: /* not_paren_empty_instance_identifier: empty */ -#line 2413 "dtool/src/cppparser/cppBison.yxx" +#line 2422 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = new CPPInstanceIdentifier(nullptr); } -#line 6669 "built/tmp/cppBison.yxx.c" +#line 6639 "built/tmp/cppBison.yxx.c" break; case 281: /* not_paren_empty_instance_identifier: ELLIPSIS */ -#line 2417 "dtool/src/cppparser/cppBison.yxx" +#line 2426 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = new CPPInstanceIdentifier(nullptr); (yyval.u.inst_ident)->_packed = true; } -#line 6678 "built/tmp/cppBison.yxx.c" +#line 6648 "built/tmp/cppBison.yxx.c" break; case 282: /* not_paren_empty_instance_identifier: ELLIPSIS name optional_attributes */ -#line 2422 "dtool/src/cppparser/cppBison.yxx" +#line 2431 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = new CPPInstanceIdentifier((yyvsp[-1].u.identifier), (yyvsp[0].attr_list)); (yyval.u.inst_ident)->_packed = true; } -#line 6687 "built/tmp/cppBison.yxx.c" +#line 6657 "built/tmp/cppBison.yxx.c" break; case 283: /* not_paren_empty_instance_identifier: KW_CONST not_paren_empty_instance_identifier */ -#line 2427 "dtool/src/cppparser/cppBison.yxx" +#line 2436 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); (yyval.u.inst_ident)->add_modifier(IIT_const); } -#line 6696 "built/tmp/cppBison.yxx.c" +#line 6666 "built/tmp/cppBison.yxx.c" break; case 284: /* not_paren_empty_instance_identifier: KW_VOLATILE not_paren_empty_instance_identifier */ -#line 2432 "dtool/src/cppparser/cppBison.yxx" +#line 2441 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); (yyval.u.inst_ident)->add_modifier(IIT_volatile); } -#line 6705 "built/tmp/cppBison.yxx.c" +#line 6675 "built/tmp/cppBison.yxx.c" break; - case 285: /* not_paren_empty_instance_identifier: '*' optional_attributes not_paren_empty_instance_identifier */ -#line 2437 "dtool/src/cppparser/cppBison.yxx" + case 285: /* not_paren_empty_instance_identifier: KW_RESTRICT not_paren_empty_instance_identifier */ +#line 2446 "dtool/src/cppparser/cppBison.yxx" +{ + (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); + (yyval.u.inst_ident)->add_modifier(IIT_restrict); +} +#line 6684 "built/tmp/cppBison.yxx.c" + break; + + case 286: /* not_paren_empty_instance_identifier: '*' optional_attributes not_paren_empty_instance_identifier */ +#line 2451 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); (yyval.u.inst_ident)->add_modifier(IIT_pointer, (yyvsp[-1].attr_list)); } -#line 6714 "built/tmp/cppBison.yxx.c" +#line 6693 "built/tmp/cppBison.yxx.c" break; - case 286: /* not_paren_empty_instance_identifier: '&' optional_attributes not_paren_empty_instance_identifier */ -#line 2442 "dtool/src/cppparser/cppBison.yxx" + case 287: /* not_paren_empty_instance_identifier: '&' optional_attributes not_paren_empty_instance_identifier */ +#line 2456 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); (yyval.u.inst_ident)->add_modifier(IIT_reference, (yyvsp[-1].attr_list)); } -#line 6723 "built/tmp/cppBison.yxx.c" +#line 6702 "built/tmp/cppBison.yxx.c" break; - case 287: /* not_paren_empty_instance_identifier: ANDAND optional_attributes not_paren_empty_instance_identifier */ -#line 2447 "dtool/src/cppparser/cppBison.yxx" + case 288: /* not_paren_empty_instance_identifier: ANDAND optional_attributes not_paren_empty_instance_identifier */ +#line 2461 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); (yyval.u.inst_ident)->add_modifier(IIT_rvalue_reference, (yyvsp[-1].attr_list)); } -#line 6732 "built/tmp/cppBison.yxx.c" +#line 6711 "built/tmp/cppBison.yxx.c" break; - case 288: /* not_paren_empty_instance_identifier: SCOPING '*' optional_attributes not_paren_empty_instance_identifier */ -#line 2452 "dtool/src/cppparser/cppBison.yxx" + case 289: /* not_paren_empty_instance_identifier: SCOPING '*' optional_attributes not_paren_empty_instance_identifier */ +#line 2466 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); (yyval.u.inst_ident)->add_scoped_pointer_modifier((yyvsp[-3].u.identifier), (yyvsp[-1].attr_list)); } -#line 6741 "built/tmp/cppBison.yxx.c" +#line 6720 "built/tmp/cppBison.yxx.c" break; - case 289: /* not_paren_empty_instance_identifier: not_paren_empty_instance_identifier '[' optional_const_expr ']' optional_attributes */ -#line 2457 "dtool/src/cppparser/cppBison.yxx" + case 290: /* not_paren_empty_instance_identifier: not_paren_empty_instance_identifier '[' optional_const_expr ']' optional_attributes */ +#line 2471 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = (yyvsp[-4].u.inst_ident); (yyval.u.inst_ident)->add_array_modifier((yyvsp[-2].u.expr), (yyvsp[0].attr_list)); } -#line 6750 "built/tmp/cppBison.yxx.c" +#line 6729 "built/tmp/cppBison.yxx.c" break; - case 290: /* empty_instance_identifier: empty */ -#line 2465 "dtool/src/cppparser/cppBison.yxx" + case 291: /* empty_instance_identifier: empty */ +#line 2479 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = new CPPInstanceIdentifier(nullptr); } -#line 6758 "built/tmp/cppBison.yxx.c" +#line 6737 "built/tmp/cppBison.yxx.c" break; - case 291: /* empty_instance_identifier: ELLIPSIS */ -#line 2469 "dtool/src/cppparser/cppBison.yxx" + case 292: /* empty_instance_identifier: ELLIPSIS */ +#line 2483 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = new CPPInstanceIdentifier(nullptr); (yyval.u.inst_ident)->_packed = true; } -#line 6767 "built/tmp/cppBison.yxx.c" +#line 6746 "built/tmp/cppBison.yxx.c" break; - case 292: /* empty_instance_identifier: ELLIPSIS name optional_attributes */ -#line 2474 "dtool/src/cppparser/cppBison.yxx" + case 293: /* empty_instance_identifier: ELLIPSIS name optional_attributes */ +#line 2488 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = new CPPInstanceIdentifier((yyvsp[-1].u.identifier), (yyvsp[0].attr_list)); (yyval.u.inst_ident)->_packed = true; } -#line 6776 "built/tmp/cppBison.yxx.c" +#line 6755 "built/tmp/cppBison.yxx.c" break; - case 293: /* empty_instance_identifier: KW_CONST empty_instance_identifier */ -#line 2479 "dtool/src/cppparser/cppBison.yxx" + case 294: /* empty_instance_identifier: KW_CONST empty_instance_identifier */ +#line 2493 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); (yyval.u.inst_ident)->add_modifier(IIT_const); } -#line 6785 "built/tmp/cppBison.yxx.c" +#line 6764 "built/tmp/cppBison.yxx.c" break; - case 294: /* empty_instance_identifier: KW_VOLATILE empty_instance_identifier */ -#line 2484 "dtool/src/cppparser/cppBison.yxx" + case 295: /* empty_instance_identifier: KW_VOLATILE empty_instance_identifier */ +#line 2498 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); (yyval.u.inst_ident)->add_modifier(IIT_volatile); } -#line 6794 "built/tmp/cppBison.yxx.c" +#line 6773 "built/tmp/cppBison.yxx.c" break; - case 295: /* empty_instance_identifier: '*' optional_attributes not_paren_empty_instance_identifier */ -#line 2489 "dtool/src/cppparser/cppBison.yxx" + case 296: /* empty_instance_identifier: KW_RESTRICT empty_instance_identifier */ +#line 2503 "dtool/src/cppparser/cppBison.yxx" +{ + (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); + (yyval.u.inst_ident)->add_modifier(IIT_restrict); +} +#line 6782 "built/tmp/cppBison.yxx.c" + break; + + case 297: /* empty_instance_identifier: '*' optional_attributes not_paren_empty_instance_identifier */ +#line 2508 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); (yyval.u.inst_ident)->add_modifier(IIT_pointer, (yyvsp[-1].attr_list)); } -#line 6803 "built/tmp/cppBison.yxx.c" +#line 6791 "built/tmp/cppBison.yxx.c" break; - case 296: /* empty_instance_identifier: '&' optional_attributes not_paren_empty_instance_identifier */ -#line 2494 "dtool/src/cppparser/cppBison.yxx" + case 298: /* empty_instance_identifier: '&' optional_attributes not_paren_empty_instance_identifier */ +#line 2513 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); (yyval.u.inst_ident)->add_modifier(IIT_reference, (yyvsp[-1].attr_list)); } -#line 6812 "built/tmp/cppBison.yxx.c" +#line 6800 "built/tmp/cppBison.yxx.c" break; - case 297: /* empty_instance_identifier: ANDAND optional_attributes not_paren_empty_instance_identifier */ -#line 2499 "dtool/src/cppparser/cppBison.yxx" + case 299: /* empty_instance_identifier: ANDAND optional_attributes not_paren_empty_instance_identifier */ +#line 2518 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); (yyval.u.inst_ident)->add_modifier(IIT_rvalue_reference, (yyvsp[-1].attr_list)); } -#line 6821 "built/tmp/cppBison.yxx.c" +#line 6809 "built/tmp/cppBison.yxx.c" break; - case 298: /* empty_instance_identifier: SCOPING '*' optional_attributes not_paren_empty_instance_identifier */ -#line 2504 "dtool/src/cppparser/cppBison.yxx" + case 300: /* empty_instance_identifier: SCOPING '*' optional_attributes not_paren_empty_instance_identifier */ +#line 2523 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = (yyvsp[0].u.inst_ident); (yyval.u.inst_ident)->add_scoped_pointer_modifier((yyvsp[-3].u.identifier), (yyvsp[-1].attr_list)); } -#line 6830 "built/tmp/cppBison.yxx.c" +#line 6818 "built/tmp/cppBison.yxx.c" break; - case 299: /* empty_instance_identifier: not_paren_empty_instance_identifier '[' optional_const_expr ']' optional_attributes */ -#line 2509 "dtool/src/cppparser/cppBison.yxx" + case 301: /* empty_instance_identifier: not_paren_empty_instance_identifier '[' optional_const_expr ']' optional_attributes */ +#line 2528 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = (yyvsp[-4].u.inst_ident); (yyval.u.inst_ident)->add_array_modifier((yyvsp[-2].u.expr), (yyvsp[0].attr_list)); } -#line 6839 "built/tmp/cppBison.yxx.c" +#line 6827 "built/tmp/cppBison.yxx.c" break; - case 300: /* empty_instance_identifier: '(' function_parameter_list ')' function_post optional_attributes maybe_trailing_return_type */ -#line 2514 "dtool/src/cppparser/cppBison.yxx" + case 302: /* empty_instance_identifier: '(' function_parameter_list ')' function_post optional_attributes maybe_trailing_return_type */ +#line 2533 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = new CPPInstanceIdentifier(nullptr); (yyval.u.inst_ident)->add_modifier(IIT_paren); (yyval.u.inst_ident)->add_func_modifier((yyvsp[-4].u.param_list), (yyvsp[-2].u.integer), (yyvsp[0].u.type), (yyvsp[-1].attr_list)); } -#line 6849 "built/tmp/cppBison.yxx.c" +#line 6837 "built/tmp/cppBison.yxx.c" break; - case 301: /* empty_instance_identifier: '(' '*' optional_attributes not_paren_empty_instance_identifier ')' '(' function_parameter_list ')' function_post optional_attributes maybe_trailing_return_type */ -#line 2520 "dtool/src/cppparser/cppBison.yxx" + case 303: /* empty_instance_identifier: '(' '*' optional_attributes not_paren_empty_instance_identifier ')' '(' function_parameter_list ')' function_post optional_attributes maybe_trailing_return_type */ +#line 2539 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = (yyvsp[-7].u.inst_ident); (yyval.u.inst_ident)->add_modifier(IIT_pointer, (yyvsp[-8].attr_list)); (yyval.u.inst_ident)->add_modifier(IIT_paren); (yyval.u.inst_ident)->add_func_modifier((yyvsp[-4].u.param_list), (yyvsp[-2].u.integer), (yyvsp[0].u.type), (yyvsp[-1].attr_list)); } -#line 6860 "built/tmp/cppBison.yxx.c" +#line 6848 "built/tmp/cppBison.yxx.c" break; - case 302: /* empty_instance_identifier: '(' '&' optional_attributes not_paren_empty_instance_identifier ')' '(' function_parameter_list ')' function_post optional_attributes maybe_trailing_return_type */ -#line 2527 "dtool/src/cppparser/cppBison.yxx" + case 304: /* empty_instance_identifier: '(' '&' optional_attributes not_paren_empty_instance_identifier ')' '(' function_parameter_list ')' function_post optional_attributes maybe_trailing_return_type */ +#line 2546 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = (yyvsp[-7].u.inst_ident); (yyval.u.inst_ident)->add_modifier(IIT_reference, (yyvsp[-8].attr_list)); (yyval.u.inst_ident)->add_modifier(IIT_paren); (yyval.u.inst_ident)->add_func_modifier((yyvsp[-4].u.param_list), (yyvsp[-2].u.integer), (yyvsp[0].u.type), (yyvsp[-1].attr_list)); } -#line 6871 "built/tmp/cppBison.yxx.c" +#line 6859 "built/tmp/cppBison.yxx.c" break; - case 303: /* empty_instance_identifier: '(' ANDAND optional_attributes not_paren_empty_instance_identifier ')' '(' function_parameter_list ')' function_post optional_attributes maybe_trailing_return_type */ -#line 2534 "dtool/src/cppparser/cppBison.yxx" + case 305: /* empty_instance_identifier: '(' ANDAND optional_attributes not_paren_empty_instance_identifier ')' '(' function_parameter_list ')' function_post optional_attributes maybe_trailing_return_type */ +#line 2553 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.inst_ident) = (yyvsp[-7].u.inst_ident); (yyval.u.inst_ident)->add_modifier(IIT_rvalue_reference, (yyvsp[-8].attr_list)); (yyval.u.inst_ident)->add_modifier(IIT_paren); (yyval.u.inst_ident)->add_func_modifier((yyvsp[-4].u.param_list), (yyvsp[-2].u.integer), (yyvsp[0].u.type), (yyvsp[-1].attr_list)); } -#line 6882 "built/tmp/cppBison.yxx.c" +#line 6870 "built/tmp/cppBison.yxx.c" break; - case 304: /* type: simple_type */ -#line 2544 "dtool/src/cppparser/cppBison.yxx" + case 306: /* type: simple_type */ +#line 2563 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.type) = CPPType::new_type((yyvsp[0].u.simple_type)); } -#line 6890 "built/tmp/cppBison.yxx.c" +#line 6878 "built/tmp/cppBison.yxx.c" break; - case 305: /* type: TYPENAME_IDENTIFIER */ -#line 2548 "dtool/src/cppparser/cppBison.yxx" + case 307: /* type: TYPENAME_IDENTIFIER */ +#line 2567 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.type) = (yyvsp[0].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); if ((yyval.u.type) == nullptr) { @@ -6898,43 +6886,43 @@ yyreduce: } assert((yyval.u.type) != nullptr); } -#line 6902 "built/tmp/cppBison.yxx.c" +#line 6890 "built/tmp/cppBison.yxx.c" break; - case 306: /* type: KW_TYPENAME name */ -#line 2556 "dtool/src/cppparser/cppBison.yxx" + case 308: /* type: KW_TYPENAME name */ +#line 2575 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.type) = CPPType::new_type(new CPPTBDType((yyvsp[0].u.identifier))); } -#line 6910 "built/tmp/cppBison.yxx.c" +#line 6898 "built/tmp/cppBison.yxx.c" break; - case 307: /* type: anonymous_struct */ -#line 2560 "dtool/src/cppparser/cppBison.yxx" + case 309: /* type: anonymous_struct */ +#line 2579 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.type) = CPPType::new_type((yyvsp[0].u.struct_type)); } -#line 6918 "built/tmp/cppBison.yxx.c" +#line 6906 "built/tmp/cppBison.yxx.c" break; - case 308: /* type: named_struct */ -#line 2564 "dtool/src/cppparser/cppBison.yxx" + case 310: /* type: named_struct */ +#line 2583 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.type) = CPPType::new_type((yyvsp[0].u.struct_type)); } -#line 6926 "built/tmp/cppBison.yxx.c" +#line 6914 "built/tmp/cppBison.yxx.c" break; - case 309: /* type: enum */ -#line 2568 "dtool/src/cppparser/cppBison.yxx" + case 311: /* type: enum */ +#line 2587 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.type) = CPPType::new_type((yyvsp[0].u.enum_type)); } -#line 6934 "built/tmp/cppBison.yxx.c" +#line 6922 "built/tmp/cppBison.yxx.c" break; - case 310: /* type: struct_keyword optional_attributes name */ -#line 2572 "dtool/src/cppparser/cppBison.yxx" + case 312: /* type: struct_keyword optional_attributes name */ +#line 2591 "dtool/src/cppparser/cppBison.yxx" { CPPType *type = (yyvsp[0].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); if (type != nullptr) { @@ -6950,11 +6938,11 @@ yyreduce: (yyval.u.type) = et; } } -#line 6954 "built/tmp/cppBison.yxx.c" +#line 6942 "built/tmp/cppBison.yxx.c" break; - case 311: /* type: enum_keyword optional_attributes name_no_final ':' enum_element_type */ -#line 2588 "dtool/src/cppparser/cppBison.yxx" + case 313: /* type: enum_keyword optional_attributes name_no_final ':' enum_element_type */ +#line 2607 "dtool/src/cppparser/cppBison.yxx" { CPPType *type = (yyvsp[-2].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); if (type != nullptr) { @@ -6970,11 +6958,11 @@ yyreduce: (yyval.u.type) = et; } } -#line 6974 "built/tmp/cppBison.yxx.c" +#line 6962 "built/tmp/cppBison.yxx.c" break; - case 312: /* type: KW_DECLTYPE '(' const_expr ')' */ -#line 2604 "dtool/src/cppparser/cppBison.yxx" + case 314: /* type: KW_DECLTYPE '(' const_expr ')' */ +#line 2623 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.type) = (yyvsp[-1].u.expr)->determine_type(); if ((yyval.u.type) == nullptr) { @@ -6983,19 +6971,19 @@ yyreduce: yyerror("could not determine type of " + str.str(), (yylsp[-1])); } } -#line 6987 "built/tmp/cppBison.yxx.c" +#line 6975 "built/tmp/cppBison.yxx.c" break; - case 313: /* type: KW_DECLTYPE '(' KW_AUTO ')' */ -#line 2613 "dtool/src/cppparser/cppBison.yxx" + case 315: /* type: KW_DECLTYPE '(' KW_AUTO ')' */ +#line 2632 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.type) = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_auto)); } -#line 6995 "built/tmp/cppBison.yxx.c" +#line 6983 "built/tmp/cppBison.yxx.c" break; - case 314: /* type: KW_UNDERLYING_TYPE '(' full_type ')' */ -#line 2617 "dtool/src/cppparser/cppBison.yxx" + case 316: /* type: KW_UNDERLYING_TYPE '(' full_type ')' */ +#line 2636 "dtool/src/cppparser/cppBison.yxx" { CPPEnumType *enum_type = (yyvsp[-1].u.type)->as_enum_type(); if (enum_type == nullptr) { @@ -7005,19 +6993,27 @@ yyreduce: (yyval.u.type) = enum_type->get_underlying_type(); } } -#line 7009 "built/tmp/cppBison.yxx.c" +#line 6997 "built/tmp/cppBison.yxx.c" break; - case 315: /* type: KW_AUTO */ -#line 2627 "dtool/src/cppparser/cppBison.yxx" + case 317: /* type: KW_AUTO */ +#line 2646 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.type) = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_auto)); } -#line 7017 "built/tmp/cppBison.yxx.c" +#line 7005 "built/tmp/cppBison.yxx.c" break; - case 316: /* type_pack: TYPEPACK_IDENTIFIER */ -#line 2634 "dtool/src/cppparser/cppBison.yxx" + case 318: /* type: KW_BUILTIN_VA_LIST */ +#line 2650 "dtool/src/cppparser/cppBison.yxx" +{ + (yyval.u.type) = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_va_list)); +} +#line 7013 "built/tmp/cppBison.yxx.c" + break; + + case 319: /* type_pack: TYPEPACK_IDENTIFIER */ +#line 2657 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.type) = (yyvsp[0].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); if ((yyval.u.type) == nullptr) { @@ -7025,19 +7021,19 @@ yyreduce: } assert((yyval.u.type) != nullptr); } -#line 7029 "built/tmp/cppBison.yxx.c" +#line 7025 "built/tmp/cppBison.yxx.c" break; - case 317: /* type_decl: simple_type */ -#line 2645 "dtool/src/cppparser/cppBison.yxx" + case 320: /* type_decl: simple_type */ +#line 2668 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.decl) = CPPType::new_type((yyvsp[0].u.simple_type)); } -#line 7037 "built/tmp/cppBison.yxx.c" +#line 7033 "built/tmp/cppBison.yxx.c" break; - case 318: /* type_decl: TYPENAME_IDENTIFIER */ -#line 2649 "dtool/src/cppparser/cppBison.yxx" + case 321: /* type_decl: TYPENAME_IDENTIFIER */ +#line 2672 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.decl) = (yyvsp[0].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); if ((yyval.u.decl) == nullptr) { @@ -7045,43 +7041,43 @@ yyreduce: } assert((yyval.u.decl) != nullptr); } -#line 7049 "built/tmp/cppBison.yxx.c" +#line 7045 "built/tmp/cppBison.yxx.c" break; - case 319: /* type_decl: KW_TYPENAME name */ -#line 2657 "dtool/src/cppparser/cppBison.yxx" + case 322: /* type_decl: KW_TYPENAME name */ +#line 2680 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.decl) = CPPType::new_type(new CPPTBDType((yyvsp[0].u.identifier))); } -#line 7057 "built/tmp/cppBison.yxx.c" +#line 7053 "built/tmp/cppBison.yxx.c" break; - case 320: /* type_decl: anonymous_struct */ -#line 2661 "dtool/src/cppparser/cppBison.yxx" + case 323: /* type_decl: anonymous_struct */ +#line 2684 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.decl) = CPPType::new_type((yyvsp[0].u.struct_type)); } -#line 7065 "built/tmp/cppBison.yxx.c" +#line 7061 "built/tmp/cppBison.yxx.c" break; - case 321: /* type_decl: named_struct */ -#line 2665 "dtool/src/cppparser/cppBison.yxx" + case 324: /* type_decl: named_struct */ +#line 2688 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.decl) = new CPPTypeDeclaration(CPPType::new_type((yyvsp[0].u.struct_type))); } -#line 7073 "built/tmp/cppBison.yxx.c" +#line 7069 "built/tmp/cppBison.yxx.c" break; - case 322: /* type_decl: enum */ -#line 2669 "dtool/src/cppparser/cppBison.yxx" + case 325: /* type_decl: enum */ +#line 2692 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.decl) = new CPPTypeDeclaration(CPPType::new_type((yyvsp[0].u.enum_type))); } -#line 7081 "built/tmp/cppBison.yxx.c" +#line 7077 "built/tmp/cppBison.yxx.c" break; - case 323: /* type_decl: struct_keyword optional_attributes name */ -#line 2673 "dtool/src/cppparser/cppBison.yxx" + case 326: /* type_decl: struct_keyword optional_attributes name */ +#line 2696 "dtool/src/cppparser/cppBison.yxx" { CPPType *type = (yyvsp[0].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); if (type != nullptr) { @@ -7097,11 +7093,11 @@ yyreduce: (yyval.u.decl) = et; } } -#line 7101 "built/tmp/cppBison.yxx.c" +#line 7097 "built/tmp/cppBison.yxx.c" break; - case 324: /* type_decl: enum_keyword optional_attributes name_no_final ':' enum_element_type */ -#line 2689 "dtool/src/cppparser/cppBison.yxx" + case 327: /* type_decl: enum_keyword optional_attributes name_no_final ':' enum_element_type */ +#line 2712 "dtool/src/cppparser/cppBison.yxx" { CPPType *type = (yyvsp[-2].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); if (type != nullptr) { @@ -7117,11 +7113,11 @@ yyreduce: (yyval.u.decl) = et; } } -#line 7121 "built/tmp/cppBison.yxx.c" +#line 7117 "built/tmp/cppBison.yxx.c" break; - case 325: /* type_decl: enum_keyword optional_attributes name */ -#line 2705 "dtool/src/cppparser/cppBison.yxx" + case 328: /* type_decl: enum_keyword optional_attributes name */ +#line 2728 "dtool/src/cppparser/cppBison.yxx" { yywarning(string("C++ does not permit forward declaration of untyped enum ") + (yyvsp[0].u.identifier)->get_fully_scoped_name(), (yylsp[-2])); @@ -7139,11 +7135,11 @@ yyreduce: (yyval.u.decl) = et; } } -#line 7143 "built/tmp/cppBison.yxx.c" +#line 7139 "built/tmp/cppBison.yxx.c" break; - case 326: /* type_decl: KW_DECLTYPE '(' const_expr ')' */ -#line 2723 "dtool/src/cppparser/cppBison.yxx" + case 329: /* type_decl: KW_DECLTYPE '(' const_expr ')' */ +#line 2746 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.decl) = (yyvsp[-1].u.expr)->determine_type(); if ((yyval.u.decl) == nullptr) { @@ -7152,19 +7148,19 @@ yyreduce: yyerror("could not determine type of " + str.str(), (yylsp[-1])); } } -#line 7156 "built/tmp/cppBison.yxx.c" +#line 7152 "built/tmp/cppBison.yxx.c" break; - case 327: /* type_decl: KW_DECLTYPE '(' KW_AUTO ')' */ -#line 2732 "dtool/src/cppparser/cppBison.yxx" + case 330: /* type_decl: KW_DECLTYPE '(' KW_AUTO ')' */ +#line 2755 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.decl) = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_auto)); } -#line 7164 "built/tmp/cppBison.yxx.c" +#line 7160 "built/tmp/cppBison.yxx.c" break; - case 328: /* type_decl: KW_UNDERLYING_TYPE '(' full_type ')' */ -#line 2736 "dtool/src/cppparser/cppBison.yxx" + case 331: /* type_decl: KW_UNDERLYING_TYPE '(' full_type ')' */ +#line 2759 "dtool/src/cppparser/cppBison.yxx" { CPPEnumType *enum_type = (yyvsp[-1].u.type)->as_enum_type(); if (enum_type == nullptr) { @@ -7174,27 +7170,35 @@ yyreduce: (yyval.u.decl) = enum_type->get_underlying_type(); } } -#line 7178 "built/tmp/cppBison.yxx.c" +#line 7174 "built/tmp/cppBison.yxx.c" break; - case 329: /* type_decl: KW_AUTO */ -#line 2746 "dtool/src/cppparser/cppBison.yxx" + case 332: /* type_decl: KW_AUTO */ +#line 2769 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.decl) = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_auto)); } -#line 7186 "built/tmp/cppBison.yxx.c" +#line 7182 "built/tmp/cppBison.yxx.c" break; - case 330: /* predefined_type: simple_type */ -#line 2753 "dtool/src/cppparser/cppBison.yxx" + case 333: /* type_decl: KW_BUILTIN_VA_LIST */ +#line 2773 "dtool/src/cppparser/cppBison.yxx" +{ + (yyval.u.decl) = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_va_list)); +} +#line 7190 "built/tmp/cppBison.yxx.c" + break; + + case 334: /* predefined_type: simple_type */ +#line 2780 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.type) = CPPType::new_type((yyvsp[0].u.simple_type)); } -#line 7194 "built/tmp/cppBison.yxx.c" +#line 7198 "built/tmp/cppBison.yxx.c" break; - case 331: /* predefined_type: TYPENAME_IDENTIFIER */ -#line 2757 "dtool/src/cppparser/cppBison.yxx" + case 335: /* predefined_type: TYPENAME_IDENTIFIER */ +#line 2784 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.type) = (yyvsp[0].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); if ((yyval.u.type) == nullptr) { @@ -7202,19 +7206,19 @@ yyreduce: } assert((yyval.u.type) != nullptr); } -#line 7206 "built/tmp/cppBison.yxx.c" +#line 7210 "built/tmp/cppBison.yxx.c" break; - case 332: /* predefined_type: KW_TYPENAME name */ -#line 2765 "dtool/src/cppparser/cppBison.yxx" + case 336: /* predefined_type: KW_TYPENAME name */ +#line 2792 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.type) = CPPType::new_type(new CPPTBDType((yyvsp[0].u.identifier))); } -#line 7214 "built/tmp/cppBison.yxx.c" +#line 7218 "built/tmp/cppBison.yxx.c" break; - case 333: /* predefined_type: struct_keyword optional_attributes name */ -#line 2769 "dtool/src/cppparser/cppBison.yxx" + case 337: /* predefined_type: struct_keyword optional_attributes name */ +#line 2796 "dtool/src/cppparser/cppBison.yxx" { CPPType *type = (yyvsp[0].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); if (type != nullptr) { @@ -7230,11 +7234,11 @@ yyreduce: (yyval.u.type) = et; } } -#line 7234 "built/tmp/cppBison.yxx.c" +#line 7238 "built/tmp/cppBison.yxx.c" break; - case 334: /* predefined_type: enum_keyword optional_attributes name */ -#line 2785 "dtool/src/cppparser/cppBison.yxx" + case 338: /* predefined_type: enum_keyword optional_attributes name */ +#line 2812 "dtool/src/cppparser/cppBison.yxx" { CPPType *type = (yyvsp[0].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); if (type != nullptr) { @@ -7250,11 +7254,11 @@ yyreduce: (yyval.u.type) = et; } } -#line 7254 "built/tmp/cppBison.yxx.c" +#line 7258 "built/tmp/cppBison.yxx.c" break; - case 335: /* predefined_type: KW_DECLTYPE '(' const_expr ')' */ -#line 2801 "dtool/src/cppparser/cppBison.yxx" + case 339: /* predefined_type: KW_DECLTYPE '(' const_expr ')' */ +#line 2828 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.type) = (yyvsp[-1].u.expr)->determine_type(); if ((yyval.u.type) == nullptr) { @@ -7263,11 +7267,11 @@ yyreduce: yyerror("could not determine type of " + str.str(), (yylsp[-1])); } } -#line 7267 "built/tmp/cppBison.yxx.c" +#line 7271 "built/tmp/cppBison.yxx.c" break; - case 336: /* predefined_type: KW_UNDERLYING_TYPE '(' full_type ')' */ -#line 2810 "dtool/src/cppparser/cppBison.yxx" + case 340: /* predefined_type: KW_UNDERLYING_TYPE '(' full_type ')' */ +#line 2837 "dtool/src/cppparser/cppBison.yxx" { CPPEnumType *enum_type = (yyvsp[-1].u.type)->as_enum_type(); if (enum_type == nullptr) { @@ -7277,71 +7281,79 @@ yyreduce: (yyval.u.type) = enum_type->get_underlying_type(); } } -#line 7281 "built/tmp/cppBison.yxx.c" +#line 7285 "built/tmp/cppBison.yxx.c" break; - case 337: /* predefined_type: KW_AUTO */ -#line 2820 "dtool/src/cppparser/cppBison.yxx" + case 341: /* predefined_type: KW_AUTO */ +#line 2847 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.type) = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_auto)); } -#line 7289 "built/tmp/cppBison.yxx.c" +#line 7293 "built/tmp/cppBison.yxx.c" break; - case 338: /* var_type_decl: type_decl */ -#line 2827 "dtool/src/cppparser/cppBison.yxx" + case 342: /* predefined_type: KW_BUILTIN_VA_LIST */ +#line 2851 "dtool/src/cppparser/cppBison.yxx" +{ + (yyval.u.type) = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_va_list)); +} +#line 7301 "built/tmp/cppBison.yxx.c" + break; + + case 343: /* var_type_decl: type_decl */ +#line 2858 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.decl) = (yyvsp[0].u.decl); } -#line 7297 "built/tmp/cppBison.yxx.c" +#line 7309 "built/tmp/cppBison.yxx.c" break; - case 339: /* var_type_decl: IDENTIFIER */ -#line 2831 "dtool/src/cppparser/cppBison.yxx" + case 344: /* var_type_decl: IDENTIFIER */ +#line 2862 "dtool/src/cppparser/cppBison.yxx" { yyerror(string("unknown type '") + (yyvsp[0].u.identifier)->get_fully_scoped_name() + "'", (yylsp[0])); (yyval.u.decl) = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_unknown)); } -#line 7307 "built/tmp/cppBison.yxx.c" +#line 7319 "built/tmp/cppBison.yxx.c" break; - case 340: /* full_type: type empty_instance_identifier */ -#line 2839 "dtool/src/cppparser/cppBison.yxx" + case 345: /* full_type: type empty_instance_identifier */ +#line 2870 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.type) = (yyvsp[0].u.inst_ident)->unroll_type((yyvsp[-1].u.type)); } -#line 7315 "built/tmp/cppBison.yxx.c" +#line 7327 "built/tmp/cppBison.yxx.c" break; - case 341: /* full_type: KW_CONST type empty_instance_identifier */ -#line 2843 "dtool/src/cppparser/cppBison.yxx" + case 346: /* full_type: KW_CONST type empty_instance_identifier */ +#line 2874 "dtool/src/cppparser/cppBison.yxx" { (yyvsp[0].u.inst_ident)->add_modifier(IIT_const); (yyval.u.type) = (yyvsp[0].u.inst_ident)->unroll_type((yyvsp[-1].u.type)); } -#line 7324 "built/tmp/cppBison.yxx.c" +#line 7336 "built/tmp/cppBison.yxx.c" break; - case 342: /* full_type: type_pack empty_instance_identifier */ -#line 2848 "dtool/src/cppparser/cppBison.yxx" + case 347: /* full_type: type_pack empty_instance_identifier */ +#line 2879 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.type) = (yyvsp[0].u.inst_ident)->unroll_type((yyvsp[-1].u.type)); } -#line 7332 "built/tmp/cppBison.yxx.c" +#line 7344 "built/tmp/cppBison.yxx.c" break; - case 343: /* full_type: KW_CONST type_pack empty_instance_identifier */ -#line 2852 "dtool/src/cppparser/cppBison.yxx" + case 348: /* full_type: KW_CONST type_pack empty_instance_identifier */ +#line 2883 "dtool/src/cppparser/cppBison.yxx" { (yyvsp[0].u.inst_ident)->add_modifier(IIT_const); (yyval.u.type) = (yyvsp[0].u.inst_ident)->unroll_type((yyvsp[-1].u.type)); } -#line 7341 "built/tmp/cppBison.yxx.c" +#line 7353 "built/tmp/cppBison.yxx.c" break; - case 344: /* $@17: %empty */ -#line 2860 "dtool/src/cppparser/cppBison.yxx" + case 349: /* $@17: %empty */ +#line 2891 "dtool/src/cppparser/cppBison.yxx" { CPPVisibility starting_vis = ((yyvsp[-2].u.extension_enum) == CPPExtensionType::T_class) ? V_private : V_public; @@ -7355,22 +7367,22 @@ yyreduce: push_scope(new_scope); push_struct(st); } -#line 7359 "built/tmp/cppBison.yxx.c" +#line 7371 "built/tmp/cppBison.yxx.c" break; - case 345: /* anonymous_struct: struct_keyword optional_attributes '{' $@17 cpp '}' */ -#line 2874 "dtool/src/cppparser/cppBison.yxx" + case 350: /* anonymous_struct: struct_keyword optional_attributes '{' $@17 cpp '}' */ +#line 2905 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.struct_type) = current_struct; current_struct->_incomplete = false; pop_struct(); pop_scope(); } -#line 7370 "built/tmp/cppBison.yxx.c" +#line 7382 "built/tmp/cppBison.yxx.c" break; - case 346: /* $@18: %empty */ -#line 2884 "dtool/src/cppparser/cppBison.yxx" + case 351: /* $@18: %empty */ +#line 2915 "dtool/src/cppparser/cppBison.yxx" { CPPVisibility starting_vis = ((yyvsp[-2].u.extension_enum) == CPPExtensionType::T_class) ? V_private : V_public; @@ -7390,120 +7402,120 @@ yyreduce: push_scope(new_scope); push_struct(st); } -#line 7394 "built/tmp/cppBison.yxx.c" +#line 7406 "built/tmp/cppBison.yxx.c" break; - case 347: /* named_struct: struct_keyword optional_attributes name_no_final $@18 maybe_final maybe_class_derivation '{' cpp '}' */ -#line 2904 "dtool/src/cppparser/cppBison.yxx" + case 352: /* named_struct: struct_keyword optional_attributes name_no_final $@18 maybe_final maybe_class_derivation '{' cpp '}' */ +#line 2935 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.struct_type) = current_struct; current_struct->_incomplete = false; pop_struct(); pop_scope(); } -#line 7405 "built/tmp/cppBison.yxx.c" +#line 7417 "built/tmp/cppBison.yxx.c" break; - case 349: /* maybe_final: KW_FINAL */ -#line 2915 "dtool/src/cppparser/cppBison.yxx" + case 354: /* maybe_final: KW_FINAL */ +#line 2946 "dtool/src/cppparser/cppBison.yxx" { current_struct->_final = true; } -#line 7413 "built/tmp/cppBison.yxx.c" +#line 7425 "built/tmp/cppBison.yxx.c" break; - case 354: /* base_specification: class_derivation_name */ -#line 2932 "dtool/src/cppparser/cppBison.yxx" + case 359: /* base_specification: class_derivation_name */ +#line 2963 "dtool/src/cppparser/cppBison.yxx" { current_struct->append_derivation((yyvsp[0].u.type), V_unknown, false); } -#line 7421 "built/tmp/cppBison.yxx.c" +#line 7433 "built/tmp/cppBison.yxx.c" break; - case 355: /* base_specification: KW_PUBLIC class_derivation_name */ -#line 2936 "dtool/src/cppparser/cppBison.yxx" + case 360: /* base_specification: KW_PUBLIC class_derivation_name */ +#line 2967 "dtool/src/cppparser/cppBison.yxx" { current_struct->append_derivation((yyvsp[0].u.type), V_public, false); } -#line 7429 "built/tmp/cppBison.yxx.c" +#line 7441 "built/tmp/cppBison.yxx.c" break; - case 356: /* base_specification: KW_PROTECTED class_derivation_name */ -#line 2940 "dtool/src/cppparser/cppBison.yxx" + case 361: /* base_specification: KW_PROTECTED class_derivation_name */ +#line 2971 "dtool/src/cppparser/cppBison.yxx" { current_struct->append_derivation((yyvsp[0].u.type), V_protected, false); } -#line 7437 "built/tmp/cppBison.yxx.c" +#line 7449 "built/tmp/cppBison.yxx.c" break; - case 357: /* base_specification: KW_PRIVATE class_derivation_name */ -#line 2944 "dtool/src/cppparser/cppBison.yxx" + case 362: /* base_specification: KW_PRIVATE class_derivation_name */ +#line 2975 "dtool/src/cppparser/cppBison.yxx" { current_struct->append_derivation((yyvsp[0].u.type), V_private, false); } -#line 7445 "built/tmp/cppBison.yxx.c" +#line 7457 "built/tmp/cppBison.yxx.c" break; - case 358: /* base_specification: KW_VIRTUAL KW_PUBLIC class_derivation_name */ -#line 2948 "dtool/src/cppparser/cppBison.yxx" + case 363: /* base_specification: KW_VIRTUAL KW_PUBLIC class_derivation_name */ +#line 2979 "dtool/src/cppparser/cppBison.yxx" { current_struct->append_derivation((yyvsp[0].u.type), V_public, true); } -#line 7453 "built/tmp/cppBison.yxx.c" +#line 7465 "built/tmp/cppBison.yxx.c" break; - case 359: /* base_specification: KW_VIRTUAL KW_PROTECTED class_derivation_name */ -#line 2952 "dtool/src/cppparser/cppBison.yxx" + case 364: /* base_specification: KW_VIRTUAL KW_PROTECTED class_derivation_name */ +#line 2983 "dtool/src/cppparser/cppBison.yxx" { current_struct->append_derivation((yyvsp[0].u.type), V_protected, true); } -#line 7461 "built/tmp/cppBison.yxx.c" +#line 7473 "built/tmp/cppBison.yxx.c" break; - case 360: /* base_specification: KW_VIRTUAL KW_PRIVATE class_derivation_name */ -#line 2956 "dtool/src/cppparser/cppBison.yxx" + case 365: /* base_specification: KW_VIRTUAL KW_PRIVATE class_derivation_name */ +#line 2987 "dtool/src/cppparser/cppBison.yxx" { current_struct->append_derivation((yyvsp[0].u.type), V_private, true); } -#line 7469 "built/tmp/cppBison.yxx.c" +#line 7481 "built/tmp/cppBison.yxx.c" break; - case 361: /* base_specification: KW_PUBLIC KW_VIRTUAL class_derivation_name */ -#line 2960 "dtool/src/cppparser/cppBison.yxx" + case 366: /* base_specification: KW_PUBLIC KW_VIRTUAL class_derivation_name */ +#line 2991 "dtool/src/cppparser/cppBison.yxx" { current_struct->append_derivation((yyvsp[0].u.type), V_public, true); } -#line 7477 "built/tmp/cppBison.yxx.c" +#line 7489 "built/tmp/cppBison.yxx.c" break; - case 362: /* base_specification: KW_PROTECTED KW_VIRTUAL class_derivation_name */ -#line 2964 "dtool/src/cppparser/cppBison.yxx" + case 367: /* base_specification: KW_PROTECTED KW_VIRTUAL class_derivation_name */ +#line 2995 "dtool/src/cppparser/cppBison.yxx" { current_struct->append_derivation((yyvsp[0].u.type), V_protected, true); } -#line 7485 "built/tmp/cppBison.yxx.c" +#line 7497 "built/tmp/cppBison.yxx.c" break; - case 363: /* base_specification: KW_PRIVATE KW_VIRTUAL class_derivation_name */ -#line 2968 "dtool/src/cppparser/cppBison.yxx" + case 368: /* base_specification: KW_PRIVATE KW_VIRTUAL class_derivation_name */ +#line 2999 "dtool/src/cppparser/cppBison.yxx" { current_struct->append_derivation((yyvsp[0].u.type), V_private, true); } -#line 7493 "built/tmp/cppBison.yxx.c" +#line 7505 "built/tmp/cppBison.yxx.c" break; - case 364: /* $@19: %empty */ -#line 2975 "dtool/src/cppparser/cppBison.yxx" + case 369: /* $@19: %empty */ +#line 3006 "dtool/src/cppparser/cppBison.yxx" { if (current_enum->_scope != nullptr) { push_scope(current_enum->_scope); } } -#line 7503 "built/tmp/cppBison.yxx.c" +#line 7515 "built/tmp/cppBison.yxx.c" break; - case 365: /* enum: enum_decl $@19 '{' enum_body '}' */ -#line 2981 "dtool/src/cppparser/cppBison.yxx" + case 370: /* enum: enum_decl $@19 '{' enum_body '}' */ +#line 3012 "dtool/src/cppparser/cppBison.yxx" { if (current_enum->_scope != nullptr) { pop_scope(); @@ -7511,145 +7523,145 @@ yyreduce: (yyval.u.enum_type) = current_enum; current_enum = nullptr; } -#line 7515 "built/tmp/cppBison.yxx.c" +#line 7527 "built/tmp/cppBison.yxx.c" break; - case 366: /* enum_decl: enum_keyword optional_attributes ':' enum_element_type */ -#line 2992 "dtool/src/cppparser/cppBison.yxx" + case 371: /* enum_decl: enum_keyword optional_attributes ':' enum_element_type */ +#line 3023 "dtool/src/cppparser/cppBison.yxx" { current_enum = new CPPEnumType((yyvsp[-3].u.extension_enum), nullptr, (yyvsp[0].u.type), current_scope, nullptr, (yylsp[-3]).file, (yyvsp[-2].attr_list)); } -#line 7523 "built/tmp/cppBison.yxx.c" +#line 7535 "built/tmp/cppBison.yxx.c" break; - case 367: /* enum_decl: enum_keyword optional_attributes */ -#line 2996 "dtool/src/cppparser/cppBison.yxx" + case 372: /* enum_decl: enum_keyword optional_attributes */ +#line 3027 "dtool/src/cppparser/cppBison.yxx" { current_enum = new CPPEnumType((yyvsp[-1].u.extension_enum), nullptr, current_scope, nullptr, (yylsp[-1]).file, (yyvsp[0].attr_list)); } -#line 7531 "built/tmp/cppBison.yxx.c" +#line 7543 "built/tmp/cppBison.yxx.c" break; - case 368: /* enum_decl: enum_keyword optional_attributes name_no_final ':' enum_element_type */ -#line 3000 "dtool/src/cppparser/cppBison.yxx" + case 373: /* enum_decl: enum_keyword optional_attributes name_no_final ':' enum_element_type */ +#line 3031 "dtool/src/cppparser/cppBison.yxx" { CPPScope *new_scope = new CPPScope(current_scope, (yyvsp[-2].u.identifier)->_names.back(), V_public); current_enum = new CPPEnumType((yyvsp[-4].u.extension_enum), (yyvsp[-2].u.identifier), (yyvsp[0].u.type), current_scope, new_scope, (yylsp[-4]).file, (yyvsp[-3].attr_list)); } -#line 7540 "built/tmp/cppBison.yxx.c" +#line 7552 "built/tmp/cppBison.yxx.c" break; - case 369: /* enum_decl: enum_keyword optional_attributes name_no_final */ -#line 3005 "dtool/src/cppparser/cppBison.yxx" + case 374: /* enum_decl: enum_keyword optional_attributes name_no_final */ +#line 3036 "dtool/src/cppparser/cppBison.yxx" { CPPScope *new_scope = new CPPScope(current_scope, (yyvsp[0].u.identifier)->_names.back(), V_public); current_enum = new CPPEnumType((yyvsp[-2].u.extension_enum), (yyvsp[0].u.identifier), current_scope, new_scope, (yylsp[-2]).file, (yyvsp[-1].attr_list)); } -#line 7549 "built/tmp/cppBison.yxx.c" +#line 7561 "built/tmp/cppBison.yxx.c" break; - case 370: /* enum_element_type: simple_int_type */ -#line 3013 "dtool/src/cppparser/cppBison.yxx" + case 375: /* enum_element_type: simple_int_type */ +#line 3044 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.type) = CPPType::new_type((yyvsp[0].u.simple_type)); } -#line 7557 "built/tmp/cppBison.yxx.c" +#line 7569 "built/tmp/cppBison.yxx.c" break; - case 371: /* enum_element_type: TYPENAME_IDENTIFIER */ -#line 3017 "dtool/src/cppparser/cppBison.yxx" + case 376: /* enum_element_type: TYPENAME_IDENTIFIER */ +#line 3048 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.type) = (yyvsp[0].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); } -#line 7565 "built/tmp/cppBison.yxx.c" +#line 7577 "built/tmp/cppBison.yxx.c" break; - case 373: /* enum_body_trailing_comma: enum_body_trailing_comma name optional_attributes ',' */ -#line 3025 "dtool/src/cppparser/cppBison.yxx" + case 378: /* enum_body_trailing_comma: enum_body_trailing_comma name optional_attributes ',' */ +#line 3056 "dtool/src/cppparser/cppBison.yxx" { assert(current_enum != nullptr); current_enum->add_element((yyvsp[-2].u.identifier)->get_simple_name(), nullptr, current_lexer, (yylsp[-2]), (yyvsp[-1].attr_list)); } -#line 7574 "built/tmp/cppBison.yxx.c" +#line 7586 "built/tmp/cppBison.yxx.c" break; - case 374: /* enum_body_trailing_comma: enum_body_trailing_comma name optional_attributes '=' const_expr ',' */ -#line 3030 "dtool/src/cppparser/cppBison.yxx" + case 379: /* enum_body_trailing_comma: enum_body_trailing_comma name optional_attributes '=' const_expr ',' */ +#line 3061 "dtool/src/cppparser/cppBison.yxx" { assert(current_enum != nullptr); current_enum->add_element((yyvsp[-4].u.identifier)->get_simple_name(), (yyvsp[-1].u.expr), current_lexer, (yylsp[-4]), (yyvsp[-3].attr_list)); } -#line 7583 "built/tmp/cppBison.yxx.c" +#line 7595 "built/tmp/cppBison.yxx.c" break; - case 376: /* enum_body: enum_body_trailing_comma name optional_attributes */ -#line 3038 "dtool/src/cppparser/cppBison.yxx" + case 381: /* enum_body: enum_body_trailing_comma name optional_attributes */ +#line 3069 "dtool/src/cppparser/cppBison.yxx" { assert(current_enum != nullptr); current_enum->add_element((yyvsp[-1].u.identifier)->get_simple_name(), nullptr, current_lexer, (yylsp[-1]), (yyvsp[0].attr_list)); } -#line 7592 "built/tmp/cppBison.yxx.c" +#line 7604 "built/tmp/cppBison.yxx.c" break; - case 377: /* enum_body: enum_body_trailing_comma name optional_attributes '=' const_expr */ -#line 3043 "dtool/src/cppparser/cppBison.yxx" + case 382: /* enum_body: enum_body_trailing_comma name optional_attributes '=' const_expr */ +#line 3074 "dtool/src/cppparser/cppBison.yxx" { assert(current_enum != nullptr); current_enum->add_element((yyvsp[-3].u.identifier)->get_simple_name(), (yyvsp[0].u.expr), current_lexer, (yylsp[-3]), (yyvsp[-2].attr_list)); } -#line 7601 "built/tmp/cppBison.yxx.c" +#line 7613 "built/tmp/cppBison.yxx.c" break; - case 378: /* enum_keyword: KW_ENUM */ -#line 3051 "dtool/src/cppparser/cppBison.yxx" + case 383: /* enum_keyword: KW_ENUM */ +#line 3082 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.extension_enum) = CPPExtensionType::T_enum; } -#line 7609 "built/tmp/cppBison.yxx.c" +#line 7621 "built/tmp/cppBison.yxx.c" break; - case 379: /* enum_keyword: KW_ENUM KW_CLASS */ -#line 3055 "dtool/src/cppparser/cppBison.yxx" + case 384: /* enum_keyword: KW_ENUM KW_CLASS */ +#line 3086 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.extension_enum) = CPPExtensionType::T_enum_class; } -#line 7617 "built/tmp/cppBison.yxx.c" +#line 7629 "built/tmp/cppBison.yxx.c" break; - case 380: /* enum_keyword: KW_ENUM KW_STRUCT */ -#line 3059 "dtool/src/cppparser/cppBison.yxx" + case 385: /* enum_keyword: KW_ENUM KW_STRUCT */ +#line 3090 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.extension_enum) = CPPExtensionType::T_enum_struct; } -#line 7625 "built/tmp/cppBison.yxx.c" +#line 7637 "built/tmp/cppBison.yxx.c" break; - case 381: /* struct_keyword: KW_CLASS */ -#line 3066 "dtool/src/cppparser/cppBison.yxx" + case 386: /* struct_keyword: KW_CLASS */ +#line 3097 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.extension_enum) = CPPExtensionType::T_class; } -#line 7633 "built/tmp/cppBison.yxx.c" +#line 7645 "built/tmp/cppBison.yxx.c" break; - case 382: /* struct_keyword: KW_STRUCT */ -#line 3070 "dtool/src/cppparser/cppBison.yxx" + case 387: /* struct_keyword: KW_STRUCT */ +#line 3101 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.extension_enum) = CPPExtensionType::T_struct; } -#line 7641 "built/tmp/cppBison.yxx.c" +#line 7653 "built/tmp/cppBison.yxx.c" break; - case 383: /* struct_keyword: KW_UNION */ -#line 3074 "dtool/src/cppparser/cppBison.yxx" + case 388: /* struct_keyword: KW_UNION */ +#line 3105 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.extension_enum) = CPPExtensionType::T_union; } -#line 7649 "built/tmp/cppBison.yxx.c" +#line 7661 "built/tmp/cppBison.yxx.c" break; - case 384: /* $@20: %empty */ -#line 3081 "dtool/src/cppparser/cppBison.yxx" + case 389: /* $@20: %empty */ +#line 3112 "dtool/src/cppparser/cppBison.yxx" { CPPScope *scope = (yyvsp[-1].u.identifier)->find_scope(current_scope, global_scope, current_lexer); if (scope == nullptr) { @@ -7667,19 +7679,19 @@ yyreduce: current_scope->define_namespace(nspace); push_scope(scope); } -#line 7671 "built/tmp/cppBison.yxx.c" +#line 7683 "built/tmp/cppBison.yxx.c" break; - case 385: /* namespace_declaration: KW_NAMESPACE optional_attributes name '{' $@20 cpp '}' */ -#line 3099 "dtool/src/cppparser/cppBison.yxx" + case 390: /* namespace_declaration: KW_NAMESPACE optional_attributes name '{' $@20 cpp '}' */ +#line 3130 "dtool/src/cppparser/cppBison.yxx" { pop_scope(); } -#line 7679 "built/tmp/cppBison.yxx.c" +#line 7691 "built/tmp/cppBison.yxx.c" break; - case 386: /* $@21: %empty */ -#line 3103 "dtool/src/cppparser/cppBison.yxx" + case 391: /* $@21: %empty */ +#line 3134 "dtool/src/cppparser/cppBison.yxx" { CPPScope *scope = (yyvsp[-1].u.identifier)->find_scope(current_scope, global_scope, current_lexer); if (scope == nullptr) { @@ -7698,161 +7710,161 @@ yyreduce: current_scope->define_namespace(nspace); push_scope(scope); } -#line 7702 "built/tmp/cppBison.yxx.c" +#line 7714 "built/tmp/cppBison.yxx.c" break; - case 387: /* namespace_declaration: KW_INLINE KW_NAMESPACE name '{' $@21 cpp '}' */ -#line 3122 "dtool/src/cppparser/cppBison.yxx" + case 392: /* namespace_declaration: KW_INLINE KW_NAMESPACE name '{' $@21 cpp '}' */ +#line 3153 "dtool/src/cppparser/cppBison.yxx" { pop_scope(); } -#line 7710 "built/tmp/cppBison.yxx.c" +#line 7722 "built/tmp/cppBison.yxx.c" break; - case 390: /* using_declaration: KW_USING name ';' */ -#line 3131 "dtool/src/cppparser/cppBison.yxx" + case 395: /* using_declaration: KW_USING name ';' */ +#line 3162 "dtool/src/cppparser/cppBison.yxx" { CPPUsing *using_decl = new CPPUsing((yyvsp[-1].u.identifier), false, (yylsp[-2]).file); current_scope->add_declaration(using_decl, global_scope, current_lexer, (yylsp[-2])); current_scope->add_using(using_decl, global_scope, current_lexer); } -#line 7720 "built/tmp/cppBison.yxx.c" +#line 7732 "built/tmp/cppBison.yxx.c" break; - case 391: /* using_declaration: KW_USING name optional_attributes '=' full_type ';' */ -#line 3137 "dtool/src/cppparser/cppBison.yxx" + case 396: /* using_declaration: KW_USING name optional_attributes '=' full_type ';' */ +#line 3168 "dtool/src/cppparser/cppBison.yxx" { // This is really just an alternative way to declare a typedef. CPPTypedefType *typedef_type = new CPPTypedefType((yyvsp[-1].u.type), (yyvsp[-4].u.identifier), current_scope, (yyvsp[-3].attr_list)); typedef_type->_using = true; current_scope->add_declaration(CPPType::new_type(typedef_type), global_scope, current_lexer, (yylsp[-5])); } -#line 7731 "built/tmp/cppBison.yxx.c" +#line 7743 "built/tmp/cppBison.yxx.c" break; - case 392: /* using_declaration: KW_USING KW_NAMESPACE name ';' */ -#line 3144 "dtool/src/cppparser/cppBison.yxx" + case 397: /* using_declaration: KW_USING KW_NAMESPACE name ';' */ +#line 3175 "dtool/src/cppparser/cppBison.yxx" { CPPUsing *using_decl = new CPPUsing((yyvsp[-1].u.identifier), true, (yylsp[-3]).file); current_scope->add_declaration(using_decl, global_scope, current_lexer, (yylsp[-3])); current_scope->add_using(using_decl, global_scope, current_lexer); } -#line 7741 "built/tmp/cppBison.yxx.c" +#line 7753 "built/tmp/cppBison.yxx.c" break; - case 393: /* using_declaration: KW_USING KW_ENUM name ';' */ -#line 3150 "dtool/src/cppparser/cppBison.yxx" + case 398: /* using_declaration: KW_USING KW_ENUM name ';' */ +#line 3181 "dtool/src/cppparser/cppBison.yxx" { CPPUsing *using_decl = new CPPUsing((yyvsp[-1].u.identifier), false, (yylsp[-3]).file); current_scope->add_declaration(using_decl, global_scope, current_lexer, (yylsp[-3])); current_scope->add_using(using_decl, global_scope, current_lexer); } -#line 7751 "built/tmp/cppBison.yxx.c" +#line 7763 "built/tmp/cppBison.yxx.c" break; - case 397: /* simple_int_type: KW_BOOL */ -#line 3165 "dtool/src/cppparser/cppBison.yxx" + case 402: /* simple_int_type: KW_BOOL */ +#line 3196 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.simple_type) = new CPPSimpleType(CPPSimpleType::T_bool); } -#line 7759 "built/tmp/cppBison.yxx.c" +#line 7771 "built/tmp/cppBison.yxx.c" break; - case 398: /* simple_int_type: KW_CHAR */ -#line 3169 "dtool/src/cppparser/cppBison.yxx" + case 403: /* simple_int_type: KW_CHAR */ +#line 3200 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.simple_type) = new CPPSimpleType(CPPSimpleType::T_char); } -#line 7767 "built/tmp/cppBison.yxx.c" +#line 7779 "built/tmp/cppBison.yxx.c" break; - case 399: /* simple_int_type: KW_WCHAR_T */ -#line 3173 "dtool/src/cppparser/cppBison.yxx" + case 404: /* simple_int_type: KW_WCHAR_T */ +#line 3204 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.simple_type) = new CPPSimpleType(CPPSimpleType::T_wchar_t); } -#line 7775 "built/tmp/cppBison.yxx.c" +#line 7787 "built/tmp/cppBison.yxx.c" break; - case 400: /* simple_int_type: KW_CHAR8_T */ -#line 3177 "dtool/src/cppparser/cppBison.yxx" + case 405: /* simple_int_type: KW_CHAR8_T */ +#line 3208 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.simple_type) = new CPPSimpleType(CPPSimpleType::T_char8_t); } -#line 7783 "built/tmp/cppBison.yxx.c" +#line 7795 "built/tmp/cppBison.yxx.c" break; - case 401: /* simple_int_type: KW_CHAR16_T */ -#line 3181 "dtool/src/cppparser/cppBison.yxx" + case 406: /* simple_int_type: KW_CHAR16_T */ +#line 3212 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.simple_type) = new CPPSimpleType(CPPSimpleType::T_char16_t); } -#line 7791 "built/tmp/cppBison.yxx.c" +#line 7803 "built/tmp/cppBison.yxx.c" break; - case 402: /* simple_int_type: KW_CHAR32_T */ -#line 3185 "dtool/src/cppparser/cppBison.yxx" + case 407: /* simple_int_type: KW_CHAR32_T */ +#line 3216 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.simple_type) = new CPPSimpleType(CPPSimpleType::T_char32_t); } -#line 7799 "built/tmp/cppBison.yxx.c" +#line 7811 "built/tmp/cppBison.yxx.c" break; - case 403: /* simple_int_type: KW_SHORT */ -#line 3189 "dtool/src/cppparser/cppBison.yxx" + case 408: /* simple_int_type: KW_SHORT */ +#line 3220 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.simple_type) = new CPPSimpleType(CPPSimpleType::T_int, CPPSimpleType::F_short); } -#line 7808 "built/tmp/cppBison.yxx.c" +#line 7820 "built/tmp/cppBison.yxx.c" break; - case 404: /* simple_int_type: KW_LONG */ -#line 3194 "dtool/src/cppparser/cppBison.yxx" + case 409: /* simple_int_type: KW_LONG */ +#line 3225 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.simple_type) = new CPPSimpleType(CPPSimpleType::T_int, CPPSimpleType::F_long); } -#line 7817 "built/tmp/cppBison.yxx.c" +#line 7829 "built/tmp/cppBison.yxx.c" break; - case 405: /* simple_int_type: KW_UNSIGNED */ -#line 3199 "dtool/src/cppparser/cppBison.yxx" + case 410: /* simple_int_type: KW_UNSIGNED */ +#line 3230 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.simple_type) = new CPPSimpleType(CPPSimpleType::T_int, CPPSimpleType::F_unsigned); } -#line 7826 "built/tmp/cppBison.yxx.c" +#line 7838 "built/tmp/cppBison.yxx.c" break; - case 406: /* simple_int_type: KW_SIGNED */ -#line 3204 "dtool/src/cppparser/cppBison.yxx" + case 411: /* simple_int_type: KW_SIGNED */ +#line 3235 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.simple_type) = new CPPSimpleType(CPPSimpleType::T_int, CPPSimpleType::F_signed); } -#line 7835 "built/tmp/cppBison.yxx.c" +#line 7847 "built/tmp/cppBison.yxx.c" break; - case 407: /* simple_int_type: KW_INT */ -#line 3209 "dtool/src/cppparser/cppBison.yxx" + case 412: /* simple_int_type: KW_INT */ +#line 3240 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.simple_type) = new CPPSimpleType(CPPSimpleType::T_int); } -#line 7843 "built/tmp/cppBison.yxx.c" +#line 7855 "built/tmp/cppBison.yxx.c" break; - case 408: /* simple_int_type: KW_SHORT simple_int_type */ -#line 3213 "dtool/src/cppparser/cppBison.yxx" + case 413: /* simple_int_type: KW_SHORT simple_int_type */ +#line 3244 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.simple_type) = (yyvsp[0].u.simple_type); (yyval.u.simple_type)->_flags |= CPPSimpleType::F_short; } -#line 7852 "built/tmp/cppBison.yxx.c" +#line 7864 "built/tmp/cppBison.yxx.c" break; - case 409: /* simple_int_type: KW_LONG simple_int_type */ -#line 3218 "dtool/src/cppparser/cppBison.yxx" + case 414: /* simple_int_type: KW_LONG simple_int_type */ +#line 3249 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.simple_type) = (yyvsp[0].u.simple_type); if ((yyval.u.simple_type)->_flags & CPPSimpleType::F_long) { @@ -7861,501 +7873,501 @@ yyreduce: (yyval.u.simple_type)->_flags |= CPPSimpleType::F_long; } } -#line 7865 "built/tmp/cppBison.yxx.c" +#line 7877 "built/tmp/cppBison.yxx.c" break; - case 410: /* simple_int_type: KW_UNSIGNED simple_int_type */ -#line 3227 "dtool/src/cppparser/cppBison.yxx" + case 415: /* simple_int_type: KW_UNSIGNED simple_int_type */ +#line 3258 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.simple_type) = (yyvsp[0].u.simple_type); (yyval.u.simple_type)->_flags |= CPPSimpleType::F_unsigned; } -#line 7874 "built/tmp/cppBison.yxx.c" +#line 7886 "built/tmp/cppBison.yxx.c" break; - case 411: /* simple_int_type: KW_SIGNED simple_int_type */ -#line 3232 "dtool/src/cppparser/cppBison.yxx" + case 416: /* simple_int_type: KW_SIGNED simple_int_type */ +#line 3263 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.simple_type) = (yyvsp[0].u.simple_type); (yyval.u.simple_type)->_flags |= CPPSimpleType::F_signed; } -#line 7883 "built/tmp/cppBison.yxx.c" +#line 7895 "built/tmp/cppBison.yxx.c" break; - case 412: /* simple_float_type: KW_FLOAT */ -#line 3240 "dtool/src/cppparser/cppBison.yxx" + case 417: /* simple_float_type: KW_FLOAT */ +#line 3271 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.simple_type) = new CPPSimpleType(CPPSimpleType::T_float); } -#line 7891 "built/tmp/cppBison.yxx.c" +#line 7903 "built/tmp/cppBison.yxx.c" break; - case 413: /* simple_float_type: KW_DOUBLE */ -#line 3244 "dtool/src/cppparser/cppBison.yxx" + case 418: /* simple_float_type: KW_DOUBLE */ +#line 3275 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.simple_type) = new CPPSimpleType(CPPSimpleType::T_double); } -#line 7899 "built/tmp/cppBison.yxx.c" +#line 7911 "built/tmp/cppBison.yxx.c" break; - case 414: /* simple_float_type: KW_LONG KW_DOUBLE */ -#line 3248 "dtool/src/cppparser/cppBison.yxx" + case 419: /* simple_float_type: KW_LONG KW_DOUBLE */ +#line 3279 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.simple_type) = new CPPSimpleType(CPPSimpleType::T_double, CPPSimpleType::F_long); } -#line 7908 "built/tmp/cppBison.yxx.c" +#line 7920 "built/tmp/cppBison.yxx.c" break; - case 415: /* simple_void_type: KW_VOID */ -#line 3256 "dtool/src/cppparser/cppBison.yxx" + case 420: /* simple_void_type: KW_VOID */ +#line 3287 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.simple_type) = new CPPSimpleType(CPPSimpleType::T_void); } -#line 7916 "built/tmp/cppBison.yxx.c" +#line 7928 "built/tmp/cppBison.yxx.c" break; - case 416: /* $@22: %empty */ -#line 3265 "dtool/src/cppparser/cppBison.yxx" + case 421: /* $@22: %empty */ +#line 3296 "dtool/src/cppparser/cppBison.yxx" { current_lexer->_resolve_identifiers = false; } -#line 7924 "built/tmp/cppBison.yxx.c" +#line 7936 "built/tmp/cppBison.yxx.c" break; - case 417: /* code: $@22 code_block */ -#line 3269 "dtool/src/cppparser/cppBison.yxx" + case 422: /* code: $@22 code_block */ +#line 3300 "dtool/src/cppparser/cppBison.yxx" { current_lexer->_resolve_identifiers = true; } -#line 7932 "built/tmp/cppBison.yxx.c" +#line 7944 "built/tmp/cppBison.yxx.c" break; - case 532: /* element: KW_WHILE */ -#line 3314 "dtool/src/cppparser/cppBison.yxx" -{ -} -#line 7939 "built/tmp/cppBison.yxx.c" - break; - - case 556: /* optional_const_expr: empty */ -#line 3323 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = nullptr; -} -#line 7947 "built/tmp/cppBison.yxx.c" - break; - - case 557: /* optional_const_expr: const_expr */ -#line 3327 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = (yyvsp[0].u.expr); -} -#line 7955 "built/tmp/cppBison.yxx.c" - break; - - case 558: /* optional_const_expr_comma: empty */ -#line 3334 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = nullptr; -} -#line 7963 "built/tmp/cppBison.yxx.c" - break; - - case 559: /* optional_const_expr_comma: const_expr_comma */ -#line 3338 "dtool/src/cppparser/cppBison.yxx" -{ - (yyval.u.expr) = (yyvsp[0].u.expr); -} -#line 7971 "built/tmp/cppBison.yxx.c" - break; - - case 560: /* const_expr_comma: const_expr */ + case 539: /* element: KW_WHILE */ #line 3345 "dtool/src/cppparser/cppBison.yxx" { - (yyval.u.expr) = (yyvsp[0].u.expr); } -#line 7979 "built/tmp/cppBison.yxx.c" +#line 7951 "built/tmp/cppBison.yxx.c" break; - case 561: /* const_expr_comma: const_expr_comma ',' const_expr */ -#line 3349 "dtool/src/cppparser/cppBison.yxx" + case 563: /* optional_const_expr: empty */ +#line 3354 "dtool/src/cppparser/cppBison.yxx" +{ + (yyval.u.expr) = nullptr; +} +#line 7959 "built/tmp/cppBison.yxx.c" + break; + + case 564: /* optional_const_expr: const_expr */ +#line 3358 "dtool/src/cppparser/cppBison.yxx" +{ + (yyval.u.expr) = (yyvsp[0].u.expr); +} +#line 7967 "built/tmp/cppBison.yxx.c" + break; + + case 565: /* optional_const_expr_comma: empty */ +#line 3365 "dtool/src/cppparser/cppBison.yxx" +{ + (yyval.u.expr) = nullptr; +} +#line 7975 "built/tmp/cppBison.yxx.c" + break; + + case 566: /* optional_const_expr_comma: const_expr_comma */ +#line 3369 "dtool/src/cppparser/cppBison.yxx" +{ + (yyval.u.expr) = (yyvsp[0].u.expr); +} +#line 7983 "built/tmp/cppBison.yxx.c" + break; + + case 567: /* const_expr_comma: const_expr */ +#line 3376 "dtool/src/cppparser/cppBison.yxx" +{ + (yyval.u.expr) = (yyvsp[0].u.expr); +} +#line 7991 "built/tmp/cppBison.yxx.c" + break; + + case 568: /* const_expr_comma: const_expr_comma ',' const_expr */ +#line 3380 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(',', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 7987 "built/tmp/cppBison.yxx.c" +#line 7999 "built/tmp/cppBison.yxx.c" break; - case 562: /* no_angle_bracket_const_expr: const_operand */ -#line 3356 "dtool/src/cppparser/cppBison.yxx" + case 569: /* no_angle_bracket_const_expr: const_operand */ +#line 3387 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = (yyvsp[0].u.expr); } -#line 7995 "built/tmp/cppBison.yxx.c" +#line 8007 "built/tmp/cppBison.yxx.c" break; - case 563: /* no_angle_bracket_const_expr: '(' full_type ')' no_angle_bracket_const_expr */ -#line 3360 "dtool/src/cppparser/cppBison.yxx" + case 570: /* no_angle_bracket_const_expr: '(' full_type ')' no_angle_bracket_const_expr */ +#line 3391 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(CPPExpression::typecast_op((yyvsp[-2].u.type), (yyvsp[0].u.expr))); } -#line 8003 "built/tmp/cppBison.yxx.c" +#line 8015 "built/tmp/cppBison.yxx.c" break; - case 564: /* no_angle_bracket_const_expr: KW_STATIC_CAST '<' full_type '>' '(' const_expr_comma ')' */ -#line 3364 "dtool/src/cppparser/cppBison.yxx" + case 571: /* no_angle_bracket_const_expr: KW_STATIC_CAST '<' full_type '>' '(' const_expr_comma ')' */ +#line 3395 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(CPPExpression::typecast_op((yyvsp[-4].u.type), (yyvsp[-1].u.expr), CPPExpression::T_static_cast)); } -#line 8011 "built/tmp/cppBison.yxx.c" +#line 8023 "built/tmp/cppBison.yxx.c" break; - case 565: /* no_angle_bracket_const_expr: KW_DYNAMIC_CAST '<' full_type '>' '(' const_expr_comma ')' */ -#line 3368 "dtool/src/cppparser/cppBison.yxx" + case 572: /* no_angle_bracket_const_expr: KW_DYNAMIC_CAST '<' full_type '>' '(' const_expr_comma ')' */ +#line 3399 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(CPPExpression::typecast_op((yyvsp[-4].u.type), (yyvsp[-1].u.expr), CPPExpression::T_dynamic_cast)); } -#line 8019 "built/tmp/cppBison.yxx.c" +#line 8031 "built/tmp/cppBison.yxx.c" break; - case 566: /* no_angle_bracket_const_expr: KW_CONST_CAST '<' full_type '>' '(' const_expr_comma ')' */ -#line 3372 "dtool/src/cppparser/cppBison.yxx" + case 573: /* no_angle_bracket_const_expr: KW_CONST_CAST '<' full_type '>' '(' const_expr_comma ')' */ +#line 3403 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(CPPExpression::typecast_op((yyvsp[-4].u.type), (yyvsp[-1].u.expr), CPPExpression::T_const_cast)); } -#line 8027 "built/tmp/cppBison.yxx.c" +#line 8039 "built/tmp/cppBison.yxx.c" break; - case 567: /* no_angle_bracket_const_expr: KW_REINTERPRET_CAST '<' full_type '>' '(' const_expr_comma ')' */ -#line 3376 "dtool/src/cppparser/cppBison.yxx" + case 574: /* no_angle_bracket_const_expr: KW_REINTERPRET_CAST '<' full_type '>' '(' const_expr_comma ')' */ +#line 3407 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(CPPExpression::typecast_op((yyvsp[-4].u.type), (yyvsp[-1].u.expr), CPPExpression::T_reinterpret_cast)); } -#line 8035 "built/tmp/cppBison.yxx.c" +#line 8047 "built/tmp/cppBison.yxx.c" break; - case 568: /* no_angle_bracket_const_expr: KW_SIZEOF '(' full_type ')' */ -#line 3380 "dtool/src/cppparser/cppBison.yxx" + case 575: /* no_angle_bracket_const_expr: KW_SIZEOF '(' full_type ')' */ +#line 3411 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(CPPExpression::sizeof_func((yyvsp[-1].u.type))); } -#line 8043 "built/tmp/cppBison.yxx.c" +#line 8055 "built/tmp/cppBison.yxx.c" break; - case 569: /* no_angle_bracket_const_expr: KW_SIZEOF no_angle_bracket_const_expr */ -#line 3384 "dtool/src/cppparser/cppBison.yxx" + case 576: /* no_angle_bracket_const_expr: KW_SIZEOF no_angle_bracket_const_expr */ +#line 3415 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(CPPExpression::sizeof_func((yyvsp[0].u.expr))); } -#line 8051 "built/tmp/cppBison.yxx.c" +#line 8063 "built/tmp/cppBison.yxx.c" break; - case 570: /* no_angle_bracket_const_expr: KW_SIZEOF ELLIPSIS '(' name ')' */ -#line 3388 "dtool/src/cppparser/cppBison.yxx" + case 577: /* no_angle_bracket_const_expr: KW_SIZEOF ELLIPSIS '(' name ')' */ +#line 3419 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(CPPExpression::sizeof_ellipsis_func((yyvsp[-1].u.identifier))); } -#line 8059 "built/tmp/cppBison.yxx.c" +#line 8071 "built/tmp/cppBison.yxx.c" break; - case 571: /* no_angle_bracket_const_expr: KW_ALIGNOF '(' full_type ')' */ -#line 3392 "dtool/src/cppparser/cppBison.yxx" + case 578: /* no_angle_bracket_const_expr: KW_ALIGNOF '(' full_type ')' */ +#line 3423 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(CPPExpression::alignof_func((yyvsp[-1].u.type))); } -#line 8067 "built/tmp/cppBison.yxx.c" +#line 8079 "built/tmp/cppBison.yxx.c" break; - case 572: /* no_angle_bracket_const_expr: '!' no_angle_bracket_const_expr */ -#line 3396 "dtool/src/cppparser/cppBison.yxx" + case 579: /* no_angle_bracket_const_expr: '!' no_angle_bracket_const_expr */ +#line 3427 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(UNARY_NOT, (yyvsp[0].u.expr)); } -#line 8075 "built/tmp/cppBison.yxx.c" +#line 8087 "built/tmp/cppBison.yxx.c" break; - case 573: /* no_angle_bracket_const_expr: '~' no_angle_bracket_const_expr */ -#line 3400 "dtool/src/cppparser/cppBison.yxx" + case 580: /* no_angle_bracket_const_expr: '~' no_angle_bracket_const_expr */ +#line 3431 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(UNARY_NEGATE, (yyvsp[0].u.expr)); } -#line 8083 "built/tmp/cppBison.yxx.c" +#line 8095 "built/tmp/cppBison.yxx.c" break; - case 574: /* no_angle_bracket_const_expr: '-' no_angle_bracket_const_expr */ -#line 3404 "dtool/src/cppparser/cppBison.yxx" + case 581: /* no_angle_bracket_const_expr: '-' no_angle_bracket_const_expr */ +#line 3435 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(UNARY_MINUS, (yyvsp[0].u.expr)); } -#line 8091 "built/tmp/cppBison.yxx.c" +#line 8103 "built/tmp/cppBison.yxx.c" break; - case 575: /* no_angle_bracket_const_expr: '+' no_angle_bracket_const_expr */ -#line 3408 "dtool/src/cppparser/cppBison.yxx" + case 582: /* no_angle_bracket_const_expr: '+' no_angle_bracket_const_expr */ +#line 3439 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(UNARY_PLUS, (yyvsp[0].u.expr)); } -#line 8099 "built/tmp/cppBison.yxx.c" +#line 8111 "built/tmp/cppBison.yxx.c" break; - case 576: /* no_angle_bracket_const_expr: '*' no_angle_bracket_const_expr */ -#line 3412 "dtool/src/cppparser/cppBison.yxx" + case 583: /* no_angle_bracket_const_expr: '*' no_angle_bracket_const_expr */ +#line 3443 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(UNARY_STAR, (yyvsp[0].u.expr)); } -#line 8107 "built/tmp/cppBison.yxx.c" +#line 8119 "built/tmp/cppBison.yxx.c" break; - case 577: /* no_angle_bracket_const_expr: '&' no_angle_bracket_const_expr */ -#line 3416 "dtool/src/cppparser/cppBison.yxx" + case 584: /* no_angle_bracket_const_expr: '&' no_angle_bracket_const_expr */ +#line 3447 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(UNARY_REF, (yyvsp[0].u.expr)); } -#line 8115 "built/tmp/cppBison.yxx.c" +#line 8127 "built/tmp/cppBison.yxx.c" break; - case 578: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr '*' no_angle_bracket_const_expr */ -#line 3420 "dtool/src/cppparser/cppBison.yxx" + case 585: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr '*' no_angle_bracket_const_expr */ +#line 3451 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression('*', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 8123 "built/tmp/cppBison.yxx.c" +#line 8135 "built/tmp/cppBison.yxx.c" break; - case 579: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr '/' no_angle_bracket_const_expr */ -#line 3424 "dtool/src/cppparser/cppBison.yxx" + case 586: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr '/' no_angle_bracket_const_expr */ +#line 3455 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression('/', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 8131 "built/tmp/cppBison.yxx.c" +#line 8143 "built/tmp/cppBison.yxx.c" break; - case 580: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr '%' no_angle_bracket_const_expr */ -#line 3428 "dtool/src/cppparser/cppBison.yxx" + case 587: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr '%' no_angle_bracket_const_expr */ +#line 3459 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression('%', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 8139 "built/tmp/cppBison.yxx.c" +#line 8151 "built/tmp/cppBison.yxx.c" break; - case 581: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr '+' no_angle_bracket_const_expr */ -#line 3432 "dtool/src/cppparser/cppBison.yxx" + case 588: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr '+' no_angle_bracket_const_expr */ +#line 3463 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression('+', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 8147 "built/tmp/cppBison.yxx.c" +#line 8159 "built/tmp/cppBison.yxx.c" break; - case 582: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr '-' no_angle_bracket_const_expr */ -#line 3436 "dtool/src/cppparser/cppBison.yxx" + case 589: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr '-' no_angle_bracket_const_expr */ +#line 3467 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression('-', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 8155 "built/tmp/cppBison.yxx.c" +#line 8167 "built/tmp/cppBison.yxx.c" break; - case 583: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr '|' no_angle_bracket_const_expr */ -#line 3440 "dtool/src/cppparser/cppBison.yxx" + case 590: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr '|' no_angle_bracket_const_expr */ +#line 3471 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression('|', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 8163 "built/tmp/cppBison.yxx.c" +#line 8175 "built/tmp/cppBison.yxx.c" break; - case 584: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr '^' no_angle_bracket_const_expr */ -#line 3444 "dtool/src/cppparser/cppBison.yxx" + case 591: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr '^' no_angle_bracket_const_expr */ +#line 3475 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression('^', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 8171 "built/tmp/cppBison.yxx.c" +#line 8183 "built/tmp/cppBison.yxx.c" break; - case 585: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr '&' no_angle_bracket_const_expr */ -#line 3448 "dtool/src/cppparser/cppBison.yxx" + case 592: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr '&' no_angle_bracket_const_expr */ +#line 3479 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression('&', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 8179 "built/tmp/cppBison.yxx.c" +#line 8191 "built/tmp/cppBison.yxx.c" break; - case 586: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr OROR no_angle_bracket_const_expr */ -#line 3452 "dtool/src/cppparser/cppBison.yxx" + case 593: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr OROR no_angle_bracket_const_expr */ +#line 3483 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(OROR, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 8187 "built/tmp/cppBison.yxx.c" +#line 8199 "built/tmp/cppBison.yxx.c" break; - case 587: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr ANDAND no_angle_bracket_const_expr */ -#line 3456 "dtool/src/cppparser/cppBison.yxx" + case 594: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr ANDAND no_angle_bracket_const_expr */ +#line 3487 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(ANDAND, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 8195 "built/tmp/cppBison.yxx.c" +#line 8207 "built/tmp/cppBison.yxx.c" break; - case 588: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr EQCOMPARE no_angle_bracket_const_expr */ -#line 3460 "dtool/src/cppparser/cppBison.yxx" + case 595: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr EQCOMPARE no_angle_bracket_const_expr */ +#line 3491 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(EQCOMPARE, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 8203 "built/tmp/cppBison.yxx.c" +#line 8215 "built/tmp/cppBison.yxx.c" break; - case 589: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr NECOMPARE no_angle_bracket_const_expr */ -#line 3464 "dtool/src/cppparser/cppBison.yxx" + case 596: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr NECOMPARE no_angle_bracket_const_expr */ +#line 3495 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(NECOMPARE, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 8211 "built/tmp/cppBison.yxx.c" +#line 8223 "built/tmp/cppBison.yxx.c" break; - case 590: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr LECOMPARE no_angle_bracket_const_expr */ -#line 3468 "dtool/src/cppparser/cppBison.yxx" + case 597: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr LECOMPARE no_angle_bracket_const_expr */ +#line 3499 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(LECOMPARE, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 8219 "built/tmp/cppBison.yxx.c" +#line 8231 "built/tmp/cppBison.yxx.c" break; - case 591: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr GECOMPARE no_angle_bracket_const_expr */ -#line 3472 "dtool/src/cppparser/cppBison.yxx" + case 598: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr GECOMPARE no_angle_bracket_const_expr */ +#line 3503 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(GECOMPARE, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 8227 "built/tmp/cppBison.yxx.c" +#line 8239 "built/tmp/cppBison.yxx.c" break; - case 592: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr SPACESHIP no_angle_bracket_const_expr */ -#line 3476 "dtool/src/cppparser/cppBison.yxx" + case 599: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr SPACESHIP no_angle_bracket_const_expr */ +#line 3507 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(SPACESHIP, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 8235 "built/tmp/cppBison.yxx.c" +#line 8247 "built/tmp/cppBison.yxx.c" break; - case 593: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr LSHIFT no_angle_bracket_const_expr */ -#line 3480 "dtool/src/cppparser/cppBison.yxx" + case 600: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr LSHIFT no_angle_bracket_const_expr */ +#line 3511 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(LSHIFT, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 8243 "built/tmp/cppBison.yxx.c" +#line 8255 "built/tmp/cppBison.yxx.c" break; - case 594: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr RSHIFT no_angle_bracket_const_expr */ -#line 3484 "dtool/src/cppparser/cppBison.yxx" + case 601: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr RSHIFT no_angle_bracket_const_expr */ +#line 3515 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(RSHIFT, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 8251 "built/tmp/cppBison.yxx.c" +#line 8263 "built/tmp/cppBison.yxx.c" break; - case 595: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr '?' no_angle_bracket_const_expr ':' no_angle_bracket_const_expr */ -#line 3488 "dtool/src/cppparser/cppBison.yxx" + case 602: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr '?' no_angle_bracket_const_expr ':' no_angle_bracket_const_expr */ +#line 3519 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression('?', (yyvsp[-4].u.expr), (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 8259 "built/tmp/cppBison.yxx.c" +#line 8271 "built/tmp/cppBison.yxx.c" break; - case 596: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr '[' const_expr ']' */ -#line 3492 "dtool/src/cppparser/cppBison.yxx" + case 603: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr '[' const_expr ']' */ +#line 3523 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression('[', (yyvsp[-3].u.expr), (yyvsp[-1].u.expr)); } -#line 8267 "built/tmp/cppBison.yxx.c" +#line 8279 "built/tmp/cppBison.yxx.c" break; - case 597: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr '(' const_expr_comma ')' */ -#line 3496 "dtool/src/cppparser/cppBison.yxx" + case 604: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr '(' const_expr_comma ')' */ +#line 3527 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression('f', (yyvsp[-3].u.expr), (yyvsp[-1].u.expr)); } -#line 8275 "built/tmp/cppBison.yxx.c" +#line 8287 "built/tmp/cppBison.yxx.c" break; - case 598: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr '(' ')' */ -#line 3500 "dtool/src/cppparser/cppBison.yxx" + case 605: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr '(' ')' */ +#line 3531 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression('f', (yyvsp[-2].u.expr)); } -#line 8283 "built/tmp/cppBison.yxx.c" +#line 8295 "built/tmp/cppBison.yxx.c" break; - case 599: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr '.' name */ -#line 3504 "dtool/src/cppparser/cppBison.yxx" + case 606: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr '.' name */ +#line 3535 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression('.', (yyvsp[-2].u.expr), new CPPExpression((yyvsp[0].u.identifier), current_scope, global_scope, current_lexer)); } -#line 8291 "built/tmp/cppBison.yxx.c" +#line 8303 "built/tmp/cppBison.yxx.c" break; - case 600: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr POINTSAT no_angle_bracket_const_expr */ -#line 3508 "dtool/src/cppparser/cppBison.yxx" + case 607: /* no_angle_bracket_const_expr: no_angle_bracket_const_expr POINTSAT no_angle_bracket_const_expr */ +#line 3539 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(POINTSAT, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 8299 "built/tmp/cppBison.yxx.c" +#line 8311 "built/tmp/cppBison.yxx.c" break; - case 601: /* no_angle_bracket_const_expr: '(' const_expr_comma ')' */ -#line 3512 "dtool/src/cppparser/cppBison.yxx" + case 608: /* no_angle_bracket_const_expr: '(' const_expr_comma ')' */ +#line 3543 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = (yyvsp[-1].u.expr); } -#line 8307 "built/tmp/cppBison.yxx.c" +#line 8319 "built/tmp/cppBison.yxx.c" break; - case 602: /* const_expr: const_operand */ -#line 3520 "dtool/src/cppparser/cppBison.yxx" + case 609: /* const_expr: const_operand */ +#line 3551 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = (yyvsp[0].u.expr); } -#line 8315 "built/tmp/cppBison.yxx.c" +#line 8327 "built/tmp/cppBison.yxx.c" break; - case 603: /* const_expr: '(' full_type ')' const_expr */ -#line 3524 "dtool/src/cppparser/cppBison.yxx" + case 610: /* const_expr: '(' full_type ')' const_expr */ +#line 3555 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(CPPExpression::typecast_op((yyvsp[-2].u.type), (yyvsp[0].u.expr))); } -#line 8323 "built/tmp/cppBison.yxx.c" +#line 8335 "built/tmp/cppBison.yxx.c" break; - case 604: /* const_expr: KW_STATIC_CAST '<' full_type '>' '(' const_expr_comma ')' */ -#line 3528 "dtool/src/cppparser/cppBison.yxx" + case 611: /* const_expr: KW_STATIC_CAST '<' full_type '>' '(' const_expr_comma ')' */ +#line 3559 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(CPPExpression::typecast_op((yyvsp[-4].u.type), (yyvsp[-1].u.expr), CPPExpression::T_static_cast)); } -#line 8331 "built/tmp/cppBison.yxx.c" +#line 8343 "built/tmp/cppBison.yxx.c" break; - case 605: /* const_expr: KW_DYNAMIC_CAST '<' full_type '>' '(' const_expr_comma ')' */ -#line 3532 "dtool/src/cppparser/cppBison.yxx" + case 612: /* const_expr: KW_DYNAMIC_CAST '<' full_type '>' '(' const_expr_comma ')' */ +#line 3563 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(CPPExpression::typecast_op((yyvsp[-4].u.type), (yyvsp[-1].u.expr), CPPExpression::T_dynamic_cast)); } -#line 8339 "built/tmp/cppBison.yxx.c" +#line 8351 "built/tmp/cppBison.yxx.c" break; - case 606: /* const_expr: KW_CONST_CAST '<' full_type '>' '(' const_expr_comma ')' */ -#line 3536 "dtool/src/cppparser/cppBison.yxx" + case 613: /* const_expr: KW_CONST_CAST '<' full_type '>' '(' const_expr_comma ')' */ +#line 3567 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(CPPExpression::typecast_op((yyvsp[-4].u.type), (yyvsp[-1].u.expr), CPPExpression::T_const_cast)); } -#line 8347 "built/tmp/cppBison.yxx.c" +#line 8359 "built/tmp/cppBison.yxx.c" break; - case 607: /* const_expr: KW_REINTERPRET_CAST '<' full_type '>' '(' const_expr_comma ')' */ -#line 3540 "dtool/src/cppparser/cppBison.yxx" + case 614: /* const_expr: KW_REINTERPRET_CAST '<' full_type '>' '(' const_expr_comma ')' */ +#line 3571 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(CPPExpression::typecast_op((yyvsp[-4].u.type), (yyvsp[-1].u.expr), CPPExpression::T_reinterpret_cast)); } -#line 8355 "built/tmp/cppBison.yxx.c" +#line 8367 "built/tmp/cppBison.yxx.c" break; - case 608: /* const_expr: TYPENAME_IDENTIFIER '(' optional_const_expr_comma ')' */ -#line 3544 "dtool/src/cppparser/cppBison.yxx" + case 615: /* const_expr: TYPENAME_IDENTIFIER '(' optional_const_expr_comma ')' */ +#line 3575 "dtool/src/cppparser/cppBison.yxx" { // A constructor call. CPPType *type = (yyvsp[-3].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); @@ -8365,11 +8377,11 @@ yyreduce: assert(type != nullptr); (yyval.u.expr) = new CPPExpression(CPPExpression::construct_op(type, (yyvsp[-1].u.expr))); } -#line 8369 "built/tmp/cppBison.yxx.c" +#line 8381 "built/tmp/cppBison.yxx.c" break; - case 609: /* const_expr: TYPENAME_IDENTIFIER '{' optional_const_expr_comma '}' */ -#line 3554 "dtool/src/cppparser/cppBison.yxx" + case 616: /* const_expr: TYPENAME_IDENTIFIER '{' optional_const_expr_comma '}' */ +#line 3585 "dtool/src/cppparser/cppBison.yxx" { // Aggregate initialization. CPPType *type = (yyvsp[-3].u.identifier)->find_type(current_scope, global_scope, false, current_lexer); @@ -8379,193 +8391,193 @@ yyreduce: assert(type != nullptr); (yyval.u.expr) = new CPPExpression(CPPExpression::aggregate_init_op(type, (yyvsp[-1].u.expr))); } -#line 8383 "built/tmp/cppBison.yxx.c" +#line 8395 "built/tmp/cppBison.yxx.c" break; - case 610: /* const_expr: KW_INT '(' optional_const_expr_comma ')' */ -#line 3564 "dtool/src/cppparser/cppBison.yxx" + case 617: /* const_expr: KW_INT '(' optional_const_expr_comma ')' */ +#line 3595 "dtool/src/cppparser/cppBison.yxx" { CPPType *type = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_int)); (yyval.u.expr) = new CPPExpression(CPPExpression::construct_op(type, (yyvsp[-1].u.expr))); } -#line 8393 "built/tmp/cppBison.yxx.c" +#line 8405 "built/tmp/cppBison.yxx.c" break; - case 611: /* const_expr: KW_CHAR '(' optional_const_expr_comma ')' */ -#line 3570 "dtool/src/cppparser/cppBison.yxx" + case 618: /* const_expr: KW_CHAR '(' optional_const_expr_comma ')' */ +#line 3601 "dtool/src/cppparser/cppBison.yxx" { CPPType *type = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_char)); (yyval.u.expr) = new CPPExpression(CPPExpression::construct_op(type, (yyvsp[-1].u.expr))); } -#line 8403 "built/tmp/cppBison.yxx.c" +#line 8415 "built/tmp/cppBison.yxx.c" break; - case 612: /* const_expr: KW_WCHAR_T '(' optional_const_expr_comma ')' */ -#line 3576 "dtool/src/cppparser/cppBison.yxx" + case 619: /* const_expr: KW_WCHAR_T '(' optional_const_expr_comma ')' */ +#line 3607 "dtool/src/cppparser/cppBison.yxx" { CPPType *type = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_wchar_t)); (yyval.u.expr) = new CPPExpression(CPPExpression::construct_op(type, (yyvsp[-1].u.expr))); } -#line 8413 "built/tmp/cppBison.yxx.c" +#line 8425 "built/tmp/cppBison.yxx.c" break; - case 613: /* const_expr: KW_CHAR8_T '(' optional_const_expr_comma ')' */ -#line 3582 "dtool/src/cppparser/cppBison.yxx" + case 620: /* const_expr: KW_CHAR8_T '(' optional_const_expr_comma ')' */ +#line 3613 "dtool/src/cppparser/cppBison.yxx" { CPPType *type = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_char8_t)); (yyval.u.expr) = new CPPExpression(CPPExpression::construct_op(type, (yyvsp[-1].u.expr))); } -#line 8423 "built/tmp/cppBison.yxx.c" +#line 8435 "built/tmp/cppBison.yxx.c" break; - case 614: /* const_expr: KW_CHAR16_T '(' optional_const_expr_comma ')' */ -#line 3588 "dtool/src/cppparser/cppBison.yxx" + case 621: /* const_expr: KW_CHAR16_T '(' optional_const_expr_comma ')' */ +#line 3619 "dtool/src/cppparser/cppBison.yxx" { CPPType *type = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_char16_t)); (yyval.u.expr) = new CPPExpression(CPPExpression::construct_op(type, (yyvsp[-1].u.expr))); } -#line 8433 "built/tmp/cppBison.yxx.c" +#line 8445 "built/tmp/cppBison.yxx.c" break; - case 615: /* const_expr: KW_CHAR32_T '(' optional_const_expr_comma ')' */ -#line 3594 "dtool/src/cppparser/cppBison.yxx" + case 622: /* const_expr: KW_CHAR32_T '(' optional_const_expr_comma ')' */ +#line 3625 "dtool/src/cppparser/cppBison.yxx" { CPPType *type = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_char32_t)); (yyval.u.expr) = new CPPExpression(CPPExpression::construct_op(type, (yyvsp[-1].u.expr))); } -#line 8443 "built/tmp/cppBison.yxx.c" +#line 8455 "built/tmp/cppBison.yxx.c" break; - case 616: /* const_expr: KW_BOOL '(' optional_const_expr_comma ')' */ -#line 3600 "dtool/src/cppparser/cppBison.yxx" + case 623: /* const_expr: KW_BOOL '(' optional_const_expr_comma ')' */ +#line 3631 "dtool/src/cppparser/cppBison.yxx" { CPPType *type = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_bool)); (yyval.u.expr) = new CPPExpression(CPPExpression::construct_op(type, (yyvsp[-1].u.expr))); } -#line 8453 "built/tmp/cppBison.yxx.c" +#line 8465 "built/tmp/cppBison.yxx.c" break; - case 617: /* const_expr: KW_SHORT '(' optional_const_expr_comma ')' */ -#line 3606 "dtool/src/cppparser/cppBison.yxx" + case 624: /* const_expr: KW_SHORT '(' optional_const_expr_comma ')' */ +#line 3637 "dtool/src/cppparser/cppBison.yxx" { CPPType *type = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_int, CPPSimpleType::F_short)); (yyval.u.expr) = new CPPExpression(CPPExpression::construct_op(type, (yyvsp[-1].u.expr))); } -#line 8464 "built/tmp/cppBison.yxx.c" +#line 8476 "built/tmp/cppBison.yxx.c" break; - case 618: /* const_expr: KW_LONG '(' optional_const_expr_comma ')' */ -#line 3613 "dtool/src/cppparser/cppBison.yxx" + case 625: /* const_expr: KW_LONG '(' optional_const_expr_comma ')' */ +#line 3644 "dtool/src/cppparser/cppBison.yxx" { CPPType *type = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_int, CPPSimpleType::F_long)); (yyval.u.expr) = new CPPExpression(CPPExpression::construct_op(type, (yyvsp[-1].u.expr))); } -#line 8475 "built/tmp/cppBison.yxx.c" +#line 8487 "built/tmp/cppBison.yxx.c" break; - case 619: /* const_expr: KW_UNSIGNED '(' optional_const_expr_comma ')' */ -#line 3620 "dtool/src/cppparser/cppBison.yxx" + case 626: /* const_expr: KW_UNSIGNED '(' optional_const_expr_comma ')' */ +#line 3651 "dtool/src/cppparser/cppBison.yxx" { CPPType *type = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_int, CPPSimpleType::F_unsigned)); (yyval.u.expr) = new CPPExpression(CPPExpression::construct_op(type, (yyvsp[-1].u.expr))); } -#line 8486 "built/tmp/cppBison.yxx.c" +#line 8498 "built/tmp/cppBison.yxx.c" break; - case 620: /* const_expr: KW_SIGNED '(' optional_const_expr_comma ')' */ -#line 3627 "dtool/src/cppparser/cppBison.yxx" + case 627: /* const_expr: KW_SIGNED '(' optional_const_expr_comma ')' */ +#line 3658 "dtool/src/cppparser/cppBison.yxx" { CPPType *type = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_int, CPPSimpleType::F_signed)); (yyval.u.expr) = new CPPExpression(CPPExpression::construct_op(type, (yyvsp[-1].u.expr))); } -#line 8497 "built/tmp/cppBison.yxx.c" +#line 8509 "built/tmp/cppBison.yxx.c" break; - case 621: /* const_expr: KW_FLOAT '(' optional_const_expr_comma ')' */ -#line 3634 "dtool/src/cppparser/cppBison.yxx" + case 628: /* const_expr: KW_FLOAT '(' optional_const_expr_comma ')' */ +#line 3665 "dtool/src/cppparser/cppBison.yxx" { CPPType *type = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_float)); (yyval.u.expr) = new CPPExpression(CPPExpression::construct_op(type, (yyvsp[-1].u.expr))); } -#line 8507 "built/tmp/cppBison.yxx.c" +#line 8519 "built/tmp/cppBison.yxx.c" break; - case 622: /* const_expr: KW_DOUBLE '(' optional_const_expr_comma ')' */ -#line 3640 "dtool/src/cppparser/cppBison.yxx" + case 629: /* const_expr: KW_DOUBLE '(' optional_const_expr_comma ')' */ +#line 3671 "dtool/src/cppparser/cppBison.yxx" { CPPType *type = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_double)); (yyval.u.expr) = new CPPExpression(CPPExpression::construct_op(type, (yyvsp[-1].u.expr))); } -#line 8517 "built/tmp/cppBison.yxx.c" +#line 8529 "built/tmp/cppBison.yxx.c" break; - case 623: /* const_expr: KW_SIZEOF '(' full_type ')' */ -#line 3646 "dtool/src/cppparser/cppBison.yxx" + case 630: /* const_expr: KW_SIZEOF '(' full_type ')' */ +#line 3677 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(CPPExpression::sizeof_func((yyvsp[-1].u.type))); } -#line 8525 "built/tmp/cppBison.yxx.c" +#line 8537 "built/tmp/cppBison.yxx.c" break; - case 624: /* const_expr: KW_SIZEOF const_expr */ -#line 3650 "dtool/src/cppparser/cppBison.yxx" + case 631: /* const_expr: KW_SIZEOF const_expr */ +#line 3681 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(CPPExpression::sizeof_func((yyvsp[0].u.expr))); } -#line 8533 "built/tmp/cppBison.yxx.c" +#line 8545 "built/tmp/cppBison.yxx.c" break; - case 625: /* const_expr: KW_SIZEOF ELLIPSIS '(' name ')' */ -#line 3654 "dtool/src/cppparser/cppBison.yxx" + case 632: /* const_expr: KW_SIZEOF ELLIPSIS '(' name ')' */ +#line 3685 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(CPPExpression::sizeof_ellipsis_func((yyvsp[-1].u.identifier))); } -#line 8541 "built/tmp/cppBison.yxx.c" +#line 8553 "built/tmp/cppBison.yxx.c" break; - case 626: /* const_expr: KW_ALIGNOF '(' full_type ')' */ -#line 3658 "dtool/src/cppparser/cppBison.yxx" + case 633: /* const_expr: KW_ALIGNOF '(' full_type ')' */ +#line 3689 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(CPPExpression::alignof_func((yyvsp[-1].u.type))); } -#line 8549 "built/tmp/cppBison.yxx.c" +#line 8561 "built/tmp/cppBison.yxx.c" break; - case 627: /* const_expr: KW_NEW predefined_type */ -#line 3662 "dtool/src/cppparser/cppBison.yxx" + case 634: /* const_expr: KW_NEW predefined_type */ +#line 3693 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(CPPExpression::new_op((yyvsp[0].u.type))); } -#line 8557 "built/tmp/cppBison.yxx.c" +#line 8569 "built/tmp/cppBison.yxx.c" break; - case 628: /* const_expr: KW_NEW predefined_type '(' optional_const_expr_comma ')' */ -#line 3666 "dtool/src/cppparser/cppBison.yxx" + case 635: /* const_expr: KW_NEW predefined_type '(' optional_const_expr_comma ')' */ +#line 3697 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(CPPExpression::new_op((yyvsp[-3].u.type), (yyvsp[-1].u.expr))); } -#line 8565 "built/tmp/cppBison.yxx.c" +#line 8577 "built/tmp/cppBison.yxx.c" break; - case 629: /* const_expr: KW_TYPEID '(' full_type ')' */ -#line 3670 "dtool/src/cppparser/cppBison.yxx" + case 636: /* const_expr: KW_TYPEID '(' full_type ')' */ +#line 3701 "dtool/src/cppparser/cppBison.yxx" { CPPIdentifier ident(""); ident.add_name("std"); @@ -8576,11 +8588,11 @@ yyreduce: } (yyval.u.expr) = new CPPExpression(CPPExpression::typeid_op((yyvsp[-1].u.type), std_type_info)); } -#line 8580 "built/tmp/cppBison.yxx.c" +#line 8592 "built/tmp/cppBison.yxx.c" break; - case 630: /* const_expr: KW_TYPEID '(' const_expr ')' */ -#line 3681 "dtool/src/cppparser/cppBison.yxx" + case 637: /* const_expr: KW_TYPEID '(' const_expr ')' */ +#line 3712 "dtool/src/cppparser/cppBison.yxx" { CPPIdentifier ident(""); ident.add_name("std"); @@ -8591,378 +8603,378 @@ yyreduce: } (yyval.u.expr) = new CPPExpression(CPPExpression::typeid_op((yyvsp[-1].u.expr), std_type_info)); } -#line 8595 "built/tmp/cppBison.yxx.c" +#line 8607 "built/tmp/cppBison.yxx.c" break; - case 631: /* const_expr: '!' const_expr */ -#line 3692 "dtool/src/cppparser/cppBison.yxx" + case 638: /* const_expr: '!' const_expr */ +#line 3723 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(UNARY_NOT, (yyvsp[0].u.expr)); } -#line 8603 "built/tmp/cppBison.yxx.c" +#line 8615 "built/tmp/cppBison.yxx.c" break; - case 632: /* const_expr: '~' const_expr */ -#line 3696 "dtool/src/cppparser/cppBison.yxx" + case 639: /* const_expr: '~' const_expr */ +#line 3727 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(UNARY_NEGATE, (yyvsp[0].u.expr)); } -#line 8611 "built/tmp/cppBison.yxx.c" +#line 8623 "built/tmp/cppBison.yxx.c" break; - case 633: /* const_expr: '-' const_expr */ -#line 3700 "dtool/src/cppparser/cppBison.yxx" + case 640: /* const_expr: '-' const_expr */ +#line 3731 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(UNARY_MINUS, (yyvsp[0].u.expr)); } -#line 8619 "built/tmp/cppBison.yxx.c" +#line 8631 "built/tmp/cppBison.yxx.c" break; - case 634: /* const_expr: '+' const_expr */ -#line 3704 "dtool/src/cppparser/cppBison.yxx" + case 641: /* const_expr: '+' const_expr */ +#line 3735 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(UNARY_PLUS, (yyvsp[0].u.expr)); } -#line 8627 "built/tmp/cppBison.yxx.c" +#line 8639 "built/tmp/cppBison.yxx.c" break; - case 635: /* const_expr: '*' const_expr */ -#line 3708 "dtool/src/cppparser/cppBison.yxx" + case 642: /* const_expr: '*' const_expr */ +#line 3739 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(UNARY_STAR, (yyvsp[0].u.expr)); } -#line 8635 "built/tmp/cppBison.yxx.c" +#line 8647 "built/tmp/cppBison.yxx.c" break; - case 636: /* const_expr: '&' const_expr */ -#line 3712 "dtool/src/cppparser/cppBison.yxx" + case 643: /* const_expr: '&' const_expr */ +#line 3743 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(UNARY_REF, (yyvsp[0].u.expr)); } -#line 8643 "built/tmp/cppBison.yxx.c" +#line 8655 "built/tmp/cppBison.yxx.c" break; - case 637: /* const_expr: const_expr '*' const_expr */ -#line 3716 "dtool/src/cppparser/cppBison.yxx" + case 644: /* const_expr: const_expr '*' const_expr */ +#line 3747 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression('*', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 8651 "built/tmp/cppBison.yxx.c" +#line 8663 "built/tmp/cppBison.yxx.c" break; - case 638: /* const_expr: const_expr '/' const_expr */ -#line 3720 "dtool/src/cppparser/cppBison.yxx" + case 645: /* const_expr: const_expr '/' const_expr */ +#line 3751 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression('/', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 8659 "built/tmp/cppBison.yxx.c" +#line 8671 "built/tmp/cppBison.yxx.c" break; - case 639: /* const_expr: const_expr '%' const_expr */ -#line 3724 "dtool/src/cppparser/cppBison.yxx" + case 646: /* const_expr: const_expr '%' const_expr */ +#line 3755 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression('%', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 8667 "built/tmp/cppBison.yxx.c" +#line 8679 "built/tmp/cppBison.yxx.c" break; - case 640: /* const_expr: const_expr '+' const_expr */ -#line 3728 "dtool/src/cppparser/cppBison.yxx" + case 647: /* const_expr: const_expr '+' const_expr */ +#line 3759 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression('+', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 8675 "built/tmp/cppBison.yxx.c" +#line 8687 "built/tmp/cppBison.yxx.c" break; - case 641: /* const_expr: const_expr '-' const_expr */ -#line 3732 "dtool/src/cppparser/cppBison.yxx" + case 648: /* const_expr: const_expr '-' const_expr */ +#line 3763 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression('-', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 8683 "built/tmp/cppBison.yxx.c" +#line 8695 "built/tmp/cppBison.yxx.c" break; - case 642: /* const_expr: const_expr '|' const_expr */ -#line 3736 "dtool/src/cppparser/cppBison.yxx" + case 649: /* const_expr: const_expr '|' const_expr */ +#line 3767 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression('|', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 8691 "built/tmp/cppBison.yxx.c" +#line 8703 "built/tmp/cppBison.yxx.c" break; - case 643: /* const_expr: const_expr '^' const_expr */ -#line 3740 "dtool/src/cppparser/cppBison.yxx" + case 650: /* const_expr: const_expr '^' const_expr */ +#line 3771 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression('^', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 8699 "built/tmp/cppBison.yxx.c" +#line 8711 "built/tmp/cppBison.yxx.c" break; - case 644: /* const_expr: const_expr '&' const_expr */ -#line 3744 "dtool/src/cppparser/cppBison.yxx" + case 651: /* const_expr: const_expr '&' const_expr */ +#line 3775 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression('&', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 8707 "built/tmp/cppBison.yxx.c" +#line 8719 "built/tmp/cppBison.yxx.c" break; - case 645: /* const_expr: const_expr OROR const_expr */ -#line 3748 "dtool/src/cppparser/cppBison.yxx" + case 652: /* const_expr: const_expr OROR const_expr */ +#line 3779 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(OROR, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 8715 "built/tmp/cppBison.yxx.c" +#line 8727 "built/tmp/cppBison.yxx.c" break; - case 646: /* const_expr: const_expr ANDAND const_expr */ -#line 3752 "dtool/src/cppparser/cppBison.yxx" + case 653: /* const_expr: const_expr ANDAND const_expr */ +#line 3783 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(ANDAND, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 8723 "built/tmp/cppBison.yxx.c" +#line 8735 "built/tmp/cppBison.yxx.c" break; - case 647: /* const_expr: const_expr EQCOMPARE const_expr */ -#line 3756 "dtool/src/cppparser/cppBison.yxx" + case 654: /* const_expr: const_expr EQCOMPARE const_expr */ +#line 3787 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(EQCOMPARE, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 8731 "built/tmp/cppBison.yxx.c" +#line 8743 "built/tmp/cppBison.yxx.c" break; - case 648: /* const_expr: const_expr NECOMPARE const_expr */ -#line 3760 "dtool/src/cppparser/cppBison.yxx" + case 655: /* const_expr: const_expr NECOMPARE const_expr */ +#line 3791 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(NECOMPARE, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 8739 "built/tmp/cppBison.yxx.c" +#line 8751 "built/tmp/cppBison.yxx.c" break; - case 649: /* const_expr: const_expr LECOMPARE const_expr */ -#line 3764 "dtool/src/cppparser/cppBison.yxx" + case 656: /* const_expr: const_expr LECOMPARE const_expr */ +#line 3795 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(LECOMPARE, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 8747 "built/tmp/cppBison.yxx.c" +#line 8759 "built/tmp/cppBison.yxx.c" break; - case 650: /* const_expr: const_expr GECOMPARE const_expr */ -#line 3768 "dtool/src/cppparser/cppBison.yxx" + case 657: /* const_expr: const_expr GECOMPARE const_expr */ +#line 3799 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(GECOMPARE, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 8755 "built/tmp/cppBison.yxx.c" +#line 8767 "built/tmp/cppBison.yxx.c" break; - case 651: /* const_expr: const_expr SPACESHIP const_expr */ -#line 3772 "dtool/src/cppparser/cppBison.yxx" + case 658: /* const_expr: const_expr SPACESHIP const_expr */ +#line 3803 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(SPACESHIP, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 8763 "built/tmp/cppBison.yxx.c" +#line 8775 "built/tmp/cppBison.yxx.c" break; - case 652: /* const_expr: const_expr '<' const_expr */ -#line 3776 "dtool/src/cppparser/cppBison.yxx" + case 659: /* const_expr: const_expr '<' const_expr */ +#line 3807 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression('<', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 8771 "built/tmp/cppBison.yxx.c" +#line 8783 "built/tmp/cppBison.yxx.c" break; - case 653: /* const_expr: const_expr '>' const_expr */ -#line 3780 "dtool/src/cppparser/cppBison.yxx" + case 660: /* const_expr: const_expr '>' const_expr */ +#line 3811 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression('>', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 8779 "built/tmp/cppBison.yxx.c" +#line 8791 "built/tmp/cppBison.yxx.c" break; - case 654: /* const_expr: const_expr LSHIFT const_expr */ -#line 3784 "dtool/src/cppparser/cppBison.yxx" + case 661: /* const_expr: const_expr LSHIFT const_expr */ +#line 3815 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(LSHIFT, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 8787 "built/tmp/cppBison.yxx.c" +#line 8799 "built/tmp/cppBison.yxx.c" break; - case 655: /* const_expr: const_expr RSHIFT const_expr */ -#line 3788 "dtool/src/cppparser/cppBison.yxx" + case 662: /* const_expr: const_expr RSHIFT const_expr */ +#line 3819 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(RSHIFT, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 8795 "built/tmp/cppBison.yxx.c" +#line 8807 "built/tmp/cppBison.yxx.c" break; - case 656: /* const_expr: const_expr '?' const_expr ':' const_expr */ -#line 3792 "dtool/src/cppparser/cppBison.yxx" + case 663: /* const_expr: const_expr '?' const_expr ':' const_expr */ +#line 3823 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression('?', (yyvsp[-4].u.expr), (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 8803 "built/tmp/cppBison.yxx.c" +#line 8815 "built/tmp/cppBison.yxx.c" break; - case 657: /* const_expr: const_expr '[' const_expr ']' */ -#line 3796 "dtool/src/cppparser/cppBison.yxx" + case 664: /* const_expr: const_expr '[' const_expr ']' */ +#line 3827 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression('[', (yyvsp[-3].u.expr), (yyvsp[-1].u.expr)); } -#line 8811 "built/tmp/cppBison.yxx.c" +#line 8823 "built/tmp/cppBison.yxx.c" break; - case 658: /* const_expr: const_expr '(' const_expr_comma ')' */ -#line 3800 "dtool/src/cppparser/cppBison.yxx" + case 665: /* const_expr: const_expr '(' const_expr_comma ')' */ +#line 3831 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression('f', (yyvsp[-3].u.expr), (yyvsp[-1].u.expr)); } -#line 8819 "built/tmp/cppBison.yxx.c" +#line 8831 "built/tmp/cppBison.yxx.c" break; - case 659: /* const_expr: const_expr '(' ')' */ -#line 3804 "dtool/src/cppparser/cppBison.yxx" + case 666: /* const_expr: const_expr '(' ')' */ +#line 3835 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression('f', (yyvsp[-2].u.expr)); } -#line 8827 "built/tmp/cppBison.yxx.c" +#line 8839 "built/tmp/cppBison.yxx.c" break; - case 660: /* const_expr: KW_NOEXCEPT_LPAREN const_expr ')' */ -#line 3808 "dtool/src/cppparser/cppBison.yxx" + case 667: /* const_expr: KW_NOEXCEPT_LPAREN const_expr ')' */ +#line 3839 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(KW_NOEXCEPT, (yyvsp[-1].u.expr)); } -#line 8835 "built/tmp/cppBison.yxx.c" +#line 8847 "built/tmp/cppBison.yxx.c" break; - case 661: /* const_expr: const_expr '.' name */ -#line 3812 "dtool/src/cppparser/cppBison.yxx" + case 668: /* const_expr: const_expr '.' name */ +#line 3843 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression('.', (yyvsp[-2].u.expr), new CPPExpression((yyvsp[0].u.identifier), current_scope, global_scope, current_lexer)); } -#line 8843 "built/tmp/cppBison.yxx.c" +#line 8855 "built/tmp/cppBison.yxx.c" break; - case 662: /* const_expr: const_expr POINTSAT const_expr */ -#line 3816 "dtool/src/cppparser/cppBison.yxx" + case 669: /* const_expr: const_expr POINTSAT const_expr */ +#line 3847 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(POINTSAT, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 8851 "built/tmp/cppBison.yxx.c" +#line 8863 "built/tmp/cppBison.yxx.c" break; - case 663: /* const_expr: '(' const_expr_comma ')' */ -#line 3820 "dtool/src/cppparser/cppBison.yxx" + case 670: /* const_expr: '(' const_expr_comma ')' */ +#line 3851 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = (yyvsp[-1].u.expr); } -#line 8859 "built/tmp/cppBison.yxx.c" +#line 8871 "built/tmp/cppBison.yxx.c" break; - case 664: /* const_operand: INTEGER */ -#line 3827 "dtool/src/cppparser/cppBison.yxx" + case 671: /* const_operand: INTEGER */ +#line 3858 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression((yyvsp[0].u.integer)); } -#line 8867 "built/tmp/cppBison.yxx.c" +#line 8879 "built/tmp/cppBison.yxx.c" break; - case 665: /* const_operand: KW_TRUE */ -#line 3831 "dtool/src/cppparser/cppBison.yxx" + case 672: /* const_operand: KW_TRUE */ +#line 3862 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(true); } -#line 8875 "built/tmp/cppBison.yxx.c" +#line 8887 "built/tmp/cppBison.yxx.c" break; - case 666: /* const_operand: KW_FALSE */ -#line 3835 "dtool/src/cppparser/cppBison.yxx" + case 673: /* const_operand: KW_FALSE */ +#line 3866 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(false); } -#line 8883 "built/tmp/cppBison.yxx.c" +#line 8895 "built/tmp/cppBison.yxx.c" break; - case 667: /* const_operand: CHAR_TOK */ -#line 3839 "dtool/src/cppparser/cppBison.yxx" + case 674: /* const_operand: CHAR_TOK */ +#line 3870 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression((yyvsp[0].u.integer)); } -#line 8891 "built/tmp/cppBison.yxx.c" +#line 8903 "built/tmp/cppBison.yxx.c" break; - case 668: /* const_operand: REAL */ -#line 3843 "dtool/src/cppparser/cppBison.yxx" + case 675: /* const_operand: REAL */ +#line 3874 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression((yyvsp[0].u.real)); } -#line 8899 "built/tmp/cppBison.yxx.c" +#line 8911 "built/tmp/cppBison.yxx.c" break; - case 669: /* const_operand: string_literal */ -#line 3847 "dtool/src/cppparser/cppBison.yxx" + case 676: /* const_operand: string_literal */ +#line 3878 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = (yyvsp[0].u.expr); } -#line 8907 "built/tmp/cppBison.yxx.c" +#line 8919 "built/tmp/cppBison.yxx.c" break; - case 670: /* const_operand: CUSTOM_LITERAL */ -#line 3851 "dtool/src/cppparser/cppBison.yxx" + case 677: /* const_operand: CUSTOM_LITERAL */ +#line 3882 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = (yyvsp[0].u.expr); } -#line 8915 "built/tmp/cppBison.yxx.c" +#line 8927 "built/tmp/cppBison.yxx.c" break; - case 671: /* const_operand: IDENTIFIER */ -#line 3855 "dtool/src/cppparser/cppBison.yxx" + case 678: /* const_operand: IDENTIFIER */ +#line 3886 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression((yyvsp[0].u.identifier), current_scope, global_scope, current_lexer); } -#line 8923 "built/tmp/cppBison.yxx.c" +#line 8935 "built/tmp/cppBison.yxx.c" break; - case 672: /* const_operand: KW_FINAL */ -#line 3859 "dtool/src/cppparser/cppBison.yxx" + case 679: /* const_operand: KW_FINAL */ +#line 3890 "dtool/src/cppparser/cppBison.yxx" { // A variable named "final". C++11 explicitly permits this. CPPIdentifier *ident = new CPPIdentifier("final", (yylsp[0])); (yyval.u.expr) = new CPPExpression(ident, current_scope, global_scope, current_lexer); } -#line 8933 "built/tmp/cppBison.yxx.c" +#line 8945 "built/tmp/cppBison.yxx.c" break; - case 673: /* const_operand: KW_OVERRIDE */ -#line 3865 "dtool/src/cppparser/cppBison.yxx" + case 680: /* const_operand: KW_OVERRIDE */ +#line 3896 "dtool/src/cppparser/cppBison.yxx" { // A variable named "override". C++11 explicitly permits this. CPPIdentifier *ident = new CPPIdentifier("override", (yylsp[0])); (yyval.u.expr) = new CPPExpression(ident, current_scope, global_scope, current_lexer); } -#line 8943 "built/tmp/cppBison.yxx.c" +#line 8955 "built/tmp/cppBison.yxx.c" break; - case 674: /* const_operand: KW_NULLPTR */ -#line 3871 "dtool/src/cppparser/cppBison.yxx" + case 681: /* const_operand: KW_NULLPTR */ +#line 3902 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(CPPExpression::get_nullptr()); } -#line 8951 "built/tmp/cppBison.yxx.c" +#line 8963 "built/tmp/cppBison.yxx.c" break; - case 675: /* const_operand: '[' capture_list ']' function_post optional_attributes maybe_trailing_return_type '{' code '}' */ -#line 3875 "dtool/src/cppparser/cppBison.yxx" + case 682: /* const_operand: '[' capture_list ']' function_post optional_attributes maybe_trailing_return_type '{' code '}' */ +#line 3906 "dtool/src/cppparser/cppBison.yxx" { (yyvsp[-7].u.closure_type)->_flags = (yyvsp[-5].u.integer); (yyvsp[-7].u.closure_type)->_attributes = (yyvsp[-4].attr_list); (yyvsp[-7].u.closure_type)->_return_type = (yyvsp[-3].u.type); (yyval.u.expr) = new CPPExpression(CPPExpression::lambda((yyvsp[-7].u.closure_type))); } -#line 8962 "built/tmp/cppBison.yxx.c" +#line 8974 "built/tmp/cppBison.yxx.c" break; - case 676: /* const_operand: '[' capture_list ']' '(' function_parameter_list ')' function_post optional_attributes maybe_trailing_return_type '{' code '}' */ -#line 3882 "dtool/src/cppparser/cppBison.yxx" + case 683: /* const_operand: '[' capture_list ']' '(' function_parameter_list ')' function_post optional_attributes maybe_trailing_return_type '{' code '}' */ +#line 3913 "dtool/src/cppparser/cppBison.yxx" { (yyvsp[-10].u.closure_type)->_parameters = (yyvsp[-7].u.param_list); (yyvsp[-10].u.closure_type)->_flags = (yyvsp[-5].u.integer); @@ -8970,251 +8982,251 @@ yyreduce: (yyvsp[-10].u.closure_type)->_return_type = (yyvsp[-3].u.type); (yyval.u.expr) = new CPPExpression(CPPExpression::lambda((yyvsp[-10].u.closure_type))); } -#line 8974 "built/tmp/cppBison.yxx.c" +#line 8986 "built/tmp/cppBison.yxx.c" break; - case 677: /* const_operand: KW_HAS_VIRTUAL_DESTRUCTOR '(' full_type ')' */ -#line 3890 "dtool/src/cppparser/cppBison.yxx" + case 684: /* const_operand: KW_HAS_VIRTUAL_DESTRUCTOR '(' full_type ')' */ +#line 3921 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(CPPExpression::type_trait(KW_HAS_VIRTUAL_DESTRUCTOR, (yyvsp[-1].u.type))); } -#line 8982 "built/tmp/cppBison.yxx.c" +#line 8994 "built/tmp/cppBison.yxx.c" break; - case 678: /* const_operand: KW_IS_ABSTRACT '(' full_type ')' */ -#line 3894 "dtool/src/cppparser/cppBison.yxx" + case 685: /* const_operand: KW_IS_ABSTRACT '(' full_type ')' */ +#line 3925 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(CPPExpression::type_trait(KW_IS_ABSTRACT, (yyvsp[-1].u.type))); } -#line 8990 "built/tmp/cppBison.yxx.c" +#line 9002 "built/tmp/cppBison.yxx.c" break; - case 679: /* const_operand: KW_IS_BASE_OF '(' full_type ',' full_type ')' */ -#line 3898 "dtool/src/cppparser/cppBison.yxx" + case 686: /* const_operand: KW_IS_BASE_OF '(' full_type ',' full_type ')' */ +#line 3929 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(CPPExpression::type_trait(KW_IS_CLASS, (yyvsp[-3].u.type), (yyvsp[-1].u.type))); } -#line 8998 "built/tmp/cppBison.yxx.c" +#line 9010 "built/tmp/cppBison.yxx.c" break; - case 680: /* const_operand: KW_IS_CLASS '(' full_type ')' */ -#line 3902 "dtool/src/cppparser/cppBison.yxx" + case 687: /* const_operand: KW_IS_CLASS '(' full_type ')' */ +#line 3933 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(CPPExpression::type_trait(KW_IS_CLASS, (yyvsp[-1].u.type))); } -#line 9006 "built/tmp/cppBison.yxx.c" +#line 9018 "built/tmp/cppBison.yxx.c" break; - case 681: /* const_operand: KW_IS_CONSTRUCTIBLE '(' full_type ')' */ -#line 3906 "dtool/src/cppparser/cppBison.yxx" + case 688: /* const_operand: KW_IS_CONSTRUCTIBLE '(' full_type ')' */ +#line 3937 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(CPPExpression::type_trait(KW_IS_CONSTRUCTIBLE, (yyvsp[-1].u.type))); } -#line 9014 "built/tmp/cppBison.yxx.c" +#line 9026 "built/tmp/cppBison.yxx.c" break; - case 682: /* const_operand: KW_IS_CONSTRUCTIBLE '(' full_type ',' full_type ')' */ -#line 3910 "dtool/src/cppparser/cppBison.yxx" + case 689: /* const_operand: KW_IS_CONSTRUCTIBLE '(' full_type ',' full_type ')' */ +#line 3941 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(CPPExpression::type_trait(KW_IS_CONSTRUCTIBLE, (yyvsp[-3].u.type), (yyvsp[-1].u.type))); } -#line 9022 "built/tmp/cppBison.yxx.c" +#line 9034 "built/tmp/cppBison.yxx.c" break; - case 683: /* const_operand: KW_IS_CONVERTIBLE_TO '(' full_type ',' full_type ')' */ -#line 3914 "dtool/src/cppparser/cppBison.yxx" + case 690: /* const_operand: KW_IS_CONVERTIBLE_TO '(' full_type ',' full_type ')' */ +#line 3945 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(CPPExpression::type_trait(KW_IS_CONVERTIBLE_TO, (yyvsp[-3].u.type), (yyvsp[-1].u.type))); } -#line 9030 "built/tmp/cppBison.yxx.c" +#line 9042 "built/tmp/cppBison.yxx.c" break; - case 684: /* const_operand: KW_IS_DESTRUCTIBLE '(' full_type ')' */ -#line 3918 "dtool/src/cppparser/cppBison.yxx" + case 691: /* const_operand: KW_IS_DESTRUCTIBLE '(' full_type ')' */ +#line 3949 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(CPPExpression::type_trait(KW_IS_DESTRUCTIBLE, (yyvsp[-1].u.type))); } -#line 9038 "built/tmp/cppBison.yxx.c" +#line 9050 "built/tmp/cppBison.yxx.c" break; - case 685: /* const_operand: KW_IS_EMPTY '(' full_type ')' */ -#line 3922 "dtool/src/cppparser/cppBison.yxx" + case 692: /* const_operand: KW_IS_EMPTY '(' full_type ')' */ +#line 3953 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(CPPExpression::type_trait(KW_IS_EMPTY, (yyvsp[-1].u.type))); } -#line 9046 "built/tmp/cppBison.yxx.c" +#line 9058 "built/tmp/cppBison.yxx.c" break; - case 686: /* const_operand: KW_IS_ENUM '(' full_type ')' */ -#line 3926 "dtool/src/cppparser/cppBison.yxx" + case 693: /* const_operand: KW_IS_ENUM '(' full_type ')' */ +#line 3957 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(CPPExpression::type_trait(KW_IS_ENUM, (yyvsp[-1].u.type))); } -#line 9054 "built/tmp/cppBison.yxx.c" +#line 9066 "built/tmp/cppBison.yxx.c" break; - case 687: /* const_operand: KW_IS_FINAL '(' full_type ')' */ -#line 3930 "dtool/src/cppparser/cppBison.yxx" + case 694: /* const_operand: KW_IS_FINAL '(' full_type ')' */ +#line 3961 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(CPPExpression::type_trait(KW_IS_FINAL, (yyvsp[-1].u.type))); } -#line 9062 "built/tmp/cppBison.yxx.c" +#line 9074 "built/tmp/cppBison.yxx.c" break; - case 688: /* const_operand: KW_IS_FUNDAMENTAL '(' full_type ')' */ -#line 3934 "dtool/src/cppparser/cppBison.yxx" + case 695: /* const_operand: KW_IS_FUNDAMENTAL '(' full_type ')' */ +#line 3965 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(CPPExpression::type_trait(KW_IS_FUNDAMENTAL, (yyvsp[-1].u.type))); } -#line 9070 "built/tmp/cppBison.yxx.c" +#line 9082 "built/tmp/cppBison.yxx.c" break; - case 689: /* const_operand: KW_IS_POD '(' full_type ')' */ -#line 3938 "dtool/src/cppparser/cppBison.yxx" + case 696: /* const_operand: KW_IS_POD '(' full_type ')' */ +#line 3969 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(CPPExpression::type_trait(KW_IS_POD, (yyvsp[-1].u.type))); } -#line 9078 "built/tmp/cppBison.yxx.c" +#line 9090 "built/tmp/cppBison.yxx.c" break; - case 690: /* const_operand: KW_IS_POLYMORPHIC '(' full_type ')' */ -#line 3942 "dtool/src/cppparser/cppBison.yxx" + case 697: /* const_operand: KW_IS_POLYMORPHIC '(' full_type ')' */ +#line 3973 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(CPPExpression::type_trait(KW_IS_POLYMORPHIC, (yyvsp[-1].u.type))); } -#line 9086 "built/tmp/cppBison.yxx.c" +#line 9098 "built/tmp/cppBison.yxx.c" break; - case 691: /* const_operand: KW_IS_STANDARD_LAYOUT '(' full_type ')' */ -#line 3946 "dtool/src/cppparser/cppBison.yxx" + case 698: /* const_operand: KW_IS_STANDARD_LAYOUT '(' full_type ')' */ +#line 3977 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(CPPExpression::type_trait(KW_IS_STANDARD_LAYOUT, (yyvsp[-1].u.type))); } -#line 9094 "built/tmp/cppBison.yxx.c" +#line 9106 "built/tmp/cppBison.yxx.c" break; - case 692: /* const_operand: KW_IS_TRIVIAL '(' full_type ')' */ -#line 3950 "dtool/src/cppparser/cppBison.yxx" + case 699: /* const_operand: KW_IS_TRIVIAL '(' full_type ')' */ +#line 3981 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(CPPExpression::type_trait(KW_IS_TRIVIAL, (yyvsp[-1].u.type))); } -#line 9102 "built/tmp/cppBison.yxx.c" +#line 9114 "built/tmp/cppBison.yxx.c" break; - case 693: /* const_operand: KW_IS_TRIVIALLY_COPYABLE '(' full_type ')' */ -#line 3954 "dtool/src/cppparser/cppBison.yxx" + case 700: /* const_operand: KW_IS_TRIVIALLY_COPYABLE '(' full_type ')' */ +#line 3985 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(CPPExpression::type_trait(KW_IS_TRIVIALLY_COPYABLE, (yyvsp[-1].u.type))); } -#line 9110 "built/tmp/cppBison.yxx.c" +#line 9122 "built/tmp/cppBison.yxx.c" break; - case 694: /* const_operand: KW_IS_UNION '(' full_type ')' */ -#line 3958 "dtool/src/cppparser/cppBison.yxx" + case 701: /* const_operand: KW_IS_UNION '(' full_type ')' */ +#line 3989 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(CPPExpression::type_trait(KW_IS_UNION, (yyvsp[-1].u.type))); } -#line 9118 "built/tmp/cppBison.yxx.c" +#line 9130 "built/tmp/cppBison.yxx.c" break; - case 695: /* formal_const_expr: formal_const_operand */ -#line 3972 "dtool/src/cppparser/cppBison.yxx" + case 702: /* formal_const_expr: formal_const_operand */ +#line 4003 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = (yyvsp[0].u.expr); } -#line 9126 "built/tmp/cppBison.yxx.c" +#line 9138 "built/tmp/cppBison.yxx.c" break; - case 696: /* formal_const_expr: '(' full_type ')' const_expr */ -#line 3976 "dtool/src/cppparser/cppBison.yxx" + case 703: /* formal_const_expr: '(' full_type ')' const_expr */ +#line 4007 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(CPPExpression::typecast_op((yyvsp[-2].u.type), (yyvsp[0].u.expr))); } -#line 9134 "built/tmp/cppBison.yxx.c" +#line 9146 "built/tmp/cppBison.yxx.c" break; - case 697: /* formal_const_expr: KW_STATIC_CAST '<' full_type '>' '(' const_expr_comma ')' */ -#line 3980 "dtool/src/cppparser/cppBison.yxx" + case 704: /* formal_const_expr: KW_STATIC_CAST '<' full_type '>' '(' const_expr_comma ')' */ +#line 4011 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(CPPExpression::typecast_op((yyvsp[-4].u.type), (yyvsp[-1].u.expr), CPPExpression::T_static_cast)); } -#line 9142 "built/tmp/cppBison.yxx.c" +#line 9154 "built/tmp/cppBison.yxx.c" break; - case 698: /* formal_const_expr: KW_DYNAMIC_CAST '<' full_type '>' '(' const_expr_comma ')' */ -#line 3984 "dtool/src/cppparser/cppBison.yxx" + case 705: /* formal_const_expr: KW_DYNAMIC_CAST '<' full_type '>' '(' const_expr_comma ')' */ +#line 4015 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(CPPExpression::typecast_op((yyvsp[-4].u.type), (yyvsp[-1].u.expr), CPPExpression::T_dynamic_cast)); } -#line 9150 "built/tmp/cppBison.yxx.c" +#line 9162 "built/tmp/cppBison.yxx.c" break; - case 699: /* formal_const_expr: KW_CONST_CAST '<' full_type '>' '(' const_expr_comma ')' */ -#line 3988 "dtool/src/cppparser/cppBison.yxx" + case 706: /* formal_const_expr: KW_CONST_CAST '<' full_type '>' '(' const_expr_comma ')' */ +#line 4019 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(CPPExpression::typecast_op((yyvsp[-4].u.type), (yyvsp[-1].u.expr), CPPExpression::T_const_cast)); } -#line 9158 "built/tmp/cppBison.yxx.c" +#line 9170 "built/tmp/cppBison.yxx.c" break; - case 700: /* formal_const_expr: KW_REINTERPRET_CAST '<' full_type '>' '(' const_expr_comma ')' */ -#line 3992 "dtool/src/cppparser/cppBison.yxx" + case 707: /* formal_const_expr: KW_REINTERPRET_CAST '<' full_type '>' '(' const_expr_comma ')' */ +#line 4023 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(CPPExpression::typecast_op((yyvsp[-4].u.type), (yyvsp[-1].u.expr), CPPExpression::T_reinterpret_cast)); } -#line 9166 "built/tmp/cppBison.yxx.c" +#line 9178 "built/tmp/cppBison.yxx.c" break; - case 701: /* formal_const_expr: KW_SIZEOF '(' full_type ')' */ -#line 3996 "dtool/src/cppparser/cppBison.yxx" + case 708: /* formal_const_expr: KW_SIZEOF '(' full_type ')' */ +#line 4027 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(CPPExpression::sizeof_func((yyvsp[-1].u.type))); } -#line 9174 "built/tmp/cppBison.yxx.c" +#line 9186 "built/tmp/cppBison.yxx.c" break; - case 702: /* formal_const_expr: KW_SIZEOF formal_const_expr */ -#line 4000 "dtool/src/cppparser/cppBison.yxx" + case 709: /* formal_const_expr: KW_SIZEOF formal_const_expr */ +#line 4031 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(CPPExpression::sizeof_func((yyvsp[0].u.expr))); } -#line 9182 "built/tmp/cppBison.yxx.c" +#line 9194 "built/tmp/cppBison.yxx.c" break; - case 703: /* formal_const_expr: KW_SIZEOF ELLIPSIS '(' name ')' */ -#line 4004 "dtool/src/cppparser/cppBison.yxx" + case 710: /* formal_const_expr: KW_SIZEOF ELLIPSIS '(' name ')' */ +#line 4035 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(CPPExpression::sizeof_ellipsis_func((yyvsp[-1].u.identifier))); } -#line 9190 "built/tmp/cppBison.yxx.c" +#line 9202 "built/tmp/cppBison.yxx.c" break; - case 704: /* formal_const_expr: KW_ALIGNOF '(' full_type ')' */ -#line 4008 "dtool/src/cppparser/cppBison.yxx" + case 711: /* formal_const_expr: KW_ALIGNOF '(' full_type ')' */ +#line 4039 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(CPPExpression::alignof_func((yyvsp[-1].u.type))); } -#line 9198 "built/tmp/cppBison.yxx.c" +#line 9210 "built/tmp/cppBison.yxx.c" break; - case 705: /* formal_const_expr: KW_NEW predefined_type */ -#line 4012 "dtool/src/cppparser/cppBison.yxx" + case 712: /* formal_const_expr: KW_NEW predefined_type */ +#line 4043 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(CPPExpression::new_op((yyvsp[0].u.type))); } -#line 9206 "built/tmp/cppBison.yxx.c" +#line 9218 "built/tmp/cppBison.yxx.c" break; - case 706: /* formal_const_expr: KW_NEW predefined_type '(' optional_const_expr_comma ')' */ -#line 4016 "dtool/src/cppparser/cppBison.yxx" + case 713: /* formal_const_expr: KW_NEW predefined_type '(' optional_const_expr_comma ')' */ +#line 4047 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(CPPExpression::new_op((yyvsp[-3].u.type), (yyvsp[-1].u.expr))); } -#line 9214 "built/tmp/cppBison.yxx.c" +#line 9226 "built/tmp/cppBison.yxx.c" break; - case 707: /* formal_const_expr: KW_TYPEID '(' full_type ')' */ -#line 4020 "dtool/src/cppparser/cppBison.yxx" + case 714: /* formal_const_expr: KW_TYPEID '(' full_type ')' */ +#line 4051 "dtool/src/cppparser/cppBison.yxx" { CPPIdentifier ident(""); ident.add_name("std"); @@ -9225,11 +9237,11 @@ yyreduce: } (yyval.u.expr) = new CPPExpression(CPPExpression::typeid_op((yyvsp[-1].u.type), std_type_info)); } -#line 9229 "built/tmp/cppBison.yxx.c" +#line 9241 "built/tmp/cppBison.yxx.c" break; - case 708: /* formal_const_expr: KW_TYPEID '(' const_expr ')' */ -#line 4031 "dtool/src/cppparser/cppBison.yxx" + case 715: /* formal_const_expr: KW_TYPEID '(' const_expr ')' */ +#line 4062 "dtool/src/cppparser/cppBison.yxx" { CPPIdentifier ident(""); ident.add_name("std"); @@ -9240,417 +9252,417 @@ yyreduce: } (yyval.u.expr) = new CPPExpression(CPPExpression::typeid_op((yyvsp[-1].u.expr), std_type_info)); } -#line 9244 "built/tmp/cppBison.yxx.c" +#line 9256 "built/tmp/cppBison.yxx.c" break; - case 709: /* formal_const_expr: '!' const_expr */ -#line 4042 "dtool/src/cppparser/cppBison.yxx" + case 716: /* formal_const_expr: '!' const_expr */ +#line 4073 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(UNARY_NOT, (yyvsp[0].u.expr)); } -#line 9252 "built/tmp/cppBison.yxx.c" +#line 9264 "built/tmp/cppBison.yxx.c" break; - case 710: /* formal_const_expr: '~' const_expr */ -#line 4046 "dtool/src/cppparser/cppBison.yxx" + case 717: /* formal_const_expr: '~' const_expr */ +#line 4077 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(UNARY_NEGATE, (yyvsp[0].u.expr)); } -#line 9260 "built/tmp/cppBison.yxx.c" +#line 9272 "built/tmp/cppBison.yxx.c" break; - case 711: /* formal_const_expr: '-' const_expr */ -#line 4050 "dtool/src/cppparser/cppBison.yxx" + case 718: /* formal_const_expr: '-' const_expr */ +#line 4081 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(UNARY_MINUS, (yyvsp[0].u.expr)); } -#line 9268 "built/tmp/cppBison.yxx.c" +#line 9280 "built/tmp/cppBison.yxx.c" break; - case 712: /* formal_const_expr: '+' const_expr */ -#line 4054 "dtool/src/cppparser/cppBison.yxx" + case 719: /* formal_const_expr: '+' const_expr */ +#line 4085 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(UNARY_PLUS, (yyvsp[0].u.expr)); } -#line 9276 "built/tmp/cppBison.yxx.c" +#line 9288 "built/tmp/cppBison.yxx.c" break; - case 713: /* formal_const_expr: '&' const_expr */ -#line 4058 "dtool/src/cppparser/cppBison.yxx" + case 720: /* formal_const_expr: '&' const_expr */ +#line 4089 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(UNARY_REF, (yyvsp[0].u.expr)); } -#line 9284 "built/tmp/cppBison.yxx.c" +#line 9296 "built/tmp/cppBison.yxx.c" break; - case 714: /* formal_const_expr: formal_const_expr '*' const_expr */ -#line 4062 "dtool/src/cppparser/cppBison.yxx" + case 721: /* formal_const_expr: formal_const_expr '*' const_expr */ +#line 4093 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression('*', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 9292 "built/tmp/cppBison.yxx.c" +#line 9304 "built/tmp/cppBison.yxx.c" break; - case 715: /* formal_const_expr: formal_const_expr '/' const_expr */ -#line 4066 "dtool/src/cppparser/cppBison.yxx" + case 722: /* formal_const_expr: formal_const_expr '/' const_expr */ +#line 4097 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression('/', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 9300 "built/tmp/cppBison.yxx.c" +#line 9312 "built/tmp/cppBison.yxx.c" break; - case 716: /* formal_const_expr: formal_const_expr '%' const_expr */ -#line 4070 "dtool/src/cppparser/cppBison.yxx" + case 723: /* formal_const_expr: formal_const_expr '%' const_expr */ +#line 4101 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression('%', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 9308 "built/tmp/cppBison.yxx.c" +#line 9320 "built/tmp/cppBison.yxx.c" break; - case 717: /* formal_const_expr: formal_const_expr '+' const_expr */ -#line 4074 "dtool/src/cppparser/cppBison.yxx" + case 724: /* formal_const_expr: formal_const_expr '+' const_expr */ +#line 4105 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression('+', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 9316 "built/tmp/cppBison.yxx.c" +#line 9328 "built/tmp/cppBison.yxx.c" break; - case 718: /* formal_const_expr: formal_const_expr '-' const_expr */ -#line 4078 "dtool/src/cppparser/cppBison.yxx" + case 725: /* formal_const_expr: formal_const_expr '-' const_expr */ +#line 4109 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression('-', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 9324 "built/tmp/cppBison.yxx.c" +#line 9336 "built/tmp/cppBison.yxx.c" break; - case 719: /* formal_const_expr: formal_const_expr '|' const_expr */ -#line 4082 "dtool/src/cppparser/cppBison.yxx" + case 726: /* formal_const_expr: formal_const_expr '|' const_expr */ +#line 4113 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression('|', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 9332 "built/tmp/cppBison.yxx.c" +#line 9344 "built/tmp/cppBison.yxx.c" break; - case 720: /* formal_const_expr: formal_const_expr '^' const_expr */ -#line 4086 "dtool/src/cppparser/cppBison.yxx" + case 727: /* formal_const_expr: formal_const_expr '^' const_expr */ +#line 4117 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression('^', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 9340 "built/tmp/cppBison.yxx.c" +#line 9352 "built/tmp/cppBison.yxx.c" break; - case 721: /* formal_const_expr: formal_const_expr '&' const_expr */ -#line 4090 "dtool/src/cppparser/cppBison.yxx" + case 728: /* formal_const_expr: formal_const_expr '&' const_expr */ +#line 4121 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression('&', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 9348 "built/tmp/cppBison.yxx.c" +#line 9360 "built/tmp/cppBison.yxx.c" break; - case 722: /* formal_const_expr: formal_const_expr OROR const_expr */ -#line 4094 "dtool/src/cppparser/cppBison.yxx" + case 729: /* formal_const_expr: formal_const_expr OROR const_expr */ +#line 4125 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(OROR, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 9356 "built/tmp/cppBison.yxx.c" +#line 9368 "built/tmp/cppBison.yxx.c" break; - case 723: /* formal_const_expr: formal_const_expr ANDAND const_expr */ -#line 4098 "dtool/src/cppparser/cppBison.yxx" + case 730: /* formal_const_expr: formal_const_expr ANDAND const_expr */ +#line 4129 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(ANDAND, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 9364 "built/tmp/cppBison.yxx.c" +#line 9376 "built/tmp/cppBison.yxx.c" break; - case 724: /* formal_const_expr: formal_const_expr EQCOMPARE const_expr */ -#line 4102 "dtool/src/cppparser/cppBison.yxx" + case 731: /* formal_const_expr: formal_const_expr EQCOMPARE const_expr */ +#line 4133 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(EQCOMPARE, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 9372 "built/tmp/cppBison.yxx.c" +#line 9384 "built/tmp/cppBison.yxx.c" break; - case 725: /* formal_const_expr: formal_const_expr NECOMPARE const_expr */ -#line 4106 "dtool/src/cppparser/cppBison.yxx" + case 732: /* formal_const_expr: formal_const_expr NECOMPARE const_expr */ +#line 4137 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(NECOMPARE, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 9380 "built/tmp/cppBison.yxx.c" +#line 9392 "built/tmp/cppBison.yxx.c" break; - case 726: /* formal_const_expr: formal_const_expr LECOMPARE const_expr */ -#line 4110 "dtool/src/cppparser/cppBison.yxx" + case 733: /* formal_const_expr: formal_const_expr LECOMPARE const_expr */ +#line 4141 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(LECOMPARE, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 9388 "built/tmp/cppBison.yxx.c" +#line 9400 "built/tmp/cppBison.yxx.c" break; - case 727: /* formal_const_expr: formal_const_expr GECOMPARE const_expr */ -#line 4114 "dtool/src/cppparser/cppBison.yxx" + case 734: /* formal_const_expr: formal_const_expr GECOMPARE const_expr */ +#line 4145 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(GECOMPARE, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 9396 "built/tmp/cppBison.yxx.c" +#line 9408 "built/tmp/cppBison.yxx.c" break; - case 728: /* formal_const_expr: formal_const_expr SPACESHIP const_expr */ -#line 4118 "dtool/src/cppparser/cppBison.yxx" + case 735: /* formal_const_expr: formal_const_expr SPACESHIP const_expr */ +#line 4149 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(SPACESHIP, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 9404 "built/tmp/cppBison.yxx.c" +#line 9416 "built/tmp/cppBison.yxx.c" break; - case 729: /* formal_const_expr: formal_const_expr '<' const_expr */ -#line 4122 "dtool/src/cppparser/cppBison.yxx" + case 736: /* formal_const_expr: formal_const_expr '<' const_expr */ +#line 4153 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression('<', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 9412 "built/tmp/cppBison.yxx.c" +#line 9424 "built/tmp/cppBison.yxx.c" break; - case 730: /* formal_const_expr: formal_const_expr '>' const_expr */ -#line 4126 "dtool/src/cppparser/cppBison.yxx" + case 737: /* formal_const_expr: formal_const_expr '>' const_expr */ +#line 4157 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression('>', (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 9420 "built/tmp/cppBison.yxx.c" +#line 9432 "built/tmp/cppBison.yxx.c" break; - case 731: /* formal_const_expr: formal_const_expr LSHIFT const_expr */ -#line 4130 "dtool/src/cppparser/cppBison.yxx" + case 738: /* formal_const_expr: formal_const_expr LSHIFT const_expr */ +#line 4161 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(LSHIFT, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 9428 "built/tmp/cppBison.yxx.c" +#line 9440 "built/tmp/cppBison.yxx.c" break; - case 732: /* formal_const_expr: formal_const_expr RSHIFT const_expr */ -#line 4134 "dtool/src/cppparser/cppBison.yxx" + case 739: /* formal_const_expr: formal_const_expr RSHIFT const_expr */ +#line 4165 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(RSHIFT, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 9436 "built/tmp/cppBison.yxx.c" +#line 9448 "built/tmp/cppBison.yxx.c" break; - case 733: /* formal_const_expr: formal_const_expr '?' const_expr ':' const_expr */ -#line 4138 "dtool/src/cppparser/cppBison.yxx" + case 740: /* formal_const_expr: formal_const_expr '?' const_expr ':' const_expr */ +#line 4169 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression('?', (yyvsp[-4].u.expr), (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 9444 "built/tmp/cppBison.yxx.c" +#line 9456 "built/tmp/cppBison.yxx.c" break; - case 734: /* formal_const_expr: formal_const_expr '[' const_expr ']' */ -#line 4142 "dtool/src/cppparser/cppBison.yxx" + case 741: /* formal_const_expr: formal_const_expr '[' const_expr ']' */ +#line 4173 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression('[', (yyvsp[-3].u.expr), (yyvsp[-1].u.expr)); } -#line 9452 "built/tmp/cppBison.yxx.c" +#line 9464 "built/tmp/cppBison.yxx.c" break; - case 735: /* formal_const_expr: formal_const_expr '(' const_expr_comma ')' */ -#line 4146 "dtool/src/cppparser/cppBison.yxx" + case 742: /* formal_const_expr: formal_const_expr '(' const_expr_comma ')' */ +#line 4177 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression('f', (yyvsp[-3].u.expr), (yyvsp[-1].u.expr)); } -#line 9460 "built/tmp/cppBison.yxx.c" +#line 9472 "built/tmp/cppBison.yxx.c" break; - case 736: /* formal_const_expr: formal_const_expr '(' ')' */ -#line 4150 "dtool/src/cppparser/cppBison.yxx" + case 743: /* formal_const_expr: formal_const_expr '(' ')' */ +#line 4181 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression('f', (yyvsp[-2].u.expr)); } -#line 9468 "built/tmp/cppBison.yxx.c" +#line 9480 "built/tmp/cppBison.yxx.c" break; - case 737: /* formal_const_expr: formal_const_expr '.' name */ -#line 4154 "dtool/src/cppparser/cppBison.yxx" + case 744: /* formal_const_expr: formal_const_expr '.' name */ +#line 4185 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression('.', (yyvsp[-2].u.expr), new CPPExpression((yyvsp[0].u.identifier), current_scope, global_scope, current_lexer)); } -#line 9476 "built/tmp/cppBison.yxx.c" +#line 9488 "built/tmp/cppBison.yxx.c" break; - case 738: /* formal_const_expr: formal_const_expr POINTSAT const_expr */ -#line 4158 "dtool/src/cppparser/cppBison.yxx" + case 745: /* formal_const_expr: formal_const_expr POINTSAT const_expr */ +#line 4189 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(POINTSAT, (yyvsp[-2].u.expr), (yyvsp[0].u.expr)); } -#line 9484 "built/tmp/cppBison.yxx.c" +#line 9496 "built/tmp/cppBison.yxx.c" break; - case 739: /* formal_const_expr: '(' const_expr_comma ')' */ -#line 4162 "dtool/src/cppparser/cppBison.yxx" + case 746: /* formal_const_expr: '(' const_expr_comma ')' */ +#line 4193 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = (yyvsp[-1].u.expr); } -#line 9492 "built/tmp/cppBison.yxx.c" +#line 9504 "built/tmp/cppBison.yxx.c" break; - case 740: /* formal_const_operand: INTEGER */ -#line 4169 "dtool/src/cppparser/cppBison.yxx" + case 747: /* formal_const_operand: INTEGER */ +#line 4200 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression((yyvsp[0].u.integer)); } -#line 9500 "built/tmp/cppBison.yxx.c" +#line 9512 "built/tmp/cppBison.yxx.c" break; - case 741: /* formal_const_operand: KW_TRUE */ -#line 4173 "dtool/src/cppparser/cppBison.yxx" + case 748: /* formal_const_operand: KW_TRUE */ +#line 4204 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(true); } -#line 9508 "built/tmp/cppBison.yxx.c" +#line 9520 "built/tmp/cppBison.yxx.c" break; - case 742: /* formal_const_operand: KW_FALSE */ -#line 4177 "dtool/src/cppparser/cppBison.yxx" + case 749: /* formal_const_operand: KW_FALSE */ +#line 4208 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(false); } -#line 9516 "built/tmp/cppBison.yxx.c" +#line 9528 "built/tmp/cppBison.yxx.c" break; - case 743: /* formal_const_operand: CHAR_TOK */ -#line 4181 "dtool/src/cppparser/cppBison.yxx" + case 750: /* formal_const_operand: CHAR_TOK */ +#line 4212 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression((yyvsp[0].u.integer)); } -#line 9524 "built/tmp/cppBison.yxx.c" +#line 9536 "built/tmp/cppBison.yxx.c" break; - case 744: /* formal_const_operand: REAL */ -#line 4185 "dtool/src/cppparser/cppBison.yxx" + case 751: /* formal_const_operand: REAL */ +#line 4216 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression((yyvsp[0].u.real)); } -#line 9532 "built/tmp/cppBison.yxx.c" +#line 9544 "built/tmp/cppBison.yxx.c" break; - case 745: /* formal_const_operand: string_literal */ -#line 4189 "dtool/src/cppparser/cppBison.yxx" + case 752: /* formal_const_operand: string_literal */ +#line 4220 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = (yyvsp[0].u.expr); } -#line 9540 "built/tmp/cppBison.yxx.c" +#line 9552 "built/tmp/cppBison.yxx.c" break; - case 746: /* formal_const_operand: CUSTOM_LITERAL */ -#line 4193 "dtool/src/cppparser/cppBison.yxx" + case 753: /* formal_const_operand: CUSTOM_LITERAL */ +#line 4224 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = (yyvsp[0].u.expr); } -#line 9548 "built/tmp/cppBison.yxx.c" +#line 9560 "built/tmp/cppBison.yxx.c" break; - case 747: /* formal_const_operand: IDENTIFIER */ -#line 4197 "dtool/src/cppparser/cppBison.yxx" + case 754: /* formal_const_operand: IDENTIFIER */ +#line 4228 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression((yyvsp[0].u.identifier), current_scope, global_scope, current_lexer); } -#line 9556 "built/tmp/cppBison.yxx.c" +#line 9568 "built/tmp/cppBison.yxx.c" break; - case 748: /* formal_const_operand: KW_FINAL */ -#line 4201 "dtool/src/cppparser/cppBison.yxx" + case 755: /* formal_const_operand: KW_FINAL */ +#line 4232 "dtool/src/cppparser/cppBison.yxx" { // A variable named "final". C++11 explicitly permits this. CPPIdentifier *ident = new CPPIdentifier("final", (yylsp[0])); (yyval.u.expr) = new CPPExpression(ident, current_scope, global_scope, current_lexer); } -#line 9566 "built/tmp/cppBison.yxx.c" +#line 9578 "built/tmp/cppBison.yxx.c" break; - case 749: /* formal_const_operand: KW_OVERRIDE */ -#line 4207 "dtool/src/cppparser/cppBison.yxx" + case 756: /* formal_const_operand: KW_OVERRIDE */ +#line 4238 "dtool/src/cppparser/cppBison.yxx" { // A variable named "override". C++11 explicitly permits this. CPPIdentifier *ident = new CPPIdentifier("override", (yylsp[0])); (yyval.u.expr) = new CPPExpression(ident, current_scope, global_scope, current_lexer); } -#line 9576 "built/tmp/cppBison.yxx.c" +#line 9588 "built/tmp/cppBison.yxx.c" break; - case 750: /* formal_const_operand: KW_NULLPTR */ -#line 4213 "dtool/src/cppparser/cppBison.yxx" + case 757: /* formal_const_operand: KW_NULLPTR */ +#line 4244 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression(CPPExpression::get_nullptr()); } -#line 9584 "built/tmp/cppBison.yxx.c" +#line 9596 "built/tmp/cppBison.yxx.c" break; - case 751: /* capture_list: empty */ -#line 4221 "dtool/src/cppparser/cppBison.yxx" + case 758: /* capture_list: empty */ +#line 4252 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.closure_type) = new CPPClosureType(); } -#line 9592 "built/tmp/cppBison.yxx.c" +#line 9604 "built/tmp/cppBison.yxx.c" break; - case 752: /* capture_list: '=' */ -#line 4225 "dtool/src/cppparser/cppBison.yxx" + case 759: /* capture_list: '=' */ +#line 4256 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.closure_type) = new CPPClosureType(CPPClosureType::CT_by_value); } -#line 9600 "built/tmp/cppBison.yxx.c" +#line 9612 "built/tmp/cppBison.yxx.c" break; - case 753: /* capture_list: '&' */ -#line 4229 "dtool/src/cppparser/cppBison.yxx" + case 760: /* capture_list: '&' */ +#line 4260 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.closure_type) = new CPPClosureType(CPPClosureType::CT_by_reference); } -#line 9608 "built/tmp/cppBison.yxx.c" +#line 9620 "built/tmp/cppBison.yxx.c" break; - case 754: /* capture_list: capture maybe_initialize */ -#line 4233 "dtool/src/cppparser/cppBison.yxx" + case 761: /* capture_list: capture maybe_initialize */ +#line 4264 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.closure_type) = new CPPClosureType(); (yyvsp[-1].u.capture)->_initializer = (yyvsp[0].u.expr); (yyval.u.closure_type)->_captures.push_back(*(yyvsp[-1].u.capture)); delete (yyvsp[-1].u.capture); } -#line 9619 "built/tmp/cppBison.yxx.c" +#line 9631 "built/tmp/cppBison.yxx.c" break; - case 755: /* capture_list: capture_list ',' capture maybe_initialize */ -#line 4240 "dtool/src/cppparser/cppBison.yxx" + case 762: /* capture_list: capture_list ',' capture maybe_initialize */ +#line 4271 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.closure_type) = (yyvsp[-3].u.closure_type); (yyvsp[-1].u.capture)->_initializer = (yyvsp[0].u.expr); (yyval.u.closure_type)->_captures.push_back(*(yyvsp[-1].u.capture)); delete (yyvsp[-1].u.capture); } -#line 9630 "built/tmp/cppBison.yxx.c" +#line 9642 "built/tmp/cppBison.yxx.c" break; - case 756: /* capture: '&' name */ -#line 4250 "dtool/src/cppparser/cppBison.yxx" + case 763: /* capture: '&' name */ +#line 4281 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.capture) = new CPPClosureType::Capture; (yyval.u.capture)->_name = (yyvsp[0].u.identifier)->get_simple_name(); (yyval.u.capture)->_type = CPPClosureType::CT_by_reference; } -#line 9640 "built/tmp/cppBison.yxx.c" +#line 9652 "built/tmp/cppBison.yxx.c" break; - case 757: /* capture: '&' name ELLIPSIS */ -#line 4256 "dtool/src/cppparser/cppBison.yxx" + case 764: /* capture: '&' name ELLIPSIS */ +#line 4287 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.capture) = new CPPClosureType::Capture; (yyval.u.capture)->_name = (yyvsp[-1].u.identifier)->get_simple_name(); (yyval.u.capture)->_type = CPPClosureType::CT_by_reference; } -#line 9650 "built/tmp/cppBison.yxx.c" +#line 9662 "built/tmp/cppBison.yxx.c" break; - case 758: /* capture: name */ -#line 4262 "dtool/src/cppparser/cppBison.yxx" + case 765: /* capture: name */ +#line 4293 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.capture) = new CPPClosureType::Capture; (yyval.u.capture)->_name = (yyvsp[0].u.identifier)->get_simple_name(); @@ -9660,11 +9672,11 @@ yyreduce: (yyval.u.capture)->_type = CPPClosureType::CT_by_value; } } -#line 9664 "built/tmp/cppBison.yxx.c" +#line 9676 "built/tmp/cppBison.yxx.c" break; - case 759: /* capture: '*' name */ -#line 4272 "dtool/src/cppparser/cppBison.yxx" + case 766: /* capture: '*' name */ +#line 4303 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.capture) = new CPPClosureType::Capture; (yyval.u.capture)->_name = (yyvsp[0].u.identifier)->get_simple_name(); @@ -9673,11 +9685,11 @@ yyreduce: yywarning("only capture name 'this' may be preceded by an asterisk", (yylsp[0])); } } -#line 9677 "built/tmp/cppBison.yxx.c" +#line 9689 "built/tmp/cppBison.yxx.c" break; - case 760: /* class_derivation_name: name */ -#line 4284 "dtool/src/cppparser/cppBison.yxx" + case 767: /* class_derivation_name: name */ +#line 4315 "dtool/src/cppparser/cppBison.yxx" { CPPType *type = (yyvsp[0].u.identifier)->find_type(current_scope, global_scope, true); if (type == nullptr) { @@ -9685,177 +9697,177 @@ yyreduce: } (yyval.u.type) = type; } -#line 9689 "built/tmp/cppBison.yxx.c" +#line 9701 "built/tmp/cppBison.yxx.c" break; - case 761: /* class_derivation_name: KW_TYPENAME name */ -#line 4292 "dtool/src/cppparser/cppBison.yxx" + case 768: /* class_derivation_name: KW_TYPENAME name */ +#line 4323 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.type) = CPPType::new_type(new CPPTBDType((yyvsp[0].u.identifier))); } -#line 9697 "built/tmp/cppBison.yxx.c" +#line 9709 "built/tmp/cppBison.yxx.c" break; - case 762: /* class_derivation_name: name ELLIPSIS */ -#line 4296 "dtool/src/cppparser/cppBison.yxx" + case 769: /* class_derivation_name: name ELLIPSIS */ +#line 4327 "dtool/src/cppparser/cppBison.yxx" { CPPClassTemplateParameter *ctp = new CPPClassTemplateParameter((yyvsp[-1].u.identifier)); ctp->_packed = true; (yyval.u.type) = CPPType::new_type(ctp); } -#line 9707 "built/tmp/cppBison.yxx.c" +#line 9719 "built/tmp/cppBison.yxx.c" break; - case 763: /* name: IDENTIFIER */ -#line 4326 "dtool/src/cppparser/cppBison.yxx" + case 770: /* name: IDENTIFIER */ +#line 4357 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.identifier) = (yyvsp[0].u.identifier); } -#line 9715 "built/tmp/cppBison.yxx.c" +#line 9727 "built/tmp/cppBison.yxx.c" break; - case 764: /* name: TYPENAME_IDENTIFIER */ -#line 4330 "dtool/src/cppparser/cppBison.yxx" + case 771: /* name: TYPENAME_IDENTIFIER */ +#line 4361 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.identifier) = (yyvsp[0].u.identifier); } -#line 9723 "built/tmp/cppBison.yxx.c" +#line 9735 "built/tmp/cppBison.yxx.c" break; - case 765: /* name: TYPEPACK_IDENTIFIER */ -#line 4334 "dtool/src/cppparser/cppBison.yxx" + case 772: /* name: TYPEPACK_IDENTIFIER */ +#line 4365 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.identifier) = (yyvsp[0].u.identifier); } -#line 9731 "built/tmp/cppBison.yxx.c" +#line 9743 "built/tmp/cppBison.yxx.c" break; - case 766: /* name: KW_FINAL */ -#line 4338 "dtool/src/cppparser/cppBison.yxx" + case 773: /* name: KW_FINAL */ +#line 4369 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.identifier) = new CPPIdentifier("final", (yylsp[0])); } -#line 9739 "built/tmp/cppBison.yxx.c" +#line 9751 "built/tmp/cppBison.yxx.c" break; - case 767: /* name: KW_OVERRIDE */ -#line 4342 "dtool/src/cppparser/cppBison.yxx" + case 774: /* name: KW_OVERRIDE */ +#line 4373 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.identifier) = new CPPIdentifier("override", (yylsp[0])); } -#line 9747 "built/tmp/cppBison.yxx.c" +#line 9759 "built/tmp/cppBison.yxx.c" break; - case 768: /* name: KW_SIGNED */ -#line 4346 "dtool/src/cppparser/cppBison.yxx" + case 775: /* name: KW_SIGNED */ +#line 4377 "dtool/src/cppparser/cppBison.yxx" { // This is not a keyword in Python, so it is useful to be able to use this // in MAKE_PROPERTY definitions, etc. (yyval.u.identifier) = new CPPIdentifier("signed", (yylsp[0])); } -#line 9757 "built/tmp/cppBison.yxx.c" +#line 9769 "built/tmp/cppBison.yxx.c" break; - case 769: /* name: KW_FLOAT */ -#line 4352 "dtool/src/cppparser/cppBison.yxx" + case 776: /* name: KW_FLOAT */ +#line 4383 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.identifier) = new CPPIdentifier("float", (yylsp[0])); } -#line 9765 "built/tmp/cppBison.yxx.c" +#line 9777 "built/tmp/cppBison.yxx.c" break; - case 770: /* name: KW_PUBLIC */ -#line 4356 "dtool/src/cppparser/cppBison.yxx" + case 777: /* name: KW_PUBLIC */ +#line 4387 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.identifier) = new CPPIdentifier("public", (yylsp[0])); } -#line 9773 "built/tmp/cppBison.yxx.c" +#line 9785 "built/tmp/cppBison.yxx.c" break; - case 771: /* name: KW_PRIVATE */ -#line 4360 "dtool/src/cppparser/cppBison.yxx" + case 778: /* name: KW_PRIVATE */ +#line 4391 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.identifier) = new CPPIdentifier("private", (yylsp[0])); } -#line 9781 "built/tmp/cppBison.yxx.c" +#line 9793 "built/tmp/cppBison.yxx.c" break; - case 772: /* name: KW_STATIC */ -#line 4364 "dtool/src/cppparser/cppBison.yxx" + case 779: /* name: KW_STATIC */ +#line 4395 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.identifier) = new CPPIdentifier("static", (yylsp[0])); } -#line 9789 "built/tmp/cppBison.yxx.c" +#line 9801 "built/tmp/cppBison.yxx.c" break; - case 773: /* name: KW_DEFAULT */ -#line 4368 "dtool/src/cppparser/cppBison.yxx" + case 780: /* name: KW_DEFAULT */ +#line 4399 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.identifier) = new CPPIdentifier("default", (yylsp[0])); } -#line 9797 "built/tmp/cppBison.yxx.c" +#line 9809 "built/tmp/cppBison.yxx.c" break; - case 774: /* name_no_final: IDENTIFIER */ -#line 4379 "dtool/src/cppparser/cppBison.yxx" + case 781: /* name_no_final: IDENTIFIER */ +#line 4410 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.identifier) = (yyvsp[0].u.identifier); } -#line 9805 "built/tmp/cppBison.yxx.c" +#line 9817 "built/tmp/cppBison.yxx.c" break; - case 775: /* name_no_final: TYPENAME_IDENTIFIER */ -#line 4383 "dtool/src/cppparser/cppBison.yxx" + case 782: /* name_no_final: TYPENAME_IDENTIFIER */ +#line 4414 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.identifier) = (yyvsp[0].u.identifier); } -#line 9813 "built/tmp/cppBison.yxx.c" +#line 9825 "built/tmp/cppBison.yxx.c" break; - case 776: /* name_no_final: TYPEPACK_IDENTIFIER */ -#line 4387 "dtool/src/cppparser/cppBison.yxx" + case 783: /* name_no_final: TYPEPACK_IDENTIFIER */ +#line 4418 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.identifier) = (yyvsp[0].u.identifier); } -#line 9821 "built/tmp/cppBison.yxx.c" +#line 9833 "built/tmp/cppBison.yxx.c" break; - case 777: /* name_no_final: KW_OVERRIDE */ -#line 4391 "dtool/src/cppparser/cppBison.yxx" + case 784: /* name_no_final: KW_OVERRIDE */ +#line 4422 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.identifier) = new CPPIdentifier("override", (yylsp[0])); } -#line 9829 "built/tmp/cppBison.yxx.c" +#line 9841 "built/tmp/cppBison.yxx.c" break; - case 778: /* string_literal: SIMPLE_STRING */ -#line 4399 "dtool/src/cppparser/cppBison.yxx" + case 785: /* string_literal: SIMPLE_STRING */ +#line 4430 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = new CPPExpression((yyvsp[0].str)); } -#line 9837 "built/tmp/cppBison.yxx.c" +#line 9849 "built/tmp/cppBison.yxx.c" break; - case 779: /* string_literal: STRING_LITERAL */ -#line 4403 "dtool/src/cppparser/cppBison.yxx" + case 786: /* string_literal: STRING_LITERAL */ +#line 4434 "dtool/src/cppparser/cppBison.yxx" { (yyval.u.expr) = (yyvsp[0].u.expr); } -#line 9845 "built/tmp/cppBison.yxx.c" +#line 9857 "built/tmp/cppBison.yxx.c" break; - case 780: /* string_literal: string_literal SIMPLE_STRING */ -#line 4407 "dtool/src/cppparser/cppBison.yxx" + case 787: /* string_literal: string_literal SIMPLE_STRING */ +#line 4438 "dtool/src/cppparser/cppBison.yxx" { // The right string takes on the literal type of the left. (yyval.u.expr) = (yyvsp[-1].u.expr); (yyval.u.expr)->_str += (yyvsp[0].str); } -#line 9855 "built/tmp/cppBison.yxx.c" +#line 9867 "built/tmp/cppBison.yxx.c" break; - case 781: /* string_literal: string_literal STRING_LITERAL */ -#line 4413 "dtool/src/cppparser/cppBison.yxx" + case 788: /* string_literal: string_literal STRING_LITERAL */ +#line 4444 "dtool/src/cppparser/cppBison.yxx" { // We have to check that the two literal types match up. (yyval.u.expr) = (yyvsp[-1].u.expr); @@ -9864,11 +9876,11 @@ yyreduce: } (yyval.u.expr)->_str += (yyvsp[0].u.expr)->_str; } -#line 9868 "built/tmp/cppBison.yxx.c" +#line 9880 "built/tmp/cppBison.yxx.c" break; -#line 9872 "built/tmp/cppBison.yxx.c" +#line 9884 "built/tmp/cppBison.yxx.c" default: break; } diff --git a/dtool/src/cppparser/cppBison.h.prebuilt b/dtool/src/cppparser/cppBison.h.prebuilt index f5b85b696c..78032c0153 100644 --- a/dtool/src/cppparser/cppBison.h.prebuilt +++ b/dtool/src/cppparser/cppBison.h.prebuilt @@ -107,104 +107,106 @@ extern int cppyydebug; KW_BEGIN_PUBLISH = 308, /* KW_BEGIN_PUBLISH */ KW_BLOCKING = 309, /* KW_BLOCKING */ KW_BOOL = 310, /* KW_BOOL */ - KW_CATCH = 311, /* KW_CATCH */ - KW_CHAR = 312, /* KW_CHAR */ - KW_CHAR8_T = 313, /* KW_CHAR8_T */ - KW_CHAR16_T = 314, /* KW_CHAR16_T */ - KW_CHAR32_T = 315, /* KW_CHAR32_T */ - KW_CLASS = 316, /* KW_CLASS */ - KW_CONST = 317, /* KW_CONST */ - KW_CONSTEVAL = 318, /* KW_CONSTEVAL */ - KW_CONSTEXPR = 319, /* KW_CONSTEXPR */ - KW_CONSTINIT = 320, /* KW_CONSTINIT */ - KW_CONST_CAST = 321, /* KW_CONST_CAST */ - KW_DECLTYPE = 322, /* KW_DECLTYPE */ - KW_DEFAULT = 323, /* KW_DEFAULT */ - KW_DELETE = 324, /* KW_DELETE */ - KW_DOUBLE = 325, /* KW_DOUBLE */ - KW_DYNAMIC_CAST = 326, /* KW_DYNAMIC_CAST */ - KW_ELSE = 327, /* KW_ELSE */ - KW_END_PUBLISH = 328, /* KW_END_PUBLISH */ - KW_ENUM = 329, /* KW_ENUM */ - KW_EXTENSION = 330, /* KW_EXTENSION */ - KW_EXTERN = 331, /* KW_EXTERN */ - KW_EXPLICIT = 332, /* KW_EXPLICIT */ - KW_EXPLICIT_LPAREN = 333, /* KW_EXPLICIT_LPAREN */ - KW_PUBLISHED = 334, /* KW_PUBLISHED */ - KW_FALSE = 335, /* KW_FALSE */ - KW_FINAL = 336, /* KW_FINAL */ - KW_FLOAT = 337, /* KW_FLOAT */ - KW_FRIEND = 338, /* KW_FRIEND */ - KW_FOR = 339, /* KW_FOR */ - KW_GOTO = 340, /* KW_GOTO */ - KW_HAS_VIRTUAL_DESTRUCTOR = 341, /* KW_HAS_VIRTUAL_DESTRUCTOR */ - KW_IF = 342, /* KW_IF */ - KW_INLINE = 343, /* KW_INLINE */ - KW_INT = 344, /* KW_INT */ - KW_IS_ABSTRACT = 345, /* KW_IS_ABSTRACT */ - KW_IS_BASE_OF = 346, /* KW_IS_BASE_OF */ - KW_IS_CLASS = 347, /* KW_IS_CLASS */ - KW_IS_CONSTRUCTIBLE = 348, /* KW_IS_CONSTRUCTIBLE */ - KW_IS_CONVERTIBLE_TO = 349, /* KW_IS_CONVERTIBLE_TO */ - KW_IS_DESTRUCTIBLE = 350, /* KW_IS_DESTRUCTIBLE */ - KW_IS_EMPTY = 351, /* KW_IS_EMPTY */ - KW_IS_ENUM = 352, /* KW_IS_ENUM */ - KW_IS_FINAL = 353, /* KW_IS_FINAL */ - KW_IS_FUNDAMENTAL = 354, /* KW_IS_FUNDAMENTAL */ - KW_IS_POD = 355, /* KW_IS_POD */ - KW_IS_POLYMORPHIC = 356, /* KW_IS_POLYMORPHIC */ - KW_IS_STANDARD_LAYOUT = 357, /* KW_IS_STANDARD_LAYOUT */ - KW_IS_TRIVIAL = 358, /* KW_IS_TRIVIAL */ - KW_IS_TRIVIALLY_COPYABLE = 359, /* KW_IS_TRIVIALLY_COPYABLE */ - KW_IS_UNION = 360, /* KW_IS_UNION */ - KW_LONG = 361, /* KW_LONG */ - KW_MAKE_MAP_KEYS_SEQ = 362, /* KW_MAKE_MAP_KEYS_SEQ */ - KW_MAKE_MAP_PROPERTY = 363, /* KW_MAKE_MAP_PROPERTY */ - KW_MAKE_PROPERTY = 364, /* KW_MAKE_PROPERTY */ - KW_MAKE_PROPERTY2 = 365, /* KW_MAKE_PROPERTY2 */ - KW_MAKE_SEQ = 366, /* KW_MAKE_SEQ */ - KW_MAKE_SEQ_PROPERTY = 367, /* KW_MAKE_SEQ_PROPERTY */ - KW_MUTABLE = 368, /* KW_MUTABLE */ - KW_NAMESPACE = 369, /* KW_NAMESPACE */ - KW_NEW = 370, /* KW_NEW */ - KW_NOEXCEPT = 371, /* KW_NOEXCEPT */ - KW_NOEXCEPT_LPAREN = 372, /* KW_NOEXCEPT_LPAREN */ - KW_NULLPTR = 373, /* KW_NULLPTR */ - KW_OPERATOR = 374, /* KW_OPERATOR */ - KW_OVERRIDE = 375, /* KW_OVERRIDE */ - KW_PRIVATE = 376, /* KW_PRIVATE */ - KW_PROTECTED = 377, /* KW_PROTECTED */ - KW_PUBLIC = 378, /* KW_PUBLIC */ - KW_REGISTER = 379, /* KW_REGISTER */ - KW_REINTERPRET_CAST = 380, /* KW_REINTERPRET_CAST */ - KW_RETURN = 381, /* KW_RETURN */ - KW_SHORT = 382, /* KW_SHORT */ - KW_SIGNED = 383, /* KW_SIGNED */ - KW_SIZEOF = 384, /* KW_SIZEOF */ - KW_STATIC = 385, /* KW_STATIC */ - KW_STATIC_ASSERT = 386, /* KW_STATIC_ASSERT */ - KW_STATIC_CAST = 387, /* KW_STATIC_CAST */ - KW_STRUCT = 388, /* KW_STRUCT */ - KW_TEMPLATE = 389, /* KW_TEMPLATE */ - KW_THREAD_LOCAL = 390, /* KW_THREAD_LOCAL */ - KW_THROW = 391, /* KW_THROW */ - KW_TRUE = 392, /* KW_TRUE */ - KW_TRY = 393, /* KW_TRY */ - KW_TYPEDEF = 394, /* KW_TYPEDEF */ - KW_TYPEID = 395, /* KW_TYPEID */ - KW_TYPENAME = 396, /* KW_TYPENAME */ - KW_UNDERLYING_TYPE = 397, /* KW_UNDERLYING_TYPE */ - KW_UNION = 398, /* KW_UNION */ - KW_UNSIGNED = 399, /* KW_UNSIGNED */ - KW_USING = 400, /* KW_USING */ - KW_VIRTUAL = 401, /* KW_VIRTUAL */ - KW_VOID = 402, /* KW_VOID */ - KW_VOLATILE = 403, /* KW_VOLATILE */ - KW_WCHAR_T = 404, /* KW_WCHAR_T */ - KW_WHILE = 405, /* KW_WHILE */ - START_CPP = 406, /* START_CPP */ - START_CONST_EXPR = 407, /* START_CONST_EXPR */ - START_TYPE = 408 /* START_TYPE */ + KW_BUILTIN_VA_LIST = 311, /* KW_BUILTIN_VA_LIST */ + KW_CATCH = 312, /* KW_CATCH */ + KW_CHAR = 313, /* KW_CHAR */ + KW_CHAR8_T = 314, /* KW_CHAR8_T */ + KW_CHAR16_T = 315, /* KW_CHAR16_T */ + KW_CHAR32_T = 316, /* KW_CHAR32_T */ + KW_CLASS = 317, /* KW_CLASS */ + KW_CONST = 318, /* KW_CONST */ + KW_CONSTEVAL = 319, /* KW_CONSTEVAL */ + KW_CONSTEXPR = 320, /* KW_CONSTEXPR */ + KW_CONSTINIT = 321, /* KW_CONSTINIT */ + KW_CONST_CAST = 322, /* KW_CONST_CAST */ + KW_DECLTYPE = 323, /* KW_DECLTYPE */ + KW_DEFAULT = 324, /* KW_DEFAULT */ + KW_DELETE = 325, /* KW_DELETE */ + KW_DOUBLE = 326, /* KW_DOUBLE */ + KW_DYNAMIC_CAST = 327, /* KW_DYNAMIC_CAST */ + KW_ELSE = 328, /* KW_ELSE */ + KW_END_PUBLISH = 329, /* KW_END_PUBLISH */ + KW_ENUM = 330, /* KW_ENUM */ + KW_EXTENSION = 331, /* KW_EXTENSION */ + KW_EXTERN = 332, /* KW_EXTERN */ + KW_EXPLICIT = 333, /* KW_EXPLICIT */ + KW_EXPLICIT_LPAREN = 334, /* KW_EXPLICIT_LPAREN */ + KW_PUBLISHED = 335, /* KW_PUBLISHED */ + KW_FALSE = 336, /* KW_FALSE */ + KW_FINAL = 337, /* KW_FINAL */ + KW_FLOAT = 338, /* KW_FLOAT */ + KW_FRIEND = 339, /* KW_FRIEND */ + KW_FOR = 340, /* KW_FOR */ + KW_GOTO = 341, /* KW_GOTO */ + KW_HAS_VIRTUAL_DESTRUCTOR = 342, /* KW_HAS_VIRTUAL_DESTRUCTOR */ + KW_IF = 343, /* KW_IF */ + KW_INLINE = 344, /* KW_INLINE */ + KW_INT = 345, /* KW_INT */ + KW_IS_ABSTRACT = 346, /* KW_IS_ABSTRACT */ + KW_IS_BASE_OF = 347, /* KW_IS_BASE_OF */ + KW_IS_CLASS = 348, /* KW_IS_CLASS */ + KW_IS_CONSTRUCTIBLE = 349, /* KW_IS_CONSTRUCTIBLE */ + KW_IS_CONVERTIBLE_TO = 350, /* KW_IS_CONVERTIBLE_TO */ + KW_IS_DESTRUCTIBLE = 351, /* KW_IS_DESTRUCTIBLE */ + KW_IS_EMPTY = 352, /* KW_IS_EMPTY */ + KW_IS_ENUM = 353, /* KW_IS_ENUM */ + KW_IS_FINAL = 354, /* KW_IS_FINAL */ + KW_IS_FUNDAMENTAL = 355, /* KW_IS_FUNDAMENTAL */ + KW_IS_POD = 356, /* KW_IS_POD */ + KW_IS_POLYMORPHIC = 357, /* KW_IS_POLYMORPHIC */ + KW_IS_STANDARD_LAYOUT = 358, /* KW_IS_STANDARD_LAYOUT */ + KW_IS_TRIVIAL = 359, /* KW_IS_TRIVIAL */ + KW_IS_TRIVIALLY_COPYABLE = 360, /* KW_IS_TRIVIALLY_COPYABLE */ + KW_IS_UNION = 361, /* KW_IS_UNION */ + KW_LONG = 362, /* KW_LONG */ + KW_MAKE_MAP_KEYS_SEQ = 363, /* KW_MAKE_MAP_KEYS_SEQ */ + KW_MAKE_MAP_PROPERTY = 364, /* KW_MAKE_MAP_PROPERTY */ + KW_MAKE_PROPERTY = 365, /* KW_MAKE_PROPERTY */ + KW_MAKE_PROPERTY2 = 366, /* KW_MAKE_PROPERTY2 */ + KW_MAKE_SEQ = 367, /* KW_MAKE_SEQ */ + KW_MAKE_SEQ_PROPERTY = 368, /* KW_MAKE_SEQ_PROPERTY */ + KW_MUTABLE = 369, /* KW_MUTABLE */ + KW_NAMESPACE = 370, /* KW_NAMESPACE */ + KW_NEW = 371, /* KW_NEW */ + KW_NOEXCEPT = 372, /* KW_NOEXCEPT */ + KW_NOEXCEPT_LPAREN = 373, /* KW_NOEXCEPT_LPAREN */ + KW_NULLPTR = 374, /* KW_NULLPTR */ + KW_OPERATOR = 375, /* KW_OPERATOR */ + KW_OVERRIDE = 376, /* KW_OVERRIDE */ + KW_PRIVATE = 377, /* KW_PRIVATE */ + KW_PROTECTED = 378, /* KW_PROTECTED */ + KW_PUBLIC = 379, /* KW_PUBLIC */ + KW_REGISTER = 380, /* KW_REGISTER */ + KW_REINTERPRET_CAST = 381, /* KW_REINTERPRET_CAST */ + KW_RESTRICT = 382, /* KW_RESTRICT */ + KW_RETURN = 383, /* KW_RETURN */ + KW_SHORT = 384, /* KW_SHORT */ + KW_SIGNED = 385, /* KW_SIGNED */ + KW_SIZEOF = 386, /* KW_SIZEOF */ + KW_STATIC = 387, /* KW_STATIC */ + KW_STATIC_ASSERT = 388, /* KW_STATIC_ASSERT */ + KW_STATIC_CAST = 389, /* KW_STATIC_CAST */ + KW_STRUCT = 390, /* KW_STRUCT */ + KW_TEMPLATE = 391, /* KW_TEMPLATE */ + KW_THREAD_LOCAL = 392, /* KW_THREAD_LOCAL */ + KW_THROW = 393, /* KW_THROW */ + KW_TRUE = 394, /* KW_TRUE */ + KW_TRY = 395, /* KW_TRY */ + KW_TYPEDEF = 396, /* KW_TYPEDEF */ + KW_TYPEID = 397, /* KW_TYPEID */ + KW_TYPENAME = 398, /* KW_TYPENAME */ + KW_UNDERLYING_TYPE = 399, /* KW_UNDERLYING_TYPE */ + KW_UNION = 400, /* KW_UNION */ + KW_UNSIGNED = 401, /* KW_UNSIGNED */ + KW_USING = 402, /* KW_USING */ + KW_VIRTUAL = 403, /* KW_VIRTUAL */ + KW_VOID = 404, /* KW_VOID */ + KW_VOLATILE = 405, /* KW_VOLATILE */ + KW_WCHAR_T = 406, /* KW_WCHAR_T */ + KW_WHILE = 407, /* KW_WHILE */ + START_CPP = 408, /* START_CPP */ + START_CONST_EXPR = 409, /* START_CONST_EXPR */ + START_TYPE = 410 /* START_TYPE */ }; typedef enum yytokentype yytoken_kind_t; #endif @@ -266,104 +268,106 @@ extern int cppyydebug; #define KW_BEGIN_PUBLISH 308 #define KW_BLOCKING 309 #define KW_BOOL 310 -#define KW_CATCH 311 -#define KW_CHAR 312 -#define KW_CHAR8_T 313 -#define KW_CHAR16_T 314 -#define KW_CHAR32_T 315 -#define KW_CLASS 316 -#define KW_CONST 317 -#define KW_CONSTEVAL 318 -#define KW_CONSTEXPR 319 -#define KW_CONSTINIT 320 -#define KW_CONST_CAST 321 -#define KW_DECLTYPE 322 -#define KW_DEFAULT 323 -#define KW_DELETE 324 -#define KW_DOUBLE 325 -#define KW_DYNAMIC_CAST 326 -#define KW_ELSE 327 -#define KW_END_PUBLISH 328 -#define KW_ENUM 329 -#define KW_EXTENSION 330 -#define KW_EXTERN 331 -#define KW_EXPLICIT 332 -#define KW_EXPLICIT_LPAREN 333 -#define KW_PUBLISHED 334 -#define KW_FALSE 335 -#define KW_FINAL 336 -#define KW_FLOAT 337 -#define KW_FRIEND 338 -#define KW_FOR 339 -#define KW_GOTO 340 -#define KW_HAS_VIRTUAL_DESTRUCTOR 341 -#define KW_IF 342 -#define KW_INLINE 343 -#define KW_INT 344 -#define KW_IS_ABSTRACT 345 -#define KW_IS_BASE_OF 346 -#define KW_IS_CLASS 347 -#define KW_IS_CONSTRUCTIBLE 348 -#define KW_IS_CONVERTIBLE_TO 349 -#define KW_IS_DESTRUCTIBLE 350 -#define KW_IS_EMPTY 351 -#define KW_IS_ENUM 352 -#define KW_IS_FINAL 353 -#define KW_IS_FUNDAMENTAL 354 -#define KW_IS_POD 355 -#define KW_IS_POLYMORPHIC 356 -#define KW_IS_STANDARD_LAYOUT 357 -#define KW_IS_TRIVIAL 358 -#define KW_IS_TRIVIALLY_COPYABLE 359 -#define KW_IS_UNION 360 -#define KW_LONG 361 -#define KW_MAKE_MAP_KEYS_SEQ 362 -#define KW_MAKE_MAP_PROPERTY 363 -#define KW_MAKE_PROPERTY 364 -#define KW_MAKE_PROPERTY2 365 -#define KW_MAKE_SEQ 366 -#define KW_MAKE_SEQ_PROPERTY 367 -#define KW_MUTABLE 368 -#define KW_NAMESPACE 369 -#define KW_NEW 370 -#define KW_NOEXCEPT 371 -#define KW_NOEXCEPT_LPAREN 372 -#define KW_NULLPTR 373 -#define KW_OPERATOR 374 -#define KW_OVERRIDE 375 -#define KW_PRIVATE 376 -#define KW_PROTECTED 377 -#define KW_PUBLIC 378 -#define KW_REGISTER 379 -#define KW_REINTERPRET_CAST 380 -#define KW_RETURN 381 -#define KW_SHORT 382 -#define KW_SIGNED 383 -#define KW_SIZEOF 384 -#define KW_STATIC 385 -#define KW_STATIC_ASSERT 386 -#define KW_STATIC_CAST 387 -#define KW_STRUCT 388 -#define KW_TEMPLATE 389 -#define KW_THREAD_LOCAL 390 -#define KW_THROW 391 -#define KW_TRUE 392 -#define KW_TRY 393 -#define KW_TYPEDEF 394 -#define KW_TYPEID 395 -#define KW_TYPENAME 396 -#define KW_UNDERLYING_TYPE 397 -#define KW_UNION 398 -#define KW_UNSIGNED 399 -#define KW_USING 400 -#define KW_VIRTUAL 401 -#define KW_VOID 402 -#define KW_VOLATILE 403 -#define KW_WCHAR_T 404 -#define KW_WHILE 405 -#define START_CPP 406 -#define START_CONST_EXPR 407 -#define START_TYPE 408 +#define KW_BUILTIN_VA_LIST 311 +#define KW_CATCH 312 +#define KW_CHAR 313 +#define KW_CHAR8_T 314 +#define KW_CHAR16_T 315 +#define KW_CHAR32_T 316 +#define KW_CLASS 317 +#define KW_CONST 318 +#define KW_CONSTEVAL 319 +#define KW_CONSTEXPR 320 +#define KW_CONSTINIT 321 +#define KW_CONST_CAST 322 +#define KW_DECLTYPE 323 +#define KW_DEFAULT 324 +#define KW_DELETE 325 +#define KW_DOUBLE 326 +#define KW_DYNAMIC_CAST 327 +#define KW_ELSE 328 +#define KW_END_PUBLISH 329 +#define KW_ENUM 330 +#define KW_EXTENSION 331 +#define KW_EXTERN 332 +#define KW_EXPLICIT 333 +#define KW_EXPLICIT_LPAREN 334 +#define KW_PUBLISHED 335 +#define KW_FALSE 336 +#define KW_FINAL 337 +#define KW_FLOAT 338 +#define KW_FRIEND 339 +#define KW_FOR 340 +#define KW_GOTO 341 +#define KW_HAS_VIRTUAL_DESTRUCTOR 342 +#define KW_IF 343 +#define KW_INLINE 344 +#define KW_INT 345 +#define KW_IS_ABSTRACT 346 +#define KW_IS_BASE_OF 347 +#define KW_IS_CLASS 348 +#define KW_IS_CONSTRUCTIBLE 349 +#define KW_IS_CONVERTIBLE_TO 350 +#define KW_IS_DESTRUCTIBLE 351 +#define KW_IS_EMPTY 352 +#define KW_IS_ENUM 353 +#define KW_IS_FINAL 354 +#define KW_IS_FUNDAMENTAL 355 +#define KW_IS_POD 356 +#define KW_IS_POLYMORPHIC 357 +#define KW_IS_STANDARD_LAYOUT 358 +#define KW_IS_TRIVIAL 359 +#define KW_IS_TRIVIALLY_COPYABLE 360 +#define KW_IS_UNION 361 +#define KW_LONG 362 +#define KW_MAKE_MAP_KEYS_SEQ 363 +#define KW_MAKE_MAP_PROPERTY 364 +#define KW_MAKE_PROPERTY 365 +#define KW_MAKE_PROPERTY2 366 +#define KW_MAKE_SEQ 367 +#define KW_MAKE_SEQ_PROPERTY 368 +#define KW_MUTABLE 369 +#define KW_NAMESPACE 370 +#define KW_NEW 371 +#define KW_NOEXCEPT 372 +#define KW_NOEXCEPT_LPAREN 373 +#define KW_NULLPTR 374 +#define KW_OPERATOR 375 +#define KW_OVERRIDE 376 +#define KW_PRIVATE 377 +#define KW_PROTECTED 378 +#define KW_PUBLIC 379 +#define KW_REGISTER 380 +#define KW_REINTERPRET_CAST 381 +#define KW_RESTRICT 382 +#define KW_RETURN 383 +#define KW_SHORT 384 +#define KW_SIGNED 385 +#define KW_SIZEOF 386 +#define KW_STATIC 387 +#define KW_STATIC_ASSERT 388 +#define KW_STATIC_CAST 389 +#define KW_STRUCT 390 +#define KW_TEMPLATE 391 +#define KW_THREAD_LOCAL 392 +#define KW_THROW 393 +#define KW_TRUE 394 +#define KW_TRY 395 +#define KW_TYPEDEF 396 +#define KW_TYPEID 397 +#define KW_TYPENAME 398 +#define KW_UNDERLYING_TYPE 399 +#define KW_UNION 400 +#define KW_UNSIGNED 401 +#define KW_USING 402 +#define KW_VIRTUAL 403 +#define KW_VOID 404 +#define KW_VOLATILE 405 +#define KW_WCHAR_T 406 +#define KW_WHILE 407 +#define START_CPP 408 +#define START_CONST_EXPR 409 +#define START_TYPE 410 /* Value type. */ diff --git a/dtool/src/cppparser/cppBison.yxx b/dtool/src/cppparser/cppBison.yxx index 6c0cf2a0d3..8a249d1185 100644 --- a/dtool/src/cppparser/cppBison.yxx +++ b/dtool/src/cppparser/cppBison.yxx @@ -262,6 +262,7 @@ pop_struct() { %token KW_BEGIN_PUBLISH %token KW_BLOCKING %token KW_BOOL +%token KW_BUILTIN_VA_LIST %token KW_CATCH %token KW_CHAR %token KW_CHAR8_T @@ -332,6 +333,7 @@ pop_struct() { %token KW_PUBLIC %token KW_REGISTER %token KW_REINTERPRET_CAST +%token KW_RESTRICT %token KW_RETURN %token KW_SHORT %token KW_SIGNED @@ -1830,6 +1832,19 @@ template_formal_parameter: $3->add_modifier(IIT_const); CPPInstance *inst = new CPPInstance($2, $3, 0, @3.file); $$ = inst; +} + | KW_VOLATILE template_formal_parameter_type formal_parameter_identifier template_parameter_maybe_initialize +{ + $3->add_modifier(IIT_volatile); + CPPInstance *inst = new CPPInstance($2, $3, 0, @3.file); + inst->set_initializer($4); + $$ = inst; +} + | KW_VOLATILE template_formal_parameter_type parameter_pack_identifier +{ + $3->add_modifier(IIT_volatile); + CPPInstance *inst = new CPPInstance($2, $3, 0, @3.file); + $$ = inst; } ; @@ -2181,50 +2196,29 @@ structure_init_body: ; function_parameter: - optional_attributes type formal_parameter_identifier maybe_initialize -{ - $3->add_attributes($1); - $$ = new CPPInstance($2, $3, 0, @3.file); - $$->set_initializer($4); -} - | optional_attributes KW_CONST type formal_parameter_identifier maybe_initialize + optional_attributes storage_class type formal_parameter_identifier maybe_initialize { + if ($2 & CPPInstance::SC_const) { + $4->add_modifier(IIT_const); + } + if ($2 & CPPInstance::SC_volatile) { + $4->add_modifier(IIT_volatile); + } $4->add_attributes($1); - $4->add_modifier(IIT_const); $$ = new CPPInstance($3, $4, 0, @4.file); $$->set_initializer($5); } - | optional_attributes KW_CONST KW_REGISTER type formal_parameter_identifier maybe_initialize -{ - $5->add_attributes($1); - $5->add_modifier(IIT_const); - $$ = new CPPInstance($4, $5, 0, @4.file); - $$->set_initializer($6); -} - | optional_attributes type_pack parameter_pack_identifier maybe_initialize -{ - $3->add_attributes($1); - $$ = new CPPInstance($2, $3, 0, @3.file); - $$->set_initializer($4); -} - | optional_attributes KW_CONST type_pack parameter_pack_identifier maybe_initialize + | optional_attributes storage_class type_pack parameter_pack_identifier maybe_initialize { + if ($2 & CPPInstance::SC_const) { + $4->add_modifier(IIT_const); + } + if ($2 & CPPInstance::SC_volatile) { + $4->add_modifier(IIT_volatile); + } $4->add_attributes($1); - $4->add_modifier(IIT_const); $$ = new CPPInstance($3, $4, 0, @4.file); $$->set_initializer($5); -} - | optional_attributes KW_CONST KW_REGISTER type_pack parameter_pack_identifier maybe_initialize -{ - $5->add_attributes($1); - $5->add_modifier(IIT_const); - $$ = new CPPInstance($4, $5, 0, @4.file); - $$->set_initializer($6); -} - | optional_attributes KW_REGISTER function_parameter -{ - $$ = $3; - $$->_attributes.add_attributes_from($1); } ; @@ -2264,6 +2258,11 @@ not_paren_formal_parameter_identifier: { $$ = $2; $$->add_modifier(IIT_volatile); +} + | KW_RESTRICT not_paren_formal_parameter_identifier %prec UNARY +{ + $$ = $2; + $$->add_modifier(IIT_restrict); } | '*' optional_attributes not_paren_formal_parameter_identifier %prec UNARY { @@ -2310,6 +2309,11 @@ formal_parameter_identifier: { $$ = $2; $$->add_modifier(IIT_volatile); +} + | KW_RESTRICT formal_parameter_identifier %prec UNARY +{ + $$ = $2; + $$->add_modifier(IIT_restrict); } | '*' optional_attributes formal_parameter_identifier %prec UNARY { @@ -2369,6 +2373,11 @@ parameter_pack_identifier: { $$ = $2; $$->add_modifier(IIT_volatile); +} + | KW_RESTRICT parameter_pack_identifier %prec UNARY +{ + $$ = $2; + $$->add_modifier(IIT_restrict); } | '*' optional_attributes parameter_pack_identifier %prec UNARY { @@ -2432,6 +2441,11 @@ not_paren_empty_instance_identifier: { $$ = $2; $$->add_modifier(IIT_volatile); +} + | KW_RESTRICT not_paren_empty_instance_identifier %prec UNARY +{ + $$ = $2; + $$->add_modifier(IIT_restrict); } | '*' optional_attributes not_paren_empty_instance_identifier %prec UNARY { @@ -2484,6 +2498,11 @@ empty_instance_identifier: { $$ = $2; $$->add_modifier(IIT_volatile); +} + | KW_RESTRICT empty_instance_identifier %prec UNARY +{ + $$ = $2; + $$->add_modifier(IIT_restrict); } | '*' optional_attributes not_paren_empty_instance_identifier %prec UNARY { @@ -2626,6 +2645,10 @@ type: | KW_AUTO { $$ = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_auto)); +} + | KW_BUILTIN_VA_LIST +{ + $$ = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_va_list)); } ; @@ -2745,6 +2768,10 @@ type_decl: | KW_AUTO { $$ = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_auto)); +} + | KW_BUILTIN_VA_LIST +{ + $$ = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_va_list)); } ; @@ -2819,6 +2846,10 @@ predefined_type: | KW_AUTO { $$ = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_auto)); +} + | KW_BUILTIN_VA_LIST +{ + $$ = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_va_list)); } ; @@ -3295,8 +3326,8 @@ element: | TIMESEQUAL | DIVIDEEQUAL | MODEQUAL | PLUSEQUAL | MINUSEQUAL | OREQUAL | ANDEQUAL | XOREQUAL | LSHIFTEQUAL | RSHIFTEQUAL | ATTR_LEFT | ATTR_RIGHT - | KW_ALIGNAS | KW_ALIGNOF | KW_AUTO | KW_BOOL | KW_CATCH - | KW_CHAR | KW_CHAR8_T | KW_CHAR16_T | KW_CHAR32_T | KW_CLASS + | KW_ALIGNAS | KW_ALIGNOF | KW_AUTO | KW_BOOL | KW_BUILTIN_VA_LIST + | KW_CATCH | KW_CHAR | KW_CHAR8_T | KW_CHAR16_T | KW_CHAR32_T | KW_CLASS | KW_CONST | KW_CONSTEVAL | KW_CONSTEXPR | KW_CONSTINIT | KW_CONST_CAST | KW_DECLTYPE | KW_DEFAULT | KW_DELETE | KW_DOUBLE | KW_DYNAMIC_CAST | KW_ELSE | KW_ENUM | KW_EXTERN | KW_EXPLICIT | KW_EXPLICIT_LPAREN @@ -3305,7 +3336,7 @@ element: | KW_NAMESPACE | KW_NEW | KW_NOEXCEPT | KW_NOEXCEPT_LPAREN | KW_NULLPTR | KW_OPERATOR | KW_OVERRIDE | KW_PRIVATE | KW_PROTECTED | KW_PUBLIC | KW_PUBLISHED | KW_REGISTER | KW_REINTERPRET_CAST - | KW_RETURN | KW_SHORT | KW_SIGNED | KW_SIZEOF | KW_STATIC + | KW_RESTRICT | KW_RETURN | KW_SHORT | KW_SIGNED | KW_SIZEOF | KW_STATIC | KW_STATIC_ASSERT | KW_STATIC_CAST | KW_STRUCT | KW_TEMPLATE | KW_THREAD_LOCAL | KW_THROW | KW_TRUE | KW_TRY | KW_TYPEDEF | KW_TYPEID | KW_TYPENAME | KW_UNDERLYING_TYPE | KW_UNION diff --git a/dtool/src/cppparser/cppEnumType.cxx b/dtool/src/cppparser/cppEnumType.cxx index 5ff18a65b0..1e0e133cad 100644 --- a/dtool/src/cppparser/cppEnumType.cxx +++ b/dtool/src/cppparser/cppEnumType.cxx @@ -117,6 +117,14 @@ add_element(const std::string &name, CPPExpression *value, } else if (_last_value->_type == CPPExpression::T_integer) { value = new CPPExpression(_last_value->_u._integer + 1); + } else if (_last_value->_type == CPPExpression::T_binary_operation && + _last_value->_u._op._operator == '+' && + _last_value->_u._op._op2->_type == CPPExpression::T_integer) { + // Prevent an endless expansion of + expressions. + value = new CPPExpression('+', + _last_value->_u._op._op1, + new CPPExpression(_last_value->_u._op._op2->_u._integer + 1)); + } else { // We may not be able to determine the value just yet. No problem; // we'll just define it as another expression. diff --git a/dtool/src/cppparser/cppExtensionType.cxx b/dtool/src/cppparser/cppExtensionType.cxx index bf0b963378..f82735274d 100644 --- a/dtool/src/cppparser/cppExtensionType.cxx +++ b/dtool/src/cppparser/cppExtensionType.cxx @@ -211,7 +211,7 @@ is_equivalent(const CPPType &other) const { // We consider two different extension types to be equivalent if they have // the same name. - return *_ident == *ot->_ident; + return _ident != nullptr && ot->_ident != nullptr && *_ident == *ot->_ident; } /** diff --git a/dtool/src/cppparser/cppFile.cxx b/dtool/src/cppparser/cppFile.cxx index ce9a61ffc5..bc3c5aeed0 100644 --- a/dtool/src/cppparser/cppFile.cxx +++ b/dtool/src/cppparser/cppFile.cxx @@ -31,37 +31,6 @@ CPPFile(const Filename &filename, const Filename &filename_as_referenced, _filename_as_referenced.set_text(); } - -/** - * - */ -CPPFile:: -CPPFile(const CPPFile ©) : - _filename(copy._filename), - _filename_as_referenced(copy._filename_as_referenced), - _source(copy._source), - _pragma_once(copy._pragma_once) -{ -} - -/** - * - */ -void CPPFile:: -operator = (const CPPFile ©) { - _filename = copy._filename; - _filename_as_referenced = copy._filename_as_referenced; - _source = copy._source; - _pragma_once = copy._pragma_once; -} - -/** - * - */ -CPPFile:: -~CPPFile() { -} - /** * Returns true if the file appears to be a C or C++ source code file based on * its extension. That is, returns true if the filename ends in .c, .C, .cc, diff --git a/dtool/src/cppparser/cppFile.h b/dtool/src/cppparser/cppFile.h index cd049e780f..5cc26d5e01 100644 --- a/dtool/src/cppparser/cppFile.h +++ b/dtool/src/cppparser/cppFile.h @@ -34,9 +34,6 @@ public: CPPFile(const Filename &filename = "", const Filename &filename_as_referenced = "", Source source = S_none); - CPPFile(const CPPFile ©); - void operator = (const CPPFile ©); - ~CPPFile(); bool is_c_or_i_file() const; static bool is_c_or_i_file(const Filename &filename); diff --git a/dtool/src/cppparser/cppInstanceIdentifier.cxx b/dtool/src/cppparser/cppInstanceIdentifier.cxx index 8c47c7d7ba..cc32ee8a81 100644 --- a/dtool/src/cppparser/cppInstanceIdentifier.cxx +++ b/dtool/src/cppparser/cppInstanceIdentifier.cxx @@ -302,6 +302,7 @@ r_unroll_type(CPPType *start_type, break; case IIT_volatile: + case IIT_restrict: // Just pass it through for now. result = r_unroll_type(start_type, mi); break; diff --git a/dtool/src/cppparser/cppInstanceIdentifier.h b/dtool/src/cppparser/cppInstanceIdentifier.h index 8a69504609..21117a8aea 100644 --- a/dtool/src/cppparser/cppInstanceIdentifier.h +++ b/dtool/src/cppparser/cppInstanceIdentifier.h @@ -35,6 +35,7 @@ enum CPPInstanceIdentifierType { IIT_array, IIT_const, IIT_volatile, + IIT_restrict, IIT_paren, IIT_func, IIT_initializer, diff --git a/dtool/src/cppparser/cppManifest.cxx b/dtool/src/cppparser/cppManifest.cxx index 197213df36..4a036f4d7a 100644 --- a/dtool/src/cppparser/cppManifest.cxx +++ b/dtool/src/cppparser/cppManifest.cxx @@ -13,6 +13,7 @@ #include "cppManifest.h" #include "cppExpression.h" +#include "cppPreprocessor.h" #include @@ -23,7 +24,11 @@ using std::string; */ CPPManifest::ExpansionNode:: ExpansionNode(int parm_number, bool stringify, bool paste) : - _parm_number(parm_number), _stringify(stringify), _paste(paste), _optional(false) + _parm_number(parm_number), + _expand(!stringify && !paste), + _stringify(stringify), + _paste(paste), + _optional(false) { } @@ -32,7 +37,12 @@ ExpansionNode(int parm_number, bool stringify, bool paste) : */ CPPManifest::ExpansionNode:: ExpansionNode(const string &str, bool paste) : - _parm_number(-1), _stringify(false), _paste(paste), _optional(false), _str(str) + _parm_number(-1), + _expand(!paste), + _stringify(false), + _paste(paste), + _optional(false), + _str(str) { } @@ -41,15 +51,35 @@ ExpansionNode(const string &str, bool paste) : */ CPPManifest::ExpansionNode:: ExpansionNode(Expansion nested, bool stringify, bool paste, bool optional) : - _parm_number(-1), _stringify(stringify), _paste(paste), _optional(optional), _nested(std::move(nested)) + _parm_number(-1), + _expand(!stringify && !paste), + _stringify(stringify), + _paste(paste), + _optional(optional), + _nested(std::move(nested)) { } +/** + * + */ +bool CPPManifest::ExpansionNode:: +operator ==(const ExpansionNode &other) const { + return _parm_number == other._parm_number + && _expand == other._expand + && _stringify == other._stringify + && _paste == other._paste + && _optional == other._optional + && _str == other._str + && _nested == other._nested; +} + /** * Creates a manifest from a preprocessor definition. */ CPPManifest:: -CPPManifest(const string &args, const cppyyltype &loc) : +CPPManifest(const CPPPreprocessor &parser, const string &args, const cppyyltype &loc) : + _parser(parser), _variadic_param(-1), _loc(loc), _expr(nullptr), @@ -93,7 +123,8 @@ CPPManifest(const string &args, const cppyyltype &loc) : * command-line -D option. */ CPPManifest:: -CPPManifest(const string ¯o, const string &definition) : +CPPManifest(const CPPPreprocessor &parser, const string ¯o, const string &definition) : + _parser(parser), _variadic_param(-1), _expr(nullptr), _vis(V_public) @@ -190,12 +221,112 @@ stringify(const string &source) { return result; } +/** + * + */ +void CPPManifest:: +extract_args(vector_string &args, const string &expr, size_t &p) const { + // Skip whitespace till paren. + while (p < expr.size() && isspace(expr[p])) { + p++; + } + if (p >= expr.size() || expr[p] != '(') { + // No paren, so we have only one arg. + size_t q = p; + while (p < expr.size() && (isalnum(expr[p]) || expr[p] == '_')) { + p++; + } + args.push_back(expr.substr(q, p - q)); + } + else if (expr[p] == '"' || expr[p] == '\'') { + // Quoted string or character. + int quote_mark = expr[p]; + p++; + while (p < expr.size() && expr[p] != quote_mark && expr[p] != '\n') { + if (expr[p] == '\\') { + p++; + } + if (p < expr.size()) { + p++; + } + } + p++; + } + else { + // Skip paren. + p++; + int paren_level = 1; + size_t q = p; + while (p < expr.size()) { + if (expr[p] == ',' && paren_level == 1) { + // Back up to strip any trailing whitespace. + size_t r = p; + while (r > q && isspace(expr[r - 1])) { + --r; + } + args.push_back(expr.substr(q, r - q)); + q = p+1; + } + else if (expr[p] == '"' || expr[p] == '\'') { + // Quoted string or character. + int quote_mark = expr[p]; + p++; + while (p < expr.size() && expr[p] != quote_mark && expr[p] != '\n') { + if (expr[p] == '\\') { + p++; + } + if (p < expr.size()) { + p++; + } + } + } + else if (expr[p] == '(') { + ++paren_level; + } + else if (expr[p] == ')') { + --paren_level; + if (paren_level == 0) { + break; + } + } + else if (isspace(expr[p])) { + // Skip whitespace at the beginning. + if (q == p) { + q++; + } + } + p++; + } + { + // Back up to strip any trailing whitespace. + size_t r = p; + while (r > q && isspace(expr[r - 1])) { + --r; + } + if (!args.empty() || r > q) { + args.push_back(expr.substr(q, r - q)); + } + } + + if (p < expr.size() && expr[p] == ')') { + p++; + } + } + + if ((int)args.size() < _num_parameters) { + _parser.warning("Not enough arguments for manifest " + _name); + } + else if (_variadic_param < 0 && (int)args.size() > _num_parameters) { + _parser.warning("Too many arguments for manifest " + _name); + } +} + /** * */ string CPPManifest:: -expand(const vector_string &args) const { - return r_expand(_expansion, args); +expand(const vector_string &args, bool expand_undefined, const Ignores &ignores) const { + return r_expand(_expansion, args, expand_undefined, ignores); } /** @@ -210,6 +341,32 @@ determine_type() const { return nullptr; } +/** + * Returns true if the macro definitions are equal. + */ +bool CPPManifest:: +is_equal(const CPPManifest *other) const { + if (this == other) { + return true; + } + if (_name != other->_name) { + return false; + } + if (_has_parameters != other->_has_parameters) { + return false; + } + if (_num_parameters != other->_num_parameters) { + return false; + } + if (_variadic_param != other->_variadic_param) { + return false; + } + if (_expansion != other->_expansion) { + return false; + } + return true; +} + /** * */ @@ -409,6 +566,10 @@ save_expansion(Expansion &expansion, const string &exp, const vector_string &par if (p < exp.size() && exp[p] == '#') { // Woah, this is a token-pasting operator. paste = true; + if (!expansion.empty()) { + // The previous expansion shouldn't be expanded. + expansion.back()._expand = false; + } ++p; } else { // Mark that the next argument should be stringified. @@ -439,7 +600,8 @@ save_expansion(Expansion &expansion, const string &exp, const vector_string &par * */ string CPPManifest:: -r_expand(const Expansion &expansion, const vector_string &args) const { +r_expand(const Expansion &expansion, const vector_string &args, + bool expand_undefined, const Ignores &ignores) const { std::string result; for (const ExpansionNode &node : expansion) { @@ -458,7 +620,8 @@ r_expand(const Expansion &expansion, const vector_string &args) const { if (node._stringify) { subst = stringify(subst); } - } else if (i == _variadic_param && node._paste) { + } + else if (i == _variadic_param && node._paste) { // Special case GCC behavior: if __VA_ARGS__ is pasted to a comma and // no arguments are passed, the comma is removed. MSVC does this // automatically. Not sure if we should allow MSVC behavior as well. @@ -467,8 +630,12 @@ r_expand(const Expansion &expansion, const vector_string &args) const { } } + if (node._expand) { + _parser.expand_manifests(subst, expand_undefined, ignores); + } + if (!subst.empty()) { - if (result.empty() || node._paste) { + if (result.empty() || node._paste || result.back() == '(') { result += subst; } else { result += ' '; @@ -477,7 +644,7 @@ r_expand(const Expansion &expansion, const vector_string &args) const { } } if (!node._str.empty()) { - if (result.empty() || node._paste) { + if (result.empty() || node._paste || node._str[0] == ',' || node._str[0] == ')') { result += node._str; } else { result += ' '; @@ -487,7 +654,7 @@ r_expand(const Expansion &expansion, const vector_string &args) const { if (!node._nested.empty()) { string nested_result; if (node._optional && args.size() >= _num_parameters) { - nested_result = r_expand(node._nested, args); + nested_result = r_expand(node._nested, args, expand_undefined, ignores); } if (node._stringify) { nested_result = stringify(nested_result); diff --git a/dtool/src/cppparser/cppManifest.h b/dtool/src/cppparser/cppManifest.h index 3fe0f1b4a1..f1e4902ab1 100644 --- a/dtool/src/cppparser/cppManifest.h +++ b/dtool/src/cppparser/cppManifest.h @@ -21,6 +21,7 @@ #include "cppBisonDefs.h" #include "vector_string.h" +#include class CPPExpression; class CPPType; @@ -30,17 +31,25 @@ class CPPType; */ class CPPManifest { public: - CPPManifest(const std::string &args, const cppyyltype &loc); - CPPManifest(const std::string ¯o, const std::string &definition); + typedef std::unordered_set Ignores; + + CPPManifest(const CPPPreprocessor &parser, const std::string &args, const cppyyltype &loc); + CPPManifest(const CPPPreprocessor &parser, const std::string ¯o, const std::string &definition); ~CPPManifest(); static std::string stringify(const std::string &source); - std::string expand(const vector_string &args = vector_string()) const; + void extract_args(vector_string &args, const std::string &expr, size_t &p) const; + std::string expand(const vector_string &args = vector_string(), + bool expand_undefined = false, + const Ignores &ignores = Ignores()) const; + CPPType *determine_type() const; + bool is_equal(const CPPManifest *other) const; void output(std::ostream &out) const; + const CPPPreprocessor &_parser; std::string _name; bool _has_parameters; size_t _num_parameters; @@ -59,7 +68,11 @@ private: ExpansionNode(int parm_number, bool stringify, bool paste); ExpansionNode(const std::string &str, bool paste = false); ExpansionNode(std::vector nested, bool stringify = false, bool paste = false, bool optional = false); + + bool operator ==(const ExpansionNode &other) const; + int _parm_number; + bool _expand; bool _stringify; bool _paste; bool _optional; @@ -73,8 +86,8 @@ private: void save_expansion(Expansion &expansion, const std::string &exp, const vector_string ¶meter_names); - std::string r_expand(const Expansion &expansion, - const vector_string &args = vector_string()) const; + std::string r_expand(const Expansion &expansion, const vector_string &args, + bool expand_undefined, const Ignores &ignores) const; Expansion _expansion; }; diff --git a/dtool/src/cppparser/cppPreprocessor.cxx b/dtool/src/cppparser/cppPreprocessor.cxx index 878e1c66d0..74d2803e5c 100644 --- a/dtool/src/cppparser/cppPreprocessor.cxx +++ b/dtool/src/cppparser/cppPreprocessor.cxx @@ -34,6 +34,7 @@ #include #include +#include using std::cerr; using std::string; @@ -45,6 +46,132 @@ using std::string; // behind the preprocessor.) static CPPVisibility preprocessor_vis = V_public; +// Don't forget to update CPPToken::output() when adding entries. +static const std::unordered_map keywords = { + {"alignas", KW_ALIGNAS}, + {"alignof", KW_ALIGNOF}, + {"__alignof", KW_ALIGNOF}, + {"__alignof__", KW_ALIGNOF}, + {"auto", KW_AUTO}, + {"__begin_publish", KW_BEGIN_PUBLISH}, + {"__blocking", KW_BLOCKING}, + {"bool", KW_BOOL}, + {"__builtin_va_list", KW_BUILTIN_VA_LIST}, + {"catch", KW_CATCH}, + {"char", KW_CHAR}, + {"char8_t", KW_CHAR8_T}, + {"char16_t", KW_CHAR16_T}, + {"char32_t", KW_CHAR32_T}, + {"class", KW_CLASS}, + {"const", KW_CONST}, + {"__const", KW_CONST}, + {"__const__", KW_CONST}, + {"consteval", KW_CONSTEVAL}, + {"constexpr", KW_CONSTEXPR}, + {"constinit", KW_CONSTINIT}, + {"const_cast", KW_CONST_CAST}, + {"decltype", KW_DECLTYPE}, + {"default", KW_DEFAULT}, + {"delete", KW_DELETE}, + {"double", KW_DOUBLE}, + {"dynamic_cast", KW_DYNAMIC_CAST}, + {"else", KW_ELSE}, + {"__end_publish", KW_END_PUBLISH}, + {"enum", KW_ENUM}, + {"extern", KW_EXTERN}, + {"__extension", KW_EXTENSION}, + {"explicit", KW_EXPLICIT}, + {"__published", KW_PUBLISHED}, + {"false", KW_FALSE}, + {"final", KW_FINAL}, + {"float", KW_FLOAT}, + {"friend", KW_FRIEND}, + {"for", KW_FOR}, + {"goto", KW_GOTO}, + {"__has_virtual_destructor", KW_HAS_VIRTUAL_DESTRUCTOR}, + {"if", KW_IF}, + {"inline", KW_INLINE}, + {"__inline", KW_INLINE}, + {"__inline__", KW_INLINE}, + {"int", KW_INT}, + {"__is_abstract", KW_IS_ABSTRACT}, + {"__is_base_of", KW_IS_BASE_OF}, + {"__is_class", KW_IS_CLASS}, + {"__is_constructible", KW_IS_CONSTRUCTIBLE}, + {"__is_convertible_to", KW_IS_CONVERTIBLE_TO}, + {"__is_destructible", KW_IS_DESTRUCTIBLE}, + {"__is_empty", KW_IS_EMPTY}, + {"__is_enum", KW_IS_ENUM}, + {"__is_final", KW_IS_FINAL}, + {"__is_fundamental", KW_IS_FUNDAMENTAL}, + {"__is_pod", KW_IS_POD}, + {"__is_polymorphic", KW_IS_POLYMORPHIC}, + {"__is_standard_layout", KW_IS_STANDARD_LAYOUT}, + {"__is_trivial", KW_IS_TRIVIAL}, + {"__is_trivially_copyable", KW_IS_TRIVIALLY_COPYABLE}, + {"__is_union", KW_IS_UNION}, + {"long", KW_LONG}, + {"__make_map_keys_seq", KW_MAKE_MAP_KEYS_SEQ}, + {"__make_map_property", KW_MAKE_MAP_PROPERTY}, + {"__make_property", KW_MAKE_PROPERTY}, + {"__make_property2", KW_MAKE_PROPERTY2}, + {"__make_seq", KW_MAKE_SEQ}, + {"__make_seq_property", KW_MAKE_SEQ_PROPERTY}, + {"mutable", KW_MUTABLE}, + {"namespace", KW_NAMESPACE}, + {"noexcept", KW_NOEXCEPT}, + {"nullptr", KW_NULLPTR}, + {"new", KW_NEW}, + {"operator", KW_OPERATOR}, + {"override", KW_OVERRIDE}, + {"private", KW_PRIVATE}, + {"protected", KW_PROTECTED}, + {"public", KW_PUBLIC}, + {"register", KW_REGISTER}, + {"reinterpret_cast", KW_REINTERPRET_CAST}, + //{"restrict", KW_RESTRICT}, + {"__restrict", KW_RESTRICT}, + {"__restrict__", KW_RESTRICT}, + {"return", KW_RETURN}, + {"short", KW_SHORT}, + {"signed", KW_SIGNED}, + {"sizeof", KW_SIZEOF}, + {"static", KW_STATIC}, + {"static_assert", KW_STATIC_ASSERT}, + {"static_cast", KW_STATIC_CAST}, + {"struct", KW_STRUCT}, + {"template", KW_TEMPLATE}, + {"thread_local", KW_THREAD_LOCAL}, + {"throw", KW_THROW}, + {"true", KW_TRUE}, + {"try", KW_TRY}, + {"typedef", KW_TYPEDEF}, + {"typeid", KW_TYPEID}, + {"typename", KW_TYPENAME}, + {"__underlying_type", KW_UNDERLYING_TYPE}, + {"union", KW_UNION}, + {"unsigned", KW_UNSIGNED}, + {"using", KW_USING}, + {"virtual", KW_VIRTUAL}, + {"void", KW_VOID}, + {"volatile", KW_VOLATILE}, + {"wchar_t", KW_WCHAR_T}, + {"while", KW_WHILE}, + + // These are alternative ways to refer to built-in operators. + {"and", ANDAND}, + {"and_eq", ANDEQUAL}, + {"bitand", '&'}, + {"bitor", '|'}, + {"compl", '~'}, + {"not", '!'}, + {"not_eq", NECOMPARE}, + {"or", OROR}, + {"or_eq", OREQUAL}, + {"xor", '^'}, + {"xor_eq", XOREQUAL}, +}; + static int hex_val(int c) { switch (c) { @@ -91,12 +218,13 @@ trim_blanks(const string &str) { CPPPreprocessor::InputFile:: InputFile() { _in = nullptr; - _ignore_manifest = nullptr; + _manifest = nullptr; _line_number = 0; _col_number = 0; _next_line_number = 1; _next_col_number = 1; _lock_position = false; + _ignore_manifest = false; } /** @@ -230,6 +358,65 @@ CPPPreprocessor() { _verbose = 1; } +/** + * + */ +bool CPPPreprocessor:: +preprocess_file(const Filename &filename) { + Filename canonical(filename); + canonical.make_canonical(); + + CPPFile file(canonical, filename, CPPFile::S_local); + + // Don't read it if we included it before and it had #pragma once. + ParsedFiles::iterator it = _parsed_files.find(file); + if (it != _parsed_files.end() && it->_pragma_once) { + // But mark it as local. + it->_source = CPPFile::S_local; + return true; + } + + if (!init_cpp(file)) { + std::cerr << "Unable to read " << filename << "\n"; + return false; + } + + int line_number = 1; + int nesting = 0; + bool next_space = false; + CPPToken token = get_next_token(); + while (!token.is_eof()) { + if (token._token == '}') { + nesting -= 1; + } + if (token._lloc.first_line > line_number) { + // Token is on a different line, so insert a newline. + std::cout << "\n"; + line_number = token._lloc.first_line; + indent(std::cout, nesting * 2); + } + else if (next_space && token._token != ';' && token._token != ':' && token._token != ',' && token._token != ')') { + // The above tokens never need a preceding space + std::cout << " "; + } + if (token._token == '{') { + nesting += 1; + } + next_space = (token._token != '(' && token._token != '~'); + token.output_code(std::cout); + + CPPToken next_token = get_next_token(); + if (next_token._lloc.file != token._lloc.file) { + // Switched to a new file, reset the line number. + line_number = 0; + } + token = std::move(next_token); + } + std::cout << "\n"; + + return get_error_count() == 0; +} + /** * Sets the verbosity level of the parser. At 0, no warnings will be * reported; at 1 or higher, expect to get spammed. @@ -252,10 +439,11 @@ get_verbose() const { */ void CPPPreprocessor:: copy_filepos(const CPPPreprocessor &other) { - assert(!_files.empty()); - _files.back()._file = other.get_file(); - _files.back()._line_number = other.get_line_number(); - _files.back()._col_number = other.get_col_number(); + InputFile *infile = _infile; + assert(infile != nullptr); + infile->_file = other.get_file(); + infile->_line_number = other.get_line_number(); + infile->_col_number = other.get_col_number(); } /** @@ -263,10 +451,12 @@ copy_filepos(const CPPPreprocessor &other) { */ CPPFile CPPPreprocessor:: get_file() const { - if (_files.empty()) { + InputFile *infile = _infile; + if (infile != nullptr) { + return infile->_file; + } else { return CPPFile(""); } - return _files.back()._file; } /** @@ -274,10 +464,12 @@ get_file() const { */ int CPPPreprocessor:: get_line_number() const { - if (_files.empty()) { + InputFile *infile = _infile; + if (infile != nullptr) { + return infile->_line_number; + } else { return 0; } - return _files.back()._line_number; } /** @@ -285,10 +477,12 @@ get_line_number() const { */ int CPPPreprocessor:: get_col_number() const { - if (_files.empty()) { + InputFile *infile = _infile; + if (infile != nullptr) { + return infile->_col_number; + } else { return 0; } - return _files.back()._col_number; } /** @@ -299,7 +493,7 @@ get_next_token() { #ifdef CPP_VERBOSE_LEX CPPToken tok = get_next_token0(); - indent(cerr, _files.size() * 2) + indent(cerr, get_file_depth() * 2) << _token_index++ << ". " << tok << "\n"; return tok; } @@ -314,7 +508,7 @@ get_next_token0() { CPPToken token(0); if (!_saved_tokens.empty()) { - token = _saved_tokens.back(); + token = std::move(_saved_tokens.back()); _saved_tokens.pop_back(); } else { token = internal_get_next_token(); @@ -351,8 +545,8 @@ get_next_token0() { ident->_names.back().set_templ (nested_parse_template_instantiation(decl->get_template_scope())); token = internal_get_next_token(); - } else { - error(string("unknown template '") + ident->get_fully_scoped_name() + "'", loc); + //} else { + // error(string("unknown template '") + ident->get_fully_scoped_name() + "'", loc); } } @@ -459,7 +653,7 @@ peek_next_token() { * */ void CPPPreprocessor:: -warning(const string &message) { +warning(const string &message) const { if (_verbose < 2) { return; } @@ -478,10 +672,10 @@ warning(const string &message) { * */ void CPPPreprocessor:: -warning(const string &message, const YYLTYPE &loc) { +warning(const string &message, const YYLTYPE &loc) const { if (_verbose >= 2) { if (_verbose >= 3) { - indent(cerr, _files.size() * 2); + indent(cerr, get_file_depth() * 2); } if (!loc.file.empty()) { @@ -505,7 +699,7 @@ warning(const string &message, const YYLTYPE &loc) { * */ void CPPPreprocessor:: -error(const string &message) { +error(const string &message) const { int line = get_line_number(); int col = get_col_number(); YYLTYPE loc; @@ -521,7 +715,7 @@ error(const string &message) { * */ void CPPPreprocessor:: -error(const string &message, const YYLTYPE &loc) { +error(const string &message, const YYLTYPE &loc) const { if (_state == S_nested || _state == S_end_nested) { // Don't report or log errors in the nested state. These will be reported // when the nesting level collapses. @@ -530,7 +724,7 @@ error(const string &message, const YYLTYPE &loc) { if (_verbose >= 1) { if (_verbose >= 3) { - indent(cerr, _files.size() * 2); + indent(cerr, get_file_depth() * 2); } if (!loc.file.empty()) { @@ -547,6 +741,34 @@ error(const string &message, const YYLTYPE &loc) { cerr << " error: " << message << "\n"; show_line(loc); + InputFile *infile = _infile; + if (infile != nullptr && !loc.file.empty()) { + // Add all the expansions to a vector for easy reverse iteration. + std::vector infiles; + while (infile != nullptr && infile->_file == loc.file && infile->_manifest != nullptr) { + infiles.push_back(infile); + infile = infile->_parent; + } + if (!infiles.empty()) { + auto rit = infiles.rbegin(); + if (_verbose >= 3) { + cerr << "Expansion of " << (*rit)->_manifest->_name << ":\n"; + while (rit != infiles.rend()) { + cerr << " -> " << trim_blanks((*rit)->_input) << "\n"; + ++rit; + } + } + else { + cerr << "with " << (*rit)->_manifest->_name; + if ((*rit)->_manifest->_has_parameters) { + cerr << "()"; + } + cerr << " expanded to: " << trim_blanks(_infile->_input) << "\n"; + } + cerr << std::endl; + } + } + if (_error_abort) { cerr << "Aborting.\n"; abort(); @@ -559,14 +781,14 @@ error(const string &message, const YYLTYPE &loc) { * Shows the indicated line, useful for error messages. */ void CPPPreprocessor:: -show_line(const YYLTYPE &loc) { +show_line(const YYLTYPE &loc) const { if (loc.file._filename.empty()) { return; } int indent_level = 0; if (_verbose >= 3) { - indent_level = _files.size() * 2; + indent_level = get_file_depth() * 2; } // Seek to the offending line in the file. @@ -705,7 +927,7 @@ init_const_expr(const string &expr) { _state = S_normal; _saved_tokens.push_back(CPPToken(START_CONST_EXPR)); - return push_string(expr, false); + return push_string(expr); } /** @@ -716,7 +938,7 @@ init_type(const string &type) { _state = S_normal; _saved_tokens.push_back(CPPToken(START_TYPE)); - return push_string(type, false); + return push_string(type); } /** @@ -725,25 +947,26 @@ init_type(const string &type) { bool CPPPreprocessor:: push_file(const CPPFile &file) { if (_verbose >= 3) { - indent(cerr, _files.size() * 2) + indent(cerr, get_file_depth() * 2) << "Reading " << file << "\n"; } assert(_last_c == 0); - _files.push_back(InputFile()); - InputFile &infile = _files.back(); + InputFile *infile = new InputFile; + if (infile->open(file)) { + infile->_parent = _infile; + _infile = infile; - if (infile.open(file)) { // Record the fact that we opened the file for the benefit of user code. _parsed_files.insert(file); - infile._prev_last_c = _last_c; + infile->_prev_last_c = _last_c; _last_c = '\0'; _start_of_line = true; return true; } - _files.pop_back(); + delete infile; return false; } @@ -751,126 +974,170 @@ push_file(const CPPFile &file) { * */ bool CPPPreprocessor:: -push_string(const string &input, bool lock_position) { +push_string(const string &input) { #ifdef CPP_VERBOSE_LEX - indent(cerr, _files.size() * 2) + indent(cerr, get_file_depth() * 2) << "Pushing to string \"" << input - << "\"\nlock_position = " << lock_position << "\n"; + << "\"\n"; #endif - CPPFile first_file = get_file(); - int first_line = get_line_number(); - int first_col = get_col_number(); - _files.push_back(InputFile()); - InputFile &infile = _files.back(); - - if (infile.connect_input(input)) { - if (lock_position) { - infile._file = first_file; - infile._line_number = first_line; - infile._col_number = first_col; - infile._lock_position = true; - } - - infile._prev_last_c = _last_c; + InputFile *infile = new InputFile; + if (infile->connect_input(input)) { + infile->_prev_last_c = _last_c; + infile->_parent = _infile; + _infile = infile; _last_c = '\0'; return true; } #ifdef CPP_VERBOSE_LEX - indent(cerr, _files.size() * 2) + indent(cerr, get_file_depth() * 2) << "Unable to read string\n"; #endif - _files.pop_back(); + delete infile; return false; } /** - * Given a string, expand all manifests within the string and return the new - * string. + * */ -string CPPPreprocessor:: -expand_manifests(const string &input_expr, bool expand_undefined, - const YYLTYPE &loc) { - // Get a copy of the expression string we can modify. - string expr = input_expr; +bool CPPPreprocessor:: +push_expansion(const string &input, const CPPManifest *manifest, const YYLTYPE &loc) { +#ifdef CPP_VERBOSE_LEX + indent(cerr, get_file_depth() * 2) + << "Pushing to expansion \"" << input + << "\"\n"; +#endif - // Repeatedly scan the expr for any manifest names or defined() function. + InputFile *infile = new InputFile; + if (infile->connect_input(input)) { + infile->_manifest = manifest; + infile->_file = loc.file; + infile->_line_number = loc.first_line; + infile->_col_number = loc.first_column; + infile->_lock_position = true; - bool manifest_found; - do { - manifest_found = false; - size_t p = 0; - while (p < expr.size()) { - if (isalpha(expr[p]) || expr[p] == '_') { - size_t q = p; - while (p < expr.size() && (isalnum(expr[p]) || expr[p] == '_')) { - p++; - } - string ident = expr.substr(q, p - q); - - // Here's an identifier. Is it "defined"? - if (ident == "defined") { - expand_defined_function(expr, q, p); - } else if (expand_undefined && ident == "__has_include") { - expand_has_include_function(expr, q, p, loc); - } else { - // Is it a manifest? - Manifests::const_iterator mi = _manifests.find(ident); - if (mi != _manifests.end()) { - const CPPManifest *manifest = (*mi).second; - expand_manifest_inline(expr, q, p, manifest); - manifest_found = true; - - } else if (ident == "__FILE__") { - // Special case: this is a dynamic definition. - string file = string("\"") + loc.file._filename_as_referenced.get_fullpath() + "\""; - expr = expr.substr(0, q) + file + expr.substr(p); - p = q + file.size(); - manifest_found = true; - - } else if (ident == "__LINE__") { - // So is this. - string line = format_string(loc.first_line); - expr = expr.substr(0, q) + line + expr.substr(p); - p = q + line.size(); - manifest_found = true; - - } else if (expand_undefined && ident != "true" && ident != "false") { - // It is not found. Expand it to 0, but only if we are currently - // parsing an #if expression. - expr = expr.substr(0, q) + "0" + expr.substr(p); - p = q + 1; - } - } - } else if (expr[p] == '\'' || expr[p] == '"') { - // Skip the next part until we find a closing quotation mark. - char quote = expr[p]; - p++; - while (p < expr.size() && expr[p] != quote) { - if (expr[p] == '\\') { - // This might be an escaped quote. Skip an extra char. - p++; - } - p++; - } - if (p >= expr.size()) { - // Unclosed string. - warning("missing terminating " + string(1, quote) + " character", loc); - } - p++; - } else { - p++; - } + if (!manifest->_has_parameters) { + // If the manifest does not use arguments, then disallow recursive + // expansion. + infile->_ignore_manifest = true; } - // If we expanded any manifests at all that time, then go back through the - // string and look again--we might have a manifest that expands to another - // manifest. - } while (manifest_found); + infile->_prev_last_c = _last_c; + infile->_parent = _infile; + _infile = infile; + _last_c = '\0'; + return true; + } - return expr; +#ifdef CPP_VERBOSE_LEX + indent(cerr, get_file_depth() * 2) + << "Unable to read expansion\n"; +#endif + + delete infile; + return false; +} + +/** + * Given a string, expand all manifests within the string. + */ +void CPPPreprocessor:: +expand_manifests(string &expr, bool expand_undefined, + const CPPManifest::Ignores &ignores) const { + size_t p = 0; + while (p < expr.size()) { + if (isalpha(expr[p]) || expr[p] == '_') { + size_t q = p; + while (p < expr.size() && (isalnum(expr[p]) || expr[p] == '_')) { + p++; + } + string ident = expr.substr(q, p - q); + + // Here's an identifier. Is it "defined"? + if (ident == "defined") { + expand_defined_function(expr, q, p); + } + else if (expand_undefined && ident == "__has_include") { + expand_has_include_function(expr, q, p); + } + else if (ident == "L" && p < expr.size() && (expr[p] == '\'' || expr[p] == '\"')) { + // Special exception for the wide string literal suffix, which is + // never expanded. + } + else { + // Is it a manifest? + Manifests::const_iterator mi = _manifests.find(ident); + if (mi != _manifests.end() && ignores.count((*mi).second) == 0) { + const CPPManifest *manifest = (*mi).second; + vector_string args; + if (manifest->_has_parameters) { + // If it's not followed by a parenthesis, don't expand it. + while (p < expr.size() && isspace(expr[p])) { + p++; + } + if (p >= expr.size() || expr[p] != '(') { + continue; + } + + manifest->extract_args(args, expr, p); + } + + // Don't consider this manifest when expanding the arguments or + // result, to prevent recursion. + CPPManifest::Ignores nested_ignores(ignores); + nested_ignores.insert(manifest); + + string result = manifest->expand(args, expand_undefined, nested_ignores); + expand_manifests(result, expand_undefined, nested_ignores); + + expr = expr.substr(0, q) + result + expr.substr(p); + p = q + result.size(); + } + else if (ident == "__FILE__") { + // Special case: this is a dynamic definition. + CPPFile file = get_file(); + string result = string("\"") + file._filename_as_referenced.get_fullpath() + "\""; + expr = expr.substr(0, q) + result + expr.substr(p); + p = q + result.size(); + + } + else if (ident == "__LINE__") { + // So is this. + string line = format_string(get_line_number()); + expr = expr.substr(0, q) + line + expr.substr(p); + p = q + line.size(); + } + else if (expand_undefined && ident != "true" && ident != "false") { + // It is not found. Expand it to 0, but only if we are currently + // parsing an #if expression. + expr = expr.substr(0, q) + "0" + expr.substr(p); + p = q + 1; + } + } + } + else if (expr[p] == '\'' || expr[p] == '"') { + // Skip the next part until we find a closing quotation mark. + char quote = expr[p]; + p++; + while (p < expr.size() && expr[p] != quote) { + if (expr[p] == '\\') { + // This might be an escaped quote. Skip an extra char. + p++; + } + p++; + } + if (p >= expr.size()) { + // Unclosed string. + warning("missing terminating " + string(1, quote) + " character"); + } + p++; + } + else { + p++; + } + } } /** @@ -883,7 +1150,8 @@ expand_manifests(const string &input_expr, bool expand_undefined, CPPExpression *CPPPreprocessor:: parse_expr(const string &input_expr, CPPScope *current_scope, CPPScope *global_scope, const YYLTYPE &loc) { - string expr = expand_manifests(input_expr, false, loc); + string expr = input_expr; + expand_manifests(expr, false); CPPExpressionParser ep(current_scope, global_scope); ep._verbose = 0; @@ -1389,7 +1657,7 @@ process_directive(int c) { loc.last_column = 0; #ifdef CPP_VERBOSE_LEX - indent(cerr, _files.size() * 2) + indent(cerr, get_file_depth() * 2) << "#" << command << " " << args << "\n"; #endif @@ -1456,6 +1724,9 @@ get_preprocessor_args(int c, string &args) { // Following the command, the rest of the line, as well as any text on // successive lines, is part of the arguments to the command. + // Check for comments first. + c = skip_comment(c); + while (c != EOF && c != '\n') { if (c == '\\') { int next_c = get(); @@ -1489,7 +1760,7 @@ handle_define_directive(const string &args, const YYLTYPE &loc) { if (args.empty()) { warning("Ignoring empty #define directive", loc); } else { - CPPManifest *manifest = new CPPManifest(args, loc); + CPPManifest *manifest = new CPPManifest(*this, args, loc); manifest->_vis = preprocessor_vis; if (!manifest->_has_parameters) { string expr_string = manifest->expand(); @@ -1504,8 +1775,10 @@ handle_define_directive(const string &args, const YYLTYPE &loc) { if (!result.second) { // There was already a macro with this name. Delete the old. CPPManifest *other = result.first->second; - warning("redefinition of macro '" + manifest->_name + "'", loc); - warning("previous definition is here", other->_loc); + if (!manifest->is_equal(other)) { + warning("redefinition of macro '" + manifest->_name + "'", loc); + warning("previous definition is here", other->_loc); + } result.first->second = manifest; } } @@ -1554,7 +1827,8 @@ handle_ifndef_directive(const string &args, const YYLTYPE &loc) { void CPPPreprocessor:: handle_if_directive(const string &args, const YYLTYPE &loc) { // When expanding manifests, we should replace unknown macros with 0. - string expr = expand_manifests(args, true, loc); + string expr = args; + expand_manifests(expr, true); int expression_result = 0; CPPExpressionParser ep(current_scope, global_scope); @@ -1599,14 +1873,14 @@ handle_include_directive(const string &args, const YYLTYPE &loc) { // filter out quotes and angle brackets properly, we'll only expand // manifests if we don't begin with a quote or bracket. if (!expr.empty() && (expr[0] != '"' && expr[0] != '<')) { - expr = expand_manifests(expr, false, loc); + expand_manifests(expr, false); } if (!expr.empty()) { if (expr[0] == '"' && expr[expr.size() - 1] == '"') { filename = expr.substr(1, expr.size() - 2); - if (_files.size() == 1) { + if (_infile->_parent == nullptr) { // If we're currently processing a top-level file, record the include // directive. We don't need to record includes from included files. _quote_includes.insert(filename); @@ -1620,7 +1894,7 @@ handle_include_directive(const string &args, const YYLTYPE &loc) { angle_quotes = true; } - if (_files.size() == 1) { + if (_infile->_parent == nullptr) { // If we're currently processing a top-level file, record the include // directive. We don't need to record includes from included files. _angle_includes.insert(filename); @@ -1777,7 +2051,7 @@ skip_false_if_block(bool consider_elifs) { * Returns true if the given manifest is defined. */ bool CPPPreprocessor:: -is_manifest_defined(const string &manifest_name) { +is_manifest_defined(const string &manifest_name) const { Manifests::const_iterator mi = _manifests.find(manifest_name); if (mi != _manifests.end()) { return true; @@ -1797,7 +2071,7 @@ is_manifest_defined(const string &manifest_name) { * Locates the given filename. Changes the first argument to the full path. */ bool CPPPreprocessor:: -find_include(Filename &filename, bool angle_quotes, CPPFile::Source &source) { +find_include(Filename &filename, bool angle_quotes, CPPFile::Source &source) const { // Now look for the filename. If we didn't use angle quotes, look first in // the current directory. if (!angle_quotes && filename.exists()) { @@ -1956,11 +2230,11 @@ get_identifier(int c) { } if (c == '(') { // It is followed by a parenthesis, so we can expand this. - return expand_manifest(manifest); + return expand_manifest(manifest, loc); } } else { // Non-function-like macros are always expanded. - return expand_manifest(manifest); + return expand_manifest(manifest, loc); } } if (name == "__FILE__") { @@ -1973,7 +2247,8 @@ get_identifier(int c) { } // Check for keywords. - int kw = check_keyword(name); + auto kwit = keywords.find(name); + int kw = (kwit != keywords.end()) ? (*kwit).second : 0; // Update our internal visibility flag. switch (kw) { @@ -2059,6 +2334,17 @@ get_literal(int token, YYLTYPE loc, const string &str, const YYSTYPE &value) { CPPIdentifier *ident = new CPPIdentifier("operator \"\" " + suffix); CPPDeclaration *decl = ident->find_symbol(current_scope, global_scope, this); + if (decl == nullptr) { + // Special case to handle C code, which allows a macro to directly follow + // a string, like "str"SUFFIX. In this case, it becomes a separate token. + Manifests::const_iterator mi = _manifests.find(suffix); + if (mi != _manifests.end() && !should_ignore_manifest((*mi).second)) { + CPPManifest *manifest = (*mi).second; + _saved_tokens.push_back(expand_manifest(manifest, loc)); + return CPPToken(token, loc, str, value); + } + } + if (decl == nullptr || decl->get_subtype() != CPPDeclaration::ST_function_group) { error("unknown literal suffix " + suffix, loc); return CPPToken(token, loc, str, value); @@ -2181,7 +2467,7 @@ get_literal(int token, YYLTYPE loc, const string &str, const YYSTYPE &value) { * */ CPPToken CPPPreprocessor:: -expand_manifest(const CPPManifest *manifest) { +expand_manifest(const CPPManifest *manifest, const YYLTYPE &loc) { vector_string args; if (manifest->_has_parameters) { @@ -2190,17 +2476,23 @@ expand_manifest(const CPPManifest *manifest) { manifest->_variadic_param, args); } - string expanded = " " + manifest->expand(args) + " "; - push_string(expanded, true); + // Keep track of the manifests we're supposed to ignore. + CPPManifest::Ignores ignores; + ignores.insert(manifest); - if (!manifest->_has_parameters) { - // If the manifest does not use arguments, then disallow recursive - // expansion. - _files.back()._ignore_manifest = manifest; + InputFile *infile = _infile; + while (infile != nullptr) { + if (infile->_ignore_manifest) { + ignores.insert(infile->_manifest); + } + infile = infile->_parent; } + string expanded = " " + manifest->expand(args, false, ignores) + " "; + push_expansion(expanded, manifest, loc); + #ifdef CPP_VERBOSE_LEX - indent(cerr, _files.size() * 2) + indent(cerr, get_file_depth() * 2) << "Expanding " << manifest->_name << " to " << expanded << "\n"; #endif @@ -2243,7 +2535,7 @@ extract_manifest_args(const string &name, int num_args, int va_arg, string arg; while (c != EOF) { if (c == ',' && paren_level == 1) { - args.push_back(arg); + args.push_back(trim_blanks(arg)); arg = ""; c = get(); @@ -2302,7 +2594,7 @@ extract_manifest_args(const string &name, int num_args, int va_arg, } } if (num_args != 0 || !arg.empty()) { - args.push_back(arg); + args.push_back(trim_blanks(arg)); } } @@ -2326,23 +2618,34 @@ extract_manifest_args(const string &name, int num_args, int va_arg, * whether the manifest exists. */ void CPPPreprocessor:: -expand_defined_function(string &expr, size_t q, size_t &p) { - string result; +expand_defined_function(string &expr, size_t q, size_t &p) const { + while (p < expr.size() && isspace(expr[p])) { + p++; + } - vector_string args; - extract_manifest_args_inline("defined", 1, -1, args, expr, p); - if (args.size() >= 1) { - if (is_manifest_defined(args[0])) { - // The macro is defined; the result is "1". - result = "1"; + bool has_paren = false; + if (expr[p] == '(') { + has_paren = true; + p++; + } + + size_t r = p; + while (p < expr.size() && (isalnum(expr[p]) || expr[p] == '_')) { + p++; + } + string name = expr.substr(r, p - r); + + if (has_paren) { + if (expr[p] == ')') { + p++; } else { - // The macro is undefined; the result is "0". - result = "0"; + error("missing ')' after 'defined'"); } } + char result = is_manifest_defined(name) ? '1' : '0'; expr = expr.substr(0, q) + result + expr.substr(p); - p = q + result.size(); + p = q + 1; } /** @@ -2350,153 +2653,109 @@ expand_defined_function(string &expr, size_t q, size_t &p) { * whether the include file exists. */ void CPPPreprocessor:: -expand_has_include_function(string &expr, size_t q, size_t &p, YYLTYPE loc) { +expand_has_include_function(string &expr, size_t q, size_t &p) const { bool found_file = false; // Skip whitespace till paren. while (p < expr.size() && isspace(expr[p])) { p++; } - size_t args_begin = p + 1; - vector_string args; - extract_manifest_args_inline("__has_include", 1, -1, args, expr, p); - - if (!args.empty() && args[0].size() >= 2) { - Filename filename; - bool angle_quotes = false; - - string inc = args[0]; - - // Just to play things safe, since our manifest-expansion logic might not - // filter out quotes and angle brackets properly, we'll only expand - // manifests if we don't begin with a quote or bracket. - if (!inc.empty() && (inc[0] != '"' && inc[0] != '<')) { - inc = expand_manifests(inc, false, loc); - } - - if (inc[0] == '"' && inc[inc.size() - 1] == '"') { - filename = inc.substr(1, inc.size() - 2); - } else if (inc[0] == '<' && inc[inc.size() - 1] == '>') { - filename = inc.substr(1, inc.size() - 2); - if (!_noangles) { - // If _noangles is true, we don't make a distinction between angle - // brackets and quote marks--all #inc statements are treated the - // same, as if they used quote marks. - angle_quotes = true; - } - } else { - loc.last_column += loc.first_column + p - 2; - loc.first_column += args_begin; - warning("invalid argument for __has_include() directive", loc); - expr = expr.substr(0, q) + "0" + expr.substr(p); - p = q + 1; - return; - } - - filename.set_text(); - - CPPFile::Source source = CPPFile::S_none; - found_file = find_include(filename, angle_quotes, source); - } else { - loc.last_column += loc.first_column + p - 2; - loc.first_column += args_begin; - warning("invalid argument for __has_include() directive", loc); + if (expr[p] != '(') { + error("expected '(' after '__has_include'"); + return; } + p++; + while (p < expr.size() && isspace(expr[p])) { + p++; + } + + int paren_level = 1; + bool needs_expansion = false; + size_t r = p; + while (p < expr.size()) { + if (expr[p] == '"' || expr[p] == '\'' || expr[p] == '<') { + // Quoted string or angle bracket. + int quote_mark = expr[p]; + if (quote_mark == '<') { + quote_mark = '>'; + } + p++; + while (p < expr.size() && expr[p] != quote_mark && expr[p] != '\n') { + if (expr[p] == '\\') { + p++; + } + if (p < expr.size()) { + p++; + } + } + } + else if (expr[p] == '(') { + ++paren_level; + } + else if (expr[p] == ')') { + --paren_level; + if (paren_level == 0) { + break; + } + } + else if (isalnum(expr[p]) || expr[p] == '_') { + needs_expansion = true; + } + p++; + } + + if (p >= expr.size() || expr[p] != ')') { + error("missing ')' after '__has_include'"); + return; + } + + // Back up to strip trailing whitespace. + size_t t = p; + while (t > r && isspace(expr[t - 1])) { + --t; + } + string inc = expr.substr(r, t - r); + p++; + + // Only expand if we've encountered unquoted identifier-valid characters, + // to be on the safe side. + if (needs_expansion) { + expand_manifests(inc, false); + } + + Filename filename; + bool angle_quotes = false; + + if (!inc.empty() && inc[0] == '"' && inc[inc.size() - 1] == '"') { + filename = inc.substr(1, inc.size() - 2); + } + else if (!inc.empty() && inc[0] == '<' && inc[inc.size() - 1] == '>') { + filename = inc.substr(1, inc.size() - 2); + if (!_noangles) { + // If _noangles is true, we don't make a distinction between angle + // brackets and quote marks--all #inc statements are treated the + // same, as if they used quote marks. + angle_quotes = true; + } + } + else { + warning("invalid argument for __has_include() directive: " + inc); + expr = expr.substr(0, q) + "0" + expr.substr(p); + p = q + 1; + return; + } + + filename.set_text(); + + CPPFile::Source source = CPPFile::S_none; + found_file = find_include(filename, angle_quotes, source); string result = found_file ? "1" : "0"; expr = expr.substr(0, q) + result + expr.substr(p); p = q + result.size(); } -/** - * - */ -void CPPPreprocessor:: -expand_manifest_inline(string &expr, size_t q, size_t &p, - const CPPManifest *manifest) { - vector_string args; - if (manifest->_has_parameters) { - extract_manifest_args_inline(manifest->_name, manifest->_num_parameters, - manifest->_variadic_param, args, expr, p); - } - string result = manifest->expand(args); - - expr = expr.substr(0, q) + result + expr.substr(p); - p = q + result.size(); -} - -/** - * - */ -void CPPPreprocessor:: -extract_manifest_args_inline(const string &name, int num_args, - int va_arg, vector_string &args, - const string &expr, size_t &p) { - // Skip whitespace till paren. - while (p < expr.size() && isspace(expr[p])) { - p++; - } - if (p >= expr.size() || expr[p] != '(') { - // No paren, so we have only one arg. - size_t q = p; - while (p < expr.size() && (isalnum(expr[p]) || expr[p] == '_')) { - p++; - } - args.push_back(expr.substr(q, p - q)); - - } else if (expr[p] == '"' || expr[p] == '\'') { - // Quoted string or character. - int quote_mark = expr[p]; - p++; - while (p < expr.size() && expr[p] != quote_mark && expr[p] != '\n') { - if (expr[p] == '\\') { - p++; - } - if (p < expr.size()) { - p++; - } - } - p++; - - } else { - // Skip paren. - p++; - size_t q = p; - while (p < expr.size() && expr[p] != ')') { - if (expr[p] == ',') { - args.push_back(expr.substr(q, p - q)); - q = p+1; - - } else if (expr[p] == '(') { - // Nested parens. - int paren_level = 1; - while (p+1 < expr.size() && paren_level > 0) { - p++; - if (expr[p] == '(') { - paren_level++; - } else if (expr[p] == ')') { - paren_level--; - } - } - } - p++; - } - args.push_back(expr.substr(q, p - q)); - - if (p < expr.size() && expr[p] == ')') { - p++; - } - } - - if ((int)args.size() < num_args) { - warning("Not enough arguments for manifest " + name); - - } else if (va_arg < 0 && (int)args.size() > num_args) { - warning("Too many arguments for manifest " + name); - } -} - /** * Assuming that we've just read a digit or a period indicating the start of a * number, read the rest. @@ -2616,133 +2875,6 @@ get_number(int c) { return get_literal(INTEGER, loc, num, result); } -/** - * - */ -int CPPPreprocessor:: -check_keyword(const string &name) { - if (name == "alignas") return KW_ALIGNAS; - if (name == "alignof") return KW_ALIGNOF; - if (name == "__alignof") return KW_ALIGNOF; - if (name == "__alignof__") return KW_ALIGNOF; - if (name == "auto") return KW_AUTO; - if (name == "__begin_publish") return KW_BEGIN_PUBLISH; - if (name == "__blocking") return KW_BLOCKING; - if (name == "bool") return KW_BOOL; - if (name == "catch") return KW_CATCH; - if (name == "char") return KW_CHAR; - if (name == "char8_t") return KW_CHAR8_T; - if (name == "char16_t") return KW_CHAR16_T; - if (name == "char32_t") return KW_CHAR32_T; - if (name == "class") return KW_CLASS; - if (name == "const") return KW_CONST; - if (name == "__const") return KW_CONST; - if (name == "__const__") return KW_CONST; - if (name == "consteval") return KW_CONSTEVAL; - if (name == "constexpr") return KW_CONSTEXPR; - if (name == "constinit") return KW_CONSTINIT; - if (name == "const_cast") return KW_CONST_CAST; - if (name == "decltype") return KW_DECLTYPE; - if (name == "default") return KW_DEFAULT; - if (name == "delete") return KW_DELETE; - if (name == "double") return KW_DOUBLE; - if (name == "dynamic_cast") return KW_DYNAMIC_CAST; - if (name == "else") return KW_ELSE; - if (name == "__end_publish") return KW_END_PUBLISH; - if (name == "enum") return KW_ENUM; - if (name == "extern") return KW_EXTERN; - if (name == "__extension") return KW_EXTENSION; - if (name == "explicit") return KW_EXPLICIT; - if (name == "__published") return KW_PUBLISHED; - if (name == "false") return KW_FALSE; - if (name == "final") return KW_FINAL; - if (name == "float") return KW_FLOAT; - if (name == "friend") return KW_FRIEND; - if (name == "for") return KW_FOR; - if (name == "goto") return KW_GOTO; - if (name == "__has_virtual_destructor") return KW_HAS_VIRTUAL_DESTRUCTOR; - if (name == "if") return KW_IF; - if (name == "inline") return KW_INLINE; - if (name == "__inline") return KW_INLINE; - if (name == "__inline__") return KW_INLINE; - if (name == "int") return KW_INT; - if (name == "__is_abstract") return KW_IS_ABSTRACT; - if (name == "__is_base_of") return KW_IS_BASE_OF; - if (name == "__is_class") return KW_IS_CLASS; - if (name == "__is_constructible") return KW_IS_CONSTRUCTIBLE; - if (name == "__is_convertible_to") return KW_IS_CONVERTIBLE_TO; - if (name == "__is_destructible") return KW_IS_DESTRUCTIBLE; - if (name == "__is_empty") return KW_IS_EMPTY; - if (name == "__is_enum") return KW_IS_ENUM; - if (name == "__is_final") return KW_IS_FINAL; - if (name == "__is_fundamental") return KW_IS_FUNDAMENTAL; - if (name == "__is_pod") return KW_IS_POD; - if (name == "__is_polymorphic") return KW_IS_POLYMORPHIC; - if (name == "__is_standard_layout") return KW_IS_STANDARD_LAYOUT; - if (name == "__is_trivial") return KW_IS_TRIVIAL; - if (name == "__is_trivially_copyable") return KW_IS_TRIVIALLY_COPYABLE; - if (name == "__is_union") return KW_IS_UNION; - if (name == "long") return KW_LONG; - if (name == "__make_map_keys_seq") return KW_MAKE_MAP_KEYS_SEQ; - if (name == "__make_map_property") return KW_MAKE_MAP_PROPERTY; - if (name == "__make_property") return KW_MAKE_PROPERTY; - if (name == "__make_property2") return KW_MAKE_PROPERTY2; - if (name == "__make_seq") return KW_MAKE_SEQ; - if (name == "__make_seq_property") return KW_MAKE_SEQ_PROPERTY; - if (name == "mutable") return KW_MUTABLE; - if (name == "namespace") return KW_NAMESPACE; - if (name == "noexcept") return KW_NOEXCEPT; - if (name == "nullptr") return KW_NULLPTR; - if (name == "new") return KW_NEW; - if (name == "operator") return KW_OPERATOR; - if (name == "override") return KW_OVERRIDE; - if (name == "private") return KW_PRIVATE; - if (name == "protected") return KW_PROTECTED; - if (name == "public") return KW_PUBLIC; - if (name == "register") return KW_REGISTER; - if (name == "reinterpret_cast") return KW_REINTERPRET_CAST; - if (name == "return") return KW_RETURN; - if (name == "short") return KW_SHORT; - if (name == "signed") return KW_SIGNED; - if (name == "sizeof") return KW_SIZEOF; - if (name == "static") return KW_STATIC; - if (name == "static_assert") return KW_STATIC_ASSERT; - if (name == "static_cast") return KW_STATIC_CAST; - if (name == "struct") return KW_STRUCT; - if (name == "template") return KW_TEMPLATE; - if (name == "thread_local") return KW_THREAD_LOCAL; - if (name == "throw") return KW_THROW; - if (name == "true") return KW_TRUE; - if (name == "try") return KW_TRY; - if (name == "typedef") return KW_TYPEDEF; - if (name == "typeid") return KW_TYPEID; - if (name == "typename") return KW_TYPENAME; - if (name == "__underlying_type") return KW_UNDERLYING_TYPE; - if (name == "union") return KW_UNION; - if (name == "unsigned") return KW_UNSIGNED; - if (name == "using") return KW_USING; - if (name == "virtual") return KW_VIRTUAL; - if (name == "void") return KW_VOID; - if (name == "volatile") return KW_VOLATILE; - if (name == "wchar_t") return KW_WCHAR_T; - if (name == "while") return KW_WHILE; - - // These are alternative ways to refer to built-in operators. - if (name == "and") return ANDAND; - if (name == "and_eq") return ANDEQUAL; - if (name == "bitand") return '&'; - if (name == "bitor") return '|'; - if (name == "compl") return '~'; - if (name == "not") return '!'; - if (name == "not_eq") return NECOMPARE; - if (name == "or") return OROR; - if (name == "or_eq") return OREQUAL; - if (name == "xor") return '^'; - if (name == "xor_eq") return XOREQUAL; - - return 0; -} - /** * */ @@ -2886,11 +3018,12 @@ scan_raw(int c) { */ bool CPPPreprocessor:: should_ignore_manifest(const CPPManifest *manifest) const { - Files::const_iterator fi; - for (fi = _files.begin(); fi != _files.end(); ++fi) { - if ((*fi)._ignore_manifest == manifest) { + InputFile *infile = _infile; + while (infile != nullptr) { + if (infile->_ignore_manifest && infile->_manifest == manifest) { return true; } + infile = infile->_parent; } return false; @@ -2902,11 +3035,12 @@ should_ignore_manifest(const CPPManifest *manifest) const { */ bool CPPPreprocessor:: should_ignore_preprocessor() const { - Files::const_iterator fi; - for (fi = _files.begin(); fi != _files.end(); ++fi) { - if ((*fi)._ignore_manifest != nullptr) { + InputFile *infile = _infile; + while (infile != nullptr) { + if (infile->_ignore_manifest) { return true; } + infile = infile->_parent; } return false; @@ -2923,18 +3057,21 @@ get() { return c; } - if (_files.empty()) { + if (UNLIKELY(_infile == nullptr)) { return EOF; } - int c = _files.back().get(); + int c = _infile->get(); - while (c == EOF && !_files.empty()) { + while (UNLIKELY(c == EOF && _infile != nullptr)) { #ifdef CPP_VERBOSE_LEX - indent(cerr, _files.size() * 2) + indent(cerr, get_file_depth() * 2) << "End of input stream, restoring to previous input\n"; #endif - _files.pop_back(); + // Pop the last file off the end. + InputFile *infile = _infile; + _infile = infile->_parent; + delete infile; // Synthesize a newline, just in case the file doesn't already end with // one. @@ -2959,21 +3096,21 @@ peek() { return _unget; } - if (_files.empty()) { + InputFile *infile = _infile; + if (UNLIKELY(infile == nullptr)) { return EOF; } - Files::reverse_iterator it = _files.rbegin(); - int c = (*it).peek(); + int c = infile->peek(); - while (c == EOF && it != _files.rend()) { - int last_c = (*it)._prev_last_c; - ++it; + while (UNLIKELY(c == EOF && infile != nullptr)) { + int last_c = infile->_prev_last_c; + infile = infile->_parent; if (last_c != '\0') { c = last_c; - } else if (it != _files.rend()) { - c = (*it).peek(); + } else if (infile != nullptr) { + c = infile->peek(); } } @@ -2999,7 +3136,7 @@ unget(int c) { CPPTemplateParameterList *CPPPreprocessor:: nested_parse_template_instantiation(CPPTemplateScope *scope) { #ifdef CPP_VERBOSE_LEX - indent(cerr, _files.size() * 2) + indent(cerr, get_file_depth() * 2) << "Beginning nested parse\n"; #endif assert(scope != nullptr); @@ -3088,7 +3225,7 @@ nested_parse_template_instantiation(CPPTemplateScope *scope) { _parsing_template_params = old_parsing_params; #ifdef CPP_VERBOSE_LEX - indent(cerr, _files.size() * 2) + indent(cerr, get_file_depth() * 2) << "Ending nested parse\n"; #endif return actual_params; @@ -3104,7 +3241,7 @@ nested_parse_template_instantiation(CPPTemplateScope *scope) { void CPPPreprocessor:: skip_to_end_nested() { #ifdef CPP_VERBOSE_LEX - indent(cerr, _files.size() * 2) + indent(cerr, get_file_depth() * 2) << "Skipping tokens:\n"; #endif @@ -3118,7 +3255,7 @@ skip_to_end_nested() { } #ifdef CPP_VERBOSE_LEX - indent(cerr, _files.size() * 2) + indent(cerr, get_file_depth() * 2) << "Done skipping tokens.\n"; #endif } @@ -3131,7 +3268,7 @@ skip_to_end_nested() { void CPPPreprocessor:: skip_to_angle_bracket() { #ifdef CPP_VERBOSE_LEX - indent(cerr, _files.size() * 2) + indent(cerr, get_file_depth() * 2) << "Skipping tokens:\n"; #endif @@ -3148,7 +3285,21 @@ skip_to_angle_bracket() { } #ifdef CPP_VERBOSE_LEX - indent(cerr, _files.size() * 2) + indent(cerr, get_file_depth() * 2) << "Done skipping tokens.\n"; #endif } + +/** + * Returns the number of files on the _infile list. + */ +int CPPPreprocessor:: +get_file_depth() const{ + int depth = 0; + InputFile *infile = _infile; + while (infile != nullptr) { + ++depth; + infile = infile->_parent; + } + return depth; +} diff --git a/dtool/src/cppparser/cppPreprocessor.h b/dtool/src/cppparser/cppPreprocessor.h index 92986cf4c8..a241fc617d 100644 --- a/dtool/src/cppparser/cppPreprocessor.h +++ b/dtool/src/cppparser/cppPreprocessor.h @@ -25,8 +25,8 @@ #include "vector_string.h" #include -#include #include +#include class CPPScope; class CPPTemplateParameterList; @@ -41,6 +41,8 @@ class CPPPreprocessor { public: CPPPreprocessor(); + bool preprocess_file(const Filename &filename); + void set_verbose(int verbose); int get_verbose() const; @@ -57,11 +59,11 @@ public: int _token_index; #endif - void warning(const std::string &message); - void warning(const std::string &message, const YYLTYPE &loc); - void error(const std::string &message); - void error(const std::string &message, const YYLTYPE &loc); - void show_line(const YYLTYPE &loc); + void warning(const std::string &message) const; + void warning(const std::string &message, const YYLTYPE &loc) const; + void error(const std::string &message) const; + void error(const std::string &message, const YYLTYPE &loc) const; + void show_line(const YYLTYPE &loc) const; CPPCommentBlock *get_comment_before(int line, CPPFile file); CPPCommentBlock *get_comment_on(int line, CPPFile file); @@ -69,7 +71,7 @@ public: int get_warning_count() const; int get_error_count() const; - typedef std::map Manifests; + typedef std::unordered_map Manifests; Manifests _manifests; typedef std::vector ManifestStack; @@ -112,10 +114,13 @@ protected: bool init_const_expr(const std::string &expr); bool init_type(const std::string &type); bool push_file(const CPPFile &file); - bool push_string(const std::string &input, bool lock_position); + bool push_string(const std::string &input); + bool push_expansion(const std::string &input, const CPPManifest *manifest, + const YYLTYPE &loc); - std::string expand_manifests(const std::string &input_expr, bool expand_undefined, - const YYLTYPE &loc); +public: + void expand_manifests(std::string &expr, bool expand_undefined = false, + const CPPManifest::Ignores &ignores = CPPManifest::Ignores()) const; CPPExpression *parse_expr(const std::string &expr, CPPScope *current_scope, CPPScope *global_scope, const YYLTYPE &loc); @@ -143,27 +148,23 @@ private: void handle_error_directive(const std::string &args, const YYLTYPE &loc); void skip_false_if_block(bool consider_elifs); - bool is_manifest_defined(const std::string &manifest_name); - bool find_include(Filename &filename, bool angle_quotes, CPPFile::Source &source); + bool is_manifest_defined(const std::string &manifest_name) const; + bool find_include(Filename &filename, bool angle_quotes, CPPFile::Source &source) const; CPPToken get_quoted_char(int c); CPPToken get_quoted_string(int c); CPPToken get_identifier(int c); CPPToken get_literal(int token, YYLTYPE loc, const std::string &str, const YYSTYPE &result = YYSTYPE()); - CPPToken expand_manifest(const CPPManifest *manifest); + CPPToken expand_manifest(const CPPManifest *manifest, const YYLTYPE &loc); + void r_expand_manifests(std::string &expr, bool expand_undefined, + const YYLTYPE &loc, std::set &expanded); void extract_manifest_args(const std::string &name, int num_args, int va_arg, vector_string &args); - void expand_defined_function(std::string &expr, size_t q, size_t &p); - void expand_has_include_function(std::string &expr, size_t q, size_t &p, YYLTYPE loc); - void expand_manifest_inline(std::string &expr, size_t q, size_t &p, - const CPPManifest *manifest); - void extract_manifest_args_inline(const std::string &name, int num_args, - int va_arg, vector_string &args, - const std::string &expr, size_t &p); + void expand_defined_function(std::string &expr, size_t q, size_t &p) const; + void expand_has_include_function(std::string &expr, size_t q, size_t &p) const; CPPToken get_number(int c); - static int check_keyword(const std::string &name); int scan_escape_sequence(int c); std::string scan_quoted(int c); std::string scan_raw(int c); @@ -180,6 +181,8 @@ private: void skip_to_end_nested(); void skip_to_angle_bracket(); + int get_file_depth() const; + class InputFile { public: InputFile(); @@ -190,7 +193,7 @@ private: int get(); int peek(); - const CPPManifest *_ignore_manifest; + const CPPManifest *_manifest; CPPFile _file; std::string _input; std::istream *_in; @@ -199,13 +202,13 @@ private: int _next_line_number; int _next_col_number; bool _lock_position; + bool _ignore_manifest; int _prev_last_c; + + InputFile *_parent = nullptr; }; - // This must be a list and not a vector because we don't have a good copy - // constructor defined for InputFile. - typedef std::list Files; - Files _files; + InputFile *_infile = nullptr; enum State { S_normal, S_eof, S_nested, S_end_nested @@ -224,8 +227,8 @@ private: std::vector _saved_tokens; - int _warning_count; - int _error_count; + mutable int _warning_count; + mutable int _error_count; bool _error_abort; }; diff --git a/dtool/src/cppparser/cppScope.cxx b/dtool/src/cppparser/cppScope.cxx index af6404e4dd..a88961d4b7 100644 --- a/dtool/src/cppparser/cppScope.cxx +++ b/dtool/src/cppparser/cppScope.cxx @@ -164,8 +164,10 @@ define_typedef_type(CPPTypedefType *type, CPPPreprocessor *error_sink) { errstr << " has conflicting declaration as "; other_type->output(errstr, 0, nullptr, true); error_sink->error(errstr.str(), type->_ident->_loc); - error_sink->error("previous definition is here", - other_td->_ident->_loc); + if (other_td != nullptr && other_td->_ident != nullptr) { + error_sink->error("previous definition is here", + other_td->_ident->_loc); + } } } } else { @@ -722,6 +724,12 @@ find_symbol(const string &name, bool recurse) const { return _struct_type; } + Functions::const_iterator fi; + fi = _functions.find(name); + if (fi != _functions.end()) { + return (*fi).second; + } + Types::const_iterator ti; ti = _types.find(name); if (ti != _types.end()) { @@ -739,12 +747,6 @@ find_symbol(const string &name, bool recurse) const { return (*vi).second; } - Functions::const_iterator fi; - fi = _functions.find(name); - if (fi != _functions.end()) { - return (*fi).second; - } - Using::const_iterator ui; for (ui = _using.begin(); ui != _using.end(); ++ui) { CPPDeclaration *decl = (*ui)->find_symbol(name, false); diff --git a/dtool/src/cppparser/cppSimpleType.cxx b/dtool/src/cppparser/cppSimpleType.cxx index 621496bac2..990a7cbaea 100644 --- a/dtool/src/cppparser/cppSimpleType.cxx +++ b/dtool/src/cppparser/cppSimpleType.cxx @@ -47,7 +47,7 @@ is_arithmetic() const { */ bool CPPSimpleType:: is_fundamental() const { - return (_type != T_unknown && _type != T_parameter && _type != T_auto); + return (_type != T_unknown && _type != T_parameter && _type != T_auto && _type != T_va_list); } /** @@ -55,7 +55,7 @@ is_fundamental() const { */ bool CPPSimpleType:: is_standard_layout() const { - return (_type != T_unknown && _type != T_parameter && _type != T_auto); + return (_type != T_unknown && _type != T_parameter && _type != T_auto && _type != T_va_list); } /** @@ -63,7 +63,7 @@ is_standard_layout() const { */ bool CPPSimpleType:: is_trivial() const { - return (_type != T_unknown && _type != T_parameter && _type != T_auto); + return (_type != T_unknown && _type != T_parameter && _type != T_auto && _type != T_va_list); } /** @@ -71,7 +71,7 @@ is_trivial() const { */ bool CPPSimpleType:: is_trivially_copyable() const { - return (_type != T_unknown && _type != T_parameter && _type != T_auto); + return (_type != T_unknown && _type != T_parameter && _type != T_auto && _type != T_va_list); } /** @@ -233,6 +233,10 @@ output(std::ostream &out, int, CPPScope *, bool) const { out << "auto"; break; + case T_va_list: + out << "__builtin_va_list"; + break; + default: out << "***invalid type***"; } diff --git a/dtool/src/cppparser/cppSimpleType.h b/dtool/src/cppparser/cppSimpleType.h index 001d9eb608..70eb615588 100644 --- a/dtool/src/cppparser/cppSimpleType.h +++ b/dtool/src/cppparser/cppSimpleType.h @@ -53,6 +53,9 @@ public: // determined at a later stage based on the type of the expression that is // assigned to it. T_auto, + + // This is also a special built-in type. + T_va_list, }; enum Flags { diff --git a/dtool/src/cppparser/cppToken.cxx b/dtool/src/cppparser/cppToken.cxx index 5649d4a612..daa624f17f 100644 --- a/dtool/src/cppparser/cppToken.cxx +++ b/dtool/src/cppparser/cppToken.cxx @@ -15,6 +15,7 @@ #include "cppExpression.h" #include "cppIdentifier.h" #include "cppBison.h" +#include "pdtoa.h" #include @@ -45,29 +46,6 @@ CPPToken(int token, const YYLTYPE &loc, const std::string &str, const YYSTYPE &v _lval.str = str; } -/** - * - */ -CPPToken:: -CPPToken(const CPPToken ©) : - _token(copy._token), - _lloc(copy._lloc) -{ - _lval.str = copy._lval.str; - _lval.u = copy._lval.u; -} - -/** - * - */ -void CPPToken:: -operator = (const CPPToken ©) { - _token = copy._token; - _lval.str = copy._lval.str; - _lval.u = copy._lval.u; - _lloc = copy._lloc; -} - /** * A named constructor for the token returned when the end of file has been * reached. @@ -85,7 +63,6 @@ is_eof() const { return _token == 0; } - /** * */ @@ -244,6 +221,10 @@ output(std::ostream &out) const { out << "ANDEQUAL"; break; + case XOREQUAL: + out << "XOREQUAL"; + break; + case LSHIFTEQUAL: out << "LSHIFTEQUAL"; break; @@ -260,10 +241,34 @@ output(std::ostream &out) const { out << "ATTR_RIGHT"; break; + case KW_ALIGNAS: + out << "KW_ALIGNAS"; + break; + + case KW_ALIGNOF: + out << "KW_ALIGNOF"; + break; + + case KW_AUTO: + out << "KW_AUTO"; + break; + + case KW_BEGIN_PUBLISH: + out << "KW_BEGIN_PUBLISH"; + break; + + case KW_BLOCKING: + out << "KW_BLOCKING"; + break; + case KW_BOOL: out << "KW_BOOL"; break; + case KW_BUILTIN_VA_LIST: + out << "KW_BUILTIN_VA_LIST"; + break; + case KW_CATCH: out << "KW_CATCH"; break; @@ -272,6 +277,18 @@ output(std::ostream &out) const { out << "KW_CHAR"; break; + case KW_CHAR8_T: + out << "KW_CHAR8_T"; + break; + + case KW_CHAR16_T: + out << "KW_CHAR16_T"; + break; + + case KW_CHAR32_T: + out << "KW_CHAR32_T"; + break; + case KW_CLASS: out << "KW_CLASS"; break; @@ -280,6 +297,26 @@ output(std::ostream &out) const { out << "KW_CONST"; break; + case KW_CONSTEVAL: + out << "KW_CONSTEVAL"; + break; + + case KW_CONSTEXPR: + out << "KW_CONSTEXPR"; + break; + + case KW_CONSTINIT: + out << "KW_CONSTINIT"; + break; + + case KW_DECLTYPE: + out << "KW_DECLTYPE"; + break; + + case KW_DEFAULT: + out << "KW_DECLTYPE"; + break; + case KW_DELETE: out << "KW_DELETE"; break; @@ -304,6 +341,14 @@ output(std::ostream &out) const { out << "KW_EXPLICIT"; break; + case KW_EXPLICIT_LPAREN: + out << "KW_EXPLICIT_LPAREN"; + break; + + case KW_EXTENSION: + out << "KW_EXTENSION"; + break; + case KW_EXTERN: out << "KW_EXTERN"; break; @@ -312,6 +357,10 @@ output(std::ostream &out) const { out << "KW_FALSE"; break; + case KW_FINAL: + out << "KW_FINAL"; + break; + case KW_FLOAT: out << "KW_FLOAT"; break; @@ -328,6 +377,10 @@ output(std::ostream &out) const { out << "KW_GOTO"; break; + case KW_HAS_VIRTUAL_DESTRUCTOR: + out << "KW_HAS_VIRTUAL_DESTRUCTOR"; + break; + case KW_IF: out << "KW_IF"; break; @@ -340,10 +393,98 @@ output(std::ostream &out) const { out << "KW_INT"; break; + case KW_IS_ABSTRACT: + out << "KW_IS_ABSTRACT"; + break; + + case KW_IS_BASE_OF: + out << "KW_IS_BASE_OF"; + break; + + case KW_IS_CLASS: + out << "KW_IS_CLASS"; + break; + + case KW_IS_CONSTRUCTIBLE: + out << "KW_IS_CONSTRUCTIBLE"; + break; + + case KW_IS_CONVERTIBLE_TO: + out << "KW_IS_CONVERTIBLE_TO"; + break; + + case KW_IS_DESTRUCTIBLE: + out << "KW_IS_DESTRUCTIBLE"; + break; + + case KW_IS_EMPTY: + out << "KW_IS_EMPTY"; + break; + + case KW_IS_ENUM: + out << "KW_IS_ENUM"; + break; + + case KW_IS_FINAL: + out << "KW_IS_FINAL"; + break; + + case KW_IS_FUNDAMENTAL: + out << "KW_IS_FUNDAMENTAL"; + break; + + case KW_IS_POD: + out << "KW_IS_POD"; + break; + + case KW_IS_POLYMORPHIC: + out << "KW_IS_POLYMORPHIC"; + break; + + case KW_IS_STANDARD_LAYOUT: + out << "KW_IS_STANDARD_LAYOUT"; + break; + + case KW_IS_TRIVIAL: + out << "KW_IS_TRIVIAL"; + break; + + case KW_IS_TRIVIALLY_COPYABLE: + out << "KW_IS_TRIVIALLY_COPYABLE"; + break; + + case KW_IS_UNION: + out << "KW_IS_UNION"; + break; + case KW_LONG: out << "KW_LONG"; break; + case KW_MAKE_MAP_KEYS_SEQ: + out << "KW_MAKE_MAP_KEYS_SEQ"; + break; + + case KW_MAKE_MAP_PROPERTY: + out << "KW_MAKE_MAP_PROPERTY"; + break; + + case KW_MAKE_PROPERTY: + out << "KW_MAKE_PROPERTY"; + break; + + case KW_MAKE_PROPERTY2: + out << "KW_MAKE_PROPERTY2"; + break; + + case KW_MAKE_SEQ: + out << "KW_MAKE_SEQ"; + break; + + case KW_MAKE_SEQ_PROPERTY: + out << "KW_MAKE_SEQ_PROPERTY"; + break; + case KW_MUTABLE: out << "KW_MUTABLE"; break; @@ -356,6 +497,18 @@ output(std::ostream &out) const { out << "KW_NEW"; break; + case KW_NOEXCEPT: + out << "KW_NOEXCEPT"; + break; + + case KW_NOEXCEPT_LPAREN: + out << "KW_NOEXCEPT_LPAREN"; + break; + + case KW_NULLPTR: + out << "KW_NULLPTR"; + break; + case KW_OPERATOR: if (_lval.u.identifier != nullptr) { out << *_lval.u.identifier << "::"; @@ -363,6 +516,10 @@ output(std::ostream &out) const { out << "KW_OPERATOR"; break; + case KW_OVERRIDE: + out << "KW_OVERRIDE"; + break; + case KW_PRIVATE: out << "KW_PRIVATE"; break; @@ -375,10 +532,22 @@ output(std::ostream &out) const { out << "KW_PUBLIC"; break; + case KW_PUBLISHED: + out << "KW_PUBLISHED"; + break; + case KW_REGISTER: out << "KW_REGISTER"; break; + case KW_REINTERPRET_CAST: + out << "KW_REINTERPRET_CAST"; + break; + + case KW_RESTRICT: + out << "KW_RESTRICT"; + break; + case KW_RETURN: out << "KW_RETURN"; break; @@ -399,6 +568,10 @@ output(std::ostream &out) const { out << "KW_STATIC"; break; + case KW_STATIC_ASSERT: + out << "KW_STATIC_ASSERT"; + break; + case KW_STATIC_CAST: out << "KW_STATIC_CAST"; break; @@ -411,6 +584,10 @@ output(std::ostream &out) const { out << "KW_TEMPLATE"; break; + case KW_THREAD_LOCAL: + out << "KW_THREAD_LOCAL"; + break; + case KW_THROW: out << "KW_THROW"; break; @@ -427,10 +604,18 @@ output(std::ostream &out) const { out << "KW_TYPEDEF"; break; + case KW_TYPEID: + out << "KW_TYPEID"; + break; + case KW_TYPENAME: out << "KW_TYPENAME"; break; + case KW_UNDERLYING_TYPE: + out << "KW_UNDERLYING_TYPE"; + break; + case KW_USING: out << "KW_USING"; break; @@ -455,6 +640,10 @@ output(std::ostream &out) const { out << "KW_VOLATILE"; break; + case KW_WCHAR_T: + out << "KW_WCHAR_T"; + break; + case KW_WHILE: out << "KW_WHILE"; break; @@ -479,3 +668,660 @@ output(std::ostream &out) const { } } } + +/** + * + */ +void CPPToken:: +output_code(std::ostream &out) const { + switch (_token) { + case REAL: + { + char buffer[128]; + pdtoa(_lval.u.real, buffer); + out << buffer; + } + break; + + case INTEGER: + out << _lval.u.integer; + break; + + case CHAR_TOK: + case SIMPLE_STRING: + out << (_token == CHAR_TOK ? '\'' : '"'); + for (char c : _lval.str) { + switch (c) { + case '\n': + out << "\\n"; + break; + + case '\t': + out << "\\t"; + break; + + case '\r': + out << "\\r"; + break; + + case '\a': + out << "\\a"; + break; + + case '\b': + out << "\\b"; + break; + + case '\v': + out << "\\v"; + break; + + case '\f': + out << "\\f"; + break; + + case '\'': + out << (_token == CHAR_TOK ? "\\\'" : "'"); + break; + + case '"': + out << (_token == CHAR_TOK ? "\"" : "\\\""); + break; + + case '\\': + out << "\\\\"; + break; + + default: + if (isprint(c)) { + out << c; + } else { + out << '\\' << std::oct << std::setw(3) << std::setfill('0') << (int)(c) + << std::dec << std::setw(0); + } + break; + } + } + out << (_token == CHAR_TOK ? '\'' : '"'); + break; + + case STRING_LITERAL: + out << *_lval.u.expr; + break; + + case SIMPLE_IDENTIFIER: + out << _lval.str; + break; + + case IDENTIFIER: + out << *_lval.u.identifier; + break; + + case TYPENAME_IDENTIFIER: + out << *_lval.u.identifier; + break; + + case SCOPING: + out << *_lval.u.identifier << "::"; + break; + + case TYPEDEFNAME: + out << _lval.str; + break; + + case ELLIPSIS: + out << "..."; + break; + + case OROR: + out << "||"; + break; + + case ANDAND: + out << "&&"; + break; + + case EQCOMPARE: + out << "=="; + break; + + case NECOMPARE: + out << "!="; + break; + + case LECOMPARE: + out << "<="; + break; + + case GECOMPARE: + out << ">="; + break; + + case LSHIFT: + out << "<<"; + break; + + case RSHIFT: + out << ">>"; + break; + + case POINTSAT_STAR: + out << "->*"; + break; + + case DOT_STAR: + out << ".*"; + break; + + case UNARY_NOT: + out << "!"; + break; + + case UNARY_MINUS: + out << "-"; + break; + + case UNARY_PLUS: + out << "+"; + break; + + case UNARY_NEGATE: + out << "~"; + break; + + case UNARY_STAR: + out << "*"; + break; + + case UNARY_REF: + out << "&"; + break; + + case POINTSAT: + out << "->"; + break; + + case SCOPE: + out << "::"; + break; + + case PLUSPLUS: + out << "++"; + break; + + case MINUSMINUS: + out << "--"; + break; + + case TIMESEQUAL: + out << "*="; + break; + + case DIVIDEEQUAL: + out << "/="; + break; + + case MODEQUAL: + out << "%="; + break; + + case PLUSEQUAL: + out << "+="; + break; + + case MINUSEQUAL: + out << "-="; + break; + + case OREQUAL: + out << "|="; + break; + + case ANDEQUAL: + out << "&="; + break; + + case XOREQUAL: + out << "^="; + break; + + case LSHIFTEQUAL: + out << "<<="; + break; + + case RSHIFTEQUAL: + out << ">>="; + break; + + case ATTR_LEFT: + out << "[["; + break; + + case ATTR_RIGHT: + out << "]]"; + break; + + case KW_ALIGNAS: + out << "alignas"; + break; + + case KW_ALIGNOF: + out << "alignof"; + break; + + case KW_AUTO: + out << "auto"; + break; + + case KW_BEGIN_PUBLISH: + out << "__begin_publish"; + break; + + case KW_BLOCKING: + out << "__blocking"; + break; + + case KW_BOOL: + out << "bool"; + break; + + case KW_BUILTIN_VA_LIST: + out << "__builtin_va_list"; + break; + + case KW_CATCH: + out << "catch"; + break; + + case KW_CHAR: + out << "char"; + break; + + case KW_CHAR8_T: + out << "char8_t"; + break; + + case KW_CHAR16_T: + out << "char16_t"; + break; + + case KW_CHAR32_T: + out << "char32_t"; + break; + + case KW_CLASS: + out << "class"; + break; + + case KW_CONST: + out << "const"; + break; + + case KW_CONSTEVAL: + out << "consteval"; + break; + + case KW_CONSTEXPR: + out << "constexpr"; + break; + + case KW_CONSTINIT: + out << "constinit"; + break; + + case KW_CONST_CAST: + out << "const_cast"; + break; + + case KW_DECLTYPE: + out << "decltype"; + break; + + case KW_DEFAULT: + out << "default"; + break; + + case KW_DELETE: + out << "delete"; + break; + + case KW_DOUBLE: + out << "double"; + break; + + case KW_DYNAMIC_CAST: + out << "dynamic_cast"; + break; + + case KW_ELSE: + out << "else"; + break; + + case KW_ENUM: + out << "enum"; + break; + + case KW_EXPLICIT: + out << "explicit"; + break; + + case KW_EXPLICIT_LPAREN: + out << "explicit("; + break; + + case KW_EXTENSION: + out << "__extension"; + break; + + case KW_EXTERN: + out << "extern"; + break; + + case KW_FALSE: + out << "false"; + break; + + case KW_FINAL: + out << "final"; + break; + + case KW_FLOAT: + out << "float"; + break; + + case KW_FRIEND: + out << "friend"; + break; + + case KW_FOR: + out << "for"; + break; + + case KW_GOTO: + out << "goto"; + break; + + case KW_HAS_VIRTUAL_DESTRUCTOR: + out << "__has_virtual_destructor"; + break; + + case KW_IF: + out << "if"; + break; + + case KW_INLINE: + out << "inline"; + break; + + case KW_INT: + out << "int"; + break; + + case KW_IS_ABSTRACT: + out << "__is_abstract"; + break; + + case KW_IS_BASE_OF: + out << "__is_base_of"; + break; + + case KW_IS_CLASS: + out << "__is_class"; + break; + + case KW_IS_CONSTRUCTIBLE: + out << "__is_constructible"; + break; + + case KW_IS_CONVERTIBLE_TO: + out << "__is_convertible_to"; + break; + + case KW_IS_DESTRUCTIBLE: + out << "__is_destructible"; + break; + + case KW_IS_EMPTY: + out << "__is_empty"; + break; + + case KW_IS_ENUM: + out << "__is_enum"; + break; + + case KW_IS_FINAL: + out << "__is_final"; + break; + + case KW_IS_FUNDAMENTAL: + out << "__is_fundamental"; + break; + + case KW_IS_POD: + out << "__is_pod"; + break; + + case KW_IS_POLYMORPHIC: + out << "__is_polymorphic"; + break; + + case KW_IS_STANDARD_LAYOUT: + out << "__is_standard_layout"; + break; + + case KW_IS_TRIVIAL: + out << "__is_trivial"; + break; + + case KW_IS_TRIVIALLY_COPYABLE: + out << "__is_trivially_copyable"; + break; + + case KW_IS_UNION: + out << "__is_union"; + break; + + case KW_LONG: + out << "long"; + break; + + case KW_MAKE_MAP_KEYS_SEQ: + out << "__make_map_keys_seq"; + break; + + case KW_MAKE_MAP_PROPERTY: + out << "__make_map_property"; + break; + + case KW_MAKE_PROPERTY: + out << "__make_property"; + break; + + case KW_MAKE_PROPERTY2: + out << "__make_property2"; + break; + + case KW_MAKE_SEQ: + out << "__make_seq"; + break; + + case KW_MAKE_SEQ_PROPERTY: + out << "__make_seq_property"; + break; + + case KW_MUTABLE: + out << "mutable"; + break; + + case KW_NAMESPACE: + out << "namespace"; + break; + + case KW_NEW: + out << "new"; + break; + + case KW_NOEXCEPT: + out << "noexcept"; + break; + + case KW_NOEXCEPT_LPAREN: + out << "noexcept("; + break; + + case KW_NULLPTR: + out << "nullptr"; + break; + + case KW_OPERATOR: + if (_lval.u.identifier != nullptr) { + out << *_lval.u.identifier << "::"; + } + out << "operator"; + break; + + case KW_OVERRIDE: + out << "override"; + break; + + case KW_PRIVATE: + out << "private"; + break; + + case KW_PROTECTED: + out << "protected"; + break; + + case KW_PUBLIC: + out << "public"; + break; + + case KW_PUBLISHED: + out << "__published"; + break; + + case KW_REGISTER: + out << "register"; + break; + + case KW_REINTERPRET_CAST: + out << "reinterpret_cast"; + break; + + case KW_RESTRICT: + out << "__restrict"; + break; + + case KW_RETURN: + out << "return"; + break; + + case KW_SHORT: + out << "short"; + break; + + case KW_SIGNED: + out << "signed"; + break; + + case KW_SIZEOF: + out << "sizeof"; + break; + + case KW_STATIC: + out << "static"; + break; + + case KW_STATIC_ASSERT: + out << "static_assert"; + break; + + case KW_STATIC_CAST: + out << "static_cast"; + break; + + case KW_STRUCT: + out << "struct"; + break; + + case KW_TEMPLATE: + out << "template"; + break; + + case KW_THREAD_LOCAL: + out << "thread_local"; + break; + + case KW_THROW: + out << "throw"; + break; + + case KW_TRUE: + out << "true"; + break; + + case KW_TRY: + out << "try"; + break; + + case KW_TYPEDEF: + out << "typedef"; + break; + + case KW_TYPEID: + out << "typeid"; + break; + + case KW_TYPENAME: + out << "typename"; + break; + + case KW_UNDERLYING_TYPE: + out << "__underlying_type"; + break; + + case KW_USING: + out << "using"; + break; + + case KW_UNION: + out << "union"; + break; + + case KW_UNSIGNED: + out << "unsigned"; + break; + + case KW_VIRTUAL: + out << "virtual"; + break; + + case KW_VOID: + out << "void"; + break; + + case KW_VOLATILE: + out << "volatile"; + break; + + case KW_WCHAR_T: + out << "wchar_t"; + break; + + case KW_WHILE: + out << "while"; + break; + + case START_CPP: + case START_CONST_EXPR: + case START_TYPE: + break; + + default: + if (_token < 128 && isprint(_token)) { + out << (char)_token; + } else { + out << "\n"; + } + } +} diff --git a/dtool/src/cppparser/cppToken.h b/dtool/src/cppparser/cppToken.h index 735ef0aac2..89ced98800 100644 --- a/dtool/src/cppparser/cppToken.h +++ b/dtool/src/cppparser/cppToken.h @@ -30,13 +30,12 @@ public: CPPToken(int token, const YYLTYPE &loc, const std::string &str = std::string(), const YYSTYPE &lval = YYSTYPE()); - CPPToken(const CPPToken ©); - void operator = (const CPPToken ©); static CPPToken eof(); bool is_eof() const; void output(std::ostream &out) const; + void output_code(std::ostream &out) const; int _token; YYSTYPE _lval; diff --git a/dtool/src/dtoolbase/dtool_platform.h b/dtool/src/dtoolbase/dtool_platform.h index ad2f85767f..dbfcb26556 100644 --- a/dtool/src/dtoolbase/dtool_platform.h +++ b/dtool/src/dtoolbase/dtool_platform.h @@ -65,6 +65,25 @@ #define DTOOL_PLATFORM "android_i386" #endif +#elif defined(__EMSCRIPTEN__) +#if defined(__wasm64__) +#define DTOOL_PLATFORM "emscripten_wasm64" +#elif defined(__wasm32__) +#define DTOOL_PLATFORM "emscripten_wasm32" +#else +#define DTOOL_PLATFORM "emscripten" +#endif + +#elif defined(__wasm32__) +#define DTOOL_PLATFORM "wasi_wasm32" + +#elif defined(__wasm64__) +#define DTOOL_PLATFORM "wasi_wasm64" + +// fallback to wasm32 with older sdk +#elif defined(__wasi__) +#define DTOOL_PLATFORM "wasi_wasm32" + #elif defined(__aarch64__) #define DTOOL_PLATFORM "linux_aarch64" diff --git a/dtool/src/dtoolbase/memoryHook.I b/dtool/src/dtoolbase/memoryHook.I index 2b63050656..724b44ca64 100644 --- a/dtool/src/dtoolbase/memoryHook.I +++ b/dtool/src/dtoolbase/memoryHook.I @@ -40,9 +40,11 @@ dec_heap(size_t size) { */ INLINE size_t MemoryHook:: get_page_size() const { +#ifndef __EMSCRIPTEN__ if (_page_size == 0) { determine_page_size(); } +#endif return _page_size; } @@ -52,10 +54,12 @@ get_page_size() const { */ INLINE size_t MemoryHook:: round_up_to_page_size(size_t size) const { +#ifndef __EMSCRIPTEN__ if (_page_size == 0) { determine_page_size(); } - return ((size + _page_size - 1) / _page_size) * _page_size; +#endif + return ((size + _page_size - 1) / _page_size) * _page_size; } /** diff --git a/dtool/src/dtoolbase/memoryHook.cxx b/dtool/src/dtoolbase/memoryHook.cxx index cd6370d9d3..37b36d8633 100644 --- a/dtool/src/dtoolbase/memoryHook.cxx +++ b/dtool/src/dtoolbase/memoryHook.cxx @@ -207,8 +207,12 @@ MemoryHook(const MemoryHook ©) : _total_heap_array_size(copy._total_heap_array_size.load(std::memory_order_relaxed)), _requested_heap_size(copy._requested_heap_size.load(std::memory_order_relaxed)), _total_mmap_size(copy._total_mmap_size.load(std::memory_order_relaxed)), - _max_heap_size(copy._max_heap_size), - _page_size(copy._page_size) { + _max_heap_size(copy._max_heap_size) +#ifndef __EMSCRIPTEN__ + , + _page_size(copy._page_size) +#endif +{ } @@ -483,9 +487,11 @@ heap_trim(size_t pad) { */ void *MemoryHook:: mmap_alloc(size_t size, bool allow_exec) { +#ifndef __EMSCRIPTEN__ if (_page_size == 0) { determine_page_size(); } +#endif assert((size % _page_size) == 0); #ifdef DO_MEMORY_USAGE @@ -602,6 +608,7 @@ overflow_heap_size() { /** * Asks the operating system for the page size. */ +#ifndef __EMSCRIPTEN__ void MemoryHook:: determine_page_size() const { #ifdef _WIN32 @@ -619,3 +626,4 @@ determine_page_size() const { assert(_page_size != 0); } +#endif // !__EMSCRIPTEN__ diff --git a/dtool/src/dtoolbase/memoryHook.h b/dtool/src/dtoolbase/memoryHook.h index 13250e7085..a6460bca6c 100644 --- a/dtool/src/dtoolbase/memoryHook.h +++ b/dtool/src/dtoolbase/memoryHook.h @@ -20,6 +20,10 @@ #include "mutexImpl.h" #include +#ifdef __EMSCRIPTEN__ +#include +#endif + /** * This class provides a wrapper around the various possible malloc schemes * Panda might employ. It also exists to allow the MemoryUsage class in Panda @@ -77,12 +81,17 @@ protected: virtual void overflow_heap_size(); +#ifndef __EMSCRIPTEN__ void determine_page_size() const; +#endif private: +#ifdef __EMSCRIPTEN__ + static const size_t _page_size = EMSCRIPTEN_PAGE_SIZE; +#else mutable size_t _page_size = 0; - mutable MutexImpl _lock; +#endif }; #include "memoryHook.I" diff --git a/dtool/src/dtoolbase/patomic.I b/dtool/src/dtoolbase/patomic.I index 346ca8cfed..d1395c9e90 100644 --- a/dtool/src/dtoolbase/patomic.I +++ b/dtool/src/dtoolbase/patomic.I @@ -433,6 +433,8 @@ patomic_wait(const volatile uint32_t *value, uint32_t old) { while (*value == old) { _patomic_wait_func((volatile void *)value, &old, sizeof(uint32_t), INFINITE); } +#elif defined(__APPLE__) + __ulock_wait(UL_COMPARE_AND_WAIT, (void *)value, old, 0); #elif defined(HAVE_POSIX_THREADS) _patomic_wait(value, old); #else @@ -451,6 +453,8 @@ patomic_notify_one(volatile uint32_t *value) { // WakeByAddressSingle((void *)value); #elif defined(_WIN32) _patomic_wake_one_func((void *)value); +#elif defined(__APPLE__) + __ulock_wake(UL_COMPARE_AND_WAIT, (void *)value, 0); #elif defined(HAVE_POSIX_THREADS) _patomic_notify_all(value); #endif @@ -467,6 +471,8 @@ patomic_notify_all(volatile uint32_t *value) { // WakeByAddressAll((void *)value); #elif defined(_WIN32) _patomic_wake_all_func((void *)value); +#elif defined(__APPLE__) + __ulock_wake(UL_COMPARE_AND_WAIT | ULF_WAKE_ALL, (void *)value, 0); #elif defined(HAVE_POSIX_THREADS) _patomic_notify_all(value); #endif diff --git a/dtool/src/dtoolbase/patomic.cxx b/dtool/src/dtoolbase/patomic.cxx index 58d52a7e42..1b939a58c6 100644 --- a/dtool/src/dtoolbase/patomic.cxx +++ b/dtool/src/dtoolbase/patomic.cxx @@ -125,7 +125,7 @@ initialize_wait(volatile VOID *addr, PVOID cmp, SIZE_T size, DWORD timeout) { return emulated_wait(addr, cmp, size, timeout); } -#elif !defined(CPPPARSER) && !defined(__linux__) && defined(HAVE_POSIX_THREADS) +#elif !defined(CPPPARSER) && !defined(__linux__) && !defined(__APPLE__) && defined(HAVE_POSIX_THREADS) // Same as above, but using pthreads. struct alignas(64) WaitTableEntry { diff --git a/dtool/src/dtoolbase/patomic.h b/dtool/src/dtoolbase/patomic.h index 604d028392..02d1ab6ebc 100644 --- a/dtool/src/dtoolbase/patomic.h +++ b/dtool/src/dtoolbase/patomic.h @@ -32,6 +32,15 @@ #include #endif +#ifdef __APPLE__ +// Undocumented API, see https://outerproduct.net/futex-dictionary.html +#define UL_COMPARE_AND_WAIT 1 +#define ULF_WAKE_ALL 0x00000100 + +extern "C" int __ulock_wait(uint32_t op, void *addr, uint64_t value, uint32_t timeout); +extern "C" int __ulock_wake(uint32_t op, void *addr, uint64_t wake_value); +#endif + #if defined(THREAD_DUMMY_IMPL) || defined(THREAD_SIMPLE_IMPL) /** @@ -164,7 +173,7 @@ ALWAYS_INLINE void patomic_notify_all(volatile uint32_t *value); EXPCL_DTOOL_DTOOLBASE extern BOOL (__stdcall *_patomic_wait_func)(volatile VOID *, PVOID, SIZE_T, DWORD); EXPCL_DTOOL_DTOOLBASE extern void (__stdcall *_patomic_wake_one_func)(PVOID); EXPCL_DTOOL_DTOOLBASE extern void (__stdcall *_patomic_wake_all_func)(PVOID); -#elif !defined(__linux__) && defined(HAVE_POSIX_THREADS) +#elif !defined(__linux__) && !defined(__APPLE__) && defined(HAVE_POSIX_THREADS) EXPCL_DTOOL_DTOOLBASE void _patomic_wait(const volatile uint32_t *value, uint32_t old); EXPCL_DTOOL_DTOOLBASE void _patomic_notify_all(volatile uint32_t *value); #endif diff --git a/dtool/src/dtoolutil/executionEnvironment.cxx b/dtool/src/dtoolutil/executionEnvironment.cxx index c6e8e6de0c..eda3dc58fa 100644 --- a/dtool/src/dtoolutil/executionEnvironment.cxx +++ b/dtool/src/dtoolutil/executionEnvironment.cxx @@ -62,7 +62,7 @@ extern char **environ; #include #endif -#if defined(IS_LINUX) || defined(IS_FREEBSD) +#if (defined(IS_LINUX) || defined(IS_FREEBSD)) && !defined(__wasi__) // For link_map and dlinfo. #include #include @@ -576,6 +576,9 @@ read_environment_variables() { _variables[variable] = value; } } +#elif defined(__EMSCRIPTEN__) + // Emscripten has no environment vars. Don't even try. + #elif defined(HAVE_PROC_SELF_ENVIRON) // In some cases, we may have a file called procselfenviron that may be read // to determine all of our environment variables. @@ -918,7 +921,7 @@ read_args() { } #endif -#ifndef _WIN32 +#if !defined(_WIN32) && !defined(__wasi__) // Try to use realpath to get cleaner paths. if (!_binary_name.empty()) { @@ -934,7 +937,7 @@ read_args() { _dtool_name = newpath; } } -#endif // _WIN32 +#endif // _WIN32 __wasi__ if (_dtool_name.empty()) { _dtool_name = _binary_name; diff --git a/dtool/src/dtoolutil/filename.cxx b/dtool/src/dtoolutil/filename.cxx index d8dd0a5651..31b7a264ca 100644 --- a/dtool/src/dtoolutil/filename.cxx +++ b/dtool/src/dtoolutil/filename.cxx @@ -436,7 +436,7 @@ Filename Filename:: temporary(const string &dirname, const string &prefix, const string &suffix, Type type) { Filename fdirname = dirname; -#if defined(_WIN32) || defined(ANDROID) +#if defined(_WIN32) || defined(ANDROID) || defined(__wasi__) // The Windows tempnam() function doesn't do a good job of choosing a // temporary directory. Choose one ourselves. if (fdirname.empty()) { @@ -1049,7 +1049,7 @@ make_canonical() { return true; } -#ifndef _WIN32 +#if !defined(_WIN32) && !defined(__wasi__) // Use realpath in order to resolve symlinks properly char newpath [PATH_MAX + 1]; if (realpath(c_str(), newpath) != nullptr) { @@ -1057,7 +1057,7 @@ make_canonical() { newpath_fn._flags = _flags; (*this) = newpath_fn; } -#endif +#endif // _WIN32 __wasi__ Filename cwd = ExecutionEnvironment::get_cwd(); if (!r_make_canonical(cwd)) { @@ -2317,7 +2317,9 @@ touch() const { perror(os_specific.c_str()); return false; } - close(fd); + if (close(fd) < 0) { + perror(os_specific.c_str()); + } return true; } perror(os_specific.c_str()); @@ -2766,7 +2768,9 @@ atomic_compare_and_exchange_contents(string &orig_contents, if (flock(fd, LOCK_EX) != 0) { #endif perror(os_specific.c_str()); - close(fd); + if (close(fd) < 0) { + perror(os_specific.c_str()); + } return false; } @@ -2778,7 +2782,9 @@ atomic_compare_and_exchange_contents(string &orig_contents, if (bytes_read < 0) { perror(os_specific.c_str()); - close(fd); + if (close(fd) < 0) { + perror(os_specific.c_str()); + } return false; } @@ -2789,7 +2795,9 @@ atomic_compare_and_exchange_contents(string &orig_contents, ssize_t bytes_written = write(fd, new_contents.data(), new_contents.size()); if (bytes_written < 0) { perror(os_specific.c_str()); - close(fd); + if (close(fd) < 0) { + perror(os_specific.c_str()); + } return false; } } @@ -2882,7 +2890,9 @@ atomic_read_contents(string &contents) const { if (flock(fd, LOCK_EX) != 0) { #endif perror(os_specific.c_str()); - close(fd); + if (close(fd) < 0) { + perror(os_specific.c_str()); + } return false; } @@ -2894,11 +2904,15 @@ atomic_read_contents(string &contents) const { if (bytes_read < 0) { perror(os_specific.c_str()); - close(fd); + if (close(fd) < 0) { + perror(os_specific.c_str()); + } return false; } - close(fd); + if (close(fd) < 0) { + perror(os_specific.c_str()); + } return true; #endif // _WIN32 } diff --git a/dtool/src/dtoolutil/filename_ext.cxx b/dtool/src/dtoolutil/filename_ext.cxx index 7feec66a75..cc67d9dd2e 100644 --- a/dtool/src/dtoolutil/filename_ext.cxx +++ b/dtool/src/dtoolutil/filename_ext.cxx @@ -134,8 +134,7 @@ PyObject *Extension:: scan_directory() const { vector_string contents; if (!_this->scan_directory(contents)) { - Py_INCREF(Py_None); - return Py_None; + return Py_NewRef(Py_None); } PyObject *result = PyList_New(contents.size()); diff --git a/dtool/src/dtoolutil/iostream_ext.cxx b/dtool/src/dtoolutil/iostream_ext.cxx index 352927b0d6..459f95c229 100644 --- a/dtool/src/dtoolutil/iostream_ext.cxx +++ b/dtool/src/dtoolutil/iostream_ext.cxx @@ -227,7 +227,7 @@ readlines(Py_ssize_t hint) { /** * Yields continuously to read all the lines from the istream. */ -static PyObject *gen_next(PyObject *self) { +static PyObject *gen_next_istream(PyObject *self) { istream *stream = nullptr; if (!Dtool_Call_ExtractThisPointer(self, Dtool_std_istream, (void **)&stream)) { return nullptr; @@ -247,7 +247,7 @@ static PyObject *gen_next(PyObject *self) { */ PyObject *Extension:: __iter__(PyObject *self) { - return Dtool_NewGenerator(self, &gen_next); + return Dtool_NewGenerator(self, &gen_next_istream); } /** @@ -283,19 +283,18 @@ write(PyObject *b) { */ void Extension:: writelines(PyObject *lines) { - PyObject *seq = PySequence_Fast(lines, "writelines() expects a sequence"); - if (seq == nullptr) { + PyObject *iter = PyObject_GetIter(lines); + if (iter == nullptr) { return; } - PyObject **items = PySequence_Fast_ITEMS(seq); - Py_ssize_t len = PySequence_Fast_GET_SIZE(seq); - - for (Py_ssize_t i = 0; i < len; ++i) { - write(items[i]); + PyObject *next = PyIter_Next(iter); + while (next != nullptr) { + write(next); + Py_DECREF(next); + next = PyIter_Next(iter); } - - Py_DECREF(seq); + Py_DECREF(iter); } #endif // HAVE_PYTHON diff --git a/dtool/src/dtoolutil/pandaFileStreamBuf.cxx b/dtool/src/dtoolutil/pandaFileStreamBuf.cxx index 1caecaf991..e5891c7158 100644 --- a/dtool/src/dtoolutil/pandaFileStreamBuf.cxx +++ b/dtool/src/dtoolutil/pandaFileStreamBuf.cxx @@ -267,7 +267,15 @@ close() { _handle = nullptr; #else if (_fd != -1) { - ::close(_fd); + if (::close(_fd) < 0) { +#ifdef NDEBUG + perror("close"); +#else + char *str = (char *)alloca(_filename.size() + 32); + sprintf(str, "close(%d \"%s\")", _fd, _filename.c_str()); + perror(str); +#endif + } } _fd = -1; #endif // _WIN32 diff --git a/dtool/src/dtoolutil/pfstream.h b/dtool/src/dtoolutil/pfstream.h index e296655337..8c746c7e43 100644 --- a/dtool/src/dtoolutil/pfstream.h +++ b/dtool/src/dtoolutil/pfstream.h @@ -16,6 +16,8 @@ #include "pfstreamBuf.h" +#ifndef __EMSCRIPTEN__ + class EXPCL_DTOOL_DTOOLUTIL IPipeStream : public std::istream { public: INLINE IPipeStream(const std::string); @@ -50,4 +52,6 @@ private: #include "pfstream.I" +#endif /* __EMSCRIPTEN__ */ + #endif /* __PFSTREAM_H__ */ diff --git a/dtool/src/dtoolutil/pfstreamBuf.cxx b/dtool/src/dtoolutil/pfstreamBuf.cxx index b2fcf2838e..f746ca5ac9 100644 --- a/dtool/src/dtoolutil/pfstreamBuf.cxx +++ b/dtool/src/dtoolutil/pfstreamBuf.cxx @@ -14,6 +14,8 @@ #include "pfstreamBuf.h" #include +#ifndef __EMSCRIPTEN__ + using std::cerr; using std::endl; using std::string; @@ -404,3 +406,5 @@ read_pipe(char *data, size_t len) { #endif // WIN_PIPE_CALLS + +#endif // __EMSCRIPTEN__ diff --git a/dtool/src/dtoolutil/pfstreamBuf.h b/dtool/src/dtoolutil/pfstreamBuf.h index 728c083252..6174e64ab4 100644 --- a/dtool/src/dtoolutil/pfstreamBuf.h +++ b/dtool/src/dtoolutil/pfstreamBuf.h @@ -18,6 +18,9 @@ #include #include +// Emscripten does not have popen. +#ifndef __EMSCRIPTEN__ + // By default, we'll use the Windows flavor of pipe functions if we're // compiling under Windows. Turn this off to use popen(), even on Windows. // (popen() doesn't seem to work on Win9x, although it does work on NT-based @@ -77,4 +80,6 @@ private: void write_chars(const char*, int, bool); }; +#endif /* __EMSCRIPTEN__ */ + #endif /* __PFSTREAMBUF_H__ */ diff --git a/dtool/src/dtoolutil/textEncoder.h b/dtool/src/dtoolutil/textEncoder.h index d349ffe3af..29a523b2c1 100644 --- a/dtool/src/dtoolutil/textEncoder.h +++ b/dtool/src/dtoolutil/textEncoder.h @@ -54,28 +54,28 @@ PUBLISHED: INLINE static Encoding get_default_encoding(); MAKE_PROPERTY(default_encoding, get_default_encoding, set_default_encoding); -#if defined(CPPPARSER) - PY_EXTEND(void set_text(PyObject *text)); - PY_EXTEND(void set_text(PyObject *text, Encoding encoding)); -#else // CPPPARSER +#if defined(CPPPARSER) && defined(HAVE_PYTHON) + EXTEND void set_text(PyObject *text); + EXTEND void set_text(PyObject *text, Encoding encoding); +#else INLINE void set_text(const std::string &text); INLINE void set_text(const std::string &text, Encoding encoding); -#endif // CPPPARSER +#endif INLINE void clear_text(); INLINE bool has_text() const; void make_upper(); void make_lower(); -#if defined(CPPPARSER) - PY_EXTEND(PyObject *get_text() const); - PY_EXTEND(PyObject *get_text(Encoding encoding) const); - PY_EXTEND(void append_text(PyObject *text)); -#else // CPPPARSER +#if defined(CPPPARSER) && defined(HAVE_PYTHON) + EXTEND PyObject *get_text() const; + EXTEND PyObject *get_text(Encoding encoding) const; + EXTEND void append_text(PyObject *text); +#else INLINE std::string get_text() const; INLINE std::string get_text(Encoding encoding) const; INLINE void append_text(const std::string &text); -#endif // CPPPARSER +#endif INLINE void append_unicode_char(char32_t character); INLINE size_t get_num_chars() const; INLINE int get_unicode_char(size_t index) const; @@ -108,19 +108,19 @@ PUBLISHED: std::wstring get_wtext_as_ascii() const; bool is_wtext() const; -#if defined(CPPPARSER) - PY_EXTEND(static PyObject *encode_wchar(char32_t ch, Encoding encoding)); - PY_EXTEND(INLINE PyObject *encode_wtext(const std::wstring &wtext) const); - PY_EXTEND(static PyObject *encode_wtext(const std::wstring &wtext, Encoding encoding)); - PY_EXTEND(INLINE PyObject *decode_text(PyObject *text) const); - PY_EXTEND(static PyObject *decode_text(PyObject *text, Encoding encoding)); -#else // CPPPARSER +#if defined(CPPPARSER) && defined(HAVE_PYTHON) + EXTEND static PyObject *encode_wchar(char32_t ch, Encoding encoding); + EXTEND INLINE PyObject *encode_wtext(const std::wstring &wtext) const; + EXTEND static PyObject *encode_wtext(const std::wstring &wtext, Encoding encoding); + EXTEND INLINE PyObject *decode_text(PyObject *text) const; + EXTEND static PyObject *decode_text(PyObject *text, Encoding encoding); +#else static std::string encode_wchar(char32_t ch, Encoding encoding); INLINE std::string encode_wtext(const std::wstring &wtext) const; static std::string encode_wtext(const std::wstring &wtext, Encoding encoding); INLINE std::wstring decode_text(const std::string &text) const; static std::wstring decode_text(const std::string &text, Encoding encoding); -#endif // CPPPARSER +#endif MAKE_PROPERTY(text, get_text, set_text); diff --git a/dtool/src/interrogate/functionRemap.cxx b/dtool/src/interrogate/functionRemap.cxx index 6d6ce0f911..b692577067 100644 --- a/dtool/src/interrogate/functionRemap.cxx +++ b/dtool/src/interrogate/functionRemap.cxx @@ -450,8 +450,6 @@ get_call_str(const string &container, const vector_string &pexprs) const { _parameters[pn]._remap->pass_parameter(call, get_parameter_expr(pn, pexprs)); } else { - const char *separator = ""; - // If this function is marked as having an extension function, call that // instead. if (_extension) { @@ -488,33 +486,41 @@ get_call_str(const string &container, const vector_string &pexprs) const { } } call << "("; - - if (_flags & F_explicit_self) { - // Pass on the PyObject * that we stripped off above. - call << separator << "self"; - separator = ", "; - } - if (_flags & F_explicit_cls) { - call << separator << "cls"; - separator = ", "; - } - - size_t pn; - size_t num_parameters = pexprs.size(); - - for (pn = _first_true_parameter; - pn < num_parameters; ++pn) { - nassertd(pn < _parameters.size()) break; - call << separator; - _parameters[pn]._remap->pass_parameter(call, get_parameter_expr(pn, pexprs)); - separator = ", "; - } + write_call_args(call, pexprs); call << ")"; } return call.str(); } +/** + * Writes the arguments to pass to the function. + */ +void FunctionRemap:: +write_call_args(std::ostream &call, const vector_string &pexprs) const { + const char *separator = ""; + if (_flags & F_explicit_self) { + // Pass on the PyObject * that we stripped off above. + call << separator << "self"; + separator = ", "; + } + if (_flags & F_explicit_cls) { + call << separator << "cls"; + separator = ", "; + } + + size_t pn; + size_t num_parameters = pexprs.size(); + + for (pn = _first_true_parameter; + pn < num_parameters; ++pn) { + nassertd(pn < _parameters.size()) break; + call << separator; + _parameters[pn]._remap->pass_parameter(call, get_parameter_expr(pn, pexprs)); + separator = ", "; + } +} + /** * Returns the minimum number of arguments that needs to be passed to this * function. diff --git a/dtool/src/interrogate/functionRemap.h b/dtool/src/interrogate/functionRemap.h index f6d2fea30c..e662e40b75 100644 --- a/dtool/src/interrogate/functionRemap.h +++ b/dtool/src/interrogate/functionRemap.h @@ -61,6 +61,7 @@ public: FunctionWrapperIndex make_wrapper_entry(FunctionIndex function_index); std::string get_call_str(const std::string &container, const vector_string &pexprs) const; + void write_call_args(std::ostream &out, const vector_string &pexprs) const; int get_min_num_args() const; int get_max_num_args() const; diff --git a/dtool/src/interrogate/interfaceMakerPythonNative.cxx b/dtool/src/interrogate/interfaceMakerPythonNative.cxx index 6958e8a5e6..632e49c125 100644 --- a/dtool/src/interrogate/interfaceMakerPythonNative.cxx +++ b/dtool/src/interrogate/interfaceMakerPythonNative.cxx @@ -32,6 +32,7 @@ #include "cppStructType.h" #include "cppExpression.h" #include "cppParameterList.h" +#include "cppReferenceType.h" #include "lineStream.h" #include @@ -797,9 +798,7 @@ write_python_instance(ostream &out, int indent_level, const string &return_expr, indent(out, indent_level) << "if (" << return_expr << " == nullptr) {\n"; indent(out, indent_level) - << " Py_INCREF(Py_None);\n"; - indent(out, indent_level) - << " return Py_None;\n"; + << " return Py_NewRef(Py_None);\n"; indent(out, indent_level) << "} else {\n"; // Special exception if we are returning TypedWritable, which might @@ -1108,6 +1107,170 @@ write_class_details(ostream &out, Object *obj) { std::string ClassName = make_safe_name(obj->_itype.get_scoped_name()); std::string cClassName = obj->_itype.get_true_name(); + CPPType *cpptype = TypeManager::resolve_type(obj->_itype._cpptype); + CPPStructType *struct_type = cpptype->as_struct_type(); + + // Determine which external imports we will need. + std::map details; + std::map::iterator di; + builder.get_type(TypeManager::unwrap(cpptype), false); + get_valid_child_classes(details, cpptype->as_struct_type()); + for (di = details.begin(); di != details.end(); di++) { + // InterrogateType ptype =idb->get_type(di->first); + if (di->second._is_legal_py_class && !isExportThisRun(di->second._structType)) { + _external_imports.insert(TypeManager::resolve_type(di->second._structType)); + } + // out << "IMPORT_THIS struct Dtool_PyTypedObject Dtool_" << + // make_safe_name(di->second._to_class_name) << ";\n"; + } + + bool py_subclassable = is_python_subclassable(struct_type); + if (py_subclassable) { + assert(!obj->_constructors.empty()); + out << "/**\n"; + out << " * Proxy class for " << cClassName << "\n"; + out << " */\n"; + out << "class DtoolProxy_" << ClassName << " final : public " << cClassName << ", public DtoolProxy {\n"; + out << "public:\n"; + // I'd love just to use "using" to inherit the constructors from the base. + // However, MSVC seems to have a bug inheriting constructors with default + // arguments. + if (struct_type->is_default_constructible()) { + out << " DtoolProxy_" << ClassName << "() = default;\n"; + } + for (Function *func : obj->_constructors) { + for (FunctionRemap *remap : func->_remaps) { + CPPParameterList::Parameters ¶ms = remap->_ftype->_parameters->_parameters; + if (params.empty()) { + continue; + } + out << " DtoolProxy_" << ClassName << "("; + for (size_t i = 0; i < params.size(); ++i) { + if (i > 0) { + out << ", "; + } + params[i]->_type->output_instance(out, remap->get_parameter_name(i), &parser); + if (i > 0 && params[i]->_initializer != nullptr) { + out << " = " << *params[i]->_initializer; + } + } + out << ")"; + if (remap->_ftype->_flags & CPPFunctionType::F_noexcept) { + out << " noexcept"; + } + out << " : " << cClassName << "("; + for (size_t i = 0; i < params.size(); ++i) { + if (i > 0) { + out << ", "; + } + // Determine whether to pass with move semantics or not. + CPPType *param_type = params[i]->_type; + CPPType::SubType subtype = param_type->get_subtype(); + while (subtype == CPPDeclaration::ST_typedef) { + param_type = param_type->as_typedef_type()->_type; + subtype = param_type->get_subtype(); + } + if (subtype == CPPType::ST_pointer || + subtype == CPPType::ST_const || + subtype == CPPType::ST_enum || + subtype == CPPType::ST_simple || + (subtype == CPPType::ST_reference && param_type->as_reference_type()->_value_category == CPPReferenceType::VC_lvalue)) { + out << remap->get_parameter_name(i); + } else { + out << "std::move(" << remap->get_parameter_name(i) << ")"; + } + } + out << ") {}\n"; + } + } + + // Move constructor is never listed above, but we do use it. + if (struct_type->is_move_constructible()) { + out << " DtoolProxy_" << ClassName << "(" << cClassName << " &&from)"; + CPPInstance *ctor = struct_type->get_move_constructor(); + if (ctor != nullptr) { + CPPFunctionType *ftype = ctor->_type->as_function_type(); + if (ftype != nullptr && (ftype->_flags & CPPFunctionType::F_noexcept) != 0) { + out << " noexcept"; + } + } + out << " : " << cClassName << "(std::move(from)) {}\n"; + } + out << "\n"; + out << " virtual bool unref() const override {\n"; + out << " if (!(" << cClassName << "::unref())) {\n"; + out << " // It was cleaned up by the Python garbage collector.\n"; + out << " return false;\n"; + out << " }\n"; + out << " nassertr(DtoolProxy::_self != nullptr, true);\n"; + out << "\n"; + out << " // If the last reference to the object is the one being held by Python,\n"; + out << " // check whether the Python wrapper itself is also at a refcount of 1.\n"; + out << " bool result = true;\n"; + out << " if (get_ref_count() == 1) {\n"; + out << " PyGILState_STATE gstate = PyGILState_Ensure();\n"; + out << " int ref_count = Py_REFCNT(DtoolProxy::_self);\n"; + out << " assert(ref_count > 0);\n"; + out << " if (ref_count == 1) {\n"; + out << " // The last reference to the Python wrapper is being held by us.\n"; + out << " // Break the reference cycle and allow the object to go away.\n"; + out << " if (!" << cClassName << "::unref()) {\n"; + out << " PyObject_GC_UnTrack(DtoolProxy::_self);\n"; + out << " ((Dtool_PyInstDef *)DtoolProxy::_self)->_memory_rules = false;\n"; + out << " Py_CLEAR(DtoolProxy::_self);\n"; + out << "\n"; + out << " // Let the caller destroy the object.\n"; + out << " result = false;\n"; + out << " }\n"; + out << " }\n"; + //out << " else {\n"; + //out << " // There is still a Python reference. Make sure it can be cleaned up\n"; + //out << " // by the garbage collector when it gets to it.\n"; + //out << " if (!PyObject_GC_IsTracked(DtoolProxy::_self)) {\n"; + //out << " PyObject_GC_Track(DtoolProxy::_self);\n"; + //out << " }\n"; + //out << " }\n"; + out << " PyGILState_Release(gstate);\n"; + out << " }\n"; + out << " return result;\n"; + out << " }\n"; + out << "\n"; + out << " virtual TypeHandle get_type() const override {\n"; + out << " return DtoolProxy::_type;\n"; + out << " }\n"; + out << "\n"; + out << " virtual TypeHandle force_init_type() override {\n"; + out << " return DtoolProxy::_type;\n"; + out << " }\n"; + out << "};\n"; + out << "\n"; + + out << "static PyObject *Dtool_WrapProxy_" << ClassName << "(void *from_this, PyTypeObject *from_type) {\n"; + out << " DtoolProxy_" << ClassName << " *to_this;\n"; + out << " if (from_type == nullptr || from_type == &Dtool_" << ClassName << "._PyType) {\n"; + out << " to_this = (DtoolProxy_" << ClassName << " *)(" << cClassName << "*)from_this;\n"; + out << " }\n"; + for (di = details.begin(); di != details.end(); di++) { + if (di->second._can_downcast && di->second._is_legal_py_class) { + out << " else if (from_type == (PyTypeObject *)Dtool_Ptr_" << make_safe_name(di->second._to_class_name) << ") {\n"; + out << " " << di->second._to_class_name << " *other_this = (" << di->second._to_class_name << " *)from_this;\n" ; + out << " to_this = (DtoolProxy_" << ClassName << " *)(" << cClassName << " *)other_this;\n"; + out << " }\n"; + } + } + out << " else {\n"; + out << " return nullptr;\n"; + out << " }\n"; + out << " nassertr(to_this->DtoolProxy::_self != nullptr, nullptr);\n"; + out << " PyObject *result = Py_NewRef(to_this->DtoolProxy::_self);\n"; + // Directly call the parent class' unref(), because we know our version + // would only find that the Python refcount > 1 and do nothing else + out << " bool nonzero = to_this->" << cClassName << "::unref();\n"; + out << " nassertr(nonzero, result);\n"; + out << " return result;\n"; + out << "}\n\n"; + } + out << "/**\n"; out << " * Python wrappers for functions of class " << cClassName << "\n" ; out << " */\n"; @@ -1151,11 +1314,9 @@ write_class_details(ostream &out, Object *obj) { } } - CPPType *cpptype = TypeManager::resolve_type(obj->_itype._cpptype); - // If we have "coercion constructors", write a single wrapper to consolidate // those. - int has_coerce = has_coerce_constructor(cpptype->as_struct_type()); + int has_coerce = has_coerce_constructor(struct_type); if (has_coerce > 0) { write_coerce_constructor(out, obj, true); if (has_coerce > 1 && TypeManager::is_reference_count(obj->_itype._cpptype)) { @@ -1178,20 +1339,6 @@ write_class_details(ostream &out, Object *obj) { } } - // Determine which external imports we will need. - std::map details; - std::map::iterator di; - builder.get_type(TypeManager::unwrap(cpptype), false); - get_valid_child_classes(details, cpptype->as_struct_type()); - for (di = details.begin(); di != details.end(); di++) { - // InterrogateType ptype =idb->get_type(di->first); - if (di->second._is_legal_py_class && !isExportThisRun(di->second._structType)) { - _external_imports.insert(TypeManager::resolve_type(di->second._structType)); - } - // out << "IMPORT_THIS struct Dtool_PyTypedObject Dtool_" << - // make_safe_name(di->second._to_class_name) << ";\n"; - } - // Write support methods to cast from and to pointers of this type. { out << "static void *Dtool_UpcastInterface_" << ClassName << "(PyObject *self, Dtool_PyTypedObject *requested_type) {\n"; @@ -1243,27 +1390,46 @@ write_class_details(ostream &out, Object *obj) { out << "static PyObject *Dtool_Wrap_" << ClassName << "(void *from_this, PyTypeObject *from_type) {\n"; out << " " << cClassName << " *to_this;\n"; out << " if (from_type == nullptr || from_type == &Dtool_" << ClassName << "._PyType) {\n"; - out << " to_this = (" << cClassName << "*)from_this;\n"; + out << " to_this = (" << cClassName << " *)from_this;\n"; out << " }\n"; for (di = details.begin(); di != details.end(); di++) { if (di->second._can_downcast && di->second._is_legal_py_class) { out << " else if (from_type == (PyTypeObject *)Dtool_Ptr_" << make_safe_name(di->second._to_class_name) << ") {\n"; out << " " << di->second._to_class_name << " *other_this = (" << di->second._to_class_name << " *)from_this;\n" ; - out << " to_this = (" << cClassName << "*)other_this;\n"; + out << " to_this = (" << cClassName << " *)other_this;\n"; out << " }\n"; } } out << " else {\n"; out << " return nullptr;\n"; out << " }\n"; - out << " // Allocate a new Python instance\n"; - out << " Dtool_PyInstDef *self = (Dtool_PyInstDef *)PyType_GenericAlloc(&Dtool_" << ClassName << "._PyType, 0);\n"; - out << " self->_signature = PY_PANDA_SIGNATURE;\n"; - out << " self->_My_Type = &Dtool_" << ClassName << ";\n"; - out << " self->_ptr_to_object = to_this;\n"; - out << " self->_memory_rules = false;\n"; - out << " self->_is_const = false;\n"; - out << " return (PyObject *)self;\n"; + if (has_self_member(struct_type)) { + out << " PyObject *stored_self = to_this->__self__;\n"; + out << " if (stored_self == nullptr) {\n"; + out << " // Allocate a new Python instance\n"; + out << " Dtool_PyInstDef *self = (Dtool_PyInstDef *)PyType_GenericAlloc(&Dtool_" << ClassName << "._PyType, 0);\n"; + out << " self->_signature = PY_PANDA_SIGNATURE;\n"; + out << " self->_My_Type = &Dtool_" << ClassName << ";\n"; + out << " self->_ptr_to_object = to_this;\n"; + out << " self->_memory_rules = true;\n"; + out << " self->_is_const = false;\n"; + out << " to_this->__self__ = Py_NewRef((PyObject *)self);\n"; + out << " return Py_NewRef((PyObject *)self);\n"; + out << " }\n"; + out << " PyObject *result = Py_NewRef(stored_self);\n"; + out << " bool nonzero = to_this->unref();\n"; + out << " nassertr(nonzero, result);\n"; + out << " return result;\n"; + } else { + out << " // Allocate a new Python instance\n"; + out << " Dtool_PyInstDef *self = (Dtool_PyInstDef *)PyType_GenericAlloc(&Dtool_" << ClassName << "._PyType, 0);\n"; + out << " self->_signature = PY_PANDA_SIGNATURE;\n"; + out << " self->_My_Type = &Dtool_" << ClassName << ";\n"; + out << " self->_ptr_to_object = to_this;\n"; + out << " self->_memory_rules = false;\n"; + out << " self->_is_const = false;\n"; + out << " return (PyObject *)self;\n"; + } out << "}\n\n"; } } @@ -1372,16 +1538,15 @@ write_sub_module(ostream &out, Object *obj) { class_ptr = "(PyObject *)" + class_ptr; - // Note: PyModule_AddObject steals a reference, so we have to call Py_INCREF - // for every but the first time we add it to the module. - if (obj->_itype.is_typedef()) { - out << " Py_INCREF(" << class_ptr << ");\n"; + // The first time we add something to a module, we use PyModule_AddObject, + // which steals a reference. This saves a call to Py_DECREF. + if (!obj->_itype.is_typedef()) { + out << " PyModule_AddObject(module, \"" << export_class_name << "\", " << class_ptr << ");\n"; + } else { + out << " PyModule_AddObjectRef(module, \"" << export_class_name << "\", " << class_ptr << ");\n"; } - - out << " PyModule_AddObject(module, \"" << export_class_name << "\", " << class_ptr << ");\n"; if (export_class_name != export_class_name2) { - out << " Py_INCREF(Dtool_Ptr_" << class_name << ");\n"; - out << " PyModule_AddObject(module, \"" << export_class_name2 << "\", " << class_ptr << ");\n"; + out << " PyModule_AddObjectRef(module, \"" << export_class_name2 << "\", " << class_ptr << ");\n"; } } @@ -1681,6 +1846,9 @@ write_module_class(ostream &out, Object *obj) { std::string cClassName = obj->_itype.get_true_name(); std::string export_class_name = classNameFromCppName(obj->_itype.get_name(), false); + CPPStructType *struct_type = obj->_itype._cpptype->as_struct_type(); + bool py_subclassable = is_python_subclassable(struct_type); + out << "/**\n"; out << " * Python method tables for " << ClassName << " (" << export_class_name << ")\n" ; out << " */\n"; @@ -1930,15 +2098,10 @@ write_module_class(ostream &out, Object *obj) { return_flags |= RF_preserve_null; } string expected_params; - write_function_forset(out, def._remaps, 0, 0, expected_params, 2, true, true, - AT_no_args, return_flags, false); - - out << " if (!PyErr_Occurred()) {\n"; - out << " return Dtool_Raise_BadArgumentsError(\n"; - output_quoted(out, 6, expected_params); - out << ");\n"; - out << " }\n"; - out << " return nullptr;\n"; + if (!write_function_forset(out, def._remaps, 0, 0, expected_params, 2, true, true, + AT_no_args, return_flags, false)) { + error_bad_args_return(out, 2, return_flags, expected_params); + } out << "}\n\n"; } break; @@ -1973,12 +2136,7 @@ write_module_class(ostream &out, Object *obj) { write_function_forset(out, def._remaps, 1, 1, expected_params, 2, true, true, AT_single_arg, RF_err_null | RF_pyobject, false, !all_nonconst); - out << " if (!PyErr_Occurred()) {\n"; - out << " return Dtool_Raise_BadArgumentsError(\n"; - output_quoted(out, 6, expected_params); - out << ");\n"; - out << " }\n"; - out << " return nullptr;\n"; + error_bad_args_return(out, 2, RF_pyobject | RF_err_null, expected_params); out << "}\n\n"; } break; @@ -2048,8 +2206,7 @@ write_module_class(ostream &out, Object *obj) { out << " }\n"; } - out << " Py_INCREF(Py_NotImplemented);\n"; - out << " return Py_NotImplemented;\n"; + out << " return Py_NewRef(Py_NotImplemented);\n"; out << "}\n\n"; } break; @@ -2087,40 +2244,31 @@ write_module_class(ostream &out, Object *obj) { if (!setattr_remaps.empty()) { out << " PyObject *args = PyTuple_Pack(2, arg, arg2);\n"; string expected_params; - write_function_forset(out, setattr_remaps, 2, 2, expected_params, 4, - true, true, AT_varargs, RF_int | RF_decref_args, true); - - out << " Py_DECREF(args);\n"; - out << " if (!PyErr_Occurred()) {\n"; - out << " Dtool_Raise_BadArgumentsError(\n"; - output_quoted(out, 8, expected_params); - out << ");\n"; - out << " }\n"; + if (!write_function_forset(out, setattr_remaps, 2, 2, expected_params, 4, + true, true, AT_varargs, RF_int | RF_decref_args, true)) { + error_bad_args_return(out, 4, RF_int | RF_decref_args, expected_params); + } } else { out << " PyErr_Format(PyExc_TypeError,\n"; out << " \"can't set attributes of built-in/extension type '%s'\",\n"; out << " Py_TYPE(self)->tp_name);\n"; + out << " return -1;\n\n"; } - out << " return -1;\n\n"; out << " } else { // __delattr__\n"; if (!delattr_remaps.empty()) { string expected_params; - write_function_forset(out, delattr_remaps, 1, 1, expected_params, 4, - true, true, AT_single_arg, RF_int, true); - - out << " if (!PyErr_Occurred()) {\n"; - out << " Dtool_Raise_BadArgumentsError(\n"; - output_quoted(out, 8, expected_params); - out << ");\n"; - out << " }\n"; + if (!write_function_forset(out, delattr_remaps, 1, 1, expected_params, 4, + true, true, AT_single_arg, RF_int, true)) { + error_bad_args_return(out, 4, RF_int | RF_decref_args, expected_params); + } } else { out << " PyErr_Format(PyExc_TypeError,\n"; out << " \"can't delete attributes of built-in/extension type '%s'\",\n"; out << " Py_TYPE(self)->tp_name);\n"; + out << " return -1;\n"; } - out << " return -1;\n"; out << " }\n"; out << "}\n\n"; @@ -2153,12 +2301,12 @@ write_module_class(ostream &out, Object *obj) { out << " }\n\n"; string expected_params; - write_function_forset(out, def._remaps, 1, 1, expected_params, 2, - true, true, AT_single_arg, - RF_pyobject | RF_err_null, true); - - // out << " PyErr_Clear();\n"; - out << " return nullptr;\n"; + if (!write_function_forset(out, def._remaps, 1, 1, expected_params, 2, + true, true, AT_single_arg, + RF_pyobject | RF_err_null, true)) { + // out << " PyErr_Clear();\n"; + out << " return nullptr;\n"; + } out << "}\n\n"; } break; @@ -2190,15 +2338,10 @@ write_module_class(ostream &out, Object *obj) { out << " }\n"; string expected_params; - write_function_forset(out, def._remaps, 1, 1, expected_params, 2, true, true, - AT_no_args, RF_pyobject | RF_err_null, false, true, "index"); - - out << " if (!PyErr_Occurred()) {\n"; - out << " return Dtool_Raise_BadArgumentsError(\n"; - output_quoted(out, 6, expected_params); - out << ");\n"; - out << " }\n"; - out << " return nullptr;\n"; + if (!write_function_forset(out, def._remaps, 1, 1, expected_params, 2, true, true, + AT_no_args, RF_pyobject | RF_err_null, false, true, "index")) { + error_bad_args_return(out, 2, RF_pyobject | RF_err_null, expected_params); + } out << "}\n\n"; } break; @@ -2240,20 +2383,22 @@ write_module_class(ostream &out, Object *obj) { } string expected_params; + bool always_returns = true; out << " if (arg != nullptr) { // __setitem__\n"; - write_function_forset(out, setitem_remaps, 2, 2, expected_params, 4, - true, true, AT_single_arg, RF_int, false, true, "index"); + if (!write_function_forset(out, setitem_remaps, 2, 2, expected_params, 4, + true, true, AT_single_arg, RF_int, false, true, "index")) { + always_returns = false; + } out << " } else { // __delitem__\n"; - write_function_forset(out, delitem_remaps, 1, 1, expected_params, 4, - true, true, AT_single_arg, RF_int, false, true, "index"); + if (!write_function_forset(out, delitem_remaps, 1, 1, expected_params, 4, + true, true, AT_single_arg, RF_int, false, true, "index")) { + always_returns = false; + } out << " }\n\n"; - out << " if (!PyErr_Occurred()) {\n"; - out << " Dtool_Raise_BadArgumentsError(\n"; - output_quoted(out, 6, expected_params); - out << ");\n"; - out << " }\n"; - out << " return -1;\n"; + if (!always_returns) { + error_bad_args_return(out, 2, RF_int, expected_params); + } out << "}\n\n"; } break; @@ -2306,22 +2451,28 @@ write_module_class(ostream &out, Object *obj) { } string expected_params; + bool always_returns = true; out << " if (arg2 != nullptr) { // __setitem__\n"; - out << " PyObject *args = PyTuple_Pack(2, arg, arg2);\n"; - write_function_forset(out, setitem_remaps, 2, 2, expected_params, 4, - true, true, AT_varargs, RF_int | RF_decref_args, false); - out << " Py_DECREF(args);\n"; + if (setitem_remaps.empty()) { + always_returns = false; + } else { + out << " PyObject *args = PyTuple_Pack(2, arg, arg2);\n"; + if (!write_function_forset(out, setitem_remaps, 2, 2, expected_params, 4, + true, true, AT_varargs, RF_int | RF_decref_args, false)) { + always_returns = false; + } + out << " Py_DECREF(args);\n"; + } out << " } else { // __delitem__\n"; - write_function_forset(out, delitem_remaps, 1, 1, expected_params, 4, - true, true, AT_single_arg, RF_int, false); + if (!write_function_forset(out, delitem_remaps, 1, 1, expected_params, 4, + true, true, AT_single_arg, RF_int, false)) { + always_returns = false; + } out << " }\n\n"; - out << " if (!PyErr_Occurred()) {\n"; - out << " Dtool_Raise_BadArgumentsError(\n"; - output_quoted(out, 6, expected_params); - out << ");\n"; - out << " }\n"; - out << " return -1;\n"; + if (!always_returns) { + error_bad_args_return(out, 2, RF_int, expected_params); + } out << "}\n\n"; } break; @@ -2524,8 +2675,7 @@ write_module_class(ostream &out, Object *obj) { // of raising an exception, if the this pointer doesn't match. This // is for things like __pow__, which Python likes to call on the // wrong-type objects. - out << " Py_INCREF(Py_NotImplemented);\n"; - out << " return Py_NotImplemented;\n"; + out << " return Py_NewRef(Py_NotImplemented);\n"; out << " }\n"; set one_param_remaps; @@ -2541,23 +2691,28 @@ write_module_class(ostream &out, Object *obj) { } string expected_params; - + bool always_returns = true; out << " if (arg2 != nullptr && arg2 != Py_None) {\n"; - out << " PyObject *args = PyTuple_Pack(2, arg, arg2);\n"; - write_function_forset(out, two_param_remaps, 2, 2, expected_params, 4, - true, true, AT_varargs, return_flags | RF_decref_args, true); - out << " Py_DECREF(args);\n"; + if (two_param_remaps.empty()) { + always_returns = false; + } else { + out << " PyObject *args = PyTuple_Pack(2, arg, arg2);\n"; + if (!write_function_forset(out, two_param_remaps, 2, 2, expected_params, 4, + true, true, AT_varargs, return_flags | RF_decref_args, true)) { + always_returns = false; + } + out << " Py_DECREF(args);\n"; + } out << " } else {\n"; - write_function_forset(out, one_param_remaps, 1, 1, expected_params, 4, - true, true, AT_single_arg, return_flags, true); + if (!write_function_forset(out, one_param_remaps, 1, 1, expected_params, 4, + true, true, AT_single_arg, return_flags, true)) { + always_returns = false; + } out << " }\n\n"; - out << " if (!PyErr_Occurred()) {\n"; - out << " return Dtool_Raise_BadArgumentsError(\n"; - output_quoted(out, 6, expected_params); - out << ");\n"; - out << " }\n"; - out << " return nullptr;\n"; + if (!always_returns) { + error_bad_args_return(out, 2, return_flags, expected_params); + } out << "}\n\n"; } break; @@ -2574,22 +2729,36 @@ write_module_class(ostream &out, Object *obj) { // Find the remap. There should be only one. FunctionRemap *remap = *def._remaps.begin(); - const char *container = ""; - if (remap->_has_this) { - out << " " << cClassName << " *local_this = nullptr;\n"; - out << " DTOOL_Call_ExtractThisPointerForType(self, &Dtool_" << ClassName << ", (void **) &local_this);\n"; - out << " if (local_this == nullptr) {\n"; - out << " return 0;\n"; - out << " }\n\n"; - container = "local_this"; + out << " " << cClassName << " *local_this = nullptr;\n"; + out << " DTOOL_Call_ExtractThisPointerForType(self, &Dtool_" << ClassName << ", (void **)&local_this);\n"; + out << " if (local_this == nullptr) {\n"; + out << " return 0;\n"; + out << " }\n\n"; + + // Only participate in cycle detection if there are no C++ + // references to this object. + out << " if (local_this->get_ref_count() != (int)((Dtool_PyInstDef *)self)->_memory_rules) {\n"; + out << " return 0;\n"; + out << " }\n\n"; + + if (py_subclassable) { + // Python-subclassable types store a reference to their Python + // wrapper. + if (struct_type->is_final()) { + out << " if (Py_TYPE(self) != &Dtool_" << ClassName << "._PyType) {\n"; + } else { + out << " if (Py_TYPE(self) != &Dtool_" << ClassName << "._PyType && DtoolInstance_TYPE(self) == &Dtool_" << ClassName << ") {\n"; + } + out << " Py_VISIT(self);\n"; + out << " }\n"; } vector_string params((int)remap->_has_this); params.push_back("visit"); params.push_back("arg"); - out << " return " << remap->call_function(out, 2, false, container, params) << ";\n"; + out << " return " << remap->call_function(out, 2, false, "local_this", params) << ";\n"; out << "}\n\n"; } break; @@ -2608,15 +2777,10 @@ write_module_class(ostream &out, Object *obj) { out << " }\n\n"; string expected_params; - write_function_forset(out, def._remaps, 1, 1, expected_params, 2, true, true, - AT_single_arg, RF_compare, false, true); - - out << " if (!PyErr_Occurred()) {\n"; - out << " Dtool_Raise_BadArgumentsError(\n"; - output_quoted(out, 6, expected_params); - out << ");\n"; - out << " }\n"; - out << " return -1;\n"; + if (!write_function_forset(out, def._remaps, 1, 1, expected_params, 2, true, true, + AT_single_arg, RF_compare, false, true)) { + error_bad_args_return(out, 2, RF_int, expected_params); + } out << "}\n\n"; } break; @@ -2782,10 +2946,10 @@ write_module_class(ostream &out, Object *obj) { out << " {\n"; string expected_params; - write_function_forset(out, remaps, 1, 1, expected_params, 6, true, false, - AT_single_arg, RF_pyobject | RF_err_null, false); - - out << " break;\n"; + if (!write_function_forset(out, remaps, 1, 1, expected_params, 6, true, false, + AT_single_arg, RF_pyobject | RF_err_null, false)) { + out << " break;\n"; + } out << " }\n"; } @@ -2818,10 +2982,10 @@ write_module_class(ostream &out, Object *obj) { out << " {\n"; string expected_params; - write_function_forset(out, remaps, 1, 1, expected_params, 6, true, false, - AT_single_arg, RF_pyobject | RF_invert_bool | RF_err_null, false); - - out << " break;\n"; + if (!write_function_forset(out, remaps, 1, 1, expected_params, 6, true, false, + AT_single_arg, RF_pyobject | RF_invert_bool | RF_err_null, false)) { + out << " break;\n"; + } out << " }\n"; } } @@ -2878,11 +3042,60 @@ write_module_class(ostream &out, Object *obj) { has_local_richcompare = true; } - out << " Py_INCREF(Py_NotImplemented);\n"; - out << " return Py_NotImplemented;\n"; + out << " return Py_NewRef(Py_NotImplemented);\n"; out << "}\n\n"; } + bool has_gc = (slots.count("tp_traverse") || has_self_member(struct_type)); + bool has_local_traverse = false; + bool has_local_clear = false; + if (py_subclassable || has_gc) { + // Note that in the case of py_subclassable, the traverse function will + // only be called if the class is subclassed from Python, since we don't + // set Py_TPFLAGS_HAVE_GC, so we don't need to check whether it's a proxy. + if (!slots.count("tp_traverse")) { + has_local_traverse = true; + out << "static int Dtool_Traverse_" << ClassName << "(PyObject *self, visitproc visit, void *arg) {\n"; + out << " // If the only reference remaining is the one held by the Python wrapper,\n"; + out << " // report the circular reference to Python's GC, so that it can break it.\n"; + out << " " << cClassName << " *local_this = nullptr;\n"; + out << " if (!Dtool_Call_ExtractThisPointer(self, Dtool_" << ClassName << ", (void **)&local_this)) {\n"; + out << " return -1;\n"; + out << " }\n"; + out << " if (local_this->get_ref_count() == (int)((Dtool_PyInstDef *)self)->_memory_rules) {\n"; + if (py_subclassable) { + out << " Py_VISIT(self);\n"; + } + if (has_self_member(struct_type)) { + out << " Py_VISIT(local_this->__self__);\n"; + } + out << " }\n"; + out << " return 0;\n"; + out << "}\n"; + out << "\n"; + } + + if (!slots.count("tp_clear")) { + has_local_clear = true; + out << "static int Dtool_Clear_" << ClassName << "(PyObject *self) {\n"; + if (has_self_member(struct_type)) { + out << " Py_CLEAR(local_this->__self__);\n"; + } + if (py_subclassable) { + if (struct_type->is_final()) { + out << " if (Py_TYPE(self) != &Dtool_" << ClassName << "._PyType) {\n"; + } else { + out << " if (Py_TYPE(self) != &Dtool_" << ClassName << "._PyType && DtoolInstance_TYPE(self) == &Dtool_" << ClassName << ") {\n"; + } + out << " DtoolProxy_" << ClassName << " *proxy = (DtoolProxy_" << ClassName << " *)DtoolInstance_VOID_PTR(self);\n"; + out << " Py_CLEAR(proxy->DtoolProxy::_self);\n"; + out << " }\n"; + } + out << " return 0;\n"; + out << "}\n\n"; + } + } + int num_getset = 0; if (obj->_properties.size() > 0) { @@ -3173,7 +3386,7 @@ write_module_class(ostream &out, Object *obj) { } string gcflag; - if (obj->_protocol_types & Object::PT_python_gc) { + if (has_gc && slots.count("tp_traverse")) { gcflag = " | Py_TPFLAGS_HAVE_GC"; } @@ -3201,12 +3414,22 @@ write_module_class(ostream &out, Object *obj) { } // traverseproc tp_traverse; - out << " nullptr, // tp_traverse\n"; - //write_function_slot(out, 4, slots, "tp_traverse"); + if (has_local_traverse) { + out << " &Dtool_Traverse_" << ClassName << ",\n"; + } else if (has_gc) { + write_function_slot(out, 4, slots, "tp_traverse"); + } else { + out << " nullptr, // tp_traverse\n"; + } // inquiry tp_clear; - out << " nullptr, // tp_clear\n"; - //write_function_slot(out, 4, slots, "tp_clear"); + if (has_local_clear) { + out << " &Dtool_Clear_" << ClassName << ",\n"; + } else if (has_gc) { + write_function_slot(out, 4, slots, "tp_clear"); + } else { + out << " nullptr, // tp_clear\n"; + } // richcmpfunc tp_richcompare; if (has_local_richcompare) { @@ -3259,7 +3482,7 @@ write_module_class(ostream &out, Object *obj) { // newfunc tp_new; write_function_slot(out, 4, slots, "tp_new", "Dtool_new_" + ClassName); // freefunc tp_free; - if (obj->_protocol_types & Object::PT_python_gc) { + if (slots.count("tp_traverse") || has_self_member(struct_type)) { out << " PyObject_GC_Del,\n"; } else { out << " PyObject_Del,\n"; @@ -3299,9 +3522,9 @@ write_module_class(ostream &out, Object *obj) { out << " Dtool_UpcastInterface_" << ClassName << ",\n"; out << " Dtool_Wrap_" << ClassName << ",\n"; - int has_coerce = has_coerce_constructor(obj->_itype._cpptype->as_struct_type()); + int has_coerce = has_coerce_constructor(struct_type); if (has_coerce > 0) { - if (TypeManager::is_reference_count(obj->_itype._cpptype)) { + if (TypeManager::is_reference_count(struct_type)) { out << " (CoerceFunction)Dtool_ConstCoerce_" << ClassName << ",\n"; if (has_coerce > 1) { out << " (CoerceFunction)Dtool_Coerce_" << ClassName << ",\n"; @@ -3932,17 +4155,24 @@ write_function_for_name(ostream &out, Object *obj, } } + bool always_returns; if (strip_keyword_args) { // None of the remaps take any keyword arguments, so let's check that // we take none. This saves some checks later on. indent(out, 4) << "if (kwds == nullptr || PyDict_GET_SIZE(kwds) == 0) {\n"; - if (min_args == 1 && min_args == 1) { + if (min_args == 1 && max_args == 1) { indent(out, 4) << " PyObject *arg = PyTuple_GET_ITEM(args, 0);\n"; - write_function_forset(out, mii->second, min_args, max_args, expected_params, 6, - coercion_allowed, true, AT_single_arg, return_flags, true, !all_nonconst); + always_returns = write_function_forset(out, mii->second, min_args, + max_args, expected_params, 6, + coercion_allowed, true, + AT_single_arg, return_flags, + true, !all_nonconst); } else { - write_function_forset(out, mii->second, min_args, max_args, expected_params, 6, - coercion_allowed, true, AT_varargs, return_flags, true, !all_nonconst); + always_returns = write_function_forset(out, mii->second, min_args, + max_args, expected_params, 6, + coercion_allowed, true, + AT_varargs, return_flags, + true, !all_nonconst); } } else if (min_args == 1 && max_args == 1 && args_type == AT_varargs) { // We already checked that the args tuple has only one argument, so @@ -3950,16 +4180,23 @@ write_function_for_name(ostream &out, Object *obj, indent(out, 4) << "{\n"; indent(out, 4) << " PyObject *arg = PyTuple_GET_ITEM(args, 0);\n"; - write_function_forset(out, mii->second, min_args, max_args, expected_params, 6, - coercion_allowed, true, AT_single_arg, return_flags, true, !all_nonconst); + always_returns = write_function_forset(out, mii->second, min_args, + max_args, expected_params, 6, + coercion_allowed, true, + AT_single_arg, return_flags, + true, !all_nonconst); } else { indent(out, 4) << "{\n"; - write_function_forset(out, mii->second, min_args, max_args, expected_params, 6, - coercion_allowed, true, args_type, return_flags, true, !all_nonconst); + always_returns = write_function_forset(out, mii->second, min_args, + max_args, expected_params, 6, + coercion_allowed, true, args_type, + return_flags, true, !all_nonconst); } indent(out, 4) << "}\n"; - indent(out, 4) << "break;\n"; + if (!always_returns) { + indent(out, 4) << "break;\n"; + } } // In NDEBUG case, fall through to the error at end of function. @@ -3999,17 +4236,7 @@ write_function_for_name(ostream &out, Object *obj, out << "#endif\n"; indent(out, 2) << "}\n"; - out << " if (!PyErr_Occurred()) {\n" - << " "; - if ((return_flags & ~RF_pyobject) == RF_err_null) { - out << "return "; - } - out << "Dtool_Raise_BadArgumentsError(\n"; - output_quoted(out, 6, expected_params); - out << ");\n" - << " }\n"; - - error_return(out, 2, return_flags); + error_bad_args_return(out, 2, return_flags, expected_params); } else { mii = map_sets.begin(); @@ -4070,24 +4297,10 @@ write_function_for_name(ostream &out, Object *obj, } int min_args = min(max_required_args, mii->first); - write_function_forset(out, mii->second, min_args, mii->first, expected_params, 2, - coercion_allowed, true, args_type, return_flags, true, !all_nonconst); - - // This block is often unreachable for many functions... maybe we can - // figure out a way in the future to better determine when it will be and - // won't be necessary to write this out. - if (args_type != AT_no_args) { - out << " if (!PyErr_Occurred()) {\n" - << " "; - if ((return_flags & ~RF_pyobject) == RF_err_null) { - out << "return "; - } - out << "Dtool_Raise_BadArgumentsError(\n"; - output_quoted(out, 6, expected_params); - out << ");\n" - << " }\n"; - - error_return(out, 2, return_flags); + if (!write_function_forset(out, mii->second, min_args, mii->first, + expected_params, 2, coercion_allowed, true, + args_type, return_flags, true, !all_nonconst)) { + error_bad_args_return(out, 2, return_flags, expected_params); } } @@ -4290,10 +4503,11 @@ write_coerce_constructor(ostream &out, Object *obj, bool is_const) { } indent(out, 6) << "case " << max_args << ": {\n"; - write_function_forset(out, mii->second, min_args, max_args, expected_params, 8, false, false, - AT_varargs, return_flags, true, false); - - indent(out, 8) << "break;\n"; + if (!write_function_forset(out, mii->second, min_args, max_args, + expected_params, 8, false, false, + AT_varargs, return_flags, true, false)) { + indent(out, 8) << "break;\n"; + } indent(out, 6) << "}\n"; } indent(out, 4) << "}\n"; @@ -4540,7 +4754,7 @@ bool RemapCompareLess(FunctionRemap *in1, FunctionRemap *in2) { * first parameter. This is a special-case hack for one of the slot * functions. */ -void InterfaceMakerPythonNative:: +bool InterfaceMakerPythonNative:: write_function_forset(ostream &out, const std::set &remapsin, int min_num_args, int max_num_args, @@ -4551,13 +4765,14 @@ write_function_forset(ostream &out, const string &first_pexpr) { if (remapsin.empty()) { - return; + return false; } FunctionRemap *remap = nullptr; std::set::iterator sii; bool all_nonconst = false; + bool always_returns = true; if (verify_const) { // Check if all of the remaps are non-const. If so, we only have to check @@ -4613,6 +4828,7 @@ write_function_forset(ostream &out, indent(out, indent_level) << "if (Dtool_ExtractArg(&arg, args, kwds, \"" << first_param_name << "\")) {\n"; indent_level += 2; args_type = AT_single_arg; + always_returns = false; } if (remapsin.size() > 1) { @@ -4624,6 +4840,7 @@ write_function_forset(ostream &out, std::vector::const_iterator sii; int num_coercion_possible = 0; + bool caught_all = false; sii = remaps.begin(); while (sii != remaps.end()) { remap = *(sii++); @@ -4638,7 +4855,16 @@ write_function_forset(ostream &out, } } - if (verify_const && (remap->_has_this && !remap->_const_method)) { + if (caught_all) { + indent(out, indent_level) + << " // [DCE] -2 \n"; + remap->write_orig_prototype(out, 0, false, (max_num_args - min_num_args)); + out << "\n"; + continue; + } + + bool remap_verify_const = verify_const && (remap->_has_this && !remap->_const_method); + if (remap_verify_const) { // If it's a non-const method, we only allow a non-const this. indent(out, indent_level) << "if (!DtoolInstance_IS_CONST(self)) {\n"; @@ -4654,17 +4880,23 @@ write_function_forset(ostream &out, // NB. We don't pass on report_errors here because we want it to // silently drop down to the next overload. - write_function_instance(out, remap, min_num_args, max_num_args, - expected_params, indent_level + 2, - false, false, args_type, return_flags, - check_exceptions, first_pexpr); + if (write_function_instance(out, remap, min_num_args, max_num_args, + expected_params, indent_level + 2, + false, false, args_type, return_flags, + check_exceptions, first_pexpr)) { + // The rest of the overloads are dead code. + if (!remap_verify_const) { + caught_all = true; + //indent(out, indent_level) << " // caught all cases here\n"; + } + } indent(out, indent_level) << "}\n\n"; } // Go through one more time, but allow coercion this time. - if (coercion_allowed) { - for (sii = remaps.begin(); sii != remaps.end(); sii ++) { + if (coercion_allowed && !caught_all) { + for (sii = remaps.begin(); sii != remaps.end(); ++sii) { remap = (*sii); if (!is_remap_coercion_possible(remap)) { indent(out, indent_level) @@ -4674,7 +4906,16 @@ write_function_forset(ostream &out, continue; } - if (verify_const && (remap->_has_this && !remap->_const_method)) { + if (caught_all) { + indent(out, indent_level) + << " // [DCE] -2 \n"; + remap->write_orig_prototype(out, 0, false, (max_num_args - min_num_args)); + out << "\n"; + continue; + } + + bool remap_verify_const = verify_const && (remap->_has_this && !remap->_const_method); + if (remap_verify_const) { indent(out, indent_level) << "if (!DtoolInstance_IS_CONST(self)) {\n"; } else { @@ -4687,14 +4928,24 @@ write_function_forset(ostream &out, out << "\n"; string ignore_expected_params; - write_function_instance(out, remap, min_num_args, max_num_args, - ignore_expected_params, indent_level + 2, - true, false, args_type, return_flags, - check_exceptions, first_pexpr); + if (write_function_instance(out, remap, min_num_args, max_num_args, + ignore_expected_params, indent_level + 2, + true, false, args_type, return_flags, + check_exceptions, first_pexpr)) { + // The rest of the overloads are dead code. + if (!remap_verify_const) { + caught_all = true; + //indent(out, indent_level) << " // caught all cases here\n"; + } + } indent(out, indent_level) << "}\n\n"; } } + + if (!caught_all) { + always_returns = false; + } } else { // There is only one possible overload with this number of parameters. // Just call it. @@ -4706,11 +4957,13 @@ write_function_forset(ostream &out, remap->write_orig_prototype(out, 0, false, (max_num_args - min_num_args)); out << "\n"; - write_function_instance(out, remap, min_num_args, max_num_args, - expected_params, indent_level, - coercion_allowed, report_errors, - args_type, return_flags, - check_exceptions, first_pexpr); + if (!write_function_instance(out, remap, min_num_args, max_num_args, + expected_params, indent_level, + coercion_allowed, report_errors, + args_type, return_flags, + check_exceptions, first_pexpr)) { + always_returns = false; + } } // Close the brace we opened earlier. @@ -4739,10 +4992,14 @@ write_function_forset(ostream &out, out << "#else\n"; error_raise_return(out, indent_level, return_flags, "TypeError", msg.str()); out << "#endif\n"; + } else { + always_returns = false; } indent_level -= 2; indent(out, indent_level) << "}\n"; } + + return always_returns; } /** @@ -4769,8 +5026,11 @@ write_function_forset(ostream &out, * If first_pexpr is not empty, it represents the preconverted value of the * first parameter. This is a special-case hack for one of the slot * functions. + * + * Returns true if the function returns unconditionally, false if it may fall + * through and additional error handling code is needed. */ -void InterfaceMakerPythonNative:: +bool InterfaceMakerPythonNative:: write_function_instance(ostream &out, FunctionRemap *remap, int min_num_args, int max_num_args, string &expected_params, int indent_level, @@ -4827,7 +5087,7 @@ write_function_instance(ostream &out, FunctionRemap *remap, --max_num_args; } } - nassertv(num_params <= (int)remap->_parameters.size()); + nassertr(num_params <= (int)remap->_parameters.size(), false); } bool only_pyobjects = true; @@ -4938,7 +5198,7 @@ write_function_instance(ostream &out, FunctionRemap *remap, // We should only ever have to consider optional arguments for functions // taking a variable number of arguments. - nassertv(args_type == AT_varargs || args_type == AT_keyword_args); + nassertr(args_type == AT_varargs || args_type == AT_keyword_args, false); } string reported_name = remap->_parameters[pn]._name; @@ -6135,8 +6395,12 @@ write_function_instance(ostream &out, FunctionRemap *remap, indent_level += 2; } - if (is_constructor && !remap->_has_this && - (remap->_flags & FunctionRemap::F_explicit_self) != 0) { + bool init_self_member = is_constructor && + (return_flags & RF_coerced) == 0 && + has_self_member(remap->_cpptype->as_struct_type()); + + if (init_self_member || (is_constructor && !remap->_has_this && + (remap->_flags & FunctionRemap::F_explicit_self) != 0)) { // If we'll be passing "self" to the constructor, we need to pre- // initialize it here. Unfortunately, we can't pre-load the "this" // pointer, but the constructor itself can do this. @@ -6216,13 +6480,54 @@ write_function_instance(ostream &out, FunctionRemap *remap, } return_expr = "&coerced"; + } else if (is_constructor && (return_flags & RF_coerced) == 0 && + is_python_subclassable(remap->_cpptype->as_struct_type())) { + // Add special code to detect whether we're trying to create a subclass + // of this object. If so, create a proxy instance instead. + CPPType *orig_type = remap->_return_type->get_orig_type(); + TypeIndex type_index = builder.get_type(TypeManager::unwrap(TypeManager::resolve_type(orig_type)), false); + const InterrogateType &itype = idb->get_type(type_index); + std::string safe_name = make_safe_name(itype.get_scoped_name()); + + CPPType *type = remap->_return_type->get_temporary_type(); + type->output_instance(indent(out, indent_level), "return_value", &parser); + out << ";\n"; + + indent(out, indent_level) + << "if (Py_TYPE(self) != &Dtool_" << safe_name << "._PyType) {\n"; + indent(out, indent_level) + << " DtoolProxy_" << safe_name << " *proxy = new DtoolProxy_" << safe_name << "("; + remap->write_call_args(out, pexprs); + out << ");\n"; + indent(out, indent_level) + << " DtoolProxy_Init(proxy, self, Dtool_" << safe_name << ", &Dtool_WrapProxy_" << safe_name << ");\n"; + indent(out, indent_level) + << " return_value = proxy;\n"; + indent(out, indent_level) + << "} else {\n"; + + return_expr = remap->call_function(out, indent_level, true, container, pexprs); + indent(out, indent_level) + << " return_value = " << return_expr << ";\n"; + indent(out, indent_level) + << "}\n"; + + return_expr = "return_value"; + manage_return = true; + } else { // The general case; an ordinary constructor or function. return_expr = remap->call_function(out, indent_level, true, container, pexprs); - if (return_flags & RF_self) { - // We won't be using the return value, anyway. - return_expr.clear(); + if ((return_flags & RF_self) != 0) { + if (TypeManager::is_pointer_to_PyObject(remap->_return_type->get_orig_type())) { + // If the function returns a PyObject *, let it override the default + // behavior of returning self. + return_flags = (return_flags & ~RF_self) | RF_pyobject; + } else { + // We won't be using the return value, anyway. + return_expr.clear(); + } } if (!return_expr.empty()) { @@ -6269,8 +6574,13 @@ write_function_instance(ostream &out, FunctionRemap *remap, indent(out, indent_level) << "}\n"; } + if (init_self_member) { + indent(out, indent_level) + << "return_value->__self__ = Py_NewRef(self);\n"; + } + if (TypeManager::is_pointer_to_PyObject(remap->_return_type->get_orig_type())) { - indent(out, indent_level) << "Py_XINCREF(return_value);\n"; + return_expr = "Py_XNewRef(return_value)"; } else { return_expr = manage_return_value(out, indent_level, remap, "return_value"); } @@ -6461,8 +6771,7 @@ write_function_instance(ostream &out, FunctionRemap *remap, } } else if (return_flags & RF_self) { - indent(out, indent_level) << "Py_INCREF(self);\n"; - indent(out, indent_level) << "return self;\n"; + indent(out, indent_level) << "return Py_NewRef(self);\n"; } else if (return_flags & RF_richcompare_zero) { indent(out, indent_level) @@ -6470,8 +6779,7 @@ write_function_instance(ostream &out, FunctionRemap *remap, } else if (return_flags & RF_pyobject) { if (return_expr.empty()) { - indent(out, indent_level) << "Py_INCREF(Py_None);\n"; - indent(out, indent_level) << "return Py_None;\n"; + indent(out, indent_level) << "return Py_NewRef(Py_None);\n"; } else if (return_flags & RF_preserve_null) { indent(out, indent_level) << "if (" << return_expr << " == nullptr) {\n"; @@ -6546,12 +6854,18 @@ write_function_instance(ostream &out, FunctionRemap *remap, indent(out, indent_level) << "}\n"; } - // Close the extra braces opened earlier. - while (open_scopes > 0) { - indent_level -= 2; - indent(out, indent_level) << "}\n"; + // If we were in a scope + bool always_returns = true; + if (open_scopes > 0) { + always_returns = false; - --open_scopes; + // Close the extra braces opened earlier. + while (open_scopes > 0) { + indent_level -= 2; + indent(out, indent_level) << "}\n"; + + --open_scopes; + } } if (clear_error && !report_errors) { @@ -6563,7 +6877,10 @@ write_function_instance(ostream &out, FunctionRemap *remap, if (min_version > 0) { // Close the #if PY_VERSION_HEX check. out << "#endif\n"; + always_returns = false; } + + return always_returns; } /** @@ -6583,8 +6900,55 @@ error_return(ostream &out, int indent_level, int return_flags) { indent(out, indent_level) << "return -1;\n"; } else if (return_flags & RF_err_notimplemented) { - indent(out, indent_level) << "Py_INCREF(Py_NotImplemented);\n"; - indent(out, indent_level) << "return Py_NotImplemented;\n"; + indent(out, indent_level) << "return Py_NewRef(Py_NotImplemented);\n"; + + } else if (return_flags & RF_err_null) { + indent(out, indent_level) << "return nullptr;\n"; + + } else if (return_flags & RF_err_false) { + indent(out, indent_level) << "return false;\n"; + } +} + +/** + * Similar to error_return, except raises a "bad arguments" error before + * returning, if the error indicator has not yet been set. + */ +void InterfaceMakerPythonNative:: +error_bad_args_return(ostream &out, int indent_level, int return_flags, + const string &expected_params) { + + if (return_flags & RF_decref_args) { + indent(out, indent_level) << "Py_DECREF(args);\n"; + } + + if ((return_flags & RF_err_null) != 0 && + (return_flags & RF_pyobject) != 0) { + // It always returns nullptr, so we'll allow the compiler to do a tail + // call optimization. + indent(out, indent_level) << "return Dtool_Raise_BadArgumentsError(\n"; + output_quoted(out, indent_level + 2, expected_params); + out << ");\n"; + return; + } + + if (return_flags & RF_int) { + // Same, but for -1. + indent(out, indent_level) << "return Dtool_Raise_BadArgumentsError_Int(\n"; + output_quoted(out, indent_level + 2, expected_params); + out << ");\n"; + return; + } + + indent(out, indent_level) << "Dtool_Raise_BadArgumentsError(\n"; + output_quoted(out, indent_level + 2, expected_params); + out << ");\n"; + + if (return_flags & RF_int) { + indent(out, indent_level) << "return -1;\n"; + + } else if (return_flags & RF_err_notimplemented) { + indent(out, indent_level) << "return Py_NewRef(Py_NotImplemented);\n"; } else if (return_flags & RF_err_null) { indent(out, indent_level) << "return nullptr;\n"; @@ -6906,8 +7270,7 @@ write_getset(ostream &out, Object *obj, Property *property) { /*if (property->_has_function != NULL) { out << " if (!local_this->" << property->_has_function->_ifunc.get_name() << "(index)) {\n" - << " Py_INCREF(Py_None);\n" - << " return Py_None;\n" + << " return Py_NewRef(Py_None);\n" << " }\n"; }*/ @@ -6924,15 +7287,11 @@ write_getset(ostream &out, Object *obj, Property *property) { } string expected_params; - write_function_forset(out, remaps, 1, 1, expected_params, 2, true, true, - AT_no_args, RF_pyobject | RF_err_null, false, true, "index"); - - out << " if (!PyErr_Occurred()) {\n"; - out << " return Dtool_Raise_BadArgumentsError(\n"; - output_quoted(out, 6, expected_params); - out << ");\n" - " }\n" - "}\n\n"; + if (!write_function_forset(out, remaps, 1, 1, expected_params, 2, true, true, + AT_no_args, RF_pyobject | RF_err_null, false, true, "index")) { + error_bad_args_return(out, 2, RF_pyobject | RF_err_null, expected_params); + } + out << "}\n\n"; // Write out a setitem if this is not a read-only property. if (!property->_setter_remaps.empty()) { @@ -6997,16 +7356,10 @@ write_getset(ostream &out, Object *obj, Property *property) { } string expected_params; - write_function_forset(out, remaps, 2, 2, - expected_params, 2, true, true, AT_single_arg, - RF_int, false, false, "index"); - - out << " if (!PyErr_Occurred()) {\n"; - out << " Dtool_Raise_BadArgumentsError(\n"; - output_quoted(out, 6, expected_params); - out << ");\n"; - out << " }\n"; - out << " return -1;\n"; + if (!write_function_forset(out, remaps, 2, 2, expected_params, 2, true, + true, AT_single_arg, RF_int, false, false, "index")) { + error_bad_args_return(out, 2, RF_int, expected_params); + } out << "}\n\n"; } @@ -7026,16 +7379,11 @@ write_getset(ostream &out, Object *obj, Property *property) { property->_inserter->_remaps.end()); string expected_params; - write_function_forset(out, remaps, 2, 2, - expected_params, 2, true, true, AT_single_arg, - RF_pyobject | RF_err_null, false, false, "index"); - - out << " if (!PyErr_Occurred()) {\n"; - out << " Dtool_Raise_BadArgumentsError(\n"; - output_quoted(out, 6, expected_params); - out << ");\n"; - out << " }\n"; - out << " return nullptr;\n"; + if (!write_function_forset(out, remaps, 2, 2, expected_params, 2, true, + true, AT_single_arg, RF_pyobject | RF_err_null, + false, false, "index")) { + error_bad_args_return(out, 2, RF_pyobject | RF_err_null, expected_params); + } out << "}\n\n"; } } @@ -7095,16 +7443,11 @@ write_getset(ostream &out, Object *obj, Property *property) { } string expected_params; - write_function_forset(out, remaps, 1, 1, expected_params, 2, true, true, - AT_single_arg, RF_pyobject | RF_err_null, false, true); - - out << " if (!PyErr_Occurred()) {\n"; - out << " return Dtool_Raise_BadArgumentsError(\n"; - output_quoted(out, 6, expected_params); - out << ");\n" - " }\n" - " return nullptr;\n" - "}\n\n"; + if (!write_function_forset(out, remaps, 1, 1, expected_params, 2, true, true, + AT_single_arg, RF_pyobject | RF_err_null, false, true)) { + error_bad_args_return(out, 2, RF_pyobject | RF_err_null, expected_params); + } + out << "}\n\n"; // Write out a setitem if this is not a read-only property. if (!property->_setter_remaps.empty()) { @@ -7144,10 +7487,11 @@ write_getset(ostream &out, Object *obj, Property *property) { property->_deleter->_remaps.end()); string expected_params; - write_function_forset(out, remaps, 1, 1, - expected_params, 4, true, true, AT_single_arg, - RF_int, false, false); - out << " return -1;\n"; + if (!write_function_forset(out, remaps, 1, 1, + expected_params, 4, true, true, AT_single_arg, + RF_int, false, false)) { + out << " return -1;\n"; + } } else { out << "#ifdef NDEBUG\n" " Dtool_Raise_TypeError(\"can't delete attribute\");\n" @@ -7171,23 +7515,15 @@ write_getset(ostream &out, Object *obj, Property *property) { // We have to create an args tuple only to unpack it later, ugh. out << " PyObject *args = PyTuple_New(2);\n" - << " PyTuple_SET_ITEM(args, 0, key);\n" - << " PyTuple_SET_ITEM(args, 1, value);\n" - << " Py_INCREF(key);\n" - << " Py_INCREF(value);\n"; + << " PyTuple_SET_ITEM(args, 0, Py_NewRef(key));\n" + << " PyTuple_SET_ITEM(args, 1, Py_NewRef(value));\n"; string expected_params; - write_function_forset(out, remaps, 2, 2, - expected_params, 2, true, true, AT_varargs, - RF_int | RF_decref_args, false, false); - - out << " if (!PyErr_Occurred()) {\n"; - out << " Dtool_Raise_BadArgumentsError(\n"; - output_quoted(out, 6, expected_params); - out << ");\n"; - out << " }\n"; - out << " Py_DECREF(args);\n"; - out << " return -1;\n"; + if (!write_function_forset(out, remaps, 2, 2, + expected_params, 2, true, true, AT_varargs, + RF_int | RF_decref_args, false, false)) { + error_bad_args_return(out, 2, RF_int | RF_decref_args, expected_params); + } out << "}\n\n"; } @@ -7232,15 +7568,11 @@ write_getset(ostream &out, Object *obj, Property *property) { } string expected_params; - write_function_forset(out, remaps, 1, 1, expected_params, 2, true, true, - AT_no_args, RF_pyobject | RF_err_null, false, true, "index"); - - out << " if (!PyErr_Occurred()) {\n"; - out << " return Dtool_Raise_BadArgumentsError(\n"; - output_quoted(out, 6, expected_params); - out << ");\n" - " }\n" - "}\n\n"; + if (!write_function_forset(out, remaps, 1, 1, expected_params, 2, true, true, + AT_no_args, RF_pyobject | RF_err_null, false, true, "index")) { + error_bad_args_return(out, 2, RF_pyobject | RF_err_null, expected_params); + } + out << "}\n\n"; } } @@ -7367,8 +7699,7 @@ write_getset(ostream &out, Object *obj, Property *property) { } else { out << " if (!" << cClassName << "::" << property->_has_function->_ifunc.get_name() << "()) {\n"; } - out << " Py_INCREF(Py_None);\n" - << " return Py_None;\n" + out << " return Py_NewRef(Py_None);\n" << " }\n"; } @@ -7432,16 +7763,10 @@ write_getset(ostream &out, Object *obj, Property *property) { } string expected_params; - write_function_forset(out, remaps, 1, 1, - expected_params, 2, true, true, AT_single_arg, - RF_int, false, false); - - out << " if (!PyErr_Occurred()) {\n"; - out << " Dtool_Raise_BadArgumentsError(\n"; - output_quoted(out, 6, expected_params); - out << ");\n"; - out << " }\n"; - out << " return -1;\n"; + if (!write_function_forset(out, remaps, 1, 1, expected_params, 2, true, + true, AT_single_arg, RF_int, false, false)) { + error_bad_args_return(out, 2, RF_int, expected_params); + } out << "}\n\n"; } } @@ -8018,6 +8343,53 @@ IsRunTimeTyped(const InterrogateType &itype) { return false; } +/** + * Returns true if this object has special support for inheriting from Python. + */ +bool InterfaceMakerPythonNative:: +is_python_subclassable(CPPStructType *struct_type) { + if (struct_type != nullptr && !struct_type->is_final() && + IsPandaTypedObject(struct_type) && + TypeManager::is_reference_count(struct_type)) { + + // Make sure the type has a published constructor. + TypeIndex type_index = builder.get_type(struct_type, false); + if (type_index != 0) { + Objects::iterator oi = _objects.find(type_index); + if (oi != _objects.end()) { + Object *obj = (*oi).second; + return !obj->_constructors.empty(); + } + } + } + return false; +} + +/** + * Returns true if the type has a public member named __self__. + */ +bool InterfaceMakerPythonNative:: +has_self_member(CPPStructType *struct_type) { + if (struct_type == nullptr) { + return false; + } + + CPPScope *scope = struct_type->get_scope(); + if (scope != nullptr && scope->_variables.count("__self__")) { + return true; + } + + for (const CPPStructType::Base &base : struct_type->_derivation) { + if (base._base != nullptr) { + CPPStructType *base_type = base._base->as_struct_type(); + if (base_type != nullptr && has_self_member(base_type)) { + return true; + } + } + } + return false; +} + /** */ diff --git a/dtool/src/interrogate/interfaceMakerPythonNative.h b/dtool/src/interrogate/interfaceMakerPythonNative.h index 348d855d01..aec04a6652 100644 --- a/dtool/src/interrogate/interfaceMakerPythonNative.h +++ b/dtool/src/interrogate/interfaceMakerPythonNative.h @@ -155,7 +155,7 @@ private: int collapse_default_remaps(std::map > &map_sets, int max_required_args); - void write_function_forset(std::ostream &out, + bool write_function_forset(std::ostream &out, const std::set &remaps, int min_num_args, int max_num_args, std::string &expected_params, int indent_level, @@ -165,7 +165,7 @@ private: bool verify_const = true, const std::string &first_expr = std::string()); - void write_function_instance(std::ostream &out, FunctionRemap *remap, + bool write_function_instance(std::ostream &out, FunctionRemap *remap, int min_num_args, int max_num_args, std::string &expected_params, int indent_level, bool coercion_allowed, bool report_errors, @@ -174,6 +174,8 @@ private: const std::string &first_pexpr = std::string()); void error_return(std::ostream &out, int indent_level, int return_flags); + void error_bad_args_return(std::ostream &out, int indent_level, int return_flags, + const std::string &expected_params); void error_raise_return(std::ostream &out, int indent_level, int return_flags, const std::string &exc_type, const std::string &message, const std::string &format_args = ""); @@ -198,6 +200,8 @@ public: bool isExportThisRun(Function *func); bool isFunctionWithThis( Function *func); bool IsRunTimeTyped(const InterrogateType &itype); + bool is_python_subclassable(CPPStructType *type); + bool has_self_member(CPPStructType *type); // comunicates the cast capabilites among methods.. struct CastDetails { diff --git a/dtool/src/interrogate/interrogate.cxx b/dtool/src/interrogate/interrogate.cxx index 942eb905f5..d0c2bc96d4 100644 --- a/dtool/src/interrogate/interrogate.cxx +++ b/dtool/src/interrogate/interrogate.cxx @@ -302,7 +302,7 @@ predefine_macro(CPPParser& parser, const string& inoption) { macro_name = inoption; } - CPPManifest *macro = new CPPManifest(macro_name, macro_def); + CPPManifest *macro = new CPPManifest(parser, macro_name, macro_def); parser._manifests[macro->_name] = macro; } diff --git a/dtool/src/interrogate/parse_file.cxx b/dtool/src/interrogate/parse_file.cxx index f1ae0632ea..0c92918c53 100644 --- a/dtool/src/interrogate/parse_file.cxx +++ b/dtool/src/interrogate/parse_file.cxx @@ -45,7 +45,7 @@ predefine_macro(CPPParser &parser, const string &option) { cerr << "Predefining " << macro_name << " as " << macro_def << "\n"; - CPPManifest *macro = new CPPManifest(macro_name, macro_def); + CPPManifest *macro = new CPPManifest(parser, macro_name, macro_def); parser._manifests[macro->_name] = macro; } @@ -208,11 +208,12 @@ int main(int argc, char **argv) { extern char *optarg; extern int optind; - const char *optstr = "I:S:D:o:l:vp"; + const char *optstr = "I:S:D:o:l:vpE"; preprocess_argv(argc, argv); parser.set_verbose(2); bool prompt = false; + bool preprocess = false; int flag = getopt(argc, argv, optstr); @@ -249,6 +250,10 @@ main(int argc, char **argv) { prompt = true; break; + case 'E': + preprocess = true; + break; + default: exit(1); } @@ -268,15 +273,23 @@ main(int argc, char **argv) { << " -D manifest_name=manifest_definition\n" << " -o output_file (ignored)\n" << " -v (increase verbosity)\n" + << " -E (output preprocessed token stream)\n" << " -p (prompt for expression instead of dumping output)\n"; exit(1); } for (int i = 1; i < argc; i++) { - if (!parser.parse_file(argv[i])) { - cerr << "Error in parsing.\n"; - exit(1); + if (preprocess) { + if (!parser.preprocess_file(argv[i])) { + cerr << "Error in preprocessing.\n"; + exit(1); + } + } else { + if (!parser.parse_file(argv[i])) { + cerr << "Error in parsing.\n"; + exit(1); + } } } diff --git a/dtool/src/interrogatedb/dtool_super_base.cxx b/dtool/src/interrogatedb/dtool_super_base.cxx index 085830a211..0b7613617e 100644 --- a/dtool/src/interrogatedb/dtool_super_base.cxx +++ b/dtool/src/interrogatedb/dtool_super_base.cxx @@ -27,15 +27,13 @@ static PyMemberDef standard_type_members[] = { static PyObject *GetSuperBase(PyObject *self) { Dtool_PyTypedObject *super_base = Dtool_GetSuperBase(); - Py_XINCREF((PyTypeObject *)super_base); // order is important .. this is used for static functions - return (PyObject *)super_base; + return Py_XNewRef((PyObject *)&super_base->_PyType); }; static void Dtool_PyModuleClassInit_DTOOL_SUPER_BASE(PyObject *module) { if (module != nullptr) { Dtool_PyTypedObject *super_base = Dtool_GetSuperBase(); - Py_INCREF((PyTypeObject *)&super_base); - PyModule_AddObject(module, "DTOOL_SUPER_BASE", (PyObject *)&super_base); + PyModule_AddObjectRef(module, "DTOOL_SUPER_BASE", (PyObject *)&super_base->_PyType); } } @@ -152,7 +150,7 @@ Dtool_PyTypedObject *Dtool_GetSuperBase() { PyErr_SetString(PyExc_TypeError, "PyType_Ready(Dtool_DTOOL_SUPER_BASE)"); return nullptr; } - Py_INCREF((PyTypeObject *)&super_base_type); + Py_INCREF(&super_base_type._PyType); PyDict_SetItemString(super_base_type._PyType.tp_dict, "DtoolGetSuperBase", PyCFunction_New(&methods[0], (PyObject *)&super_base_type)); diff --git a/dtool/src/interrogatedb/py_compat.h b/dtool/src/interrogatedb/py_compat.h index 2a340ff060..4b67fba763 100644 --- a/dtool/src/interrogatedb/py_compat.h +++ b/dtool/src/interrogatedb/py_compat.h @@ -239,6 +239,32 @@ INLINE PyObject *PyObject_CallMethodNoArgs(PyObject *obj, PyObject *name) { INLINE PyObject *PyObject_CallMethodOneArg(PyObject *obj, PyObject *name, PyObject *arg) { return PyObject_CallMethodObjArgs(obj, name, arg, nullptr); } + +INLINE int PyObject_GC_IsTracked(PyObject *obj) { + return _PyObject_GC_IS_TRACKED(obj); +} +#endif + +/* Python 3.10 */ + +#if PY_VERSION_HEX < 0x030A0000 +INLINE int PyModule_AddObjectRef(PyObject *module, const char *name, PyObject *value) { + int ret = PyModule_AddObject(module, name, value); + if (ret == 0) { + Py_INCREF(value); + } + return ret; +} + +ALWAYS_INLINE PyObject *Py_NewRef(PyObject *obj) { + Py_INCREF(obj); + return obj; +} + +ALWAYS_INLINE PyObject *Py_XNewRef(PyObject *obj) { + Py_XINCREF(obj); + return obj; +} #endif /* Python 3.12 */ diff --git a/dtool/src/interrogatedb/py_panda.I b/dtool/src/interrogatedb/py_panda.I index 9434d64617..f3cb5a1d12 100644 --- a/dtool/src/interrogatedb/py_panda.I +++ b/dtool/src/interrogatedb/py_panda.I @@ -97,8 +97,7 @@ ALWAYS_INLINE void Dtool_Assign_PyObject(PyObject *&ptr, PyObject *value) { PyObject *prev_value = ptr; if (prev_value != value) { - Py_XINCREF(value); - ptr = value; + ptr = Py_XNewRef(value); Py_XDECREF(prev_value); } } @@ -246,8 +245,7 @@ ALWAYS_INLINE PyObject *Dtool_WrapValue(unsigned long long value) { ALWAYS_INLINE PyObject *Dtool_WrapValue(bool value) { PyObject *result = (value ? Py_True : Py_False); - Py_INCREF(result); - return result; + return Py_NewRef(result); } ALWAYS_INLINE PyObject *Dtool_WrapValue(double value) { @@ -256,8 +254,7 @@ ALWAYS_INLINE PyObject *Dtool_WrapValue(double value) { ALWAYS_INLINE PyObject *Dtool_WrapValue(const char *value) { if (value == nullptr) { - Py_INCREF(Py_None); - return Py_None; + return Py_NewRef(Py_None); } else { #if PY_MAJOR_VERSION >= 3 return PyUnicode_FromString(value); @@ -269,8 +266,7 @@ ALWAYS_INLINE PyObject *Dtool_WrapValue(const char *value) { ALWAYS_INLINE PyObject *Dtool_WrapValue(const wchar_t *value) { if (value == nullptr) { - Py_INCREF(Py_None); - return Py_None; + return Py_NewRef(Py_None); } else { return PyUnicode_FromWideChar(value, (Py_ssize_t)wcslen(value)); } @@ -290,8 +286,7 @@ ALWAYS_INLINE PyObject *Dtool_WrapValue(const std::wstring &value) { ALWAYS_INLINE PyObject *Dtool_WrapValue(const std::string *value) { if (value == nullptr) { - Py_INCREF(Py_None); - return Py_None; + return Py_NewRef(Py_None); } else { #if PY_MAJOR_VERSION >= 3 return PyUnicode_FromStringAndSize(value->data(), (Py_ssize_t)value->length()); @@ -303,8 +298,7 @@ ALWAYS_INLINE PyObject *Dtool_WrapValue(const std::string *value) { ALWAYS_INLINE PyObject *Dtool_WrapValue(const std::wstring *value) { if (value == nullptr) { - Py_INCREF(Py_None); - return Py_None; + return Py_NewRef(Py_None); } else { return PyUnicode_FromWideChar(value->data(), (Py_ssize_t)value->length()); } @@ -323,8 +317,7 @@ ALWAYS_INLINE PyObject *Dtool_WrapValue(wchar_t value) { } ALWAYS_INLINE PyObject *Dtool_WrapValue(std::nullptr_t) { - Py_INCREF(Py_None); - return Py_None; + return Py_NewRef(Py_None); } ALWAYS_INLINE PyObject *Dtool_WrapValue(PyObject *value) { diff --git a/dtool/src/interrogatedb/py_panda.cxx b/dtool/src/interrogatedb/py_panda.cxx index f8c3bb194c..b691fbef48 100644 --- a/dtool/src/interrogatedb/py_panda.cxx +++ b/dtool/src/interrogatedb/py_panda.cxx @@ -218,11 +218,46 @@ PyObject *Dtool_Raise_AttributeError(PyObject *obj, const char *attribute) { * prints out a generic message, to help reduce the amount of strings in the * compiled library. * + * If there is already an exception set, does nothing. + * * Always returns NULL so that it can be conveniently used as a return * expression for wrapper functions that return a PyObject pointer. */ +PyObject *_Dtool_Raise_BadArgumentsError(const char *message) { + if (!PyErr_Occurred()) { + return PyErr_Format(PyExc_TypeError, "Arguments must match:\n%s", message); + } + return nullptr; +} + +/** + * Overload that prints a generic message instead. + */ PyObject *_Dtool_Raise_BadArgumentsError() { - return Dtool_Raise_TypeError("arguments do not match any function overload"); + if (!PyErr_Occurred()) { + PyErr_SetString(PyExc_TypeError, "arguments do not match any function overload"); + } + return nullptr; +} + +/** + * Overload that returns -1 instead of nullptr. + */ +int _Dtool_Raise_BadArgumentsError_Int(const char *message) { + if (!PyErr_Occurred()) { + PyErr_Format(PyExc_TypeError, "Arguments must match:\n%s", message); + } + return -1; +} + +/** + * Overload that returns -1 instead of nullptr and prints a generic message. + */ +int _Dtool_Raise_BadArgumentsError_Int() { + if (!PyErr_Occurred()) { + PyErr_SetString(PyExc_TypeError, "arguments do not match any function overload"); + } + return -1; } /** @@ -238,8 +273,7 @@ PyObject *_Dtool_Return_None() { return Dtool_Raise_AssertionError(); } #endif - Py_INCREF(Py_None); - return Py_None; + return Py_NewRef(Py_None); } /** @@ -255,9 +289,7 @@ PyObject *Dtool_Return_Bool(bool value) { return Dtool_Raise_AssertionError(); } #endif - PyObject *result = (value ? Py_True : Py_False); - Py_INCREF(result); - return result; + return Py_NewRef(value ? Py_True : Py_False); } /** @@ -290,8 +322,7 @@ static PyObject *Dtool_EnumType_New(PyTypeObject *subtype, PyObject *args, PyObj } if (Py_TYPE(arg) == subtype) { - Py_INCREF(arg); - return arg; + return Py_NewRef(arg); } PyObject *value2member = PyDict_GetItemString(subtype->tp_dict, "_value2member_map_"); @@ -299,8 +330,7 @@ static PyObject *Dtool_EnumType_New(PyTypeObject *subtype, PyObject *args, PyObj PyObject *member = PyDict_GetItem(value2member, arg); if (member != nullptr) { - Py_INCREF(member); - return member; + return Py_NewRef(member); } PyObject *repr = PyObject_Repr(arg); @@ -383,12 +413,10 @@ PyTypeObject *Dtool_EnumType_Create(const char *name, PyObject *names, const cha value2member_map_sunder_str = PyString_InternFromString("_value2member_map_"); #endif PyObject *name_value_tuple = PyTuple_New(4); - PyTuple_SET_ITEM(name_value_tuple, 0, name_str); - PyTuple_SET_ITEM(name_value_tuple, 1, value_str); + PyTuple_SET_ITEM(name_value_tuple, 0, Py_NewRef(name_str)); + PyTuple_SET_ITEM(name_value_tuple, 1, Py_NewRef(value_str)); PyTuple_SET_ITEM(name_value_tuple, 2, name_sunder_str); PyTuple_SET_ITEM(name_value_tuple, 3, value_sunder_str); - Py_INCREF(name_str); - Py_INCREF(value_str); PyObject *slots_dict = PyDict_New(); PyDict_SetItemString(slots_dict, "__slots__", name_value_tuple); @@ -481,8 +509,7 @@ PyObject *DTool_CreatePyInstance(void *local_this, Dtool_PyTypedObject &in_class if (local_this == nullptr) { // This is actually a very common case, so let's allow this, but return // Py_None consistently. This eliminates code in the wrappers. - Py_INCREF(Py_None); - return Py_None; + return Py_NewRef(Py_None); } Dtool_PyInstDef *self = (Dtool_PyInstDef *)PyType_GenericAlloc(&in_classdef._PyType, 0); @@ -513,6 +540,32 @@ Dtool_TypeMap *Dtool_GetGlobalTypeMap() { } } +/** + * + */ +void DtoolProxy_Init(DtoolProxy *proxy, PyObject *self, + Dtool_PyTypedObject &classdef, + TypeRegistry::PythonWrapFunc *wrap_func) { + if (proxy == nullptr) { + // Out of memory, the generated code will handle this. + return; + } + + proxy->_self = Py_NewRef(self); + PyTypeObject *cls = Py_TYPE(self); + if (cls != &classdef._PyType) { + TypeRegistry *registry = TypeRegistry::ptr(); + TypeHandle handle = registry->register_dynamic_type(cls->tp_name); + registry->record_derivation(handle, classdef._type); + //TODO unregister type when it is unloaded? weak callback? + PyTypeObject *cls_ref = (PyTypeObject *)Py_NewRef((PyObject *)cls); + registry->record_python_type(handle, cls_ref, wrap_func); + proxy->_type = handle; + } else { + proxy->_type = classdef._type; + } +} + #define PY_MAJOR_VERSION_STR #PY_MAJOR_VERSION "." #PY_MINOR_VERSION #if PY_MAJOR_VERSION >= 3 @@ -689,8 +742,7 @@ PyObject *Dtool_BorrowThisReference(PyObject *self, PyObject *args) { to->_is_const = from->_is_const; to->_ptr_to_object = from->_ptr_to_object; - Py_INCREF(Py_None); - return Py_None; + return Py_NewRef(Py_None); } return PyErr_Format(PyExc_TypeError, "types %s and %s do not match", @@ -720,8 +772,7 @@ Dtool_AddToDictionary(PyObject *self1, PyObject *args) { if (PyErr_Occurred()) { return nullptr; } - Py_INCREF(Py_None); - return Py_None; + return Py_NewRef(Py_None); } /** diff --git a/dtool/src/interrogatedb/py_panda.h b/dtool/src/interrogatedb/py_panda.h index 1c6bd4ae00..9d8fc113ff 100644 --- a/dtool/src/interrogatedb/py_panda.h +++ b/dtool/src/interrogatedb/py_panda.h @@ -182,6 +182,16 @@ typedef std::map Dtool_TypeMap; EXPCL_PYPANDA Dtool_TypeMap *Dtool_GetGlobalTypeMap(); +class DtoolProxy { +public: + mutable PyObject *_self; + TypeHandle _type; +}; + +EXPCL_PYPANDA void DtoolProxy_Init(DtoolProxy *proxy, PyObject *self, + Dtool_PyTypedObject &classdef, + TypeRegistry::PythonWrapFunc *wrap_func); + /** */ @@ -216,12 +226,17 @@ EXPCL_PYPANDA PyObject *Dtool_Raise_ArgTypeError(PyObject *obj, int param, const EXPCL_PYPANDA PyObject *Dtool_Raise_AttributeError(PyObject *obj, const char *attribute); EXPCL_PYPANDA PyObject *_Dtool_Raise_BadArgumentsError(); +EXPCL_PYPANDA PyObject *_Dtool_Raise_BadArgumentsError(const char *message); +EXPCL_PYPANDA int _Dtool_Raise_BadArgumentsError_Int(); +EXPCL_PYPANDA int _Dtool_Raise_BadArgumentsError_Int(const char *message); #ifdef NDEBUG // Define it to a function that just prints a generic message. #define Dtool_Raise_BadArgumentsError(x) _Dtool_Raise_BadArgumentsError() +#define Dtool_Raise_BadArgumentsError_Int(x) _Dtool_Raise_BadArgumentsError_Int() #else // Expand this to a TypeError listing all of the overloads. -#define Dtool_Raise_BadArgumentsError(x) Dtool_Raise_TypeError("Arguments must match:\n" x) +#define Dtool_Raise_BadArgumentsError(x) _Dtool_Raise_BadArgumentsError(x) +#define Dtool_Raise_BadArgumentsError_Int(x) _Dtool_Raise_BadArgumentsError_Int(x) #endif // These functions are similar to Dtool_WrapValue, except that they also @@ -232,7 +247,7 @@ EXPCL_PYPANDA PyObject *Dtool_Return_Bool(bool value); EXPCL_PYPANDA PyObject *_Dtool_Return(PyObject *value); #ifdef NDEBUG -#define Dtool_Return_None() (LIKELY(PyErr_Occurred() == nullptr) ? (Py_INCREF(Py_None), Py_None) : nullptr) +#define Dtool_Return_None() (LIKELY(PyErr_Occurred() == nullptr) ? (Py_NewRef(Py_None)) : nullptr) #define Dtool_Return(value) (LIKELY(PyErr_Occurred() == nullptr) ? value : nullptr) #else #define Dtool_Return_None() _Dtool_Return_None() diff --git a/dtool/src/interrogatedb/py_wrappers.cxx b/dtool/src/interrogatedb/py_wrappers.cxx index 0f41600de9..f0be01a3fb 100644 --- a/dtool/src/interrogatedb/py_wrappers.cxx +++ b/dtool/src/interrogatedb/py_wrappers.cxx @@ -243,8 +243,7 @@ static PyObject *Dtool_MutableSequenceWrapper_clear(PyObject *self, PyObject *) return nullptr; } } - Py_INCREF(Py_None); - return Py_None; + return Py_NewRef(Py_None); } /** @@ -270,8 +269,7 @@ static PyObject *Dtool_MutableSequenceWrapper_remove(PyObject *self, PyObject *v int cmp = PyObject_RichCompareBool(item, value, Py_EQ); if (cmp > 0) { if (wrap->_setitem_func(wrap->_base._self, index, nullptr) == 0) { - Py_INCREF(Py_None); - return Py_None; + return Py_NewRef(Py_None); } else { return nullptr; } @@ -405,8 +403,7 @@ static PyObject *Dtool_MutableSequenceWrapper_extend(PyObject *self, PyObject *a } Py_DECREF(iter); - Py_INCREF(Py_None); - return Py_None; + return Py_NewRef(Py_None); } /** @@ -481,8 +478,7 @@ static PyObject *Dtool_MappingWrapper_get(PyObject *self, PyObject *args) { return value; } else if (PyErr_ExceptionMatches(PyExc_KeyError)) { PyErr_Clear(); - Py_INCREF(defvalue); - return defvalue; + return Py_NewRef(defvalue); } else { return nullptr; } @@ -604,8 +600,7 @@ static PyObject *Dtool_MappingWrapper_keys(PyObject *self, PyObject *) { } (void)PyObject_INIT(keys, &wrapper_type); - Py_XINCREF(wrap->_base._self); - keys->_base._self = wrap->_base._self; + keys->_base._self = Py_XNewRef(wrap->_base._self); keys->_base._name = wrap->_base._name; keys->_keys._len_func = wrap->_keys._len_func; keys->_keys._getitem_func = wrap->_keys._getitem_func; @@ -745,8 +740,7 @@ static PyObject *Dtool_MappingWrapper_values(PyObject *self, PyObject *) { } (void)PyObject_INIT(values, &wrapper_type); - Py_XINCREF(wrap->_base._self); - values->_base._self = wrap->_base._self; + values->_base._self = Py_XNewRef(wrap->_base._self); values->_base._name = wrap->_base._name; values->_keys._len_func = wrap->_keys._len_func; values->_keys._getitem_func = wrap->_keys._getitem_func; @@ -894,8 +888,7 @@ static PyObject *Dtool_MappingWrapper_items(PyObject *self, PyObject *) { } (void)PyObject_INIT(items, &wrapper_type); - Py_XINCREF(wrap->_base._self); - items->_base._self = wrap->_base._self; + items->_base._self = Py_XNewRef(wrap->_base._self); items->_base._name = wrap->_base._name; items->_keys._len_func = wrap->_keys._len_func; items->_keys._getitem_func = wrap->_keys._getitem_func; @@ -945,8 +938,7 @@ static PyObject *Dtool_MutableMappingWrapper_pop(PyObject *self, PyObject *args) } } else if (PyErr_ExceptionMatches(PyExc_KeyError)) { PyErr_Clear(); - Py_INCREF(defvalue); - return defvalue; + return Py_NewRef(defvalue); } else { return nullptr; } @@ -1014,8 +1006,7 @@ static PyObject *Dtool_MutableMappingWrapper_clear(PyObject *self, PyObject *) { } } } - Py_INCREF(Py_None); - return Py_None; + return Py_NewRef(Py_None); } /** @@ -1046,8 +1037,7 @@ static PyObject *Dtool_MutableMappingWrapper_setdefault(PyObject *self, PyObject } else if (PyErr_ExceptionMatches(PyExc_KeyError)) { PyErr_Clear(); if (wrap->_setitem_func(wrap->_base._self, key, defvalue) == 0) { - Py_INCREF(defvalue); - return defvalue; + return Py_NewRef(defvalue); } } return nullptr; @@ -1071,8 +1061,7 @@ static PyObject *Dtool_MutableMappingWrapper_update(PyObject *self, PyObject *ar case 0: if (kwargs == nullptr) { // This is legal. - Py_INCREF(Py_None); - return Py_None; + return Py_NewRef(Py_None); } dict = kwargs; break; @@ -1093,8 +1082,7 @@ static PyObject *Dtool_MutableMappingWrapper_update(PyObject *self, PyObject *ar return nullptr; } } - Py_INCREF(Py_None); - return Py_None; + return Py_NewRef(Py_None); } /** @@ -1276,8 +1264,7 @@ Dtool_SequenceWrapper *Dtool_NewSequenceWrapper(PyObject *self, const char *name } (void)PyObject_INIT(wrap, &wrapper_type); - Py_XINCREF(self); - wrap->_base._self = self; + wrap->_base._self = Py_XNewRef(self); wrap->_base._name = name; wrap->_len_func = nullptr; wrap->_getitem_func = nullptr; @@ -1387,8 +1374,7 @@ Dtool_MutableSequenceWrapper *Dtool_NewMutableSequenceWrapper(PyObject *self, co } (void)PyObject_INIT(wrap, &wrapper_type); - Py_XINCREF(self); - wrap->_base._self = self; + wrap->_base._self = Py_XNewRef(self); wrap->_base._name = name; wrap->_len_func = nullptr; wrap->_getitem_func = nullptr; @@ -1502,8 +1488,7 @@ Dtool_MappingWrapper *Dtool_NewMappingWrapper(PyObject *self, const char *name) } (void)PyObject_INIT(wrap, &wrapper_type); - Py_XINCREF(self); - wrap->_base._self = self; + wrap->_base._self = Py_XNewRef(self); wrap->_base._name = name; wrap->_keys._len_func = nullptr; wrap->_keys._getitem_func = nullptr; @@ -1622,8 +1607,7 @@ Dtool_MappingWrapper *Dtool_NewMutableMappingWrapper(PyObject *self, const char } (void)PyObject_INIT(wrap, &wrapper_type); - Py_XINCREF(self); - wrap->_base._self = self; + wrap->_base._self = Py_XNewRef(self); wrap->_base._name = name; wrap->_keys._len_func = nullptr; wrap->_keys._getitem_func = nullptr; @@ -1700,8 +1684,7 @@ Dtool_NewGenerator(PyObject *self, iternextfunc gen_next) { Dtool_GeneratorWrapper *gen; gen = (Dtool_GeneratorWrapper *)PyType_GenericAlloc(&wrapper_type, 0); if (gen != nullptr) { - Py_INCREF(self); - gen->_base._self = self; + gen->_base._self = Py_NewRef(self); gen->_iternext_func = gen_next; } return (PyObject *)gen; diff --git a/dtool/src/parser-inc/cstdarg b/dtool/src/parser-inc/cstdarg new file mode 100644 index 0000000000..5d0419f603 --- /dev/null +++ b/dtool/src/parser-inc/cstdarg @@ -0,0 +1,5 @@ +#pragma once + +namespace std { + typedef __builtin_va_list va_list; +}; diff --git a/dtool/src/parser-inc/emscripten.h b/dtool/src/parser-inc/emscripten.h new file mode 100644 index 0000000000..036a87f86a --- /dev/null +++ b/dtool/src/parser-inc/emscripten.h @@ -0,0 +1 @@ +#include diff --git a/dtool/src/parser-inc/emscripten/em_asm.h b/dtool/src/parser-inc/emscripten/em_asm.h new file mode 100644 index 0000000000..3fc1120f20 --- /dev/null +++ b/dtool/src/parser-inc/emscripten/em_asm.h @@ -0,0 +1,13 @@ +#pragma once + +#define EM_ASM(...) +#define EM_ASM_INT(...) +#define EM_ASM_DOUBLE(...) +#define MAIN_THREAD_EM_ASM(...) +#define MAIN_THREAD_EM_ASM_INT(...) +#define MAIN_THREAD_EM_ASM_DOUBLE(...) +#define MAIN_THREAD_ASYNC_EM_ASM(...) +#define EM_ASM_(...) +#define EM_ASM_ARGS(...) +#define EM_ASM_INT_V(...) +#define EM_ASM_DOUBLE_V(...) diff --git a/dtool/src/parser-inc/emscripten/em_js.h b/dtool/src/parser-inc/emscripten/em_js.h new file mode 100644 index 0000000000..5ea2940580 --- /dev/null +++ b/dtool/src/parser-inc/emscripten/em_js.h @@ -0,0 +1,3 @@ +#pragma once + +#define EM_JS(ret, name, params, ...) diff --git a/dtool/src/parser-inc/emscripten/emscripten.h b/dtool/src/parser-inc/emscripten/emscripten.h new file mode 100644 index 0000000000..a1ff82c0a9 --- /dev/null +++ b/dtool/src/parser-inc/emscripten/emscripten.h @@ -0,0 +1,24 @@ +#pragma once + +#include "em_asm.h" +#include "em_js.h" + +typedef short emscripten_align1_short; + +typedef long long emscripten_align4_int64; +typedef long long emscripten_align2_int64; +typedef long long emscripten_align1_int64; + +typedef int emscripten_align2_int; +typedef int emscripten_align1_int; + +typedef float emscripten_align2_float; +typedef float emscripten_align1_float; + +typedef double emscripten_align4_double; +typedef double emscripten_align2_double; +typedef double emscripten_align1_double; + +typedef void (*em_callback_func)(void); +typedef void (*em_arg_callback_func)(void*); +typedef void (*em_str_callback_func)(const char *); diff --git a/dtool/src/parser-inc/emscripten/fiber.h b/dtool/src/parser-inc/emscripten/fiber.h new file mode 100644 index 0000000000..fedd641d60 --- /dev/null +++ b/dtool/src/parser-inc/emscripten/fiber.h @@ -0,0 +1,7 @@ +#pragma once + +#include +#include + +typedef struct asyncify_data_s asyncify_data_t; +typedef struct emscripten_fiber_s emscripten_fiber_t; diff --git a/dtool/src/parser-inc/emscripten/trace.h b/dtool/src/parser-inc/emscripten/trace.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/dtool/src/parser-inc/signal.h b/dtool/src/parser-inc/signal.h new file mode 100644 index 0000000000..8711c572dc --- /dev/null +++ b/dtool/src/parser-inc/signal.h @@ -0,0 +1,21 @@ +#pragma once + +#include +#include + +#define SIG_DFL SIG_DFL +#define SIG_ERR SIG_ERR +#define SIG_HOLD SIG_HOLD +#define SIG_IGN SIG_IGN + +typedef int pthread_t; +typedef unsigned int uid_t; +typedef int pid_t; + +typedef int sig_atomic_t; +typedef unsigned int sigset_t; + +union sigval { + int sival_int; + void *sival_ptr; +}; diff --git a/dtool/src/parser-inc/stdarg.h b/dtool/src/parser-inc/stdarg.h index 38099206b2..593c056acf 100644 --- a/dtool/src/parser-inc/stdarg.h +++ b/dtool/src/parser-inc/stdarg.h @@ -1,6 +1,6 @@ #ifndef STDARG_H #define STDARG_H -typedef struct {} va_list[1]; +typedef __builtin_va_list va_list; #endif diff --git a/dtool/src/parser-inc/sys/stat.h b/dtool/src/parser-inc/sys/stat.h index 29ebbf9bf4..c62d64e091 100644 --- a/dtool/src/parser-inc/sys/stat.h +++ b/dtool/src/parser-inc/sys/stat.h @@ -1,3 +1,8 @@ #pragma once +#include +#include + struct stat; + +int stat(const char *restrict, struct stat *restrict); diff --git a/dtool/src/prc/CMakeLists.txt b/dtool/src/prc/CMakeLists.txt index 17b9629bdd..599c408d39 100644 --- a/dtool/src/prc/CMakeLists.txt +++ b/dtool/src/prc/CMakeLists.txt @@ -69,6 +69,11 @@ if(ANDROID) androidLogStream.cxx) endif() +if(EMSCRIPTEN) + set(P3PRC_SOURCES ${P3PRC_SOURCES} + emscriptenLogStream.cxx) +endif() + if(HAVE_OPENSSL) list(APPEND P3PRC_SOURCES encryptStreamBuf.cxx encryptStream.cxx) endif() diff --git a/dtool/src/prc/androidLogStream.cxx b/dtool/src/prc/androidLogStream.cxx index 938f5badaa..d847227268 100644 --- a/dtool/src/prc/androidLogStream.cxx +++ b/dtool/src/prc/androidLogStream.cxx @@ -118,23 +118,4 @@ AndroidLogStream:: delete rdbuf(); } -/** - * Returns an AndroidLogStream suitable for writing log messages with the - * indicated severity. - */ -std::ostream &AndroidLogStream:: -out(NotifySeverity severity) { - static AndroidLogStream* streams[NS_fatal + 1] = {nullptr}; - - if (streams[severity] == nullptr) { - int priority = ANDROID_LOG_UNKNOWN; - if (severity != NS_unspecified) { - priority = ((int)severity) + 1; - } - streams[severity] = new AndroidLogStream(priority); - } - - return *streams[severity]; -} - #endif // ANDROID diff --git a/dtool/src/prc/androidLogStream.h b/dtool/src/prc/androidLogStream.h index f8d2dae034..708137eec3 100644 --- a/dtool/src/prc/androidLogStream.h +++ b/dtool/src/prc/androidLogStream.h @@ -49,6 +49,8 @@ public: virtual ~AndroidLogStream(); static std::ostream &out(NotifySeverity severity); + + friend class Notify; }; #endif // ANDROID diff --git a/dtool/src/prc/configPageManager.cxx b/dtool/src/prc/configPageManager.cxx index 78a8484854..47c206e720 100644 --- a/dtool/src/prc/configPageManager.cxx +++ b/dtool/src/prc/configPageManager.cxx @@ -127,11 +127,13 @@ reload_implicit_pages() { const BlobInfo *blobinfo = (const BlobInfo *)dlsym(RTLD_MAIN_ONLY, "blobinfo"); //#elif defined(RTLD_SELF) // const BlobInfo *blobinfo = (const BlobInfo *)dlsym(RTLD_SELF, "blobinfo"); +#elif defined(__EMSCRIPTEN__) + const BlobInfo *blobinfo = nullptr; #else const BlobInfo *blobinfo = (const BlobInfo *)dlsym(dlopen(nullptr, RTLD_NOW), "blobinfo"); #endif if (blobinfo == nullptr) { -#ifndef _WIN32 +#if !defined(_WIN32) && !defined(__EMSCRIPTEN__) // Clear the error flag. dlerror(); #endif @@ -153,6 +155,7 @@ reload_implicit_pages() { // Pull them out and store them in _prc_patterns. _prc_patterns.clear(); +#ifdef PRC_PATTERNS string prc_patterns = PRC_PATTERNS; if (blobinfo != nullptr && blobinfo->prc_patterns != nullptr) { prc_patterns = blobinfo->prc_patterns; @@ -171,10 +174,12 @@ reload_implicit_pages() { _prc_patterns.push_back(glob); } } +#endif // PRC_PATTERNS // Similarly for PRC_ENCRYPTED_PATTERNS. _prc_encrypted_patterns.clear(); +#ifdef PRC_ENCRYPTED_PATTERNS string prc_encrypted_patterns = PRC_ENCRYPTED_PATTERNS; if (blobinfo != nullptr && blobinfo->prc_encrypted_patterns != nullptr) { prc_encrypted_patterns = blobinfo->prc_encrypted_patterns; @@ -191,10 +196,12 @@ reload_implicit_pages() { _prc_encrypted_patterns.push_back(glob); } } +#endif // PRC_ENCRYPTED_PATTERNS // And again for PRC_EXECUTABLE_PATTERNS. _prc_executable_patterns.clear(); +#ifdef PRC_EXECUTABLE_PATTERNS string prc_executable_patterns = PRC_EXECUTABLE_PATTERNS; if (blobinfo != nullptr && blobinfo->prc_executable_patterns != nullptr) { prc_executable_patterns = blobinfo->prc_executable_patterns; @@ -211,10 +218,12 @@ reload_implicit_pages() { _prc_executable_patterns.push_back(glob); } } +#endif // PRC_EXECUTABLE_PATTERNS // Now build up the search path for .prc files. _search_path.clear(); +#ifdef PRC_DIR_ENVVARS // PRC_DIR_ENVVARS lists one or more environment variables separated by // spaces. Pull them out, and each of those contains the name of a single // directory to search. Add it to the search path. @@ -236,7 +245,9 @@ reload_implicit_pages() { } } } +#endif // PRC_DIR_ENVVARS +#ifdef PRC_PATH_ENVVARS // PRC_PATH_ENVVARS lists one or more environment variables separated by // spaces. Pull them out, and then each one of those contains a list of // directories to search. Add each of those to the search path. @@ -264,7 +275,9 @@ reload_implicit_pages() { } } } +#endif // PRC_PATH_ENVVARS +#ifdef PRC_PATH2_ENVVARS /* * PRC_PATH2_ENVVARS is a special variable that is rarely used; it exists * primarily to support the Cygwin-based "ctattach" tools used by the Walt @@ -294,7 +307,9 @@ reload_implicit_pages() { } } } +#endif // PRC_PATH2_ENVVARS +#ifdef DEFAULT_PRC_DIR if (_search_path.is_empty()) { // If nothing's on the search path (PRC_DIR and PRC_PATH were not // defined), then use the DEFAULT_PRC_DIR. @@ -310,6 +325,7 @@ reload_implicit_pages() { } } } +#endif // DEFAULT_PRC_DIR // Now find all of the *.prc files (or whatever matches PRC_PATTERNS) on the // path. @@ -398,6 +414,11 @@ reload_implicit_pages() { if ((file._file_flags & FF_execute) != 0 && filename.is_executable()) { + +#ifdef __EMSCRIPTEN__ + prc_cat.error() + << "Executable config files are not supported with Emscripten.\n"; +#else // Attempt to execute the file as a command. string command = filename.to_os_specific(); @@ -420,6 +441,7 @@ reload_implicit_pages() { _pages_sorted = false; page->read_prc(ifs); +#endif // __EMSCRIPTEN__ } else if ((file._file_flags & FF_decrypt) != 0) { // Read and decrypt the file. diff --git a/dtool/src/prc/emscriptenLogStream.cxx b/dtool/src/prc/emscriptenLogStream.cxx new file mode 100644 index 0000000000..6126276826 --- /dev/null +++ b/dtool/src/prc/emscriptenLogStream.cxx @@ -0,0 +1,111 @@ +/** + * PANDA 3D SOFTWARE + * Copyright (c) Carnegie Mellon University. All rights reserved. + * + * All use of this software is subject to the terms of the revised BSD + * license. You should have received a copy of this license along + * with this source code in a file named "LICENSE." + * + * @file emscriptenLogStream.cxx + * @author rdb + * @date 2015-04-02 + */ + +#include "emscriptenLogStream.h" +#include "configVariableString.h" + +#ifdef __EMSCRIPTEN__ + +#include + +/** + * + */ +EmscriptenLogStream::EmscriptenLogStreamBuf:: +EmscriptenLogStreamBuf(int flags) : + _flags(flags) { + + // The EmscriptenLogStreamBuf doesn't actually need a buffer--it's happy + // writing characters one at a time, since they're just getting stuffed into + // a string. (Although the code is written portably enough to use a buffer + // correctly, if we had one.) + setg(0, 0, 0); + setp(0, 0); +} + +/** + * + */ +EmscriptenLogStream::EmscriptenLogStreamBuf:: +~EmscriptenLogStreamBuf() { + sync(); +} + +/** + * Called by the system ostream implementation when the buffer should be + * flushed to output (for instance, on destruction). + */ +int EmscriptenLogStream::EmscriptenLogStreamBuf:: +sync() { + std::streamsize n = pptr() - pbase(); + + // Write the characters that remain in the buffer. + for (char *p = pbase(); p < pptr(); ++p) { + write_char(*p); + } + + pbump(-n); // Reset pptr(). + return 0; // EOF to indicate write full. +} + +/** + * Called by the system ostream implementation when its internal buffer is + * filled, plus one character. + */ +int EmscriptenLogStream::EmscriptenLogStreamBuf:: +overflow(int ch) { + std::streamsize n = pptr() - pbase(); + + if (n != 0 && sync() != 0) { + return EOF; + } + + if (ch != EOF) { + // Write one more character. + write_char(ch); + } + + return 0; +} + +/** + * Stores a single character. + */ +void EmscriptenLogStream::EmscriptenLogStreamBuf:: +write_char(char c) { + if (c == '\n') { + // Write a line to the log file. + emscripten_log(_flags, "%.*s", _data.size(), _data.c_str()); + _data.clear(); + } else { + _data += c; + } +} + +/** + * + */ +EmscriptenLogStream:: +EmscriptenLogStream(int flags) : + std::ostream(new EmscriptenLogStreamBuf(flags)) { +} + +/** + * + */ +EmscriptenLogStream:: +~EmscriptenLogStream() { + delete rdbuf(); +} + +#endif // __EMSCRIPTEN__ diff --git a/dtool/src/prc/emscriptenLogStream.h b/dtool/src/prc/emscriptenLogStream.h new file mode 100644 index 0000000000..4af8a973d5 --- /dev/null +++ b/dtool/src/prc/emscriptenLogStream.h @@ -0,0 +1,57 @@ +/** + * PANDA 3D SOFTWARE + * Copyright (c) Carnegie Mellon University. All rights reserved. + * + * All use of this software is subject to the terms of the revised BSD + * license. You should have received a copy of this license along + * with this source code in a file named "LICENSE." + * + * @file emscriptenLogStream.h + * @author rdb + * @date 2015-04-02 + */ + +#ifndef EMSCRIPTENLOGSTREAM_H +#define EMSCRIPTENLOGSTREAM_H + +#ifdef __EMSCRIPTEN__ + +#include "dtoolbase.h" +#include "notifySeverity.h" + +#include +#include + +/** + * This is a type of ostream that writes each line to the JavaScript log + * window. + */ +class EmscriptenLogStream : public std::ostream { +private: + class EmscriptenLogStreamBuf : public std::streambuf { + public: + EmscriptenLogStreamBuf(int flags); + virtual ~EmscriptenLogStreamBuf(); + + protected: + virtual int overflow(int c); + virtual int sync(); + + private: + void write_char(char c); + + int _flags; + string _data; + }; + + EmscriptenLogStream(int flags); + +public: + virtual ~EmscriptenLogStream(); + + friend class Notify; +}; + +#endif // __EMSCRIPTEN__ + +#endif // EMSCRIPTENLOGSTREAM_H diff --git a/dtool/src/prc/notify.cxx b/dtool/src/prc/notify.cxx index 9528ed9903..009c6ab818 100644 --- a/dtool/src/prc/notify.cxx +++ b/dtool/src/prc/notify.cxx @@ -28,10 +28,13 @@ #ifdef ANDROID #include - #include "androidLogStream.h" #endif +#ifdef __EMSCRIPTEN__ +#include "emscriptenLogStream.h" +#endif + using std::cerr; using std::cout; using std::ostream; @@ -255,6 +258,21 @@ get_category(const string &fullname) { return get_category(basename, parent_category); } +/** + * A convenient way to get the ostream that should be written to for a Notify- + * type message of a particular severity. Also see Category::out() for a + * message that is specific to a particular Category. + */ +ostream &Notify:: +out(NotifySeverity severity) { +#if defined(ANDROID) || defined(__EMSCRIPTEN__) + // Android and JavaScript have dedicated log systems. + return *(ptr()->_log_streams[severity]); +#else + return *(ptr()->_ostream_ptr); +#endif +} + /** * A convenient way to get the ostream that should be written to for a Notify- * type message. Also see Category::out() for a message that is specific to a @@ -342,7 +360,15 @@ assert_failure(const char *expression, int line, } #ifdef ANDROID + // Write to Android log system. __android_log_assert("assert", "Panda3D", "Assertion failed: %s", message.c_str()); +#endif + +#ifdef __EMSCRIPTEN__ + // Write to JavaScript console. + emscripten_log(EM_LOG_CONSOLE | EM_LOG_ERROR | EM_LOG_C_STACK, + "Assertion failed: %s", message.c_str()); + #else nout << "Assertion failed: " << message << "\n"; #endif @@ -372,6 +398,11 @@ assert_failure(const char *expression, int line, int *ptr = nullptr; *ptr = 1; +#elif defined(__EMSCRIPTEN__) + // This should drop us into the browser's JavaScript debugger. + //emscripten_debugger(); + EM_ASM(debugger;); + #else // _MSC_VER abort(); #endif // _MSC_VER @@ -429,6 +460,39 @@ config_initialized() { // notify-output even after the initial import of Panda3D modules. However, // it cannot be changed after the first time it is set. +#if defined(ANDROID) + // Android redirects stdio and stderr to /dev/null, + // but does provide its own logging system. We use a special + // type of stream that redirects it to Android's log system. + + Notify *ptr = Notify::ptr(); + + for (int i = 0; i <= NS_fatal; ++i) { + int priority = ANDROID_LOG_UNKNOWN; + if (severity != NS_unspecified) { + priority = i + 1; + } + ptr->_log_streams[i] = new AndroidLogStream(priority); + } + +#elif defined(__EMSCRIPTEN__) + // We have no writable filesystem in JavaScript. Instead, we set up a + // special stream that logs straight into the Javascript console. + + EmscriptenLogStream *error_stream = new EmscriptenLogStream(EM_LOG_CONSOLE | EM_LOG_ERROR); + EmscriptenLogStream *warn_stream = new EmscriptenLogStream(EM_LOG_CONSOLE | EM_LOG_WARN); + EmscriptenLogStream *info_stream = new EmscriptenLogStream(EM_LOG_CONSOLE); + + Notify *ptr = Notify::ptr(); + ptr->_log_streams[NS_unspecified] = info_stream; + ptr->_log_streams[NS_spam] = info_stream; + ptr->_log_streams[NS_debug] = info_stream; + ptr->_log_streams[NS_info] = info_stream; + ptr->_log_streams[NS_warning] = warn_stream; + ptr->_log_streams[NS_error] = error_stream; + ptr->_log_streams[NS_fatal] = error_stream; + +#else if (_global_ptr == nullptr || _global_ptr->_ostream_ptr == &cerr) { static ConfigVariableFilename notify_output ("notify-output", "", @@ -484,4 +548,5 @@ config_initialized() { #endif } } +#endif } diff --git a/dtool/src/prc/notifyCategory.cxx b/dtool/src/prc/notifyCategory.cxx index 43c0deb31e..17d2309ab8 100644 --- a/dtool/src/prc/notifyCategory.cxx +++ b/dtool/src/prc/notifyCategory.cxx @@ -18,10 +18,6 @@ #include "configVariableBool.h" #include "config_prc.h" -#ifdef ANDROID -#include "androidLogStream.h" -#endif - #include // for strftime(). #include @@ -58,22 +54,6 @@ NotifyCategory(const std::string &fullname, const std::string &basename, std::ostream &NotifyCategory:: out(NotifySeverity severity, bool prefix) const { if (is_on(severity)) { - -#ifdef ANDROID - // Android redirects stdio and stderr to devnull, but does provide its own - // logging system. We use a special type of stream that redirects it to - // Android's log system. - if (prefix) { - if (severity == NS_info) { - return AndroidLogStream::out(severity) << *this << ": "; - } else { - return AndroidLogStream::out(severity) << *this << "(" << severity << "): "; - } - } else { - return AndroidLogStream::out(severity); - } -#else - if (prefix) { if (get_notify_timestamp()) { // Format a timestamp to include as a prefix as well. @@ -87,18 +67,17 @@ out(NotifySeverity severity, bool prefix) const { char buffer[128]; strftime(buffer, 128, ":%m-%d-%Y %H:%M:%S ", &atm); - nout << buffer; + Notify::out(severity) << buffer; } if (severity == NS_info) { - return nout << *this << ": "; + return Notify::out(severity) << *this << ": "; } else { - return nout << *this << "(" << severity << "): "; + return Notify::out(severity) << *this << "(" << severity << "): "; } } else { - return nout; + return Notify::out(severity); } -#endif } else if (severity <= NS_debug && get_check_debug_notify_protect()) { // Someone issued a debug Notify output statement without protecting it diff --git a/dtool/src/prc/p3prc_composite2.cxx b/dtool/src/prc/p3prc_composite2.cxx index 0791ee0b01..1e8dd8d7d2 100644 --- a/dtool/src/prc/p3prc_composite2.cxx +++ b/dtool/src/prc/p3prc_composite2.cxx @@ -2,6 +2,7 @@ #include "configVariableManager.cxx" #include "configVariableSearchPath.cxx" #include "configVariableString.cxx" +#include "emscriptenLogStream.cxx" #include "encryptStreamBuf.cxx" #include "encryptStream.cxx" #include "nativeNumericData.cxx" diff --git a/dtool/src/prc/pnotify.h b/dtool/src/prc/pnotify.h index c88f8a8b33..a4c9a6aca2 100644 --- a/dtool/src/prc/pnotify.h +++ b/dtool/src/prc/pnotify.h @@ -18,7 +18,13 @@ #include "notifySeverity.h" #include +#ifdef __EMSCRIPTEN__ +#include +#endif + class NotifyCategory; +class AndroidLogStream; +class EmscriptenLogStream; /** * An object that handles general error reporting to the user. It contains a @@ -61,6 +67,7 @@ PUBLISHED: const std::string &parent_fullname); NotifyCategory *get_category(const std::string &fullname); + static std::ostream &out(NotifySeverity severity); static std::ostream &out(); static std::ostream &null(); static void write_string(const std::string &str); @@ -92,6 +99,12 @@ private: typedef std::map Categories; Categories _categories; +#if defined(ANDROID) + AndroidLogStream *_log_streams[NS_fatal + 1]; +#elif defined(__EMSCRIPTEN__) + EmscriptenLogStream *_log_streams[NS_fatal + 1]; +#endif + static Notify *_global_ptr; }; diff --git a/makepanda/installer.nsi b/makepanda/installer.nsi index 841fd2d2c6..7dd818477c 100644 --- a/makepanda/installer.nsi +++ b/makepanda/installer.nsi @@ -384,6 +384,7 @@ SectionGroup "Python modules" SecGroupPython !insertmacro PyBindingSection 3.10-32 .cp310-win32.pyd !insertmacro PyBindingSection 3.11-32 .cp311-win32.pyd !insertmacro PyBindingSection 3.12-32 .cp312-win32.pyd + !insertmacro PyBindingSection 3.13-32 .cp313-win32.pyd !else !insertmacro PyBindingSection 3.5 .cp35-win_amd64.pyd !insertmacro PyBindingSection 3.6 .cp36-win_amd64.pyd @@ -393,6 +394,7 @@ SectionGroup "Python modules" SecGroupPython !insertmacro PyBindingSection 3.10 .cp310-win_amd64.pyd !insertmacro PyBindingSection 3.11 .cp311-win_amd64.pyd !insertmacro PyBindingSection 3.12 .cp312-win_amd64.pyd + !insertmacro PyBindingSection 3.13 .cp313-win_amd64.pyd !endif SectionGroupEnd @@ -503,6 +505,7 @@ Function .onInit !insertmacro MaybeEnablePyBindingSection 3.10-32 !insertmacro MaybeEnablePyBindingSection 3.11-32 !insertmacro MaybeEnablePyBindingSection 3.12-32 + !insertmacro MaybeEnablePyBindingSection 3.13-32 ${EndIf} !else !insertmacro MaybeEnablePyBindingSection 3.5 @@ -514,6 +517,7 @@ Function .onInit !insertmacro MaybeEnablePyBindingSection 3.10 !insertmacro MaybeEnablePyBindingSection 3.11 !insertmacro MaybeEnablePyBindingSection 3.12 + !insertmacro MaybeEnablePyBindingSection 3.13 ${EndIf} !endif @@ -535,6 +539,10 @@ Function .onInit SectionSetFlags ${SecPyBindings3.12} ${SF_RO} SectionSetInstTypes ${SecPyBindings3.12} 0 !endif + !ifdef SecPyBindings3.13 + SectionSetFlags ${SecPyBindings3.13} ${SF_RO} + SectionSetInstTypes ${SecPyBindings3.13} 0 + !endif ${EndUnless} FunctionEnd @@ -853,6 +861,7 @@ Section Uninstall !insertmacro RemovePythonPath 3.10-32 !insertmacro RemovePythonPath 3.11-32 !insertmacro RemovePythonPath 3.12-32 + !insertmacro RemovePythonPath 3.13-32 !else !insertmacro RemovePythonPath 3.5 !insertmacro RemovePythonPath 3.6 @@ -862,6 +871,7 @@ Section Uninstall !insertmacro RemovePythonPath 3.10 !insertmacro RemovePythonPath 3.11 !insertmacro RemovePythonPath 3.12 + !insertmacro RemovePythonPath 3.13 !endif SetDetailsPrint both @@ -932,6 +942,7 @@ SectionEnd !insertmacro MUI_DESCRIPTION_TEXT ${SecPyBindings3.10-32} $(DESC_SecPyBindings3.10-32) !insertmacro MUI_DESCRIPTION_TEXT ${SecPyBindings3.11-32} $(DESC_SecPyBindings3.11-32) !insertmacro MUI_DESCRIPTION_TEXT ${SecPyBindings3.12-32} $(DESC_SecPyBindings3.12-32) + !insertmacro MUI_DESCRIPTION_TEXT ${SecPyBindings3.13-32} $(DESC_SecPyBindings3.13-32) !else !insertmacro MUI_DESCRIPTION_TEXT ${SecPyBindings3.5} $(DESC_SecPyBindings3.5) !insertmacro MUI_DESCRIPTION_TEXT ${SecPyBindings3.6} $(DESC_SecPyBindings3.6) @@ -941,6 +952,7 @@ SectionEnd !insertmacro MUI_DESCRIPTION_TEXT ${SecPyBindings3.10} $(DESC_SecPyBindings3.10) !insertmacro MUI_DESCRIPTION_TEXT ${SecPyBindings3.11} $(DESC_SecPyBindings3.11) !insertmacro MUI_DESCRIPTION_TEXT ${SecPyBindings3.12} $(DESC_SecPyBindings3.12) + !insertmacro MUI_DESCRIPTION_TEXT ${SecPyBindings3.13} $(DESC_SecPyBindings3.13) !endif !ifdef INCLUDE_PYVER !insertmacro MUI_DESCRIPTION_TEXT ${SecPython} $(DESC_SecPython) diff --git a/makepanda/makepackage.py b/makepanda/makepackage.py index 8bca2e31e1..6bfad076c6 100755 --- a/makepanda/makepackage.py +++ b/makepanda/makepackage.py @@ -61,8 +61,7 @@ This package contains the SDK for development with Panda3D. /usr/%_lib/panda3d /usr/include/panda3d """ -INSTALLER_SPEC_FILE_PVIEW = """\ -/usr/share/applications/pview.desktop +INSTALLER_SPEC_FILE_MIME = """\ /usr/share/mime-info/panda3d.mime /usr/share/mime-info/panda3d.keys /usr/share/mime/packages/panda3d.xml @@ -384,9 +383,15 @@ def MakeInstallerLinux(version, debversion=None, rpmversion=None, rpmrelease=1, txt = INSTALLER_SPEC_FILE[1:] - # Add the MIME associations if we have pview - if not PkgSkip("PVIEW"): - txt += INSTALLER_SPEC_FILE_PVIEW + # Add the MIME associations if we have pview or pstats + if not PkgSkip("PVIEW") or not PkgSkip("PSTATS"): + txt += INSTALLER_SPEC_FILE_MIME + + if not PkgSkip("PVIEW"): + txt += "/usr/share/applications/pview.desktop\n" + + if not PkgSkip("PSTATS"): + txt += "/usr/share/applications/pstats.desktop\n" # Add the platform-specific Python directories. dirs = set() diff --git a/makepanda/makepanda.py b/makepanda/makepanda.py index 6ebecad720..994f336d0e 100755 --- a/makepanda/makepanda.py +++ b/makepanda/makepanda.py @@ -867,7 +867,6 @@ if (COMPILER=="GCC"): assimp_libs = ("libassimp", "libassimpd") # Name pkg-config libs, include(dir)s - SmartPkgEnable("EIGEN", "eigen3", (), ("Eigen/Dense",), target_pkg = 'ALWAYS') SmartPkgEnable("ARTOOLKIT", "", ("AR"), "AR/ar.h") SmartPkgEnable("FCOLLADA", "", ChooseLib(fcollada_libs, "FCOLLADA"), ("FCollada", "FCollada/FCollada.h")) SmartPkgEnable("ASSIMP", "assimp", ChooseLib(assimp_libs, "ASSIMP"), "assimp/Importer.hpp") @@ -876,31 +875,52 @@ if (COMPILER=="GCC"): SmartPkgEnable("SWRESAMPLE","libswresample", "libswresample", ("libswresample/swresample.h"), target_pkg = "FFMPEG", thirdparty_dir = "ffmpeg") SmartPkgEnable("FFTW", "fftw3", ("fftw3"), ("fftw.h")) SmartPkgEnable("FMODEX", "", ("fmodex"), ("fmodex", "fmodex/fmod.h")) - SmartPkgEnable("FREETYPE", "freetype2", ("freetype"), ("freetype2", "freetype2/freetype/freetype.h")) - SmartPkgEnable("HARFBUZZ", "harfbuzz", ("harfbuzz"), ("harfbuzz", "harfbuzz/hb-ft.h")) - SmartPkgEnable("GL", "gl", ("GL"), ("GL/gl.h"), framework = "OpenGL") - SmartPkgEnable("GLES", "glesv1_cm", ("GLESv1_CM"), ("GLES/gl.h"), framework = "OpenGLES") - SmartPkgEnable("GLES2", "glesv2", ("GLESv2"), ("GLES2/gl2.h")) #framework = "OpenGLES"? - SmartPkgEnable("EGL", "egl", ("EGL"), ("EGL/egl.h")) SmartPkgEnable("NVIDIACG", "", ("Cg"), "Cg/cg.h", framework = "Cg") SmartPkgEnable("ODE", "", ("ode"), "ode/ode.h", tool = "ode-config") - SmartPkgEnable("OPENAL", "openal", ("openal"), "AL/al.h", framework = "OpenAL") SmartPkgEnable("SQUISH", "", ("squish"), "squish.h") SmartPkgEnable("TIFF", "libtiff-4", ("tiff"), "tiff.h") SmartPkgEnable("VRPN", "", ("vrpn", "quat"), ("vrpn", "quat.h", "vrpn/vrpn_Types.h")) - SmartPkgEnable("BULLET", "bullet", ("BulletSoftBody", "BulletDynamics", "BulletCollision", "LinearMath"), ("bullet", "bullet/btBulletDynamicsCommon.h")) - SmartPkgEnable("VORBIS", "vorbisfile",("vorbisfile", "vorbis", "ogg"), ("ogg/ogg.h", "vorbis/vorbisfile.h")) SmartPkgEnable("OPUS", "opusfile", ("opusfile", "opus", "ogg"), ("ogg/ogg.h", "opus/opusfile.h", "opus")) SmartPkgEnable("JPEG", "", ("jpeg"), "jpeglib.h") - SmartPkgEnable("PNG", "libpng", ("png"), "png.h", tool = "libpng-config") SmartPkgEnable("MIMALLOC", "", ("mimalloc"), "mimalloc.h") - # Copy freetype libraries to be specified after harfbuzz libraries as well, - # because there's a circular dependency between the two libraries. - if not PkgSkip("FREETYPE") and not PkgSkip("HARFBUZZ"): - for (opt, name) in LIBNAMES: - if opt == "FREETYPE": - LibName("HARFBUZZ", name) + if GetTarget() != 'emscripten': + # Most of these are provided by emscripten or via emscripten-ports. + SmartPkgEnable("OPENAL", "openal", ("openal"), "AL/al.h", framework = "OpenAL") + SmartPkgEnable("EIGEN", "eigen3", (), ("Eigen/Dense",), target_pkg = 'ALWAYS') + SmartPkgEnable("VORBIS", "vorbisfile",("vorbisfile", "vorbis", "ogg"), ("ogg/ogg.h", "vorbis/vorbisfile.h")) + SmartPkgEnable("BULLET", "bullet", ("BulletSoftBody", "BulletDynamics", "BulletCollision", "LinearMath"), ("bullet", "bullet/btBulletDynamicsCommon.h")) + SmartPkgEnable("FREETYPE", "freetype2", ("freetype"), ("freetype2", "freetype2/freetype/freetype.h")) + SmartPkgEnable("HARFBUZZ", "harfbuzz", ("harfbuzz"), ("harfbuzz", "harfbuzz/hb-ft.h")) + SmartPkgEnable("PNG", "libpng", ("png"), "png.h", tool = "libpng-config") + SmartPkgEnable("GL", "gl", ("GL"), ("GL/gl.h"), framework = "OpenGL") + SmartPkgEnable("GLES", "glesv1_cm", ("GLESv1_CM"), ("GLES/gl.h"), framework = "OpenGLES") + SmartPkgEnable("GLES2", "glesv2", ("GLESv2"), ("GLES2/gl2.h")) #framework = "OpenGLES"? + SmartPkgEnable("EGL", "egl", ("EGL"), ("EGL/egl.h")) + + # Copy freetype libraries to be specified after harfbuzz libraries as well, + # because there's a circular dependency between the two libraries. + if not PkgSkip("FREETYPE") and not PkgSkip("HARFBUZZ"): + for (opt, name) in LIBNAMES: + if opt == "FREETYPE": + LibName("HARFBUZZ", name) + else: + PkgDisable("EIGEN") + PkgDisable("X11") + PkgDisable("GL") + PkgDisable("GLES") + PkgDisable("TINYDISPLAY") + for pkg, empkg in { + 'VORBIS': 'VORBIS', + 'BULLET': 'BULLET', + 'ZLIB': 'ZLIB', + 'FREETYPE': 'FREETYPE', + 'HARFBUZZ': 'HARFBUZZ', + 'PNG': 'LIBPNG', + }.items(): + if not PkgSkip(pkg): + LinkFlag(pkg, '-s USE_' + empkg + '=1') + CompileFlag(pkg, '-s USE_' + empkg + '=1') if not PkgSkip("FFMPEG"): if GetTarget() == "darwin": @@ -909,8 +929,9 @@ if (COMPILER=="GCC"): # Needed when linking ffmpeg statically on Linux. LibName("FFMPEG", "-Wl,-Bsymbolic") # Don't export ffmpeg symbols from libp3ffmpeg when linking statically. - for ffmpeg_lib in ffmpeg_libs: - LibName("FFMPEG", "-Wl,--exclude-libs,%s.a" % (ffmpeg_lib)) + if GetTarget() != "emscripten": + for ffmpeg_lib in ffmpeg_libs: + LibName("FFMPEG", "-Wl,--exclude-libs,%s.a" % (ffmpeg_lib)) if not PkgSkip("OPENEXR"): # OpenEXR libraries have different names depending on the version. @@ -929,7 +950,7 @@ if (COMPILER=="GCC"): # using the OpenEXR 3 naming scheme. SmartPkgEnable("OPENEXR", "OpenEXR", ("OpenEXR", "IlmThread", "Imath", "Iex"), openexr_incs) - if GetTarget() != "darwin": + if GetTarget() not in ("darwin", "emscripten"): for fcollada_lib in fcollada_libs: LibName("FCOLLADA", "-Wl,--exclude-libs,lib%s.a" % (fcollada_lib)) @@ -1005,7 +1026,7 @@ if (COMPILER=="GCC"): LibName("OPENAL", "-framework AudioUnit") LibName("OPENAL", "-framework AudioToolbox") LibName("OPENAL", "-framework CoreAudio") - else: + elif GetTarget() != "emscripten": LibName("OPENAL", "-Wl,--exclude-libs,libopenal.a") if not PkgSkip("ASSIMP") and \ @@ -1015,7 +1036,7 @@ if (COMPILER=="GCC"): if os.path.isfile(irrxml): LibName("ASSIMP", irrxml) - if GetTarget() != "darwin": + if GetTarget() not in ("darwin", "emscripten"): LibName("ASSIMP", "-Wl,--exclude-libs,libassimp.a") LibName("ASSIMP", "-Wl,--exclude-libs,libIrrXML.a") @@ -1023,19 +1044,31 @@ if (COMPILER=="GCC"): python_lib = SDK["PYTHONVERSION"] SmartPkgEnable("PYTHON", "", python_lib, (SDK["PYTHONVERSION"], SDK["PYTHONVERSION"] + "/Python.h")) + if not PkgSkip("PYTHON") and GetTarget() == "emscripten": + # Python may have been compiled with these requirements. + # Is there a cleaner way to check this? + LinkFlag("PYTHON", "-s USE_BZIP2=1 -s USE_SQLITE3=1") + if not PkgHasCustomLocation("PYTHON"): + python_libdir = GetThirdpartyDir() + "python/lib" + if os.path.isfile(python_libdir + "/libmpdec.a"): + LibName("PYTHON", python_libdir + "/libmpdec.a") + if os.path.isfile(python_libdir + "/libexpat.a"): + LibName("PYTHON", python_libdir + "/libexpat.a") + if GetTarget() == "linux": LibName("PYTHON", "-lutil") LibName("PYTHON", "-lrt") SmartPkgEnable("OPENSSL", "openssl", ("ssl", "crypto"), ("openssl/ssl.h", "openssl/crypto.h")) - SmartPkgEnable("ZLIB", "zlib", ("z"), "zlib.h") SmartPkgEnable("GTK3", "gtk+-3.0") + if GetTarget() != 'emscripten': + SmartPkgEnable("ZLIB", "zlib", ("z"), "zlib.h") - if not PkgSkip("OPENSSL") and GetTarget() != "darwin": + if not PkgSkip("OPENSSL") and GetTarget() not in ("darwin", "emscripten"): LibName("OPENSSL", "-Wl,--exclude-libs,libssl.a") LibName("OPENSSL", "-Wl,--exclude-libs,libcrypto.a") - if GetTarget() != 'darwin': + if GetTarget() not in ('darwin', 'emscripten'): # CgGL is covered by the Cg framework, and we don't need X11 components on OSX if not PkgSkip("NVIDIACG"): SmartPkgEnable("CGGL", "", ("CgGL"), "Cg/cgGL.h", thirdparty_dir = "nvidiacg") @@ -1139,7 +1172,7 @@ if (COMPILER=="GCC"): LibName(pkg, "-dylib_file /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib:/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib") DefSymbol("WITHINPANDA", "WITHIN_PANDA", "1") -if GetLinkAllStatic(): +if GetLinkAllStatic() or GetTarget() == 'emscripten': DefSymbol("ALWAYS", "LINK_ALL_STATIC") if GetTarget() == 'android': DefSymbol("ALWAYS", "ANDROID") @@ -1373,6 +1406,8 @@ def CompileCxx(obj,src,opts): if (opt=="ALWAYS") or (opt in opts): cmd += ' -F' + BracketNameWithQuotes(dir) for (opt,var,val) in DEFSYMBOLS: if (opt=="ALWAYS") or (opt in opts): cmd += ' -D' + var + '=' + val + for (opt,flag) in COMPILEFLAGS: + if (opt=="ALWAYS") or (opt in opts): cmd += ' ' + flag for x in ipath: cmd += ' -I' + x if not GetLinkAllStatic() and 'NOHIDDEN' not in opts: @@ -1396,7 +1431,7 @@ def CompileCxx(obj,src,opts): if 'NOARCH:' + arch.upper() not in opts: cmd += " -arch %s" % arch - elif 'clang' not in GetCXX().split('/')[-1]: + elif 'clang' not in GetCXX().split('/')[-1] and GetCXX() != 'em++': # Enable interprocedural optimizations in GCC. cmd += " -fno-semantic-interposition" @@ -1442,6 +1477,12 @@ def CompileCxx(obj,src,opts): if arch != 'arm64' and arch.startswith('arm') and PkgSkip("NEON") == 0: cmd += ' -mfpu=neon' + elif GetTarget() == 'emscripten': + if GetOptimize() <= 1: + cmd += " -s ASSERTIONS=2" + elif GetOptimize() <= 2: + cmd += " -s ASSERTIONS=1" + else: cmd += " -pthread" @@ -1451,6 +1492,8 @@ def CompileCxx(obj,src,opts): cmd += " -fexceptions" else: cmd += " -fno-exceptions" + if GetTarget() == 'emscripten': + cmd += " -s DISABLE_EXCEPTION_CATCHING=1" if src.endswith(".mm"): # Work around Apple compiler bug. @@ -1463,7 +1506,8 @@ def CompileCxx(obj,src,opts): cmd += " -fno-rtti" if ('SSE2' in opts or not PkgSkip("SSE2")) and not arch.startswith("arm") and arch != 'aarch64': - cmd += " -msse2" + if GetTarget() != "emscripten": + cmd += " -msse2" # Needed by both Python, Panda, Eigen, all of which break aliasing rules. cmd += " -fno-strict-aliasing" @@ -1478,9 +1522,14 @@ def CompileCxx(obj,src,opts): cmd += " -fno-finite-math-only" # Make sure this is off to avoid GCC/Eigen bug (see GitHub #228) - cmd += " -fno-unsafe-math-optimizations" + if GetTarget() != "emscripten": + cmd += " -fno-unsafe-math-optimizations" - if (optlevel==1): cmd += " -ggdb -D_DEBUG" + if (optlevel==1): + if GetTarget() == "emscripten": + cmd += " -g -D_DEBUG" + else: + cmd += " -ggdb -D_DEBUG" if (optlevel==2): cmd += " -O1 -D_DEBUG" if (optlevel==3): cmd += " -O2" if (optlevel==4): cmd += " -O3 -DNDEBUG" @@ -1630,6 +1679,9 @@ def CompileIgate(woutd,wsrc,opts): elif target == 'android': cmd += ' -D__ANDROID__' + if GetTarget() == "emscripten": + cmd += ' -D__EMSCRIPTEN__' + optlevel = GetOptimizeOption(opts) if (optlevel==1): cmd += ' -D_DEBUG' if (optlevel==2): cmd += ' -D_DEBUG' @@ -1668,10 +1720,8 @@ def CompileIgate(woutd,wsrc,opts): def CompileImod(wobj, wsrc, opts): module = GetValueOption(opts, "IMOD:") library = GetValueOption(opts, "ILIB:") - if (COMPILER=="MSVC"): - woutc = wobj[:-4]+".cxx" - if (COMPILER=="GCC"): - woutc = wobj[:-2]+".cxx" + woutc = os.path.splitext(wobj)[0] + ".cxx" + if (PkgSkip("PYTHON")): WriteFile(woutc, "") CompileCxx(wobj, woutc, opts) @@ -1894,13 +1944,18 @@ def CompileLink(dll, obj, opts): else: cmd = cxx + ' -shared' # Always set soname on Android to avoid a linker warning when loading the library. - if "MODULE" not in opts or GetTarget() == 'android': + if GetTarget() == 'android' or ("MODULE" not in opts and GetTarget() != 'emscripten'): cmd += " -Wl,-soname=" + os.path.basename(dll) cmd += ' -o ' + dll + ' -L' + GetOutputDir() + '/lib -L' + GetOutputDir() + '/tmp' - for x in obj: - if GetOrigExt(x) != ".dat": - cmd += ' ' + x + if GetTarget() == 'emscripten' and GetOrigExt(dll) != ".exe": + for x in obj: + if GetOrigExt(x) not in (".dat", ".dll"): + cmd += ' ' + x + else: + for x in obj: + if GetOrigExt(x) != ".dat": + cmd += ' ' + x if (GetOrigExt(dll) == ".exe" and GetTarget() == 'windows' and "NOICON" not in opts): cmd += " " + GetOutputDir() + "/tmp/pandaIcon.res" @@ -1934,6 +1989,13 @@ def CompileLink(dll, obj, opts): elif arch == 'mips': cmd += ' -mips32' cmd += ' -lc -lm' + + elif GetTarget() == 'emscripten': + cmd += " -s WARN_ON_UNDEFINED_SYMBOLS=1" + if GetOrigExt(dll) == ".exe": + cmd += " --memory-init-file 0" + cmd += " -s EXIT_RUNTIME=1" + else: cmd += " -pthread" if "SYSROOT" in SDK: @@ -1953,13 +2015,23 @@ def CompileLink(dll, obj, opts): for (opt, dir) in FRAMEWORKDIRECTORIES: if (opt=="ALWAYS") or (opt in opts): cmd += ' -F' + BracketNameWithQuotes(dir) - for (opt, name) in LIBNAMES: + if GetOrigExt(dll) == ".exe" or GetTarget() != 'emscripten': + for (opt, name) in LIBNAMES: + if (opt=="ALWAYS") or (opt in opts): + cmd += ' ' + BracketNameWithQuotes(name) + for (opt, flag) in LINKFLAGS: if (opt=="ALWAYS") or (opt in opts): - cmd += ' ' + BracketNameWithQuotes(name) + cmd += ' ' + flag - if GetTarget() != 'freebsd': + if GetTarget() not in ('freebsd', 'emscripten'): cmd += " -ldl" + if GetTarget() == 'emscripten': + optlevel = GetOptimizeOption(opts) + if optlevel == 2: cmd += " -O1" + if optlevel == 3: cmd += " -O2" + if optlevel == 4: cmd += " -O3" + oscmd(cmd) if GetOptimizeOption(opts) == 4 and GetTarget() in ('linux', 'android'): @@ -2283,7 +2355,7 @@ def CompileAnything(target, inputs, opts, progress = None): if target.lower().endswith(".dylib"): target = target[:-5] + MAJOR_VERSION + ".dylib" SetOrigExt(target, origsuffix) - elif tplatform != "windows" and tplatform != "android": + elif tplatform not in ("windows", "android", "emscripten"): # On Linux, libraries are named like libpanda.so.1.2 target += "." + MAJOR_VERSION SetOrigExt(target, origsuffix) @@ -2468,11 +2540,11 @@ PRC_PARAMETERS=[ ("DEFAULT_PRC_DIR", '"etc"', '"etc"'), ("PRC_DIR_ENVVARS", '"PANDA_PRC_DIR"', '"PANDA_PRC_DIR"'), ("PRC_PATH_ENVVARS", '"PANDA_PRC_PATH"', '"PANDA_PRC_PATH"'), - ("PRC_PATH2_ENVVARS", '""', '""'), + ("PRC_PATH2_ENVVARS", 'UNDEF', 'UNDEF'), ("PRC_PATTERNS", '"*.prc"', '"*.prc"'), ("PRC_ENCRYPTED_PATTERNS", '"*.prc.pe"', '"*.prc.pe"'), ("PRC_ENCRYPTION_KEY", '""', '""'), - ("PRC_EXECUTABLE_PATTERNS", '""', '""'), + ("PRC_EXECUTABLE_PATTERNS", 'UNDEF', 'UNDEF'), ("PRC_EXECUTABLE_ARGS_ENVVAR", '"PANDA_PRC_XARGS"', '"PANDA_PRC_XARGS"'), ("PRC_PUBLIC_KEYS_FILENAME", '""', '""'), ("PRC_RESPECT_TRUST_LEVEL", 'UNDEF', 'UNDEF'), @@ -2558,6 +2630,26 @@ def WriteConfigSettings(): dtool_config["PHAVE_LOCKF"] = 'UNDEF' dtool_config["HAVE_VIDEO4LINUX"] = 'UNDEF' + if (GetTarget() == "emscripten"): + # There are no threads in JavaScript, so don't bother using them. + dtool_config["HAVE_THREADS"] = 'UNDEF' + dtool_config["DO_PIPELINING"] = 'UNDEF' + dtool_config["HAVE_POSIX_THREADS"] = 'UNDEF' + dtool_config["IS_LINUX"] = 'UNDEF' + dtool_config["HAVE_VIDEO4LINUX"] = 'UNDEF' + dtool_config["HAVE_NET"] = 'UNDEF' + dtool_config["PHAVE_LINUX_INPUT_H"] = 'UNDEF' + dtool_config["HAVE_X11"] = 'UNDEF' + dtool_config["HAVE_GLX"] = 'UNDEF' + + # There are no environment vars either, or default prc files. + prc_parameters["DEFAULT_PRC_DIR"] = 'UNDEF' + prc_parameters["PRC_DIR_ENVVARS"] = 'UNDEF' + prc_parameters["PRC_PATH_ENVVARS"] = 'UNDEF' + prc_parameters["PRC_PATH2_ENVVARS"] = 'UNDEF' + prc_parameters["PRC_PATTERNS"] = 'UNDEF' + prc_parameters["PRC_ENCRYPTED_PATTERNS"] = 'UNDEF' + if (GetOptimize() <= 2 and GetTarget() == "windows"): dtool_config["USE_DEBUG_PYTHON"] = '1' @@ -2571,7 +2663,7 @@ def WriteConfigSettings(): if (GetOptimize() <= 3): dtool_config["DO_COLLISION_RECORDING"] = '1' - if (GetOptimize() <= 3): + if (GetOptimize() <= 3) and GetTarget() != 'emscripten': dtool_config["DO_MEMORY_USAGE"] = '1' if (GetOptimize() <= 3): @@ -2779,7 +2871,8 @@ del_files = ['core.py', 'core.pyc', 'core.pyo', '_core.pyd', '_core.so', 'direct.py', 'direct.pyc', 'direct.pyo', '_direct.pyd', '_direct.so', - 'dtoolconfig.pyd', 'dtoolconfig.so'] + 'dtoolconfig.pyd', 'dtoolconfig.so', + 'net.pyd', 'net.so'] for basename in del_files: path = os.path.join(GetOutputDir(), 'panda3d', basename) @@ -2827,6 +2920,20 @@ if not PkgSkip("PYTHON"): if __debug__: print("Warning: panda3d.dtoolconfig is deprecated, use panda3d.interrogatedb instead.") from .interrogatedb import * +""") + + # Add this for forward compatibility. + ConditionalWriteFile(GetOutputDir() + '/panda3d/net.py', """\ +__all__ = 'BufferedDatagramConnection', 'Buffered_DatagramConnection', 'Connection', 'ConnectionListener', 'ConnectionManager', 'ConnectionReader', 'ConnectionWriter', 'DatagramGeneratorNet', 'DatagramSinkNet', 'Dtool_BorrowThisReference', 'Dtool_PyNativeInterface', 'NetAddress', 'NetDatagram', 'PointerToBaseConnection', 'PointerToBase_Connection', 'PointerToConnection', 'PointerTo_Connection', 'QueuedConnectionListener', 'QueuedConnectionManager', 'QueuedConnectionReader', 'QueuedReturnConnectionListenerData', 'QueuedReturnDatagram', 'QueuedReturnNetDatagram', 'QueuedReturnPointerToConnection', 'QueuedReturn_ConnectionListenerData', 'QueuedReturn_Datagram', 'QueuedReturn_NetDatagram', 'QueuedReturn_PointerTo_Connection', 'RecentConnectionReader', 'SocketAddress', 'SocketFdset', 'SocketIP', 'SocketTCP', 'SocketTCPListen', 'SocketUDP', 'SocketUDPIncoming', 'SocketUDPOutgoing', 'Socket_Address', 'Socket_IP', 'Socket_TCP', 'Socket_TCP_Listen', 'Socket_UDP', 'Socket_UDP_Incoming', 'Socket_UDP_Outgoing', 'Socket_fdset' + +from . import core + +scope = globals() +for name in __all__: + if hasattr(core, name): + scope[name] = getattr(core, name) + +del core, scope, name """) # PandaModules is now deprecated; generate a shim for backward compatibility. @@ -2918,7 +3025,7 @@ build_apps = direct.dist.commands:build_apps bdist_apps = direct.dist.commands:bdist_apps [setuptools.finalize_distribution_options] -build_apps = direct.dist.commands:finalize_distribution_options +build_apps = direct.dist._dist_hooks:finalize_distribution_options """ if not PkgSkip("DIRECT"): @@ -3820,7 +3927,9 @@ TargetAdd('libp3gsgbase.in', opts=['IMOD:panda3d.core', 'ILIB:libp3gsgbase', 'SR OPTS=['DIR:panda/src/pnmimage', 'BUILDING:PANDA', 'ZLIB'] TargetAdd('p3pnmimage_composite1.obj', opts=OPTS, input='p3pnmimage_composite1.cxx') TargetAdd('p3pnmimage_composite2.obj', opts=OPTS, input='p3pnmimage_composite2.cxx') -TargetAdd('p3pnmimage_convert_srgb_sse2.obj', opts=OPTS+['SSE2'], input='convert_srgb_sse2.cxx') + +if GetTarget() != "emscripten": + TargetAdd('p3pnmimage_convert_srgb_sse2.obj', opts=OPTS+['SSE2'], input='convert_srgb_sse2.cxx') OPTS=['DIR:panda/src/pnmimage', 'ZLIB'] IGATEFILES=GetDirectoryContents('panda/src/pnmimage', ["*.h", "*_composite*.cxx"]) @@ -3832,27 +3941,29 @@ PyTargetAdd('p3pnmimage_pfmFile_ext.obj', opts=OPTS, input='pfmFile_ext.cxx') # DIRECTORY: panda/src/nativenet/ # -OPTS=['DIR:panda/src/nativenet', 'BUILDING:PANDA'] -TargetAdd('p3nativenet_composite1.obj', opts=OPTS, input='p3nativenet_composite1.cxx') +if GetTarget() != 'emscripten': + OPTS=['DIR:panda/src/nativenet', 'BUILDING:PANDA'] + TargetAdd('p3nativenet_composite1.obj', opts=OPTS, input='p3nativenet_composite1.cxx') OPTS=['DIR:panda/src/nativenet'] IGATEFILES=GetDirectoryContents('panda/src/nativenet', ["*.h", "*_composite*.cxx"]) TargetAdd('libp3nativenet.in', opts=OPTS, input=IGATEFILES) -TargetAdd('libp3nativenet.in', opts=['IMOD:panda3d.core', 'ILIB:libp3nativenet', 'SRCDIR:panda/src/nativenet']) +TargetAdd('libp3nativenet.in', opts=['IMOD:panda3d.net', 'ILIB:libp3nativenet', 'SRCDIR:panda/src/nativenet']) # # DIRECTORY: panda/src/net/ # -OPTS=['DIR:panda/src/net', 'BUILDING:PANDA'] -TargetAdd('p3net_composite1.obj', opts=OPTS, input='p3net_composite1.cxx') -TargetAdd('p3net_composite2.obj', opts=OPTS, input='p3net_composite2.cxx') +if GetTarget() != 'emscripten': + OPTS=['DIR:panda/src/net', 'BUILDING:PANDA'] + TargetAdd('p3net_composite1.obj', opts=OPTS, input='p3net_composite1.cxx') + TargetAdd('p3net_composite2.obj', opts=OPTS, input='p3net_composite2.cxx') OPTS=['DIR:panda/src/net'] IGATEFILES=GetDirectoryContents('panda/src/net', ["*.h", "*_composite*.cxx"]) IGATEFILES.remove("datagram_ui.h") TargetAdd('libp3net.in', opts=OPTS, input=IGATEFILES) -TargetAdd('libp3net.in', opts=['IMOD:panda3d.core', 'ILIB:libp3net', 'SRCDIR:panda/src/net']) +TargetAdd('libp3net.in', opts=['IMOD:panda3d.net', 'ILIB:libp3net', 'SRCDIR:panda/src/net']) # # DIRECTORY: panda/src/pstatclient/ @@ -4184,7 +4295,6 @@ TargetAdd('libpanda.dll', input='p3pnmimagetypes_composite1.obj') TargetAdd('libpanda.dll', input='p3pnmimagetypes_composite2.obj') TargetAdd('libpanda.dll', input='p3pnmimage_composite1.obj') TargetAdd('libpanda.dll', input='p3pnmimage_composite2.obj') -TargetAdd('libpanda.dll', input='p3pnmimage_convert_srgb_sse2.obj') TargetAdd('libpanda.dll', input='p3text_composite1.obj') TargetAdd('libpanda.dll', input='p3text_composite2.obj') TargetAdd('libpanda.dll', input='p3tform_composite1.obj') @@ -4194,14 +4304,17 @@ TargetAdd('libpanda.dll', input='p3putil_composite2.obj') TargetAdd('libpanda.dll', input='p3audio_composite1.obj') TargetAdd('libpanda.dll', input='p3pgui_composite1.obj') TargetAdd('libpanda.dll', input='p3pgui_composite2.obj') -TargetAdd('libpanda.dll', input='p3net_composite1.obj') -TargetAdd('libpanda.dll', input='p3net_composite2.obj') -TargetAdd('libpanda.dll', input='p3nativenet_composite1.obj') TargetAdd('libpanda.dll', input='p3pandabase_pandabase.obj') TargetAdd('libpanda.dll', input='libpandaexpress.dll') TargetAdd('libpanda.dll', input='libp3dtoolconfig.dll') TargetAdd('libpanda.dll', input='libp3dtool.dll') +if GetTarget() != "emscripten": + TargetAdd('libpanda.dll', input='p3net_composite1.obj') + TargetAdd('libpanda.dll', input='p3net_composite2.obj') + TargetAdd('libpanda.dll', input='p3nativenet_composite1.obj') + TargetAdd('libpanda.dll', input='p3pnmimage_convert_srgb_sse2.obj') + if PkgSkip("FREETYPE")==0: TargetAdd('libpanda.dll', input="p3pnmtext_composite1.obj") @@ -4239,11 +4352,13 @@ PyTargetAdd('core_module.obj', input='libp3text.in') PyTargetAdd('core_module.obj', input='libp3tform.in') PyTargetAdd('core_module.obj', input='libp3putil.in') PyTargetAdd('core_module.obj', input='libp3audio.in') -PyTargetAdd('core_module.obj', input='libp3nativenet.in') -PyTargetAdd('core_module.obj', input='libp3net.in') PyTargetAdd('core_module.obj', input='libp3pgui.in') PyTargetAdd('core_module.obj', input='libp3movies.in') +if GetTarget() != "emscripten": + PyTargetAdd('core_module.obj', input='libp3nativenet.in') + PyTargetAdd('core_module.obj', input='libp3net.in') + if PkgSkip("FREETYPE")==0: PyTargetAdd('core_module.obj', input='libp3pnmtext.in') @@ -4285,8 +4400,10 @@ PyTargetAdd('core.pyd', input='libp3tform_igate.obj') PyTargetAdd('core.pyd', input='libp3putil_igate.obj') PyTargetAdd('core.pyd', input='libp3audio_igate.obj') PyTargetAdd('core.pyd', input='libp3pgui_igate.obj') -PyTargetAdd('core.pyd', input='libp3net_igate.obj') -PyTargetAdd('core.pyd', input='libp3nativenet_igate.obj') + +if GetTarget() != "emscripten": + PyTargetAdd('core.pyd', input='libp3net_igate.obj') + PyTargetAdd('core.pyd', input='libp3nativenet_igate.obj') if PkgSkip("FREETYPE")==0: PyTargetAdd('core.pyd', input="libp3pnmtext_igate.obj") @@ -4664,7 +4781,7 @@ if not PkgSkip("EGG"): # DIRECTORY: panda/src/x11display/ # -if GetTarget() not in ['windows', 'darwin'] and not PkgSkip("X11"): +if GetTarget() not in ['windows', 'darwin', 'emscripten'] and not PkgSkip("X11"): OPTS=['DIR:panda/src/x11display', 'BUILDING:PANDAX11', 'X11'] TargetAdd('p3x11display_composite1.obj', opts=OPTS, input='p3x11display_composite1.cxx') @@ -4672,7 +4789,7 @@ if GetTarget() not in ['windows', 'darwin'] and not PkgSkip("X11"): # DIRECTORY: panda/src/glxdisplay/ # -if GetTarget() not in ['windows', 'darwin'] and not PkgSkip("GL") and not PkgSkip("X11"): +if GetTarget() not in ['windows', 'darwin', 'emscripten'] and not PkgSkip("GL") and not PkgSkip("X11"): DefSymbol('GLX', 'HAVE_GLX', '') OPTS=['DIR:panda/src/glxdisplay', 'BUILDING:PANDAGL', 'GL', 'NVIDIACG', 'CGGL', 'GLX'] TargetAdd('p3glxdisplay_composite1.obj', opts=OPTS, input='p3glxdisplay_composite1.cxx') @@ -4802,6 +4919,21 @@ if GetTarget() != 'android' and not PkgSkip("EGL") and not PkgSkip("GLES2"): TargetAdd('libpandagles2.dll', input=COMMON_PANDA_LIBS) TargetAdd('libpandagles2.dll', opts=['MODULE', 'GLES2', 'EGL', 'X11']) +# +# DIRECTORY: panda/src/webgldisplay/ +# + +if GetTarget() == 'emscripten' and not PkgSkip("GLES2"): + DefSymbol('GLES2', 'OPENGLES_2', '') + LinkFlag('GLES2', '-s GL_ENABLE_GET_PROC_ADDRESS=1') + OPTS=['DIR:panda/src/webgldisplay', 'DIR:panda/src/glstuff', 'BUILDING:PANDAGLES2', 'GLES2', 'WEBGL'] + TargetAdd('p3webgldisplay_webgldisplay_composite1.obj', opts=OPTS, input='p3webgldisplay_composite1.cxx') + TargetAdd('libp3webgldisplay.dll', input='p3gles2gsg_config_gles2gsg.obj') + TargetAdd('libp3webgldisplay.dll', input='p3gles2gsg_gles2gsg.obj') + TargetAdd('libp3webgldisplay.dll', input='p3webgldisplay_webgldisplay_composite1.obj') + TargetAdd('libp3webgldisplay.dll', input=COMMON_PANDA_LIBS) + TargetAdd('libp3webgldisplay.dll', opts=['MODULE', 'GLES2', 'WEBGL']) + # # DIRECTORY: panda/src/ode/ # @@ -4987,6 +5119,8 @@ if not PkgSkip("PVIEW"): if GetLinkAllStatic() and not PkgSkip("GL"): TargetAdd('pview.exe', input='libpandagl.dll') + if GetTarget() == "emscripten" and not PkgSkip("GLES2"): + TargetAdd('pview.exe', input='libp3webgldisplay.dll') # # DIRECTORY: panda/src/android/ @@ -5153,7 +5287,7 @@ if not PkgSkip("DIRECT"): # DIRECTORY: direct/src/distributed/ # -if not PkgSkip("DIRECT"): +if not PkgSkip("DIRECT") and GetTarget() != 'emscripten': OPTS=['DIR:direct/src/distributed', 'DIR:direct/src/dcparser', 'WITHINPANDA', 'BUILDING:DIRECT'] TargetAdd('p3distributed_config_distributed.obj', opts=OPTS, input='config_distributed.cxx') @@ -5221,7 +5355,8 @@ if not PkgSkip("DIRECT"): if GetTarget() == 'darwin': TargetAdd('libp3direct.dll', input='p3showbase_showBase_assist.obj') TargetAdd('libp3direct.dll', input='p3deadrec_composite1.obj') - TargetAdd('libp3direct.dll', input='p3distributed_config_distributed.obj') + if GetTarget() != 'emscripten': + TargetAdd('libp3direct.dll', input='p3distributed_config_distributed.obj') TargetAdd('libp3direct.dll', input='p3interval_composite1.obj') TargetAdd('libp3direct.dll', input='p3motiontrail_config_motiontrail.obj') TargetAdd('libp3direct.dll', input='p3motiontrail_cMotionTrail.obj') @@ -5232,7 +5367,8 @@ if not PkgSkip("DIRECT"): PyTargetAdd('direct_module.obj', input='libp3showbase.in') PyTargetAdd('direct_module.obj', input='libp3deadrec.in') PyTargetAdd('direct_module.obj', input='libp3interval.in') - PyTargetAdd('direct_module.obj', input='libp3distributed.in') + if GetTarget() != 'emscripten': + PyTargetAdd('direct_module.obj', input='libp3distributed.in') PyTargetAdd('direct_module.obj', input='libp3motiontrail.in') PyTargetAdd('direct_module.obj', opts=['IMOD:panda3d.direct', 'ILIB:direct', 'IMPORT:panda3d.core']) @@ -5241,15 +5377,17 @@ if not PkgSkip("DIRECT"): PyTargetAdd('direct.pyd', input='libp3deadrec_igate.obj') PyTargetAdd('direct.pyd', input='libp3interval_igate.obj') PyTargetAdd('direct.pyd', input='p3interval_cInterval_ext.obj') - PyTargetAdd('direct.pyd', input='libp3distributed_igate.obj') + if GetTarget() != 'emscripten': + PyTargetAdd('direct.pyd', input='libp3distributed_igate.obj') PyTargetAdd('direct.pyd', input='libp3motiontrail_igate.obj') # These are part of direct.pyd, not libp3direct.dll, because they rely on # the Python libraries. If a C++ user needs these modules, we can move them # back and filter out the Python-specific code. PyTargetAdd('direct.pyd', input='p3dcparser_ext_composite.obj') - PyTargetAdd('direct.pyd', input='p3distributed_cConnectionRepository.obj') - PyTargetAdd('direct.pyd', input='p3distributed_cDistributedSmoothNodeBase.obj') + if GetTarget() != 'emscripten': + PyTargetAdd('direct.pyd', input='p3distributed_cConnectionRepository.obj') + PyTargetAdd('direct.pyd', input='p3distributed_cDistributedSmoothNodeBase.obj') PyTargetAdd('direct.pyd', input='direct_module.obj') PyTargetAdd('direct.pyd', input='libp3direct.dll') @@ -6077,7 +6215,7 @@ if not PkgSkip("PANDATOOL"): # DIRECTORY: pandatool/src/text-stats/ # -if not PkgSkip("PANDATOOL"): +if not PkgSkip("PANDATOOL") and GetTarget() != 'emscripten': OPTS=['DIR:pandatool/src/text-stats'] TargetAdd('text-stats_textMonitor.obj', opts=OPTS, input='textMonitor.cxx') TargetAdd('text-stats_textStats.obj', opts=OPTS, input='textStats.cxx') @@ -6362,6 +6500,9 @@ if PkgSkip("PYTHON") == 0: PyTargetAdd('deploy-stub.exe', input='frozen_dllmain.obj') PyTargetAdd('deploy-stub.exe', opts=['WINSHELL', 'DEPLOYSTUB', 'NOICON', 'ANDROID']) + if GetTarget() == 'emscripten': + PyTargetAdd('deploy-stub.exe', opts=['ZLIB']) + if GetTarget() == 'windows': PyTargetAdd('deploy-stubw.exe', input='deploy-stub.obj') PyTargetAdd('deploy-stubw.exe', input='frozen_dllmain.obj') diff --git a/makepanda/makepandacore.py b/makepanda/makepandacore.py index a04e6d4893..1cd99c41f7 100644 --- a/makepanda/makepandacore.py +++ b/makepanda/makepandacore.py @@ -46,6 +46,14 @@ ANDROID_API = None SYS_LIB_DIRS = [] SYS_INC_DIRS = [] DEBUG_DEPENDENCIES = False +if sys.platform == "darwin" or sys.platform.startswith("freebsd"): + DEFAULT_CC = "clang" + DEFAULT_CXX = "clang++" +else: + DEFAULT_CC = "gcc" + DEFAULT_CXX = "g++" +DEFAULT_AR = "ar" +DEFAULT_RANLIB = "ranlib" # Is the current Python a 32-bit or 64-bit build? There doesn't # appear to be a universal test for this. @@ -353,6 +361,7 @@ def SetTarget(target, arch=None): be called *before* any calls are made to GetOutputDir, GetCC, etc.""" global TARGET, TARGET_ARCH, HAS_TARGET_ARCH global TOOLCHAIN_PREFIX + global DEFAULT_CC, DEFAULT_CXX, DEFAULT_AR, DEFAULT_RANLIB host = GetHost() host_arch = GetHostArch() @@ -376,6 +385,9 @@ def SetTarget(target, arch=None): exit("Windows architecture must be x86 or x64") elif target == 'darwin': + DEFAULT_CC = "clang" + DEFAULT_CXX = "clang++" + if arch == 'amd64': arch = 'x86_64' if arch == 'aarch64': @@ -437,6 +449,8 @@ def SetTarget(target, arch=None): ANDROID_TRIPLE += str(ANDROID_API) TOOLCHAIN_PREFIX = ANDROID_TRIPLE + '-' + DEFAULT_CC = "clang" + DEFAULT_CXX = "clang++" elif target == 'linux': if arch is not None: @@ -445,7 +459,19 @@ def SetTarget(target, arch=None): elif host != 'linux': exit('Should specify an architecture when building for Linux') + elif target == 'emscripten': + DEFAULT_CC = "emcc" + DEFAULT_CXX = "em++" + DEFAULT_AR = "emar" + DEFAULT_RANLIB = "emranlib" + + arch = "wasm32" + elif target == host: + if target == 'freebsd': + DEFAULT_CC = "clang" + DEFAULT_CXX = "clang++" + if arch is None or arch == host_arch: # Not a cross build. pass @@ -486,16 +512,10 @@ def CrossCompiling(): return GetTarget() != GetHost() def GetCC(): - if TARGET in ('darwin', 'freebsd', 'android'): - return os.environ.get('CC', TOOLCHAIN_PREFIX + 'clang') - else: - return os.environ.get('CC', TOOLCHAIN_PREFIX + 'gcc') + return os.environ.get('CC', TOOLCHAIN_PREFIX + DEFAULT_CC) def GetCXX(): - if TARGET in ('darwin', 'freebsd', 'android'): - return os.environ.get('CXX', TOOLCHAIN_PREFIX + 'clang++') - else: - return os.environ.get('CXX', TOOLCHAIN_PREFIX + 'g++') + return os.environ.get('CXX', TOOLCHAIN_PREFIX + DEFAULT_CXX) def GetStrip(): # Hack @@ -507,16 +527,16 @@ def GetStrip(): def GetAR(): # Hack if TARGET == 'android': - return TOOLCHAIN_PREFIX + 'ar' + return TOOLCHAIN_PREFIX + DEFAULT_AR else: - return 'ar' + return DEFAULT_AR def GetRanlib(): # Hack if TARGET == 'android': - return TOOLCHAIN_PREFIX + 'ranlib' + return TOOLCHAIN_PREFIX + DEFAULT_RANLIB else: - return 'ranlib' + return DEFAULT_RANLIB BISON = None def GetBison(): @@ -1393,6 +1413,9 @@ def GetThirdpartyDir(): elif (target == 'android'): THIRDPARTYDIR = base + "/android-libs-%s/" % (target_arch) + elif (target == 'emscripten'): + THIRDPARTYDIR = base + "/emscripten-libs/" + else: Warn("Unsupported platform:", target) return @@ -2844,6 +2867,8 @@ LIBDIRECTORIES = [] FRAMEWORKDIRECTORIES = [] LIBNAMES = [] DEFSYMBOLS = [] +COMPILEFLAGS = [] +LINKFLAGS = [] def IncDirectory(opt, dir): INCDIRECTORIES.append((opt, dir)) @@ -2907,6 +2932,12 @@ def LibName(opt, name): def DefSymbol(opt, sym, val=""): DEFSYMBOLS.append((opt, sym, val)) +def CompileFlag(opt, flag): + COMPILEFLAGS.append((opt, flag)) + +def LinkFlag(opt, flag): + LINKFLAGS.append((opt, flag)) + ######################################################################## # # This subroutine prepares the environment for the build. @@ -2972,7 +3003,9 @@ def SetupBuildEnvironment(compiler): sysroot_flag = " -target " + ANDROID_TRIPLE # Extract the dirs from the line that starts with 'libraries: ='. - cmd = GetCXX() + " -print-search-dirs" + sysroot_flag + # The -E is mostly to keep emscripten happy by preventing it from + # running the compiler and complaining about the lack of input files. + cmd = GetCXX() + " -E -print-search-dirs" + sysroot_flag handle = os.popen(cmd) for line in handle: if not line.startswith('libraries: ='): @@ -3380,11 +3413,19 @@ def SetOrigExt(x, v): ORIG_EXT[x] = v def GetExtensionSuffix(): - if GetTarget() == 'windows': - if GetTargetArch() == 'x64': - return '.cp%d%d-win_amd64.pyd' % (sys.version_info[:2]) + target = GetTarget() + if target == 'windows': + if GetOptimize() <= 2: + dllext = '_d' else: - return '.cp%d%d-win32.pyd' % (sys.version_info[:2]) + dllext = '' + + if GetTargetArch() == 'x64': + return dllext + '.cp%d%d-win_amd64.pyd' % (sys.version_info[:2]) + else: + return dllext + '.cp%d%d-win32.pyd' % (sys.version_info[:2]) + elif target == 'emscripten': + return '.so' elif CrossCompiling(): return '.{0}.so'.format(GetPythonABI()) else: @@ -3455,6 +3496,15 @@ def CalcLocation(fn, ipath): if (fn.endswith(".rsrc")): return OUTPUTDIR+"/tmp/"+fn if (fn.endswith(".plugin")):return OUTPUTDIR+"/plugins/"+fn if (fn.endswith(".app")): return OUTPUTDIR+"/bin/"+fn + elif (target == 'emscripten'): + if (fn.endswith(".obj")): return OUTPUTDIR+"/tmp/"+fn[:-4]+".o" + if (fn.endswith(".dll")): return OUTPUTDIR+"/lib/"+fn[:-4]+".o" + if (fn.endswith(".pyd")): return OUTPUTDIR+"/panda3d/"+fn[:-4]+".o" + if (fn.endswith(".mll")): return OUTPUTDIR+"/plugins/"+fn + if (fn.endswith(".plugin")):return OUTPUTDIR+"/plugins/"+fn[:-7]+dllext+".js" + if (fn.endswith(".exe")): return OUTPUTDIR+"/bin/"+fn[:-4]+".js" + if (fn.endswith(".lib")): return OUTPUTDIR+"/lib/"+fn[:-4]+".a" + if (fn.endswith(".ilb")): return OUTPUTDIR+"/tmp/"+fn[:-4]+".a" else: if (fn.endswith(".obj")): return OUTPUTDIR+"/tmp/"+fn[:-4]+".o" if (fn.endswith(".dll")): return OUTPUTDIR+"/lib/"+fn[:-4]+".so" @@ -3679,10 +3729,17 @@ def TargetAdd(target, dummy=0, opts=[], input=[], dep=[], ipath=None, winrc=None if GetLinkAllStatic() and ORIG_EXT[fullinput] == '.lib' and fullinput in TARGET_TABLE: tdep = TARGET_TABLE[fullinput] for y in tdep.inputs: - if ORIG_EXT[y] == '.lib': + if ORIG_EXT[y] == '.lib' and y not in t.inputs: t.inputs.append(y) - for opt, _ in LIBNAMES + LIBDIRECTORIES + FRAMEWORKDIRECTORIES: + for opt, _ in LIBNAMES + LIBDIRECTORIES + FRAMEWORKDIRECTORIES + LINKFLAGS + COMPILEFLAGS: + if opt in tdep.opts and opt not in t.opts: + t.opts.append(opt) + + elif GetTarget() == 'emscripten' and ORIG_EXT[fullinput] == '.dll' and fullinput in TARGET_TABLE: + # Transfer over flags like -s USE_LIBPNG=1 + tdep = TARGET_TABLE[fullinput] + for opt, _ in LINKFLAGS: if opt in tdep.opts and opt not in t.opts: t.opts.append(opt) diff --git a/makepanda/makewheel.py b/makepanda/makewheel.py index 5879b2546a..3b2f332260 100644 --- a/makepanda/makewheel.py +++ b/makepanda/makewheel.py @@ -878,7 +878,7 @@ if __debug__: entry_points += 'build_apps = direct.dist.commands:build_apps\n' entry_points += 'bdist_apps = direct.dist.commands:bdist_apps\n' entry_points += '[setuptools.finalize_distribution_options]\n' - entry_points += 'build_apps = direct.dist.commands:finalize_distribution_options\n' + entry_points += 'build_apps = direct.dist._dist_hooks:finalize_distribution_options\n' whl.write_file_data('panda3d_tools/__init__.py', PANDA3D_TOOLS_INIT.format(tools_init)) diff --git a/makepanda/test_wheel.py b/makepanda/test_wheel.py index 8742c8df6f..cfe270099e 100755 --- a/makepanda/test_wheel.py +++ b/makepanda/test_wheel.py @@ -41,7 +41,7 @@ def test_wheel(wheel, verbose=False): if sys.version_info >= (3, 10): packages += ["pytest>=6.2.4"] else: - packages += ["pytest"] + packages += ["pytest>=3.9.0"] if sys.version_info[0:2] == (3, 4): if sys.platform == "win32": @@ -50,6 +50,9 @@ def test_wheel(wheel, verbose=False): # See https://github.com/python-attrs/attrs/pull/807 packages += ["attrs<21"] + if sys.version_info >= (3, 12): + packages += ["setuptools"] + if subprocess.call([python, "-m", "pip", "install"] + packages) != 0: shutil.rmtree(envdir) sys.exit(1) @@ -59,7 +62,22 @@ def test_wheel(wheel, verbose=False): if verbose: test_cmd.append("--verbose") - exit_code = subprocess.call(test_cmd) + # Put the location of the python DLL on the path, for deploy-stub test + # This is needed because venv does not install a copy of the python DLL + env = None + if sys.platform == "win32": + deploy_libs = os.path.join(envdir, "Lib", "site-packages", "deploy_libs") + if os.path.isdir(deploy_libs): + # We have to do this dance because os.environ is case insensitive + env = dict(os.environ) + for key, value in env.items(): + if key.upper() == "PATH": + env[key] = deploy_libs + ";" + value + break + else: + env["PATH"] = deploy_libs + + exit_code = subprocess.call(test_cmd, env=env) shutil.rmtree(envdir) if exit_code != 0: diff --git a/panda/CMakeLists.txt b/panda/CMakeLists.txt index 72f5628ba2..cb33932d9c 100644 --- a/panda/CMakeLists.txt +++ b/panda/CMakeLists.txt @@ -60,6 +60,9 @@ add_subdirectory(src/wgldisplay) add_subdirectory(src/windisplay) add_subdirectory(src/x11display) +# Creates a metalib, so should go after +add_subdirectory(src/tinydisplay) + # For other components # bullet add_subdirectory(src/bullet) @@ -132,6 +135,18 @@ ${win32_init}") if __debug__: print(\"Warning: panda3d.dtoolconfig is deprecated, use panda3d.interrogatedb instead.\") from .interrogatedb import * +") + + set(net_file "__all__ = 'BufferedDatagramConnection', 'Buffered_DatagramConnection', 'Connection', 'ConnectionListener', 'ConnectionManager', 'ConnectionReader', 'ConnectionWriter', 'DatagramGeneratorNet', 'DatagramSinkNet', 'Dtool_BorrowThisReference', 'Dtool_PyNativeInterface', 'NetAddress', 'NetDatagram', 'PointerToBaseConnection', 'PointerToBase_Connection', 'PointerToConnection', 'PointerTo_Connection', 'QueuedConnectionListener', 'QueuedConnectionManager', 'QueuedConnectionReader', 'QueuedReturnConnectionListenerData', 'QueuedReturnDatagram', 'QueuedReturnNetDatagram', 'QueuedReturnPointerToConnection', 'QueuedReturn_ConnectionListenerData', 'QueuedReturn_Datagram', 'QueuedReturn_NetDatagram', 'QueuedReturn_PointerTo_Connection', 'RecentConnectionReader', 'SocketAddress', 'SocketFdset', 'SocketIP', 'SocketTCP', 'SocketTCPListen', 'SocketUDP', 'SocketUDPIncoming', 'SocketUDPOutgoing', 'Socket_Address', 'Socket_IP', 'Socket_TCP', 'Socket_TCP_Listen', 'Socket_UDP', 'Socket_UDP_Incoming', 'Socket_UDP_Outgoing', 'Socket_fdset' + +from . import core + +scope = globals() +for name in __all__: + if hasattr(core, name): + scope[name] = getattr(core, name) + +del core, scope, name ") if(IS_MULTICONFIG) @@ -139,10 +154,16 @@ from .interrogatedb import * # Generate an __init__.py in the per-configuration directory. file(WRITE "${PROJECT_BINARY_DIR}/${config}/panda3d/__init__.py" ${init_file}) file(WRITE "${PROJECT_BINARY_DIR}/${config}/panda3d/dtoolconfig.py" ${dtoolconfig_file}) + if(HAVE_NET) + file(WRITE "${PROJECT_BINARY_DIR}/${config}/panda3d/net.py" ${net_file}) + endif() endforeach(config) else() file(WRITE "${PROJECT_BINARY_DIR}/panda3d/__init__.py" ${init_file}) file(WRITE "${PROJECT_BINARY_DIR}/panda3d/dtoolconfig.py" ${dtoolconfig_file}) + if(HAVE_NET) + file(WRITE "${PROJECT_BINARY_DIR}/${config}/panda3d/net.py" ${net_file}) + endif() endif() # Also generate a panda3d.dist-info directory. diff --git a/panda/metalibs/pandagl/pandagl.cxx b/panda/metalibs/pandagl/pandagl.cxx index dfed9f2ba2..be59040afc 100644 --- a/panda/metalibs/pandagl/pandagl.cxx +++ b/panda/metalibs/pandagl/pandagl.cxx @@ -65,23 +65,21 @@ init_libpandagl() { */ int get_pipe_type_pandagl() { -#ifdef HAVE_WGL +#if defined(HAVE_WGL) return wglGraphicsPipe::get_class_type().get_index(); -#endif -#ifdef HAVE_COCOA +#elif defined(HAVE_COCOA) return CocoaGLGraphicsPipe::get_class_type().get_index(); -#endif -#ifdef HAVE_GLX +#elif defined(HAVE_GLX) return glxGraphicsPipe::get_class_type().get_index(); -#endif -#ifdef HAVE_EGL +#elif defined(HAVE_EGL) return eglGraphicsPipe::get_class_type().get_index(); -#endif +#else return 0; +#endif } #if defined(HAVE_EGL) && !defined(USE_X11) diff --git a/panda/src/audiotraits/openalAudioSound.cxx b/panda/src/audiotraits/openalAudioSound.cxx index f43bd5ca24..4bf8edf8b5 100644 --- a/panda/src/audiotraits/openalAudioSound.cxx +++ b/panda/src/audiotraits/openalAudioSound.cxx @@ -180,9 +180,20 @@ play() { if (_sd->_sample) { push_fresh_buffers(); + // The macOS implementation of alSourcePlay resets the offset, so we call + // it before and avoid calling restart_stalled_audio() afterwards (#1607) +#ifdef HAVE_OPENAL_FRAMEWORK + ALenum status; + alGetSourcei(_source, AL_SOURCE_STATE, &status); + if (status != AL_PLAYING) { + alSourcePlay(_source); + } +#endif alSourcef(_source, AL_SEC_OFFSET, _start_time); _stream_queued[0]._time_offset = _start_time; +#ifndef HAVE_OPENAL_FRAMEWORK restart_stalled_audio(); +#endif } else { audio_debug("Play: stream tell = " << _sd->_stream->tell() << " seeking " << _start_time); if (_sd->_stream->tell() != _start_time) { diff --git a/panda/src/bullet/bulletContactCallbacks.h b/panda/src/bullet/bulletContactCallbacks.h index a0e7e6c79f..53549ed10e 100644 --- a/panda/src/bullet/bulletContactCallbacks.h +++ b/panda/src/bullet/bulletContactCallbacks.h @@ -88,7 +88,12 @@ contact_added_callback(btManifoldPoint &cp, BulletManifoldPoint mp(cp); BulletContactCallbackData cbdata(mp, node0, node1, id0, id1, index0, index1); + // Release the world mutex object so that bullet methods can be called from the callback. + LightMutex &mutex = BulletWorld::get_global_lock(); + + mutex.release(); bullet_contact_added_callback->do_callback(&cbdata); + mutex.acquire(); } } diff --git a/panda/src/chan/animBundle.cxx b/panda/src/chan/animBundle.cxx index 8313516485..9b95b9fe4c 100644 --- a/panda/src/chan/animBundle.cxx +++ b/panda/src/chan/animBundle.cxx @@ -93,7 +93,7 @@ fillin(DatagramIterator &scan, BamReader *manager) { * Factory method to generate a AnimBundle object */ TypedWritable *AnimBundle:: -make_AnimBundle(const FactoryParams ¶ms) { +make_from_bam(const FactoryParams ¶ms) { AnimBundle *me = new AnimBundle; DatagramIterator scan; BamReader *manager; @@ -108,5 +108,5 @@ make_AnimBundle(const FactoryParams ¶ms) { */ void AnimBundle:: register_with_read_factory() { - BamReader::get_factory()->register_factory(get_class_type(), make_AnimBundle); + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); } diff --git a/panda/src/chan/animBundle.h b/panda/src/chan/animBundle.h index 77c07e26d7..0605381bff 100644 --- a/panda/src/chan/animBundle.h +++ b/panda/src/chan/animBundle.h @@ -56,7 +56,7 @@ public: static void register_with_read_factory(); virtual void write_datagram(BamWriter* manager, Datagram &me); - static TypedWritable *make_AnimBundle(const FactoryParams ¶ms); + static TypedWritable *make_from_bam(const FactoryParams ¶ms); protected: void fillin(DatagramIterator& scan, BamReader* manager); diff --git a/panda/src/chan/animChannelMatrixDynamic.cxx b/panda/src/chan/animChannelMatrixDynamic.cxx index 53b2771685..731dcf8215 100644 --- a/panda/src/chan/animChannelMatrixDynamic.cxx +++ b/panda/src/chan/animChannelMatrixDynamic.cxx @@ -246,7 +246,7 @@ fillin(DatagramIterator &scan, BamReader *manager) { * Factory method to generate an AnimChannelMatrixDynamic object. */ TypedWritable *AnimChannelMatrixDynamic:: -make_AnimChannelMatrixDynamic(const FactoryParams ¶ms) { +make_from_bam(const FactoryParams ¶ms) { AnimChannelMatrixDynamic *me = new AnimChannelMatrixDynamic; DatagramIterator scan; BamReader *manager; @@ -261,5 +261,5 @@ make_AnimChannelMatrixDynamic(const FactoryParams ¶ms) { */ void AnimChannelMatrixDynamic:: register_with_read_factory() { - BamReader::get_factory()->register_factory(get_class_type(), make_AnimChannelMatrixDynamic); + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); } diff --git a/panda/src/chan/animChannelMatrixDynamic.h b/panda/src/chan/animChannelMatrixDynamic.h index 5602f027c6..449819f367 100644 --- a/panda/src/chan/animChannelMatrixDynamic.h +++ b/panda/src/chan/animChannelMatrixDynamic.h @@ -78,7 +78,7 @@ public: virtual int complete_pointers(TypedWritable **plist, BamReader *manager); void fillin(DatagramIterator &scan, BamReader *manager); - static TypedWritable *make_AnimChannelMatrixDynamic(const FactoryParams ¶ms); + static TypedWritable *make_from_bam(const FactoryParams ¶ms); public: virtual TypeHandle get_type() const { diff --git a/panda/src/chan/animChannelMatrixXfmTable.cxx b/panda/src/chan/animChannelMatrixXfmTable.cxx index 5370a9833e..247f35512b 100644 --- a/panda/src/chan/animChannelMatrixXfmTable.cxx +++ b/panda/src/chan/animChannelMatrixXfmTable.cxx @@ -511,7 +511,7 @@ fillin(DatagramIterator &scan, BamReader *manager) { * Factory method to generate an AnimChannelMatrixXfmTable object. */ TypedWritable *AnimChannelMatrixXfmTable:: -make_AnimChannelMatrixXfmTable(const FactoryParams ¶ms) { +make_from_bam(const FactoryParams ¶ms) { AnimChannelMatrixXfmTable *me = new AnimChannelMatrixXfmTable; DatagramIterator scan; BamReader *manager; @@ -526,5 +526,5 @@ make_AnimChannelMatrixXfmTable(const FactoryParams ¶ms) { */ void AnimChannelMatrixXfmTable:: register_with_read_factory() { - BamReader::get_factory()->register_factory(get_class_type(), make_AnimChannelMatrixXfmTable); + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); } diff --git a/panda/src/chan/animChannelMatrixXfmTable.h b/panda/src/chan/animChannelMatrixXfmTable.h index 047f145453..f02e3fd717 100644 --- a/panda/src/chan/animChannelMatrixXfmTable.h +++ b/panda/src/chan/animChannelMatrixXfmTable.h @@ -77,7 +77,7 @@ public: static void register_with_read_factory(); virtual void write_datagram(BamWriter* manager, Datagram &me); - static TypedWritable *make_AnimChannelMatrixXfmTable(const FactoryParams ¶ms); + static TypedWritable *make_from_bam(const FactoryParams ¶ms); protected: void fillin(DatagramIterator& scan, BamReader* manager); diff --git a/panda/src/chan/animChannelScalarDynamic.cxx b/panda/src/chan/animChannelScalarDynamic.cxx index c69ad0e6b9..481f471fe1 100644 --- a/panda/src/chan/animChannelScalarDynamic.cxx +++ b/panda/src/chan/animChannelScalarDynamic.cxx @@ -174,7 +174,7 @@ fillin(DatagramIterator &scan, BamReader *manager) { * Factory method to generate a AnimChannelScalarDynamic object */ TypedWritable *AnimChannelScalarDynamic:: -make_AnimChannelScalarDynamic(const FactoryParams ¶ms) { +make_from_bam(const FactoryParams ¶ms) { AnimChannelScalarDynamic *me = new AnimChannelScalarDynamic; DatagramIterator scan; BamReader *manager; @@ -189,5 +189,5 @@ make_AnimChannelScalarDynamic(const FactoryParams ¶ms) { */ void AnimChannelScalarDynamic:: register_with_read_factory() { - BamReader::get_factory()->register_factory(get_class_type(), make_AnimChannelScalarDynamic); + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); } diff --git a/panda/src/chan/animChannelScalarDynamic.h b/panda/src/chan/animChannelScalarDynamic.h index 7455adb4b9..c79a7651d9 100644 --- a/panda/src/chan/animChannelScalarDynamic.h +++ b/panda/src/chan/animChannelScalarDynamic.h @@ -72,7 +72,7 @@ public: virtual int complete_pointers(TypedWritable **plist, BamReader *manager); void fillin(DatagramIterator &scan, BamReader *manager); - static TypedWritable *make_AnimChannelScalarDynamic(const FactoryParams ¶ms); + static TypedWritable *make_from_bam(const FactoryParams ¶ms); public: virtual TypeHandle get_type() const { diff --git a/panda/src/chan/animChannelScalarTable.cxx b/panda/src/chan/animChannelScalarTable.cxx index ae95b3d1ea..886cb8db9a 100644 --- a/panda/src/chan/animChannelScalarTable.cxx +++ b/panda/src/chan/animChannelScalarTable.cxx @@ -324,8 +324,8 @@ fillin(DatagramIterator& scan, BamReader* manager) { /** * Factory method to generate a AnimChannelScalarTable object */ -TypedWritable* AnimChannelScalarTable:: -make_AnimChannelScalarTable(const FactoryParams ¶ms) { +TypedWritable *AnimChannelScalarTable:: +make_from_bam(const FactoryParams ¶ms) { AnimChannelScalarTable *me = new AnimChannelScalarTable; DatagramIterator scan; BamReader *manager; @@ -340,5 +340,5 @@ make_AnimChannelScalarTable(const FactoryParams ¶ms) { */ void AnimChannelScalarTable:: register_with_read_factory() { - BamReader::get_factory()->register_factory(get_class_type(), make_AnimChannelScalarTable); + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); } diff --git a/panda/src/chan/animChannelScalarTable.h b/panda/src/chan/animChannelScalarTable.h index f9c626fc26..2c82ceb796 100644 --- a/panda/src/chan/animChannelScalarTable.h +++ b/panda/src/chan/animChannelScalarTable.h @@ -60,7 +60,7 @@ public: static void register_with_read_factory(); virtual void write_datagram(BamWriter* manager, Datagram &me); - static TypedWritable *make_AnimChannelScalarTable(const FactoryParams ¶ms); + static TypedWritable *make_from_bam(const FactoryParams ¶ms); protected: void fillin(DatagramIterator& scan, BamReader* manager); diff --git a/panda/src/chan/animGroup.cxx b/panda/src/chan/animGroup.cxx index 57124d6ac2..5c9200ff70 100644 --- a/panda/src/chan/animGroup.cxx +++ b/panda/src/chan/animGroup.cxx @@ -290,8 +290,8 @@ complete_pointers(TypedWritable **p_list, BamReader *) { /** * Factory method to generate a AnimGroup object */ -TypedWritable* AnimGroup:: -make_AnimGroup(const FactoryParams ¶ms) { +TypedWritable *AnimGroup:: +make_from_bam(const FactoryParams ¶ms) { AnimGroup *me = new AnimGroup; DatagramIterator scan; BamReader *manager; @@ -306,5 +306,5 @@ make_AnimGroup(const FactoryParams ¶ms) { */ void AnimGroup:: register_with_read_factory() { - BamReader::get_factory()->register_factory(get_class_type(), make_AnimGroup); + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); } diff --git a/panda/src/chan/animGroup.h b/panda/src/chan/animGroup.h index cc3fdb3394..f49bb88fcf 100644 --- a/panda/src/chan/animGroup.h +++ b/panda/src/chan/animGroup.h @@ -74,7 +74,7 @@ public: virtual int complete_pointers(TypedWritable **p_list, BamReader *manager); - static TypedWritable *make_AnimGroup(const FactoryParams ¶ms); + static TypedWritable *make_from_bam(const FactoryParams ¶ms); protected: void fillin(DatagramIterator& scan, BamReader* manager); diff --git a/panda/src/chan/movingPartMatrix.cxx b/panda/src/chan/movingPartMatrix.cxx index 0c8c7bc7bd..db9d143bbb 100644 --- a/panda/src/chan/movingPartMatrix.cxx +++ b/panda/src/chan/movingPartMatrix.cxx @@ -387,8 +387,8 @@ apply_control(PandaNode *node) { /** * Factory method to generate a MovingPartMatrix object */ -TypedWritable* MovingPartMatrix:: -make_MovingPartMatrix(const FactoryParams ¶ms) { +TypedWritable *MovingPartMatrix:: +make_from_bam(const FactoryParams ¶ms) { MovingPartMatrix *me = new MovingPartMatrix; DatagramIterator scan; BamReader *manager; @@ -403,5 +403,5 @@ make_MovingPartMatrix(const FactoryParams ¶ms) { */ void MovingPartMatrix:: register_with_read_factory() { - BamReader::get_factory()->register_factory(get_class_type(), make_MovingPartMatrix); + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); } diff --git a/panda/src/chan/movingPartMatrix.h b/panda/src/chan/movingPartMatrix.h index 364686555a..7e8aaa0e90 100644 --- a/panda/src/chan/movingPartMatrix.h +++ b/panda/src/chan/movingPartMatrix.h @@ -47,7 +47,7 @@ protected: public: static void register_with_read_factory(); - static TypedWritable *make_MovingPartMatrix(const FactoryParams ¶ms); + static TypedWritable *make_from_bam(const FactoryParams ¶ms); public: virtual TypeHandle get_type() const { diff --git a/panda/src/chan/movingPartScalar.cxx b/panda/src/chan/movingPartScalar.cxx index d0d03b4152..612f02afce 100644 --- a/panda/src/chan/movingPartScalar.cxx +++ b/panda/src/chan/movingPartScalar.cxx @@ -133,8 +133,8 @@ apply_control(PandaNode *node) { /** * Factory method to generate a MovingPartScalar object */ -TypedWritable* MovingPartScalar:: -make_MovingPartScalar(const FactoryParams ¶ms) { +TypedWritable *MovingPartScalar:: +make_from_bam(const FactoryParams ¶ms) { MovingPartScalar *me = new MovingPartScalar; DatagramIterator scan; BamReader *manager; @@ -149,5 +149,5 @@ make_MovingPartScalar(const FactoryParams ¶ms) { */ void MovingPartScalar:: register_with_read_factory() { - BamReader::get_factory()->register_factory(get_class_type(), make_MovingPartScalar); + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); } diff --git a/panda/src/chan/movingPartScalar.h b/panda/src/chan/movingPartScalar.h index ee55f2e7b8..8d3666ed87 100644 --- a/panda/src/chan/movingPartScalar.h +++ b/panda/src/chan/movingPartScalar.h @@ -45,7 +45,7 @@ protected: public: static void register_with_read_factory(); - static TypedWritable *make_MovingPartScalar(const FactoryParams ¶ms); + static TypedWritable *make_from_bam(const FactoryParams ¶ms); public: virtual TypeHandle get_type() const { diff --git a/panda/src/chan/partBundle.cxx b/panda/src/chan/partBundle.cxx index f3bb114637..076482cdd9 100644 --- a/panda/src/chan/partBundle.cxx +++ b/panda/src/chan/partBundle.cxx @@ -772,7 +772,7 @@ complete_pointers(TypedWritable **p_list, BamReader *manager) { /** * Factory method to generate a PartBundle object */ -TypedWritable* PartBundle:: +TypedWritable *PartBundle:: make_from_bam(const FactoryParams ¶ms) { PartBundle *me = new PartBundle; DatagramIterator scan; diff --git a/panda/src/chan/partGroup.cxx b/panda/src/chan/partGroup.cxx index 52cee4ce19..2be55b7d68 100644 --- a/panda/src/chan/partGroup.cxx +++ b/panda/src/chan/partGroup.cxx @@ -677,8 +677,8 @@ complete_pointers(TypedWritable **p_list, BamReader *manager) { /** * Factory method to generate a PartGroup object */ -TypedWritable* PartGroup:: -make_PartGroup(const FactoryParams ¶ms) { +TypedWritable *PartGroup:: +make_from_bam(const FactoryParams ¶ms) { PartGroup *me = new PartGroup; DatagramIterator scan; BamReader *manager; @@ -693,5 +693,5 @@ make_PartGroup(const FactoryParams ¶ms) { */ void PartGroup:: register_with_read_factory() { - BamReader::get_factory()->register_factory(get_class_type(), make_PartGroup); + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); } diff --git a/panda/src/chan/partGroup.h b/panda/src/chan/partGroup.h index 0dd9f8c7dd..9655a5792b 100644 --- a/panda/src/chan/partGroup.h +++ b/panda/src/chan/partGroup.h @@ -122,7 +122,7 @@ public: virtual int complete_pointers(TypedWritable **p_list, BamReader *manager); - static TypedWritable *make_PartGroup(const FactoryParams ¶ms); + static TypedWritable *make_from_bam(const FactoryParams ¶ms); protected: void fillin(DatagramIterator& scan, BamReader* manager); diff --git a/panda/src/char/characterJoint.cxx b/panda/src/char/characterJoint.cxx index 7e3e1c9b9a..c2dd79b3f9 100644 --- a/panda/src/char/characterJoint.cxx +++ b/panda/src/char/characterJoint.cxx @@ -534,8 +534,8 @@ complete_pointers(TypedWritable **p_list, BamReader* manager) { /** * Factory method to generate a CharacterJoint object */ -TypedWritable* CharacterJoint:: -make_CharacterJoint(const FactoryParams ¶ms) { +TypedWritable *CharacterJoint:: +make_from_bam(const FactoryParams ¶ms) { CharacterJoint *me = new CharacterJoint; DatagramIterator scan; BamReader *manager; @@ -550,5 +550,5 @@ make_CharacterJoint(const FactoryParams ¶ms) { */ void CharacterJoint:: register_with_read_factory() { - BamReader::get_factory()->register_factory(get_class_type(), make_CharacterJoint); + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); } diff --git a/panda/src/char/characterJoint.h b/panda/src/char/characterJoint.h index 49be4d145b..7d261578a3 100644 --- a/panda/src/char/characterJoint.h +++ b/panda/src/char/characterJoint.h @@ -91,7 +91,7 @@ public: virtual int complete_pointers(TypedWritable **p_list, BamReader *manager); - static TypedWritable *make_CharacterJoint(const FactoryParams ¶ms); + static TypedWritable *make_from_bam(const FactoryParams ¶ms); protected: void fillin(DatagramIterator& scan, BamReader* manager); diff --git a/panda/src/char/characterJointBundle.cxx b/panda/src/char/characterJointBundle.cxx index 86a43f7e13..dda107a9a5 100644 --- a/panda/src/char/characterJointBundle.cxx +++ b/panda/src/char/characterJointBundle.cxx @@ -97,9 +97,8 @@ r_set_character(PartGroup *group, Character *character) { /** * Factory method to generate a CharacterJointBundle object */ -TypedWritable* CharacterJointBundle:: -make_CharacterJointBundle(const FactoryParams ¶ms) -{ +TypedWritable *CharacterJointBundle:: +make_from_bam(const FactoryParams ¶ms) { CharacterJointBundle *me = new CharacterJointBundle; DatagramIterator scan; BamReader *manager; @@ -114,7 +113,6 @@ make_CharacterJointBundle(const FactoryParams ¶ms) * Factory method to generate a CharacterJointBundle object */ void CharacterJointBundle:: -register_with_read_factory() -{ - BamReader::get_factory()->register_factory(get_class_type(), make_CharacterJointBundle); +register_with_read_factory() { + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); } diff --git a/panda/src/char/characterJointBundle.h b/panda/src/char/characterJointBundle.h index e1c93e1842..7d799b44dc 100644 --- a/panda/src/char/characterJointBundle.h +++ b/panda/src/char/characterJointBundle.h @@ -47,7 +47,7 @@ private: public: static void register_with_read_factory(); - static TypedWritable *make_CharacterJointBundle(const FactoryParams ¶ms); + static TypedWritable *make_from_bam(const FactoryParams ¶ms); public: virtual TypeHandle get_type() const { diff --git a/panda/src/char/characterSlider.cxx b/panda/src/char/characterSlider.cxx index 26d0f35053..0671bbdf79 100644 --- a/panda/src/char/characterSlider.cxx +++ b/panda/src/char/characterSlider.cxx @@ -85,9 +85,8 @@ update_internals(PartBundle *, PartGroup *, bool, bool, Thread *current_thread) /** * Factory method to generate a CharacterSlider object */ -TypedWritable* CharacterSlider:: -make_CharacterSlider(const FactoryParams ¶ms) -{ +TypedWritable *CharacterSlider:: +make_from_bam(const FactoryParams ¶ms) { CharacterSlider *me = new CharacterSlider; DatagramIterator scan; BamReader *manager; @@ -101,7 +100,6 @@ make_CharacterSlider(const FactoryParams ¶ms) * Factory method to generate a CharacterSlider object */ void CharacterSlider:: -register_with_read_factory() -{ - BamReader::get_factory()->register_factory(get_class_type(), make_CharacterSlider); +register_with_read_factory() { + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); } diff --git a/panda/src/char/characterSlider.h b/panda/src/char/characterSlider.h index 6a5da971b8..3184b2546a 100644 --- a/panda/src/char/characterSlider.h +++ b/panda/src/char/characterSlider.h @@ -49,7 +49,7 @@ private: public: static void register_with_read_factory(); - static TypedWritable *make_CharacterSlider(const FactoryParams ¶ms); + static TypedWritable *make_from_bam(const FactoryParams ¶ms); public: virtual TypeHandle get_type() const { diff --git a/panda/src/cocoadisplay/cocoaGraphicsPipe.h b/panda/src/cocoadisplay/cocoaGraphicsPipe.h index 420d2e6a01..60485b735d 100644 --- a/panda/src/cocoadisplay/cocoaGraphicsPipe.h +++ b/panda/src/cocoadisplay/cocoaGraphicsPipe.h @@ -16,8 +16,10 @@ #include "pandabase.h" #include "graphicsPipe.h" +#include "patomic.h" #include +#include /** * This graphics pipe represents the base class for pipes that create @@ -28,17 +30,28 @@ public: CocoaGraphicsPipe(CGDirectDisplayID display = CGMainDisplayID()); virtual ~CocoaGraphicsPipe(); - INLINE CGDirectDisplayID get_display_id() const; - -public: virtual PreferredWindowThread get_preferred_window_thread() const; + INLINE CGDirectDisplayID get_display_id() const; + + bool init_vsync(uint32_t &counter); + void wait_vsync(uint32_t &counter, bool adaptive=false); + private: + static CVReturn display_link_cb(CVDisplayLinkRef link, const CVTimeStamp *now, + const CVTimeStamp *output_time, + CVOptionFlags flags_in, CVOptionFlags *flags_out, + void *context); + void load_display_information(); // This is the Quartz display identifier. CGDirectDisplayID _display; + CVDisplayLinkRef _display_link = nullptr; + patomic _last_wait_frame {0}; + uint32_t _vsync_counter = 0; + public: static TypeHandle get_class_type() { return _type_handle; diff --git a/panda/src/cocoadisplay/cocoaGraphicsPipe.mm b/panda/src/cocoadisplay/cocoaGraphicsPipe.mm index 83a487e9fd..3734f37af8 100644 --- a/panda/src/cocoadisplay/cocoaGraphicsPipe.mm +++ b/panda/src/cocoadisplay/cocoaGraphicsPipe.mm @@ -76,6 +76,13 @@ CocoaGraphicsPipe(CGDirectDisplayID display) : _display(display) { cocoadisplay_cat.debug() << "Creating CocoaGraphicsPipe for display ID " << _display << "\n"; } + + // It takes a while to fire up the display link, so let's fire it up now if + // we expect to need VSync. + if (sync_video) { + uint32_t counter; + init_vsync(counter); + } } /** @@ -98,11 +105,19 @@ load_display_information() { &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); size_t num_modes = 0; + int32_t current_mode_id = -1; CFArrayRef modes = CGDisplayCopyAllDisplayModes(_display, options); if (modes != NULL) { num_modes = CFArrayGetCount(modes); _display_information->_total_display_modes = num_modes; _display_information->_display_mode_array = new DisplayMode[num_modes]; + + // Get information about the current mode. + CGDisplayModeRef mode = CGDisplayCopyDisplayMode(_display); + if (mode) { + current_mode_id = CGDisplayModeGetIODisplayModeID(mode); + CGDisplayModeRelease(mode); + } } if (options != NULL) { CFRelease(options); @@ -146,6 +161,14 @@ load_display_information() { // pixel can be deduced from the string length. Nifty! _display_information->_display_mode_array[i].bits_per_pixel = CFStringGetLength(encoding); } + + if (current_mode_id >= 0 && current_mode_id == CGDisplayModeGetIODisplayModeID(mode)) { + _display_information->_current_display_mode_index = i; + + // Stop checking + current_mode_id = -1; + } + CFRelease(encoding); } if (modes != nullptr) { @@ -171,6 +194,14 @@ load_display_information() { */ CocoaGraphicsPipe:: ~CocoaGraphicsPipe() { + if (_display_link != nil) { + CVDisplayLinkRelease(_display_link); + _display_link = nil; + + // Unblock any threads that may be waiting on the VSync counter. + __atomic_fetch_add(&_vsync_counter, 1u, __ATOMIC_SEQ_CST); + patomic_notify_all(&_vsync_counter); + } } /** @@ -184,3 +215,112 @@ CocoaGraphicsPipe::get_preferred_window_thread() const { // only be called from the main thread! return PWT_app; } + +/** + * Ensures a CVDisplayLink is created, which tells us when the display will + * want a frame, to avoid tearing (vertical blanking interval). + * Initializes the counter with the value that can be passed to wait_vsync + * to wait for the next interval. + */ +bool CocoaGraphicsPipe:: +init_vsync(uint32_t &counter) { + if (_display_link != nil) { + // Already set up. + __atomic_load(&_vsync_counter, &counter, __ATOMIC_SEQ_CST); + return true; + } + + counter = 0; + _vsync_counter = 0; + + CVDisplayLinkRef display_link; + CVReturn result = CVDisplayLinkCreateWithActiveCGDisplays(&display_link); + if (result != kCVReturnSuccess) { + cocoadisplay_cat.error() << "Failed to create CVDisplayLink.\n"; + display_link = nil; + return false; + } + + result = CVDisplayLinkSetCurrentCGDisplay(display_link, _display); + if (result != kCVReturnSuccess) { + cocoadisplay_cat.error() << "Failed to set CVDisplayLink's current display.\n"; + CVDisplayLinkRelease(display_link); + display_link = nil; + return false; + } + + result = CVDisplayLinkSetOutputCallback(display_link, &display_link_cb, this); + if (result != kCVReturnSuccess) { + cocoadisplay_cat.error() << "Failed to set CVDisplayLink output callback.\n"; + CVDisplayLinkRelease(display_link); + display_link = nil; + return false; + } + + result = CVDisplayLinkStart(display_link); + if (result != kCVReturnSuccess) { + cocoadisplay_cat.error() << "Failed to start the CVDisplayLink.\n"; + CVDisplayLinkRelease(display_link); + display_link = nil; + return false; + } + + _display_link = display_link; + return true; +} + +/** + * The first time this method is called in a frame, waits for the vertical + * blanking interval. If init_vsync has not first been called, does nothing. + * + * The given counter will be updated with the vblank counter. If adaptive is + * true and the value differs from the current, no wait will occur. + */ +void CocoaGraphicsPipe:: +wait_vsync(uint32_t &counter, bool adaptive) { + if (_display_link == nil) { + return; + } + + // Use direct atomic operations since we need this to be thread-safe even + // when compiling without thread support. + uint32_t current_count = __atomic_load_n(&_vsync_counter, __ATOMIC_SEQ_CST); + uint32_t diff = current_count - counter; + if (diff > 0) { + if (cocoadisplay_cat.is_spam()) { + cocoadisplay_cat.spam() + << "Missed vertical blanking interval by " << diff << " frames.\n"; + } + if (adaptive) { + counter = current_count; + return; + } + } + + // We only wait for the first window that gets flipped in a single frame, + // otherwise we end up halving our FPS when we have multiple windows! + int cur_frame = ClockObject::get_global_clock()->get_frame_count(); + if (_last_wait_frame.exchange(cur_frame) == cur_frame) { + counter = current_count; + return; + } + + patomic_wait(&_vsync_counter, current_count); + __atomic_load(&_vsync_counter, &counter, __ATOMIC_SEQ_CST); +} + +/** + * Called whenever a display wants a frame. The context argument contains the + * applicable CocoaGraphicsPipe. + */ +CVReturn CocoaGraphicsPipe:: +display_link_cb(CVDisplayLinkRef link, const CVTimeStamp *now, + const CVTimeStamp *output_time, CVOptionFlags flags_in, + CVOptionFlags *flags_out, void *context) { + + CocoaGraphicsPipe *pipe = (CocoaGraphicsPipe *)context; + __atomic_fetch_add(&pipe->_vsync_counter, 1u, __ATOMIC_SEQ_CST); + patomic_notify_all(&pipe->_vsync_counter); + + return kCVReturnSuccess; +} diff --git a/panda/src/cocoadisplay/cocoaGraphicsWindow.mm b/panda/src/cocoadisplay/cocoaGraphicsWindow.mm index e76cf38fa0..3aae8aee63 100644 --- a/panda/src/cocoadisplay/cocoaGraphicsWindow.mm +++ b/panda/src/cocoadisplay/cocoaGraphicsWindow.mm @@ -449,6 +449,11 @@ open_window() { _parent_window_handle->attach_child(_window_handle); } + if (_fb_properties.get_float_color() && + [_view respondsToSelector:@selector(setWantsExtendedDynamicRangeOpenGLSurface:)]) { + [_view setWantsExtendedDynamicRangeOpenGLSurface:YES]; + } + // Configure the view to be high resolution capable using the dpi-aware // configuration flag. If dpi-aware is false, macOS will upscale the view // for us. diff --git a/panda/src/cocoagldisplay/cocoaGLGraphicsStateGuardian.h b/panda/src/cocoagldisplay/cocoaGLGraphicsStateGuardian.h index 4527648c7c..00cbe9ce55 100644 --- a/panda/src/cocoagldisplay/cocoaGLGraphicsStateGuardian.h +++ b/panda/src/cocoagldisplay/cocoaGLGraphicsStateGuardian.h @@ -20,7 +20,6 @@ #import #import -#import /** * A tiny specialization on GLGraphicsStateGuardian to add some Cocoa-specific @@ -39,7 +38,6 @@ public: CocoaGLGraphicsStateGuardian *share_with); virtual ~CocoaGLGraphicsStateGuardian(); - bool setup_vsync(); INLINE void lock_context(); INLINE void unlock_context(); @@ -49,11 +47,6 @@ public: NSOpenGLPixelFormat *_format = nullptr; FrameBufferProperties _fbprops; - CVDisplayLinkRef _display_link = nullptr; - TrueMutexImpl _swap_lock; - TrueConditionVarImpl _swap_condition; - AtomicAdjust::Integer _last_wait_frame = 0; - protected: virtual void query_gl_version(); virtual void *do_get_extension_func(const char *name); diff --git a/panda/src/cocoagldisplay/cocoaGLGraphicsStateGuardian.mm b/panda/src/cocoagldisplay/cocoaGLGraphicsStateGuardian.mm index 9f8de82705..9cacb3e270 100644 --- a/panda/src/cocoagldisplay/cocoaGLGraphicsStateGuardian.mm +++ b/panda/src/cocoagldisplay/cocoaGLGraphicsStateGuardian.mm @@ -28,21 +28,6 @@ #define NSAppKitVersionNumber10_7 1138 #endif -/** - * Called whenever a display wants a frame. The context argument contains the - * applicable CocoaGLGraphicsStateGuardian. - */ -static CVReturn -display_link_cb(CVDisplayLinkRef link, const CVTimeStamp *now, - const CVTimeStamp* output_time, CVOptionFlags flags_in, - CVOptionFlags *flags_out, void *context) { - CocoaGLGraphicsStateGuardian *gsg = (CocoaGLGraphicsStateGuardian *)context; - gsg->_swap_lock.lock(); - gsg->_swap_condition.notify(); - gsg->_swap_lock.unlock(); - return kCVReturnSuccess; -} - TypeHandle CocoaGLGraphicsStateGuardian::_type_handle; /** @@ -51,8 +36,7 @@ TypeHandle CocoaGLGraphicsStateGuardian::_type_handle; CocoaGLGraphicsStateGuardian:: CocoaGLGraphicsStateGuardian(GraphicsEngine *engine, GraphicsPipe *pipe, CocoaGLGraphicsStateGuardian *share_with) : - GLGraphicsStateGuardian(engine, pipe), - _swap_condition(_swap_lock) + GLGraphicsStateGuardian(engine, pipe) { _share_context = nil; _context = nil; @@ -71,57 +55,12 @@ CocoaGLGraphicsStateGuardian:: if (_format != nil) { [_format release]; } - if (_display_link != nil) { - CVDisplayLinkRelease(_display_link); - _display_link = nil; - _swap_lock.lock(); - _swap_condition.notify(); - _swap_lock.unlock(); - } if (_context != nil) { [_context clearDrawable]; [_context release]; } } -/** - * Creates a CVDisplayLink, which tells us when the display the window is on - * will want a frame. - */ -bool CocoaGLGraphicsStateGuardian:: -setup_vsync() { - if (_display_link != nil) { - // Already set up. - return true; - } - - CVReturn result = CVDisplayLinkCreateWithActiveCGDisplays(&_display_link); - if (result != kCVReturnSuccess) { - cocoadisplay_cat.error() << "Failed to create CVDisplayLink.\n"; - return false; - } - - result = CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(_display_link, (CGLContextObj)[_context CGLContextObj], (CGLPixelFormatObj)[_format CGLPixelFormatObj]); - if (result != kCVReturnSuccess) { - cocoadisplay_cat.error() << "Failed to set CVDisplayLink's current display.\n"; - return false; - } - - result = CVDisplayLinkSetOutputCallback(_display_link, &display_link_cb, this); - if (result != kCVReturnSuccess) { - cocoadisplay_cat.error() << "Failed to set CVDisplayLink output callback.\n"; - return false; - } - - result = CVDisplayLinkStart(_display_link); - if (result != kCVReturnSuccess) { - cocoadisplay_cat.error() << "Failed to start the CVDisplayLink.\n"; - return false; - } - - return true; -} - /** * Gets the FrameBufferProperties to match the indicated config. */ @@ -249,6 +188,10 @@ choose_pixel_format(const FrameBufferProperties &properties, attribs.push_back(NSOpenGLPFAColorSize); attribs.push_back(properties.get_color_bits()); + if (properties.get_float_color()) { + attribs.push_back(NSOpenGLPFAColorFloat); + } + // Set the depth buffer bits to 24 manually when 1 is requested. // This prevents getting a depth buffer of only 16 bits when requesting 1. attribs.push_back(NSOpenGLPFADepthSize); diff --git a/panda/src/cocoagldisplay/cocoaGLGraphicsWindow.h b/panda/src/cocoagldisplay/cocoaGLGraphicsWindow.h index 85d0416c94..7bd612678d 100644 --- a/panda/src/cocoagldisplay/cocoaGLGraphicsWindow.h +++ b/panda/src/cocoagldisplay/cocoaGLGraphicsWindow.h @@ -42,6 +42,7 @@ protected: private: bool _vsync_enabled = false; + uint32_t _vsync_counter = 0; public: static TypeHandle get_class_type() { diff --git a/panda/src/cocoagldisplay/cocoaGLGraphicsWindow.mm b/panda/src/cocoagldisplay/cocoaGLGraphicsWindow.mm index c1e1821226..33a97a90f9 100644 --- a/panda/src/cocoagldisplay/cocoaGLGraphicsWindow.mm +++ b/panda/src/cocoagldisplay/cocoaGLGraphicsWindow.mm @@ -159,13 +159,16 @@ end_flip() { CocoaGLGraphicsStateGuardian *cocoagsg; DCAST_INTO_V(cocoagsg, _gsg); - if (_vsync_enabled) { - AtomicAdjust::Integer cur_frame = ClockObject::get_global_clock()->get_frame_count(); - if (AtomicAdjust::set(cocoagsg->_last_wait_frame, cur_frame) != cur_frame) { - cocoagsg->_swap_lock.lock(); - cocoagsg->_swap_condition.wait(); - cocoagsg->_swap_lock.unlock(); + if (sync_video) { + CocoaGraphicsPipe *cocoapipe = (CocoaGraphicsPipe *)_pipe.p(); + if (!_vsync_enabled) { + // If this fails, we don't keep trying. + cocoapipe->init_vsync(_vsync_counter); + _vsync_enabled = true; } + cocoapipe->wait_vsync(_vsync_counter); + } else { + _vsync_enabled = false; } cocoagsg->lock_context(); @@ -237,8 +240,6 @@ open_window() { } _fb_properties = cocoagsg->get_fb_properties(); - _vsync_enabled = sync_video && cocoagsg->setup_vsync(); - return true; } diff --git a/panda/src/collide/collisionBox.cxx b/panda/src/collide/collisionBox.cxx index 5b6dff09e0..f4224f2d14 100644 --- a/panda/src/collide/collisionBox.cxx +++ b/panda/src/collide/collisionBox.cxx @@ -1414,7 +1414,7 @@ compute_vectors(Points &points) { */ void CollisionBox:: register_with_read_factory() { - BamReader::get_factory()->register_factory(get_class_type(), make_CollisionBox); + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); } /** @@ -1457,7 +1457,7 @@ write_datagram(BamWriter *manager, Datagram &me) { * Factory method to generate a CollisionBox object */ TypedWritable *CollisionBox:: -make_CollisionBox(const FactoryParams ¶ms) { +make_from_bam(const FactoryParams ¶ms) { CollisionBox *me = new CollisionBox; DatagramIterator scan; BamReader *manager; diff --git a/panda/src/collide/collisionBox.h b/panda/src/collide/collisionBox.h index 69a0e13889..1b2489b9fc 100644 --- a/panda/src/collide/collisionBox.h +++ b/panda/src/collide/collisionBox.h @@ -155,7 +155,7 @@ public: virtual void write_datagram(BamWriter *manager, Datagram &me); protected: - static TypedWritable *make_CollisionBox(const FactoryParams ¶ms); + static TypedWritable *make_from_bam(const FactoryParams ¶ms); void fillin(DatagramIterator &scan, BamReader *manager); public: diff --git a/panda/src/collide/collisionFloorMesh.cxx b/panda/src/collide/collisionFloorMesh.cxx index 5f0ab0cabc..cde2eda522 100644 --- a/panda/src/collide/collisionFloorMesh.cxx +++ b/panda/src/collide/collisionFloorMesh.cxx @@ -386,8 +386,8 @@ fillin(DatagramIterator& scan, BamReader* manager) /** * Factory method to generate a CollisionPolygon object */ -TypedWritable* CollisionFloorMesh:: -make_CollisionFloorMesh(const FactoryParams ¶ms) { +TypedWritable *CollisionFloorMesh:: +make_from_bam(const FactoryParams ¶ms) { CollisionFloorMesh *me = new CollisionFloorMesh; DatagramIterator scan; BamReader *manager; @@ -402,10 +402,9 @@ make_CollisionFloorMesh(const FactoryParams ¶ms) { */ void CollisionFloorMesh:: register_with_read_factory() { - BamReader::get_factory()->register_factory(get_class_type(), make_CollisionFloorMesh); + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); } - /** * */ diff --git a/panda/src/collide/collisionFloorMesh.h b/panda/src/collide/collisionFloorMesh.h index 9304b79e11..67dfef43e2 100644 --- a/panda/src/collide/collisionFloorMesh.h +++ b/panda/src/collide/collisionFloorMesh.h @@ -101,7 +101,7 @@ public: static void register_with_read_factory(); virtual void write_datagram(BamWriter* manager, Datagram &me); - static TypedWritable *make_CollisionFloorMesh(const FactoryParams ¶ms); + static TypedWritable *make_from_bam(const FactoryParams ¶ms); static TypeHandle get_class_type() { return _type_handle; } diff --git a/panda/src/collide/collisionHandlerPhysical_ext.cxx b/panda/src/collide/collisionHandlerPhysical_ext.cxx index 023d7ba718..4fec83a6aa 100644 --- a/panda/src/collide/collisionHandlerPhysical_ext.cxx +++ b/panda/src/collide/collisionHandlerPhysical_ext.cxx @@ -32,8 +32,7 @@ __reduce__(PyObject *self) const { PyTuple_SET_ITEM(nodepaths, i++, DTool_CreatePyInstance((void *)center, Dtool_NodePath, false, true)); } else { - PyTuple_SET_ITEM(nodepaths, i++, Py_None); - Py_INCREF(Py_None); + PyTuple_SET_ITEM(nodepaths, i++, Py_NewRef(Py_None)); } CollisionHandlerPhysical::Colliders::const_iterator it; diff --git a/panda/src/collide/collisionHeightfield.cxx b/panda/src/collide/collisionHeightfield.cxx index 6568163d31..f44c9eff8e 100644 --- a/panda/src/collide/collisionHeightfield.cxx +++ b/panda/src/collide/collisionHeightfield.cxx @@ -799,7 +799,7 @@ get_test_pcollector() { } TypedWritable *CollisionHeightfield:: -make_CollisionHeightfield(const FactoryParams ¶ms) { +make_from_bam(const FactoryParams ¶ms) { CollisionHeightfield *me = new CollisionHeightfield; DatagramIterator scan; BamReader *manager; @@ -815,5 +815,5 @@ fillin(DatagramIterator &scan, BamReader *manager) { void CollisionHeightfield:: register_with_read_factory() { - BamReader::get_factory()->register_factory(get_class_type(), make_CollisionHeightfield); + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); } diff --git a/panda/src/collide/collisionHeightfield.h b/panda/src/collide/collisionHeightfield.h index bbeb6da34d..a593ca1b1d 100644 --- a/panda/src/collide/collisionHeightfield.h +++ b/panda/src/collide/collisionHeightfield.h @@ -151,7 +151,7 @@ private: static PStatCollector _test_pcollector; protected: - static TypedWritable *make_CollisionHeightfield(const FactoryParams ¶ms); + static TypedWritable *make_from_bam(const FactoryParams ¶ms); void fillin(DatagramIterator &scan, BamReader *manager); public: diff --git a/panda/src/collide/collisionInvSphere.cxx b/panda/src/collide/collisionInvSphere.cxx index 3abd9ae451..edc4350df2 100644 --- a/panda/src/collide/collisionInvSphere.cxx +++ b/panda/src/collide/collisionInvSphere.cxx @@ -562,7 +562,7 @@ fill_viz_geom() { */ void CollisionInvSphere:: register_with_read_factory() { - BamReader::get_factory()->register_factory(get_class_type(), make_CollisionInvSphere); + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); } /** @@ -578,7 +578,7 @@ write_datagram(BamWriter *manager, Datagram &me) { * Factory method to generate a CollisionInvSphere object */ TypedWritable *CollisionInvSphere:: -make_CollisionInvSphere(const FactoryParams ¶ms) { +make_from_bam(const FactoryParams ¶ms) { CollisionInvSphere *me = new CollisionInvSphere; DatagramIterator scan; BamReader *manager; diff --git a/panda/src/collide/collisionInvSphere.h b/panda/src/collide/collisionInvSphere.h index 0bbc9e2121..5355cfd3cc 100644 --- a/panda/src/collide/collisionInvSphere.h +++ b/panda/src/collide/collisionInvSphere.h @@ -78,7 +78,7 @@ public: virtual void write_datagram(BamWriter *manager, Datagram &me); protected: - static TypedWritable *make_CollisionInvSphere(const FactoryParams ¶ms); + static TypedWritable *make_from_bam(const FactoryParams ¶ms); void fillin(DatagramIterator &scan, BamReader *manager); public: diff --git a/panda/src/collide/collisionPlane.cxx b/panda/src/collide/collisionPlane.cxx index 2e174d4aa8..2a133b1655 100644 --- a/panda/src/collide/collisionPlane.cxx +++ b/panda/src/collide/collisionPlane.cxx @@ -596,9 +596,8 @@ fillin(DatagramIterator& scan, BamReader* manager) /** * Factory method to generate a CollisionPlane object */ -TypedWritable* CollisionPlane:: -make_CollisionPlane(const FactoryParams ¶ms) -{ +TypedWritable *CollisionPlane:: +make_from_bam(const FactoryParams ¶ms) { CollisionPlane *me = new CollisionPlane; DatagramIterator scan; BamReader *manager; @@ -612,7 +611,6 @@ make_CollisionPlane(const FactoryParams ¶ms) * Factory method to generate a CollisionPlane object */ void CollisionPlane:: -register_with_read_factory() -{ - BamReader::get_factory()->register_factory(get_class_type(), make_CollisionPlane); +register_with_read_factory() { + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); } diff --git a/panda/src/collide/collisionPlane.h b/panda/src/collide/collisionPlane.h index 719e33f489..2140fec93e 100644 --- a/panda/src/collide/collisionPlane.h +++ b/panda/src/collide/collisionPlane.h @@ -90,7 +90,7 @@ public: static void register_with_read_factory(); virtual void write_datagram(BamWriter* manager, Datagram &me); - static TypedWritable *make_CollisionPlane(const FactoryParams ¶ms); + static TypedWritable *make_from_bam(const FactoryParams ¶ms); protected: void fillin(DatagramIterator& scan, BamReader* manager); diff --git a/panda/src/collide/collisionPolygon.cxx b/panda/src/collide/collisionPolygon.cxx index c40fc04cb6..ab78a388c0 100644 --- a/panda/src/collide/collisionPolygon.cxx +++ b/panda/src/collide/collisionPolygon.cxx @@ -1877,8 +1877,8 @@ fillin(DatagramIterator &scan, BamReader *manager) { /** * Factory method to generate a CollisionPolygon object */ -TypedWritable* CollisionPolygon:: -make_CollisionPolygon(const FactoryParams ¶ms) { +TypedWritable *CollisionPolygon:: +make_from_bam(const FactoryParams ¶ms) { CollisionPolygon *me = new CollisionPolygon; DatagramIterator scan; BamReader *manager; @@ -1893,5 +1893,5 @@ make_CollisionPolygon(const FactoryParams ¶ms) { */ void CollisionPolygon:: register_with_read_factory() { - BamReader::get_factory()->register_factory(get_class_type(), make_CollisionPolygon); + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); } diff --git a/panda/src/collide/collisionPolygon.h b/panda/src/collide/collisionPolygon.h index 3fc6c5a962..1189b5bfe9 100644 --- a/panda/src/collide/collisionPolygon.h +++ b/panda/src/collide/collisionPolygon.h @@ -154,7 +154,7 @@ public: static void register_with_read_factory(); virtual void write_datagram(BamWriter* manager, Datagram &me); - static TypedWritable *make_CollisionPolygon(const FactoryParams ¶ms); + static TypedWritable *make_from_bam(const FactoryParams ¶ms); protected: void fillin(DatagramIterator& scan, BamReader* manager); diff --git a/panda/src/collide/collisionSphere.cxx b/panda/src/collide/collisionSphere.cxx index 631c0a5171..b8323faa63 100644 --- a/panda/src/collide/collisionSphere.cxx +++ b/panda/src/collide/collisionSphere.cxx @@ -771,7 +771,7 @@ compute_point(PN_stdfloat latitude, PN_stdfloat longitude) const { */ void CollisionSphere:: register_with_read_factory() { - BamReader::get_factory()->register_factory(get_class_type(), make_CollisionSphere); + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); } /** @@ -789,7 +789,7 @@ write_datagram(BamWriter *manager, Datagram &me) { * Factory method to generate a CollisionSphere object */ TypedWritable *CollisionSphere:: -make_CollisionSphere(const FactoryParams ¶ms) { +make_from_bam(const FactoryParams ¶ms) { CollisionSphere *me = new CollisionSphere; DatagramIterator scan; BamReader *manager; diff --git a/panda/src/collide/collisionSphere.h b/panda/src/collide/collisionSphere.h index 39b21d59f1..bff8f279f9 100644 --- a/panda/src/collide/collisionSphere.h +++ b/panda/src/collide/collisionSphere.h @@ -101,7 +101,7 @@ public: virtual void write_datagram(BamWriter *manager, Datagram &me); protected: - static TypedWritable *make_CollisionSphere(const FactoryParams ¶ms); + static TypedWritable *make_from_bam(const FactoryParams ¶ms); void fillin(DatagramIterator &scan, BamReader *manager); public: diff --git a/panda/src/device/inputDeviceNode.cxx b/panda/src/device/inputDeviceNode.cxx index b5e749b2d6..286dd93c08 100644 --- a/panda/src/device/inputDeviceNode.cxx +++ b/panda/src/device/inputDeviceNode.cxx @@ -69,7 +69,7 @@ do_transmit_data(DataGraphTraverser *, const DataNodeTransmit &, const ButtonEvent &event = bel->get_event(i); if (event._type == ButtonEvent::T_down) { _button_states[event._button] = true; - } else if (event._type == ButtonEvent::T_down) { + } else if (event._type == ButtonEvent::T_up) { _button_states[event._button] = false; } } diff --git a/panda/src/display/displayInformation.cxx b/panda/src/display/displayInformation.cxx index 337da59699..8f758f6f58 100644 --- a/panda/src/display/displayInformation.cxx +++ b/panda/src/display/displayInformation.cxx @@ -75,7 +75,6 @@ DisplayInformation:: DisplayInformation:: DisplayInformation() { DisplayInformation::DetectionState state; - int get_adapter_display_mode_state; int get_device_caps_state; int window_width; int window_height; @@ -88,7 +87,6 @@ DisplayInformation() { uint64_t available_physical_memory; state = DisplayInformation::DS_unknown; - get_adapter_display_mode_state = false; get_device_caps_state = false; window_width = 0; window_height = 0; @@ -101,7 +99,7 @@ DisplayInformation() { available_physical_memory = 0; _state = state; - _get_adapter_display_mode_state = get_adapter_display_mode_state; + _current_display_mode_index = -1; _get_device_caps_state = get_device_caps_state; _maximum_window_width = window_width; _maximum_window_height = window_height; @@ -210,7 +208,17 @@ get_display_mode(int display_index) { } /** - * + * Returns the index of the current display mode (determined at the time of + * application start) in the display mode array, or -1 if this could not be + * determined. + */ +int DisplayInformation:: +get_current_display_mode_index() const { + return _current_display_mode_index; +} + +/** + * @deprecated use get_display_mode instead. */ int DisplayInformation:: get_display_mode_width (int display_index) { @@ -225,7 +233,7 @@ get_display_mode_width (int display_index) { } /** - * + * @deprecated use get_display_mode instead. */ int DisplayInformation:: get_display_mode_height (int display_index) { @@ -240,7 +248,7 @@ get_display_mode_height (int display_index) { } /** - * + * @deprecated use get_display_mode instead. */ int DisplayInformation:: get_display_mode_bits_per_pixel (int display_index) { @@ -255,9 +263,9 @@ get_display_mode_bits_per_pixel (int display_index) { } /** - * + * @deprecated use get_display_mode instead. */ -int DisplayInformation:: +double DisplayInformation:: get_display_mode_refresh_rate (int display_index) { int value; @@ -270,7 +278,7 @@ get_display_mode_refresh_rate (int display_index) { } /** - * + * @deprecated use get_display_mode instead. */ int DisplayInformation:: get_display_mode_fullscreen_only (int display_index) { diff --git a/panda/src/display/displayInformation.h b/panda/src/display/displayInformation.h index 2869c8320a..3e4ef6d648 100644 --- a/panda/src/display/displayInformation.h +++ b/panda/src/display/displayInformation.h @@ -22,7 +22,7 @@ PUBLISHED: int width; int height; int bits_per_pixel; - int refresh_rate; + double refresh_rate; int fullscreen_only; bool operator == (const DisplayMode &other) const; @@ -57,11 +57,13 @@ PUBLISHED: const DisplayMode &get_display_mode(int display_index); MAKE_SEQ(get_display_modes, get_total_display_modes, get_display_mode); + int get_current_display_mode_index() const; + // Older interface for display modes. int get_display_mode_width(int display_index); int get_display_mode_height(int display_index); int get_display_mode_bits_per_pixel(int display_index); - int get_display_mode_refresh_rate(int display_index); + double get_display_mode_refresh_rate(int display_index); int get_display_mode_fullscreen_only(int display_index); GraphicsStateGuardian::ShaderModel get_shader_model(); @@ -116,7 +118,7 @@ PUBLISHED: public: DetectionState _state; - int _get_adapter_display_mode_state; + int _current_display_mode_index; int _get_device_caps_state; int _maximum_window_width; int _maximum_window_height; diff --git a/panda/src/display/graphicsPipeSelection.cxx b/panda/src/display/graphicsPipeSelection.cxx index 8be3f856a8..24fd0b5ffc 100644 --- a/panda/src/display/graphicsPipeSelection.cxx +++ b/panda/src/display/graphicsPipeSelection.cxx @@ -49,6 +49,7 @@ GraphicsPipeSelection() : _lock("GraphicsPipeSelection") { _default_display_module = load_display.get_word(0); _default_pipe_name = load_display.get_word(1); + _default_pipe_type = TypeHandle::none(); if (_default_display_module == "*") { // '*' or empty string is the key for all display modules. @@ -124,7 +125,11 @@ print_pipe_types() const { LightMutexHolder holder(_lock); nout << "Known pipe types:" << std::endl; for (const PipeType &pipe_type : _pipe_types) { - nout << " " << pipe_type._type << "\n"; + nout << " " << pipe_type._type; + if (_pipe_types.size() > 1 && pipe_type._type == _default_pipe_type) { + nout << " (default)"; + } + nout << "\n"; } if (_display_modules.empty()) { nout << "(all display modules loaded.)\n"; @@ -256,7 +261,7 @@ make_default_pipe() { if (!_default_pipe_name.empty()) { // First, look for an exact match of the default type name from the - // Configrc file (excepting case and hyphenunderscore). + // Config.prc file (excepting case and hyphen / underscore). for (const PipeType &ptype : _pipe_types) { if (cmp_nocase_uh(ptype._type.get_name(), _default_pipe_name) == 0) { // Here's an exact match. @@ -281,6 +286,18 @@ make_default_pipe() { } } + // Look for the preferred type of the default display module. + if (_default_pipe_type != TypeHandle::none()) { + for (const PipeType &ptype : _pipe_types) { + if (ptype._type == _default_pipe_type) { + PT(GraphicsPipe) pipe = (*ptype._constructor)(); + if (pipe != nullptr) { + return pipe; + } + } + } + } + // Couldn't find a matching pipe type; choose the first one on the list. for (const PipeType &ptype : _pipe_types) { PT(GraphicsPipe) pipe = (*ptype._constructor)(); @@ -358,7 +375,7 @@ do_load_default_module() { return; } - load_named_module(_default_display_module); + _default_pipe_type = load_named_module(_default_display_module); DisplayModules::iterator di = std::find(_display_modules.begin(), _display_modules.end(), diff --git a/panda/src/display/graphicsPipeSelection.h b/panda/src/display/graphicsPipeSelection.h index c62d5b16a4..42445336d7 100644 --- a/panda/src/display/graphicsPipeSelection.h +++ b/panda/src/display/graphicsPipeSelection.h @@ -87,6 +87,7 @@ private: DisplayModules _display_modules; std::string _default_display_module; std::string _default_pipe_name; + TypeHandle _default_pipe_type; bool _default_module_loaded; static GraphicsPipeSelection *_global_ptr; diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index feb017f382..d90cb6ac08 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/panda/src/display/graphicsStateGuardian.cxx @@ -2083,6 +2083,8 @@ fetch_specified_texture(Shader::ShaderTexSpec &spec, SamplerState &sampler, const LightAttrib *target_light; _target_rs->get_attrib_def(target_light); + PT(Texture) tex; + // We don't count ambient lights, which would be pretty silly to handle // via this mechanism. size_t num_lights = target_light->get_num_non_ambient_lights(); @@ -2092,28 +2094,21 @@ fetch_specified_texture(Shader::ShaderTexSpec &spec, SamplerState &sampler, Light *light_obj = light.node()->as_light(); nassertr(light_obj != nullptr, nullptr); - PT(Texture) tex; LightLensNode *lln = DCAST(LightLensNode, light.node()); if (lln != nullptr && lln->_shadow_caster) { tex = get_shadow_map(light); } else { tex = get_dummy_shadow_map((Texture::TextureType)spec._desired_type); } - - if (tex != nullptr) { - sampler = tex->get_default_sampler(); - } - return tex; } else { // There is no such light assigned. Bind a dummy shadow map. - PT(Texture) tex = get_dummy_shadow_map((Texture::TextureType)spec._desired_type); - if (tex != nullptr) { - sampler = tex->get_default_sampler(); - } - return tex; + tex = get_dummy_shadow_map((Texture::TextureType)spec._desired_type); } + if (tex != nullptr) { + sampler = tex->get_default_sampler(); + } + return tex; } - break; case Shader::STO_ff_stage_i: { @@ -2181,7 +2176,6 @@ fetch_specified_texture(Shader::ShaderTexSpec &spec, SamplerState &sampler, } return default_add_tex; } - break; case Shader::STO_stage_normal_i: { @@ -2211,7 +2205,6 @@ fetch_specified_texture(Shader::ShaderTexSpec &spec, SamplerState &sampler, } return default_normal_height_tex; } - break; case Shader::STO_stage_gloss_i: { @@ -2264,7 +2257,6 @@ fetch_specified_texture(Shader::ShaderTexSpec &spec, SamplerState &sampler, } return default_normal_height_tex; } - break; case Shader::STO_stage_selector_i: { diff --git a/panda/src/display/pythonGraphicsWindowProc.cxx b/panda/src/display/pythonGraphicsWindowProc.cxx index fe2013bed1..53e7885697 100644 --- a/panda/src/display/pythonGraphicsWindowProc.cxx +++ b/panda/src/display/pythonGraphicsWindowProc.cxx @@ -26,8 +26,7 @@ PythonGraphicsWindowProc:: PythonGraphicsWindowProc(PyObject* function, PyObject* name) : PythonCallbackObject(function) { - _name = name; - Py_INCREF(_name); + _name = Py_NewRef(name); } /** diff --git a/panda/src/downloader/httpAuthorization.cxx b/panda/src/downloader/httpAuthorization.cxx index 5cc9f9f540..d0c7d28476 100644 --- a/panda/src/downloader/httpAuthorization.cxx +++ b/panda/src/downloader/httpAuthorization.cxx @@ -16,7 +16,7 @@ #include "urlSpec.h" #include "string_utils.h" -#ifdef HAVE_OPENSSL +#if defined(HAVE_OPENSSL) || defined(__EMSCRIPTEN__) using std::string; diff --git a/panda/src/downloader/httpAuthorization.h b/panda/src/downloader/httpAuthorization.h index 65d49d7366..cf694040b5 100644 --- a/panda/src/downloader/httpAuthorization.h +++ b/panda/src/downloader/httpAuthorization.h @@ -20,7 +20,7 @@ // use any OpenSSL code, because it is a support module for HTTPChannel, which // *does* use OpenSSL code. -#ifdef HAVE_OPENSSL +#if defined(HAVE_OPENSSL) || defined(__EMSCRIPTEN__) #include "referenceCount.h" #include "httpEnum.h" diff --git a/panda/src/downloader/httpBasicAuthorization.cxx b/panda/src/downloader/httpBasicAuthorization.cxx index a8abd67979..2f8a46bec4 100644 --- a/panda/src/downloader/httpBasicAuthorization.cxx +++ b/panda/src/downloader/httpBasicAuthorization.cxx @@ -13,7 +13,7 @@ #include "httpBasicAuthorization.h" -#ifdef HAVE_OPENSSL +#if defined(HAVE_OPENSSL) || defined(__EMSCRIPTEN__) using std::string; diff --git a/panda/src/downloader/httpBasicAuthorization.h b/panda/src/downloader/httpBasicAuthorization.h index 92e85bb3ab..100bcd57d0 100644 --- a/panda/src/downloader/httpBasicAuthorization.h +++ b/panda/src/downloader/httpBasicAuthorization.h @@ -20,7 +20,7 @@ // use any OpenSSL code, because it is a support module for HTTPChannel, which // *does* use OpenSSL code. -#ifdef HAVE_OPENSSL +#if defined(HAVE_OPENSSL) || defined(__EMSCRIPTEN__) #include "httpAuthorization.h" diff --git a/panda/src/downloader/httpChannel.h b/panda/src/downloader/httpChannel.h index 200ed95a70..e085079d1a 100644 --- a/panda/src/downloader/httpChannel.h +++ b/panda/src/downloader/httpChannel.h @@ -453,6 +453,9 @@ std::ostream &operator << (std::ostream &out, HTTPChannel::State state); #include "httpChannel.I" +#elif defined(__EMSCRIPTEN__) +#include "httpChannel_emscripten.h" + #endif // HAVE_OPENSSL #endif diff --git a/panda/src/downloader/httpChannel_emscripten.I b/panda/src/downloader/httpChannel_emscripten.I new file mode 100644 index 0000000000..ada7def14d --- /dev/null +++ b/panda/src/downloader/httpChannel_emscripten.I @@ -0,0 +1,442 @@ +/** + * PANDA 3D SOFTWARE + * Copyright (c) Carnegie Mellon University. All rights reserved. + * + * All use of this software is subject to the terms of the revised BSD + * license. You should have received a copy of this license along + * with this source code in a file named "LICENSE." + * + * @file httpChannel_emscripten.I + * @author rdb + * @date 2021-02-10 + */ + +/** + * Returns the HTTPClient object that owns this channel. + */ +INLINE HTTPClient *HTTPChannel:: +get_client() const { + return _client; +} + +/** + * Returns true if the last-requested document was successfully retrieved and + * is ready to be read, false otherwise. + */ +INLINE bool HTTPChannel:: +is_valid() const { + return get_status_code() / 100 == 2; +} + +/** + * Returns the URL that was used to retrieve the most recent document: + * whatever URL was last passed to get_document() or get_header(). If a + * redirect has transparently occurred, this will return the new, redirected + * URL (the actual URL at which the document was located). + */ +INLINE const URLSpec &HTTPChannel:: +get_url() const { + return _document_spec.get_url(); +} + +/** + * Returns the DocumentSpec associated with the most recent document. This + * includes its actual URL (following redirects) along with the identity tag + * and last-modified date, if supplied by the server. + * + * This structure may be saved and used to retrieve the same version of the + * document later, or to conditionally retrieve a newer version if it is + * available. + */ +INLINE const DocumentSpec &HTTPChannel:: +get_document_spec() const { + return _document_spec; +} + +/** + * Returns the HTML return code from the document retrieval request. This + * will be in the 200 range if the document is successfully retrieved, or some + * other value in the case of an error. + * + * Some proxy errors during an https-over-proxy request would return the same + * status code as a different error that occurred on the host server. To + * differentiate these cases, status codes that are returned by the proxy + * during the CONNECT phase (except code 407) are incremented by 1000. + */ +INLINE int HTTPChannel:: +get_status_code() const { + return _status_entry._status_code; +} + +/** + * Returns the string as returned by the server describing the status code for + * humans. This may or may not be meaningful. + */ +INLINE std::string HTTPChannel:: +get_status_string() const { + return _status_entry._status_string; +} + +/** + * If the document failed to connect because of a 401 (Authorization + * required), this method will return the "realm" returned by the server in + * which the requested document must be authenticated. This string may be + * presented to the user to request an associated username and password (which + * then should be stored in HTTPClient::set_username()). + */ +INLINE const std::string &HTTPChannel:: +get_www_realm() const { + return _www_realm; +} + +/** + * Specifies the Content-Type header, useful for applications that require + * different types of content, such as JSON. + */ +INLINE void HTTPChannel:: +set_content_type(std::string content_type) { + _content_type = content_type; +} + +/** + * Returns the value of the Content-Type header. + */ +INLINE std::string HTTPChannel:: +get_content_type() const { + return _content_type; +} + +/** + * This may be called immediately after a call to get_document() or some + * related function to specify the expected size of the document we are + * retrieving, if we happen to know. This is used as the return value to + * get_file_size() only in the case that the server does not tell us the + * actual file size. + */ +INLINE void HTTPChannel:: +set_expected_file_size(size_t file_size) { + _expected_file_size = file_size; + _got_expected_file_size = true; +} + +/** + * Returns true if the size of the file we are currently retrieving was told + * us by the server and thus is reliably known, or false if the size reported + * by get_file_size() represents an educated guess (possibly as set by + * set_expected_file_size(), or as inferred from a chunked transfer encoding + * in progress). + */ +INLINE bool HTTPChannel:: +is_file_size_known() const { + return _got_file_size; +} + +/** + * Returns the first byte of the file requested by the request. This will + * normally be 0 to indicate that the file is being requested from the + * beginning, but if the file was requested via a get_subdocument() call, this + * will contain the first_byte parameter from that call. + */ +INLINE size_t HTTPChannel:: +get_first_byte_requested() const { + return _first_byte_requested; +} + +/** + * Returns the last byte of the file requested by the request. This will + * normally be 0 to indicate that the file is being requested to its last + * byte, but if the file was requested via a get_subdocument() call, this will + * contain the last_byte parameter from that call. + */ +INLINE size_t HTTPChannel:: +get_last_byte_requested() const { + return _last_byte_requested; +} + +/** + * Returns the first byte of the file (that will be) delivered by the server + * in response to the current request. Normally, this is the same as + * get_first_byte_requested(), but some servers will ignore a subdocument + * request and always return the whole file, in which case this value will be + * 0, regardless of what was requested to get_subdocument(). + */ +INLINE size_t HTTPChannel:: +get_first_byte_delivered() const { + return _first_byte_delivered; +} + +/** + * Returns the last byte of the file (that will be) delivered by the server in + * response to the current request. Normally, this is the same as + * get_last_byte_requested(), but some servers will ignore a subdocument + * request and always return the whole file, in which case this value will be + * 0, regardless of what was requested to get_subdocument(). + */ +INLINE size_t HTTPChannel:: +get_last_byte_delivered() const { + return _last_byte_delivered; +} + +/** + * Stops whatever file transaction is currently in progress, closes the + * connection, and resets to begin anew. You shouldn't ever need to call + * this, since the channel should be able to reset itself cleanly between + * requests, but it is provided in case you are an especially nervous type. + * + * Don't call this after every request unless you set + * set_persistent_connection() to false, since calling reset() rudely closes + * the connection regardless of whether we have told the server we intend to + * keep it open or not. + */ +INLINE void HTTPChannel:: +reset() { + reset_for_new_request(); + _status_list.clear(); +} + +/** + * Preserves the previous status code (presumably a failure) from the previous + * connection attempt. If the subsequent connection attempt also fails, the + * returned status code will be the better of the previous code and the + * current code. + * + * This can be called to daisy-chain subsequent attempts to download the same + * document from different servers. After all servers have been attempted, + * the final status code will reflect the attempt that most nearly succeeded. + */ +INLINE void HTTPChannel:: +preserve_status() { + _status_list.push_back(_status_entry); +} + +/** + * Resets the extra headers that were previously added via calls to + * send_extra_header(). + */ +INLINE void HTTPChannel:: +clear_extra_headers() { + _send_extra_headers.clear(); +} + +/** + * Specifies an additional key: value pair that is added into the header sent + * to the server with the next request. This is passed along with no + * interpretation by the HTTPChannel code. You may call this repeatedly to + * append multiple headers. + * + * This is persistent for one request only; it must be set again for each new + * request. + */ +INLINE void HTTPChannel:: +send_extra_header(const std::string &key, const std::string &value) { + _send_extra_headers.push_back(std::make_pair(key, value)); +} + +/** + * Opens the named document for reading, if available. Returns true if + * successful, false otherwise. + */ +INLINE bool HTTPChannel:: +get_document(const DocumentSpec &url) { + if (!begin_request(HTTPEnum::M_get, url, std::string(), false, 0, 0)) { + return false; + } + while (run()) { + } + return is_valid(); +} + +/** + * Retrieves only the specified byte range of the indicated document. If + * last_byte is 0, it stands for the last byte of the document. When a + * subdocument is requested, get_file_size() and get_bytes_downloaded() will + * report the number of bytes of the subdocument, not of the complete + * document. + */ +INLINE bool HTTPChannel:: +get_subdocument(const DocumentSpec &url, size_t first_byte, size_t last_byte) { + if (!begin_request(HTTPEnum::M_get, url, std::string(), false, first_byte, last_byte)) { + return false; + } + while (run()) { + } + return is_valid(); +} + +/** + * Like get_document(), except only the header associated with the document is + * retrieved. This may be used to test for existence of the document; it + * might also return the size of the document (if the server gives us this + * information). + */ +INLINE bool HTTPChannel:: +get_header(const DocumentSpec &url) { + if (!begin_request(HTTPEnum::M_head, url, std::string(), false, 0, 0)) { + return false; + } + while (run()) { + } + return is_valid(); +} + +/** + * Posts form data to a particular URL and retrieves the response. + */ +INLINE bool HTTPChannel:: +post_form(const DocumentSpec &url, const std::string &body) { + if (!begin_request(HTTPEnum::M_post, url, body, false, 0, 0)) { + return false; + } + while (run()) { + } + return is_valid(); +} + +/** + * Uploads the indicated body to the server to replace the indicated URL, if + * the server allows this. + */ +INLINE bool HTTPChannel:: +put_document(const DocumentSpec &url, const std::string &body) { + if (!begin_request(HTTPEnum::M_put, url, body, false, 0, 0)) { + return false; + } + while (run()) { + } + return is_valid(); +} + +/** + * Requests the server to remove the indicated URL. + */ +INLINE bool HTTPChannel:: +delete_document(const DocumentSpec &url) { + if (!begin_request(HTTPEnum::M_delete, url, std::string(), false, 0, 0)) { + return false; + } + while (run()) { + } + return is_valid(); +} + +/** + * Sends an OPTIONS message to the server, which should query the available + * options, possibly in relation to a specified URL. + */ +INLINE bool HTTPChannel:: +get_options(const DocumentSpec &url) { + if (!begin_request(HTTPEnum::M_options, url, std::string(), false, 0, 0)) { + return false; + } + while (run()) { + } + return is_valid(); +} + +/** + * Begins a non-blocking request to retrieve a given document. This method + * will return immediately, even before a connection to the server has + * necessarily been established; you must then call run() from time to time + * until the return value of run() is false. Then you may check is_valid() + * and get_status_code() to determine the status of your request. + * + * If a previous request had been pending, that request is discarded. + */ +INLINE void HTTPChannel:: +begin_get_document(const DocumentSpec &url) { + begin_request(HTTPEnum::M_get, url, std::string(), true, 0, 0); +} + +/** + * Begins a non-blocking request to retrieve only the specified byte range of + * the indicated document. If last_byte is 0, it stands for the last byte of + * the document. When a subdocument is requested, get_file_size() and + * get_bytes_downloaded() will report the number of bytes of the subdocument, + * not of the complete document. + */ +INLINE void HTTPChannel:: +begin_get_subdocument(const DocumentSpec &url, size_t first_byte, + size_t last_byte) { + begin_request(HTTPEnum::M_get, url, std::string(), true, first_byte, last_byte); +} + +/** + * Begins a non-blocking request to retrieve a given header. See + * begin_get_document() and get_header(). + */ +INLINE void HTTPChannel:: +begin_get_header(const DocumentSpec &url) { + begin_request(HTTPEnum::M_head, url, std::string(), true, 0, 0); +} + +/** + * Posts form data to a particular URL and retrieves the response, all using + * non-blocking I/O. See begin_get_document() and post_form(). + * + * It is important to note that you *must* call run() repeatedly after calling + * this method until run() returns false, and you may not call any other + * document posting or retrieving methods using the HTTPChannel object in the + * interim, or your form data may not get posted. + */ +INLINE void HTTPChannel:: +begin_post_form(const DocumentSpec &url, const std::string &body) { + begin_request(HTTPEnum::M_post, url, body, true, 0, 0); +} + +/** + * Returns the number of bytes downloaded during the last (or current) + * download_to_file() or download_to_ram operation(). This can be used in + * conjunction with get_file_size() to report the percent complete (but be + * careful, since get_file_size() may return 0 if the server has not told us + * the size of the file). + */ +INLINE size_t HTTPChannel:: +get_bytes_downloaded() const { + return _bytes_downloaded; +} + +/** + * When download throttling is in effect (set_download_throttle() has been set + * to true) and non-blocking I/O methods (like begin_get_document()) are used, + * this returns the number of bytes "requested" from the server so far: that + * is, the theoretical maximum value for get_bytes_downloaded(), if the server + * has been keeping up with our demand. + * + * If this number is less than get_bytes_downloaded(), then the server has not + * been supplying bytes fast enough to meet our own download throttle rate. + * + * When download throttling is not in effect, or when the blocking I/O methods + * (like get_document(), etc.) are used, this returns 0. + */ +INLINE size_t HTTPChannel:: +get_bytes_requested() const { + return _bytes_requested; +} + +/** + * Returns true when a download_to() or download_to_ram() has executed and the + * file has been fully downloaded. If this still returns false after + * processing has completed, there was an error in transmission. + * + * Note that simply testing is_download_complete() does not prove that the + * requested document was successfully retrieved--you might have just + * downloaded the "404 not found" stub (for instance) that a server would + * provide in response to some error condition. You should also check + * is_valid() to prove that the file you expected has been successfully + * retrieved. + */ +INLINE bool HTTPChannel:: +is_download_complete() const { + if (_download_dest != DD_none) { + return get_state() == S_done; + } + return false; +} + +/** + * + */ +INLINE HTTPChannel::StatusEntry:: +StatusEntry() { + _status_code = SC_incomplete; +} diff --git a/panda/src/downloader/httpChannel_emscripten.cxx b/panda/src/downloader/httpChannel_emscripten.cxx new file mode 100644 index 0000000000..859166fbb7 --- /dev/null +++ b/panda/src/downloader/httpChannel_emscripten.cxx @@ -0,0 +1,790 @@ +/** + * PANDA 3D SOFTWARE + * Copyright (c) Carnegie Mellon University. All rights reserved. + * + * All use of this software is subject to the terms of the revised BSD + * license. You should have received a copy of this license along + * with this source code in a file named "LICENSE." + * + * @file httpChannel_emscripten.cxx + * @author rdb + * @date 2021-02-10 + */ + +#include "httpChannel_emscripten.h" + +#ifdef __EMSCRIPTEN__ + +#include "string_utils.h" + +#include + +#define _NOTIFY_HTTP_CHANNEL_ID "[" << this << "] " + +#ifndef CPPPARSER +extern "C" char *EMSCRIPTEN_KEEPALIVE +_extend_string(std::string *str, int length) { + size_t offset = str->size(); + str->resize(offset + (size_t)length); + return (char *)str->data() + offset; +} + +extern "C" void EMSCRIPTEN_KEEPALIVE +_write_stream(std::ostream *strm, const char *data, int length) { + strm->write(data, (size_t)length); +} + +extern "C" bool EMSCRIPTEN_KEEPALIVE +_http_channel_run(HTTPChannel *channel) { + return channel->run(); +} +#endif + +TypeHandle HTTPChannel::_type_handle; + +/** + * + */ +HTTPChannel:: +HTTPChannel(HTTPClient *client) : + _client(client) +{ + if (downloader_cat.is_debug()) { + downloader_cat.debug() + << _NOTIFY_HTTP_CHANNEL_ID + << "created.\n"; + } + + EM_ASM({ + if (!window._httpChannels) { + window._httpChannels = {}; + } + var xhr = new XMLHttpRequest(); + window._httpChannels[$0] = xhr; + }, this); + + // _nonblocking is true if the XHR is actually in non-blocking mode. + _nonblocking = false; + + // _wanted_nonblocking is true if the user specifically requested one of the + // non-blocking interfaces. It is false if the XHR is only incidentally + // non-blocking (for instance, because ASYNCIFY is on). + _wanted_nonblocking = false; + + _first_byte_requested = 0; + _last_byte_requested = 0; + _first_byte_delivered = 0; + _last_byte_delivered = 0; + _expected_file_size = 0; + _file_size = 0; + _transfer_file_size = 0; + _got_expected_file_size = false; + _got_file_size = false; + _got_transfer_file_size = false; + _bytes_downloaded = 0; + _bytes_requested = 0; + _status_entry = StatusEntry(); + _content_type = "application/x-www-form-urlencoded"; + _download_dest = DD_none; + _download_to_ramfile = nullptr; + _download_to_stream = nullptr; +} + +/** + * + */ +HTTPChannel:: +~HTTPChannel() { + EM_ASM({ + var xhr = window._httpChannels[$0]; + if (xhr) { + xhr.onprogress = null; + xhr.onreadystatechange = null; + delete window._httpChannels[$0]; + } + }, this); + + if (downloader_cat.is_debug()) { + downloader_cat.debug() + << _NOTIFY_HTTP_CHANNEL_ID + << "destroyed.\n"; + } + + reset_download_to(); +} + +/** + * Returns the HTML header value associated with the indicated key, or empty + * string if the key was not defined in the message returned by the server. + */ +std::string HTTPChannel:: +get_header_value(const std::string &key) const { + Headers::const_iterator hi = _headers.find(downcase(key)); + if (hi != _headers.end()) { + return (*hi).second; + } + return std::string(); +} + +/** + * Returns the size of the file, if it is known. Returns the value set by + * set_expected_file_size() if the file size is not known, or 0 if this value + * was not set. + * + * If the file is dynamically generated, the size may not be available until a + * read has started (e.g. open_read_body() has been called); and even then it + * may increase as more of the file is read due to the nature of HTTP/1.1 + * requests which can change their minds midstream about how much data they're + * sending you. + */ +std::streamsize HTTPChannel:: +get_file_size() const { + if (_got_file_size) { + return _file_size; + } else if (_got_transfer_file_size) { + return _transfer_file_size; + } else if (_got_expected_file_size) { + return _expected_file_size; + } else { + return 0; + } +} + +/** + * Outputs a list of all headers defined by the server to the indicated output + * stream. + */ +void HTTPChannel:: +write_headers(std::ostream &out) const { + Headers::const_iterator hi; + for (hi = _headers.begin(); hi != _headers.end(); ++hi) { + out << (*hi).first << ": " << (*hi).second << "\n"; + } +} + +/** + * This must be called from time to time when non-blocking I/O is in use. It + * checks for data coming in on the socket and writes data out to the socket + * when possible, and does whatever processing is required towards completing + * the current task. + * + * The return value is true if the task is still pending (and run() will need + * to be called again in the future), or false if the current task is + * complete. + */ +bool HTTPChannel:: +run() { + if (downloader_cat.is_spam()) { + downloader_cat.spam() + << _NOTIFY_HTTP_CHANNEL_ID + << "run().\n"; + } + + State state = get_state(); + switch (state) { + case S_unsent: + // Invalid. + return false; + + case S_opened: + if (!run_send()) { + return false; + } + break; + + case S_headers_received: + if (!run_headers_received()) { + return false; + } + break; + + case S_loading: + if (_download_dest != DD_none) { + return false; + } + break; + + case S_done: + close_download_stream(); + return false; + } + + // If we get here, we must be running in non-blocking mode. + if (!_wanted_nonblocking && emscripten_has_asyncify()) { + // But we are pretending to be in blocking mode, so we must yield until the + // state changes. + while (get_state() != state) { + emscripten_sleep(0); + } + } + + return true; +} + +/** + * Returns the current readyState of the XMLHttpRequest object. + */ +HTTPChannel::State HTTPChannel:: +get_state() const { + return (State)EM_ASM_INT(return window._httpChannels[$0].readyState, this); +} + +/** + * Calls XHR.send(). + */ +bool HTTPChannel:: +run_send() { + for (const ExtraHeader &header : _send_extra_headers) { + EM_ASM({ + var xhr = window._httpChannels[$0]; + xhr.setRequestHeader(UTF8ToString($1), UTF8ToString($2)); + }, this, header.first.c_str(), header.second.c_str()); + } + + if (_method == HTTPEnum::M_get || _method == HTTPEnum::M_head) { + // No body is sent with GET / HEAD requests. + EM_ASM({ + var xhr = window._httpChannels[$0]; + xhr.send(null); + }, this); + } + else { + EM_ASM({ + var xhr = window._httpChannels[$0]; + xhr.setRequestHeader("Content-Type", UTF8ToString($2)); + xhr.send(UTF8ToString($1)); + }, this, _body.c_str(), _content_type.c_str()); + } + + return true; +} + +/** + * Called when the headers have been received. + */ +bool HTTPChannel:: +run_headers_received() { + char status_string[512]; + char *header_str = nullptr; + status_string[0] = 0; + + // Fetch the status code, text and response headers from JavaScript. + int status_code = EM_ASM_INT({ + var xhr = window._httpChannels[$0]; + stringToUTF8(xhr.statusText, $1, 512); + + var headers = xhr.getAllResponseHeaders(); + var len = lengthBytesUTF8(headers) + 1; + var buffer = _malloc(len); + stringToUTF8(headers, buffer, len); + setValue($2, buffer, '*'); + + return xhr.status; + }, this, status_string, &header_str); + _status_entry._status_code = status_code; + + // Parse the response header string. + char *ptr = header_str; + char *delim = strstr(ptr, ": "); + while (delim != nullptr) { + std::string key(ptr, delim); + ptr = delim + 2; + + std::string value; + delim = strstr(ptr, "\r\n"); + if (delim != nullptr) { + value.assign(ptr, delim); + ptr = delim + 2; + delim = strstr(ptr, ": "); + } + else { + // The XHR spec prescribes that there is always another CRLF + // after the last header, but we handle this case anyway. + value.assign(ptr); + } + + _headers[std::move(key)] = std::move(value); + } + free(header_str); + + // Look for key properties in the header fields. + if (status_code == 206) { + std::string content_range = get_header_value("Content-Range"); + if (content_range.empty()) { + downloader_cat.warning() + << _NOTIFY_HTTP_CHANNEL_ID + << "Got 206 response without Content-Range header!\n"; + _status_entry._status_code = SC_invalid_http; + return false; + + } else { + if (!parse_content_range(content_range)) { + downloader_cat.warning() + << _NOTIFY_HTTP_CHANNEL_ID + << "Couldn't parse Content-Range: " << content_range << "\n"; + _status_entry._status_code = SC_invalid_http; + return false; + } + } + + } else { + _first_byte_delivered = 0; + _last_byte_delivered = 0; + } + if (downloader_cat.is_debug()) { + if (_first_byte_requested != 0 || _last_byte_requested != 0 || + _first_byte_delivered != 0 || _last_byte_delivered != 0) { + downloader_cat.debug() + << _NOTIFY_HTTP_CHANNEL_ID + << "Requested byte range " << _first_byte_requested + << " to " << _last_byte_delivered + << "; server delivers range " << _first_byte_delivered + << " to " << _last_byte_delivered + << "\n"; + } + } + + // Set the _document_spec to reflect what we just retrieved. + _document_spec = DocumentSpec(_request.get_url()); + std::string tag = get_header_value("ETag"); + if (!tag.empty()) { + _document_spec.set_tag(HTTPEntityTag(tag)); + } + std::string date = get_header_value("Last-Modified"); + if (!date.empty()) { + _document_spec.set_date(HTTPDate(date)); + } + + // In case we've got a download in effect, now we know what the first byte + // of the subdocument request will be, so we can open the file and position + // it. + if (status_code / 100 == 1 || status_code == 204 || status_code == 304) { + // Never mind on the download. + reset_download_to(); + } + + if (!open_download_file()) { + return false; + } + + if (_download_dest == DD_ram) { + std::string *dest = &_download_to_ramfile->_data; + EM_ASM({ + var xhr = window._httpChannels[$0]; + var loaded = 0; + xhr.onprogress = function (ev) { + var chunk = this.responseText.slice(loaded, ev.loaded); + var ptr = __extend_string($1, chunk.length); + writeAsciiToMemory(chunk, ptr, true); + loaded = ev.loaded; + }; + }, this, dest); + } + else if (_download_dest == DD_stream) { + std::ostream *dest = _download_to_stream; + char buffer[4096]; + EM_ASM({ + var xhr = window._httpChannels[$0]; + var loaded = 0; + xhr.onprogress = function (ev) { + while (loaded < ev.loaded) { + var size = Math.min(ev.loaded - read, 4096); + writeAsciiToMemory(this.responseText.substr(read, size), $2, true); + __write_stream($1, $2, size); + loaded += size; + } + }; + }, this, dest, buffer); + } + + _got_expected_file_size = false; + _got_file_size = false; + _got_transfer_file_size = false; + + std::string content_length = get_header_value("Content-Length"); + if (!content_length.empty()) { + _file_size = atoi(content_length.c_str()); + _got_file_size = true; + } + else if (status_code == 206) { + // Well, we didn't get a content-length from the server, but we can infer + // the number of bytes based on the range we're given. + _file_size = _last_byte_delivered - _first_byte_delivered + 1; + _got_file_size = true; + } + + // Reset these for the next request. + clear_extra_headers(); + + return (_download_dest != DD_none); +} + +/** + * Begins a new document request to the server, throwing away whatever request + * was currently pending if necessary. + */ +bool HTTPChannel:: +begin_request(HTTPEnum::Method method, const DocumentSpec &url, + const std::string &body, bool nonblocking, + size_t first_byte, size_t last_byte) { + + downloader_cat.info() + << _NOTIFY_HTTP_CHANNEL_ID + << "begin " << method << " " << url << "\n"; + + reset_for_new_request(); + + _wanted_nonblocking = nonblocking; + _nonblocking = nonblocking || emscripten_has_asyncify(); + + _request = url; + _document_spec = DocumentSpec(); + _method = method; + _body = body; + + _first_byte_requested = first_byte; + _last_byte_requested = last_byte; + + bool result = (bool)EM_ASM_INT({ + var methods = (["OPTIONS", "GET", "HEAD", "POST", "PUT", "DELETE", "TRACE", "CONNECT"]); + var xhr = window._httpChannels[$0]; + try { + xhr.open(methods[$1], UTF8ToString($2), !!$3); + xhr.withCredentials = true; + xhr.overrideMimeType("text/plain; charset=x-user-defined"); + if ($4 != 0 || $5 != 0) { + xhr.setRequestHeader("Range", "bytes=" + $4 + "-" + ($5 || "")); + } + xhr.onprogress = null; + xhr.onreadystatechange = null; + return 1; + } + catch (ex) { + (console.error || console.log)(ex); + return 0; + } + }, this, method, _request.get_url().c_str(), (int)_nonblocking, (int)first_byte, (int)last_byte); + + if (!result) { + return false; + } + + if (_wanted_nonblocking) { + // Call run() automatically when the state changes. + EM_ASM({ + var xhr = window._httpChannels[$0]; + xhr.onreadystatechange = function () { + var xhr = window._httpChannels[$0]; + if (!xhr || !__http_channel_run($0)) { + xhr.onreadystatechange = null; + } + }; + }, this); + } + else { + return run_send() && run_headers_received(); + } + + return true; +} + +/** + * Resets the internal state variables in preparation for beginning a new + * request. + */ +void HTTPChannel:: +reset_for_new_request() { + if (downloader_cat.is_spam()) { + downloader_cat.spam() + << _NOTIFY_HTTP_CHANNEL_ID + << "reset_for_new_request.\n"; + } + + EM_ASM({ + var xhr = window._httpChannels[$0]; + xhr.onprogress = null; + xhr.onreadystatechange = null; + if (xhr.readyState !== 0) { + try { + xhr.abort(); + } + catch (ex) { + } + } + }, this); + + reset_download_to(); + + _status_entry = StatusEntry(); + + _bytes_downloaded = 0; + _bytes_requested = 0; +} + +/** + * If a download has been requested, opens the file on disk (or prepares the + * RamFile or stream) and seeks within it to the appropriate + * _first_byte_delivered position, so that downloaded bytes will be written to + * the appropriate point within the file. Returns true if the starting + * position is valid, false otherwise (in which case the state is set to + * S_failure). + */ +bool HTTPChannel:: +open_download_file() { + _subdocument_resumes = (_subdocument_resumes && _first_byte_delivered != 0); + + if (_subdocument_resumes) { + if (_download_dest == DD_ram) { + if (_first_byte_delivered > _download_to_ramfile->_data.length()) { + downloader_cat.info() + << _NOTIFY_HTTP_CHANNEL_ID + << "Invalid starting position of byte " << _first_byte_delivered + << " within Ramfile (which has " + << _download_to_ramfile->_data.length() << " bytes)\n"; + close_download_stream(); + _status_entry._status_code = SC_download_invalid_range; + return false; + } + + if (_first_byte_delivered == 0) { + _download_to_ramfile->_data = string(); + } + else { + _download_to_ramfile->_data = + _download_to_ramfile->_data.substr(0, _first_byte_delivered); + } + } + else if (_download_dest == DD_stream) { + _download_to_stream->seekp(_first_byte_delivered); + } + } + else { + // If _subdocument_resumes is false, we should be sure to reset to the + // beginning of the file, regardless of the value of + // _first_byte_delivered. + if (_download_dest == DD_file || _download_dest == DD_stream) { + _download_to_stream->seekp(0); + } + else if (_download_dest == DD_ram) { + _download_to_ramfile->_data = string(); + } + } + + return true; +} + +/** + * Interprets the "Content-Range" header in the reply, and fills in + * _first_byte_delivered and _last_byte_delivered appropriately if the header + * response can be understood. + */ +bool HTTPChannel:: +parse_content_range(const std::string &content_range) { + // First, get the units indication. + size_t p = 0; + while (p < content_range.length() && !isspace(content_range[p])) { + p++; + } + + std::string units = content_range.substr(0, p); + while (p < content_range.length() && isspace(content_range[p])) { + p++; + } + + if (units == "bytes") { + const char *c_str = content_range.c_str(); + char *endptr; + if (p < content_range.length() && isdigit(content_range[p])) { + long first_byte = strtol(c_str + p, &endptr, 10); + p = endptr - c_str; + if (p < content_range.length() && content_range[p] == '-') { + p++; + if (p < content_range.length() && isdigit(content_range[p])) { + long last_byte = strtol(c_str + p, &endptr, 10); + p = endptr - c_str; + + if (last_byte >= first_byte) { + _first_byte_delivered = first_byte; + _last_byte_delivered = last_byte; + return true; + } + } + } + } + } + + // Invalid or unhandled response. + return false; +} + +/** + * Resets the indication of how the document will be downloaded. This must be + * re-specified after each get_document() (or related) call. + */ +void HTTPChannel:: +reset_download_to() { + close_download_stream(); + _download_dest = DD_none; +} + +/** + * Ensures the file opened for receiving the download has been correctly + * closed. + */ +void HTTPChannel:: +close_download_stream() { + if (_download_to_stream != nullptr) { + _download_to_stream->flush(); + if (_download_dest == DD_file) { + VirtualFileSystem::close_write_file(_download_to_stream); + } + } + _download_to_ramfile = nullptr; + _download_to_stream = nullptr; +} + +/** + * Specifies a Ramfile object to download the resulting document to. This + * should be called immediately after get_document() or begin_get_document() + * or related functions. + * + * In the case of the blocking I/O methods like get_document(), this function + * will download the entire document to the Ramfile and return true if it was + * successfully downloaded, false otherwise. + * + * In the case of non-blocking I/O methods like begin_get_document(), this + * function simply indicates an intention to download to the indicated + * Ramfile. It returns true if the file can be opened for writing, false + * otherwise, but the contents will not be completely downloaded until run() + * has returned false. At this time, it is possible that a communications + * error will have left a partial file, so is_download_complete() may be + * called to test this. + * + * If subdocument_resumes is true and the document in question was previously + * requested as a subdocument (i.e. get_subdocument() with a first_byte value + * greater than zero), this will automatically seek to the appropriate byte + * within the Ramfile for writing the output. In this case, the Ramfile must + * already have at least first_byte bytes in it. + */ +bool HTTPChannel:: +download_to_ram(Ramfile *ramfile, bool subdocument_resumes) { + State state = get_state(); + nassertr(state != S_unsent, false); + nassertr(ramfile != nullptr, false); + + reset_download_to(); + ramfile->_pos = 0; + _download_dest = DD_ram; + _download_to_ramfile = ramfile; + _subdocument_resumes = (subdocument_resumes && _first_byte_delivered != 0); + + if (state != S_done && _wanted_nonblocking) { + // In nonblocking mode, we just kick off the request. + return state != S_opened || run_send(); + } + + // In normal, blocking mode, go ahead and do the download. + if (!open_download_file()) { + reset_download_to(); + return false; + } + + if (state != S_done) { + while (run()) { + } + } + + // Copy the entire response text. + int bytes_read = EM_ASM_INT({ + var xhr = window._httpChannels[$0]; + var state = xhr.readyState; + var body = xhr.responseText; + var ptr = __extend_string($1, body.length); + writeAsciiToMemory(body, ptr, true); + return state; + }, this, &ramfile->_data); + + _bytes_downloaded = bytes_read; + + close_download_stream(); + + return is_valid(); +} + +/** + * Specifies the name of an ostream to download the resulting document to. + * This should be called immediately after get_document() or + * begin_get_document() or related functions. + * + * In the case of the blocking I/O methods like get_document(), this function + * will download the entire document to the file and return true if it was + * successfully downloaded, false otherwise. + * + * In the case of non-blocking I/O methods like begin_get_document(), this + * function simply indicates an intention to download to the indicated file. + * It returns true if the file can be opened for writing, false otherwise, but + * the contents will not be completely downloaded until run() has returned + * false. At this time, it is possible that a communications error will have + * left a partial file, so is_download_complete() may be called to test this. + * + * If subdocument_resumes is true and the document in question was previously + * requested as a subdocument (i.e. get_subdocument() with a first_byte value + * greater than zero), this will automatically seek to the appropriate byte + * within the file for writing the output. In this case, the file must + * already exist and must have at least first_byte bytes in it. If + * subdocument_resumes is false, a subdocument will always be downloaded + * beginning at the first byte of the file. + */ +bool HTTPChannel:: +download_to_stream(std::ostream *strm, bool subdocument_resumes) { + State state = get_state(); + nassertr(state != S_unsent, false); + + reset_download_to(); + _download_dest = DD_stream; + _download_to_stream = strm; + _download_to_stream->clear(); + _subdocument_resumes = subdocument_resumes; + + if (state != S_done && _wanted_nonblocking) { + // In nonblocking mode, we just kick off the request. + return state != S_opened || run_send(); + } + + // In normal, blocking mode, go ahead and do the download. + if (!open_download_file()) { + reset_download_to(); + return false; + } + + if (state != S_done) { + while (run()) { + } + } + + // Copy the entire response text. + char buffer[4096]; + int bytes_read = EM_ASM_INT({ + var xhr = window._httpChannels[$0]; + var state = xhr.readyState; + var body = xhr.responseText; + var read = 0; + while (read < body.length) { + var size = Math.min(body.length - read, 4096); + for (var dest = $2; dest < $2 + size; ++dest) { + HEAP8[(dest>>0)] = body.charCodeAt(read++) & 0xff; + } + __write_stream($1, $2, size); + } + return read; + }, this, strm, buffer); + + strm->flush(); + _bytes_downloaded = bytes_read; + + close_download_stream(); + + return is_valid(); +} + +#endif // __EMSCRIPTEN__ diff --git a/panda/src/downloader/httpChannel_emscripten.h b/panda/src/downloader/httpChannel_emscripten.h new file mode 100644 index 0000000000..f75d959951 --- /dev/null +++ b/panda/src/downloader/httpChannel_emscripten.h @@ -0,0 +1,241 @@ +/** + * PANDA 3D SOFTWARE + * Copyright (c) Carnegie Mellon University. All rights reserved. + * + * All use of this software is subject to the terms of the revised BSD + * license. You should have received a copy of this license along + * with this source code in a file named "LICENSE." + * + * @file httpChannel_emscripten.h + * @author rdb + * @date 2021-02-10 + */ + +#ifndef HTTPCHANNEL_EMSCRIPTEN_H +#define HTTPCHANNEL_EMSCRIPTEN_H + +#include "pandabase.h" + +#ifdef __EMSCRIPTEN__ + +#include "config_downloader.h" +#include "documentSpec.h" +#include "httpEnum.h" +#include "pmap.h" +#include "pointerTo.h" +#include "pvector.h" +#include "ramfile.h" +#include "typedReferenceCount.h" +#include "urlSpec.h" + +class HTTPClient; + +/** + * This is a reduced implementation of HTTPChannel used on the web, which uses + * XMLHttpRequest instead of OpenSSL. It offers fewer features. + */ +class EXPCL_PANDA_DOWNLOADER HTTPChannel : public TypedReferenceCount { +private: + HTTPChannel(HTTPClient *client); + +public: + virtual ~HTTPChannel(); + +PUBLISHED: + // get_status_code() will either return an HTTP-style status code >= 100 + // (e.g. 404), or one of the following values. In general, these are + // ordered from less-successful to more-successful. + enum StatusCode { + SC_incomplete = 0, + SC_internal_error, + SC_no_connection, + SC_timeout, + SC_lost_connection, + SC_non_http_response, + SC_invalid_http, + SC_socks_invalid_version, + SC_socks_no_acceptable_login_method, + SC_socks_refused, + SC_socks_no_connection, + SC_ssl_internal_failure, + SC_ssl_no_handshake, + + // No one returns this code, but StatusCode values higher than this are + // deemed more successful than any generic HTTP response. + SC_http_error_watermark, + + SC_ssl_invalid_server_certificate, + SC_ssl_self_signed_server_certificate, + SC_ssl_unexpected_server, + + // These errors are only generated after a download_to_*() call been + // issued. + SC_download_open_error, + SC_download_write_error, + SC_download_invalid_range, + }; + + INLINE HTTPClient *get_client() const; + + INLINE bool is_valid() const; + + INLINE const URLSpec &get_url() const; + INLINE const DocumentSpec &get_document_spec() const; + INLINE int get_status_code() const; + INLINE std::string get_status_string() const; + INLINE const std::string &get_www_realm() const; + std::string get_header_value(const std::string &key) const; + + INLINE void set_content_type(std::string content_type); + INLINE std::string get_content_type() const; + + INLINE void set_expected_file_size(size_t file_size); + std::streamsize get_file_size() const; + INLINE bool is_file_size_known() const; + + INLINE size_t get_first_byte_requested() const; + INLINE size_t get_last_byte_requested() const; + INLINE size_t get_first_byte_delivered() const; + INLINE size_t get_last_byte_delivered() const; + + void write_headers(std::ostream &out) const; + + INLINE void reset(); + INLINE void preserve_status(); + + INLINE void clear_extra_headers(); + INLINE void send_extra_header(const std::string &key, const std::string &value); + + BLOCKING INLINE bool get_document(const DocumentSpec &url); + BLOCKING INLINE bool get_subdocument(const DocumentSpec &url, + size_t first_byte, size_t last_byte); + BLOCKING INLINE bool get_header(const DocumentSpec &url); + BLOCKING INLINE bool post_form(const DocumentSpec &url, const std::string &body); + BLOCKING INLINE bool put_document(const DocumentSpec &url, const std::string &body); + BLOCKING INLINE bool delete_document(const DocumentSpec &url); + BLOCKING INLINE bool get_options(const DocumentSpec &url); + + INLINE void begin_get_document(const DocumentSpec &url); + INLINE void begin_get_subdocument(const DocumentSpec &url, + size_t first_byte, size_t last_byte); + INLINE void begin_get_header(const DocumentSpec &url); + INLINE void begin_post_form(const DocumentSpec &url, const std::string &body); + bool run(); + + BLOCKING bool download_to_ram(Ramfile *ramfile, bool subdocument_resumes = true); + BLOCKING bool download_to_stream(std::ostream *strm, bool subdocument_resumes = true); + + INLINE size_t get_bytes_downloaded() const; + INLINE size_t get_bytes_requested() const; + INLINE bool is_download_complete() const; + +private: + enum State { + S_unsent = 0, + S_opened = 1, + S_headers_received = 2, + S_loading = 3, + S_done = 4 + }; + State get_state() const; + + bool run_send(); + bool run_headers_received(); + + bool begin_request(HTTPEnum::Method method, const DocumentSpec &url, + const std::string &body, bool nonblocking, + size_t first_byte, size_t last_byte); + void reset_for_new_request(); + + bool open_download_file(); + + bool parse_content_range(const std::string &content_range); + + void reset_download_to(); + void close_download_stream(); + +private: + class StatusEntry { + public: + INLINE StatusEntry(); + int _status_code; + std::string _status_string; + }; + typedef pvector StatusList; + + HTTPClient *_client; + StatusList _status_list; + URLSpec _proxy; + + typedef std::pair ExtraHeader; + pvector _send_extra_headers; + + bool _nonblocking; + bool _wanted_nonblocking; + + DocumentSpec _document_spec; + DocumentSpec _request; + HTTPEnum::Method _method; + std::string request_path; + std::string _header; + std::string _body; + std::string _content_type; + size_t _first_byte_requested; + size_t _last_byte_requested; + size_t _first_byte_delivered; + size_t _last_byte_delivered; + + enum DownloadDest { + DD_none, + DD_file, + DD_ram, + DD_stream, + }; + DownloadDest _download_dest; + bool _subdocument_resumes; + //Filename _download_to_filename; + Ramfile *_download_to_ramfile; + std::ostream *_download_to_stream; + + StatusEntry _status_entry; + + std::string _www_realm; + //std::string _www_username; + //PT(HTTPAuthorization) _www_auth; + + typedef pmap Headers; + Headers _headers; + + size_t _expected_file_size; + size_t _file_size; + size_t _transfer_file_size; + size_t _bytes_downloaded; + size_t _bytes_requested; + bool _got_expected_file_size; + bool _got_file_size; + bool _got_transfer_file_size; + +public: + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + TypedReferenceCount::init_type(); + register_type(_type_handle, "HTTPChannel", + TypedReferenceCount::get_class_type()); + } + +private: + static TypeHandle _type_handle; + friend class HTTPClient; +}; + +#include "httpChannel_emscripten.I" + +#endif // __EMSCRIPTEN__ + +#endif diff --git a/panda/src/downloader/httpClient.h b/panda/src/downloader/httpClient.h index 93490fe642..b2881532c8 100644 --- a/panda/src/downloader/httpClient.h +++ b/panda/src/downloader/httpClient.h @@ -214,6 +214,10 @@ private: #include "httpClient.I" +#elif defined(__EMSCRIPTEN__) + +#include "httpClient_emscripten.h" + #endif // HAVE_OPENSSL #endif diff --git a/panda/src/downloader/httpClient_emscripten.I b/panda/src/downloader/httpClient_emscripten.I new file mode 100644 index 0000000000..e19d6258b8 --- /dev/null +++ b/panda/src/downloader/httpClient_emscripten.I @@ -0,0 +1,32 @@ +/** + * PANDA 3D SOFTWARE + * Copyright (c) Carnegie Mellon University. All rights reserved. + * + * All use of this software is subject to the terms of the revised BSD + * license. You should have received a copy of this license along + * with this source code in a file named "LICENSE." + * + * @file httpClient_emscripten.I + * @author rdb + * @date 2021-02-10 + */ + +/** + * Implements HTTPAuthorization::base64_encode(). This is provided here just + * as a convenient place to publish it for access by the scripting language; + * C++ code should probably use HTTPAuthorization directly. + */ +INLINE std::string HTTPClient:: +base64_encode(const std::string &s) { + return HTTPAuthorization::base64_encode(s); +} + +/** + * Implements HTTPAuthorization::base64_decode(). This is provided here just + * as a convenient place to publish it for access by the scripting language; + * C++ code should probably use HTTPAuthorization directly. + */ +INLINE std::string HTTPClient:: +base64_decode(const std::string &s) { + return HTTPAuthorization::base64_decode(s); +} diff --git a/panda/src/downloader/httpClient_emscripten.cxx b/panda/src/downloader/httpClient_emscripten.cxx new file mode 100644 index 0000000000..a9c32d44ed --- /dev/null +++ b/panda/src/downloader/httpClient_emscripten.cxx @@ -0,0 +1,424 @@ +/** + * PANDA 3D SOFTWARE + * Copyright (c) Carnegie Mellon University. All rights reserved. + * + * All use of this software is subject to the terms of the revised BSD + * license. You should have received a copy of this license along + * with this source code in a file named "LICENSE." + * + * @file httpClient_emscripten.cxx + * @author rdb + * @date 2021-02-10 + */ + +#include "httpClient_emscripten.h" +#include "httpChannel.h" +#include "config_downloader.h" +#include "httpBasicAuthorization.h" +#include "httpDigestAuthorization.h" + +#ifdef __EMSCRIPTEN__ + +#include + +using std::string; + +PT(HTTPClient) HTTPClient::_global_ptr; + +/** + * + */ +HTTPClient:: +HTTPClient() { + ConfigVariableList http_username + ("http-username", + PRC_DESC("Adds one or more username/password pairs to all HTTP clients. The client " + "will present this username/password when asked to authenticate a request " + "for a particular server and/or realm. The username is of the form " + "server:realm:username:password, where either or both of server and " + "realm may be empty, or just realm:username:password or username:password. " + "If the server or realm is empty, they will match anything.")); + + { + // Also load in the general usernames. + int num_unique_values = http_username.get_num_unique_values(); + for (int i = 0; i < num_unique_values; i++) { + string username = http_username.get_unique_value(i); + add_http_username(username); + } + } +} + +/** + * Specifies the username:password string corresponding to a particular server + * and/or realm, when demanded by the server. Either or both of the server or + * realm may be empty; if so, they match anything. Also, the server may be + * set to the special string `"*proxy"`, which will match any proxy server. + * + * If the username is set to the empty string, this clears the password for + * the particular server/realm pair. + */ +void HTTPClient:: +set_username(const string &server, const string &realm, const string &username) { + string key = server + ":" + realm; + if (username.empty()) { + _usernames.erase(key); + } else { + _usernames[key] = username; + } +} + +/** + * Returns the username:password string set for this server/realm pair, or + * empty string if nothing has been set. See set_username(). + */ +string HTTPClient:: +get_username(const string &server, const string &realm) const { + string key = server + ":" + realm; + Usernames::const_iterator ui; + ui = _usernames.find(key); + if (ui != _usernames.end()) { + return (*ui).second; + } + return string(); +} + +/** + * Stores the indicated cookie in the client's list of cookies, as if it had + * been received from a server. + */ +void HTTPClient:: +set_cookie(const HTTPCookie &cookie) { + std::ostringstream stream; + stream << cookie; + std::string str = stream.str(); + + EM_ASM({ + document.cookie = UTF8ToString($0); + }, str.c_str()); +} + +/** + * Removes the cookie with the matching domain/path/name from the client's + * list of cookies. Returns true if it was removed, false if the cookie was + * not matched. + */ +bool HTTPClient:: +clear_cookie(const HTTPCookie &cookie) { + HTTPCookie expired; + expired.set_name(cookie.get_name()); + expired.set_path(cookie.get_path()); + expired.set_domain(cookie.get_domain()); + expired.set_expires(HTTPDate((time_t)0)); + + std::ostringstream stream; + stream << expired; + std::string str = stream.str(); + + return (bool)EM_ASM_INT({ + var set = UTF8ToString($0); + var old = document.cookie; + document.cookie = set; + return (document.cookie !== old); + }, str.c_str()); +} + +/** + * Removes the all stored cookies from the client. + */ +void HTTPClient:: +clear_all_cookies() { + // NB. This is imperfect, and won't clear cookies with other domains or paths. + EM_ASM({ + var cookies = document.cookie.split(";"); + for (var i = 0; i < cookies.length; ++i) { + var name = cookies[i].split("=", 1)[0]; + document.cookie = name + "=;expires=Thu, 01 Jan 1970 00:00:00 GMT"; + } + + cookies = document.cookie.split(";"); + for (var i = 0; i < cookies.length; ++i) { + var name = cookies[i].split("=", 1)[0]; + document.cookie = name + "=;path=/;expires=Thu, 01 Jan 1970 00:00:00 GMT"; + } + }); +} + +/** + * Returns true if there is a cookie in the client matching the given cookie's + * domain/path/name, false otherwise. + */ +//bool HTTPClient:: +//has_cookie(const HTTPCookie &cookie) const { +//} + +/** + * Looks up and returns the cookie in the client matching the given cookie's + * domain/path/name. If there is no matching cookie, returns an empty cookie. + */ +//HTTPCookie HTTPClient:: +//get_cookie(const HTTPCookie &cookie) const { +// return HTTPCookie(); +//} + +/** + * Outputs the complete list of cookies stored on the client, for all domains, + * including the expired cookies (which will normally not be sent back to a + * host). + */ +void HTTPClient:: +write_cookies(std::ostream &out) const { + char *str = (char *)EM_ASM_INT({ + var str = document.cookie.replace(/; ?/g, "\n"); + var len = lengthBytesUTF8(str) + 1; + var buffer = _malloc(len); + stringToUTF8(str, buffer, len); + return buffer; + }); + + out << str << "\n"; + free(str); +} + +/** + * Returns a new HTTPChannel object that may be used for reading multiple + * documents using the same connection, for greater network efficiency than + * calling HTTPClient::get_document() repeatedly (which would force a new + * connection for each document). + * + * Also, HTTPChannel has some additional, less common interface methods than + * the basic interface methods that exist on HTTPClient; if you wish to call + * any of these methods you must first obtain an HTTPChannel. + */ +PT(HTTPChannel) HTTPClient:: +make_channel(bool persistent_connection) { + return new HTTPChannel(this); +} + +/** + * Posts form data to a particular URL and retrieves the response. Returns a + * new HTTPChannel object whether the document is successfully read or not; + * you can test is_valid() and get_return_code() to determine whether the + * document was retrieved. + */ +PT(HTTPChannel) HTTPClient:: +post_form(const URLSpec &url, const string &body) { + PT(HTTPChannel) doc = new HTTPChannel(this); + doc->post_form(url, body); + return doc; +} + +/** + * Opens the named document for reading. Returns a new HTTPChannel object + * whether the document is successfully read or not; you can test is_valid() + * and get_return_code() to determine whether the document was retrieved. + */ +PT(HTTPChannel) HTTPClient:: +get_document(const URLSpec &url) { + PT(HTTPChannel) doc = new HTTPChannel(this); + doc->get_document(url); + return doc; +} + +/** + * Like get_document(), except only the header associated with the document is + * retrieved. This may be used to test for existence of the document; it + * might also return the size of the document (if the server gives us this + * information). + */ +PT(HTTPChannel) HTTPClient:: +get_header(const URLSpec &url) { + PT(HTTPChannel) doc = new HTTPChannel(this); + doc->get_header(url); + return doc; +} + +/** + * Returns the default global HTTPClient. + */ +HTTPClient *HTTPClient:: +get_global_ptr() { + if (_global_ptr == nullptr) { + _global_ptr = new HTTPClient; + } + return _global_ptr; +} + +/** + * Handles a Config definition for http-username as + * server:realm:username:password, where either or both of server and realm + * may be empty, or just server:username:password or username:password. + */ +void HTTPClient:: +add_http_username(const string &http_username) { + size_t c1 = http_username.find(':'); + if (c1 != string::npos) { + size_t c2 = http_username.find(':', c1 + 1); + if (c2 != string::npos) { + size_t c3 = http_username.find(':', c2 + 1); + if (c3 != string::npos) { + size_t c4 = http_username.find(':', c3 + 1); + if (c4 != string::npos) { + // Oops, we have five? Problem. + downloader_cat.error() + << "Invalid http-username " << http_username << "\n"; + } + else { + // Ok, we have four. + set_username(http_username.substr(0, c1), + http_username.substr(c1 + 1, c2 - (c1 + 1)), + http_username.substr(c2 + 1)); + } + } + else { + // We have only three. + set_username(string(), + http_username.substr(0, c1), + http_username.substr(c1 + 1)); + } + } + else { + // We have only two. + set_username(string(), string(), http_username); + } + } else { + // We have only one? Problem. + downloader_cat.error() + << "Invalid http-username " << http_username << "\n"; + } +} + +/** + * Chooses a suitable username:password string for the given URL and realm. + */ +string HTTPClient:: +select_username(const URLSpec &url, const string &realm) const { + string username; + + // Look in several places in order to find the matching username. + + // Fist, if there's a username on the URL, that always wins (except when we + // are looking for a proxy username). + if (url.has_username()) { + username = url.get_username(); + } + + // Otherwise, start looking on the HTTPClient. + if (username.empty()) { + // Try the specific serverrealm. + username = get_username(url.get_server(), realm); + } + if (username.empty()) { + // Then, try the specific serverany realm. + username = get_username(url.get_server(), string()); + } + if (username.empty()) { + // Then, try any server with this realm. + username = get_username(string(), realm); + } + if (username.empty()) { + // Then, take the general password. + username = get_username(string(), string()); + } + + return username; +} + +/** + * Chooses a suitable pre-computed authorization for the indicated URL. + * Returns NULL if no authorization matches. + */ +HTTPAuthorization *HTTPClient:: +select_auth(const URLSpec &url, const string &last_realm) { + Domains &domains = _www_domains; + std::string canon = HTTPAuthorization::get_canonical_url(url).get_url(); + + // Look for the longest domain string that is a prefix of our canonical URL. + // We have to make a linear scan through the list. + Domains::const_iterator best_di = domains.end(); + size_t longest_length = 0; + Domains::const_iterator di; + for (di = domains.begin(); di != domains.end(); ++di) { + const string &domain = (*di).first; + size_t length = domain.length(); + if (domain == canon.substr(0, length)) { + // This domain string matches. Is it the longest? + if (length > longest_length) { + best_di = di; + longest_length = length; + } + } + } + + if (best_di != domains.end()) { + // Ok, we found a matching domain. Use it. + if (downloader_cat.is_spam()) { + downloader_cat.spam() + << "Choosing domain " << (*best_di).first << " for " << url << "\n"; + } + const Realms &realms = (*best_di).second._realms; + // First, try our last realm. + Realms::const_iterator ri; + ri = realms.find(last_realm); + if (ri != realms.end()) { + return (*ri).second; + } + + if (!realms.empty()) { + // Oh well, just return the first realm. + return (*realms.begin()).second; + } + } + + // No matching domains. + return nullptr; +} + +/** + * Generates a new authorization entry in response to a 401 or 407 challenge + * from the server or proxy. The new authorization entry is stored for future + * connections to the same server (or, more precisely, the same domain, which + * may be a subset of the server, or it may include multiple servers). + */ +PT(HTTPAuthorization) HTTPClient:: +generate_auth(const URLSpec &url, const string &challenge) { + HTTPAuthorization::AuthenticationSchemes schemes; + HTTPAuthorization::parse_authentication_schemes(schemes, challenge); + + PT(HTTPAuthorization) auth; + HTTPAuthorization::AuthenticationSchemes::iterator si; + + si = schemes.find("digest"); + if (si != schemes.end()) { + auth = new HTTPDigestAuthorization((*si).second, url, false); + } + + if (auth == nullptr || !auth->is_valid()) { + si = schemes.find("basic"); + if (si != schemes.end()) { + auth = new HTTPBasicAuthorization((*si).second, url, false); + } + } + + if (auth == nullptr || !auth->is_valid()) { + downloader_cat.warning() + << "Don't know how to use any of the server's available authorization schemes:\n"; + for (si = schemes.begin(); si != schemes.end(); ++si) { + downloader_cat.warning() << (*si).first << "\n"; + } + } + else { + // Now that we've got an authorization, store it under under each of its + // suggested domains for future use. + Domains &domains = _www_domains; + const vector_string &domain = auth->get_domain(); + vector_string::const_iterator si; + for (si = domain.begin(); si != domain.end(); ++si) { + domains[(*si)]._realms[auth->get_realm()] = auth; + } + } + + return auth; +} + +#endif // __EMSCRIPTEN__ diff --git a/panda/src/downloader/httpClient_emscripten.h b/panda/src/downloader/httpClient_emscripten.h new file mode 100644 index 0000000000..fd56bb16f9 --- /dev/null +++ b/panda/src/downloader/httpClient_emscripten.h @@ -0,0 +1,93 @@ +/** + * PANDA 3D SOFTWARE + * Copyright (c) Carnegie Mellon University. All rights reserved. + * + * All use of this software is subject to the terms of the revised BSD + * license. You should have received a copy of this license along + * with this source code in a file named "LICENSE." + * + * @file httpClient_emscripten.h + * @author rdb + * @date 2021-02-10 + */ + +#ifndef HTTPCLIENT_EMSCRIPTEN_H +#define HTTPCLIENT_EMSCRIPTEN_H + +#include "pandabase.h" + +#ifdef __EMSCRIPTEN__ + +#include "urlSpec.h" +#include "httpAuthorization.h" +#include "httpEnum.h" +#include "httpChannel.h" +#include "httpCookie.h" +#include "pointerTo.h" +#include "pvector.h" +#include "pmap.h" +#include "referenceCount.h" + +class Filename; +class HTTPChannel; + +/** + * Reduced version of HTTPClient that is available in Emscripten. It uses the + * browser to make HTTP requests. As such, there is only a global HTTPClient + * pointer, and it is not possible to make individual HTTPClient objects. + */ +class EXPCL_PANDA_DOWNLOADER HTTPClient : public ReferenceCount { +private: + HTTPClient(); + +PUBLISHED: + void set_username(const std::string &server, const std::string &realm, const std::string &username); + std::string get_username(const std::string &server, const std::string &realm) const; + + void set_cookie(const HTTPCookie &cookie); + bool clear_cookie(const HTTPCookie &cookie); + void clear_all_cookies(); + //bool has_cookie(const HTTPCookie &cookie) const; + //HTTPCookie get_cookie(const HTTPCookie &cookie) const; + + void write_cookies(std::ostream &out) const; + + PT(HTTPChannel) make_channel(bool persistent_connection); + BLOCKING PT(HTTPChannel) post_form(const URLSpec &url, const std::string &body); + BLOCKING PT(HTTPChannel) get_document(const URLSpec &url); + BLOCKING PT(HTTPChannel) get_header(const URLSpec &url); + + INLINE static std::string base64_encode(const std::string &s); + INLINE static std::string base64_decode(const std::string &s); + + static HTTPClient *get_global_ptr(); + +private: + void add_http_username(const std::string &http_username); + std::string select_username(const URLSpec &url, const std::string &realm) const; + + HTTPAuthorization *select_auth(const URLSpec &url, const std::string &last_realm); + PT(HTTPAuthorization) generate_auth(const URLSpec &url, + const std::string &challenge); + + typedef pmap Usernames; + Usernames _usernames; + + typedef pmap Realms; + class Domain { + public: + Realms _realms; + }; + typedef pmap Domains; + Domains _www_domains; + + static PT(HTTPClient) _global_ptr; + + friend class HTTPChannel; +}; + +#include "httpClient_emscripten.I" + +#endif // __EMSCRIPTEN__ + +#endif diff --git a/panda/src/downloader/httpCookie.cxx b/panda/src/downloader/httpCookie.cxx index 7c7dff1b0e..0578b72539 100644 --- a/panda/src/downloader/httpCookie.cxx +++ b/panda/src/downloader/httpCookie.cxx @@ -13,7 +13,7 @@ #include "httpCookie.h" -#ifdef HAVE_OPENSSL +#if defined(HAVE_OPENSSL) || defined(__EMSCRIPTEN__) #include "httpChannel.h" #include "string_utils.h" diff --git a/panda/src/downloader/httpCookie.h b/panda/src/downloader/httpCookie.h index 26570e4aad..73284f1f8c 100644 --- a/panda/src/downloader/httpCookie.h +++ b/panda/src/downloader/httpCookie.h @@ -20,7 +20,7 @@ // this to establish https connections; this is because it uses the OpenSSL // library to portably handle all of the socket communications. -#ifdef HAVE_OPENSSL +#if defined(HAVE_OPENSSL) || defined(__EMSCRIPTEN__) #include "httpDate.h" #include "urlSpec.h" diff --git a/panda/src/downloader/httpDigestAuthorization.cxx b/panda/src/downloader/httpDigestAuthorization.cxx index 1d80164654..1a57a691cf 100644 --- a/panda/src/downloader/httpDigestAuthorization.cxx +++ b/panda/src/downloader/httpDigestAuthorization.cxx @@ -13,7 +13,7 @@ #include "httpDigestAuthorization.h" -#ifdef HAVE_OPENSSL +#if defined(HAVE_OPENSSL) || defined(__EMSCRIPTEN__) #include "hashVal.h" #include "string_utils.h" diff --git a/panda/src/downloader/httpDigestAuthorization.h b/panda/src/downloader/httpDigestAuthorization.h index ecd2ab3024..78efdbc1a0 100644 --- a/panda/src/downloader/httpDigestAuthorization.h +++ b/panda/src/downloader/httpDigestAuthorization.h @@ -20,7 +20,7 @@ // use any OpenSSL code, because it is a support module for HTTPChannel, which // *does* use OpenSSL code. -#ifdef HAVE_OPENSSL +#if defined(HAVE_OPENSSL) || defined(__EMSCRIPTEN__) #include "httpAuthorization.h" diff --git a/panda/src/downloader/httpEnum.cxx b/panda/src/downloader/httpEnum.cxx index ebe7914110..9e1df29e35 100644 --- a/panda/src/downloader/httpEnum.cxx +++ b/panda/src/downloader/httpEnum.cxx @@ -13,7 +13,7 @@ #include "httpEnum.h" -#ifdef HAVE_OPENSSL +#if defined(HAVE_OPENSSL) || defined(__EMSCRIPTEN__) /** * diff --git a/panda/src/downloader/httpEnum.h b/panda/src/downloader/httpEnum.h index 1beec15753..1a6388bebf 100644 --- a/panda/src/downloader/httpEnum.h +++ b/panda/src/downloader/httpEnum.h @@ -20,7 +20,7 @@ // this to establish https connections; this is because it uses the OpenSSL // library to portably handle all of the socket communications. -#ifdef HAVE_OPENSSL +#if defined(HAVE_OPENSSL) || defined(__EMSCRIPTEN__) /** * This class is just used as a namespace wrapper for some of the enumerated @@ -28,12 +28,14 @@ */ class EXPCL_PANDA_DOWNLOADER HTTPEnum { PUBLISHED: +#ifdef HAVE_OPENSSL enum HTTPVersion { HV_09, // HTTP 0.9 or older HV_10, // HTTP 1.0 HV_11, // HTTP 1.1 HV_other, }; +#endif enum Method { M_options, diff --git a/panda/src/downloader/p3downloader_composite2.cxx b/panda/src/downloader/p3downloader_composite2.cxx index 4afed2e40a..2d60fbeae2 100644 --- a/panda/src/downloader/p3downloader_composite2.cxx +++ b/panda/src/downloader/p3downloader_composite2.cxx @@ -1,7 +1,9 @@ #include "httpAuthorization.cxx" #include "httpBasicAuthorization.cxx" #include "httpChannel.cxx" +#include "httpChannel_emscripten.cxx" #include "httpClient.cxx" +#include "httpClient_emscripten.cxx" #include "httpCookie.cxx" #include "httpDate.cxx" #include "httpDigestAuthorization.cxx" diff --git a/panda/src/downloader/virtualFileHTTP.cxx b/panda/src/downloader/virtualFileHTTP.cxx index 8e392c3d16..ee36ea95bd 100644 --- a/panda/src/downloader/virtualFileHTTP.cxx +++ b/panda/src/downloader/virtualFileHTTP.cxx @@ -19,7 +19,7 @@ #include -#ifdef HAVE_OPENSSL +#if defined(HAVE_OPENSSL) || defined(__EMSCRIPTEN__) using std::istream; using std::ostream; @@ -140,9 +140,32 @@ open_read_file(bool auto_unwrap) const { return nullptr; } + strstream->seekg(0); + return return_file(strstream, auto_unwrap); } +/** + * Fills up the indicated string with the contents of the file, if it is a + * regular file. Returns true on success, false otherwise. + */ +bool VirtualFileHTTP:: +read_file(string &result, bool auto_unwrap) const { + result = string(); + + if (_status_only) { + return false; + } + + Ramfile ramfile; + if (!_channel->download_to_ram(&ramfile, false)) { + return false; + } + + result = std::move(ramfile._data); + return true; +} + /** * Fills up the indicated pvector with the contents of the file, if it is a * regular file. Returns true on success, false otherwise. diff --git a/panda/src/downloader/virtualFileHTTP.h b/panda/src/downloader/virtualFileHTTP.h index 219390f4aa..49e5f4bd19 100644 --- a/panda/src/downloader/virtualFileHTTP.h +++ b/panda/src/downloader/virtualFileHTTP.h @@ -20,7 +20,7 @@ #include "httpChannel.h" #include "urlSpec.h" -#ifdef HAVE_OPENSSL +#if defined(HAVE_OPENSSL) || defined(__EMSCRIPTEN__) class VirtualFileMountHTTP; @@ -51,6 +51,7 @@ public: virtual std::streamsize get_file_size() const; virtual time_t get_timestamp() const; + virtual bool read_file(std::string &result, bool auto_unwrap) const; virtual bool read_file(vector_uchar &result, bool auto_unwrap) const; private: diff --git a/panda/src/downloader/virtualFileMountHTTP.cxx b/panda/src/downloader/virtualFileMountHTTP.cxx index 09625d53bc..a17666eb88 100644 --- a/panda/src/downloader/virtualFileMountHTTP.cxx +++ b/panda/src/downloader/virtualFileMountHTTP.cxx @@ -15,7 +15,7 @@ #include "virtualFileHTTP.h" #include "virtualFileSystem.h" -#ifdef HAVE_OPENSSL +#if defined(HAVE_OPENSSL) || defined(__EMSCRIPTEN__) using std::string; diff --git a/panda/src/downloader/virtualFileMountHTTP.h b/panda/src/downloader/virtualFileMountHTTP.h index 265e785c40..d6000ce0be 100644 --- a/panda/src/downloader/virtualFileMountHTTP.h +++ b/panda/src/downloader/virtualFileMountHTTP.h @@ -16,7 +16,7 @@ #include "pandabase.h" -#ifdef HAVE_OPENSSL +#if defined(HAVE_OPENSSL) || defined(__EMSCRIPTEN__) #include "virtualFileMount.h" #include "httpClient.h" diff --git a/panda/src/event/asyncFuture_ext.cxx b/panda/src/event/asyncFuture_ext.cxx index eaed216bfe..44163e9be6 100644 --- a/panda/src/event/asyncFuture_ext.cxx +++ b/panda/src/event/asyncFuture_ext.cxx @@ -84,8 +84,7 @@ static PyObject *get_done_result(const AsyncFuture *future) { future->get_result(ptr, ref_ptr); if (ptr == nullptr) { - Py_INCREF(Py_None); - return Py_None; + return Py_NewRef(Py_None); } TypeHandle type = ptr->get_type(); @@ -133,7 +132,7 @@ static PyObject *get_done_result(const AsyncFuture *future) { /** * Yields continuously until the task has finished. */ -static PyObject *gen_next(PyObject *self) { +static PyObject *gen_next_asyncfuture(PyObject *self) { const AsyncFuture *future = nullptr; if (!Dtool_Call_ExtractThisPointer(self, Dtool_AsyncFuture, (void **)&future)) { return nullptr; @@ -141,9 +140,9 @@ static PyObject *gen_next(PyObject *self) { if (!future->done()) { // Continue awaiting the result. - Py_INCREF(self); - return self; - } else { + return Py_NewRef(self); + } + else { PyObject *result = get_done_result(future); if (result != nullptr) { PyErr_SetObject(PyExc_StopIteration, result); @@ -159,7 +158,7 @@ static PyObject *gen_next(PyObject *self) { */ PyObject *Extension:: __await__(PyObject *self) { - return Dtool_NewGenerator(self, &gen_next); + return Dtool_NewGenerator(self, &gen_next_asyncfuture); } /** @@ -323,8 +322,7 @@ add_done_callback(PyObject *self, PyObject *fn) { _this->add_waiting_task(task); - Py_INCREF(Py_None); - return Py_None; + return Py_NewRef(Py_None); } /** diff --git a/panda/src/event/asyncTaskManager.cxx b/panda/src/event/asyncTaskManager.cxx index 43dc285f04..d02adf0501 100644 --- a/panda/src/event/asyncTaskManager.cxx +++ b/panda/src/event/asyncTaskManager.cxx @@ -663,3 +663,16 @@ make_global_ptr() { _global_ptr = new AsyncTaskManager("TaskManager"); _global_ptr->ref(); } + +#ifdef __EMSCRIPTEN__ + +extern "C" void task_manager_poll(); + +void task_manager_poll() { + AsyncTaskManager *mgr = AsyncTaskManager::get_global_ptr(); + nassertv_always(mgr != NULL); + + mgr->poll(); +} + +#endif diff --git a/panda/src/event/pythonTask.I b/panda/src/event/pythonTask.I index 78f8e30cc7..2e9bca8c64 100644 --- a/panda/src/event/pythonTask.I +++ b/panda/src/event/pythonTask.I @@ -16,8 +16,7 @@ */ INLINE PyObject *PythonTask:: get_function() { - Py_INCREF(_function); - return _function; + return Py_NewRef(_function); } /** @@ -25,8 +24,7 @@ get_function() { */ INLINE PyObject *PythonTask:: get_upon_death() { - Py_INCREF(_upon_death); - return _upon_death; + return Py_NewRef(_upon_death); } /** @@ -34,8 +32,7 @@ get_upon_death() { */ INLINE PyObject *PythonTask:: get_owner() const { - Py_INCREF(_owner); - return _owner; + return Py_NewRef(_owner); } /** @@ -50,7 +47,5 @@ set_result(PyObject *result) { nassertv(is_alive()); nassertv(!done()); nassertv(_exception == nullptr); - Py_INCREF(result); - Py_XDECREF(_exc_value); - _exc_value = result; + Py_XSETREF(_exc_value, Py_NewRef(result)); } diff --git a/panda/src/event/pythonTask.cxx b/panda/src/event/pythonTask.cxx index 882d98d801..02e9185090 100644 --- a/panda/src/event/pythonTask.cxx +++ b/panda/src/event/pythonTask.cxx @@ -51,17 +51,17 @@ PythonTask(PyObject *func_or_coro, const std::string &name) : nassertv(func_or_coro != nullptr); if (func_or_coro == Py_None || PyCallable_Check(func_or_coro)) { - _function = func_or_coro; - Py_INCREF(_function); - } else if (PyCoro_CheckExact(func_or_coro)) { + _function = Py_NewRef(func_or_coro); + } + else if (PyCoro_CheckExact(func_or_coro)) { // We also allow passing in a coroutine, because why not. - _generator = func_or_coro; - Py_INCREF(_generator); - } else if (PyGen_CheckExact(func_or_coro)) { + _generator = Py_NewRef(func_or_coro); + } + else if (PyGen_CheckExact(func_or_coro)) { // Something emulating a coroutine. - _generator = func_or_coro; - Py_INCREF(_generator); - } else { + _generator = Py_NewRef(func_or_coro); + } + else { nassert_raise("Invalid function passed to PythonTask"); } @@ -97,9 +97,17 @@ PythonTask:: _exc_traceback = nullptr; } + PyObject *self = __self__; + if (self != nullptr) { + PyObject_GC_UnTrack(self); + __self__ = nullptr; + Py_DECREF(self); + } + + // All of these may have already been cleared by __clear__. Py_XDECREF(_function); - Py_DECREF(_args); - Py_DECREF(__dict__); + Py_XDECREF(_args); + Py_XDECREF(__dict__); Py_XDECREF(_exception); Py_XDECREF(_exc_value); Py_XDECREF(_exc_traceback); @@ -114,10 +122,8 @@ PythonTask:: */ void PythonTask:: set_function(PyObject *function) { - Py_XDECREF(_function); + Py_XSETREF(_function, Py_NewRef(function)); - _function = function; - Py_INCREF(_function); if (_function != Py_None && !PyCallable_Check(_function)) { nassert_raise("Invalid function passed to PythonTask"); } @@ -165,18 +171,16 @@ get_args() { PyObject *with_task = PyTuple_New(num_args + 1); for (int i = 0; i < num_args; ++i) { PyObject *item = PyTuple_GET_ITEM(_args, i); - Py_INCREF(item); - PyTuple_SET_ITEM(with_task, i, item); + PyTuple_SET_ITEM(with_task, i, Py_NewRef(item)); } this->ref(); PyObject *self = DTool_CreatePyInstance(this, Dtool_PythonTask, true, false); PyTuple_SET_ITEM(with_task, num_args, self); return with_task; - - } else { - Py_INCREF(_args); - return _args; + } + else { + return Py_NewRef(_args); } } @@ -186,10 +190,8 @@ get_args() { */ void PythonTask:: set_upon_death(PyObject *upon_death) { - Py_XDECREF(_upon_death); + Py_XSETREF(_upon_death, Py_NewRef(upon_death)); - _upon_death = upon_death; - Py_INCREF(_upon_death); if (_upon_death != Py_None && !PyCallable_Check(_upon_death)) { nassert_raise("Invalid upon_death function passed to PythonTask"); } @@ -234,9 +236,7 @@ set_owner(PyObject *owner) { unregister_from_owner(); } - Py_XDECREF(_owner); - _owner = owner; - Py_INCREF(_owner); + Py_XSETREF(_owner, Py_NewRef(owner)); if (_owner != Py_None && _state != S_inactive) { register_to_owner(); @@ -254,14 +254,11 @@ get_result() const { if (_exception == nullptr) { // The result of the call is stored in _exc_value. - Py_XINCREF(_exc_value); - return _exc_value; - } else { + return Py_XNewRef(_exc_value); + } + else { _retrieved_exception = true; - Py_INCREF(_exception); - Py_XINCREF(_exc_value); - Py_XINCREF(_exc_traceback); - PyErr_Restore(_exception, _exc_value, _exc_traceback); + PyErr_Restore(Py_NewRef(_exception), Py_XNewRef(_exc_value), Py_XNewRef(_exc_traceback)); return nullptr; } } @@ -273,13 +270,15 @@ get_result() const { /*PyObject *PythonTask:: exception() const { if (_exception == nullptr) { - Py_INCREF(Py_None); - return Py_None; - } else if (_exc_value == nullptr || _exc_value == Py_None) { + return Py_NewRef(Py_None); + } + else if (_exc_value == nullptr || _exc_value == Py_None) { return PyObject_CallNoArgs(_exception); - } else if (PyTuple_Check(_exc_value)) { + } + else if (PyTuple_Check(_exc_value)) { return PyObject_Call(_exception, _exc_value, nullptr); - } else { + } + else { return PyObject_CallOneArg(_exception, _exc_value); } }*/ @@ -301,7 +300,6 @@ __setattr__(PyObject *self, PyObject *attr, PyObject *v) { PyObject *descr = _PyType_Lookup(Py_TYPE(self), attr); if (descr != nullptr) { - Py_INCREF(descr); descrsetfunc f = descr->ob_type->tp_descr_set; if (f != nullptr) { return f(descr, self, v); @@ -363,8 +361,7 @@ __getattribute__(PyObject *self, PyObject *attr) const { if (item != nullptr) { // PyDict_GetItem returns a borrowed reference. - Py_INCREF(item); - return item; + return Py_NewRef(item); } return PyObject_GenericGetAttr(self, attr); @@ -375,14 +372,13 @@ __getattribute__(PyObject *self, PyObject *attr) const { */ int PythonTask:: __traverse__(visitproc visit, void *arg) { -/* + Py_VISIT(__self__); Py_VISIT(_function); Py_VISIT(_args); Py_VISIT(_upon_death); Py_VISIT(_owner); Py_VISIT(__dict__); Py_VISIT(_generator); -*/ return 0; } @@ -391,17 +387,58 @@ __traverse__(visitproc visit, void *arg) { */ int PythonTask:: __clear__() { -/* Py_CLEAR(_function); Py_CLEAR(_args); Py_CLEAR(_upon_death); Py_CLEAR(_owner); Py_CLEAR(__dict__); Py_CLEAR(_generator); -*/ + + Py_CLEAR(__self__); return 0; } +/** + * + */ +bool PythonTask:: +unref() const { + if (!AsyncTask::unref()) { + // It was cleaned up by the Python garbage collector. + return false; + } + + // If the last reference to the object is the one being held by Python, + // check whether the Python wrapper itself is also at a refcount of 1. + bool result = true; + if (get_ref_count() == 1) { + PyGILState_STATE gstate = PyGILState_Ensure(); + + // Check whether we have a Python wrapper. This is not the case if the + // object has been created by C++ and never been exposed to Python code. + PyObject *self = __self__; + if (self != nullptr) { + int ref_count = Py_REFCNT(self); + assert(ref_count > 0); + if (ref_count == 1) { + // The last reference to the Python wrapper is being held by us. + // Break the reference cycle and allow the object to go away. + if (!AsyncTask::unref()) { + PyObject_GC_UnTrack(self); + ((Dtool_PyInstDef *)self)->_memory_rules = false; + __self__ = nullptr; + Py_DECREF(self); + + // Let the caller destroy the object. + result = false; + } + } + } + PyGILState_Release(gstate); + } + return result; +} + /** * Cancels this task. This is equivalent to remove(), except for coroutines, * for which it will throw an exception into any currently pending await. @@ -625,7 +662,7 @@ do_python_task() { if (result == nullptr) { result = Py_None; } - Py_INCREF(result); + result = Py_NewRef(result); Py_DECREF(exc); #else if (_PyGen_FetchStopIterationValue(&result) == 0) { diff --git a/panda/src/event/pythonTask.h b/panda/src/event/pythonTask.h index 88bee56bd9..148252e999 100644 --- a/panda/src/event/pythonTask.h +++ b/panda/src/event/pythonTask.h @@ -89,6 +89,14 @@ PUBLISHED: // custom variables may be stored. PyObject *__dict__; +public: + // This holds a reference to the Python wrapper corresponding to this + // PythonTask object. It is necessary for this to remain consistent for + // the __traverse__ method to work correctly. + mutable PyObject *__self__ = nullptr; + + virtual bool unref() const; + protected: virtual bool cancel(); diff --git a/panda/src/express/datagram_ext.I b/panda/src/express/datagram_ext.I index 284d9b2bf3..70a71a8b44 100644 --- a/panda/src/express/datagram_ext.I +++ b/panda/src/express/datagram_ext.I @@ -47,10 +47,10 @@ __reduce__() const { } extern struct Dtool_PyTypedObject Dtool_Datagram; - Py_INCREF((PyObject *)&Dtool_Datagram._PyType); + PyObject *tp = (PyObject *)&Dtool_Datagram._PyType; PyObject *result = PyTuple_New(2); - PyTuple_SET_ITEM(result, 0, (PyObject *)&Dtool_Datagram._PyType); + PyTuple_SET_ITEM(result, 0, Py_NewRef(tp)); PyTuple_SET_ITEM(result, 1, args); return result; } diff --git a/panda/src/express/multifile.I b/panda/src/express/multifile.I index d418c77598..266670b077 100644 --- a/panda/src/express/multifile.I +++ b/panda/src/express/multifile.I @@ -68,7 +68,7 @@ get_timestamp() const { } /** - * Changes the overall mudification timestamp of the multifile. Note that this + * Changes the overall modification timestamp of the multifile. Note that this * will be reset to the current time every time you modify a subfile. * Only set this if you know what you are doing! */ diff --git a/panda/src/express/pointerToArray_ext.I b/panda/src/express/pointerToArray_ext.I index 039f3f011c..3406a67263 100644 --- a/panda/src/express/pointerToArray_ext.I +++ b/panda/src/express/pointerToArray_ext.I @@ -304,10 +304,7 @@ __getbuffer__(PyObject *self, Py_buffer *view, int flags) { return -1; } - if (self != nullptr) { - Py_INCREF(self); - } - view->obj = self; + view->obj = Py_XNewRef(self); view->buf = (void*) this->_this->p(); view->len = this->_this->size() * sizeof(Element); view->readonly = 0; @@ -345,10 +342,7 @@ __getbuffer__(PyObject *self, Py_buffer *view, int flags) { template<> INLINE int Extension >:: __getbuffer__(PyObject *self, Py_buffer *view, int flags) { - if (self != nullptr) { - Py_INCREF(self); - } - view->obj = self; + view->obj = Py_XNewRef(self); view->buf = (void*) this->_this->p(); set_matrix_view(*view, flags, this->_this->size(), 3, false, false); @@ -367,10 +361,7 @@ __getbuffer__(PyObject *self, Py_buffer *view, int flags) { template<> INLINE int Extension >:: __getbuffer__(PyObject *self, Py_buffer *view, int flags) { - if (self != nullptr) { - Py_INCREF(self); - } - view->obj = self; + view->obj = Py_XNewRef(self); view->buf = (void*) this->_this->p(); set_matrix_view(*view, flags, this->_this->size(), 3, true, false); @@ -389,10 +380,7 @@ __getbuffer__(PyObject *self, Py_buffer *view, int flags) { template<> INLINE int Extension >:: __getbuffer__(PyObject *self, Py_buffer *view, int flags) { - if (self != nullptr) { - Py_INCREF(self); - } - view->obj = self; + view->obj = Py_XNewRef(self); view->buf = (void*) this->_this->p(); set_matrix_view(*view, flags, this->_this->size(), 4, false, false); @@ -411,10 +399,7 @@ __getbuffer__(PyObject *self, Py_buffer *view, int flags) { template<> INLINE int Extension >:: __getbuffer__(PyObject *self, Py_buffer *view, int flags) { - if (self != nullptr) { - Py_INCREF(self); - } - view->obj = self; + view->obj = Py_XNewRef(self); view->buf = (void*) this->_this->p(); set_matrix_view(*view, flags, this->_this->size(), 4, true, false); @@ -473,10 +458,7 @@ __getbuffer__(PyObject *self, Py_buffer *view, int flags) const { return -1; } - if (self != nullptr) { - Py_INCREF(self); - } - view->obj = self; + view->obj = Py_XNewRef(self); view->buf = (void*) this->_this->p(); view->len = this->_this->size() * sizeof(Element); view->readonly = 1; @@ -518,10 +500,7 @@ __getbuffer__(PyObject *self, Py_buffer *view, int flags) const { "Object is not writable."); return -1; } - if (self != nullptr) { - Py_INCREF(self); - } - view->obj = self; + view->obj = Py_XNewRef(self); view->buf = (void*) this->_this->p(); set_matrix_view(*view, flags, this->_this->size(), 3, false, true); @@ -544,10 +523,7 @@ __getbuffer__(PyObject *self, Py_buffer *view, int flags) const { "Object is not writable."); return -1; } - if (self != nullptr) { - Py_INCREF(self); - } - view->obj = self; + view->obj = Py_XNewRef(self); view->buf = (void*) this->_this->p(); set_matrix_view(*view, flags, this->_this->size(), 3, true, true); @@ -570,10 +546,7 @@ __getbuffer__(PyObject *self, Py_buffer *view, int flags) const { "Object is not writable."); return -1; } - if (self != nullptr) { - Py_INCREF(self); - } - view->obj = self; + view->obj = Py_XNewRef(self); view->buf = (void*) this->_this->p(); set_matrix_view(*view, flags, this->_this->size(), 4, false, true); @@ -596,10 +569,7 @@ __getbuffer__(PyObject *self, Py_buffer *view, int flags) const { "Object is not writable."); return -1; } - if (self != nullptr) { - Py_INCREF(self); - } - view->obj = self; + view->obj = Py_XNewRef(self); view->buf = (void*) this->_this->p(); set_matrix_view(*view, flags, this->_this->size(), 4, true, true); diff --git a/panda/src/express/trueClock.cxx b/panda/src/express/trueClock.cxx index 710473782d..157bac657e 100644 --- a/panda/src/express/trueClock.cxx +++ b/panda/src/express/trueClock.cxx @@ -473,6 +473,46 @@ set_time_scale(double time, double new_time_scale) { _time_scale = new_time_scale; } +#elif defined(__EMSCRIPTEN__) + +/** + * The Emscripten implementation. This uses either the JavaScript function + * performance.now() if available, otherwise Date.now(). + */ + +#include + +/** + * + */ +double TrueClock:: +get_long_time() { + return emscripten_get_now() * 0.001; +} + +/** + * + */ +double TrueClock:: +get_short_raw_time() { + return emscripten_get_now() * 0.001; +} + +/** + * + */ +bool TrueClock:: +set_cpu_affinity(uint32_t mask) const { + return false; +} + +/** + * + */ +TrueClock:: +TrueClock() { +} + #else // !_WIN32 // The Posix implementation. diff --git a/panda/src/express/virtualFile.h b/panda/src/express/virtualFile.h index ca11ee4982..acefe65d83 100644 --- a/panda/src/express/virtualFile.h +++ b/panda/src/express/virtualFile.h @@ -84,7 +84,7 @@ public: INLINE bool write_file(const std::string &data, bool auto_wrap); INLINE void set_original_filename(const Filename &filename); - bool read_file(std::string &result, bool auto_unwrap) const; + virtual bool read_file(std::string &result, bool auto_unwrap) const; virtual bool read_file(vector_uchar &result, bool auto_unwrap) const; virtual bool write_file(const unsigned char *data, size_t data_size, bool auto_wrap); diff --git a/panda/src/express/virtualFileSystem.cxx b/panda/src/express/virtualFileSystem.cxx index 1655c214be..37c220f4ca 100644 --- a/panda/src/express/virtualFileSystem.cxx +++ b/panda/src/express/virtualFileSystem.cxx @@ -28,6 +28,10 @@ #include "executionEnvironment.h" #include "pset.h" +#ifdef __EMSCRIPTEN__ +#include "virtualFileMountHTTP.h" +#endif + using std::iostream; using std::istream; using std::ostream; @@ -853,10 +857,54 @@ get_global_ptr() { _global_ptr = new VirtualFileSystem; // Set up the default mounts. First, there is always the root mount. - _global_ptr->mount("/", "/", 0); +#ifdef __EMSCRIPTEN__ + // Unless we're running in node.js, we don't have a filesystem, and instead + // mount the current server root as our filesystem root. + bool is_node = (bool)EM_ASM_INT(return (typeof process === 'object' && typeof process.versions === 'object' && typeof process.versions.node === 'string')); + if (!is_node) { + _global_ptr->mount(new VirtualFileMountHTTP(URLSpec("/")), "/", MF_read_only); - // And our initial cwd comes from the environment. - _global_ptr->chdir(ExecutionEnvironment::get_cwd()); + // And get the "current working directory". + char cwd[4096]; + bool have_memfs = (bool)EM_ASM_INT({ + var path = location.pathname; + stringToUTF8(path.substring(0, path.lastIndexOf('/')), $0, 4096); + + if (FS && FS.root) { + /* Emscripten creates these by default, but we don't want them. */ + var contents = FS.root.contents; + delete contents.dev; + delete contents.home; + delete contents.proc; + delete contents.tmp; + return true; + } + else { + return false; + } + }, cwd); + + if (cwd[0] == 0) { + cwd[0] = '/'; + cwd[1] = 0; + } + + _global_ptr->_cwd = cwd; + + // If we built with the Emscripten VFS enabled, mount it on top of the + // current directory, so that emscripten's preload system will work. + if (have_memfs) { + _global_ptr->mount("/", _global_ptr->_cwd, MF_read_only); + } + } + else +#endif + { + _global_ptr->mount("/", "/", 0); + + // And our initial cwd comes from the environment. + _global_ptr->chdir(ExecutionEnvironment::get_cwd()); + } // Then, we add whatever mounts are listed in the Configrc file. ConfigVariableList mounts diff --git a/panda/src/framework/pandaFramework.cxx b/panda/src/framework/pandaFramework.cxx index 6c0fb681fc..6d249cdc56 100644 --- a/panda/src/framework/pandaFramework.cxx +++ b/panda/src/framework/pandaFramework.cxx @@ -37,8 +37,24 @@ #endif #endif +extern "C" EXPCL_PANDA_PNMIMAGETYPES void init_libpnmimagetypes(); + using std::string; +#ifdef __EMSCRIPTEN__ +#include + +static void em_do_frame(void *arg) { + PandaFramework *fwx = (PandaFramework *)arg; + nassertv_always(fwx != NULL); + + if (!fwx->do_frame(Thread::get_current_thread())) { + emscripten_cancel_main_loop(); + framework_cat.info() << "Main loop cancelled.\n"; + } +} +#endif + LoaderOptions PandaFramework::_loader_options; /** @@ -115,7 +131,6 @@ open_framework() { // Let's explicitly make a call to the image type library to ensure it gets // pulled in by the dynamic linker. - extern EXPCL_PANDA_PNMIMAGETYPES void init_libpnmimagetypes(); init_libpnmimagetypes(); reset_frame_rate(); @@ -792,9 +807,14 @@ do_frame(Thread *current_thread) { */ void PandaFramework:: main_loop() { +#ifdef __EMSCRIPTEN__ + framework_cat.info() << "Starting main loop.\n"; + emscripten_set_main_loop_arg(&em_do_frame, (void *)this, 0, true); +#else Thread *current_thread = Thread::get_current_thread(); while (do_frame(current_thread)) { } +#endif } /** diff --git a/panda/src/glstuff/glGraphicsBuffer_src.h b/panda/src/glstuff/glGraphicsBuffer_src.h index 83c58ba45b..ab07322293 100644 --- a/panda/src/glstuff/glGraphicsBuffer_src.h +++ b/panda/src/glstuff/glGraphicsBuffer_src.h @@ -36,7 +36,7 @@ * additional bitplanes above and beyond the normal depth,stencil,color. One * can use them to render out multiple textures in a single pass. Cumulative * render-to-texture means that if don't clear the buffer, then the contents - * of the buffer will be equal to the texture's previous contents. This alo + * of the buffer will be equal to the texture's previous contents. This also * means you can meaningfully share a bitplane between two buffers by binding * the same texture to both buffers. * diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.I b/panda/src/glstuff/glGraphicsStateGuardian_src.I index 9571762b6f..dd0afb1ce3 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.I +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.I @@ -256,8 +256,16 @@ INLINE bool CLP(GraphicsStateGuardian):: is_at_least_gles_version(int major_version, int minor_version) const { #ifndef OPENGLES return false; + #elif defined(OPENGLES_1) return major_version == 1 && _gl_version_minor >= minor_version; + +/*#elif defined(__EMSCRIPTEN__) + // We're running WebGL. WebGL 1 is based on OpenGL ES 2, and + // WebGL 2 is based on OpenGL ES 3. So add one to the major version. + // There don't appear to be minor WebGL versions (yet). + return (_gl_version_major + 1 >= major_version); +*/ #else if (_gl_version_major < major_version) { return false; diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 9242c584e8..c50cfddb4f 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -628,6 +628,7 @@ debug_callback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei l void CLP(GraphicsStateGuardian):: reset() { _last_error_check = -1.0; + _white_texture = 0; free_pointers(); GraphicsStateGuardian::reset(); @@ -942,7 +943,10 @@ reset() { #elif defined(OPENGLES) if (gl_support_primitive_restart_index && is_at_least_gles_version(3, 0)) { + // In WebGL 2, primitive restart is always enabled. +#ifndef __EMSCRIPTEN__ glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX); +#endif _supported_geom_rendering |= Geom::GR_strip_cut_index; } @@ -987,6 +991,8 @@ reset() { #ifndef OPENGLES_1 _glDrawRangeElements = null_glDrawRangeElements; + // Temporarily disabled in WebGL due to Firefox bug +#ifndef __EMSCRIPTEN__ #ifdef OPENGLES if (is_at_least_gles_version(3, 0)) { _glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC) @@ -1007,6 +1013,7 @@ reset() { << "glDrawRangeElements advertised as supported by OpenGL runtime, but could not get pointers to extension functions.\n"; _glDrawRangeElements = null_glDrawRangeElements; } +#endif // !__EMSCRIPTEN__ #endif // !OPENGLES_1 _supports_3d_texture = false; @@ -1570,7 +1577,12 @@ reset() { _supports_depth24 = true; _supports_depth32 = true; } else { +#ifdef __EMSCRIPTEN__ + if (has_extension("WEBGL_depth_texture") || + has_extension("GL_ANGLE_depth_texture")) { +#else if (has_extension("GL_ANGLE_depth_texture")) { +#endif // This extension provides both depth textures and depth-stencil support. _supports_depth_texture = true; _supports_depth_stencil = true; @@ -2624,6 +2636,12 @@ reset() { _glDrawBuffers = (PFNGLDRAWBUFFERSPROC) get_extension_func("glDrawBuffers"); +#ifdef __EMSCRIPTEN__ + } else if (has_extension("WEBGL_draw_buffers")) { + _glDrawBuffers = (PFNGLDRAWBUFFERSPROC) + get_extension_func("glDrawBuffers"); +#endif // EMSCRIPTEN + } else if (has_extension("GL_EXT_draw_buffers")) { _glDrawBuffers = (PFNGLDRAWBUFFERSPROC) get_extension_func("glDrawBuffersEXT"); @@ -2839,7 +2857,7 @@ reset() { #elif defined(OPENGLES) // In OpenGL ES 2.x and above, this is supported in the core. - _supports_blend_equation_separate = false; + _supports_blend_equation_separate = true; #else if (is_at_least_gl_version(1, 2)) { @@ -3178,7 +3196,7 @@ reset() { _max_image_units = 0; #ifndef OPENGLES_1 #ifdef OPENGLES - if (is_at_least_gl_version(3, 1)) { + if (is_at_least_gles_version(3, 1) && gl_immutable_texture_storage) { #else if (is_at_least_gl_version(4, 2) || has_extension("GL_ARB_shader_image_load_store")) { #endif @@ -3300,7 +3318,7 @@ reset() { } #endif // !OPENGLES -#ifndef OPENGLES_1 +#if !defined(OPENGLES_1) && !defined(__EMSCRIPTEN__) _supports_get_program_binary = false; _program_binary_formats.clear(); @@ -3641,7 +3659,7 @@ reset() { report_my_gl_errors(); -#ifndef OPENGLES_1 +#if !defined(OPENGLES_1) && !defined(__EMSCRIPTEN__) if (GLCAT.is_debug()) { if (_supports_get_program_binary) { GLCAT.debug() @@ -9633,7 +9651,7 @@ query_glsl_version() { if (ver.empty() || sscanf(ver.c_str(), "%d.%d", &_gl_shadlang_ver_major, &_gl_shadlang_ver_minor) != 2) { - GLCAT.warning() << "Invalid GL_SHADING_LANGUAGE_VERSION format.\n"; + GLCAT.warning() << "Invalid GL_SHADING_LANGUAGE_VERSION format: " << ver << "\n"; } } #else @@ -9644,7 +9662,11 @@ query_glsl_version() { if (ver.empty() || sscanf(ver.c_str(), "OpenGL ES GLSL ES %d.%d", &_gl_shadlang_ver_major, &_gl_shadlang_ver_minor) != 2) { - GLCAT.warning() << "Invalid GL_SHADING_LANGUAGE_VERSION format.\n"; +#ifdef __EMSCRIPTEN__ // See emscripten bug 4070 + if (sscanf(ver.c_str(), "OpenGL ES GLSL %d.%d", &_gl_shadlang_ver_major, + &_gl_shadlang_ver_minor) != 2) +#endif + GLCAT.warning() << "Invalid GL_SHADING_LANGUAGE_VERSION format: " << ver << "\n"; } #endif @@ -11042,6 +11064,13 @@ get_internal_image_format(Texture *tex, bool force_sized) const { } } +#if defined(__EMSCRIPTEN__) && defined(OPENGLES) + // WebGL 1 has no sized formats, it would seem. + if (!is_at_least_gles_version(3, 0)) { + return get_external_image_format(tex); + } +#endif + switch (format) { #ifndef OPENGLES case Texture::F_color_index: @@ -14070,7 +14099,8 @@ upload_texture(CLP(TextureContext) *gtc, bool force, bool uses_mipmaps) { << "Attempt to modify texture with immutable storage, recreating texture.\n"; gtc->reset_data(gtc->_target, num_views); } - else if (_supports_tex_storage && gl_immutable_texture_storage) { + else if (_supports_tex_storage && gl_immutable_texture_storage && + texture_type != Texture::TT_buffer_texture) { gtc->_immutable = true; } } @@ -14284,7 +14314,8 @@ upload_texture_image(CLP(TextureContext) *gtc, int view, bool needs_reload, GLCAT.debug() << "allocating storage for texture " << tex->get_name() << ", " << width << " x " << height << " x " << depth << ", mipmaps " - << num_levels << "\n"; + << num_levels << ", internal_format = 0x" << std::hex + << internal_format << std::dec << "\n"; } switch (texture_type) { diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.h b/panda/src/glstuff/glGraphicsStateGuardian_src.h index dc44c68d61..1abbc1d2a4 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.h +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.h @@ -770,8 +770,11 @@ protected: bool _supports_anisotropy; GLint _max_image_units; bool _supports_multi_bind; + +#if !defined(OPENGLES_1) && !defined(__EMSCRIPTEN__) bool _supports_get_program_binary; pset _program_binary_formats; +#endif #ifdef OPENGLES bool _supports_depth24; diff --git a/panda/src/glstuff/glShaderContext_src.cxx b/panda/src/glstuff/glShaderContext_src.cxx index f3a3667825..7b1fff3273 100644 --- a/panda/src/glstuff/glShaderContext_src.cxx +++ b/panda/src/glstuff/glShaderContext_src.cxx @@ -1192,7 +1192,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) { if (param_type == GL_FLOAT_VEC3) { bind._piece = Shader::SMP_vec3; } else if (param_type == GL_FLOAT_VEC4) { - bind._piece = Shader::SMP_vec3; + bind._piece = Shader::SMP_vec4; } else { GLCAT.error() << "p3d_Color should be vec3 or vec4\n"; @@ -1231,7 +1231,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) { bind._part[0] = Shader::SMO_attr_fogcolor; if (param_type == GL_FLOAT_VEC3) { - bind._piece = Shader::SMP_vec4; + bind._piece = Shader::SMP_vec3; } else if (param_type == GL_FLOAT_VEC4) { bind._piece = Shader::SMP_vec4; } else { @@ -1256,7 +1256,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) { if (param_type == GL_FLOAT) { bind._piece = Shader::SMP_float; - bind._offset = 13; + bind._offset = 1; } else { GLCAT.error() << "p3d_Fog.start should be float\n"; @@ -1268,7 +1268,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) { if (param_type == GL_FLOAT) { bind._piece = Shader::SMP_float; - bind._offset = 14; + bind._offset = 2; } else { GLCAT.error() << "p3d_Fog.end should be float\n"; @@ -1280,7 +1280,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) { if (param_type == GL_FLOAT) { bind._piece = Shader::SMP_float; - bind._offset = 15; + bind._offset = 3; } else { GLCAT.error() << "p3d_Fog.scale should be float\n"; @@ -1708,17 +1708,35 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) { case GL_UNSIGNED_INT_IMAGE_BUFFER: // This won't really change at runtime, so we might as well bind once // and then forget about it. - // Note that OpenGL ES doesn't support changing this at runtime, so we - // rely on the shader using a layout declaration. -#ifndef OPENGLES - _glgsg->_glUniform1i(p, _glsl_img_inputs.size()); -#endif { +#ifdef OPENGLES + // In OpenGL ES, we can't choose our own binding, but we can ask the + // driver what it assigned (or what the shader specified). + GLint binding = 0; + glGetUniformiv(_glsl_program, p, &binding); + if (GLCAT.is_debug()) { + GLCAT.debug() + << "Active uniform " << param_name + << " is bound to image unit " << binding << "\n"; + } + + if (binding >= _glsl_img_inputs.size()) { + _glsl_img_inputs.resize(binding + 1); + } + + ImageInput &input = _glsl_img_inputs[binding]; + input._name = InternalName::make(param_name); +#else + if (GLCAT.is_debug()) { + GLCAT.debug() + << "Binding image uniform " << param_name + << " to image unit " << _glsl_img_inputs.size() << "\n"; + } + _glgsg->_glUniform1i(p, _glsl_img_inputs.size()); ImageInput input; input._name = InternalName::make(param_name); - input._writable = false; - input._gtc = nullptr; - _glsl_img_inputs.push_back(input); + _glsl_img_inputs.push_back(std::move(input)); +#endif } return; default: @@ -2676,6 +2694,10 @@ update_shader_texture_bindings(ShaderContext *prev) { const ParamTextureImage *param = nullptr; Texture *tex; + if (input._name == nullptr) { + continue; + } + const ShaderInput &sinp = _glgsg->_target_shader->get_shader_input(input._name); switch (sinp.get_value_type()) { case ShaderInput::M_texture_image: @@ -2729,6 +2751,16 @@ update_shader_texture_bindings(ShaderContext *prev) { // TODO: automatically convert to sized type instead of plain GL_RGBA // If a base type is used, it will crash. GLenum internal_format = gtc->_internal_format; +#ifdef OPENGLES + if (!gtc->_immutable) { + static bool error_shown = false; + if (!error_shown) { + error_shown = true; + GLCAT.error() + << "Enable gl-immutable-texture-storage to use image textures in OpenGL ES.\n"; + } + } +#endif if (internal_format == GL_RGBA || internal_format == GL_RGB) { GLCAT.error() << "Texture " << tex->get_name() << " has an unsized format. Textures bound " @@ -3264,6 +3296,7 @@ glsl_compile_and_link() { // If we requested to retrieve the shader, we should indicate that before // linking. +#ifndef __EMSCRIPTEN__ bool retrieve_binary = false; if (_glgsg->_supports_get_program_binary) { retrieve_binary = _shader->get_cache_compiled_shader(); @@ -3276,6 +3309,7 @@ glsl_compile_and_link() { _glgsg->_glProgramParameteri(_glsl_program, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE); } +#endif // !__EMSCRIPTEN__ if (GLCAT.is_debug()) { GLCAT.debug() @@ -3296,6 +3330,7 @@ glsl_compile_and_link() { // Report any warnings. glsl_report_program_errors(_glsl_program, false); +#ifndef __EMSCRIPTEN__ if (retrieve_binary) { GLint length = 0; _glgsg->_glGetProgramiv(_glsl_program, GL_PROGRAM_BINARY_LENGTH, &length); @@ -3326,6 +3361,7 @@ glsl_compile_and_link() { } #endif // NDEBUG } +#endif // !__EMSCRIPTEN__ _glgsg->report_my_gl_errors(); return valid; diff --git a/panda/src/glstuff/glShaderContext_src.h b/panda/src/glstuff/glShaderContext_src.h index 7e63c1a611..b42fa97538 100644 --- a/panda/src/glstuff/glShaderContext_src.h +++ b/panda/src/glstuff/glShaderContext_src.h @@ -107,8 +107,8 @@ private: struct ImageInput { CPT(InternalName) _name; - CLP(TextureContext) *_gtc; - bool _writable; + CLP(TextureContext) *_gtc = nullptr; + bool _writable = false; }; pvector _glsl_img_inputs; diff --git a/panda/src/gobj/geomVertexArrayData_ext.cxx b/panda/src/gobj/geomVertexArrayData_ext.cxx index bc135cd184..d3ffa6704a 100644 --- a/panda/src/gobj/geomVertexArrayData_ext.cxx +++ b/panda/src/gobj/geomVertexArrayData_ext.cxx @@ -53,10 +53,7 @@ __getbuffer__(PyObject *self, Py_buffer *view, int flags) { view->internal = (void*) data; - if (self != nullptr) { - Py_INCREF(self); - } - view->obj = self; + view->obj = Py_XNewRef(self); view->buf = (void*) handle->get_write_pointer(); view->len = row_size * handle->get_num_rows(); view->readonly = 0; @@ -115,10 +112,7 @@ __getbuffer__(PyObject *self, Py_buffer *view, int flags) const { view->internal = (void*) data; - if (self != nullptr) { - Py_INCREF(self); - } - view->obj = self; + view->obj = Py_XNewRef(self); view->buf = (void*) handle->get_read_pointer(true); view->len = row_size * handle->get_num_rows(); view->readonly = 1; diff --git a/panda/src/gobj/material.cxx b/panda/src/gobj/material.cxx index a87c978c1c..16496444f5 100644 --- a/panda/src/gobj/material.cxx +++ b/panda/src/gobj/material.cxx @@ -457,7 +457,7 @@ write(std::ostream &out, int indent_level) const { */ void Material:: register_with_read_factory() { - BamReader::get_factory()->register_factory(get_class_type(), make_Material); + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); } /** @@ -503,7 +503,7 @@ write_datagram(BamWriter *manager, Datagram &me) { * Factory method to generate a Material object */ TypedWritable *Material:: -make_Material(const FactoryParams ¶ms) { +make_from_bam(const FactoryParams ¶ms) { Material *me = new Material; DatagramIterator scan; BamReader *manager; diff --git a/panda/src/gobj/material.h b/panda/src/gobj/material.h index 259d5d6874..b0c25de57b 100644 --- a/panda/src/gobj/material.h +++ b/panda/src/gobj/material.h @@ -170,7 +170,7 @@ public: virtual void write_datagram(BamWriter *manager, Datagram &me); protected: - static TypedWritable *make_Material(const FactoryParams ¶ms); + static TypedWritable *make_from_bam(const FactoryParams ¶ms); void fillin(DatagramIterator &scan, BamReader *manager); public: diff --git a/panda/src/gobj/pythonTexturePoolFilter.cxx b/panda/src/gobj/pythonTexturePoolFilter.cxx index 0ceb5c0729..0fc11b181d 100644 --- a/panda/src/gobj/pythonTexturePoolFilter.cxx +++ b/panda/src/gobj/pythonTexturePoolFilter.cxx @@ -78,9 +78,7 @@ init(PyObject *tex_filter) { return false; } - _entry_point = tex_filter; - - Py_INCREF(_entry_point); + _entry_point = Py_NewRef(tex_filter); return true; } diff --git a/panda/src/gobj/texture.I b/panda/src/gobj/texture.I index 1894d72967..0d349f6653 100644 --- a/panda/src/gobj/texture.I +++ b/panda/src/gobj/texture.I @@ -1888,7 +1888,7 @@ set_filename(const Filename &filename) { } /** - * Removes the alpha filename, if it was previously set. See set_filename(). + * Removes the filename, if it was previously set. See set_filename(). */ INLINE void Texture:: clear_filename() { @@ -1904,8 +1904,8 @@ clear_filename() { * The Texture's get_filename() function returns the name of the image file * that was loaded into the buffer. In the case where a texture specified two * separate files to load, a 1- or 3-channel color image and a 1-channel alpha - * image, this Filename is update to contain the name of the image file that - * was loaded into the buffer's alpha channel. + * image, the alpha_filename is updated to contain the name of the image file + * that was loaded into the buffer's alpha channel. */ INLINE void Texture:: set_alpha_filename(const Filename &alpha_filename) { @@ -1935,7 +1935,7 @@ set_fullpath(const Filename &fullpath) { } /** - * Removes the alpha fullpath, if it was previously set. See set_fullpath(). + * Removes the fullpath, if it was previously set. See set_fullpath(). */ INLINE void Texture:: clear_fullpath() { diff --git a/panda/src/gobj/texturePool.cxx b/panda/src/gobj/texturePool.cxx index 5a636c7c18..6143fc3357 100644 --- a/panda/src/gobj/texturePool.cxx +++ b/panda/src/gobj/texturePool.cxx @@ -30,6 +30,10 @@ #include +#ifdef __EMSCRIPTEN__ +#include +#endif + using std::istream; using std::ostream; using std::string; @@ -1070,6 +1074,15 @@ ns_release_all_textures() { // Blow away the cache of resolved relative filenames. _relpath_lookup.clear(); + +#ifdef __EMSCRIPTEN__ + // Also empty the emscripten preload cache. + EM_ASM({ + if (Module["preloadedImages"]) { + Module["preloadedImages"] = {}; + } + }); +#endif } /** diff --git a/panda/src/gobj/textureStage.cxx b/panda/src/gobj/textureStage.cxx index fd46d1055f..3540deb92d 100644 --- a/panda/src/gobj/textureStage.cxx +++ b/panda/src/gobj/textureStage.cxx @@ -346,14 +346,14 @@ operand_valid_for_alpha(TextureStage::CombineOperand co) { */ void TextureStage:: register_with_read_factory() { - BamReader::get_factory()->register_factory(get_class_type(), make_TextureStage); + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); } /** * Factory method to generate a TextureStage object */ -TypedWritable* TextureStage:: -make_TextureStage(const FactoryParams ¶ms) { +TypedWritable *TextureStage:: +make_from_bam(const FactoryParams ¶ms) { DatagramIterator scan; BamReader *manager; diff --git a/panda/src/gobj/textureStage.h b/panda/src/gobj/textureStage.h index 22974874a0..10a9bc5251 100644 --- a/panda/src/gobj/textureStage.h +++ b/panda/src/gobj/textureStage.h @@ -262,7 +262,7 @@ public: virtual void write_datagram(BamWriter *manager, Datagram &me); virtual int complete_pointers(TypedWritable **plist, BamReader *manager); - static TypedWritable *make_TextureStage(const FactoryParams ¶ms); + static TypedWritable *make_from_bam(const FactoryParams ¶ms); protected: void fillin(DatagramIterator& scan, BamReader* manager); diff --git a/panda/src/grutil/meshDrawer.cxx b/panda/src/grutil/meshDrawer.cxx index 24ff840187..aa28c8a87e 100644 --- a/panda/src/grutil/meshDrawer.cxx +++ b/panda/src/grutil/meshDrawer.cxx @@ -416,6 +416,11 @@ void MeshDrawer::geometry(NodePath draw_node) { /** * Stars or continues linked segment. Control position, frame, thickness and * color with parameters. Frame contains u,v,u-size,v-size quadruple. + * Note that for the first two calls to this method, the "frame" parameter is + * ignored; it first takes effect as of the third call. + * Similarly, note that in the second call to this method, the "color" parameter + * is ignored; it only has effect in the first call and calls from the third + * onwards. */ void MeshDrawer:: link_segment(const LVector3 &pos, const LVector4 &frame, diff --git a/panda/src/linmath/lmatrix3_ext_src.h b/panda/src/linmath/lmatrix3_ext_src.h index fa979338ff..1cc4404e85 100644 --- a/panda/src/linmath/lmatrix3_ext_src.h +++ b/panda/src/linmath/lmatrix3_ext_src.h @@ -11,6 +11,8 @@ * @date 2013-09-12 */ +#ifdef HAVE_PYTHON + /** * This class defines the extension methods for LMatrix3, which are called * instead of any C++ methods with the same prototype. @@ -26,3 +28,5 @@ public: }; #include "lmatrix3_ext_src.I" + +#endif diff --git a/panda/src/linmath/lmatrix4_ext_src.h b/panda/src/linmath/lmatrix4_ext_src.h index da7a430175..48b178bea4 100644 --- a/panda/src/linmath/lmatrix4_ext_src.h +++ b/panda/src/linmath/lmatrix4_ext_src.h @@ -11,6 +11,8 @@ * @date 2013-09-12 */ +#ifdef HAVE_PYTHON + /** * This class defines the extension methods for LMatrix4, which are called * instead of any C++ methods with the same prototype. @@ -26,3 +28,5 @@ public: }; #include "lmatrix4_ext_src.I" + +#endif diff --git a/panda/src/linmath/lpoint2_ext_src.h b/panda/src/linmath/lpoint2_ext_src.h index 496e7ec1a8..bfe4bbb16f 100644 --- a/panda/src/linmath/lpoint2_ext_src.h +++ b/panda/src/linmath/lpoint2_ext_src.h @@ -11,6 +11,8 @@ * @date 2013-09-13 */ +#ifdef HAVE_PYTHON + /** * This class defines the extension methods for LPoint2, which are called * instead of any C++ methods with the same prototype. @@ -27,3 +29,5 @@ public: }; #include "lpoint2_ext_src.I" + +#endif diff --git a/panda/src/linmath/lpoint3_ext_src.h b/panda/src/linmath/lpoint3_ext_src.h index 6789810ff5..6da9001739 100644 --- a/panda/src/linmath/lpoint3_ext_src.h +++ b/panda/src/linmath/lpoint3_ext_src.h @@ -11,6 +11,8 @@ * @date 2013-09-13 */ +#ifdef HAVE_PYTHON + /** * This class defines the extension methods for LPoint3, which are called * instead of any C++ methods with the same prototype. @@ -27,3 +29,5 @@ public: }; #include "lpoint3_ext_src.I" + +#endif diff --git a/panda/src/linmath/lpoint4_ext_src.h b/panda/src/linmath/lpoint4_ext_src.h index 2cb8eb6b9f..565eb461a0 100644 --- a/panda/src/linmath/lpoint4_ext_src.h +++ b/panda/src/linmath/lpoint4_ext_src.h @@ -11,6 +11,8 @@ * @date 2013-09-13 */ +#ifdef HAVE_PYTHON + /** * This class defines the extension methods for LPoint4, which are called * instead of any C++ methods with the same prototype. @@ -27,3 +29,5 @@ public: }; #include "lpoint4_ext_src.I" + +#endif diff --git a/panda/src/linmath/lvecBase2_ext_src.I b/panda/src/linmath/lvecBase2_ext_src.I index 5b36e339ec..d435399721 100644 --- a/panda/src/linmath/lvecBase2_ext_src.I +++ b/panda/src/linmath/lvecBase2_ext_src.I @@ -265,8 +265,7 @@ __ifloordiv__(PyObject *self, FLOATTYPE scalar) { _this->_v(0) = std::floor(_this->_v(0) / scalar); _this->_v(1) = std::floor(_this->_v(1) / scalar); #endif - Py_INCREF(self); - return self; + return Py_NewRef(self); } /** @@ -295,8 +294,7 @@ INLINE_LINMATH PyObject *Extension:: __ipow__(PyObject *self, FLOATTYPE exponent) { _this->_v(0) = cpow(_this->_v(0), exponent); _this->_v(1) = cpow(_this->_v(1), exponent); - Py_INCREF(self); - return self; + return Py_NewRef(self); } /** @@ -371,10 +369,8 @@ __getbuffer__(PyObject *self, Py_buffer *view, int flags) const { static const char format[2] = {FLOATTOKEN, 0}; static const Py_ssize_t shape = FLOATNAME(LVecBase2)::num_components; - Py_INCREF(self); - view->buf = (void *)_this->get_data(); - view->obj = self; + view->obj = Py_NewRef(self); view->len = 2 * sizeof(FLOATTYPE); view->readonly = 1; view->itemsize = sizeof(FLOATTYPE); diff --git a/panda/src/linmath/lvecBase2_ext_src.h b/panda/src/linmath/lvecBase2_ext_src.h index 372c805517..83928d72d1 100644 --- a/panda/src/linmath/lvecBase2_ext_src.h +++ b/panda/src/linmath/lvecBase2_ext_src.h @@ -11,6 +11,8 @@ * @date 2013-09-13 */ +#ifdef HAVE_PYTHON + /** * This class defines the extension methods for LVecBase2, which are called * instead of any C++ methods with the same prototype. @@ -39,3 +41,5 @@ public: }; #include "lvecBase2_ext_src.I" + +#endif diff --git a/panda/src/linmath/lvecBase3_ext_src.I b/panda/src/linmath/lvecBase3_ext_src.I index c59add2465..e69e0f00de 100644 --- a/panda/src/linmath/lvecBase3_ext_src.I +++ b/panda/src/linmath/lvecBase3_ext_src.I @@ -274,8 +274,7 @@ __ifloordiv__(PyObject *self, FLOATTYPE scalar) { _this->_v(1) = std::floor(_this->_v(1) / scalar); _this->_v(2) = std::floor(_this->_v(2) / scalar); #endif - Py_INCREF(self); - return self; + return Py_NewRef(self); } /** @@ -306,8 +305,7 @@ __ipow__(PyObject *self, FLOATTYPE exponent) { _this->_v(0) = cpow(_this->_v(0), exponent); _this->_v(1) = cpow(_this->_v(1), exponent); _this->_v(2) = cpow(_this->_v(2), exponent); - Py_INCREF(self); - return self; + return Py_NewRef(self); } /** @@ -384,10 +382,8 @@ __getbuffer__(PyObject *self, Py_buffer *view, int flags) const { static const char format[2] = {FLOATTOKEN, 0}; static const Py_ssize_t shape = FLOATNAME(LVecBase3)::num_components; - Py_INCREF(self); - view->buf = (void *)_this->get_data(); - view->obj = self; + view->obj = Py_NewRef(self); view->len = 3 * sizeof(FLOATTYPE); view->readonly = 1; view->itemsize = sizeof(FLOATTYPE); diff --git a/panda/src/linmath/lvecBase3_ext_src.h b/panda/src/linmath/lvecBase3_ext_src.h index e5e509147e..19e31a526f 100644 --- a/panda/src/linmath/lvecBase3_ext_src.h +++ b/panda/src/linmath/lvecBase3_ext_src.h @@ -11,6 +11,8 @@ * @date 2013-09-13 */ +#ifdef HAVE_PYTHON + /** * This class defines the extension methods for LVecBase3, which are called * instead of any C++ methods with the same prototype. @@ -39,3 +41,5 @@ public: }; #include "lvecBase3_ext_src.I" + +#endif diff --git a/panda/src/linmath/lvecBase4_ext_src.I b/panda/src/linmath/lvecBase4_ext_src.I index d1be8a5316..44c97033d7 100644 --- a/panda/src/linmath/lvecBase4_ext_src.I +++ b/panda/src/linmath/lvecBase4_ext_src.I @@ -287,8 +287,7 @@ __ifloordiv__(PyObject *self, FLOATTYPE scalar) { _this->_v(2) = std::floor(_this->_v(2) / scalar); _this->_v(3) = std::floor(_this->_v(3) / scalar); #endif - Py_INCREF(self); - return self; + return Py_NewRef(self); } /** @@ -321,8 +320,7 @@ __ipow__(PyObject *self, FLOATTYPE exponent) { _this->_v(1) = cpow(_this->_v(1), exponent); _this->_v(2) = cpow(_this->_v(2), exponent); _this->_v(3) = cpow(_this->_v(3), exponent); - Py_INCREF(self); - return self; + return Py_NewRef(self); } /** @@ -402,10 +400,8 @@ __getbuffer__(PyObject *self, Py_buffer *view, int flags) const { static const char format[2] = {FLOATTOKEN, 0}; static const Py_ssize_t shape = FLOATNAME(LVecBase4)::num_components; - Py_INCREF(self); - view->buf = (void *)_this->get_data(); - view->obj = self; + view->obj = Py_NewRef(self); view->len = 4 * sizeof(FLOATTYPE); view->readonly = 1; view->itemsize = sizeof(FLOATTYPE); diff --git a/panda/src/linmath/lvecBase4_ext_src.h b/panda/src/linmath/lvecBase4_ext_src.h index b21e1b7ab7..8466b7e64b 100644 --- a/panda/src/linmath/lvecBase4_ext_src.h +++ b/panda/src/linmath/lvecBase4_ext_src.h @@ -11,6 +11,8 @@ * @date 2013-09-13 */ +#ifdef HAVE_PYTHON + /** * This class defines the extension methods for LVecBase4, which are called * instead of any C++ methods with the same prototype. @@ -39,3 +41,5 @@ public: }; #include "lvecBase4_ext_src.I" + +#endif diff --git a/panda/src/linmath/lvector2_ext_src.h b/panda/src/linmath/lvector2_ext_src.h index 6518c6ebd4..c98f104c05 100644 --- a/panda/src/linmath/lvector2_ext_src.h +++ b/panda/src/linmath/lvector2_ext_src.h @@ -11,6 +11,8 @@ * @date 2013-09-13 */ +#ifdef HAVE_PYTHON + /** * This class defines the extension methods for LVector2, which are called * instead of any C++ methods with the same prototype. @@ -27,3 +29,5 @@ public: }; #include "lvector2_ext_src.I" + +#endif diff --git a/panda/src/linmath/lvector3_ext_src.h b/panda/src/linmath/lvector3_ext_src.h index b6b94c9c74..c88dfcadc6 100644 --- a/panda/src/linmath/lvector3_ext_src.h +++ b/panda/src/linmath/lvector3_ext_src.h @@ -11,6 +11,8 @@ * @date 2013-09-13 */ +#ifdef HAVE_PYTHON + /** * This class defines the extension methods for LVector3, which are called * instead of any C++ methods with the same prototype. @@ -27,3 +29,5 @@ public: }; #include "lvector3_ext_src.I" + +#endif diff --git a/panda/src/linmath/lvector4_ext_src.h b/panda/src/linmath/lvector4_ext_src.h index e398875517..41864edcaf 100644 --- a/panda/src/linmath/lvector4_ext_src.h +++ b/panda/src/linmath/lvector4_ext_src.h @@ -11,6 +11,8 @@ * @date 2013-09-13 */ +#ifdef HAVE_PYTHON + /** * This class defines the extension methods for LVector4, which are called * instead of any C++ methods with the same prototype. @@ -27,3 +29,5 @@ public: }; #include "lvector4_ext_src.I" + +#endif diff --git a/panda/src/nativenet/CMakeLists.txt b/panda/src/nativenet/CMakeLists.txt index d9071630e6..381a1cf66a 100644 --- a/panda/src/nativenet/CMakeLists.txt +++ b/panda/src/nativenet/CMakeLists.txt @@ -37,6 +37,10 @@ add_component_library(p3nativenet SYMBOL BUILDING_PANDA_NATIVENET target_link_libraries(p3nativenet p3pandabase pandaexpress) target_interrogate(p3nativenet ALL) +# These are temporarily built with -module panda3d.net, even though they are +# still part of panda3d.core, see #1466 +set_target_properties(p3nativenet PROPERTIES IGATE_MODULE panda3d.net) + if(NOT BUILD_METALIBS) install(TARGETS p3nativenet EXPORT Core COMPONENT Core diff --git a/panda/src/nativenet/socket_ip.h b/panda/src/nativenet/socket_ip.h index e6fc5eeb24..fdf91fbc9a 100644 --- a/panda/src/nativenet/socket_ip.h +++ b/panda/src/nativenet/socket_ip.h @@ -81,7 +81,11 @@ private: inline bool Socket_IP:: ErrorClose() { if (Active()) { - DO_CLOSE(_socket); + if (DO_CLOSE(_socket) != 0) { +#ifndef _WIN32 + perror("Socket_IP::ErrorClose"); +#endif + } } _socket = BAD_SOCKET; @@ -126,7 +130,11 @@ inline Socket_IP:: inline void Socket_IP:: Close() { if (Active()) { - DO_CLOSE(_socket); + if (DO_CLOSE(_socket) != 0) { +#ifndef _WIN32 + perror("Socket_IP::ErrorClose"); +#endif + } } _socket = BAD_SOCKET; diff --git a/panda/src/nativenet/socket_portable.h b/panda/src/nativenet/socket_portable.h index 4000495fe3..ce29e5841e 100644 --- a/panda/src/nativenet/socket_portable.h +++ b/panda/src/nativenet/socket_portable.h @@ -183,7 +183,7 @@ const int LOCAL_CONNECT_BLOCKING = EINPROGRESS; * LINUX and FreeBSD STUFF ************************************************************************/ -#elif defined(IS_LINUX) || defined(IS_OSX) || defined(IS_FREEBSD) +#elif defined(IS_LINUX) || defined(IS_OSX) || defined(IS_FREEBSD) || defined(__EMSCRIPTEN__) #include #include @@ -246,7 +246,9 @@ inline int DO_RECV_FROM(SOCKET sck, char *data, int len, sockaddr *addr) { inline int init_network() { +#ifndef __EMSCRIPTEN__ signal(SIGPIPE, SIG_IGN); // hmm do i still need this ... +#endif return ALL_OK; } diff --git a/panda/src/net/CMakeLists.txt b/panda/src/net/CMakeLists.txt index d811b806e8..6c0d3e79c3 100644 --- a/panda/src/net/CMakeLists.txt +++ b/panda/src/net/CMakeLists.txt @@ -36,6 +36,10 @@ add_component_library(p3net SYMBOL BUILDING_PANDA_NET target_link_libraries(p3net p3nativenet p3pipeline p3pandabase pandaexpress) target_interrogate(p3net ALL) +# These are temporarily built with -module panda3d.net, even though they are +# still part of panda3d.core, see #1466 +set_target_properties(p3net PROPERTIES IGATE_MODULE panda3d.net) + if(WIN32) target_link_libraries(p3net iphlpapi.lib) endif() diff --git a/panda/src/net/connectionManager.cxx b/panda/src/net/connectionManager.cxx index 1af31a8f78..935f6b802a 100644 --- a/panda/src/net/connectionManager.cxx +++ b/panda/src/net/connectionManager.cxx @@ -544,6 +544,8 @@ scan_interfaces() { #elif defined(__ANDROID__) // TODO: implementation using netlink_socket? +#elif defined(__EMSCRIPTEN__) + #else // _WIN32 struct ifaddrs *ifa; if (getifaddrs(&ifa) != 0) { diff --git a/panda/src/ode/odeBody_ext.I b/panda/src/ode/odeBody_ext.I index 5535b900dd..340ea5e259 100644 --- a/panda/src/ode/odeBody_ext.I +++ b/panda/src/ode/odeBody_ext.I @@ -22,8 +22,7 @@ get_data() const { if (data == nullptr) { data = Py_None; } - Py_INCREF(data); - return data; + return Py_NewRef(data); } /** diff --git a/panda/src/ode/odeBody_ext.cxx b/panda/src/ode/odeBody_ext.cxx index 59361c5fa1..94892a55dd 100644 --- a/panda/src/ode/odeBody_ext.cxx +++ b/panda/src/ode/odeBody_ext.cxx @@ -25,8 +25,7 @@ set_data(PyObject *data) { void *old_data = _this->get_data(); if (data != nullptr && data != Py_None) { - Py_INCREF(data); - _this->set_data((void *)data); + _this->set_data((void *)Py_NewRef(data)); _this->_destroy_callback = &destroy_callback; } else { _this->set_data(nullptr); diff --git a/panda/src/ode/odeSpace_ext.cxx b/panda/src/ode/odeSpace_ext.cxx index 97e841f30b..4c6fb56161 100644 --- a/panda/src/ode/odeSpace_ext.cxx +++ b/panda/src/ode/odeSpace_ext.cxx @@ -82,10 +82,9 @@ collide(PyObject* arg, PyObject* callback) { return -1; } else { - _python_callback = (PyObject*) callback; - Py_XINCREF(_python_callback); + _python_callback = Py_NewRef(callback); dSpaceCollide(_this->get_id(), (void*) arg, &near_callback); - Py_XDECREF(_python_callback); + Py_CLEAR(_python_callback); return 0; } } diff --git a/panda/src/ode/odeUtil_ext.cxx b/panda/src/ode/odeUtil_ext.cxx index c5aabaa812..e3115bfda6 100644 --- a/panda/src/ode/odeUtil_ext.cxx +++ b/panda/src/ode/odeUtil_ext.cxx @@ -31,10 +31,9 @@ collide2(const OdeGeom &geom1, const OdeGeom &geom2, PyObject* arg, PyObject* ca PyErr_Format(PyExc_TypeError, "'%s' object is not callable", callback->ob_type->tp_name); return -1; } else { - _python_callback = (PyObject*) callback; - Py_XINCREF(_python_callback); + _python_callback = Py_XNewRef(callback); dSpaceCollide2(geom1.get_id(), geom2.get_id(), (void*) arg, &near_callback); - Py_XDECREF(_python_callback); + Py_CLEAR(_python_callback); return 0; } } diff --git a/panda/src/parametrics/cubicCurveseg.cxx b/panda/src/parametrics/cubicCurveseg.cxx index dcb5905cfa..fb68f25ed6 100644 --- a/panda/src/parametrics/cubicCurveseg.cxx +++ b/panda/src/parametrics/cubicCurveseg.cxx @@ -516,14 +516,14 @@ compute_seg(int rtype0, PN_stdfloat t0, const LVecBase4 &v0, */ void CubicCurveseg:: register_with_read_factory() { - BamReader::get_factory()->register_factory(get_class_type(), make_CubicCurveseg); + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); } /** * Factory method to generate an object of this type. */ TypedWritable *CubicCurveseg:: -make_CubicCurveseg(const FactoryParams ¶ms) { +make_from_bam(const FactoryParams ¶ms) { CubicCurveseg *me = new CubicCurveseg; DatagramIterator scan; BamReader *manager; diff --git a/panda/src/parametrics/cubicCurveseg.h b/panda/src/parametrics/cubicCurveseg.h index 16202ee732..c24de8d903 100644 --- a/panda/src/parametrics/cubicCurveseg.h +++ b/panda/src/parametrics/cubicCurveseg.h @@ -112,7 +112,7 @@ public: static void register_with_read_factory(); protected: - static TypedWritable *make_CubicCurveseg(const FactoryParams ¶ms); + static TypedWritable *make_from_bam(const FactoryParams ¶ms); virtual void write_datagram(BamWriter *manager, Datagram &me); void fillin(DatagramIterator &scan, BamReader *manager); diff --git a/panda/src/parametrics/hermiteCurve.cxx b/panda/src/parametrics/hermiteCurve.cxx index 7bb2399368..55f3bccd28 100644 --- a/panda/src/parametrics/hermiteCurve.cxx +++ b/panda/src/parametrics/hermiteCurve.cxx @@ -817,14 +817,14 @@ recompute_basis() { */ void HermiteCurve:: register_with_read_factory() { - BamReader::get_factory()->register_factory(get_class_type(), make_HermiteCurve); + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); } /** * Factory method to generate an object of this type. */ TypedWritable *HermiteCurve:: -make_HermiteCurve(const FactoryParams ¶ms) { +make_from_bam(const FactoryParams ¶ms) { HermiteCurve *me = new HermiteCurve; DatagramIterator scan; BamReader *manager; diff --git a/panda/src/parametrics/hermiteCurve.h b/panda/src/parametrics/hermiteCurve.h index eb991090cc..45e601de1b 100644 --- a/panda/src/parametrics/hermiteCurve.h +++ b/panda/src/parametrics/hermiteCurve.h @@ -154,7 +154,7 @@ public: static void register_with_read_factory(); protected: - static TypedWritable *make_HermiteCurve(const FactoryParams ¶ms); + static TypedWritable *make_from_bam(const FactoryParams ¶ms); virtual void write_datagram(BamWriter *manager, Datagram &me); void fillin(DatagramIterator &scan, BamReader *manager); diff --git a/panda/src/parametrics/nurbsCurve.cxx b/panda/src/parametrics/nurbsCurve.cxx index 09e6bf063e..5a60019f2e 100644 --- a/panda/src/parametrics/nurbsCurve.cxx +++ b/panda/src/parametrics/nurbsCurve.cxx @@ -485,14 +485,14 @@ find_cv(PN_stdfloat t) { */ void NurbsCurve:: register_with_read_factory() { - BamReader::get_factory()->register_factory(get_class_type(), make_NurbsCurve); + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); } /** * Factory method to generate an object of this type. */ TypedWritable *NurbsCurve:: -make_NurbsCurve(const FactoryParams ¶ms) { +make_from_bam(const FactoryParams ¶ms) { NurbsCurve *me = new NurbsCurve; DatagramIterator scan; BamReader *manager; diff --git a/panda/src/parametrics/nurbsCurve.h b/panda/src/parametrics/nurbsCurve.h index 06f3177d72..2bd7bd9729 100644 --- a/panda/src/parametrics/nurbsCurve.h +++ b/panda/src/parametrics/nurbsCurve.h @@ -111,7 +111,7 @@ public: static void register_with_read_factory(); protected: - static TypedWritable *make_NurbsCurve(const FactoryParams ¶ms); + static TypedWritable *make_from_bam(const FactoryParams ¶ms); virtual void write_datagram(BamWriter *manager, Datagram &me); void fillin(DatagramIterator &scan, BamReader *manager); diff --git a/panda/src/pgraph/lensNode.cxx b/panda/src/pgraph/lensNode.cxx index 1b428d9e98..ae90f61c4b 100644 --- a/panda/src/pgraph/lensNode.cxx +++ b/panda/src/pgraph/lensNode.cxx @@ -119,7 +119,8 @@ set_lens_active(int index, bool flag) { /** * Returns true if the given point is within the bounds of the lens of the - * LensNode (i.e. if the camera can see the point). + * LensNode (i.e. if the camera can see the point). The point is assumed to + * be relative to the LensNode itself. */ bool LensNode:: is_in_view(int index, const LPoint3 &pos) { diff --git a/panda/src/pgraph/nodePath.h b/panda/src/pgraph/nodePath.h index 6211b18127..b8f82f779f 100644 --- a/panda/src/pgraph/nodePath.h +++ b/panda/src/pgraph/nodePath.h @@ -947,7 +947,7 @@ PUBLISHED: PY_EXTENSION(NodePath find_net_python_tag(PyObject *keys) const); PY_MAKE_PROPERTY(python_tags, get_python_tags); - PY_EXTENSION(int __traverse__(visitproc visit, void *arg)); + //PY_EXTENSION(int __traverse__(visitproc visit, void *arg)); INLINE void list_tags() const; diff --git a/panda/src/pgraph/nodePathCollection_ext.cxx b/panda/src/pgraph/nodePathCollection_ext.cxx index 836e2959e0..a06caf8380 100644 --- a/panda/src/pgraph/nodePathCollection_ext.cxx +++ b/panda/src/pgraph/nodePathCollection_ext.cxx @@ -110,10 +110,9 @@ get_tight_bounds() const { PyObject *max_inst = DTool_CreatePyInstance((void*) max_point, Dtool_LPoint3f, true, false); #endif return Py_BuildValue("NN", min_inst, max_inst); - - } else { - Py_INCREF(Py_None); - return Py_None; + } + else { + return Py_NewRef(Py_None); } } diff --git a/panda/src/pgraph/nodePath_ext.I b/panda/src/pgraph/nodePath_ext.I index 01554fb08d..47c1874aa6 100644 --- a/panda/src/pgraph/nodePath_ext.I +++ b/panda/src/pgraph/nodePath_ext.I @@ -23,8 +23,7 @@ INLINE PyObject *Extension:: get_python_tags() { // An empty NodePath returns None if (_this->is_empty()) { - Py_INCREF(Py_None); - return Py_None; + return Py_NewRef(Py_None); } return invoke_extension(_this->node()).get_python_tags(); } @@ -38,8 +37,7 @@ INLINE PyObject *Extension:: get_tag_keys() const { // An empty NodePath returns None if (_this->is_empty()) { - Py_INCREF(Py_None); - return Py_None; + return Py_NewRef(Py_None); } return invoke_extension(_this->node()).get_tag_keys(); } @@ -52,8 +50,7 @@ INLINE PyObject *Extension:: get_python_tag_keys() const { // An empty NodePath returns None if (_this->is_empty()) { - Py_INCREF(Py_None); - return Py_None; + return Py_NewRef(Py_None); } return invoke_extension(_this->node()).get_python_tag_keys(); } @@ -83,8 +80,7 @@ get_python_tag(PyObject *key) const { // An empty NodePath quietly returns no tags. This makes // get_net_python_tag() easier to implement. if (_this->is_empty()) { - Py_INCREF(Py_None); - return Py_None; + return Py_NewRef(Py_None); } return invoke_extension(_this->node()).get_python_tag(key); } @@ -139,10 +135,10 @@ has_net_python_tag(PyObject *key) const { /** * Called by Python to implement cycle detection. */ -INLINE int Extension:: +/*INLINE int Extension:: __traverse__(visitproc visit, void *arg) { if (_this->is_empty()) { return 0; } return invoke_extension(_this->node()).__traverse__(visit, arg); -} +}*/ diff --git a/panda/src/pgraph/nodePath_ext.cxx b/panda/src/pgraph/nodePath_ext.cxx index 3bcad4b423..23cfb172d2 100644 --- a/panda/src/pgraph/nodePath_ext.cxx +++ b/panda/src/pgraph/nodePath_ext.cxx @@ -59,8 +59,7 @@ __deepcopy__(PyObject *self, PyObject *memo) const { PyObject *dupe = PyDict_GetItem(memo, self); if (dupe != nullptr) { // Already in the memo dictionary. - Py_INCREF(dupe); - return dupe; + return Py_NewRef(dupe); } NodePath *np_dupe; @@ -174,8 +173,7 @@ PyObject *Extension:: get_tags() const { // An empty NodePath returns None if (_this->is_empty()) { - Py_INCREF(Py_None); - return Py_None; + return Py_NewRef(Py_None); } // Just call PandaNode.tags rather than defining a whole new interface. @@ -323,8 +321,7 @@ get_tight_bounds(const NodePath &other) const { return Py_BuildValue("NN", min_inst, max_inst); } else { - Py_INCREF(Py_None); - return Py_None; + return Py_NewRef(Py_None); } } diff --git a/panda/src/pgraph/nodePath_ext.h b/panda/src/pgraph/nodePath_ext.h index e736b4ed1b..b1127f930d 100644 --- a/panda/src/pgraph/nodePath_ext.h +++ b/panda/src/pgraph/nodePath_ext.h @@ -48,7 +48,7 @@ public: NodePath find_net_python_tag(PyObject *key) const; // This is defined to implement cycle detection in Python tags. - INLINE int __traverse__(visitproc visit, void *arg); + //INLINE int __traverse__(visitproc visit, void *arg); void set_shader_input(CPT_InternalName id, PyObject *value, int priority=0); void set_shader_inputs(PyObject *args, PyObject *kwargs); diff --git a/panda/src/pgraph/pandaNode_ext.cxx b/panda/src/pgraph/pandaNode_ext.cxx index d4071ff4c6..cd7ca8b252 100644 --- a/panda/src/pgraph/pandaNode_ext.cxx +++ b/panda/src/pgraph/pandaNode_ext.cxx @@ -50,8 +50,7 @@ __deepcopy__(PyObject *self, PyObject *memo) const { PyObject *dupe = PyDict_GetItem(memo, self); if (dupe != nullptr) { // Already in the memo dictionary. - Py_INCREF(dupe); - return dupe; + return Py_NewRef(dupe); } PT(PandaNode) node_dupe = _this->copy_subgraph(); @@ -94,9 +93,7 @@ get_tag_keys() const { */ PyObject *Extension:: get_python_tags() { - PyObject *dict = do_get_python_tags(); - Py_INCREF(dict); - return dict; + return Py_NewRef(do_get_python_tags()); } /** @@ -121,8 +118,7 @@ set_python_tag(PyObject *key, PyObject *value) { PyObject *Extension:: get_python_tag(PyObject *key) const { if (_this->_python_tag_data == nullptr) { - Py_INCREF(Py_None); - return Py_None; + return Py_NewRef(Py_None); } PyObject *dict = ((PythonTagDataImpl *)_this->_python_tag_data.p())->_dict; @@ -131,8 +127,7 @@ get_python_tag(PyObject *key) const { value = Py_None; } // PyDict_GetItem returns a borrowed reference. - Py_INCREF(value); - return value; + return Py_NewRef(value); } /** diff --git a/panda/src/pgraph/pythonLoaderFileType.cxx b/panda/src/pgraph/pythonLoaderFileType.cxx index ee6e23bbbc..9076a3535e 100644 --- a/panda/src/pgraph/pythonLoaderFileType.cxx +++ b/panda/src/pgraph/pythonLoaderFileType.cxx @@ -44,10 +44,9 @@ PythonLoaderFileType() { PythonLoaderFileType:: PythonLoaderFileType(std::string extension, PyObject *entry_point) : _extension(std::move(extension)), - _entry_point(entry_point) { + _entry_point(Py_NewRef(entry_point)) { init_type(); - Py_INCREF(entry_point); } /** @@ -314,8 +313,7 @@ load_file(const Filename &path, const LoaderOptions &options, record->ref(); PyTuple_SET_ITEM(args, 2, DTool_CreatePyInstanceTyped((void *)record, Dtool_BamCacheRecord, true, false, record->get_type_index())); } else { - PyTuple_SET_ITEM(args, 2, Py_None); - Py_INCREF(Py_None); + PyTuple_SET_ITEM(args, 2, Py_NewRef(Py_None)); } PT(PandaNode) node; diff --git a/panda/src/pgraph/renderState_ext.cxx b/panda/src/pgraph/renderState_ext.cxx index c7a9fe0672..6cfe05965e 100644 --- a/panda/src/pgraph/renderState_ext.cxx +++ b/panda/src/pgraph/renderState_ext.cxx @@ -96,8 +96,7 @@ get_composition_cache() const { PyObject *a, *b; const RenderState *source = _this->_composition_cache.get_key(i); if (source == nullptr) { - a = Py_None; - Py_INCREF(a); + a = Py_NewRef(Py_None); } else { source->ref(); a = DTool_CreatePyInstanceTyped((void *)source, Dtool_RenderState, @@ -105,8 +104,7 @@ get_composition_cache() const { } const RenderState *result = _this->_composition_cache.get_data(i)._result; if (result == nullptr) { - b = Py_None; - Py_INCREF(b); + b = Py_NewRef(Py_None); } else { result->ref(); b = DTool_CreatePyInstanceTyped((void *)result, Dtool_RenderState, @@ -144,8 +142,7 @@ get_invert_composition_cache() const { PyObject *a, *b; const RenderState *source = _this->_invert_composition_cache.get_key(i); if (source == nullptr) { - a = Py_None; - Py_INCREF(a); + a = Py_NewRef(Py_None); } else { source->ref(); a = DTool_CreatePyInstanceTyped((void *)source, Dtool_RenderState, @@ -153,8 +150,7 @@ get_invert_composition_cache() const { } const RenderState *result = _this->_invert_composition_cache.get_data(i)._result; if (result == nullptr) { - b = Py_None; - Py_INCREF(b); + b = Py_NewRef(Py_None); } else { result->ref(); b = DTool_CreatePyInstanceTyped((void *)result, Dtool_RenderState, diff --git a/panda/src/pgraph/transformState.h b/panda/src/pgraph/transformState.h index 964c4fc7d8..ca4727b25f 100644 --- a/panda/src/pgraph/transformState.h +++ b/panda/src/pgraph/transformState.h @@ -134,6 +134,17 @@ PUBLISHED: INLINE bool has_nonzero_shear() const; INLINE bool has_mat() const; +#ifdef CPPPARSER + // Force interrogate to make a copy as a temporary solution for #1625. + LPoint3 get_pos() const; + LVecBase3 get_hpr() const; + LQuaternion get_quat() const; + LQuaternion get_norm_quat() const; + LVecBase3 get_scale() const; + PN_stdfloat get_uniform_scale() const; + LVecBase3 get_shear() const; + LMatrix4 get_mat() const; +#else INLINE const LPoint3 &get_pos() const; INLINE const LVecBase3 &get_hpr() const; INLINE const LQuaternion &get_quat() const; @@ -142,6 +153,7 @@ PUBLISHED: INLINE PN_stdfloat get_uniform_scale() const; INLINE const LVecBase3 &get_shear() const; INLINE const LMatrix4 &get_mat() const; +#endif INLINE const LMatrix4 *get_inverse_mat() const; INLINE LVecBase2 get_pos2d() const; diff --git a/panda/src/pgraph/transformState_ext.cxx b/panda/src/pgraph/transformState_ext.cxx index 10b629ddff..cc9ea28033 100644 --- a/panda/src/pgraph/transformState_ext.cxx +++ b/panda/src/pgraph/transformState_ext.cxx @@ -42,8 +42,7 @@ get_composition_cache() const { const TransformState *source = _this->_composition_cache.get_key(si); if (source == nullptr) { - a = Py_None; - Py_INCREF(a); + a = Py_NewRef(Py_None); } else { source->ref(); a = DTool_CreatePyInstanceTyped((void *)source, Dtool_TransformState, @@ -51,8 +50,7 @@ get_composition_cache() const { } const TransformState *result = _this->_composition_cache.get_data(si)._result; if (result == nullptr) { - b = Py_None; - Py_INCREF(b); + b = Py_NewRef(Py_None); } else { result->ref(); b = DTool_CreatePyInstanceTyped((void *)result, Dtool_TransformState, @@ -97,8 +95,7 @@ get_invert_composition_cache() const { const TransformState *source = _this->_invert_composition_cache.get_key(si); if (source == nullptr) { - a = Py_None; - Py_INCREF(a); + a = Py_NewRef(Py_None); } else { source->ref(); a = DTool_CreatePyInstanceTyped((void *)source, Dtool_TransformState, @@ -106,8 +103,7 @@ get_invert_composition_cache() const { } const TransformState *result = _this->_invert_composition_cache.get_data(si)._result; if (result == nullptr) { - b = Py_None; - Py_INCREF(b); + b = Py_NewRef(Py_None); } else { result->ref(); b = DTool_CreatePyInstanceTyped((void *)result, Dtool_TransformState, diff --git a/panda/src/pgui/pgEntry.I b/panda/src/pgui/pgEntry.I index e758a7ff8c..61262d87aa 100644 --- a/panda/src/pgui/pgEntry.I +++ b/panda/src/pgui/pgEntry.I @@ -134,7 +134,6 @@ get_cursor_position() const { /** * Returns the node position x of the cursor */ - INLINE PN_stdfloat PGEntry:: get_cursor_X() const { LightReMutexHolder holder(_lock); @@ -144,14 +143,12 @@ get_cursor_X() const { /** * Returns the node position y of the cursor */ - INLINE PN_stdfloat PGEntry:: get_cursor_Y() const { LightReMutexHolder holder(_lock); - return _cursor_def.get_y(); + return _cursor_def.get_z(); } - /** * Sets the maximum number of characters that may be typed into the entry. * This is a limit on the number of characters, as opposed to the width of the diff --git a/panda/src/pgui/pgEntry.h b/panda/src/pgui/pgEntry.h index 11ac7f2e22..3497220c72 100644 --- a/panda/src/pgui/pgEntry.h +++ b/panda/src/pgui/pgEntry.h @@ -80,6 +80,7 @@ PUBLISHED: INLINE void set_cursor_position(int position); INLINE int get_cursor_position() const; + MAKE_PROPERTY(cursor_position, get_cursor_position, set_cursor_position); INLINE PN_stdfloat get_cursor_X() const; INLINE PN_stdfloat get_cursor_Y() const; @@ -90,33 +91,45 @@ PUBLISHED: INLINE PN_stdfloat get_max_width() const; INLINE void set_num_lines(int num_lines); INLINE int get_num_lines() const; + MAKE_PROPERTY(max_chars, get_max_chars, set_max_chars); + MAKE_PROPERTY(max_width, get_max_width, set_max_width); + MAKE_PROPERTY(num_lines, get_num_lines, set_num_lines); INLINE void set_blink_rate(PN_stdfloat blink_rate); INLINE PN_stdfloat get_blink_rate() const; + MAKE_PROPERTY(blink_rate, get_blink_rate, set_blink_rate); INLINE NodePath get_cursor_def(); INLINE void clear_cursor_def(); + MAKE_PROPERTY(cursor_def, get_cursor_def); INLINE void set_cursor_keys_active(bool flag); INLINE bool get_cursor_keys_active() const; + MAKE_PROPERTY(cursor_keys_active, get_cursor_keys_active, set_cursor_keys_active); INLINE void set_obscure_mode(bool flag); INLINE bool get_obscure_mode() const; + MAKE_PROPERTY(obscure_mode, get_obscure_mode, set_obscure_mode); INLINE void set_overflow_mode(bool flag); INLINE bool get_overflow_mode() const; + MAKE_PROPERTY(overflow_mode, get_overflow_mode, set_overflow_mode); INLINE void set_candidate_active(const std::string &candidate_active); INLINE const std::string &get_candidate_active() const; + MAKE_PROPERTY(candidate_active, get_candidate_active, set_candidate_active); INLINE void set_candidate_inactive(const std::string &candidate_inactive); INLINE const std::string &get_candidate_inactive() const; + MAKE_PROPERTY(candidate_inactive, get_candidate_inactive, set_candidate_inactive); void set_text_def(int state, TextNode *node); TextNode *get_text_def(int state) const; virtual void set_active(bool active) final; virtual void set_focus(bool focus); + MAKE_PROPERTY(active, get_active, set_active); + MAKE_PROPERTY(focus, get_focus, set_focus); INLINE static std::string get_accept_prefix(); INLINE static std::string get_accept_failed_prefix(); @@ -132,6 +145,12 @@ PUBLISHED: INLINE std::string get_erase_event() const; INLINE std::string get_cursormove_event() const; + MAKE_PROPERTY(accept_prefix, get_accept_prefix); + MAKE_PROPERTY(accept_failed_prefix, get_accept_failed_prefix); + MAKE_PROPERTY(overflow_prefix, get_overflow_prefix); + MAKE_PROPERTY(type_prefix, get_type_prefix); + MAKE_PROPERTY(erase_prefix, get_erase_prefix); + MAKE_PROPERTY(cursormove_prefix, get_cursormove_prefix); INLINE bool set_wtext(const std::wstring &wtext); INLINE std::wstring get_plain_wtext() const; diff --git a/panda/src/pgui/pgFrameStyle.h b/panda/src/pgui/pgFrameStyle.h index b6a2270019..3b62a079bd 100644 --- a/panda/src/pgui/pgFrameStyle.h +++ b/panda/src/pgui/pgFrameStyle.h @@ -47,27 +47,33 @@ PUBLISHED: INLINE void set_type(Type type); INLINE Type get_type() const; + MAKE_PROPERTY(type, get_type, set_type); INLINE void set_color(PN_stdfloat r, PN_stdfloat g, PN_stdfloat b, PN_stdfloat a); INLINE void set_color(const LColor &color); INLINE LColor get_color() const; + MAKE_PROPERTY(color, get_color, set_color); INLINE void set_texture(Texture *texture); INLINE bool has_texture() const; INLINE Texture *get_texture() const; INLINE void clear_texture(); + MAKE_PROPERTY2(texture, has_texture, get_texture, set_texture, clear_texture); INLINE void set_width(PN_stdfloat x, PN_stdfloat y); INLINE void set_width(const LVecBase2 &width); INLINE const LVecBase2 &get_width() const; + MAKE_PROPERTY(width, get_width, set_width); INLINE void set_uv_width(PN_stdfloat u, PN_stdfloat v); INLINE void set_uv_width(const LVecBase2 &uv_width); INLINE const LVecBase2 &get_uv_width() const; + MAKE_PROPERTY(uv_width, get_uv_width, set_uv_width); INLINE void set_visible_scale(PN_stdfloat x, PN_stdfloat y); INLINE void set_visible_scale(const LVecBase2 &visible_scale); INLINE const LVecBase2 &get_visible_scale() const; + MAKE_PROPERTY(visible_scale, get_visible_scale, set_visible_scale); LVecBase4 get_internal_frame(const LVecBase4 &frame) const; diff --git a/panda/src/pgui/pgItem.h b/panda/src/pgui/pgItem.h index a27c08d46c..048c01f532 100644 --- a/panda/src/pgui/pgItem.h +++ b/panda/src/pgui/pgItem.h @@ -132,6 +132,7 @@ PUBLISHED: bool has_state_def(int state) const; INLINE NodePath &get_state_def(int state); MAKE_SEQ(get_state_defs, get_num_state_defs, get_state_def); + MAKE_SEQ_PROPERTY(state_defs, get_num_state_defs, get_state_def); NodePath instance_to_state_def(int state, const NodePath &path); PGFrameStyle get_frame_style(int state); @@ -171,6 +172,17 @@ PUBLISHED: INLINE std::string get_release_event(const ButtonHandle &button) const; INLINE std::string get_keystroke_event() const; + MAKE_PROPERTY(enter_prefix, get_enter_prefix); + MAKE_PROPERTY(exit_prefix, get_exit_prefix); + MAKE_PROPERTY(within_prefix, get_within_prefix); + MAKE_PROPERTY(without_prefix, get_without_prefix); + MAKE_PROPERTY(focus_in_prefix, get_focus_in_prefix); + MAKE_PROPERTY(focus_out_prefix, get_focus_out_prefix); + MAKE_PROPERTY(press_prefix, get_press_prefix); + MAKE_PROPERTY(repeat_prefix, get_repeat_prefix); + MAKE_PROPERTY(release_prefix, get_release_prefix); + MAKE_PROPERTY(keystroke_prefix, get_keystroke_prefix); + INLINE LMatrix4 get_frame_inv_xform() const; #ifdef HAVE_AUDIO diff --git a/panda/src/pgui/pgScrollFrame.h b/panda/src/pgui/pgScrollFrame.h index 5a7c19386d..c759700ae2 100644 --- a/panda/src/pgui/pgScrollFrame.h +++ b/panda/src/pgui/pgScrollFrame.h @@ -56,20 +56,31 @@ PUBLISHED: INLINE const LVecBase4 &get_virtual_frame() const; INLINE bool has_virtual_frame() const; INLINE void clear_virtual_frame(); + MAKE_PROPERTY2(virtual_frame, + has_virtual_frame, get_virtual_frame, + set_virtual_frame, clear_virtual_frame); INLINE void set_manage_pieces(bool manage_pieces); INLINE bool get_manage_pieces() const; + MAKE_PROPERTY(manage_pieces, get_manage_pieces, set_manage_pieces); INLINE void set_auto_hide(bool auto_hide); INLINE bool get_auto_hide() const; + MAKE_PROPERTY(auto_hide, get_auto_hide, set_auto_hide); INLINE void set_horizontal_slider(PGSliderBar *horizontal_slider); INLINE void clear_horizontal_slider(); INLINE PGSliderBar *get_horizontal_slider() const; + MAKE_PROPERTY2(horizontal_slider, + get_horizontal_slider, get_horizontal_slider, + set_horizontal_slider, clear_horizontal_slider); INLINE void set_vertical_slider(PGSliderBar *vertical_slider); INLINE void clear_vertical_slider(); INLINE PGSliderBar *get_vertical_slider() const; + MAKE_PROPERTY2(vertical_slider, + get_vertical_slider, get_vertical_slider, + set_vertical_slider, clear_vertical_slider); void remanage(); INLINE void recompute(); diff --git a/panda/src/pgui/pgSliderBar.h b/panda/src/pgui/pgSliderBar.h index 3b387d9cc8..106426148e 100644 --- a/panda/src/pgui/pgSliderBar.h +++ b/panda/src/pgui/pgSliderBar.h @@ -56,6 +56,7 @@ PUBLISHED: INLINE void set_axis(const LVector3 &axis); INLINE const LVector3 &get_axis() const; + MAKE_PROPERTY(axis, get_axis, set_axis); INLINE void set_range(PN_stdfloat min_value, PN_stdfloat max_value); INLINE PN_stdfloat get_min_value() const; @@ -63,40 +64,58 @@ PUBLISHED: INLINE void set_scroll_size(PN_stdfloat scroll_size); INLINE PN_stdfloat get_scroll_size() const; + MAKE_PROPERTY(scroll_size, get_scroll_size, set_scroll_size); INLINE void set_page_size(PN_stdfloat page_size); INLINE PN_stdfloat get_page_size() const; + MAKE_PROPERTY(page_size, get_page_size, set_page_size); INLINE void set_value(PN_stdfloat value); INLINE PN_stdfloat get_value() const; + MAKE_PROPERTY(value, get_value, set_value); INLINE void set_ratio(PN_stdfloat ratio); INLINE PN_stdfloat get_ratio() const; + MAKE_PROPERTY(ratio, get_ratio, set_ratio); INLINE bool is_button_down() const; + MAKE_PROPERTY(button_down, is_button_down); INLINE void set_resize_thumb(bool resize_thumb); INLINE bool get_resize_thumb() const; + MAKE_PROPERTY(resize_thumb, get_resize_thumb, set_resize_thumb); INLINE void set_manage_pieces(bool manage_pieces); INLINE bool get_manage_pieces() const; + MAKE_PROPERTY(manage_pieces, get_manage_pieces, set_manage_pieces); INLINE void set_thumb_button(PGButton *thumb_button); INLINE void clear_thumb_button(); INLINE PGButton *get_thumb_button() const; + MAKE_PROPERTY2(thumb_button, + get_thumb_button, get_thumb_button, + set_thumb_button, clear_thumb_button); INLINE void set_left_button(PGButton *left_button); INLINE void clear_left_button(); INLINE PGButton *get_left_button() const; + MAKE_PROPERTY2(left_button, + get_left_button, get_left_button, + set_left_button, clear_left_button); INLINE void set_right_button(PGButton *right_button); INLINE void clear_right_button(); INLINE PGButton *get_right_button() const; + MAKE_PROPERTY2(right_button, + get_right_button, get_right_button, + set_right_button, clear_right_button); INLINE static std::string get_adjust_prefix(); INLINE std::string get_adjust_event() const; + MAKE_PROPERTY(adjust_prefix, get_adjust_prefix); virtual void set_active(bool active) final; + MAKE_PROPERTY(active, get_active, set_active); void remanage(); void recompute(); diff --git a/panda/src/pgui/pgTop.h b/panda/src/pgui/pgTop.h index f5e6bac554..d69ab4decc 100644 --- a/panda/src/pgui/pgTop.h +++ b/panda/src/pgui/pgTop.h @@ -51,9 +51,12 @@ PUBLISHED: void set_mouse_watcher(MouseWatcher *watcher); INLINE MouseWatcher *get_mouse_watcher() const; INLINE MouseWatcherGroup *get_group() const; + MAKE_PROPERTY(mouse_watcher, get_mouse_watcher, set_mouse_watcher); + MAKE_PROPERTY(group, get_group); INLINE void set_start_sort(int start_sort); INLINE int get_start_sort() const; + MAKE_PROPERTY(start_sort, get_start_sort, set_start_sort); public: // These methods duplicate the functionality of MouseWatcherGroup. diff --git a/panda/src/pgui/pgVirtualFrame.h b/panda/src/pgui/pgVirtualFrame.h index d284b08ab0..7480a6fc92 100644 --- a/panda/src/pgui/pgVirtualFrame.h +++ b/panda/src/pgui/pgVirtualFrame.h @@ -59,12 +59,16 @@ PUBLISHED: INLINE const LVecBase4 &get_clip_frame() const; INLINE bool has_clip_frame() const; void clear_clip_frame(); + MAKE_PROPERTY2(clip_frame, has_clip_frame, get_clip_frame, set_clip_frame, clear_clip_frame); INLINE void set_canvas_transform(const TransformState *transform); INLINE const TransformState *get_canvas_transform() const; + MAKE_PROPERTY(canvas_transform, get_canvas_transform, set_canvas_transform); INLINE PandaNode *get_canvas_node() const; INLINE PandaNode *get_canvas_parent() const; + MAKE_PROPERTY(canvas_node, get_canvas_node); + MAKE_PROPERTY(canvas_parent, get_canvas_parent); protected: virtual void clip_frame_changed(); diff --git a/panda/src/pgui/pgWaitBar.h b/panda/src/pgui/pgWaitBar.h index 9f8415d28c..34480adba7 100644 --- a/panda/src/pgui/pgWaitBar.h +++ b/panda/src/pgui/pgWaitBar.h @@ -40,14 +40,17 @@ PUBLISHED: INLINE void set_range(PN_stdfloat range); INLINE PN_stdfloat get_range() const; + MAKE_PROPERTY(range, get_range, set_range); INLINE void set_value(PN_stdfloat value); INLINE PN_stdfloat get_value() const; + MAKE_PROPERTY(value, get_value, set_value); INLINE PN_stdfloat get_percent() const; INLINE void set_bar_style(const PGFrameStyle &style); INLINE PGFrameStyle get_bar_style() const; + MAKE_PROPERTY(bar_style, get_bar_style, set_bar_style); private: void update(); diff --git a/panda/src/pipeline/CMakeLists.txt b/panda/src/pipeline/CMakeLists.txt index aa7852623b..75e83c9614 100644 --- a/panda/src/pipeline/CMakeLists.txt +++ b/panda/src/pipeline/CMakeLists.txt @@ -115,11 +115,9 @@ endif() set(P3PIPELINE_IGATEEXT pmutex_ext.h - pmutex_ext.I pythonThread.cxx pythonThread.h reMutex_ext.h - reMutex_ext.I ) composite_sources(p3pipeline P3PIPELINE_SOURCES) diff --git a/panda/src/pipeline/pythonThread.cxx b/panda/src/pipeline/pythonThread.cxx index 07c86ba413..84770c258e 100644 --- a/panda/src/pipeline/pythonThread.cxx +++ b/panda/src/pipeline/pythonThread.cxx @@ -27,8 +27,7 @@ PythonThread(PyObject *function, PyObject *args, const std::string &name, const std::string &sync_name) : Thread(name, sync_name) { - _function = function; - Py_INCREF(_function); + _function = Py_NewRef(function); _args = nullptr; _result = nullptr; @@ -78,14 +77,13 @@ PyObject *PythonThread:: join() { Thread::join(); - if (_result == nullptr) { + PyObject *result = _result; + if (result == nullptr) { // No result; return None. - Py_INCREF(Py_None); - return Py_None; + result = Py_None; } - Py_INCREF(_result); - return _result; + return Py_NewRef(result); } /** @@ -147,10 +145,7 @@ call_python_func(PyObject *function, PyObject *args) { PyObject *exc, *val, *tb; PyErr_Fetch(&exc, &val, &tb); - Py_XINCREF(exc); - Py_XINCREF(val); - Py_XINCREF(tb); - PyErr_Restore(exc, val, tb); + PyErr_Restore(Py_XNewRef(exc), Py_XNewRef(val), Py_XNewRef(tb)); PyErr_Print(); PyErr_Restore(exc, val, tb); @@ -206,10 +201,7 @@ call_python_func(PyObject *function, PyObject *args) { // Temporarily restore the exception state so we can print a callback // on-the-spot. - Py_XINCREF(exc); - Py_XINCREF(val); - Py_XINCREF(tb); - PyErr_Restore(exc, val, tb); + PyErr_Restore(Py_XNewRef(exc), Py_XNewRef(val), Py_XNewRef(tb)); PyErr_Print(); PyThreadState_Swap(orig_thread_state); @@ -252,10 +244,7 @@ call_python_func(PyObject *function, PyObject *args) { thread_cat.error() << "Exception occurred within " << *current_thread << "\n"; - Py_XINCREF(exc); - Py_XINCREF(val); - Py_XINCREF(tb); - PyErr_Restore(exc, val, tb); + PyErr_Restore(Py_XNewRef(exc), Py_XNewRef(val), Py_XNewRef(tb)); PyErr_Print(); } else { thread_cat.info() diff --git a/panda/src/pipeline/thread.cxx b/panda/src/pipeline/thread.cxx index 15b31d96db..179fdba442 100644 --- a/panda/src/pipeline/thread.cxx +++ b/panda/src/pipeline/thread.cxx @@ -92,16 +92,19 @@ Thread:: */ PT(Thread) Thread:: bind_thread(const std::string &name, const std::string &sync_name) { - Thread *current_thread = get_current_thread(); - if (current_thread != get_external_thread()) { + PT(Thread) thread = new ExternalThread(name, sync_name); +#ifndef HAVE_THREADS + Thread *current_thread = get_main_thread(); +#else + Thread *current_thread = ThreadImpl::bind_thread(thread); +#endif + if (current_thread != nullptr && + current_thread != thread.p()) { // This thread already has an associated thread. nassertr(current_thread->get_name() == name && current_thread->get_sync_name() == sync_name, current_thread); - return current_thread; + thread = current_thread; } - - PT(Thread) thread = new ExternalThread(name, sync_name); - ThreadImpl::bind_thread(thread); return thread; } diff --git a/panda/src/pipeline/threadDummyImpl.I b/panda/src/pipeline/threadDummyImpl.I index 85ab2263a4..2065f0ad28 100644 --- a/panda/src/pipeline/threadDummyImpl.I +++ b/panda/src/pipeline/threadDummyImpl.I @@ -63,13 +63,15 @@ prepare_for_exit() { } /** - * Associates the indicated Thread object with the currently-executing thread. + * Associates the indicated Thread object with the currently-executing thread, + * unless a thread is already bound, in which case it is returned. * You should not call this directly; use Thread::bind_thread() instead. */ -INLINE void ThreadDummyImpl:: +INLINE Thread *ThreadDummyImpl:: bind_thread(Thread *thread) { // This method shouldn't be called in the non-threaded case. - nassertv(false); + nassertr(false, nullptr); + return nullptr; } /** diff --git a/panda/src/pipeline/threadDummyImpl.h b/panda/src/pipeline/threadDummyImpl.h index 3e1b7a8ab7..82a21e05a9 100644 --- a/panda/src/pipeline/threadDummyImpl.h +++ b/panda/src/pipeline/threadDummyImpl.h @@ -55,7 +55,7 @@ public: INLINE static void prepare_for_exit(); static Thread *get_current_thread(); - INLINE static void bind_thread(Thread *thread); + INLINE static Thread *bind_thread(Thread *thread); INLINE static bool is_threading_supported(); INLINE static bool is_true_threads(); INLINE static bool is_simple_threads(); diff --git a/panda/src/pipeline/threadPosixImpl.cxx b/panda/src/pipeline/threadPosixImpl.cxx index 773061398e..9266ded933 100644 --- a/panda/src/pipeline/threadPosixImpl.cxx +++ b/panda/src/pipeline/threadPosixImpl.cxx @@ -193,18 +193,23 @@ get_unique_id() const { } /** - * Associates the indicated Thread object with the currently-executing thread. + * Associates the indicated Thread object with the currently-executing thread, + * unless a thread is already bound, in which case it is returned. * You should not call this directly; use Thread::bind_thread() instead. */ -void ThreadPosixImpl:: +Thread *ThreadPosixImpl:: bind_thread(Thread *thread) { - if (_current_thread == nullptr && thread == Thread::get_main_thread()) { + if (_current_thread != nullptr) { + return _current_thread; + } + if (thread == Thread::get_main_thread()) { _main_thread_known.test_and_set(std::memory_order_relaxed); } _current_thread = thread; #ifdef ANDROID bind_java_thread(); #endif + return thread; } #ifdef ANDROID diff --git a/panda/src/pipeline/threadPosixImpl.h b/panda/src/pipeline/threadPosixImpl.h index 65d7f951ca..34422506d7 100644 --- a/panda/src/pipeline/threadPosixImpl.h +++ b/panda/src/pipeline/threadPosixImpl.h @@ -49,7 +49,7 @@ public: INLINE static void prepare_for_exit(); INLINE static Thread *get_current_thread(); - static void bind_thread(Thread *thread); + static Thread *bind_thread(Thread *thread); INLINE static bool is_threading_supported(); INLINE static bool is_true_threads(); INLINE static bool is_simple_threads(); diff --git a/panda/src/pipeline/threadSimpleImpl.I b/panda/src/pipeline/threadSimpleImpl.I index d712892883..04cda3a99b 100644 --- a/panda/src/pipeline/threadSimpleImpl.I +++ b/panda/src/pipeline/threadSimpleImpl.I @@ -36,11 +36,13 @@ is_same_system_thread() const { } /** - * Associates the indicated Thread object with the currently-executing thread. + * Associates the indicated Thread object with the currently-executing thread, + * unless a thread is already bound, in which case it is returned. * You should not call this directly; use Thread::bind_thread() instead. */ -INLINE void ThreadSimpleImpl:: +INLINE Thread *ThreadSimpleImpl:: bind_thread(Thread *) { + return get_current_thread(); } /** diff --git a/panda/src/pipeline/threadSimpleImpl.h b/panda/src/pipeline/threadSimpleImpl.h index 5e747ea917..819ad1a71f 100644 --- a/panda/src/pipeline/threadSimpleImpl.h +++ b/panda/src/pipeline/threadSimpleImpl.h @@ -61,7 +61,7 @@ public: INLINE static Thread *get_current_thread(); INLINE bool is_same_system_thread() const; - INLINE static void bind_thread(Thread *thread); + INLINE static Thread *bind_thread(Thread *thread); INLINE static bool is_threading_supported(); static bool is_true_threads(); INLINE static bool is_simple_threads(); diff --git a/panda/src/pipeline/threadWin32Impl.cxx b/panda/src/pipeline/threadWin32Impl.cxx index 22bf5cab79..c8653a4f5c 100644 --- a/panda/src/pipeline/threadWin32Impl.cxx +++ b/panda/src/pipeline/threadWin32Impl.cxx @@ -184,15 +184,20 @@ get_current_thread() { } /** - * Associates the indicated Thread object with the currently-executing thread. + * Associates the indicated Thread object with the currently-executing thread, + * unless a thread is already bound, in which case it is returned. * You should not call this directly; use Thread::bind_thread() instead. */ -void ThreadWin32Impl:: +Thread *ThreadWin32Impl:: bind_thread(Thread *thread) { - if (_current_thread == nullptr && thread == Thread::get_main_thread()) { + if (_current_thread != nullptr) { + return _current_thread; + } + if (thread == Thread::get_main_thread()) { _main_thread_known.test_and_set(std::memory_order_relaxed); } _current_thread = thread; + return thread; } /** diff --git a/panda/src/pipeline/threadWin32Impl.h b/panda/src/pipeline/threadWin32Impl.h index 3c9cfd275e..1d62320789 100644 --- a/panda/src/pipeline/threadWin32Impl.h +++ b/panda/src/pipeline/threadWin32Impl.h @@ -44,7 +44,7 @@ public: INLINE static void prepare_for_exit(); static Thread *get_current_thread(); - static void bind_thread(Thread *thread); + static Thread *bind_thread(Thread *thread); INLINE static bool is_threading_supported(); INLINE static bool is_true_threads(); INLINE static bool is_simple_threads(); diff --git a/panda/src/pnmimage/CMakeLists.txt b/panda/src/pnmimage/CMakeLists.txt index 9991f25f70..6dff4f2e0f 100644 --- a/panda/src/pnmimage/CMakeLists.txt +++ b/panda/src/pnmimage/CMakeLists.txt @@ -9,6 +9,7 @@ set(P3PNMIMAGE_HEADERS pnmPainter.h pnmPainter.I pnmReader.I pnmReader.h pnmWriter.I pnmWriter.h pnmimage_base.h + pnmReaderEmscripten.h ppmcmap.h ) @@ -24,6 +25,7 @@ set(P3PNMIMAGE_SOURCES pnmFileTypeRegistry.cxx pnmImage.cxx pnmImageHeader.cxx pnmPainter.cxx pnmReader.cxx pnmWriter.cxx pnmimage_base.cxx + pnmReaderEmscripten.cxx ppmcmap.cxx ) diff --git a/panda/src/pnmimage/p3pnmimage_composite2.cxx b/panda/src/pnmimage/p3pnmimage_composite2.cxx index a005eec42e..dbce891768 100644 --- a/panda/src/pnmimage/p3pnmimage_composite2.cxx +++ b/panda/src/pnmimage/p3pnmimage_composite2.cxx @@ -2,6 +2,7 @@ #include "pnmImageHeader.cxx" #include "pnmPainter.cxx" #include "pnmReader.cxx" +#include "pnmReaderEmscripten.cxx" #include "pnmWriter.cxx" #include "pnmFileTypeRegistry.cxx" #include "pnmimage_base.cxx" diff --git a/panda/src/pnmimage/pfmFile_ext.cxx b/panda/src/pnmimage/pfmFile_ext.cxx index baf1caf8e9..7aab96a2dc 100644 --- a/panda/src/pnmimage/pfmFile_ext.cxx +++ b/panda/src/pnmimage/pfmFile_ext.cxx @@ -63,8 +63,7 @@ get_points() const { default: Py_DECREF(list); - Py_INCREF(Py_None); - return Py_None; + return Py_NewRef(Py_None); } return list; @@ -92,10 +91,7 @@ __getbuffer__(PyObject *self, Py_buffer *view, int flags) const { int channels = _this->get_num_channels(); int num_pixels = _this->get_x_size() * _this->get_y_size(); - if (self != nullptr) { - Py_INCREF(self); - } - view->obj = self; + view->obj = Py_XNewRef(self); view->buf = (void *) &(table[0]); view->len = 4 * table.size(); view->readonly = 1; diff --git a/panda/src/pnmimage/pnmFileType.h b/panda/src/pnmimage/pnmFileType.h index ddf44c9992..93e409390f 100644 --- a/panda/src/pnmimage/pnmFileType.h +++ b/panda/src/pnmimage/pnmFileType.h @@ -58,12 +58,8 @@ public: // The TypedWritable interface follows. public: - static void register_with_read_factory(); virtual void write_datagram(BamWriter *writer, Datagram &datagram); -protected: - static TypedWritable *make_PNMFileType(const FactoryParams ¶ms); - public: static TypeHandle get_class_type() { return _type_handle; diff --git a/panda/src/pnmimage/pnmImageHeader.cxx b/panda/src/pnmimage/pnmImageHeader.cxx index c7a6129bd7..0eae5285cc 100644 --- a/panda/src/pnmimage/pnmImageHeader.cxx +++ b/panda/src/pnmimage/pnmImageHeader.cxx @@ -20,10 +20,36 @@ #include "virtualFileSystem.h" #include "zStream.h" +#ifdef __EMSCRIPTEN__ +#include "subfileInfo.h" +#include "pnmReaderEmscripten.h" + +#include +#endif + using std::istream; using std::ostream; using std::string; +#ifdef __EMSCRIPTEN__ +/** + * Returns true and sets width/height if the given path is in the emscripten + * preload image cache. + */ +EM_JS(int, query_preload, (const char *path, int *width, int *height), { + var cache = Module["preloadedImages"]; + if (cache) { + var canvas = cache[UTF8ToString(path)]; + if (canvas) { + setValue(width, canvas["width"], "i32"); + setValue(height, canvas["height"], "i32"); + return 1; + } + } + return 0; +}) +#endif + /** * Opens up the image file and tries to read its header information to * determine its size, number of channels, etc. If successful, updates the @@ -84,11 +110,11 @@ make_reader(const Filename &filename, PNMFileType *type, << "Reading image from " << filename << "\n"; } bool owns_file = false; - istream *file = nullptr; + istream *in = nullptr; if (filename == "-") { owns_file = false; - file = &std::cin; + in = &std::cin; if (pnmimage_cat.is_debug()) { pnmimage_cat.debug() @@ -97,10 +123,35 @@ make_reader(const Filename &filename, PNMFileType *type, } else { VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr(); owns_file = true; - file = vfs->open_read_file(filename, true); + PT(VirtualFile) file = vfs->get_file(filename, false); + if (file != nullptr) { +#ifdef __EMSCRIPTEN__ + // Is this a real file, and do we have that in the Emscripten cache? + SubfileInfo info; + if (file->get_system_info(info) && info.get_start() == 0) { + Filename fn = info.get_filename(); + if (!fn.make_canonical()) { + fn.make_absolute(); + } + int width, height; + if (query_preload(fn.c_str(), &width, &height)) { + if (pnmimage_cat.is_debug()) { + pnmimage_cat.debug() + << "(found in emscripten cache)\n"; + } + return new PNMReaderEmscripten(type, fn, width, height); + } + } +#endif + in = vfs->open_read_file(filename, true); + if (in != nullptr && in->fail()) { + file->close_read_file(in); + in = nullptr; + } + } } - if (file == nullptr) { + if (in == nullptr) { if (pnmimage_cat.is_debug()) { pnmimage_cat.debug() << "Unable to open file.\n"; @@ -108,7 +159,7 @@ make_reader(const Filename &filename, PNMFileType *type, return nullptr; } - return make_reader(file, owns_file, filename, string(), type, + return make_reader(in, owns_file, filename, string(), type, report_unknown_type); } diff --git a/panda/src/pnmimage/pnmReaderEmscripten.cxx b/panda/src/pnmimage/pnmReaderEmscripten.cxx new file mode 100644 index 0000000000..cd0bdc9f9f --- /dev/null +++ b/panda/src/pnmimage/pnmReaderEmscripten.cxx @@ -0,0 +1,73 @@ +/** + * PANDA 3D SOFTWARE + * Copyright (c) Carnegie Mellon University. All rights reserved. + * + * All use of this software is subject to the terms of the revised BSD + * license. You should have received a copy of this license along + * with this source code in a file named "LICENSE." + * + * @file pnmReaderEmscripten.cxx + * @author rdb + * @date 2021-02-05 + */ + +#include "pnmReaderEmscripten.h" + +#ifdef __EMSCRIPTEN__ + +#include "config_pnmimage.h" + +#include + +/** + * + */ +PNMReaderEmscripten:: +PNMReaderEmscripten(PNMFileType *type, Filename fullpath, int width, int height) : + PNMReader(type, nullptr, false), + _fullpath(std::move(fullpath)) +{ + _x_size = width; + _y_size = height; + _num_channels = 4; + _maxval = 255; +} + +/** + * Reads in an entire image all at once, storing it in the pre-allocated + * _x_size * _y_size array and alpha pointers. (If the image type has no + * alpha channel, alpha is ignored.) Returns the number of rows correctly + * read. + * + * Derived classes need not override this if they instead provide + * supports_read_row() and read_row(), below. + */ +int PNMReaderEmscripten:: +read_data(xel *array, xelval *alpha) { + if (!is_valid()) { + return 0; + } + + int width, height; + unsigned char *data = (unsigned char *)emscripten_get_preloaded_image_data(_fullpath.c_str(), &width, &height); + nassertr(data != nullptr, 0); + nassertr(width == _x_size, 0); + if (height > _x_size) { + height = _x_size; + } + + size_t total_size = (size_t)width * (size_t)height; + for (int i = 0; i < total_size; ++i) { + array[i].r = data[i * 4 + 0]; + array[i].g = data[i * 4 + 1]; + array[i].b = data[i * 4 + 2]; + alpha[i] = data[i * 4 + 3]; + } + + free(data); + + return height; +} + + +#endif // __EMSCRIPTEN__ diff --git a/panda/src/pnmimage/pnmReaderEmscripten.h b/panda/src/pnmimage/pnmReaderEmscripten.h new file mode 100644 index 0000000000..774ed3dce5 --- /dev/null +++ b/panda/src/pnmimage/pnmReaderEmscripten.h @@ -0,0 +1,40 @@ +/** + * PANDA 3D SOFTWARE + * Copyright (c) Carnegie Mellon University. All rights reserved. + * + * All use of this software is subject to the terms of the revised BSD + * license. You should have received a copy of this license along + * with this source code in a file named "LICENSE." + * + * @file pnmReaderEmscripten.h + * @author rdb + * @date 2021-02-05 + */ + +#ifndef PNMREADEREMSCRIPTEN_H +#define PNMREADEREMSCRIPTEN_H + +#include "pandabase.h" + +#ifdef __EMSCRIPTEN__ + +#include "pnmFileType.h" +#include "pnmReader.h" +#include "pnmWriter.h" + +/** + * For reading files using the emscripten pre-load system. + */ +class PNMReaderEmscripten final : public PNMReader { +public: + PNMReaderEmscripten(PNMFileType *type, Filename fullpath, int width, int height); + + virtual int read_data(xel *array, xelval *alpha); + +private: + Filename _fullpath; +}; + +#endif // __EMSCRIPTEN__ + +#endif diff --git a/panda/src/pnmimagetypes/bmp.h b/panda/src/pnmimagetypes/bmp.h index 2c5a08006f..bff1668ffd 100644 --- a/panda/src/pnmimagetypes/bmp.h +++ b/panda/src/pnmimagetypes/bmp.h @@ -48,7 +48,6 @@ BMPlenfileheader(int classv) case C_WINV4: case C_WINV5: return 14; - return 14; default: pm_error(er_internal, "BMPlenfileheader"); return 0; diff --git a/panda/src/pnmimagetypes/config_pnmimagetypes.h b/panda/src/pnmimagetypes/config_pnmimagetypes.h index 75fb491143..91fb6ac8f7 100644 --- a/panda/src/pnmimagetypes/config_pnmimagetypes.h +++ b/panda/src/pnmimagetypes/config_pnmimagetypes.h @@ -74,6 +74,6 @@ EXPCL_PANDA_PNMIMAGETYPES std::istream &operator >> (std::istream &in, IMGHeader extern ConfigVariableEnum img_header_type; extern ConfigVariableInt img_size; -extern EXPCL_PANDA_PNMIMAGETYPES void init_libpnmimagetypes(); +extern "C" EXPCL_PANDA_PNMIMAGETYPES void init_libpnmimagetypes(); #endif diff --git a/panda/src/pnmimagetypes/pnmFileTypeBMP.cxx b/panda/src/pnmimagetypes/pnmFileTypeBMP.cxx index 28efd2feb2..13baa23d1f 100644 --- a/panda/src/pnmimagetypes/pnmFileTypeBMP.cxx +++ b/panda/src/pnmimagetypes/pnmFileTypeBMP.cxx @@ -119,7 +119,7 @@ make_writer(std::ostream *file, bool owns_file) { void PNMFileTypeBMP:: register_with_read_factory() { BamReader::get_factory()-> - register_factory(get_class_type(), make_PNMFileTypeBMP); + register_factory(get_class_type(), make_from_bam); } /** @@ -131,7 +131,7 @@ register_with_read_factory() { * we just pull the object from the registry. */ TypedWritable *PNMFileTypeBMP:: -make_PNMFileTypeBMP(const FactoryParams ¶ms) { +make_from_bam(const FactoryParams ¶ms) { return PNMFileTypeRegistry::get_global_ptr()->get_type_by_handle(get_class_type()); } diff --git a/panda/src/pnmimagetypes/pnmFileTypeBMP.h b/panda/src/pnmimagetypes/pnmFileTypeBMP.h index 87c4e8f629..8de5666208 100644 --- a/panda/src/pnmimagetypes/pnmFileTypeBMP.h +++ b/panda/src/pnmimagetypes/pnmFileTypeBMP.h @@ -78,7 +78,7 @@ public: static void register_with_read_factory(); protected: - static TypedWritable *make_PNMFileTypeBMP(const FactoryParams ¶ms); + static TypedWritable *make_from_bam(const FactoryParams ¶ms); public: static TypeHandle get_class_type() { diff --git a/panda/src/pnmimagetypes/pnmFileTypeEXR.cxx b/panda/src/pnmimagetypes/pnmFileTypeEXR.cxx index 6165241004..7541d41a8f 100644 --- a/panda/src/pnmimagetypes/pnmFileTypeEXR.cxx +++ b/panda/src/pnmimagetypes/pnmFileTypeEXR.cxx @@ -482,7 +482,7 @@ write_data(xel *array, xelval *alpha) { void PNMFileTypeEXR:: register_with_read_factory() { BamReader::get_factory()-> - register_factory(get_class_type(), make_PNMFileTypeEXR); + register_factory(get_class_type(), make_from_bam); } /** @@ -494,7 +494,7 @@ register_with_read_factory() { * we just pull the object from the registry. */ TypedWritable *PNMFileTypeEXR:: -make_PNMFileTypeEXR(const FactoryParams ¶ms) { +make_from_bam(const FactoryParams ¶ms) { return PNMFileTypeRegistry::get_global_ptr()->get_type_by_handle(get_class_type()); } diff --git a/panda/src/pnmimagetypes/pnmFileTypeEXR.h b/panda/src/pnmimagetypes/pnmFileTypeEXR.h index 23e211ee98..a1a095aeff 100644 --- a/panda/src/pnmimagetypes/pnmFileTypeEXR.h +++ b/panda/src/pnmimagetypes/pnmFileTypeEXR.h @@ -88,7 +88,7 @@ public: static void register_with_read_factory(); protected: - static TypedWritable *make_PNMFileTypeEXR(const FactoryParams ¶ms); + static TypedWritable *make_from_bam(const FactoryParams ¶ms); public: static TypeHandle get_class_type() { diff --git a/panda/src/pnmimagetypes/pnmFileTypeIMG.cxx b/panda/src/pnmimagetypes/pnmFileTypeIMG.cxx index 4f9390e53f..a46e82cc85 100644 --- a/panda/src/pnmimagetypes/pnmFileTypeIMG.cxx +++ b/panda/src/pnmimagetypes/pnmFileTypeIMG.cxx @@ -315,7 +315,7 @@ write_row(xel *row_data, xelval *) { void PNMFileTypeIMG:: register_with_read_factory() { BamReader::get_factory()-> - register_factory(get_class_type(), make_PNMFileTypeIMG); + register_factory(get_class_type(), make_from_bam); } /** @@ -327,7 +327,7 @@ register_with_read_factory() { * we just pull the object from the registry. */ TypedWritable *PNMFileTypeIMG:: -make_PNMFileTypeIMG(const FactoryParams ¶ms) { +make_from_bam(const FactoryParams ¶ms) { return PNMFileTypeRegistry::get_global_ptr()->get_type_by_handle(get_class_type()); } diff --git a/panda/src/pnmimagetypes/pnmFileTypeIMG.h b/panda/src/pnmimagetypes/pnmFileTypeIMG.h index e75aaeb972..8fb465af3c 100644 --- a/panda/src/pnmimagetypes/pnmFileTypeIMG.h +++ b/panda/src/pnmimagetypes/pnmFileTypeIMG.h @@ -63,7 +63,7 @@ public: static void register_with_read_factory(); protected: - static TypedWritable *make_PNMFileTypeIMG(const FactoryParams ¶ms); + static TypedWritable *make_from_bam(const FactoryParams ¶ms); public: static TypeHandle get_class_type() { diff --git a/panda/src/pnmimagetypes/pnmFileTypeJPG.cxx b/panda/src/pnmimagetypes/pnmFileTypeJPG.cxx index 19d9cff18f..abc857e69e 100644 --- a/panda/src/pnmimagetypes/pnmFileTypeJPG.cxx +++ b/panda/src/pnmimagetypes/pnmFileTypeJPG.cxx @@ -120,7 +120,7 @@ make_writer(std::ostream *file, bool owns_file) { void PNMFileTypeJPG:: register_with_read_factory() { BamReader::get_factory()-> - register_factory(get_class_type(), make_PNMFileTypeJPG); + register_factory(get_class_type(), make_from_bam); } /** @@ -132,7 +132,7 @@ register_with_read_factory() { * we just pull the object from the registry. */ TypedWritable *PNMFileTypeJPG:: -make_PNMFileTypeJPG(const FactoryParams ¶ms) { +make_from_bam(const FactoryParams ¶ms) { return PNMFileTypeRegistry::get_global_ptr()->get_type_by_handle(get_class_type()); } diff --git a/panda/src/pnmimagetypes/pnmFileTypeJPG.h b/panda/src/pnmimagetypes/pnmFileTypeJPG.h index d577e52bf6..f1e4268d8f 100644 --- a/panda/src/pnmimagetypes/pnmFileTypeJPG.h +++ b/panda/src/pnmimagetypes/pnmFileTypeJPG.h @@ -105,7 +105,7 @@ public: static void register_with_read_factory(); protected: - static TypedWritable *make_PNMFileTypeJPG(const FactoryParams ¶ms); + static TypedWritable *make_from_bam(const FactoryParams ¶ms); public: static TypeHandle get_class_type() { diff --git a/panda/src/pnmimagetypes/pnmFileTypePNG.cxx b/panda/src/pnmimagetypes/pnmFileTypePNG.cxx index afb7dc1de2..dd4f4eaeb6 100644 --- a/panda/src/pnmimagetypes/pnmFileTypePNG.cxx +++ b/panda/src/pnmimagetypes/pnmFileTypePNG.cxx @@ -141,7 +141,7 @@ make_writer(ostream *file, bool owns_file) { void PNMFileTypePNG:: register_with_read_factory() { BamReader::get_factory()-> - register_factory(get_class_type(), make_PNMFileTypePNG); + register_factory(get_class_type(), make_from_bam); } /** @@ -153,7 +153,7 @@ register_with_read_factory() { * we just pull the object from the registry. */ TypedWritable *PNMFileTypePNG:: -make_PNMFileTypePNG(const FactoryParams ¶ms) { +make_from_bam(const FactoryParams ¶ms) { return PNMFileTypeRegistry::get_global_ptr()->get_type_by_handle(get_class_type()); } diff --git a/panda/src/pnmimagetypes/pnmFileTypePNG.h b/panda/src/pnmimagetypes/pnmFileTypePNG.h index 8ed2b817e4..e423e26a21 100644 --- a/panda/src/pnmimagetypes/pnmFileTypePNG.h +++ b/panda/src/pnmimagetypes/pnmFileTypePNG.h @@ -101,7 +101,7 @@ public: static void register_with_read_factory(); protected: - static TypedWritable *make_PNMFileTypePNG(const FactoryParams ¶ms); + static TypedWritable *make_from_bam(const FactoryParams ¶ms); public: static TypeHandle get_class_type() { diff --git a/panda/src/pnmimagetypes/pnmFileTypePNM.cxx b/panda/src/pnmimagetypes/pnmFileTypePNM.cxx index 6995c70ca6..c61e0faf75 100644 --- a/panda/src/pnmimagetypes/pnmFileTypePNM.cxx +++ b/panda/src/pnmimagetypes/pnmFileTypePNM.cxx @@ -1219,7 +1219,7 @@ write_row(xel *row_data, xelval *) { void PNMFileTypePNM:: register_with_read_factory() { BamReader::get_factory()-> - register_factory(get_class_type(), make_PNMFileTypePNM); + register_factory(get_class_type(), make_from_bam); } /** @@ -1231,7 +1231,7 @@ register_with_read_factory() { * we just pull the object from the registry. */ TypedWritable *PNMFileTypePNM:: -make_PNMFileTypePNM(const FactoryParams ¶ms) { +make_from_bam(const FactoryParams ¶ms) { return PNMFileTypeRegistry::get_global_ptr()->get_type_by_handle(get_class_type()); } diff --git a/panda/src/pnmimagetypes/pnmFileTypePNM.h b/panda/src/pnmimagetypes/pnmFileTypePNM.h index 811661b1fa..ab42fe1ee0 100644 --- a/panda/src/pnmimagetypes/pnmFileTypePNM.h +++ b/panda/src/pnmimagetypes/pnmFileTypePNM.h @@ -72,7 +72,7 @@ public: static void register_with_read_factory(); protected: - static TypedWritable *make_PNMFileTypePNM(const FactoryParams ¶ms); + static TypedWritable *make_from_bam(const FactoryParams ¶ms); public: static TypeHandle get_class_type() { diff --git a/panda/src/pnmimagetypes/pnmFileTypePfm.cxx b/panda/src/pnmimagetypes/pnmFileTypePfm.cxx index 1303cc9c6c..1933515785 100644 --- a/panda/src/pnmimagetypes/pnmFileTypePfm.cxx +++ b/panda/src/pnmimagetypes/pnmFileTypePfm.cxx @@ -316,7 +316,7 @@ write_pfm(const PfmFile &pfm) { void PNMFileTypePfm:: register_with_read_factory() { BamReader::get_factory()-> - register_factory(get_class_type(), make_PNMFileTypePfm); + register_factory(get_class_type(), make_from_bam); } /** @@ -328,6 +328,6 @@ register_with_read_factory() { * we just pull the object from the registry. */ TypedWritable *PNMFileTypePfm:: -make_PNMFileTypePfm(const FactoryParams ¶ms) { +make_from_bam(const FactoryParams ¶ms) { return PNMFileTypeRegistry::get_global_ptr()->get_type_by_handle(get_class_type()); } diff --git a/panda/src/pnmimagetypes/pnmFileTypePfm.h b/panda/src/pnmimagetypes/pnmFileTypePfm.h index c97ec46eb6..096c1fc4da 100644 --- a/panda/src/pnmimagetypes/pnmFileTypePfm.h +++ b/panda/src/pnmimagetypes/pnmFileTypePfm.h @@ -69,7 +69,7 @@ public: static void register_with_read_factory(); protected: - static TypedWritable *make_PNMFileTypePfm(const FactoryParams ¶ms); + static TypedWritable *make_from_bam(const FactoryParams ¶ms); public: static TypeHandle get_class_type() { diff --git a/panda/src/pnmimagetypes/pnmFileTypeSGI.cxx b/panda/src/pnmimagetypes/pnmFileTypeSGI.cxx index 9a3e9c0f7e..eba81e8ccd 100644 --- a/panda/src/pnmimagetypes/pnmFileTypeSGI.cxx +++ b/panda/src/pnmimagetypes/pnmFileTypeSGI.cxx @@ -123,7 +123,7 @@ make_writer(std::ostream *file, bool owns_file) { void PNMFileTypeSGI:: register_with_read_factory() { BamReader::get_factory()-> - register_factory(get_class_type(), make_PNMFileTypeSGI); + register_factory(get_class_type(), make_from_bam); } /** @@ -135,7 +135,7 @@ register_with_read_factory() { * we just pull the object from the registry. */ TypedWritable *PNMFileTypeSGI:: -make_PNMFileTypeSGI(const FactoryParams ¶ms) { +make_from_bam(const FactoryParams ¶ms) { return PNMFileTypeRegistry::get_global_ptr()->get_type_by_handle(get_class_type()); } diff --git a/panda/src/pnmimagetypes/pnmFileTypeSGI.h b/panda/src/pnmimagetypes/pnmFileTypeSGI.h index dbced028e2..0152354251 100644 --- a/panda/src/pnmimagetypes/pnmFileTypeSGI.h +++ b/panda/src/pnmimagetypes/pnmFileTypeSGI.h @@ -111,7 +111,7 @@ public: static void register_with_read_factory(); protected: - static TypedWritable *make_PNMFileTypeSGI(const FactoryParams ¶ms); + static TypedWritable *make_from_bam(const FactoryParams ¶ms); public: static TypeHandle get_class_type() { diff --git a/panda/src/pnmimagetypes/pnmFileTypeSoftImage.cxx b/panda/src/pnmimagetypes/pnmFileTypeSoftImage.cxx index 9003dc8ad6..bb7fba20e8 100644 --- a/panda/src/pnmimagetypes/pnmFileTypeSoftImage.cxx +++ b/panda/src/pnmimagetypes/pnmFileTypeSoftImage.cxx @@ -725,7 +725,7 @@ write_row(xel *row_data, xelval *alpha_data) { void PNMFileTypeSoftImage:: register_with_read_factory() { BamReader::get_factory()-> - register_factory(get_class_type(), make_PNMFileTypeSoftImage); + register_factory(get_class_type(), make_from_bam); } /** @@ -737,7 +737,7 @@ register_with_read_factory() { * we just pull the object from the registry. */ TypedWritable *PNMFileTypeSoftImage:: -make_PNMFileTypeSoftImage(const FactoryParams ¶ms) { +make_from_bam(const FactoryParams ¶ms) { return PNMFileTypeRegistry::get_global_ptr()->get_type_by_handle(get_class_type()); } diff --git a/panda/src/pnmimagetypes/pnmFileTypeSoftImage.h b/panda/src/pnmimagetypes/pnmFileTypeSoftImage.h index 55457bbfca..2597e77713 100644 --- a/panda/src/pnmimagetypes/pnmFileTypeSoftImage.h +++ b/panda/src/pnmimagetypes/pnmFileTypeSoftImage.h @@ -70,7 +70,7 @@ public: static void register_with_read_factory(); protected: - static TypedWritable *make_PNMFileTypeSoftImage(const FactoryParams ¶ms); + static TypedWritable *make_from_bam(const FactoryParams ¶ms); public: static TypeHandle get_class_type() { diff --git a/panda/src/pnmimagetypes/pnmFileTypeStbImage.cxx b/panda/src/pnmimagetypes/pnmFileTypeStbImage.cxx index 29f1d70315..612e8da641 100644 --- a/panda/src/pnmimagetypes/pnmFileTypeStbImage.cxx +++ b/panda/src/pnmimagetypes/pnmFileTypeStbImage.cxx @@ -587,7 +587,7 @@ read_data(xel *array, xelval *alpha) { void PNMFileTypeStbImage:: register_with_read_factory() { BamReader::get_factory()-> - register_factory(get_class_type(), make_PNMFileTypeStbImage); + register_factory(get_class_type(), make_from_bam); } /** @@ -599,7 +599,7 @@ register_with_read_factory() { * we just pull the object from the registry. */ TypedWritable *PNMFileTypeStbImage:: -make_PNMFileTypeStbImage(const FactoryParams ¶ms) { +make_from_bam(const FactoryParams ¶ms) { return PNMFileTypeRegistry::get_global_ptr()->get_type_by_handle(get_class_type()); } diff --git a/panda/src/pnmimagetypes/pnmFileTypeStbImage.h b/panda/src/pnmimagetypes/pnmFileTypeStbImage.h index 260d6dc61c..ecfd73ebaf 100644 --- a/panda/src/pnmimagetypes/pnmFileTypeStbImage.h +++ b/panda/src/pnmimagetypes/pnmFileTypeStbImage.h @@ -46,7 +46,7 @@ public: static void register_with_read_factory(); protected: - static TypedWritable *make_PNMFileTypeStbImage(const FactoryParams ¶ms); + static TypedWritable *make_from_bam(const FactoryParams ¶ms); public: static TypeHandle get_class_type() { diff --git a/panda/src/pnmimagetypes/pnmFileTypeTGA.cxx b/panda/src/pnmimagetypes/pnmFileTypeTGA.cxx index c1322d4087..c881c1f085 100644 --- a/panda/src/pnmimagetypes/pnmFileTypeTGA.cxx +++ b/panda/src/pnmimagetypes/pnmFileTypeTGA.cxx @@ -557,7 +557,7 @@ write_data(xel *array, xelval *) { void PNMFileTypeTGA:: register_with_read_factory() { BamReader::get_factory()-> - register_factory(get_class_type(), make_PNMFileTypeTGA); + register_factory(get_class_type(), make_from_bam); } /** @@ -569,7 +569,7 @@ register_with_read_factory() { * we just pull the object from the registry. */ TypedWritable *PNMFileTypeTGA:: -make_PNMFileTypeTGA(const FactoryParams ¶ms) { +make_from_bam(const FactoryParams ¶ms) { return PNMFileTypeRegistry::get_global_ptr()->get_type_by_handle(get_class_type()); } diff --git a/panda/src/pnmimagetypes/pnmFileTypeTGA.h b/panda/src/pnmimagetypes/pnmFileTypeTGA.h index d4ce1426cd..4181a2a356 100644 --- a/panda/src/pnmimagetypes/pnmFileTypeTGA.h +++ b/panda/src/pnmimagetypes/pnmFileTypeTGA.h @@ -100,7 +100,7 @@ public: static void register_with_read_factory(); protected: - static TypedWritable *make_PNMFileTypeTGA(const FactoryParams ¶ms); + static TypedWritable *make_from_bam(const FactoryParams ¶ms); public: static TypeHandle get_class_type() { diff --git a/panda/src/pnmimagetypes/pnmFileTypeTIFF.cxx b/panda/src/pnmimagetypes/pnmFileTypeTIFF.cxx index 170d13af46..74216fa48f 100644 --- a/panda/src/pnmimagetypes/pnmFileTypeTIFF.cxx +++ b/panda/src/pnmimagetypes/pnmFileTypeTIFF.cxx @@ -1249,7 +1249,7 @@ tiff_error(const char *module, const char *format, va_list ap) { void PNMFileTypeTIFF:: register_with_read_factory() { BamReader::get_factory()-> - register_factory(get_class_type(), make_PNMFileTypeTIFF); + register_factory(get_class_type(), make_from_bam); } /** @@ -1261,7 +1261,7 @@ register_with_read_factory() { * we just pull the object from the registry. */ TypedWritable *PNMFileTypeTIFF:: -make_PNMFileTypeTIFF(const FactoryParams ¶ms) { +make_from_bam(const FactoryParams ¶ms) { return PNMFileTypeRegistry::get_global_ptr()->get_type_by_handle(get_class_type()); } diff --git a/panda/src/pnmimagetypes/pnmFileTypeTIFF.h b/panda/src/pnmimagetypes/pnmFileTypeTIFF.h index 36148a082e..7de62bf0f3 100644 --- a/panda/src/pnmimagetypes/pnmFileTypeTIFF.h +++ b/panda/src/pnmimagetypes/pnmFileTypeTIFF.h @@ -97,7 +97,7 @@ public: static void register_with_read_factory(); protected: - static TypedWritable *make_PNMFileTypeTIFF(const FactoryParams ¶ms); + static TypedWritable *make_from_bam(const FactoryParams ¶ms); public: static TypeHandle get_class_type() { diff --git a/panda/src/pstatclient/pStatClient_ext.cxx b/panda/src/pstatclient/pStatClient_ext.cxx index f78305f521..0724470cfb 100644 --- a/panda/src/pstatclient/pStatClient_ext.cxx +++ b/panda/src/pstatclient/pStatClient_ext.cxx @@ -107,7 +107,7 @@ make_python_frame_collector(PyFrameObject *frame, PyCodeObject *code) { } meth_name = PyUnicode_FromFormat("_%s%S", cls_name, meth_name); } else { - Py_INCREF(meth_name); + meth_name = Py_NewRef(meth_name); } if (!find_method(cls, meth_name, code)) { // Not a matching method object, it's something else. Forget it. diff --git a/panda/src/putil/CMakeLists.txt b/panda/src/putil/CMakeLists.txt index 1332402586..ecc14b9843 100644 --- a/panda/src/putil/CMakeLists.txt +++ b/panda/src/putil/CMakeLists.txt @@ -129,20 +129,15 @@ set(P3PUTIL_IGATEEXT bamWriter_ext.h bitArray_ext.cxx bitArray_ext.h - bitArray_ext.I bitMask_ext.h - bitMask_ext.I callbackObject_ext.h doubleBitMask_ext.h - doubleBitMask_ext.I paramPyObject.cxx paramPyObject.h - paramPyObject.I pythonCallbackObject.cxx pythonCallbackObject.h sparseArray_ext.cxx sparseArray_ext.h - sparseArray_ext.I typedWritable_ext.cxx typedWritable_ext.h ) diff --git a/panda/src/putil/bamReaderParam.I b/panda/src/putil/bamReaderParam.I index 9913332f2c..5be221d39f 100644 --- a/panda/src/putil/bamReaderParam.I +++ b/panda/src/putil/bamReaderParam.I @@ -14,7 +14,7 @@ /** * */ -INLINE const DatagramIterator &BamReaderParam:: +INLINE DatagramIterator &BamReaderParam:: get_iterator() { return _iterator; } @@ -32,7 +32,7 @@ get_manager() { * */ INLINE BamReaderParam:: -BamReaderParam(const DatagramIterator &dgi, BamReader *manager) : +BamReaderParam(DatagramIterator &dgi, BamReader *manager) : _iterator(dgi), _manager(manager) { diff --git a/panda/src/putil/bamReaderParam.h b/panda/src/putil/bamReaderParam.h index a935de3dbe..7f928d7601 100644 --- a/panda/src/putil/bamReaderParam.h +++ b/panda/src/putil/bamReaderParam.h @@ -27,15 +27,15 @@ class DatagramIterator; */ class EXPCL_PANDA_PUTIL BamReaderParam : public FactoryParam { public: - INLINE const DatagramIterator &get_iterator(); + INLINE DatagramIterator &get_iterator(); INLINE BamReader *get_manager(); private: - const DatagramIterator &_iterator; + DatagramIterator &_iterator; BamReader *_manager; public: - INLINE BamReaderParam(const DatagramIterator &dgi, BamReader *manager); + INLINE BamReaderParam(DatagramIterator &dgi, BamReader *manager); INLINE ~BamReaderParam(); public: diff --git a/panda/src/putil/bamReader_ext.cxx b/panda/src/putil/bamReader_ext.cxx index fce150f92c..308028cea3 100644 --- a/panda/src/putil/bamReader_ext.cxx +++ b/panda/src/putil/bamReader_ext.cxx @@ -135,8 +135,7 @@ read_object() { } if (ptr == nullptr) { - Py_INCREF(Py_None); - return Py_None; + return Py_NewRef(Py_None); } if (ref_ptr != nullptr) { @@ -165,15 +164,13 @@ get_file_version() const { */ void Extension:: register_factory(TypeHandle handle, PyObject *func) { - nassertv(func != nullptr); - if (!PyCallable_Check(func)) { Dtool_Raise_TypeError("second argument to register_factory must be callable"); return; } - Py_INCREF(func); - BamReader::get_factory()->register_factory(handle, &factory_callback, (void *)func); + void *user_data = (void *)Py_NewRef(func); + BamReader::get_factory()->register_factory(handle, &factory_callback, user_data); } #endif diff --git a/panda/src/putil/paramPyObject.I b/panda/src/putil/paramPyObject.I index 4099812974..3515226711 100644 --- a/panda/src/putil/paramPyObject.I +++ b/panda/src/putil/paramPyObject.I @@ -17,8 +17,7 @@ * Increments the reference count. Assumes the GIL is held. */ INLINE ParamPyObject:: -ParamPyObject(PyObject *value) : _value(value) { - Py_INCREF(value); +ParamPyObject(PyObject *value) : _value(Py_NewRef(value)) { } /** @@ -26,6 +25,5 @@ ParamPyObject(PyObject *value) : _value(value) { */ INLINE PyObject *ParamPyObject:: get_value() const { - Py_INCREF(_value); - return _value; + return Py_NewRef(_value); } diff --git a/panda/src/putil/paramPyObject.cxx b/panda/src/putil/paramPyObject.cxx index ac2e54aff9..59124bc055 100644 --- a/panda/src/putil/paramPyObject.cxx +++ b/panda/src/putil/paramPyObject.cxx @@ -13,6 +13,8 @@ #include "paramPyObject.h" +#ifdef HAVE_PYTHON + TypeHandle ParamPyObject::_type_handle; /** @@ -40,3 +42,5 @@ output(std::ostream &out) const { out << "<" << Py_TYPE(_value)->tp_name << " object at " << (void *)_value << ">"; } + +#endif diff --git a/panda/src/putil/pythonCallbackObject.cxx b/panda/src/putil/pythonCallbackObject.cxx index 666200fd3b..454c9bdaf5 100644 --- a/panda/src/putil/pythonCallbackObject.cxx +++ b/panda/src/putil/pythonCallbackObject.cxx @@ -37,8 +37,7 @@ extern struct Dtool_PyTypedObject Dtool_PythonCallbackObject; */ PythonCallbackObject:: PythonCallbackObject(PyObject *function) { - _function = Py_None; - Py_INCREF(_function); + _function = Py_NewRef(Py_None); set_function(function); @@ -69,8 +68,7 @@ PythonCallbackObject:: void PythonCallbackObject:: set_function(PyObject *function) { Py_DECREF(_function); - _function = function; - Py_INCREF(_function); + _function = Py_NewRef(function); if (_function != Py_None && !PyCallable_Check(_function)) { nassert_raise("Invalid function passed to PythonCallbackObject"); } @@ -81,8 +79,7 @@ set_function(PyObject *function) { */ PyObject *PythonCallbackObject:: get_function() { - Py_INCREF(_function); - return _function; + return Py_NewRef(_function); } /** @@ -90,7 +87,7 @@ get_function() { */ PyObject *PythonCallbackObject:: __reduce__() const { - return Py_BuildValue("O(O)", (PyObject *)&Dtool_PythonCallbackObject, _function); + return Py_BuildValue("O(O)", (PyObject *)&Dtool_PythonCallbackObject._PyType, _function); } /** diff --git a/panda/src/putil/typedWritable.C.template b/panda/src/putil/typedWritable.C.template deleted file mode 100644 index 53cc650bba..0000000000 --- a/panda/src/putil/typedWritable.C.template +++ /dev/null @@ -1,86 +0,0 @@ -//FOR C Files -#include -#include -#include -#include - - -//////////////////////////////////////////////////////////////////// -// Function: Generic::write_datagram -// Access: Public -// Description: Function to write the important information in -// the particular object to a Datagram -//////////////////////////////////////////////////////////////////// -void Generic:: -write_datagram(BamWriter *manager, Datagram &me) -{ - GenericParent::write_datagram(manager, me); -} - -//////////////////////////////////////////////////////////////////// -// Function: Generic::fillin -// Access: Protected -// Description: Function that reads out of the datagram (or asks -// manager to read) all of the data that is needed to -// re-create this object and stores it in the appropiate -// place -//////////////////////////////////////////////////////////////////// -void Generic:: -fillin(DatagramIterator& scan, BamReader* manager) -{ - GenericParent::fillin(scan, manager); -} - -//////////////////////////////////////////////////////////////////// -// Function: Generic::complete_pointers -// Access: Public -// Description: Takes in a vector of pointes to TypedWriteable -// objects that correspond to all the requests for -// pointers that this object made to BamReader. -//////////////////////////////////////////////////////////////////// -int Generic:: -complete_pointers(vector_typedWriteable &p_list, BamReader *manager) -{ - int start = GenericParent::complete_pointers(p_list, manager); -} - -//////////////////////////////////////////////////////////////////// -// Function: Generic::finalize -// Access: Public -// Description: Method to ensure that any necessary clean up tasks -// that have to be performed by this object are performed -//////////////////////////////////////////////////////////////////// -void Generic:: -finalize() -{ -} - -//////////////////////////////////////////////////////////////////// -// Function: Generic::make_Generic -// Access: Protected -// Description: Factory method to generate a Generic object -//////////////////////////////////////////////////////////////////// -TypedWriteable* Generic:: -make_Generic(const FactoryParams ¶ms) -{ - Generic *me = new Generic; - BamReader *manager; - Datagram packet; - - parse_params(params, manager, packet); - DatagramIterator scan(packet); - - me->fillin(scan, manager); - return me; -} - -//////////////////////////////////////////////////////////////////// -// Function: Generic::register_with_factory -// Access: Public, Static -// Description: Factory method to generate a Generic object -//////////////////////////////////////////////////////////////////// -void Generic:: -register_with_read_factory() -{ - BamReader::get_factory()->register_factory(get_class_type(), make_Generic); -} diff --git a/panda/src/putil/typedWritable.h.template b/panda/src/putil/typedWritable.h.template deleted file mode 100644 index 9d6ed2200d..0000000000 --- a/panda/src/putil/typedWritable.h.template +++ /dev/null @@ -1,20 +0,0 @@ -//FOR H File of files derived from TypedWriteable, WriteableConfigurable -//or TypedWriteableReferenceCount -class BamReader; - -//FOR H FILES - -public: - static void register_with_read_factory(); - virtual void write_datagram(BamWriter* manager, Datagram &me); - virtual int complete_pointers(vector_typedWriteable &p_list, - BamReader *manager); - virtual void finalize(); - - static TypedWriteable *make_Generic(const FactoryParams ¶ms); - -protected: - void fillin(DatagramIterator& scan, BamReader* manager); - -private: - int _num_GenericPointers; diff --git a/panda/src/putil/typedWritable_ext.cxx b/panda/src/putil/typedWritable_ext.cxx index 501a07a600..699794b368 100644 --- a/panda/src/putil/typedWritable_ext.cxx +++ b/panda/src/putil/typedWritable_ext.cxx @@ -31,7 +31,7 @@ extern Dtool_PyTypedObject Dtool_TypeHandle; /** * Class that upcalls to the parent class when write_datagram is called. */ -class TypedWritableProxy : public TypedWritable { +class TypedWritableProxy : public TypedWritable, public DtoolProxy { public: ~TypedWritableProxy() { } @@ -123,10 +123,6 @@ public: virtual TypeHandle force_init_type() override { return _type; } - -public: - PyObject *_self; - TypeHandle _type; }; /** @@ -149,8 +145,7 @@ wrap_typed_writable(void *from_this, PyTypeObject *from_type) { } nassertr(to_this->_self != nullptr, nullptr); - Py_INCREF(to_this->_self); - return to_this->_self; + return Py_NewRef(to_this->_self); } /** @@ -212,8 +207,8 @@ __new__(PyTypeObject *cls) { // Make sure that the bindings know how to obtain a wrapper for this type. TypeRegistry *registry = TypeRegistry::ptr(); - registry->record_python_type(*handle, cls, &wrap_typed_writable); - Py_INCREF(cls); + PyTypeObject *cls_ref = (PyTypeObject *)Py_NewRef((PyObject *)cls); + registry->record_python_type(*handle, cls_ref, &wrap_typed_writable); // Note that we don't increment the reference count here, because that would // create a memory leak. The TypedWritableProxy gets deleted when the Python diff --git a/panda/src/recorder/mouseRecorder.cxx b/panda/src/recorder/mouseRecorder.cxx index 37a5a2a440..04b2e8c446 100644 --- a/panda/src/recorder/mouseRecorder.cxx +++ b/panda/src/recorder/mouseRecorder.cxx @@ -228,11 +228,9 @@ make_from_bam(const FactoryParams ¶ms) { RecorderBase *MouseRecorder:: make_recorder(const FactoryParams ¶ms) { MouseRecorder *node = new MouseRecorder(""); - DatagramIterator scan; - BamReader *manager; + BamReaderParam *param = DCAST(BamReaderParam, params.get_param(0)); - parse_params(params, scan, manager); - node->fillin_recorder(scan, manager); + node->fillin_recorder(param->get_iterator(), param->get_manager()); return node; } diff --git a/panda/src/recorder/mouseRecorder.h b/panda/src/recorder/mouseRecorder.h index a30c2d428a..1c29a42152 100644 --- a/panda/src/recorder/mouseRecorder.h +++ b/panda/src/recorder/mouseRecorder.h @@ -79,7 +79,7 @@ public: INLINE virtual int get_ref_count() const final { return ReferenceCount::get_ref_count(); }; INLINE virtual void ref() const final { ReferenceCount::ref(); }; - INLINE virtual bool unref() const final { return ReferenceCount::unref(); }; + INLINE virtual bool unref() const { return ReferenceCount::unref(); }; protected: static TypedWritable *make_from_bam(const FactoryParams ¶ms); diff --git a/panda/src/recorder/socketStreamRecorder.cxx b/panda/src/recorder/socketStreamRecorder.cxx index 8418485b20..a81a48e1d8 100644 --- a/panda/src/recorder/socketStreamRecorder.cxx +++ b/panda/src/recorder/socketStreamRecorder.cxx @@ -113,11 +113,9 @@ write_recorder(BamWriter *manager, Datagram &dg) { RecorderBase *SocketStreamRecorder:: make_recorder(const FactoryParams ¶ms) { SocketStreamRecorder *node = new SocketStreamRecorder; - DatagramIterator scan; - BamReader *manager; + BamReaderParam *param = DCAST(BamReaderParam, params.get_param(0)); - parse_params(params, scan, manager); - node->fillin_recorder(scan, manager); + node->fillin_recorder(param->get_iterator(), param->get_manager()); return node; } diff --git a/panda/src/text/config_text.cxx b/panda/src/text/config_text.cxx index dee79539ba..60eb1be6dd 100644 --- a/panda/src/text/config_text.cxx +++ b/panda/src/text/config_text.cxx @@ -62,7 +62,11 @@ ConfigVariableBool text_kerning "is true, since HarfBuzz offers superior kerning support.")); ConfigVariableBool text_use_harfbuzz +#ifdef HAVE_HARFBUZZ +("text-use-harfbuzz", true, +#else ("text-use-harfbuzz", false, +#endif PRC_DESC("Set this true to enable HarfBuzz support, which offers superior " "text shaping and better support for non-Latin text.")); diff --git a/panda/src/text/dynamicTextFont.cxx b/panda/src/text/dynamicTextFont.cxx index 347841a92f..4d933619b5 100644 --- a/panda/src/text/dynamicTextFont.cxx +++ b/panda/src/text/dynamicTextFont.cxx @@ -621,6 +621,9 @@ make_glyph(int character, FT_Face face, int glyph_index) { render_distance_field(image, outline, bounds.xMin, bounds.yMin); glyph = slot_glyph(character, int_x_size, int_y_size, advance); + if (glyph == nullptr) { + return nullptr; + } if (!_needs_image_processing) { copy_pnmimage_to_texture(image, glyph); } else { @@ -633,6 +636,9 @@ make_glyph(int character, FT_Face face, int glyph_index) { // other processing before it goes to the texture, we can just copy it // directly into the texture. glyph = slot_glyph(character, bitmap.width, bitmap.rows, advance); + if (glyph == nullptr) { + return nullptr; + } copy_bitmap_to_texture(bitmap, glyph); } else { @@ -660,6 +666,9 @@ make_glyph(int character, FT_Face face, int glyph_index) { tex_x_size += outline * 2; tex_y_size += outline * 2; glyph = slot_glyph(character, int_x_size, int_y_size, advance); + if (glyph == nullptr) { + return nullptr; + } if (outline != 0) { // Pad the glyph image to make room for the outline. @@ -940,10 +949,7 @@ slot_glyph(int character, int x_size, int y_size, PN_stdfloat advance) { if (page->is_empty()) { // If we couldn't even put it on an empty page, we're screwed. - text_cat.error() - << "Glyph of size " << x_size << " by " << y_size - << " pixels won't fit on an empty page.\n"; - return nullptr; + goto does_not_fit; } pi = (pi + 1) % _pages.size(); @@ -954,15 +960,27 @@ slot_glyph(int character, int x_size, int y_size, PN_stdfloat advance) { if (garbage_collect() != 0) { // Yes, we just freed up some space. Try once more, recursively. return slot_glyph(character, x_size, y_size, advance); + } - } else { - // No good; all recorded glyphs are actually in use. We need to make a - // new page. + // No good; all recorded glyphs are actually in use. We need to make a new + // page. + { _preferred_page = _pages.size(); PT(DynamicTextPage) page = new DynamicTextPage(this, _preferred_page); _pages.push_back(page); - return page->slot_glyph(character, x_size, y_size, _texture_margin, advance); + + DynamicTextGlyph *glyph = page->slot_glyph(character, x_size, y_size, _texture_margin, advance); + if (glyph != nullptr) { + return glyph; + } } + +does_not_fit: + // If you get this error, increase text-page-size in Config.prc. + text_cat.error() + << "Glyph of size " << x_size << " by " << y_size + << " pixels won't fit on an empty page.\n"; + return nullptr; } /** diff --git a/panda/src/text/fontPool.I b/panda/src/text/fontPool.I index c6fd4544e3..319d12905b 100644 --- a/panda/src/text/fontPool.I +++ b/panda/src/text/fontPool.I @@ -53,7 +53,7 @@ add_font(const std::string &filename, TextFont *font) { /** * Removes the indicated font from the pool, indicating it will never be * loaded again; the font may then be freed. If this function is never - * called, a reference count will be maintained on every font every loaded, + * called, a reference count will be maintained on every font ever loaded, * and fonts will never be freed. */ INLINE void FontPool:: diff --git a/panda/src/text/geomTextGlyph.cxx b/panda/src/text/geomTextGlyph.cxx index 87751532f9..cdf2c92938 100644 --- a/panda/src/text/geomTextGlyph.cxx +++ b/panda/src/text/geomTextGlyph.cxx @@ -175,16 +175,15 @@ add_glyph(const TextGlyph *glyph) { */ void GeomTextGlyph:: register_with_read_factory() { - BamReader::get_factory()->register_factory(get_class_type(), make_GeomTextGlyph); + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); } /** * Factory method to generate a GeomTextGlyph object */ -TypedWritable* GeomTextGlyph:: -make_GeomTextGlyph(const FactoryParams ¶ms) { - GeomTextGlyph *me = new GeomTextGlyph(nullptr, - nullptr); +TypedWritable *GeomTextGlyph:: +make_from_bam(const FactoryParams ¶ms) { + GeomTextGlyph *me = new GeomTextGlyph(nullptr, nullptr); DatagramIterator scan; BamReader *manager; diff --git a/panda/src/text/geomTextGlyph.h b/panda/src/text/geomTextGlyph.h index e9fa1245ae..0a9e679385 100644 --- a/panda/src/text/geomTextGlyph.h +++ b/panda/src/text/geomTextGlyph.h @@ -52,7 +52,7 @@ private: public: static void register_with_read_factory(); - static TypedWritable *make_GeomTextGlyph(const FactoryParams ¶ms); + static TypedWritable *make_from_bam(const FactoryParams ¶ms); PUBLISHED: static TypeHandle get_class_type() { diff --git a/panda/src/text/textAssembler.cxx b/panda/src/text/textAssembler.cxx index 78e3e4adbb..64f4a7ec91 100644 --- a/panda/src/text/textAssembler.cxx +++ b/panda/src/text/textAssembler.cxx @@ -1411,6 +1411,10 @@ assemble_row(TextAssembler::TextRow &row, PN_stdfloat xpos = 0.0f; align = TextProperties::A_left; + TextProperties::Direction dir = TextProperties::D_ltr; + size_t rtl_begin = 0; + PN_stdfloat rtl_begin_xpos = 0.0f; + // Remember previous character, for kerning. int prev_char = -1; @@ -1472,6 +1476,8 @@ assemble_row(TextAssembler::TextRow &row, // Shape the buffer accumulated so far. shape_buffer(harfbuff, placed_glyphs, xpos, prev_cprops->_properties); hb_buffer_reset(harfbuff); + rtl_begin = placed_glyphs.size(); + rtl_begin_xpos = xpos; } else if (harfbuff == nullptr && text_use_harfbuzz && font->is_of_type(DynamicTextFont::get_class_type())) { @@ -1486,6 +1492,29 @@ assemble_row(TextAssembler::TextRow &row, } #endif + // When not using harfbuzz, check if the direction was set explicitly. + if (properties->has_direction() && properties->get_direction() != dir) { + if (dir == TextProperties::D_rtl) { + // Flip the preceding characters. + PN_stdfloat xpos2 = xpos; + size_t i = placed_glyphs.size(); + while (i > rtl_begin) { + --i; + PN_stdfloat new_xpos = rtl_begin_xpos + (xpos - xpos2); + xpos2 = placed_glyphs[i]._xpos; + placed_glyphs[i]._xpos = new_xpos; + } + dir = TextProperties::D_ltr; + } + else if (dir == TextProperties::D_ltr) { + // When switching to right-to-left, keep track of the first glyph that + // was RTL so that we can later offset the X positions. + dir = TextProperties::D_rtl; + rtl_begin = placed_glyphs.size(); + rtl_begin_xpos = xpos; + } + } + if (character == ' ') { // A space is a special case. xpos += properties->get_glyph_scale() * properties->get_text_scale() * font->get_space_advance(); @@ -1651,6 +1680,18 @@ assemble_row(TextAssembler::TextRow &row, } } + if (dir == TextProperties::D_rtl) { + // Flip the preceding characters. + PN_stdfloat xpos2 = xpos; + size_t i = placed_glyphs.size(); + while (i > rtl_begin) { + --i; + PN_stdfloat new_xpos = rtl_begin_xpos + (xpos - xpos2); + xpos2 = placed_glyphs[i]._xpos; + placed_glyphs[i]._xpos = new_xpos; + } + } + #ifdef HAVE_HARFBUZZ if (harfbuff != nullptr && hb_buffer_get_length(harfbuff) > 0) { shape_buffer(harfbuff, placed_glyphs, xpos, prev_cprops->_properties); diff --git a/panda/src/text/textNode.I b/panda/src/text/textNode.I index 188fb009a4..4ba8ead2ac 100644 --- a/panda/src/text/textNode.I +++ b/panda/src/text/textNode.I @@ -756,7 +756,9 @@ clear_wordwrap() { } /** - * + * Sets the color of the text. Note that this will modulate the color of all + * components of the text, including the shadow and outline. If you wish to + * only set the foreground color, see DynamicTextFont::set_fg(). */ INLINE void TextNode:: set_text_color(const LColor &text_color) { @@ -766,7 +768,9 @@ set_text_color(const LColor &text_color) { } /** - * + * Sets the color of the text. Note that this will modulate the color of all + * components of the text, including the shadow and outline. If you wish to + * only set the foreground color, see DynamicTextFont::set_fg(). */ INLINE void TextNode:: set_text_color(PN_stdfloat r, PN_stdfloat g, PN_stdfloat b, PN_stdfloat a) { diff --git a/panda/src/text/textProperties.I b/panda/src/text/textProperties.I index d56c354d46..c31cd883de 100644 --- a/panda/src/text/textProperties.I +++ b/panda/src/text/textProperties.I @@ -419,7 +419,9 @@ get_preserve_trailing_whitespace() const { } /** - * + * Sets the color of the text. Note that this will modulate the color of all + * components of the text, including the shadow and outline. If you wish to + * only set the foreground color, see DynamicTextFont::set_fg(). */ INLINE void TextProperties:: set_text_color(PN_stdfloat r, PN_stdfloat g, PN_stdfloat b, PN_stdfloat a) { @@ -427,7 +429,9 @@ set_text_color(PN_stdfloat r, PN_stdfloat g, PN_stdfloat b, PN_stdfloat a) { } /** - * + * Sets the color of the text. Note that this will modulate the color of all + * components of the text, including the shadow and outline. If you wish to + * only set the foreground color, see DynamicTextFont::set_fg(). */ INLINE void TextProperties:: set_text_color(const LColor &text_color) { @@ -448,7 +452,7 @@ clear_text_color() { } /** - * + * Returns true if a text color was specified with set_text_color(). */ INLINE bool TextProperties:: has_text_color() const { diff --git a/panda/src/tinydisplay/CMakeLists.txt b/panda/src/tinydisplay/CMakeLists.txt new file mode 100644 index 0000000000..d89eb8005e --- /dev/null +++ b/panda/src/tinydisplay/CMakeLists.txt @@ -0,0 +1,128 @@ +if (NOT HAVE_TINYDISPLAY) + return() +endif() + +set(P3TINYDISPLAY_HEADERS + config_tinydisplay.h + tinyGeomMunger.I tinyGeomMunger.h + tinySDLGraphicsPipe.I tinySDLGraphicsPipe.h + tinySDLGraphicsWindow.I tinySDLGraphicsWindow.h + tinyGraphicsBuffer.I tinyGraphicsBuffer.h + tinyGraphicsStateGuardian.I tinyGraphicsStateGuardian.h + tinyTextureContext.I tinyTextureContext.h + tinyWinGraphicsPipe.I tinyWinGraphicsPipe.h + tinyWinGraphicsWindow.I tinyWinGraphicsWindow.h + tinyXGraphicsPipe.I tinyXGraphicsPipe.h + tinyXGraphicsWindow.I tinyXGraphicsWindow.h + tinyOffscreenGraphicsPipe.I tinyOffscreenGraphicsPipe.h + srgb_tables.h + zbuffer.h + zfeatures.h + zgl.h + zline.h + zmath.h + ztriangle.h + ztriangle_two.h + ztriangle_code_1.h + ztriangle_code_2.h + ztriangle_code_3.h + ztriangle_code_4.h + ztriangle_table.h + store_pixel.h + store_pixel_code.h + store_pixel_table.h +) + +set(P3TINYDISPLAY_SOURCES + clip.cxx + config_tinydisplay.cxx + error.cxx + image_util.cxx + init.cxx + td_light.cxx + memory.cxx + specbuf.cxx + store_pixel.cxx + td_texture.cxx + tinyGeomMunger.cxx + tinyGraphicsBuffer.cxx + tinyGraphicsStateGuardian.cxx + tinyOffscreenGraphicsPipe.cxx + tinySDLGraphicsPipe.cxx + tinySDLGraphicsWindow.cxx + tinyTextureContext.cxx + tinyWinGraphicsPipe.cxx + tinyWinGraphicsWindow.cxx + tinyXGraphicsPipe.cxx + tinyXGraphicsWindow.cxx + vertex.cxx + srgb_tables.cxx + zbuffer.cxx + zdither.cxx + zline.cxx + zmath.cxx +) + +set(P3TINYDISPLAY_ZTRIANGLE_SOURCES + ztriangle_1.cxx + ztriangle_2.cxx + ztriangle_3.cxx + ztriangle_4.cxx + ztriangle_table.cxx +) + +set_source_files_properties(${P3TINYDISPLAY_ZTRIANGLE_SOURCES} + PROPERTIES SKIP_UNITY_BUILD_INCLUSION YES) + +if(NOT MSVC) + set_source_files_properties(${P3TINYDISPLAY_ZTRIANGLE_SOURCES} + PROPERTIES COMPILE_FLAGS "-Wno-unused-but-set-variable") +endif() + +if(HAVE_COCOA) + set(P3TINYDISPLAY_HEADERS ${P3TINYDISPLAY_HEADERS} + tinyCocoaGraphicsPipe.I tinyCocoaGraphicsPipe.h + tinyCocoaGraphicsWindow.I tinyCocoaGraphicsWindow.h) + + set(P3TINYDISPLAY_SOURCES ${P3TINYDISPLAY_SOURCES} + tinyCocoaGraphicsPipe.cxx + tinyCocoaGraphicsWindow.mm) + + set_source_files_properties(tinyCocoaGraphicsWindow.mm + PROPERTIES SKIP_UNITY_BUILD_INCLUSION YES) + + add_compile_definitions(HAVE_COCOA) +endif() + +composite_sources(p3tinydisplay P3TINYDISPLAY_SOURCES) + +# Determine the additional components to link in. +set(COCOADISPLAY_LINK_TARGETS) + +if(WIN32) + list(APPEND COCOADISPLAY_LINK_TARGETS p3windisplay) +endif() + +if(HAVE_X11) + list(APPEND COCOADISPLAY_LINK_TARGETS p3x11display) +endif() + +if(HAVE_COCOA) + list(APPEND COCOADISPLAY_LINK_TARGETS p3cocoadisplay) +endif() + +set(CMAKE_INSTALL_DEFAULT_COMPONENT_NAME "TinyDisplay") +add_metalib(p3tinydisplay ${MODULE_TYPE} + ${P3TINYDISPLAY_HEADERS} ${P3TINYDISPLAY_SOURCES} ${P3TINYDISPLAY_ZTRIANGLE_SOURCES} + COMPONENTS ${COCOADISPLAY_LINK_TARGETS}) +unset(CMAKE_INSTALL_DEFAULT_COMPONENT_NAME) + +set_target_properties(p3tinydisplay PROPERTIES DEFINE_SYMBOL BUILDING_TINYDISPLAY) +target_link_libraries(p3tinydisplay panda) + +install(TARGETS p3tinydisplay + EXPORT TinyDisplay COMPONENT TinyDisplay + DESTINATION ${MODULE_DESTINATION} + ARCHIVE COMPONENT TinyDisplayDevel) + +export_targets(TinyDisplay NAMESPACE "Panda3D::TinyDisplay::" COMPONENT TinyDisplayDevel) diff --git a/panda/src/tinydisplay/srgb_tables.cxx b/panda/src/tinydisplay/srgb_tables.cxx index b7901d39cd..8192d869d2 100644 --- a/panda/src/tinydisplay/srgb_tables.cxx +++ b/panda/src/tinydisplay/srgb_tables.cxx @@ -1,3 +1,5 @@ +#include "srgb_tables.h" + const unsigned short decode_sRGB[256] = { 0x0000, 0x0013, 0x0027, 0x003b, 0x004f, 0x0063, 0x0077, 0x008b, 0x009f, 0x00b3, 0x00c6, 0x00db, 0x00f0, 0x0107, 0x011f, 0x0139, 0x0153, 0x016f, 0x018c, 0x01aa, 0x01ca, 0x01eb, diff --git a/panda/src/tinydisplay/srgb_tables.h b/panda/src/tinydisplay/srgb_tables.h index 2ff9108aa5..aa0ace53bb 100644 --- a/panda/src/tinydisplay/srgb_tables.h +++ b/panda/src/tinydisplay/srgb_tables.h @@ -1,6 +1,11 @@ +#ifndef SRGB_TABLES_H +#define SRGB_TABLES_H + /* 8-bit sRGB to 16-bit linear */ extern const unsigned short decode_sRGB[256]; /* 12-bit linear to 8-bit sRGB. I used 12-bit because it can represent all possible 8-bit sRGB values. */ extern const unsigned char encode_sRGB[4096]; + +#endif diff --git a/panda/src/tinydisplay/tinyCocoaGraphicsWindow.h b/panda/src/tinydisplay/tinyCocoaGraphicsWindow.h index 961a1749c3..f2e55d1f5d 100644 --- a/panda/src/tinydisplay/tinyCocoaGraphicsWindow.h +++ b/panda/src/tinydisplay/tinyCocoaGraphicsWindow.h @@ -62,6 +62,8 @@ private: small_vector _swap_chain; int _swap_index = 0; + uint32_t _vsync_counter = 0; + bool _vsync_enabled = false; public: static TypeHandle get_class_type() { diff --git a/panda/src/tinydisplay/tinyCocoaGraphicsWindow.mm b/panda/src/tinydisplay/tinyCocoaGraphicsWindow.mm index 38c08e88f7..6565eccac3 100644 --- a/panda/src/tinydisplay/tinyCocoaGraphicsWindow.mm +++ b/panda/src/tinydisplay/tinyCocoaGraphicsWindow.mm @@ -114,6 +114,21 @@ end_flip() { if (_flip_ready) { do_present(); _swap_index = (_swap_index + 1) % _swap_chain.size(); + + // We don't really support proper VSync because we just update the backing + // store and let the OS update it when needed, but we still need to wait + // for VBlank so that the frame rate is appropriately limited. + if (sync_video) { + CocoaGraphicsPipe *cocoapipe = (CocoaGraphicsPipe *)_pipe.p(); + if (!_vsync_enabled) { + // If this fails, we don't keep trying. + cocoapipe->init_vsync(_vsync_counter); + _vsync_enabled = true; + } + cocoapipe->wait_vsync(_vsync_counter); + } else { + _vsync_enabled = false; + } } GraphicsWindow::end_flip(); diff --git a/panda/src/tinydisplay/zmath.h b/panda/src/tinydisplay/zmath.h index 5296a8ad06..73fae86d6c 100644 --- a/panda/src/tinydisplay/zmath.h +++ b/panda/src/tinydisplay/zmath.h @@ -1,6 +1,8 @@ #ifndef __ZMATH__ #define __ZMATH__ +#include "numeric_types.h" + /* Matrix & Vertex */ typedef struct { diff --git a/panda/src/webgldisplay/config_webgldisplay.cxx b/panda/src/webgldisplay/config_webgldisplay.cxx new file mode 100644 index 0000000000..ae907febb6 --- /dev/null +++ b/panda/src/webgldisplay/config_webgldisplay.cxx @@ -0,0 +1,53 @@ +/** + * PANDA 3D SOFTWARE + * Copyright (c) Carnegie Mellon University. All rights reserved. + * + * All use of this software is subject to the terms of the revised BSD + * license. You should have received a copy of this license along + * with this source code in a file named "LICENSE." + * + * @file config_webgldisplay.cxx + * @author rdb + * @date 2015-04-01 + */ + +#include "config_webgldisplay.h" +#include "webGLGraphicsPipe.h" +#include "webGLGraphicsWindow.h" +#include "webGLGraphicsStateGuardian.h" +#include "graphicsPipeSelection.h" +#include "dconfig.h" +#include "pandaSystem.h" + +Configure(config_webgldisplay); +NotifyCategoryDef(webgldisplay, "display"); + +ConfigureFn(config_webgldisplay) { + init_libwebgldisplay(); +} + +/** + * Initializes the library. This must be called at least once before any of + * the functions or classes in this library can be used. Normally it will be + * called by the static initializers and need not be called explicitly, but + * special cases exist. + */ +void +init_libwebgldisplay() { + static bool initialized = false; + if (initialized) { + return; + } + initialized = true; + + WebGLGraphicsPipe::init_type(); + WebGLGraphicsWindow::init_type(); + WebGLGraphicsStateGuardian::init_type(); + + GraphicsPipeSelection *selection = GraphicsPipeSelection::get_global_ptr(); + selection->add_pipe_type(WebGLGraphicsPipe::get_class_type(), + WebGLGraphicsPipe::pipe_constructor); + + PandaSystem *ps = PandaSystem::get_global_ptr(); + ps->set_system_tag("WebGL", "window_system", "HTML"); +} diff --git a/panda/src/webgldisplay/config_webgldisplay.h b/panda/src/webgldisplay/config_webgldisplay.h new file mode 100644 index 0000000000..4d9f8c0154 --- /dev/null +++ b/panda/src/webgldisplay/config_webgldisplay.h @@ -0,0 +1,27 @@ +/** + * PANDA 3D SOFTWARE + * Copyright (c) Carnegie Mellon University. All rights reserved. + * + * All use of this software is subject to the terms of the revised BSD + * license. You should have received a copy of this license along + * with this source code in a file named "LICENSE." + * + * @file config_webgldisplay.h + * @author rdb + * @date 2015-04-01 + */ + +#ifndef CONFIG_WEBGLDISPLAY_H +#define CONFIG_WEBGLDISPLAY_H + +#include "pandabase.h" +#include "notifyCategoryProxy.h" +#include "configVariableString.h" +#include "configVariableBool.h" +#include "configVariableInt.h" + +NotifyCategoryDecl(webgldisplay,,); + +extern "C" void init_libwebgldisplay(); + +#endif diff --git a/panda/src/webgldisplay/p3webgldisplay_composite1.cxx b/panda/src/webgldisplay/p3webgldisplay_composite1.cxx new file mode 100644 index 0000000000..fb61c95b9a --- /dev/null +++ b/panda/src/webgldisplay/p3webgldisplay_composite1.cxx @@ -0,0 +1,4 @@ +#include "config_webgldisplay.cxx" +#include "webGLGraphicsPipe.cxx" +#include "webGLGraphicsStateGuardian.cxx" +#include "webGLGraphicsWindow.cxx" diff --git a/panda/src/webgldisplay/webGLGraphicsPipe.I b/panda/src/webgldisplay/webGLGraphicsPipe.I new file mode 100644 index 0000000000..e67c3f9d65 --- /dev/null +++ b/panda/src/webgldisplay/webGLGraphicsPipe.I @@ -0,0 +1,12 @@ +/** + * PANDA 3D SOFTWARE + * Copyright (c) Carnegie Mellon University. All rights reserved. + * + * All use of this software is subject to the terms of the revised BSD + * license. You should have received a copy of this license along + * with this source code in a file named "LICENSE." + * + * @file webGLGraphicsPipe.I + * @author rdb + * @date 2015-04-01 + */ diff --git a/panda/src/webgldisplay/webGLGraphicsPipe.cxx b/panda/src/webgldisplay/webGLGraphicsPipe.cxx new file mode 100644 index 0000000000..9e80679fcd --- /dev/null +++ b/panda/src/webgldisplay/webGLGraphicsPipe.cxx @@ -0,0 +1,138 @@ +/** + * PANDA 3D SOFTWARE + * Copyright (c) Carnegie Mellon University. All rights reserved. + * + * All use of this software is subject to the terms of the revised BSD + * license. You should have received a copy of this license along + * with this source code in a file named "LICENSE." + * + * @file webGLGraphicsPipe.cxx + * @author rdb + * @date 2015-04-01 + */ + +#include "webGLGraphicsPipe.h" +#include "webGLGraphicsWindow.h" +#include "webGLGraphicsStateGuardian.h" +#include "config_webgldisplay.h" +#include "frameBufferProperties.h" + +TypeHandle WebGLGraphicsPipe::_type_handle; + +/** + * + */ +WebGLGraphicsPipe:: +WebGLGraphicsPipe() { +} + +/** + * + */ +WebGLGraphicsPipe:: +~WebGLGraphicsPipe() { +} + +/** + * Returns the name of the rendering interface associated with this + * GraphicsPipe. This is used to present to the user to allow him/her to + * choose between several possible GraphicsPipes available on a particular + * platform, so the name should be meaningful and unique for a given platform. + */ +std::string WebGLGraphicsPipe:: +get_interface_name() const { + return "WebGL"; +} + +/** + * This function is passed to the GraphicsPipeSelection object to allow the + * user to make a default webGLGraphicsPipe. + */ +PT(GraphicsPipe) WebGLGraphicsPipe:: +pipe_constructor() { + return new WebGLGraphicsPipe; +} + +/** + * Returns an indication of the thread in which this GraphicsPipe requires its + * window processing to be performed: typically either the app thread (e.g. + * X) or the draw thread (Windows). + */ +GraphicsPipe::PreferredWindowThread WebGLGraphicsPipe:: +get_preferred_window_thread() const { + // JavaScript has no threads, so does it matter? + return PWT_draw; +} + +/** + * Creates a new window on the pipe, if possible. + */ +PT(GraphicsOutput) WebGLGraphicsPipe:: +make_output(const std::string &name, + const FrameBufferProperties &fb_prop, + const WindowProperties &win_prop, + int flags, + GraphicsEngine *engine, + GraphicsStateGuardian *gsg, + GraphicsOutput *host, + int retry, + bool &precertify) { + + if (!_is_valid) { + return NULL; + } + + WebGLGraphicsStateGuardian *web_gl = 0; + if (gsg != NULL) { + DCAST_INTO_R(web_gl, gsg, NULL); + } + + // First thing to try: a WebGLGraphicsWindow + + if (retry == 0) { + if (((flags&BF_require_parasite)!=0)|| + ((flags&BF_refuse_window)!=0)|| + ((flags&BF_resizeable)!=0)|| + ((flags&BF_size_track_host)!=0)|| + ((flags&BF_rtt_cumulative)!=0)|| + ((flags&BF_can_bind_color)!=0)|| + ((flags&BF_can_bind_every)!=0)) { + return NULL; + } + return new WebGLGraphicsWindow(engine, this, name, fb_prop, win_prop, + flags, gsg, host); + } + + // Second thing to try: a GLES2GraphicsBuffer + if (retry == 1) { + if ((host==0)|| + //(!gl_support_fbo)|| + ((flags&BF_require_parasite)!=0)|| + ((flags&BF_require_window)!=0)) { + return NULL; + } + // Early failure - if we are sure that this buffer WONT meet specs, we can + // bail out early. + if ((flags & BF_fb_props_optional)==0) { + if ((fb_prop.get_indexed_color() > 0)|| + (fb_prop.get_back_buffers() > 0)|| + (fb_prop.get_accum_bits() > 0)|| + (fb_prop.get_multisamples() > 0)) { + return NULL; + } + } + // Early success - if we are sure that this buffer WILL meet specs, we can + // precertify it. + if ((web_gl != 0) && + (web_gl->is_valid()) && + (!web_gl->needs_reset()) && + (fb_prop.is_basic())) { + precertify = true; + } + return new GLES2GraphicsBuffer(engine, this, name, fb_prop, win_prop, + flags, gsg, host); + } + + // Nothing else left to try. + return NULL; +} diff --git a/panda/src/webgldisplay/webGLGraphicsPipe.h b/panda/src/webgldisplay/webGLGraphicsPipe.h new file mode 100644 index 0000000000..a8e2a8ddc6 --- /dev/null +++ b/panda/src/webgldisplay/webGLGraphicsPipe.h @@ -0,0 +1,71 @@ +/** + * PANDA 3D SOFTWARE + * Copyright (c) Carnegie Mellon University. All rights reserved. + * + * All use of this software is subject to the terms of the revised BSD + * license. You should have received a copy of this license along + * with this source code in a file named "LICENSE." + * + * @file webGLGraphicsPipe.h + * @author rdb + * @date 2015-04-01 + */ + +#ifndef WEBGLGRAPHICSPIPE_H +#define WEBGLGRAPHICSPIPE_H + +#include "pandabase.h" +#include "graphicsWindow.h" +#include "graphicsPipe.h" + +class FrameBufferProperties; + +class WebGLGraphicsWindow; + +/** + * This graphics pipe represents the interface for creating OpenGL ES graphics + * windows on an X-based (e.g. Unix) client. + */ +class WebGLGraphicsPipe : public GraphicsPipe { +public: + WebGLGraphicsPipe(); + virtual ~WebGLGraphicsPipe(); + + virtual std::string get_interface_name() const; + static PT(GraphicsPipe) pipe_constructor(); + +public: + virtual PreferredWindowThread get_preferred_window_thread() const; + +protected: + virtual PT(GraphicsOutput) make_output(const std::string &name, + const FrameBufferProperties &fb_prop, + const WindowProperties &win_prop, + int flags, + GraphicsEngine *engine, + GraphicsStateGuardian *gsg, + GraphicsOutput *host, + int retry, + bool &precertify); + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + GraphicsPipe::init_type(); + register_type(_type_handle, "WebGLGraphicsPipe", + GraphicsPipe::get_class_type()); + } + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + +private: + static TypeHandle _type_handle; +}; + +#include "webGLGraphicsPipe.I" + +#endif diff --git a/panda/src/webgldisplay/webGLGraphicsStateGuardian.I b/panda/src/webgldisplay/webGLGraphicsStateGuardian.I new file mode 100644 index 0000000000..c9afd537dc --- /dev/null +++ b/panda/src/webgldisplay/webGLGraphicsStateGuardian.I @@ -0,0 +1,12 @@ +/** + * PANDA 3D SOFTWARE + * Copyright (c) Carnegie Mellon University. All rights reserved. + * + * All use of this software is subject to the terms of the revised BSD + * license. You should have received a copy of this license along + * with this source code in a file named "LICENSE." + * + * @file webGLGraphicsStateGuardian.I + * @author rdb + * @date 2015-04-01 + */ diff --git a/panda/src/webgldisplay/webGLGraphicsStateGuardian.cxx b/panda/src/webgldisplay/webGLGraphicsStateGuardian.cxx new file mode 100644 index 0000000000..564a8df148 --- /dev/null +++ b/panda/src/webgldisplay/webGLGraphicsStateGuardian.cxx @@ -0,0 +1,174 @@ +/** + * PANDA 3D SOFTWARE + * Copyright (c) Carnegie Mellon University. All rights reserved. + * + * All use of this software is subject to the terms of the revised BSD + * license. You should have received a copy of this license along + * with this source code in a file named "LICENSE." + * + * @file webGLGraphicsStateGuardian.cxx + * @author rdb + * @date 2015-04-01 + */ + +#include "webGLGraphicsStateGuardian.h" +#include "config_webgldisplay.h" + +extern "C" { + extern void* emscripten_GetProcAddress(const char *x); +} + +TypeHandle WebGLGraphicsStateGuardian::_type_handle; + +/** + * + */ +WebGLGraphicsStateGuardian:: +WebGLGraphicsStateGuardian(GraphicsEngine *engine, GraphicsPipe *pipe) : + GLES2GraphicsStateGuardian(engine, pipe) +{ + _context = 0; + _have_context = false; +} + +/** + * + */ +WebGLGraphicsStateGuardian:: +~WebGLGraphicsStateGuardian() { + if (_context != 0) { + const char *target = "#canvas"; + emscripten_set_webglcontextlost_callback(target, NULL, false, NULL); + emscripten_set_webglcontextrestored_callback(target, NULL, false, NULL); + + if (emscripten_webgl_destroy_context(_context) != EMSCRIPTEN_RESULT_SUCCESS) { + webgldisplay_cat.error() << "Failed to destroy WebGL context!\n"; + } + _context = 0; + } +} + +/** + * Selects a visual or fbconfig for all the windows and buffers that use this + * gsg. Also creates the GL context and obtains the visual. + */ +void WebGLGraphicsStateGuardian:: +choose_pixel_format(const FrameBufferProperties &properties, + const char *target) { + + nassertv(_context == 0); + + EmscriptenWebGLContextAttributes attribs; + emscripten_webgl_init_context_attributes(&attribs); + + attribs.alpha = (properties.get_alpha_bits() > 0); + attribs.depth = (properties.get_depth_bits() > 0); + attribs.stencil = (properties.get_stencil_bits() > 0); + attribs.majorVersion = 2; + attribs.minorVersion = 0; + attribs.enableExtensionsByDefault = false; + + EMSCRIPTEN_WEBGL_CONTEXT_HANDLE result; + result = emscripten_webgl_create_context(target, &attribs); + + if (result <= 0) { + // Fall back to WebGL 1. + attribs.majorVersion = 1; + result = emscripten_webgl_create_context(target, &attribs); + } + + if (result > 0) { + _context = result; + _have_context = true; + + // We may lose the WebGL context at any time, at which time we have to be + // prepared to drop all resources. + emscripten_set_webglcontextlost_callback(target, (void *)this, false, &on_context_event); + emscripten_set_webglcontextrestored_callback(target, (void *)this, false, &on_context_event); + } else { + webgldisplay_cat.error() << "Context creation failed.\n"; + } +} + +/** + * Resets all internal state as if the gsg were newly created. + */ +void WebGLGraphicsStateGuardian:: +reset() { + GLES2GraphicsStateGuardian::reset(); +} + +/** + * WebGL may take the context away from us at any time. We have to be ready + * for that. + */ +EM_BOOL WebGLGraphicsStateGuardian:: +on_context_event(int type, const void *, void *user_data) { + WebGLGraphicsStateGuardian *gsg = (WebGLGraphicsStateGuardian *)user_data; + nassertr(gsg != NULL, false); + + if (type == EMSCRIPTEN_EVENT_WEBGLCONTEXTLOST) { + webgldisplay_cat.info() << "WebGL context lost!\n"; + gsg->context_lost(); + return true; + + } else if (type == EMSCRIPTEN_EVENT_WEBGLCONTEXTRESTORED) { + webgldisplay_cat.info() << "WebGL context restored!\n"; + gsg->reset(); + return true; + } + + return false; +} + +/** + * Called to indicate that we lost the WebGL context, and any resources we + * prepared previously are gone. + */ +void WebGLGraphicsStateGuardian:: +context_lost() { + release_all(); + + // Assign a new PreparedGraphicsObjects to prevent the GSG from to trying to + // neatly clean up the old resources. + _prepared_objects = new PreparedGraphicsObjects; +} + +/** + * This may be redefined by a derived class (e.g. glx or wgl) to get whatever + * further extensions strings may be appropriate to that interface, in + * addition to the GL extension strings return by glGetString(). + */ +void WebGLGraphicsStateGuardian:: +get_extra_extensions() { +} + +/** + * Returns true if the indicated extension is reported by the GL system, false + * otherwise. The extension name is case-sensitive. + */ +bool WebGLGraphicsStateGuardian:: +has_extension(const std::string &extension) const { + nassertr(_context != 0, false); + + // If the GSG asks for it, that is probably a good reason to activate the + // extension. + EM_BOOL result = emscripten_webgl_enable_extension(_context, extension.c_str()); +#ifndef NDEBUG + if (result) { + webgldisplay_cat.info() << "Activated extension: " << extension << "\n"; + } +#endif + return result; +} + +/** + * Returns the pointer to the GL extension function with the indicated name. + * It is the responsibility of the caller to ensure that the required + * extension is defined in the OpenGL runtime prior to calling this; it is an + * error to call this for a function that is not defined. + */ +void *WebGLGraphicsStateGuardian:: +do_get_extension_func(const char *name) { + return emscripten_GetProcAddress(name); +} diff --git a/panda/src/webgldisplay/webGLGraphicsStateGuardian.h b/panda/src/webgldisplay/webGLGraphicsStateGuardian.h new file mode 100644 index 0000000000..57d993a27a --- /dev/null +++ b/panda/src/webgldisplay/webGLGraphicsStateGuardian.h @@ -0,0 +1,72 @@ +/** + * PANDA 3D SOFTWARE + * Copyright (c) Carnegie Mellon University. All rights reserved. + * + * All use of this software is subject to the terms of the revised BSD + * license. You should have received a copy of this license along + * with this source code in a file named "LICENSE." + * + * @file webGLGraphicsStateGuardian.h + * @author rdb + * @date 2015-04-01 + */ + +#ifndef WEBGLGRAPHICSSTATEGUARDIAN_H +#define WEBGLGRAPHICSSTATEGUARDIAN_H + +#include "pandabase.h" +#include "webGLGraphicsPipe.h" +#include "gles2gsg.h" + +#include + +/** + * A specialization on GLES2GraphicsStateGuardian to add emscripten-specific + * context set-up. + */ +class WebGLGraphicsStateGuardian : public GLES2GraphicsStateGuardian { +public: + WebGLGraphicsStateGuardian(GraphicsEngine *engine, GraphicsPipe *pipe); + virtual ~WebGLGraphicsStateGuardian(); + + void choose_pixel_format(const FrameBufferProperties &properties, + const char *target); + + static EM_BOOL on_context_event(int type, const void *, void *user_data); + + virtual void reset(); + +private: + EMSCRIPTEN_WEBGL_CONTEXT_HANDLE _context; + bool _have_context; + +protected: + void context_lost(); + + virtual void get_extra_extensions(); + virtual bool has_extension(const std::string &extension) const; + virtual void *do_get_extension_func(const char *name); + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + GLES2GraphicsStateGuardian::init_type(); + register_type(_type_handle, "WebGLGraphicsStateGuardian", + GLES2GraphicsStateGuardian::get_class_type()); + } + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + +private: + static TypeHandle _type_handle; + + friend class WebGLGraphicsWindow; +}; + +#include "webGLGraphicsStateGuardian.I" + +#endif diff --git a/panda/src/webgldisplay/webGLGraphicsWindow.I b/panda/src/webgldisplay/webGLGraphicsWindow.I new file mode 100644 index 0000000000..318027958c --- /dev/null +++ b/panda/src/webgldisplay/webGLGraphicsWindow.I @@ -0,0 +1,12 @@ +/** + * PANDA 3D SOFTWARE + * Copyright (c) Carnegie Mellon University. All rights reserved. + * + * All use of this software is subject to the terms of the revised BSD + * license. You should have received a copy of this license along + * with this source code in a file named "LICENSE." + * + * @file webGLGraphicsWindow.I + * @author rdb + * @date 2015-03-31 + */ diff --git a/panda/src/webgldisplay/webGLGraphicsWindow.cxx b/panda/src/webgldisplay/webGLGraphicsWindow.cxx new file mode 100644 index 0000000000..700f89c1b8 --- /dev/null +++ b/panda/src/webgldisplay/webGLGraphicsWindow.cxx @@ -0,0 +1,971 @@ +/** + * PANDA 3D SOFTWARE + * Copyright (c) Carnegie Mellon University. All rights reserved. + * + * All use of this software is subject to the terms of the revised BSD + * license. You should have received a copy of this license along + * with this source code in a file named "LICENSE." + * + * @file webGLGraphicsWindow.cxx + * @author rdb + * @date 2015-03-31 + */ + +#include "webGLGraphicsWindow.h" +#include "webGLGraphicsStateGuardian.h" +#include "config_webgldisplay.h" +#include "mouseButton.h" +#include "keyboardButton.h" +#include "throw_event.h" +#include "pointerData.h" +#include + +TypeHandle WebGLGraphicsWindow::_type_handle; + +/** + * + */ +WebGLGraphicsWindow:: +WebGLGraphicsWindow(GraphicsEngine *engine, GraphicsPipe *pipe, + const std::string &name, + const FrameBufferProperties &fb_prop, + const WindowProperties &win_prop, + int flags, + GraphicsStateGuardian *gsg, + GraphicsOutput *host) : + GraphicsWindow(engine, pipe, name, fb_prop, win_prop, flags, gsg, host) +{ + PT(GraphicsWindowInputDevice) device = + GraphicsWindowInputDevice::pointer_and_keyboard(this, "keyboard_mouse"); + add_input_device(device); + _input = device.p(); +} + +/** + * + */ +WebGLGraphicsWindow:: +~WebGLGraphicsWindow() { +} + +/** + * Forces the pointer to the indicated position within the window, if + * possible. + * + * Returns true if successful, false on failure. This may fail if the mouse + * is not currently within the window, or if the API doesn't support this + * operation. + */ +bool WebGLGraphicsWindow:: +move_pointer(int device, int x, int y) { + if (device == 0 && _properties.get_mouse_mode() == WindowProperties::M_relative) { + // The pointer position is meaningless in relative mode, so we silently + // pretend that this worked. + _input->set_pointer_in_window(x, y); + return true; + } + return false; +} + +/** + * This function will be called within the draw thread before beginning + * rendering for a given frame. It should do whatever setup is required, and + * return true if the frame should be rendered, or false if it should be + * skipped. + */ +bool WebGLGraphicsWindow:: +begin_frame(FrameMode mode, Thread *current_thread) { + PStatTimer timer(_make_current_pcollector, current_thread); + + begin_frame_spam(mode); + if (_gsg == nullptr) { + return false; + } + + WebGLGraphicsStateGuardian *webgl_gsg; + DCAST_INTO_R(webgl_gsg, _gsg, false); + + if (emscripten_is_webgl_context_lost(webgl_gsg->_context)) { + // The context was lost, and any GL calls we make will fail. + return false; + } + + if (emscripten_webgl_make_context_current(webgl_gsg->_context) != EMSCRIPTEN_RESULT_SUCCESS) { + webgldisplay_cat.error() + << "Failed to make context current.\n"; + return false; + } + + if (mode == FM_render) { + // begin_render_texture(); + clear_cube_map_selection(); + } + + _gsg->set_current_properties(&get_fb_properties()); + return _gsg->begin_frame(current_thread); +} + +/** + * This function will be called within the draw thread after rendering is + * completed for a given frame. It should do whatever finalization is + * required. + */ +void WebGLGraphicsWindow:: +end_frame(FrameMode mode, Thread *current_thread) { + end_frame_spam(mode); + nassertv(_gsg != nullptr); + + if (mode == FM_render) { + // end_render_texture(); + copy_to_textures(); + } + + _gsg->end_frame(current_thread); + + if (mode == FM_render) { + trigger_flip(); + clear_cube_map_selection(); + } +} + +/** + * This function will be called within the draw thread after begin_flip() has + * been called on all windows, to finish the exchange of the front and back + * buffers. + * + * This should cause the window to wait for the flip, if necessary. + */ +void WebGLGraphicsWindow:: +end_flip() { + GraphicsWindow::end_flip(); +} + +/** + * Do whatever processing is necessary to ensure that the window responds to + * user events. Also, honor any requests recently made via + * request_properties() + * + * This function is called only within the window thread. + */ +void WebGLGraphicsWindow:: +process_events() { + GraphicsWindow::process_events(); +} + +/** + * Applies the requested set of properties to the window, if possible, for + * instance to request a change in size or minimization status. + * + * The window properties are applied immediately, rather than waiting until + * the next frame. This implies that this method may *only* be called from + * within the window thread. + * + * The return value is true if the properties are set, false if they are + * ignored. This is mainly useful for derived classes to implement extensions + * to this function. + */ +void WebGLGraphicsWindow:: +set_properties_now(WindowProperties &properties) { + GraphicsWindow::set_properties_now(properties); + + const char *target = "#canvas"; + + if (properties.has_size()) { + emscripten_set_canvas_element_size(target, properties.get_x_size(), properties.get_y_size()); + _properties.set_size(properties.get_size()); + properties.clear_size(); + set_size_and_recalc(_properties.get_x_size(), _properties.get_y_size()); + throw_event(get_window_event(), this); + } + + if (properties.has_fullscreen() && + properties.get_fullscreen() != _properties.get_fullscreen()) { + + if (properties.get_fullscreen()) { + EMSCRIPTEN_RESULT result = emscripten_request_fullscreen(target, true); + + if (result == EMSCRIPTEN_RESULT_SUCCESS) { + _properties.set_fullscreen(true); + properties.clear_fullscreen(); + + } else if (result == EMSCRIPTEN_RESULT_DEFERRED) { + // We can't switch to fullscreen just yet - this action is deferred + // until we're in an event handler. We can't know for sure yet that + // fullscreen will be supported, but we shouldn't report failure. + properties.clear_fullscreen(); + } + } else { + if (emscripten_exit_fullscreen() == EMSCRIPTEN_RESULT_SUCCESS) { + _properties.set_fullscreen(false); + properties.clear_fullscreen(); + } + } + } + + if (properties.has_mouse_mode() && + properties.get_mouse_mode() != _properties.get_mouse_mode()) { + + if (properties.get_mouse_mode() == WindowProperties::M_relative) { + EMSCRIPTEN_RESULT result = emscripten_request_pointerlock(target, true); + + if (result == EMSCRIPTEN_RESULT_SUCCESS) { + // Great, we're in pointerlock mode. + _properties.set_mouse_mode(WindowProperties::M_absolute); + _properties.set_cursor_hidden(true); + properties.clear_mouse_mode(); + + } else if (result == EMSCRIPTEN_RESULT_DEFERRED) { + // We can't switch to pointerlock just yet - this action is deferred + // until we're in an event handler. We can't know for sure yet that + // pointerlock will be supported, but we shouldn't report failure. + properties.clear_mouse_mode(); + if (properties.has_cursor_hidden() && properties.get_cursor_hidden()) { + properties.clear_cursor_hidden(); + } + } + } else { + if (emscripten_exit_pointerlock() == EMSCRIPTEN_RESULT_SUCCESS) { + _properties.set_mouse_mode(WindowProperties::M_absolute); + properties.clear_mouse_mode(); + properties.clear_cursor_hidden(); + } + } + } + + if (properties.has_cursor_hidden() && + properties.get_cursor_hidden() == (_properties.get_mouse_mode() == WindowProperties::M_relative)) { + // A hidden cursor comes for free with pointerlock. Without pointerlock, + // though, we can't hide the cursor. + properties.clear_cursor_hidden(); + } +} + +/** + * Closes the window right now. Called from the window thread. + */ +void WebGLGraphicsWindow:: +close_window() { + if (_gsg != nullptr) { + emscripten_webgl_make_context_current(0); + _gsg.clear(); + } + + // Clear the assigned callbacks. + const char *target = "#canvas"; + emscripten_set_fullscreenchange_callback(target, nullptr, false, nullptr); + emscripten_set_pointerlockchange_callback(target, nullptr, false, nullptr); + emscripten_set_visibilitychange_callback(nullptr, false, nullptr); + + emscripten_set_focus_callback(target, nullptr, false, nullptr); + emscripten_set_blur_callback(target, nullptr, false, nullptr); + + emscripten_set_keypress_callback(target, nullptr, false, nullptr); + emscripten_set_keydown_callback(target, nullptr, false, nullptr); + emscripten_set_keyup_callback(target, nullptr, false, nullptr); + + //emscripten_set_click_callback(target, nullptr, false, nullptr); + emscripten_set_mousedown_callback(target, nullptr, false, nullptr); + emscripten_set_mouseup_callback(target, nullptr, false, nullptr); + emscripten_set_mousemove_callback(target, nullptr, false, nullptr); + emscripten_set_mouseenter_callback(target, nullptr, false, nullptr); + emscripten_set_mouseleave_callback(target, nullptr, false, nullptr); + + emscripten_set_wheel_callback(target, nullptr, false, nullptr); + + GraphicsWindow::close_window(); +} + +/** + * Opens the window right now. Called from the window thread. Returns true + * if the window is successfully opened, or false if there was a problem. + */ +bool WebGLGraphicsWindow:: +open_window() { + //WebGLGraphicsPipe *webgl_pipe; + //DCAST_INTO_R(webgl_pipe, _pipe, false); + + const char *target = "#canvas"; + + // GSG Creation/Initialization + WebGLGraphicsStateGuardian *webgl_gsg; + if (_gsg == nullptr) { + // There is no old gsg. Create a new one. + webgl_gsg = new WebGLGraphicsStateGuardian(_engine, _pipe); + webgl_gsg->choose_pixel_format(_fb_properties, target); + _gsg = webgl_gsg; + } else { + // If the old gsg has the wrong pixel format, create a new one. + DCAST_INTO_R(webgl_gsg, _gsg, false); + //if (!webgl_gsg->_fb_properties.subsumes(_fb_properties)) { + // webgl_gsg = new WebGLGraphicsStateGuardian(_engine, _pipe); + // webgl_gsg->choose_pixel_format(_fb_properties, target); + // _gsg = webgl_gsg; + //} + } + + if (!webgl_gsg->_have_context) { + return false; + } + + if (_properties.has_size() && _properties.get_size() != LVecBase2i(1, 1)) { + emscripten_set_canvas_element_size(target, _properties.get_x_size(), _properties.get_y_size()); + } else { + int width, height; + emscripten_get_canvas_element_size(target, &width, &height); + _properties.set_size(width, height); + + EmscriptenFullscreenChangeEvent event; + emscripten_get_fullscreen_status(&event); + _properties.set_fullscreen(event.isFullscreen); + } + + _properties.set_undecorated(true); + + if (emscripten_webgl_make_context_current(webgl_gsg->_context) != EMSCRIPTEN_RESULT_SUCCESS) { + webgldisplay_cat.error() + << "Failed to make context current.\n"; + return false; + } + + webgl_gsg->reset(); + + _fb_properties.clear(); + _fb_properties.set_rgb_color(true); + _fb_properties.set_force_hardware(true); + _fb_properties.set_back_buffers(1); + + GLint red_bits, green_bits, blue_bits, alpha_bits, depth_bits, stencil_bits; + + glGetIntegerv(GL_RED_BITS, &red_bits); + glGetIntegerv(GL_GREEN_BITS, &green_bits); + glGetIntegerv(GL_BLUE_BITS, &blue_bits); + glGetIntegerv(GL_ALPHA_BITS, &alpha_bits); + glGetIntegerv(GL_DEPTH_BITS, &depth_bits); + glGetIntegerv(GL_STENCIL_BITS, &stencil_bits); + + _fb_properties.set_rgba_bits(red_bits, green_bits, blue_bits, alpha_bits); + _fb_properties.set_depth_bits(depth_bits); + _fb_properties.set_stencil_bits(stencil_bits); + + // Set callbacks. + emscripten_set_fullscreenchange_callback(target, (void *)this, false, &on_fullscreen_event); + emscripten_set_pointerlockchange_callback(target, (void *)this, false, &on_pointerlock_event); + emscripten_set_visibilitychange_callback((void *)this, false, &on_visibility_event); + + emscripten_set_focus_callback(target, (void *)this, false, &on_focus_event); + emscripten_set_blur_callback(target, (void *)this, false, &on_focus_event); + + void *user_data = _input; + emscripten_set_keypress_callback(target, user_data, false, &on_keyboard_event); + emscripten_set_keydown_callback(target, user_data, false, &on_keyboard_event); + emscripten_set_keyup_callback(target, user_data, false, &on_keyboard_event); + + //emscripten_set_click_callback(target, user_data, false, &on_mouse_event); + emscripten_set_mousedown_callback(target, user_data, false, &on_mouse_event); + emscripten_set_mouseup_callback(target, user_data, false, &on_mouse_event); + emscripten_set_mousemove_callback(target, user_data, false, &on_mouse_event); + emscripten_set_mouseenter_callback(target, user_data, false, &on_mouse_event); + emscripten_set_mouseleave_callback(target, user_data, false, &on_mouse_event); + + emscripten_set_wheel_callback(target, user_data, false, &on_wheel_event); + + return true; +} + +/** + * + */ +EM_BOOL WebGLGraphicsWindow:: +on_fullscreen_event(int type, const EmscriptenFullscreenChangeEvent *event, void *user_data) { + WebGLGraphicsWindow *window = (WebGLGraphicsWindow *)user_data; + nassertr(window != nullptr, false); + + if (type == EMSCRIPTEN_EVENT_FULLSCREENCHANGE) { + WindowProperties props; + props.set_fullscreen(event->isFullscreen); + window->system_changed_properties(props); + return true; + } + + return false; +} + +/** + * + */ +EM_BOOL WebGLGraphicsWindow:: +on_pointerlock_event(int type, const EmscriptenPointerlockChangeEvent *event, void *user_data) { + WebGLGraphicsWindow *window = (WebGLGraphicsWindow *)user_data; + nassertr(window != nullptr, false); + + if (type == EMSCRIPTEN_EVENT_POINTERLOCKCHANGE) { + WindowProperties props; + if (event->isActive) { + std::cout << "pointerlock engaged\n"; + props.set_mouse_mode(WindowProperties::M_relative); + props.set_cursor_hidden(true); + } else { + std::cout << "pointerlock disabled\n"; + props.set_mouse_mode(WindowProperties::M_absolute); + props.set_cursor_hidden(false); + } + window->system_changed_properties(props); + return true; + } + + return false; +} + +/** + * + */ +EM_BOOL WebGLGraphicsWindow:: +on_visibility_event(int type, const EmscriptenVisibilityChangeEvent *event, void *user_data) { + WebGLGraphicsWindow *window = (WebGLGraphicsWindow *)user_data; + nassertr(window != nullptr, false); + + if (type == EMSCRIPTEN_EVENT_VISIBILITYCHANGE) { + WindowProperties props; + props.set_minimized(event->hidden != 0); + window->system_changed_properties(props); + return true; + } + + return false; +} + +/** + * + */ +EM_BOOL WebGLGraphicsWindow:: +on_focus_event(int type, const EmscriptenFocusEvent *event, void *user_data) { + WebGLGraphicsWindow *window = (WebGLGraphicsWindow *)user_data; + nassertr(window != nullptr, false); + + if (type == EMSCRIPTEN_EVENT_FOCUS) { + WindowProperties props; + props.set_foreground(true); + window->system_changed_properties(props); + return true; + } else if (type == EMSCRIPTEN_EVENT_BLUR) { + WindowProperties props; + props.set_foreground(false); + window->system_changed_properties(props); + return true; + } + + return false; +} + +/** + * Handles HTML5 keypress, keydown and keyup events. + */ +EM_BOOL WebGLGraphicsWindow:: +on_keyboard_event(int type, const EmscriptenKeyboardEvent *event, void *user_data) { + GraphicsWindowInputDevice *device; + device = (GraphicsWindowInputDevice *)user_data; + nassertr(device != nullptr, false); + + if (type == EMSCRIPTEN_EVENT_KEYPRESS) { + // We have to use String.fromCharCode to turn this into a text character. + // When called from a key event, it does some special magic to ensure that + // it does the right thing. We grab the first unicode code point. + // Unfortunately, this doesn't seem to handle dead keys on Firefox. + int keycode = 0; + EM_ASM_({ + stringToUTF32(String.fromCharCode($0), $1, 4); + }, event->charCode, &keycode); + + if (keycode != 0) { + device->keystroke(keycode); + return true; + } + + } else if (type == EMSCRIPTEN_EVENT_KEYDOWN || + type == EMSCRIPTEN_EVENT_KEYUP) { + + ButtonHandle handle = map_key(event->which); + + // Send a raw event too, if the browser supports providing it. + ButtonHandle raw_handle; + if (event->code[0]) { + raw_handle = map_raw_key(event->code); + } else { + // This browser doesn't send raw events. Let's just pretend the user is + // using QWERTY. Better than nothing? + raw_handle = handle; + } + + if (raw_handle != ButtonHandle::none()) { + if (type == EMSCRIPTEN_EVENT_KEYUP) { + device->raw_button_up(raw_handle); + } else if (!event->repeat) { + device->raw_button_down(raw_handle); + } + } + + // Send a regular event for the 'virtual' key mapping. + if (handle != ButtonHandle::none()) { + if (type == EMSCRIPTEN_EVENT_KEYUP) { + //webgldisplay_cat.info() << "button up " << handle << "\n"; + device->button_up(handle); + } else if (event->repeat) { + device->button_resume_down(handle); + } else { + //webgldisplay_cat.info() << "button down " << handle << "\n"; + device->button_down(handle); + } + + // If we preventDefault a keydown event, its keypress event won't fire, + // which would prevent text input from working. However, we must still + // prevent the default action from working in backspace and tab events. + if (type == EMSCRIPTEN_EVENT_KEYDOWN && + event->keyCode != 8 && event->keyCode != 9) { + return false; + } else { + return true; + } + } else if (event->which != 0) { + webgldisplay_cat.info() + << "unhandled event code " << event->which << "\n"; + } + } + + return false; +} + +/** + * Handles mousedown, mouseup, mousemove, mouseenter and mouseleave events. + */ +EM_BOOL WebGLGraphicsWindow:: +on_mouse_event(int type, const EmscriptenMouseEvent *event, void *user_data) { + GraphicsWindowInputDevice *device; + device = (GraphicsWindowInputDevice *)user_data; + nassertr(device != nullptr, false); + + const char *target = "#canvas"; + + switch (type) { + case EMSCRIPTEN_EVENT_MOUSEDOWN: + // Don't register out-of-bounds mouse downs. + if (event->targetX >= 0 && event->targetY >= 0) { + int w, h; + emscripten_get_canvas_element_size(target, &w, &h); + if (event->targetX < w && event->targetY < h) { + device->button_down(MouseButton::button(event->button)); + return true; + } + } + return false; + + case EMSCRIPTEN_EVENT_MOUSEUP: + device->button_up(MouseButton::button(event->button)); + return true; + + case EMSCRIPTEN_EVENT_MOUSEMOVE: + { + EmscriptenPointerlockChangeEvent ev; + emscripten_get_pointerlock_status(&ev); + + if (ev.isActive) { + PointerData md = device->get_pointer(); + device->set_pointer_in_window(md.get_x() + event->movementX, + md.get_y() + event->movementY); + } else { + device->set_pointer_in_window(event->targetX, event->targetY); + } + } + return true; + + case EMSCRIPTEN_EVENT_MOUSEENTER: + break; + + case EMSCRIPTEN_EVENT_MOUSELEAVE: + device->set_pointer_out_of_window(); + return true; + + default: + break; + } + + return false; +} + +/** + * + */ +EM_BOOL WebGLGraphicsWindow:: +on_wheel_event(int type, const EmscriptenWheelEvent *event, void *user_data) { + GraphicsWindowInputDevice *device; + device = (GraphicsWindowInputDevice *)user_data; + nassertr(device != nullptr, false); + + if (type == EMSCRIPTEN_EVENT_WHEEL) { + if (event->deltaY < 0) { + device->button_down(MouseButton::wheel_up()); + device->button_up(MouseButton::wheel_up()); + } + if (event->deltaY > 0) { + device->button_down(MouseButton::wheel_down()); + device->button_up(MouseButton::wheel_down()); + } + return true; + } + + return false; +} + + +/** + * Maps a JavaScript event keycode to a ButtonHandle. + */ +ButtonHandle WebGLGraphicsWindow:: +map_key(int which) { + switch (which) { + case 8: + return KeyboardButton::backspace(); + case 9: + return KeyboardButton::tab(); + case 13: + return KeyboardButton::enter(); + case 16: + return KeyboardButton::shift(); + case 17: + return KeyboardButton::control(); + case 18: + return KeyboardButton::alt(); + case 19: + return KeyboardButton::pause(); + case 20: + return KeyboardButton::caps_lock(); + case 27: + return KeyboardButton::escape(); + case 32: + return KeyboardButton::space(); + case 33: + return KeyboardButton::page_up(); + case 34: + return KeyboardButton::page_down(); + case 35: + return KeyboardButton::end(); + case 36: + return KeyboardButton::home(); + case 37: + return KeyboardButton::left(); + case 38: + return KeyboardButton::up(); + case 39: + return KeyboardButton::right(); + case 40: + return KeyboardButton::down(); + case 42: + return KeyboardButton::print_screen(); + case 45: + return KeyboardButton::insert(); + case 46: + return KeyboardButton::del(); + case 48: + case 49: + case 50: + case 51: + case 52: + case 53: + case 54: + case 55: + case 56: + case 57: + return KeyboardButton::ascii_key('0' + (which - 48)); + case 59: + return KeyboardButton::ascii_key(';'); + case 61: + return KeyboardButton::ascii_key('='); + case 65: + case 66: + case 67: + case 68: + case 69: + case 70: + case 71: + case 72: + case 73: + case 74: + case 75: + case 76: + case 77: + case 78: + case 79: + case 80: + case 81: + case 82: + case 83: + case 84: + case 85: + case 86: + case 87: + case 88: + case 89: + case 90: + return KeyboardButton::ascii_key('a' + (which - 65)); + case 91: + return KeyboardButton::lmeta(); + case 92: + return KeyboardButton::rmeta(); + case 93: + return KeyboardButton::menu(); + case 96: + case 97: + case 98: + case 99: + case 100: + case 101: + case 102: + case 103: + case 104: + case 105: + return KeyboardButton::ascii_key('0' + (which - 96)); + case 106: + return KeyboardButton::ascii_key('*'); + case 107: + return KeyboardButton::ascii_key('+'); + case 109: + return KeyboardButton::ascii_key('-'); + case 110: + return KeyboardButton::ascii_key('.'); + case 111: + return KeyboardButton::ascii_key('/'); + case 112: + return KeyboardButton::f1(); + case 113: + return KeyboardButton::f2(); + case 114: + return KeyboardButton::f3(); + case 115: + return KeyboardButton::f4(); + case 116: + return KeyboardButton::f5(); + case 117: + return KeyboardButton::f6(); + case 118: + return KeyboardButton::f7(); + case 119: + return KeyboardButton::f8(); + case 120: + return KeyboardButton::f9(); + case 121: + return KeyboardButton::f10(); + case 122: + return KeyboardButton::f11(); + case 123: + return KeyboardButton::f12(); + case 144: + return KeyboardButton::num_lock(); + case 145: + return KeyboardButton::scroll_lock(); + case 173: + return KeyboardButton::ascii_key('-'); + case 186: + return KeyboardButton::ascii_key(';'); + case 187: + return KeyboardButton::ascii_key('='); + case 188: + return KeyboardButton::ascii_key(','); + case 189: + return KeyboardButton::ascii_key('-'); + case 190: + return KeyboardButton::ascii_key('.'); + case 191: + return KeyboardButton::ascii_key('?'); + case 192: + return KeyboardButton::ascii_key('`'); + case 219: + return KeyboardButton::ascii_key('['); + case 220: + return KeyboardButton::ascii_key('\\'); + case 221: + return KeyboardButton::ascii_key(']'); + case 222: + return KeyboardButton::ascii_key('\''); + default: + return ButtonHandle::none(); + } +} + +/** + * Maps a HTML5 KeyboardEvent.code string to a ButtonHandle. + */ +ButtonHandle WebGLGraphicsWindow:: +map_raw_key(const char *code) { + static struct { + const char *code; + ButtonHandle handle; + } mappings[] = { + //{"Again", KeyboardButton::()}, + {"AltLeft", KeyboardButton::lalt()}, + {"AltRight", KeyboardButton::ralt()}, + {"ArrowDown", KeyboardButton::down()}, + {"ArrowLeft", KeyboardButton::left()}, + {"ArrowRight", KeyboardButton::right()}, + {"ArrowUp", KeyboardButton::up()}, + {"Backquote", KeyboardButton::ascii_key('`')}, + {"Backslash", KeyboardButton::ascii_key('\\')}, + {"Backspace", KeyboardButton::backspace()}, + {"BracketLeft", KeyboardButton::ascii_key('[')}, + {"BracketRight", KeyboardButton::ascii_key(']')}, + //{"BrowserBack", KeyboardButton::()}, + //{"BrowserFavorites", KeyboardButton::()}, + //{"BrowserForward", KeyboardButton::()}, + //{"BrowserRefresh", KeyboardButton::()}, + //{"BrowserSearch", KeyboardButton::()}, + //{"BrowserStop", KeyboardButton::()}, + {"CapsLock", KeyboardButton::caps_lock()}, + {"Comma", KeyboardButton::ascii_key(',')}, + {"ContextMenu", KeyboardButton::menu()}, + {"ControlLeft", KeyboardButton::lcontrol()}, + {"ControlRight", KeyboardButton::rcontrol()}, + //{"Convert", KeyboardButton::()}, + //{"Copy", KeyboardButton::()}, + //{"Cut", KeyboardButton::()}, + {"Delete", KeyboardButton::del()}, + {"Digit0", KeyboardButton::ascii_key('0')}, + {"Digit1", KeyboardButton::ascii_key('1')}, + {"Digit2", KeyboardButton::ascii_key('2')}, + {"Digit3", KeyboardButton::ascii_key('3')}, + {"Digit4", KeyboardButton::ascii_key('4')}, + {"Digit5", KeyboardButton::ascii_key('5')}, + {"Digit6", KeyboardButton::ascii_key('6')}, + {"Digit7", KeyboardButton::ascii_key('7')}, + {"Digit8", KeyboardButton::ascii_key('8')}, + {"Digit9", KeyboardButton::ascii_key('9')}, + //{"Eject", KeyboardButton::()}, + {"End", KeyboardButton::end()}, + {"Enter", KeyboardButton::enter()}, + {"Equal", KeyboardButton::ascii_key('=')}, + {"Escape", KeyboardButton::escape()}, + {"F1", KeyboardButton::f1()}, + {"F10", KeyboardButton::f10()}, + {"F11", KeyboardButton::f11()}, + {"F12", KeyboardButton::f12()}, + {"F13", KeyboardButton::f13()}, + {"F14", KeyboardButton::f14()}, + {"F15", KeyboardButton::f15()}, + {"F16", KeyboardButton::f16()}, + //{"F17", KeyboardButton::f17()}, + //{"F18", KeyboardButton::f18()}, + //{"F19", KeyboardButton::f19()}, + {"F2", KeyboardButton::f2()}, + //{"F20", KeyboardButton::f20()}, + //{"F21", KeyboardButton::f21()}, + //{"F22", KeyboardButton::f22()}, + //{"F23", KeyboardButton::f23()}, + //{"F24", KeyboardButton::f24()}, + {"F3", KeyboardButton::f3()}, + {"F4", KeyboardButton::f4()}, + {"F5", KeyboardButton::f5()}, + {"F6", KeyboardButton::f6()}, + {"F7", KeyboardButton::f7()}, + {"F8", KeyboardButton::f8()}, + {"F9", KeyboardButton::f9()}, + //{"Find", KeyboardButton::()}, + //{"Fn", KeyboardButton::()}, + {"Help", KeyboardButton::help()}, + {"Home", KeyboardButton::home()}, + {"Insert", KeyboardButton::insert()}, + //{"IntlBackslash", KeyboardButton::()}, + //{"IntlRo", KeyboardButton::()}, + //{"IntlYen", KeyboardButton::()}, + //{"KanaMode", KeyboardButton::()}, + {"KeyA", KeyboardButton::ascii_key('a')}, + {"KeyB", KeyboardButton::ascii_key('b')}, + {"KeyC", KeyboardButton::ascii_key('c')}, + {"KeyD", KeyboardButton::ascii_key('d')}, + {"KeyE", KeyboardButton::ascii_key('e')}, + {"KeyF", KeyboardButton::ascii_key('f')}, + {"KeyG", KeyboardButton::ascii_key('g')}, + {"KeyH", KeyboardButton::ascii_key('h')}, + {"KeyI", KeyboardButton::ascii_key('i')}, + {"KeyJ", KeyboardButton::ascii_key('j')}, + {"KeyK", KeyboardButton::ascii_key('k')}, + {"KeyL", KeyboardButton::ascii_key('l')}, + {"KeyM", KeyboardButton::ascii_key('m')}, + {"KeyN", KeyboardButton::ascii_key('n')}, + {"KeyO", KeyboardButton::ascii_key('o')}, + {"KeyP", KeyboardButton::ascii_key('p')}, + {"KeyQ", KeyboardButton::ascii_key('q')}, + {"KeyR", KeyboardButton::ascii_key('r')}, + {"KeyS", KeyboardButton::ascii_key('s')}, + {"KeyT", KeyboardButton::ascii_key('t')}, + {"KeyU", KeyboardButton::ascii_key('u')}, + {"KeyV", KeyboardButton::ascii_key('v')}, + {"KeyW", KeyboardButton::ascii_key('w')}, + {"KeyX", KeyboardButton::ascii_key('x')}, + {"KeyY", KeyboardButton::ascii_key('y')}, + {"KeyZ", KeyboardButton::ascii_key('z')}, + //{"Lang1", KeyboardButton::()}, + //{"Lang2", KeyboardButton::()}, + //{"LaunchApp1", KeyboardButton::()}, + //{"MediaPlayPause", KeyboardButton::()}, + //{"MediaStop", KeyboardButton::()}, + //{"MediaTrackNext", KeyboardButton::()}, + //{"MediaTrackPrevious", KeyboardButton::()}, + {"Minus", KeyboardButton::ascii_key('-')}, + //{"NonConvert", KeyboardButton::()}, + {"NumLock", KeyboardButton::num_lock()}, + {"Numpad0", KeyboardButton::ascii_key('0')}, + {"Numpad1", KeyboardButton::ascii_key('1')}, + {"Numpad2", KeyboardButton::ascii_key('2')}, + {"Numpad3", KeyboardButton::ascii_key('3')}, + {"Numpad4", KeyboardButton::ascii_key('4')}, + {"Numpad5", KeyboardButton::ascii_key('5')}, + {"Numpad6", KeyboardButton::ascii_key('6')}, + {"Numpad7", KeyboardButton::ascii_key('7')}, + {"Numpad8", KeyboardButton::ascii_key('8')}, + {"Numpad9", KeyboardButton::ascii_key('9')}, + {"NumpadAdd", KeyboardButton::ascii_key('+')}, + {"NumpadComma", KeyboardButton::ascii_key(',')}, + {"NumpadDecimal", KeyboardButton::ascii_key('.')}, + {"NumpadDivide", KeyboardButton::ascii_key('/')}, + {"NumpadEnter", KeyboardButton::enter()}, + {"NumpadEqual", KeyboardButton::ascii_key('=')}, + {"NumpadMultiply", KeyboardButton::ascii_key('*')}, + {"NumpadSubtract", KeyboardButton::ascii_key('-')}, + //{"Open", KeyboardButton::()}, + {"OSLeft", KeyboardButton::lmeta()}, + {"OSRight", KeyboardButton::rmeta()}, + {"PageDown", KeyboardButton::page_down()}, + {"PageUp", KeyboardButton::page_up()}, + //{"Paste", KeyboardButton::()}, + {"Pause", KeyboardButton::pause()}, + {"Period", KeyboardButton::ascii_key('.')}, + //{"Power", KeyboardButton::()}, + {"PrintScreen", KeyboardButton::print_screen()}, + //{"Props", KeyboardButton::()}, + {"Quote", KeyboardButton::ascii_key('\'')}, + {"ScrollLock", KeyboardButton::scroll_lock()}, + //{"Select", KeyboardButton::()}, + {"Semicolon", KeyboardButton::ascii_key(';')}, + {"ShiftLeft", KeyboardButton::lshift()}, + {"ShiftRight", KeyboardButton::rshift()}, + {"Slash", KeyboardButton::ascii_key('/')}, + //{"Sleep", KeyboardButton::()}, + {"Space", KeyboardButton::ascii_key(' ')}, + {"Tab", KeyboardButton::tab()}, + //{"Undo", KeyboardButton::()}, + //{"VolumeDown", KeyboardButton::()}, + //{"VolumeMute", KeyboardButton::()}, + //{"VolumeUp", KeyboardButton::()}, + //{"WakeUp", KeyboardButton::()}, + {nullptr, ButtonHandle::none()} + }; + + for (int i = 0; mappings[i].code; ++i) { + int cmp = strcmp(mappings[i].code, code); + if (cmp == 0) { + return mappings[i].handle; + } else if (cmp > 0) { + // They're in alphabetical order, and we've passed it by, so bail early. + return ButtonHandle::none(); + } + } + + return ButtonHandle::none(); +} diff --git a/panda/src/webgldisplay/webGLGraphicsWindow.h b/panda/src/webgldisplay/webGLGraphicsWindow.h new file mode 100644 index 0000000000..16535cc730 --- /dev/null +++ b/panda/src/webgldisplay/webGLGraphicsWindow.h @@ -0,0 +1,87 @@ +/** + * PANDA 3D SOFTWARE + * Copyright (c) Carnegie Mellon University. All rights reserved. + * + * All use of this software is subject to the terms of the revised BSD + * license. You should have received a copy of this license along + * with this source code in a file named "LICENSE." + * + * @file webGLGraphicsWindow.h + * @author rdb + * @date 2015-03-31 + */ + +#ifndef WEBGLGRAPHICSWINDOW_H +#define WEBGLGRAPHICSWINDOW_H + +#include "pandabase.h" + +#include "webGLGraphicsPipe.h" +#include "graphicsWindow.h" + +#include + +/** + * An interface to Emscripten's WebGL interface that represents an HTML5 + * canvas. + */ +class WebGLGraphicsWindow : public GraphicsWindow { +public: + WebGLGraphicsWindow(GraphicsEngine *engine, GraphicsPipe *pipe, + const std::string &name, + const FrameBufferProperties &fb_prop, + const WindowProperties &win_prop, + int flags, + GraphicsStateGuardian *gsg, + GraphicsOutput *host); + virtual ~WebGLGraphicsWindow(); + + virtual bool move_pointer(int device, int x, int y); + virtual bool begin_frame(FrameMode mode, Thread *current_thread); + virtual void end_frame(FrameMode mode, Thread *current_thread); + virtual void end_flip(); + + virtual void process_events(); + virtual void set_properties_now(WindowProperties &properties); + +protected: + virtual void close_window(); + virtual bool open_window(); + +private: + static EM_BOOL on_fullscreen_event(int type, const EmscriptenFullscreenChangeEvent *event, void *user_data); + static EM_BOOL on_pointerlock_event(int type, const EmscriptenPointerlockChangeEvent *event, void *user_data); + static EM_BOOL on_visibility_event(int type, const EmscriptenVisibilityChangeEvent *event, void *user_data); + static EM_BOOL on_focus_event(int type, const EmscriptenFocusEvent *event, void *user_data); + static EM_BOOL on_keyboard_event(int type, const EmscriptenKeyboardEvent *event, void *user_data); + static EM_BOOL on_mouse_event(int type, const EmscriptenMouseEvent *event, void *user_data); + static EM_BOOL on_wheel_event(int type, const EmscriptenWheelEvent *event, void *user_data); + + static ButtonHandle map_key(int which); + static ButtonHandle map_raw_key(const char *code); + + std::string _canvas_id; + + GraphicsWindowInputDevice *_input; + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + GraphicsWindow::init_type(); + register_type(_type_handle, "WebGLGraphicsWindow", + GraphicsWindow::get_class_type()); + } + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + +private: + static TypeHandle _type_handle; +}; + +#include "webGLGraphicsWindow.I" + +#endif diff --git a/panda/src/wgldisplay/wglGraphicsStateGuardian.cxx b/panda/src/wgldisplay/wglGraphicsStateGuardian.cxx index 77521e2ff3..72c116b94b 100644 --- a/panda/src/wgldisplay/wglGraphicsStateGuardian.cxx +++ b/panda/src/wgldisplay/wglGraphicsStateGuardian.cxx @@ -336,6 +336,8 @@ choose_pixel_format(const FrameBufferProperties &properties, _supports_pixel_format = has_extension("WGL_ARB_pixel_format"); _supports_wgl_multisample = has_extension("WGL_ARB_multisample"); + bool supports_pixel_format_float = _supports_pixel_format && has_extension("WGL_ARB_pixel_format_float"); + if (has_extension("WGL_ARB_create_context")) { _wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress("wglCreateContextAttribsARB"); @@ -381,6 +383,10 @@ choose_pixel_format(const FrameBufferProperties &properties, iattrib_list[ni++] = WGL_PIXEL_TYPE_ARB; iattrib_list[ni++] = WGL_TYPE_RGBA_ARB; } + else if (supports_pixel_format_float) { + iattrib_list[ni++] = WGL_PIXEL_TYPE_ARB; + iattrib_list[ni++] = WGL_TYPE_RGBA_FLOAT_ARB; + } if (need_pbuffer) { iattrib_list[ni++] = WGL_DRAW_TO_PBUFFER_ARB; diff --git a/panda/src/windisplay/winDetectDx.h b/panda/src/windisplay/winDetectDx.h index a6da2e143f..4b659cb135 100644 --- a/panda/src/windisplay/winDetectDx.h +++ b/panda/src/windisplay/winDetectDx.h @@ -99,7 +99,6 @@ static int get_display_information (DisplaySearchParameters &display_search_para int success; DisplayInformation::DetectionState state; - int get_adapter_display_mode_state; int get_device_caps_state; GraphicsStateGuardian::ShaderModel shader_model; @@ -117,6 +116,7 @@ static int get_display_information (DisplaySearchParameters &display_search_para int window_height; int window_bits_per_pixel; int total_display_modes; + int current_display_mode_index; DisplayMode *display_mode_array; uint64_t physical_memory; @@ -139,6 +139,7 @@ static int get_display_information (DisplaySearchParameters &display_search_para window_height = 0; window_bits_per_pixel = 0; total_display_modes = 0; + current_display_mode_index = -1; display_mode_array = nullptr; minimum_width = display_search_parameters._minimum_width; @@ -153,7 +154,6 @@ static int get_display_information (DisplaySearchParameters &display_search_para texture_memory = 0; state = DisplayInformation::DS_unknown; - get_adapter_display_mode_state = false; get_device_caps_state = false; physical_memory = 0; @@ -193,6 +193,7 @@ static int get_display_information (DisplaySearchParameters &display_search_para device_type = D3DDEVTYPE_HAL; // windowed mode max res and format + bool get_adapter_display_mode_state = false; if (direct_3d -> GetAdapterDisplayMode (adapter, ¤t_d3d_display_mode) == D3D_OK) { if (debug) { printf ("current mode w = %d h = %d r = %d f = %d \n", @@ -428,6 +429,14 @@ static int get_display_information (DisplaySearchParameters &display_search_para display_mode -> refresh_rate = d3d_display_mode.RefreshRate; display_mode -> fullscreen_only = display_format_array [format_index].fullscreen_only; + if (get_adapter_display_mode_state && + d3d_display_mode.Width == current_d3d_display_mode.Width && + d3d_display_mode.Height == current_d3d_display_mode.Height && + d3d_display_mode.RefreshRate == current_d3d_display_mode.RefreshRate && + d3d_display_mode.Format == current_d3d_display_mode.Format) { + current_display_mode_index = total_display_modes; + } + total_display_modes++; } } @@ -587,7 +596,7 @@ static int get_display_information (DisplaySearchParameters &display_search_para if (success) { display_information -> _state = state; - display_information -> _get_adapter_display_mode_state = get_adapter_display_mode_state; + display_information -> _current_display_mode_index = current_display_mode_index; display_information -> _get_device_caps_state = get_device_caps_state; display_information -> _maximum_window_width = window_width; display_information -> _maximum_window_height = window_height; diff --git a/panda/src/windisplay/winGraphicsPipe.cxx b/panda/src/windisplay/winGraphicsPipe.cxx index 28787c43b3..428040f0f6 100644 --- a/panda/src/windisplay/winGraphicsPipe.cxx +++ b/panda/src/windisplay/winGraphicsPipe.cxx @@ -328,9 +328,21 @@ WinGraphicsPipe() { if (windisplay_cat.is_debug()) { windisplay_cat.debug() << "Using EnumDisplaySettings to fetch display information.\n"; } + pvector display_modes; + DisplayMode current_mode = {0}; + int current_mode_index = -1; DEVMODE dm{}; dm.dmSize = sizeof(dm); + + if (EnumDisplaySettings(nullptr, ENUM_CURRENT_SETTINGS, &dm) != 0) { + current_mode.width = dm.dmPelsWidth; + current_mode.height = dm.dmPelsHeight; + current_mode.bits_per_pixel = dm.dmBitsPerPel; + current_mode.refresh_rate = dm.dmDisplayFrequency; + current_mode.fullscreen_only = 0; + } + for (int i = 0; EnumDisplaySettings(nullptr, i, &dm) != 0; ++i) { DisplayMode mode; mode.width = dm.dmPelsWidth; @@ -339,6 +351,9 @@ WinGraphicsPipe() { mode.refresh_rate = dm.dmDisplayFrequency; mode.fullscreen_only = 0; if (i == 0 || mode != display_modes.back()) { + if (current_mode_index < 0 && mode == current_mode) { + current_mode_index = (int)display_modes.size(); + } display_modes.push_back(mode); } } @@ -346,6 +361,7 @@ WinGraphicsPipe() { // Copy this information to the DisplayInformation object. _display_information->_total_display_modes = display_modes.size(); if (!display_modes.empty()) { + _display_information->_current_display_mode_index = current_mode_index; _display_information->_display_mode_array = new DisplayMode[display_modes.size()]; std::copy(display_modes.begin(), display_modes.end(), _display_information->_display_mode_array); diff --git a/panda/src/windisplay/winGraphicsWindow.cxx b/panda/src/windisplay/winGraphicsWindow.cxx index 224ef26b4e..05b769bb3b 100644 --- a/panda/src/windisplay/winGraphicsWindow.cxx +++ b/panda/src/windisplay/winGraphicsWindow.cxx @@ -676,18 +676,18 @@ initialize_input_devices() { _input = device; // Get the number of devices. - if (GetRawInputDeviceList(nullptr, &nInputDevices, sizeof(RAWINPUTDEVICELIST)) != 0) { + if ((int)GetRawInputDeviceList(nullptr, &nInputDevices, sizeof(RAWINPUTDEVICELIST)) != 0) { return; } // Allocate the array to hold the DeviceList pRawInputDeviceList = (PRAWINPUTDEVICELIST)alloca(sizeof(RAWINPUTDEVICELIST) * nInputDevices); - if (pRawInputDeviceList==0) { + if (pRawInputDeviceList == nullptr) { return; } // Fill the Array - if (GetRawInputDeviceList(pRawInputDeviceList, &nInputDevices, sizeof(RAWINPUTDEVICELIST)) == -1) { + if ((int)GetRawInputDeviceList(pRawInputDeviceList, &nInputDevices, sizeof(RAWINPUTDEVICELIST)) == -1) { return; } @@ -696,13 +696,13 @@ initialize_input_devices() { if (pRawInputDeviceList[i].dwType == RIM_TYPEMOUSE) { // Fetch information about specified mouse device. UINT nSize; - if (GetRawInputDeviceInfoA(pRawInputDeviceList[i].hDevice, RIDI_DEVICENAME, (LPVOID)0, &nSize) != 0) { - return; + if ((int)GetRawInputDeviceInfoA(pRawInputDeviceList[i].hDevice, RIDI_DEVICENAME, (LPVOID)nullptr, &nSize) != 0) { + continue; } char *psName = (char*)alloca(sizeof(TCHAR) * nSize); - if (psName == 0) return; - if (GetRawInputDeviceInfoA(pRawInputDeviceList[i].hDevice, RIDI_DEVICENAME, (LPVOID)psName, &nSize) < 0) { - return; + if (psName == nullptr) continue; + if ((int)GetRawInputDeviceInfoA(pRawInputDeviceList[i].hDevice, RIDI_DEVICENAME, (LPVOID)psName, &nSize) < 0) { + continue; } // If it's not an RDP mouse, add it to the list of raw mice. diff --git a/panda/src/x11display/x11GraphicsPipe.cxx b/panda/src/x11display/x11GraphicsPipe.cxx index bfbacfc972..1f74c64fdb 100644 --- a/panda/src/x11display/x11GraphicsPipe.cxx +++ b/panda/src/x11display/x11GraphicsPipe.cxx @@ -283,11 +283,25 @@ x11GraphicsPipe(const std::string &display) : x11display_cat.debug() << "Using XRRScreenResources to obtain display modes\n"; } + + // Query current configuration, we just grab the first CRTC for now, + // since we don't have a way to represent multiple monitors. + RRMode current_mode_id = 0; + if (res->ncrtc > 0) { + if (auto info = get_crtc_info(res.get(), res->crtcs[0])) { + current_mode_id = info->mode; + } + } + _display_information->_total_display_modes = res->nmode; _display_information->_display_mode_array = new DisplayMode[res->nmode]; for (int i = 0; i < res->nmode; ++i) { XRRModeInfo &mode = res->modes[i]; + if (mode.id == current_mode_id) { + _display_information->_current_display_mode_index = i; + } + DisplayMode *dm = _display_information->_display_mode_array + i; dm->width = mode.width; dm->height = mode.height; diff --git a/pandatool/CMakeLists.txt b/pandatool/CMakeLists.txt index d3f6347736..3ebe06ac35 100644 --- a/pandatool/CMakeLists.txt +++ b/pandatool/CMakeLists.txt @@ -28,6 +28,7 @@ add_subdirectory(src/imageprogs) add_subdirectory(src/lwo) add_subdirectory(src/lwoegg) add_subdirectory(src/lwoprogs) +add_subdirectory(src/mac-stats) add_subdirectory(src/miscprogs) add_subdirectory(src/objegg) add_subdirectory(src/objprogs) diff --git a/pandatool/src/assimp/loaderFileTypeAssimp.cxx b/pandatool/src/assimp/loaderFileTypeAssimp.cxx index f19ce58e2f..bd3061f250 100644 --- a/pandatool/src/assimp/loaderFileTypeAssimp.cxx +++ b/pandatool/src/assimp/loaderFileTypeAssimp.cxx @@ -57,22 +57,49 @@ get_extension() const { */ string LoaderFileTypeAssimp:: get_additional_extensions() const { + // This may be called at static init time, so ensure it is constructed now. + static ConfigVariableString assimp_disable_extensions + ("assimp-disable-extensions", "gltf glb", + PRC_DESC("A list of extensions (without preceding dot) that should not be " + "loaded via the Assimp loader, even if Assimp supports these " + "formats. It is useful to set this for eg. gltf and glb files " + "to prevent them from being accidentally loaded via the Assimp " + "plug-in instead of via a superior plug-in like panda3d-gltf.")); + + bool has_disabled_exts = !assimp_disable_extensions.empty(); + aiString aexts; aiGetExtensionList(&aexts); + char *buffer = (char *)alloca(aexts.length + 2); + char *p = buffer; + // The format is like: *.mdc;*.mdl;*.mesh.xml;*.mot - std::string ext; char *sub = strtok(aexts.data, ";"); while (sub != nullptr) { - ext += sub + 2; - sub = strtok(nullptr, ";"); - - if (sub != nullptr) { - ext += ' '; + bool enabled = true; + if (has_disabled_exts) { + for (size_t i = 0; i < assimp_disable_extensions.get_num_words(); ++i) { + std::string disabled_ext = assimp_disable_extensions.get_word(i); + if (strcmp(sub + 2, disabled_ext.c_str()) == 0) { + enabled = false; + break; + } + } } + if (enabled) { + *(p++) = ' '; + size_t len = strlen(sub + 2); + memcpy(p, sub + 2, len); + p += len; + } + + sub = strtok(nullptr, ";"); } - return ext; + // Strip first space + ++buffer; + return std::string(buffer, p - buffer); } /** diff --git a/pandatool/src/daeegg/daeCharacter.cxx b/pandatool/src/daeegg/daeCharacter.cxx index a73071d9d4..57c048fc4a 100644 --- a/pandatool/src/daeegg/daeCharacter.cxx +++ b/pandatool/src/daeegg/daeCharacter.cxx @@ -40,12 +40,11 @@ TypeHandle DaeCharacter::_type_handle; DaeCharacter:: DaeCharacter(EggGroup *node_group, const FCDControllerInstance *instance) : _node_group(node_group), - _name(node_group->get_name()), + _skin_mesh(nullptr), _instance(instance), - _skin_controller(nullptr), - _skin_mesh(nullptr) { - - _bind_shape_mat = LMatrix4d::ident_mat(); + _bind_shape_mat(LMatrix4d::ident_mat()), + _name(node_group->get_name()), + _skin_controller(nullptr) { // If it's a skin controller, add the controller joints. const FCDController *controller = (const FCDController *)instance->GetEntity(); diff --git a/pandatool/src/deploy-stub/android_log.c b/pandatool/src/deploy-stub/android_log.c index 209515f90d..83b6090111 100644 --- a/pandatool/src/deploy-stub/android_log.c +++ b/pandatool/src/deploy-stub/android_log.c @@ -28,11 +28,9 @@ _py_write(PyObject *self, PyObject *args) { char *text; if (PyArg_ParseTuple(args, "iss", &prio, &tag, &text)) { __android_log_write(prio, tag, text); - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } return NULL; - } static PyMethodDef python_simple_funcs[] = { diff --git a/pandatool/src/deploy-stub/deploy-stub.c b/pandatool/src/deploy-stub/deploy-stub.c index 484b08d159..7e0b22464d 100644 --- a/pandatool/src/deploy-stub/deploy-stub.c +++ b/pandatool/src/deploy-stub/deploy-stub.c @@ -321,7 +321,9 @@ static int setup_logging(const char *path, int append) { dup2(fd, 1); dup2(fd, 2); - close(fd); + if (close(fd) < 0) { + perror("setup_logging: close"); + } return 1; #endif } diff --git a/pandatool/src/egg-palettize/txaFileFilter.cxx b/pandatool/src/egg-palettize/txaFileFilter.cxx index c877d667ab..d45bea3b81 100644 --- a/pandatool/src/egg-palettize/txaFileFilter.cxx +++ b/pandatool/src/egg-palettize/txaFileFilter.cxx @@ -92,7 +92,7 @@ post_load(Texture *tex) { egg_tex->set_alpha_mode(tex_image.get_alpha_mode()); egg_tex->set_format(props._format); egg_tex->set_minfilter(props._minfilter); - egg_tex->set_minfilter(props._magfilter); + egg_tex->set_magfilter(props._magfilter); egg_tex->set_anisotropic_degree(props._anisotropic_degree); tex->set_aux_data("egg", egg_tex); diff --git a/pandatool/src/eggprogs/eggRename.cxx b/pandatool/src/eggprogs/eggRename.cxx index 532f096dbb..6b2c98698b 100644 --- a/pandatool/src/eggprogs/eggRename.cxx +++ b/pandatool/src/eggprogs/eggRename.cxx @@ -37,11 +37,11 @@ run() { if (!_strip_prefix.empty()) { nout << "Stripping prefix from nodes.\n"; int num_renamed = 0; - int num_egg_files = 0; + //int num_egg_files = 0; Eggs::iterator ei; for (ei = _eggs.begin(); ei != _eggs.end(); ++ei) { num_renamed += (*ei)->rename_nodes(_strip_prefix, true); - ++num_egg_files; + //++num_egg_files; } nout << " (" << num_renamed << " renamed.)\n"; } diff --git a/pandatool/src/gtk-stats/CMakeLists.txt b/pandatool/src/gtk-stats/CMakeLists.txt index 26b4dd0372..2305c59404 100644 --- a/pandatool/src/gtk-stats/CMakeLists.txt +++ b/pandatool/src/gtk-stats/CMakeLists.txt @@ -34,7 +34,7 @@ target_link_libraries(gtk-stats p3progbase p3pstatserver PKG::GTK3) # This program is NOT actually called gtk-stats. It's pstats-gtk on Win32 and # pstats everywhere else (as the Win32 GUI is not built). -if(WIN32) +if(WIN32 OR APPLE) set_target_properties(gtk-stats PROPERTIES OUTPUT_NAME "pstats-gtk") else() set_target_properties(gtk-stats PROPERTIES OUTPUT_NAME "pstats") diff --git a/pandatool/src/gtk-stats/gtkStatsMonitor.cxx b/pandatool/src/gtk-stats/gtkStatsMonitor.cxx index 8373720f90..0410504457 100644 --- a/pandatool/src/gtk-stats/gtkStatsMonitor.cxx +++ b/pandatool/src/gtk-stats/gtkStatsMonitor.cxx @@ -60,8 +60,9 @@ close() { remove_all_graphs(); - for (GtkWidget *label : _status_bar_labels) { - gtk_container_remove(GTK_CONTAINER(_status_bar), label); + for (GtkWidget *flow_box_child : _status_bar_labels) { + gtk_container_remove(GTK_CONTAINER(_status_bar), flow_box_child); + g_object_unref(flow_box_child); } _status_bar_collectors.clear(); _status_bar_labels.clear(); @@ -160,11 +161,6 @@ new_collector(int collector_index) { for (GtkStatsGraph *graph : _graphs) { graph->new_collector(collector_index); } - - // We might need to update our menus. - for (GtkStatsChartMenu *chart_menu : _chart_menus) { - chart_menu->check_update(); - } } /** @@ -190,6 +186,8 @@ new_thread(int thread_index) { */ void GtkStatsMonitor:: new_data(int thread_index, int frame_number) { + PStatMonitor::new_data(thread_index, frame_number); + for (GtkStatsGraph *graph : _graphs) { graph->new_data(thread_index, frame_number); } @@ -255,7 +253,8 @@ idle() { gtk_label_set_text(GTK_LABEL(_frame_rate_label), buffer); if (!_status_bar_labels.empty()) { - gtk_label_set_text(GTK_LABEL(_status_bar_labels[0]), buffer); + GtkWidget *label = gtk_bin_get_child(GTK_BIN(_status_bar_labels[0])); + gtk_label_set_text(GTK_LABEL(label), buffer); } } } @@ -610,9 +609,16 @@ update_status_bar() { size_t li = 1; collectors.push_back(0); if (_status_bar_labels.empty()) { + // As workaround for https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/2029 + // We manually create a GtkFlowBoxChild instance and attach the label to it + // and increase its reference count so it it not prematurely destroyed when + // removed from the GtkFlowBox, causing the app to segfault. GtkWidget *label = gtk_label_new(""); - gtk_container_add(GTK_CONTAINER(_status_bar), label); - _status_bar_labels.push_back(label); + GtkWidget *flow_box_child = gtk_flow_box_child_new(); + gtk_container_add(GTK_CONTAINER(flow_box_child), label); + gtk_container_add(GTK_CONTAINER(_status_bar), flow_box_child); + _status_bar_labels.push_back(flow_box_child); + g_object_ref(flow_box_child); } // Gather the top-level collector list. @@ -642,15 +648,21 @@ update_status_bar() { std::string text = def._name; text += ": " + PStatGraph::format_number(value, PStatGraph::GBU_named | PStatGraph::GBU_show_units, def._level_units); + GtkWidget *flow_box_child; GtkWidget *label; if (li < _status_bar_labels.size()) { - label = _status_bar_labels[li++]; + flow_box_child = _status_bar_labels[li++]; + label = gtk_bin_get_child(GTK_BIN(flow_box_child)); gtk_label_set_text(GTK_LABEL(label), text.c_str()); } else { label = gtk_label_new(text.c_str()); - gtk_container_add(GTK_CONTAINER(_status_bar), label); - _status_bar_labels.push_back(label); + // See comment above + flow_box_child = gtk_flow_box_child_new(); + gtk_container_add(GTK_CONTAINER(flow_box_child), label); + gtk_container_add(GTK_CONTAINER(_status_bar), flow_box_child); + _status_bar_labels.push_back(flow_box_child); + g_object_ref(flow_box_child); } collectors.push_back(collector); @@ -740,7 +752,8 @@ status_bar_button_event(GtkWidget *widget, GdkEventButton *event, gpointer data) gtk_widget_show_all(menu); - GtkWidget *label = monitor->_status_bar_labels[index]; + GtkWidget *flow_box_child = monitor->_status_bar_labels[index]; + GtkWidget *label = gtk_bin_get_child(GTK_BIN(flow_box_child)); gtk_menu_popup_at_widget(GTK_MENU(menu), label, GDK_GRAVITY_NORTH_WEST, GDK_GRAVITY_SOUTH_WEST, nullptr); @@ -858,7 +871,8 @@ handle_status_bar_popup(int item) { gtk_widget_show_all(menu); - GtkWidget *label = _status_bar_labels[item]; + GtkWidget *flow_box_child = _status_bar_labels[item]; + GtkWidget *label = gtk_bin_get_child(GTK_BIN(flow_box_child)); gtk_menu_popup_at_widget(GTK_MENU(menu), label, GDK_GRAVITY_NORTH_WEST, GDK_GRAVITY_SOUTH_WEST, nullptr); diff --git a/pandatool/src/gtk-stats/gtkStatsServer.cxx b/pandatool/src/gtk-stats/gtkStatsServer.cxx index ce7f99e1e9..25fdba2ee9 100644 --- a/pandatool/src/gtk-stats/gtkStatsServer.cxx +++ b/pandatool/src/gtk-stats/gtkStatsServer.cxx @@ -123,6 +123,7 @@ make_monitor(const NetAddress &address) { if (_status_bar_label != nullptr) { gtk_container_remove(GTK_CONTAINER(_status_bar), _status_bar_label); + g_object_unref(_status_bar_label); _status_bar_label = nullptr; } @@ -177,9 +178,16 @@ new_session() { std::ostringstream strm; strm << "Waiting for client to connect on port " << _port << "..."; std::string title = strm.str(); - _status_bar_label = gtk_label_new(title.c_str()); + // As workaround for https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/2029 + // We manually create a GtkFlowBoxChild instance and attach the label to it + // and increase its reference count so it it not prematurely destroyed when + // removed from the GtkFlowBox, causing the app to segfault. + GtkWidget * label = gtk_label_new(title.c_str()); + _status_bar_label = gtk_flow_box_child_new(); + gtk_container_add(GTK_CONTAINER(_status_bar_label), label); gtk_container_add(GTK_CONTAINER(_status_bar), _status_bar_label); gtk_widget_show(_status_bar_label); + g_object_ref(_status_bar_label); } gtk_widget_set_sensitive(_new_session_menu_item, FALSE); @@ -462,6 +470,7 @@ close_session() { if (_status_bar_label != nullptr) { gtk_container_remove(GTK_CONTAINER(_status_bar), _status_bar_label); + g_object_unref(_status_bar_label); _status_bar_label = nullptr; } diff --git a/pandatool/src/mac-stats/CMakeLists.txt b/pandatool/src/mac-stats/CMakeLists.txt new file mode 100644 index 0000000000..bb56cd0771 --- /dev/null +++ b/pandatool/src/mac-stats/CMakeLists.txt @@ -0,0 +1,53 @@ +if(NOT APPLE OR NOT HAVE_NET) + return() +endif() + +set(MACSTATS_HEADERS + macStats.h + macStatsAppDelegate.h + macStatsChartMenu.h + macStatsChartMenuDelegate.h + macStatsFlameGraph.h + macStatsGraph.h + macStatsGraphView.h + macStatsGraphViewController.h + macStatsLabel.h + macStatsLabelStack.h + macStatsMonitor.h + macStatsPianoRoll.h + macStatsScaleArea.h + macStatsServer.h + macStatsStripChart.h + macStatsTimeline.h +) + +set(MACSTATS_SOURCES + macStats.mm + macStatsAppDelegate.mm + macStatsChartMenu.mm + macStatsChartMenuDelegate.mm + macStatsFlameGraph.mm + macStatsGraph.mm + macStatsGraphView.mm + macStatsGraphViewController.mm + macStatsLabel.mm + macStatsLabelStack.mm + macStatsMonitor.mm + macStatsPianoRoll.mm + macStatsScaleArea.mm + macStatsServer.mm + macStatsStripChart.mm + macStatsTimeline.mm +) + +composite_sources(mac-stats MACSTATS_SOURCES) +add_executable(mac-stats ${MACSTATS_HEADERS} ${MACSTATS_SOURCES}) +target_link_libraries(mac-stats p3progbase p3pstatserver) +target_link_libraries(mac-stats "-framework Cocoa") +target_link_libraries(mac-stats "-framework Carbon") +target_link_libraries(mac-stats "-framework Quartz") + +# This program is NOT actually called win-stats. It's just pstats +set_target_properties(mac-stats PROPERTIES OUTPUT_NAME "pstats") + +install(TARGETS mac-stats EXPORT Tools COMPONENT Tools DESTINATION ${CMAKE_INSTALL_BINDIR}) diff --git a/pandatool/src/mac-stats/macStatsMonitor.mm b/pandatool/src/mac-stats/macStatsMonitor.mm index b64ae21382..7d001e39a5 100644 --- a/pandatool/src/mac-stats/macStatsMonitor.mm +++ b/pandatool/src/mac-stats/macStatsMonitor.mm @@ -174,11 +174,6 @@ new_collector(int collector_index) { for (MacStatsGraph *graph : _graphs) { graph->new_collector(collector_index); } - - // We might need to update our menus. - for (MacStatsChartMenu *chart_menu : _chart_menus) { - chart_menu->check_update(); - } } /** @@ -204,6 +199,8 @@ new_thread(int thread_index) { */ void MacStatsMonitor:: new_data(int thread_index, int frame_number) { + PStatMonitor::new_data(thread_index, frame_number); + for (MacStatsGraph *graph : _graphs) { graph->new_data(thread_index, frame_number); } @@ -355,9 +352,9 @@ get_collector_color(int collector_index, bool highlight) { } LRGBColor rgb = PStatMonitor::get_collector_color(collector_index); - rgb[0] = encode_sRGB_float(rgb[0]); - rgb[1] = encode_sRGB_float(rgb[1]); - rgb[2] = encode_sRGB_float(rgb[2]); + rgb[0] = encode_sRGB_float((float)rgb[0]); + rgb[1] = encode_sRGB_float((float)rgb[1]); + rgb[2] = encode_sRGB_float((float)rgb[2]); PN_stdfloat bright = rgb.dot(LRGBColor(0.2126, 0.7152, 0.0722)); CGColorRef color = CGColorCreateGenericRGB(rgb[0], rgb[1], rgb[2], 1.0); diff --git a/pandatool/src/mac-stats/macStatsTimeline.mm b/pandatool/src/mac-stats/macStatsTimeline.mm index 4a971e7a2b..464edde12d 100644 --- a/pandatool/src/mac-stats/macStatsTimeline.mm +++ b/pandatool/src/mac-stats/macStatsTimeline.mm @@ -232,9 +232,6 @@ draw_bar(int row, int from_x, int to_x, int collector_index, if ((to_x - from_x) >= scale * 4) { // Only bother drawing the text if we've got some space to draw on. - const PStatClientData *client_data = monitor->get_client_data(); - const PStatCollectorDef &def = client_data->get_collector_def(collector_index); - const CFStringRef keys[] = { (__bridge CFStringRef)NSForegroundColorAttributeName, (__bridge CFStringRef)NSFontAttributeName, @@ -245,7 +242,7 @@ draw_bar(int row, int from_x, int to_x, int collector_index, }; CFDictionaryRef attribs = CFDictionaryCreate(kCFAllocatorDefault, (const void **)keys, (const void **)values, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - CFStringRef str = CFStringCreateWithCString(kCFAllocatorDefault, def._name.c_str(), kCFStringEncodingUTF8); + CFStringRef str = CFStringCreateWithCString(kCFAllocatorDefault, collector_name.c_str(), kCFStringEncodingUTF8); CFAttributedStringRef astr = CFAttributedStringCreate(kCFAllocatorDefault, str, attribs); CTLineRef line = CTLineCreateWithAttributedString(astr); @@ -260,23 +257,43 @@ draw_bar(int row, int from_x, int to_x, int collector_index, double text_left = std::max(from_x, 0) + scale / 2.0; double text_right = std::min(to_x, get_xsize()) - scale / 2.0; double text_top = top + (bottom - top - text_height) / 2.0 + text_height; -/* + if (text_width >= text_right - text_left) { size_t c = collector_name.rfind(':'); if (text_right - text_left < scale * 6) { // It's a really tiny space. Draw a single letter. - const char *ch = collector_name.data() + (c != std::string::npos ? c + 1 : 0); - pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER); - pango_layout_set_text(layout, ch, 1); - } else { + UniChar ch = *(collector_name.data() + (c != std::string::npos ? c + 1 : 0)); + + CFStringRef str = CFStringCreateWithCharacters(kCFAllocatorDefault, &ch, 1); + CFAttributedStringRef astr = CFAttributedStringCreate(kCFAllocatorDefault, str, attribs); + + CTLineRef new_line = CTLineCreateWithAttributedString((CFAttributedStringRef)astr); + bounds = CTLineGetImageBounds(new_line, _ctx); + text_width = bounds.size.width; + + CFRelease(line); + CFRelease(astr); + CFRelease(str); + line = new_line; + } + else { // Maybe just use everything after the last colon. if (c != std::string::npos) { - pango_layout_set_text(layout, collector_name.data() + c + 1, - collector_name.size() - c - 1); - pango_layout_get_pixel_size(layout, &text_width, &text_height); + const char *short_name = collector_name.data() + c + 1; + CFStringRef str = CFStringCreateWithCString(kCFAllocatorDefault, short_name, kCFStringEncodingUTF8); + CFAttributedStringRef astr = CFAttributedStringCreate(kCFAllocatorDefault, str, attribs); + + CTLineRef new_line = CTLineCreateWithAttributedString((CFAttributedStringRef)astr); + bounds = CTLineGetImageBounds(new_line, _ctx); + text_width = bounds.size.width; + + CFRelease(line); + CFRelease(astr); + CFRelease(str); + line = new_line; } } - }*/ + } if (text_width >= text_right - text_left) { // Have CoreText truncate to the correct length. diff --git a/pandatool/src/palettizer/destTextureImage.cxx b/pandatool/src/palettizer/destTextureImage.cxx index 38f9a879d1..3c80f3d924 100644 --- a/pandatool/src/palettizer/destTextureImage.cxx +++ b/pandatool/src/palettizer/destTextureImage.cxx @@ -123,7 +123,7 @@ to_power_2(int value) { void DestTextureImage:: register_with_read_factory() { BamReader::get_factory()-> - register_factory(get_class_type(), make_DestTextureImage); + register_factory(get_class_type(), make_from_bam); } /** @@ -140,8 +140,8 @@ write_datagram(BamWriter *writer, Datagram &datagram) { * encountered in a Bam file; it should allocate and return a new object with * all the data read. */ -TypedWritable* DestTextureImage:: -make_DestTextureImage(const FactoryParams ¶ms) { +TypedWritable *DestTextureImage:: +make_from_bam(const FactoryParams ¶ms) { DestTextureImage *me = new DestTextureImage; DatagramIterator scan; BamReader *manager; diff --git a/pandatool/src/palettizer/destTextureImage.h b/pandatool/src/palettizer/destTextureImage.h index 31075b8f99..860655b6a1 100644 --- a/pandatool/src/palettizer/destTextureImage.h +++ b/pandatool/src/palettizer/destTextureImage.h @@ -45,7 +45,7 @@ public: virtual void write_datagram(BamWriter *writer, Datagram &datagram); protected: - static TypedWritable *make_DestTextureImage(const FactoryParams ¶ms); + static TypedWritable *make_from_bam(const FactoryParams ¶ms); void fillin(DatagramIterator &scan, BamReader *manager); public: diff --git a/pandatool/src/palettizer/eggFile.cxx b/pandatool/src/palettizer/eggFile.cxx index 40376a7988..c47eae2f3e 100644 --- a/pandatool/src/palettizer/eggFile.cxx +++ b/pandatool/src/palettizer/eggFile.cxx @@ -696,7 +696,7 @@ rescan_textures() { void EggFile:: register_with_read_factory() { BamReader::get_factory()-> - register_factory(get_class_type(), make_EggFile); + register_factory(get_class_type(), make_from_bam); } /** @@ -764,8 +764,8 @@ complete_pointers(TypedWritable **p_list, BamReader *manager) { * encountered in a Bam file; it should allocate and return a new object with * all the data read. */ -TypedWritable* EggFile:: -make_EggFile(const FactoryParams ¶ms) { +TypedWritable *EggFile:: +make_from_bam(const FactoryParams ¶ms) { EggFile *me = new EggFile(); DatagramIterator scan; BamReader *manager; diff --git a/pandatool/src/palettizer/eggFile.h b/pandatool/src/palettizer/eggFile.h index cc3887242e..aa8e729e6d 100644 --- a/pandatool/src/palettizer/eggFile.h +++ b/pandatool/src/palettizer/eggFile.h @@ -107,7 +107,7 @@ public: BamReader *manager); protected: - static TypedWritable *make_EggFile(const FactoryParams ¶ms); + static TypedWritable *make_from_bam(const FactoryParams ¶ms); void fillin(DatagramIterator &scan, BamReader *manager); private: diff --git a/pandatool/src/palettizer/paletteGroup.cxx b/pandatool/src/palettizer/paletteGroup.cxx index 5f231b2e14..d7e583259d 100644 --- a/pandatool/src/palettizer/paletteGroup.cxx +++ b/pandatool/src/palettizer/paletteGroup.cxx @@ -560,7 +560,7 @@ update_images(bool redo_all) { void PaletteGroup:: register_with_read_factory() { BamReader::get_factory()-> - register_factory(get_class_type(), make_PaletteGroup); + register_factory(get_class_type(), make_from_bam); } /** @@ -654,7 +654,7 @@ finalize(BamReader *) { * all the data read. */ TypedWritable *PaletteGroup:: -make_PaletteGroup(const FactoryParams ¶ms) { +make_from_bam(const FactoryParams ¶ms) { PaletteGroup *me = new PaletteGroup; DatagramIterator scan; BamReader *manager; diff --git a/pandatool/src/palettizer/paletteGroup.h b/pandatool/src/palettizer/paletteGroup.h index 54eaa08fc0..5c20e1ca4d 100644 --- a/pandatool/src/palettizer/paletteGroup.h +++ b/pandatool/src/palettizer/paletteGroup.h @@ -115,7 +115,7 @@ public: virtual void finalize(BamReader *manager); protected: - static TypedWritable *make_PaletteGroup(const FactoryParams ¶ms); + static TypedWritable *make_from_bam(const FactoryParams ¶ms); void fillin(DatagramIterator &scan, BamReader *manager); private: diff --git a/pandatool/src/palettizer/paletteGroups.cxx b/pandatool/src/palettizer/paletteGroups.cxx index c964f2b057..ada0702a9a 100644 --- a/pandatool/src/palettizer/paletteGroups.cxx +++ b/pandatool/src/palettizer/paletteGroups.cxx @@ -280,7 +280,7 @@ r_make_complete(PaletteGroups::Groups &result, PaletteGroup *group) { void PaletteGroups:: register_with_read_factory() { BamReader::get_factory()-> - register_factory(get_class_type(), make_PaletteGroups); + register_factory(get_class_type(), make_from_bam); } /** @@ -320,8 +320,8 @@ complete_pointers(TypedWritable **p_list, BamReader *manager) { * encountered in a Bam file; it should allocate and return a new object with * all the data read. */ -TypedWritable* PaletteGroups:: -make_PaletteGroups(const FactoryParams ¶ms) { +TypedWritable *PaletteGroups:: +make_from_bam(const FactoryParams ¶ms) { PaletteGroups *me = new PaletteGroups; DatagramIterator scan; BamReader *manager; diff --git a/pandatool/src/palettizer/paletteGroups.h b/pandatool/src/palettizer/paletteGroups.h index bdcfd248e1..b9858f8257 100644 --- a/pandatool/src/palettizer/paletteGroups.h +++ b/pandatool/src/palettizer/paletteGroups.h @@ -76,7 +76,7 @@ public: BamReader *manager); protected: - static TypedWritable *make_PaletteGroups(const FactoryParams ¶ms); + static TypedWritable *make_from_bam(const FactoryParams ¶ms); public: void fillin(DatagramIterator &scan, BamReader *manager); diff --git a/pandatool/src/palettizer/paletteImage.cxx b/pandatool/src/palettizer/paletteImage.cxx index c02e13a2ad..3ceedbf553 100644 --- a/pandatool/src/palettizer/paletteImage.cxx +++ b/pandatool/src/palettizer/paletteImage.cxx @@ -969,7 +969,7 @@ remove_image() { void PaletteImage:: register_with_read_factory() { BamReader::get_factory()-> - register_factory(get_class_type(), make_PaletteImage); + register_factory(get_class_type(), make_from_bam); } /** @@ -1037,7 +1037,7 @@ complete_pointers(TypedWritable **p_list, BamReader *manager) { * all the data read. */ TypedWritable *PaletteImage:: -make_PaletteImage(const FactoryParams ¶ms) { +make_from_bam(const FactoryParams ¶ms) { PaletteImage *me = new PaletteImage; DatagramIterator scan; BamReader *manager; diff --git a/pandatool/src/palettizer/paletteImage.h b/pandatool/src/palettizer/paletteImage.h index 60395fdc39..cec32aa0f1 100644 --- a/pandatool/src/palettizer/paletteImage.h +++ b/pandatool/src/palettizer/paletteImage.h @@ -117,7 +117,7 @@ public: BamReader *manager); protected: - static TypedWritable *make_PaletteImage(const FactoryParams ¶ms); + static TypedWritable *make_from_bam(const FactoryParams ¶ms); void fillin(DatagramIterator &scan, BamReader *manager); private: diff --git a/pandatool/src/palettizer/palettePage.cxx b/pandatool/src/palettizer/palettePage.cxx index 9bdc74c57e..98fa9cb2be 100644 --- a/pandatool/src/palettizer/palettePage.cxx +++ b/pandatool/src/palettizer/palettePage.cxx @@ -214,7 +214,7 @@ update_images(bool redo_all) { void PalettePage:: register_with_read_factory() { BamReader::get_factory()-> - register_factory(get_class_type(), make_PalettePage); + register_factory(get_class_type(), make_from_bam); } /** @@ -271,8 +271,8 @@ complete_pointers(TypedWritable **p_list, BamReader *manager) { * encountered in a Bam file; it should allocate and return a new object with * all the data read. */ -TypedWritable* PalettePage:: -make_PalettePage(const FactoryParams ¶ms) { +TypedWritable *PalettePage:: +make_from_bam(const FactoryParams ¶ms) { PalettePage *me = new PalettePage; DatagramIterator scan; BamReader *manager; diff --git a/pandatool/src/palettizer/palettePage.h b/pandatool/src/palettizer/palettePage.h index 91ba875219..8cac0f7adc 100644 --- a/pandatool/src/palettizer/palettePage.h +++ b/pandatool/src/palettizer/palettePage.h @@ -69,7 +69,7 @@ public: BamReader *manager); protected: - static TypedWritable *make_PalettePage(const FactoryParams ¶ms); + static TypedWritable *make_from_bam(const FactoryParams ¶ms); void fillin(DatagramIterator &scan, BamReader *manager); private: diff --git a/pandatool/src/palettizer/palettizer.cxx b/pandatool/src/palettizer/palettizer.cxx index 2b9df0f1e1..0860cb3819 100644 --- a/pandatool/src/palettizer/palettizer.cxx +++ b/pandatool/src/palettizer/palettizer.cxx @@ -913,7 +913,7 @@ compute_statistics(std::ostream &out, int indent_level, void Palettizer:: register_with_read_factory() { BamReader::get_factory()-> - register_factory(get_class_type(), make_Palettizer); + register_factory(get_class_type(), make_from_bam); } /** @@ -1099,8 +1099,8 @@ finalize(BamReader *manager) { * encountered in a Bam file; it should allocate and return a new object with * all the data read. */ -TypedWritable* Palettizer:: -make_Palettizer(const FactoryParams ¶ms) { +TypedWritable *Palettizer:: +make_from_bam(const FactoryParams ¶ms) { Palettizer *me = new Palettizer; DatagramIterator scan; BamReader *manager; diff --git a/pandatool/src/palettizer/palettizer.h b/pandatool/src/palettizer/palettizer.h index 523968e952..93f211bb6b 100644 --- a/pandatool/src/palettizer/palettizer.h +++ b/pandatool/src/palettizer/palettizer.h @@ -152,7 +152,7 @@ public: virtual void finalize(BamReader *manager); protected: - static TypedWritable *make_Palettizer(const FactoryParams ¶ms); + static TypedWritable *make_from_bam(const FactoryParams ¶ms); void fillin(DatagramIterator &scan, BamReader *manager); private: diff --git a/pandatool/src/palettizer/sourceTextureImage.cxx b/pandatool/src/palettizer/sourceTextureImage.cxx index aea0046ad1..c3aac42218 100644 --- a/pandatool/src/palettizer/sourceTextureImage.cxx +++ b/pandatool/src/palettizer/sourceTextureImage.cxx @@ -149,7 +149,7 @@ set_header(const PNMImageHeader &header) { void SourceTextureImage:: register_with_read_factory() { BamReader::get_factory()-> - register_factory(get_class_type(), make_SourceTextureImage); + register_factory(get_class_type(), make_from_bam); } /** @@ -188,7 +188,7 @@ complete_pointers(TypedWritable **p_list, BamReader *manager) { * all the data read. */ TypedWritable *SourceTextureImage:: -make_SourceTextureImage(const FactoryParams ¶ms) { +make_from_bam(const FactoryParams ¶ms) { SourceTextureImage *me = new SourceTextureImage; DatagramIterator scan; BamReader *manager; diff --git a/pandatool/src/palettizer/sourceTextureImage.h b/pandatool/src/palettizer/sourceTextureImage.h index 1f1f64b9dc..6c803a73f3 100644 --- a/pandatool/src/palettizer/sourceTextureImage.h +++ b/pandatool/src/palettizer/sourceTextureImage.h @@ -56,7 +56,7 @@ public: BamReader *manager); protected: - static TypedWritable *make_SourceTextureImage(const FactoryParams ¶ms); + static TypedWritable *make_from_bam(const FactoryParams ¶ms); void fillin(DatagramIterator &scan, BamReader *manager); public: diff --git a/pandatool/src/palettizer/textureImage.cxx b/pandatool/src/palettizer/textureImage.cxx index bbc47002d2..8eddd6bb4d 100644 --- a/pandatool/src/palettizer/textureImage.cxx +++ b/pandatool/src/palettizer/textureImage.cxx @@ -1236,7 +1236,7 @@ get_source_key(const Filename &filename, const Filename &alpha_filename, void TextureImage:: register_with_read_factory() { BamReader::get_factory()-> - register_factory(get_class_type(), make_TextureImage); + register_factory(get_class_type(), make_from_bam); } /** @@ -1346,7 +1346,7 @@ complete_pointers(TypedWritable **p_list, BamReader *manager) { * all the data read. */ TypedWritable *TextureImage:: -make_TextureImage(const FactoryParams ¶ms) { +make_from_bam(const FactoryParams ¶ms) { TextureImage *me = new TextureImage; DatagramIterator scan; BamReader *manager; diff --git a/pandatool/src/palettizer/textureImage.h b/pandatool/src/palettizer/textureImage.h index 1e590da621..3fd041d68a 100644 --- a/pandatool/src/palettizer/textureImage.h +++ b/pandatool/src/palettizer/textureImage.h @@ -161,7 +161,7 @@ public: BamReader *manager); protected: - static TypedWritable *make_TextureImage(const FactoryParams ¶ms); + static TypedWritable *make_from_bam(const FactoryParams ¶ms); void fillin(DatagramIterator &scan, BamReader *manager); private: diff --git a/pandatool/src/palettizer/texturePlacement.cxx b/pandatool/src/palettizer/texturePlacement.cxx index 01f47b42a1..b92583b6d6 100644 --- a/pandatool/src/palettizer/texturePlacement.cxx +++ b/pandatool/src/palettizer/texturePlacement.cxx @@ -987,7 +987,7 @@ compute_size_from_uvs(const LTexCoordd &min_uv, const LTexCoordd &max_uv) { void TexturePlacement:: register_with_read_factory() { BamReader::get_factory()-> - register_factory(get_class_type(), make_TexturePlacement); + register_factory(get_class_type(), make_from_bam); } /** @@ -1077,8 +1077,8 @@ complete_pointers(TypedWritable **p_list, BamReader *manager) { * encountered in a Bam file; it should allocate and return a new object with * all the data read. */ -TypedWritable* TexturePlacement:: -make_TexturePlacement(const FactoryParams ¶ms) { +TypedWritable *TexturePlacement:: +make_from_bam(const FactoryParams ¶ms) { TexturePlacement *me = new TexturePlacement; DatagramIterator scan; BamReader *manager; diff --git a/pandatool/src/palettizer/texturePlacement.h b/pandatool/src/palettizer/texturePlacement.h index 552f50f3d6..efe90f858d 100644 --- a/pandatool/src/palettizer/texturePlacement.h +++ b/pandatool/src/palettizer/texturePlacement.h @@ -120,7 +120,7 @@ public: BamReader *manager); protected: - static TypedWritable *make_TexturePlacement(const FactoryParams ¶ms); + static TypedWritable *make_from_bam(const FactoryParams ¶ms); void fillin(DatagramIterator &scan, BamReader *manager); private: diff --git a/pandatool/src/palettizer/texturePosition.cxx b/pandatool/src/palettizer/texturePosition.cxx index dd7617d1d8..ea4f61ac2c 100644 --- a/pandatool/src/palettizer/texturePosition.cxx +++ b/pandatool/src/palettizer/texturePosition.cxx @@ -75,7 +75,7 @@ operator = (const TexturePosition ©) { void TexturePosition:: register_with_read_factory() { BamReader::get_factory()-> - register_factory(get_class_type(), make_TexturePosition); + register_factory(get_class_type(), make_from_bam); } /** @@ -103,8 +103,8 @@ write_datagram(BamWriter *writer, Datagram &datagram) { * encountered in a Bam file; it should allocate and return a new object with * all the data read. */ -TypedWritable* TexturePosition:: -make_TexturePosition(const FactoryParams ¶ms) { +TypedWritable *TexturePosition:: +make_from_bam(const FactoryParams ¶ms) { TexturePosition *me = new TexturePosition; DatagramIterator scan; BamReader *manager; diff --git a/pandatool/src/palettizer/texturePosition.h b/pandatool/src/palettizer/texturePosition.h index 08f373a644..c1edd40e20 100644 --- a/pandatool/src/palettizer/texturePosition.h +++ b/pandatool/src/palettizer/texturePosition.h @@ -50,7 +50,7 @@ public: virtual void write_datagram(BamWriter *writer, Datagram &datagram); protected: - static TypedWritable *make_TexturePosition(const FactoryParams ¶ms); + static TypedWritable *make_from_bam(const FactoryParams ¶ms); public: void fillin(DatagramIterator &scan, BamReader *manager); diff --git a/pandatool/src/palettizer/textureProperties.cxx b/pandatool/src/palettizer/textureProperties.cxx index bb670539b9..c5635409d2 100644 --- a/pandatool/src/palettizer/textureProperties.cxx +++ b/pandatool/src/palettizer/textureProperties.cxx @@ -834,7 +834,7 @@ union_quality_level(EggTexture::QualityLevel a, EggTexture::QualityLevel b) { void TextureProperties:: register_with_read_factory() { BamReader::get_factory()-> - register_factory(get_class_type(), make_TextureProperties); + register_factory(get_class_type(), make_from_bam); } /** @@ -888,8 +888,8 @@ complete_pointers(TypedWritable **p_list, BamReader *manager) { * encountered in a Bam file; it should allocate and return a new object with * all the data read. */ -TypedWritable* TextureProperties:: -make_TextureProperties(const FactoryParams ¶ms) { +TypedWritable *TextureProperties:: +make_from_bam(const FactoryParams ¶ms) { TextureProperties *me = new TextureProperties; DatagramIterator scan; BamReader *manager; diff --git a/pandatool/src/palettizer/textureProperties.h b/pandatool/src/palettizer/textureProperties.h index 6d27e06216..f143bdcb4a 100644 --- a/pandatool/src/palettizer/textureProperties.h +++ b/pandatool/src/palettizer/textureProperties.h @@ -92,7 +92,7 @@ public: BamReader *manager); protected: - static TypedWritable *make_TextureProperties(const FactoryParams ¶ms); + static TypedWritable *make_from_bam(const FactoryParams ¶ms); public: void fillin(DatagramIterator &scan, BamReader *manager); diff --git a/pandatool/src/palettizer/textureReference.cxx b/pandatool/src/palettizer/textureReference.cxx index 4a11b5348d..3b6c2696fa 100644 --- a/pandatool/src/palettizer/textureReference.cxx +++ b/pandatool/src/palettizer/textureReference.cxx @@ -791,7 +791,7 @@ translate_uv(const LTexCoordd &min_uv, const LTexCoordd &max_uv) { void TextureReference:: register_with_read_factory() { BamReader::get_factory()-> - register_factory(get_class_type(), make_TextureReference); + register_factory(get_class_type(), make_from_bam); } /** @@ -859,8 +859,8 @@ complete_pointers(TypedWritable **p_list, BamReader *manager) { * encountered in a Bam file; it should allocate and return a new object with * all the data read. */ -TypedWritable* TextureReference:: -make_TextureReference(const FactoryParams ¶ms) { +TypedWritable *TextureReference:: +make_from_bam(const FactoryParams ¶ms) { TextureReference *me = new TextureReference; DatagramIterator scan; BamReader *manager; diff --git a/pandatool/src/palettizer/textureReference.h b/pandatool/src/palettizer/textureReference.h index f17d8337b2..720994c9c6 100644 --- a/pandatool/src/palettizer/textureReference.h +++ b/pandatool/src/palettizer/textureReference.h @@ -114,7 +114,7 @@ public: BamReader *manager); protected: - static TypedWritable *make_TextureReference(const FactoryParams ¶ms); + static TypedWritable *make_from_bam(const FactoryParams ¶ms); void fillin(DatagramIterator &scan, BamReader *manager); public: diff --git a/pandatool/src/palettizer/txaLine.cxx b/pandatool/src/palettizer/txaLine.cxx index d704fdb045..6d04b5daf1 100644 --- a/pandatool/src/palettizer/txaLine.cxx +++ b/pandatool/src/palettizer/txaLine.cxx @@ -495,7 +495,7 @@ match_texture(TextureImage *texture) const { case KW_mipmap: request._minfilter = EggTexture::FT_linear_mipmap_linear; - request._magfilter = EggTexture::FT_linear_mipmap_linear; + request._magfilter = EggTexture::FT_linear; break; case KW_anisotropic: diff --git a/pandatool/src/pstatserver/pStatMonitor.cxx b/pandatool/src/pstatserver/pStatMonitor.cxx index fd5b83b866..86390d5ab7 100644 --- a/pandatool/src/pstatserver/pStatMonitor.cxx +++ b/pandatool/src/pstatserver/pStatMonitor.cxx @@ -563,7 +563,22 @@ new_thread(int) { * data will facilitate this. */ void PStatMonitor:: -new_data(int, int) { +new_data(int thread_index, int frame_number) { + const PStatClientData *client_data = get_client_data(); + + // Don't bother to update the thread data until we know at least something + // about the collectors and threads. + if (client_data->get_num_collectors() != 0 && + client_data->get_num_threads() != 0) { + PStatView &view = get_view(thread_index); + const PStatThreadData *thread_data = view.get_thread_data(); + if (!thread_data->is_empty()) { + int latest = thread_data->get_latest_frame_number(); + if (frame_number == latest) { + view.set_to_frame(thread_data->get_frame(frame_number)); + } + } + } } /** diff --git a/pandatool/src/pstatserver/pStatStripChart.cxx b/pandatool/src/pstatserver/pStatStripChart.cxx index 7861ae8d90..d961b7c055 100644 --- a/pandatool/src/pstatserver/pStatStripChart.cxx +++ b/pandatool/src/pstatserver/pStatStripChart.cxx @@ -188,7 +188,8 @@ set_auto_vertical_scale() { for (int frame_number = oldest_frame; frame_number <= latest_frame; ++frame_number) { if (thread_data->has_frame(frame_number)) { - values.push_back(get_net_value(frame_number)); + const FrameData &frame = get_frame_data(frame_number); + values.push_back(frame._net_value); } } } @@ -589,9 +590,16 @@ get_frame_data(int frame_number) const { } const PStatThreadData *thread_data = _view.get_thread_data(); - _view.set_to_frame(thread_data->get_frame(frame_number)); + //assert(thread_data->has_frame(frame_number)); + const PStatFrameData &frame_data = thread_data->get_frame(frame_number); + _view.set_to_frame(frame_data); FrameData &fdata = _data[frame_number]; + fdata._start = frame_data.get_start(); + fdata._end = frame_data.get_end(); + fdata._net_time = frame_data.get_net_time(); + + double net_value = 0.0; const PStatViewLevel *level = _view.get_level(_collector_index); int num_children = level->get_num_children(); @@ -604,6 +612,7 @@ get_frame_data(int frame_number) const { cd._net_value = child->get_net_value(); if (cd._net_value != 0.0) { fdata.push_back(cd); + net_value += cd._net_value; } } @@ -616,8 +625,11 @@ get_frame_data(int frame_number) const { cd._net_value = level->get_value_alone(); if (cd._net_value > 0.0) { fdata.push_back(cd); + net_value += cd._net_value; } + fdata._net_value = net_value; + ((PStatStripChart *)this)->inc_label_usage(fdata); return fdata; @@ -645,34 +657,38 @@ compute_average_pixel_data(PStatStripChart::FrameData &result, } double then = now - pstats_average_time; + then_i = thread_data->get_frame_number_after(then, then_i); + now_i = thread_data->get_frame_number_after(now, now_i); - int latest_frame = thread_data->get_latest_frame_number(); - while (then_i <= latest_frame && - thread_data->get_frame(then_i).get_end() < then) { - then_i++; - } - while (now_i <= latest_frame && - thread_data->get_frame(now_i).get_end() < now) { - now_i++; - } - - then = max(then, thread_data->get_frame(then_i).get_start()); + const FrameData *fdata = &get_frame_data(then_i); + then = max(then, fdata->_start); + double then_end = fdata->_end; // Sum up a weighted average of all of the individual frames we pass. // We start with just the portion of frame then_i that actually does fall // within our "then to now" window. - accumulate_frame_data(result, get_frame_data(then_i), - thread_data->get_frame(then_i).get_end() - then); - double last = thread_data->get_frame(then_i).get_end(); + accumulate_frame_data(result, *fdata, then_end - then); + double last = then_end; // Then we get all of each of the middle frames. + double weight = 0.0; for (int frame_number = then_i + 1; frame_number < now_i; frame_number++) { - accumulate_frame_data(result, get_frame_data(frame_number), - thread_data->get_frame(frame_number).get_end() - last); - last = thread_data->get_frame(frame_number).get_end(); + if (thread_data->has_frame(frame_number)) { + if (weight > 0.0) { + accumulate_frame_data(result, *fdata, weight); + weight = 0.0; + } + fdata = &get_frame_data(frame_number); + } + weight += fdata->_end - last; + last = fdata->_end; + } + + if (weight > 0.0) { + accumulate_frame_data(result, *fdata, weight); } // And finally, we get the remainder as now_i. @@ -683,22 +699,6 @@ compute_average_pixel_data(PStatStripChart::FrameData &result, scale_frame_data(result, 1.0f / (now - then)); } -/** - * Returns the net value of the chart's collector for the indicated frame - * number. - */ -double PStatStripChart:: -get_net_value(int frame_number) const { - const FrameData &frame = get_frame_data(frame_number); - - double net_value = 0.0; - for (const ColorData &cd : frame) { - net_value += cd._net_value; - } - - return net_value; -} - /** * Computes the average value of the chart's collector over the past * pstats_average_time number of seconds. @@ -741,17 +741,21 @@ get_average_net_value() const { // We start with just the portion of frame then_i that actually does fall // within our "then to now" window (usually some portion of it will). const PStatFrameData &frame_data = thread_data->get_frame(then_i); + const FrameData *frame = &get_frame_data(then_i); if (frame_data.get_end() > then) { - double this_time = (frame_data.get_end() - then); - net_value += get_net_value(then_i) * this_time; + double this_time = (frame->_end - then); + net_value += frame->_net_value * this_time; net_time += this_time; } // Then we get all of each of the remaining frames. for (int frame_number = then_i + 1; frame_number <= now_i; frame_number++) { - double this_time = thread_data->get_frame(frame_number).get_net_time(); - net_value += get_net_value(frame_number) * this_time; + if (thread_data->has_frame(frame_number)) { + frame = &get_frame_data(frame_number); + } + double this_time = frame->_net_time; + net_value += frame->_net_value * this_time; net_time += this_time; } diff --git a/pandatool/src/pstatserver/pStatStripChart.h b/pandatool/src/pstatserver/pStatStripChart.h index e8bd39f84d..0a68fee6f3 100644 --- a/pandatool/src/pstatserver/pStatStripChart.h +++ b/pandatool/src/pstatserver/pStatStripChart.h @@ -86,7 +86,11 @@ protected: int _count; double _net_value; }; - typedef pvector FrameData; + class FrameData : public pvector { + public: + double _start, _end; + double _net_value, _net_time; + }; typedef pmap Data; static void accumulate_frame_data(FrameData &fdata, @@ -96,8 +100,6 @@ protected: const FrameData &get_frame_data(int frame_number) const; void compute_average_pixel_data(PStatStripChart::FrameData &result, int &then_i, int &now_i, double now); - double get_net_value(int frame_number) const; - double get_net_value(int frame_number, int collector_index) const; double get_average_net_value() const; void changed_size(int xsize, int ysize); diff --git a/pandatool/src/pstatserver/pStatThreadData.cxx b/pandatool/src/pstatserver/pStatThreadData.cxx index 0871b60e3c..39957916c1 100644 --- a/pandatool/src/pstatserver/pStatThreadData.cxx +++ b/pandatool/src/pstatserver/pStatThreadData.cxx @@ -136,10 +136,11 @@ get_frame_at_time(double time) const { /** * Returns the frame number of the latest frame not later than the indicated - * time. + * time. If no frames were found, returns get_oldest_frame_number() - 1. * - * If the hint is nonnegative, it represents a frame number that we believe - * the correct answer to be near, which may speed the search for the frame. + * If the hint is nonnegative, it represents a frame number (for which + * has_frame() must return true) we believe the correct answer to be after and + * close by, which may speed the search for the frame. */ int PStatThreadData:: get_frame_number_at_time(double time, int hint) const { @@ -161,15 +162,85 @@ get_frame_number_at_time(double time, int hint) const { } } - // The hint is totally wrong. Start from the end and work backwards. + // The hint is wrong, we have to search the entire set. + int first_i = 0; + int last_i = _frames.size() - 1; + while (first_i < last_i && _frames[first_i] == nullptr) { + ++first_i; + } + while (first_i < last_i && _frames[last_i] == nullptr) { + --last_i; + } - int i = _frames.size() - 1; - while (i >= 0) { + if (first_i >= last_i) { + // There are no frames. + return _first_frame_number - 1; + } + + // Take a guess by interpolating based on the first and last frame times. + double first = _frames[first_i]->get_start(); + if (time < first) { + return _first_frame_number - 1; + } + + double last = _frames[last_i]->get_start(); + double t = (time - first) / (last - first); + hint = std::max(0, (int)(t * (last_i - first_i))) + first_i; + + // Find a frame around the guess that has data. + if (_frames[hint] == nullptr) { + if (hint <= first_i) { + hint = first_i; + } + else do { + // Skip backward until we find a frame with data. + --hint; + } while (_frames[hint] == nullptr); + } + + if (_frames[hint]->get_start() <= time) { + // Search forward. + for (int i = hint + 1; i < (int)_frames.size(); ++i) { + const PStatFrameData *frame = _frames[i]; + if (frame != nullptr) { + if (frame->get_start() <= time) { + hint = i; + } else { + break; + } + } + } + return _first_frame_number + hint; + } + + // Search backward. + for (int i = hint - 1; i >= 0; --i) { const PStatFrameData *frame = _frames[i]; if (frame != nullptr && frame->get_start() <= time) { + return _first_frame_number + i; + } + } + + return _first_frame_number - 1; +} + +/** + * Returns the frame number of the first frame later than the indicated time + * and start frame number. + */ +int PStatThreadData:: +get_frame_number_after(double time, int start_at) const { + int i = std::max(0, start_at - _first_frame_number); + double end = get_frame(i).get_end(); + + while (end < time) { + ++i; + if (i >= _frames.size()) { break; } - --i; + if (_frames[i] != nullptr) { + end = _frames[i]->get_end(); + } } return _first_frame_number + i; diff --git a/pandatool/src/pstatserver/pStatThreadData.h b/pandatool/src/pstatserver/pStatThreadData.h index d5fab4577a..471312d212 100644 --- a/pandatool/src/pstatserver/pStatThreadData.h +++ b/pandatool/src/pstatserver/pStatThreadData.h @@ -51,6 +51,7 @@ public: double get_oldest_time() const; const PStatFrameData &get_frame_at_time(double time) const; int get_frame_number_at_time(double time, int hint = -1) const; + int get_frame_number_after(double time, int start_at = 0) const; const PStatFrameData &get_latest_frame() const; diff --git a/pandatool/src/win-stats/winStatsMonitor.cxx b/pandatool/src/win-stats/winStatsMonitor.cxx index b182e3a7c6..18623f5c66 100644 --- a/pandatool/src/win-stats/winStatsMonitor.cxx +++ b/pandatool/src/win-stats/winStatsMonitor.cxx @@ -146,11 +146,6 @@ new_collector(int collector_index) { for (WinStatsGraph *graph : _graphs) { graph->new_collector(collector_index); } - - // We might need to update our menus. - for (WinStatsChartMenu *chart_menu : _chart_menus) { - chart_menu->do_update(); - } } /** @@ -196,6 +191,8 @@ remove_thread(int thread_index) { */ void WinStatsMonitor:: new_data(int thread_index, int frame_number) { + PStatMonitor::new_data(thread_index, frame_number); + for (WinStatsGraph *graph : _graphs) { graph->new_data(thread_index, frame_number); } diff --git a/requirements-test.txt b/requirements-test.txt index bf6a71e61c..2f9b041024 100644 --- a/requirements-test.txt +++ b/requirements-test.txt @@ -1,4 +1,5 @@ -pytest +pytest>=3.9.0 pytest-cov Pmw-py3==2.1 +setuptools>=15.2 diff --git a/setup.cfg b/setup.cfg index 50078db334..f67637e357 100644 --- a/setup.cfg +++ b/setup.cfg @@ -18,6 +18,7 @@ classifiers = Programming Language :: Python :: 3.9 Programming Language :: Python :: 3.10 Programming Language :: Python :: 3.11 + Programming Language :: Python :: 3.12 Programming Language :: Python :: Implementation :: CPython Topic :: Games/Entertainment Topic :: Multimedia @@ -37,3 +38,4 @@ project_urls = [tool:pytest] testpaths = tests +norecursedirs = *.egg .* _darcs build CVS node_modules venv {arch} diff --git a/tests/collide/test_into_heightfield.py b/tests/collide/test_into_heightfield.py index fe2ab07b57..6cf5745458 100644 --- a/tests/collide/test_into_heightfield.py +++ b/tests/collide/test_into_heightfield.py @@ -26,9 +26,9 @@ def test_sphere_into_heightfield(): entry, np_from, np_into = make_collision(sphere, heightfield) assert entry.get_surface_point(np_from) == (1, 510, 10.1) - with pytest.raises(AssertionError) as err: - assert heightfield.set_num_subdivisions(-1) == err - assert heightfield.set_num_subdivisions(11) == err + #with pytest.raises(AssertionError) as err: + # assert heightfield.set_num_subdivisions(-1) == err + # assert heightfield.set_num_subdivisions(11) == err # Use a greater number of subdivisions, should still work num_subdivisions = 10 diff --git a/tests/display/test_cg_shader.py b/tests/display/test_cg_shader.py index 2597b39971..d118f08637 100644 --- a/tests/display/test_cg_shader.py +++ b/tests/display/test_cg_shader.py @@ -18,14 +18,14 @@ def run_cg_compile_check(gsg, shader_path, expect_fail=False): assert shader is not None -@pytest.mark.skipif(platform.machine().lower() == 'arm64', reason="Cg not supported on arm64") +@pytest.mark.skipif(platform.machine().lower() in ('arm64', 'aarch64'), reason="Cg not supported on arm64") def test_cg_compile_error(gsg): """Test getting compile errors from bad Cg shaders""" shader_path = core.Filename(SHADERS_DIR, 'cg_bad.sha') run_cg_compile_check(gsg, shader_path, expect_fail=True) -@pytest.mark.skipif(platform.machine().lower() == 'arm64', reason="Cg not supported on arm64") +@pytest.mark.skipif(platform.machine().lower() in ('arm64', 'aarch64'), reason="Cg not supported on arm64") def test_cg_from_file(gsg): """Test compiling Cg shaders from files""" shader_path = core.Filename(SHADERS_DIR, 'cg_simple.sha') diff --git a/tests/dist/test_FreezeTool.py b/tests/dist/test_FreezeTool.py index 32ae5fd2bc..e0eb82b7a5 100644 --- a/tests/dist/test_FreezeTool.py +++ b/tests/dist/test_FreezeTool.py @@ -1,5 +1,9 @@ from direct.dist.FreezeTool import Freezer, PandaModuleFinder +import pytest +import os import sys +import subprocess +import platform def test_Freezer_moduleSuffixes(): @@ -56,3 +60,48 @@ def test_Freezer_getModulePath_getModuleStar(tmp_path): assert freezer.getModuleStar("module2") == None finally: sys.path = backup + + +@pytest.mark.parametrize("use_console", (False, True)) +def test_Freezer_generateRuntimeFromStub(tmp_path, use_console): + try: + # If installed as a wheel + import panda3d_tools + bin_dir = os.path.dirname(panda3d_tools.__file__) + except: + import panda3d + bin_dir = os.path.join(os.path.dirname(os.path.dirname(panda3d.__file__)), 'bin') + + if sys.platform == 'win32': + suffix = '.exe' + else: + suffix = '' + + if not use_console: + stub_file = os.path.join(bin_dir, 'deploy-stubw' + suffix) + + if use_console or not os.path.isfile(stub_file): + stub_file = os.path.join(bin_dir, 'deploy-stub' + suffix) + + if not os.path.isfile(stub_file): + pytest.skip("Unable to find deploy-stub executable") + + target = str(tmp_path / ('stubtest' + suffix)) + + freezer = Freezer() + freezer.addModule('site', filename='site.py', text='import sys\nsys.frozen=True') + freezer.addModule('module2', filename='module2.py', text='print("Module imported")') + freezer.addModule('__main__', filename='main.py', text='import module2\nprint("Hello world")') + assert '__main__' in freezer.modules + + freezer.done(addStartupModules=True) + assert '__main__' in dict(freezer.getModuleDefs()) + + freezer.generateRuntimeFromStub(target, open(stub_file, 'rb'), use_console) + + if sys.platform == 'darwin' and platform.machine().lower() == 'arm64': + # Not supported; see #1348 + return + + output = subprocess.check_output(target) + assert output.replace(b'\r\n', b'\n') == b'Module imported\nHello world\n' diff --git a/tests/event/test_event.py b/tests/event/test_event.py new file mode 100644 index 0000000000..947ed093a3 --- /dev/null +++ b/tests/event/test_event.py @@ -0,0 +1,64 @@ +from panda3d.core import Event, EventQueue +from contextlib import contextmanager +import gc + + +@contextmanager +def gc_disabled(): + gc.disable() + gc.collect() + gc.freeze() + gc.set_debug(gc.DEBUG_SAVEALL) + + try: + yield + finally: + gc.set_debug(0) + gc.garbage.clear() + gc.unfreeze() + gc.collect() + gc.enable() + + +def test_event_subclass_gc(): + class PythonEvent(Event): + pass + + # Only subclasses should be tracked by the GC + assert not gc.is_tracked(Event('test')) + + # Python wrapper destructs last + with gc_disabled(): + event = PythonEvent('test_event_subclass_gc1') + + assert len(gc.get_objects()) == 1 + assert gc.get_objects()[0] == event + + event = None + + gc.collect() + assert len(gc.garbage) == 1 + assert gc.garbage[0].name == 'test_event_subclass_gc1' + + # C++ reference destructs last + with gc_disabled(): + event = PythonEvent('test_event_subclass_gc2') + queue = EventQueue() + queue.queue_event(event) + + assert event in gc.get_objects() + + event = None + + # Hasn't been collected yet, since parent still holds a reference + gc.collect() + assert len(gc.garbage) == 0 + assert 'test_event_subclass_gc2' in [obj.name for obj in gc.get_objects() if isinstance(obj, Event)] + + queue = None + + # Destructed without needing the GC + assert 'test_event_subclass_gc2' not in [obj.name for obj in gc.get_objects() if isinstance(obj, Event)] + + gc.collect() + assert len(gc.garbage) == 0 diff --git a/tests/event/test_pythontask.py b/tests/event/test_pythontask.py index d6806b4f72..584788494f 100644 --- a/tests/event/test_pythontask.py +++ b/tests/event/test_pythontask.py @@ -1,7 +1,26 @@ from panda3d.core import PythonTask +from contextlib import contextmanager import pytest import types import sys +import gc + + +@contextmanager +def gc_disabled(): + gc.disable() + gc.collect() + gc.freeze() + gc.set_debug(gc.DEBUG_SAVEALL) + + try: + yield + finally: + gc.set_debug(0) + gc.garbage.clear() + gc.unfreeze() + gc.collect() + gc.enable() def test_pythontask_property_builtin(): @@ -76,3 +95,23 @@ def test_pythontask_dict_set(): rc2 = sys.getrefcount(d) assert rc1 == rc2 + + +def test_pythontask_cycle(): + with gc_disabled(): + task = PythonTask() + assert gc.is_tracked(task) + task.marker = 'test_pythontask_cycle' + task.prop = task + + del task + + gc.collect() + assert len(gc.garbage) > 0 + + for g in gc.garbage: + if isinstance(g, PythonTask) and \ + getattr(g, 'marker', None) == 'test_pythontask_cycle': + break + else: + pytest.fail('not found in garbage') diff --git a/tests/gui/test_DirectButton.py b/tests/gui/test_DirectButton.py index 6f85e72f59..d01455bae1 100644 --- a/tests/gui/test_DirectButton.py +++ b/tests/gui/test_DirectButton.py @@ -1,6 +1,21 @@ from direct.gui.DirectButton import DirectButton +def test_button_default_extraArgs(): + btn = DirectButton() + + assert btn.configure('extraArgs') == ('extraArgs', [], []) + assert btn._optionInfo['extraArgs'] == [[], [], None] + + # Changing will not affect default value + btn['extraArgs'].append(1) + assert btn.configure('extraArgs') == ('extraArgs', [], [1]) + + # Changing this does + btn.configure('extraArgs')[1].append(2) + assert btn.configure('extraArgs') == ('extraArgs', [2], [1]) + + def test_button_destroy(): btn = DirectButton(text="Test") btn.destroy() diff --git a/tests/pgraph/test_pandanode.py b/tests/pgraph/test_pandanode.py index 28e684c04b..9870b4d3c6 100644 --- a/tests/pgraph/test_pandanode.py +++ b/tests/pgraph/test_pandanode.py @@ -1,4 +1,25 @@ from panda3d.core import PandaNode, TransformState +from contextlib import contextmanager +import pytest +import gc + + +@contextmanager +def gc_disabled(): + gc.disable() + gc.collect() + gc.freeze() + gc.set_debug(gc.DEBUG_SAVEALL) + gc.garbage.clear() + + try: + yield + finally: + gc.set_debug(0) + gc.garbage.clear() + gc.unfreeze() + gc.collect() + gc.enable() def test_node_prev_transform(): @@ -34,3 +55,123 @@ def test_node_prev_transform(): assert node.transform == t3 assert node.prev_transform == t3 assert not node.has_dirty_prev_transform() + + +def test_node_tag_cycle(): + with gc_disabled(): + node = PandaNode('test_node_tag_cycle') + node.set_python_tag('self', node) + node.set_python_tag('self2', node) + assert gc.is_tracked(node) + node = None + + gc.collect() + assert len(gc.garbage) > 0 + + for g in gc.garbage: + if isinstance(g, PandaNode) and g.name == 'test_node_tag_cycle': + break + else: + assert False + + +@pytest.mark.xfail +def test_node_tag_cycle_multiple_wrappers(): + # Doesn't yet work since the traverse checks that the refcount is 1. + with gc_disabled(): + node = PandaNode('test_node_tag_cycle_multiple_wrappers') + node.set_python_tag('self', node) + + # Find another reference to the same node, we do this by temporarily + # attaching a child. + child = PandaNode('child') + node.add_child(child) + node2 = child.get_parent(0) + node.remove_child(0) + child = None + + assert node2 == node + assert node2 is not node + assert node2.this == node.this + + node.set_python_tag('self2', node2) + + node = None + node2 = None + + gc.collect() + assert len(gc.garbage) > 0 + + for g in gc.garbage: + if isinstance(g, PandaNode) and g.name == 'test_node_tag_cycle_multiple_wrappers': + break + else: + pytest.fail('not found in garbage') + + +def test_node_subclass_persistent(): + class NodeSubclass(PandaNode): + pass + + node = NodeSubclass('test_node_subclass') + assert isinstance(node, PandaNode) + + # Always GC-tracked + assert gc.is_tracked(node) + + # Registered type handle + type_handle = node.get_type() + assert type_handle.name == 'NodeSubclass' + assert type_handle != PandaNode.get_class_type() + assert tuple(type_handle.parent_classes) == (PandaNode.get_class_type(), ) + + # Persistent wrapper + parent = PandaNode('parent') + parent.add_child(node) + child = parent.get_child(0) + assert child.this == node.this + assert child is node + assert type(child) is NodeSubclass + parent = None + child = None + + +def test_node_subclass_gc(): + class NodeSubclass(PandaNode): + pass + + # Python wrapper destructs last + with gc_disabled(): + node = NodeSubclass('test_node_subclass_gc1') + + assert len(gc.get_objects()) == 1 + assert gc.get_objects()[0] == node + + node = None + + gc.collect() + assert len(gc.garbage) == 1 + assert gc.garbage[0].name == 'test_node_subclass_gc1' + + # C++ reference destructs last + with gc_disabled(): + node = NodeSubclass('test_node_subclass_gc2') + parent = PandaNode('parent') + parent.add_child(node) + + assert node in gc.get_objects() + + node = None + + # Hasn't been collected yet, since parent still holds a reference + gc.collect() + assert len(gc.garbage) == 0 + assert 'test_node_subclass_gc2' in [obj.name for obj in gc.get_objects() if isinstance(obj, PandaNode)] + + parent = None + + # Destructed without needing the GC + assert 'test_node_subclass_gc2' not in [obj.name for obj in gc.get_objects() if isinstance(obj, PandaNode)] + + gc.collect() + assert len(gc.garbage) == 0 diff --git a/tests/putil/test_datagram.py b/tests/putil/test_datagram.py index 9b0e1d0c0a..1fbcb5aab3 100644 --- a/tests/putil/test_datagram.py +++ b/tests/putil/test_datagram.py @@ -1,6 +1,7 @@ import pytest from panda3d import core import tempfile +import sys # Fixtures for generating interesting datagrams (and verification functions) on # the fly... @@ -178,6 +179,7 @@ def test_file_small(datagram_small): do_file_test(dg, verify, filename) +@pytest.mark.skipif(sys.platform == "emscripten", reason="Low-memory environment") def test_file_large(datagram_large): """This tests DatagramOutputFile/DatagramInputFile on very large datagrams.""" dg, verify = datagram_large diff --git a/tests/requirements.txt b/tests/requirements.txt index 3bc9b3f390..1019c223b6 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -1,2 +1,3 @@ pytest==3.2.0 panda3d +setuptools diff --git a/tests/run_mypy.py b/tests/run_mypy.py index df27d80cda..fc949dc3e6 100644 --- a/tests/run_mypy.py +++ b/tests/run_mypy.py @@ -1,7 +1,7 @@ -import os import pathlib import shutil import subprocess +import sys import tempfile @@ -10,15 +10,18 @@ def main(): direct_src = root / 'direct' / 'src' mypy_config = root / 'mypy.ini' with tempfile.TemporaryDirectory() as temp_dir: - os.environ['MYPYPATH'] = temp_dir direct_copy = pathlib.Path(temp_dir, 'direct') shutil.copytree(direct_src, direct_copy) - subprocess.run([ + command = [ + sys.executable, + '-m', 'mypy', - str(direct_copy), + str(direct_copy.resolve()), '--config-file', - str(mypy_config), - ]) + str(mypy_config.resolve()), + ] + result = subprocess.run(command, cwd=temp_dir) + sys.exit(result.returncode) if __name__ == '__main__': diff --git a/tests/showbase/test_Loader.py b/tests/showbase/test_Loader.py index 0dadecb384..dbbe78e8e8 100644 --- a/tests/showbase/test_Loader.py +++ b/tests/showbase/test_Loader.py @@ -1,6 +1,7 @@ -from panda3d.core import Filename, NodePath +from panda3d.core import Filename, NodePath, LoaderFileTypeRegistry from direct.showbase.Loader import Loader import pytest +import sys @pytest.fixture @@ -68,3 +69,93 @@ def test_load_model_missing(loader): def test_load_model_okmissing(loader): model = loader.load_model('/nonexistent.bam', okMissing=True) assert model is None + + +def test_loader_entry_points(tmp_path): + # A dummy loader for .fnrgl files. + (tmp_path / "fnargle.py").write_text(""" +from panda3d.core import ModelRoot +import sys + +sys._fnargle_loaded = True + +class FnargleLoader: + name = "Fnargle" + extensions = ['fnrgl'] + supports_compressed = False + + @staticmethod + def load_file(path, options, record=None): + return ModelRoot("fnargle") +""") + (tmp_path / "fnargle.dist-info").mkdir() + (tmp_path / "fnargle.dist-info" / "METADATA").write_text(""" +Metadata-Version: 2.0 +Name: fnargle +Version: 1.0.0 +""") + (tmp_path / "fnargle.dist-info" / "entry_points.txt").write_text(""" +[panda3d.loaders] +fnrgl = fnargle:FnargleLoader +""") + + model_path = tmp_path / "test.fnrgl" + model_path.write_text("") + + if sys.version_info >= (3, 11): + import sysconfig + stdlib = sysconfig.get_path("stdlib") + platstdlib = sysconfig.get_path("platstdlib") + else: + from distutils import sysconfig + stdlib = sysconfig.get_python_lib(False, True) + platstdlib = sysconfig.get_python_lib(True, True) + + registry = LoaderFileTypeRegistry.get_global_ptr() + prev_loaded = Loader._loadedPythonFileTypes + prev_path = sys.path + file_type = None + try: + # We do this so we don't re-register thirdparty loaders + sys.path = [str(tmp_path), platstdlib, stdlib] + + Loader._loadedPythonFileTypes = False + + # base parameter is only used for audio + loader = Loader(None) + assert Loader._loadedPythonFileTypes + + # Should be registered, not yet loaded + file_type = registry.get_type_from_extension('fnrgl') + assert file_type is not None + assert not hasattr(sys, '_fnargle_loaded') + + assert file_type.supports_load() + assert not file_type.supports_save() + assert not file_type.supports_compressed() + assert file_type.get_extension() == 'fnrgl' + + # The above should have caused it to load + assert sys._fnargle_loaded + assert 'fnargle' in sys.modules + + # Now try loading a fnargle file + model_fn = Filename(model_path) + model_fn.make_true_case() + model = loader.load_model(model_fn, noCache=True) + assert model is not None + assert model.name == "fnargle" + + finally: + # Set everything back to what it was + Loader._loadedPythonFileTypes = prev_loaded + sys.path = prev_path + + if hasattr(sys, '_fnargle_loaded'): + del sys._fnargle_loaded + + if 'fnargle' in sys.modules: + del sys.modules['fnargle'] + + if file_type is not None: + registry.unregister_type(file_type) diff --git a/tests/test_imports.py b/tests/test_imports.py index 0fba7bff13..c6295bc7d0 100644 --- a/tests/test_imports.py +++ b/tests/test_imports.py @@ -36,6 +36,13 @@ def test_imports_panda3d(): importlib.import_module('panda3d.%s' % (module)) +def test_imports_panda3d_net(): + from panda3d import core + from panda3d import net + assert core.ConnectionWriter == net.ConnectionWriter + assert core.ConnectionWriter.__module__ == 'panda3d.net' + + def test_imports_direct(): import direct.actor.Actor import direct.actor.DistributedActor diff --git a/tests/tkpanels/test_Placer.py b/tests/tkpanels/test_Placer.py index 1a5072bf82..1cc146efeb 100644 --- a/tests/tkpanels/test_Placer.py +++ b/tests/tkpanels/test_Placer.py @@ -4,7 +4,7 @@ from direct.showbase.ShowBase import ShowBase from direct.tkpanels.Placer import Placer -def test_Placer(window): +def test_Placer(window, tk_toplevel): base = ShowBase() base.start_direct() root = Pmw.initialise()