Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Open Toontown 2024-03-30 19:09:37 -04:00
commit 6d182ccb5e
409 changed files with 14195 additions and 6697 deletions

View File

@ -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

View File

@ -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/

View File

@ -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

View File

@ -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

View File

@ -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
)

View File

@ -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}

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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

View File

@ -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,

View File

@ -46,9 +46,7 @@ void Extension<DCClass>::
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<DCClass>::
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<DCClass>::
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<DCClass>::
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);
}
/**

View File

@ -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;

View File

@ -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

16
direct/src/dist/_dist_hooks.py vendored Normal file
View File

@ -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 = []

View File

@ -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 = []

View File

@ -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 (

View File

@ -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)

View File

@ -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

View File

@ -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:

View File

@ -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

View File

@ -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

View File

@ -64,8 +64,6 @@ hidden = NodePath("hidden")
loader: Loader
direct: "DirectSession"
# Set direct notify categories now that we have config
directNotify.setDconfigLevels()

View File

@ -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;
}
/*

View File

@ -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):

View File

@ -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),

View File

@ -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)

View File

@ -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 `<Collide>` used with `<Line>` (#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

View File

@ -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

View File

@ -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 "")

File diff suppressed because it is too large Load Diff

View File

@ -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. */

View File

@ -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

View File

@ -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.

View File

@ -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;
}
/**

View File

@ -31,37 +31,6 @@ CPPFile(const Filename &filename, const Filename &filename_as_referenced,
_filename_as_referenced.set_text();
}
/**
*
*/
CPPFile::
CPPFile(const CPPFile &copy) :
_filename(copy._filename),
_filename_as_referenced(copy._filename_as_referenced),
_source(copy._source),
_pragma_once(copy._pragma_once)
{
}
/**
*
*/
void CPPFile::
operator = (const CPPFile &copy) {
_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,

View File

@ -34,9 +34,6 @@ public:
CPPFile(const Filename &filename = "",
const Filename &filename_as_referenced = "",
Source source = S_none);
CPPFile(const CPPFile &copy);
void operator = (const CPPFile &copy);
~CPPFile();
bool is_c_or_i_file() const;
static bool is_c_or_i_file(const Filename &filename);

View File

@ -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;

View File

@ -35,6 +35,7 @@ enum CPPInstanceIdentifierType {
IIT_array,
IIT_const,
IIT_volatile,
IIT_restrict,
IIT_paren,
IIT_func,
IIT_initializer,

View File

@ -13,6 +13,7 @@
#include "cppManifest.h"
#include "cppExpression.h"
#include "cppPreprocessor.h"
#include <ctype.h>
@ -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 &macro, const string &definition) :
CPPManifest(const CPPPreprocessor &parser, const string &macro, 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);

View File

@ -21,6 +21,7 @@
#include "cppBisonDefs.h"
#include "vector_string.h"
#include <unordered_set>
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 &macro, const std::string &definition);
typedef std::unordered_set<const CPPManifest *> Ignores;
CPPManifest(const CPPPreprocessor &parser, const std::string &args, const cppyyltype &loc);
CPPManifest(const CPPPreprocessor &parser, const std::string &macro, 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<ExpansionNode> 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 &parameter_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;
};

File diff suppressed because it is too large Load Diff

View File

@ -25,8 +25,8 @@
#include "vector_string.h"
#include <map>
#include <list>
#include <vector>
#include <unordered_map>
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<std::string, CPPManifest *> Manifests;
typedef std::unordered_map<std::string, CPPManifest *> Manifests;
Manifests _manifests;
typedef std::vector<CPPManifest *> 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<const CPPManifest *> &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<InputFile> Files;
Files _files;
InputFile *_infile = nullptr;
enum State {
S_normal, S_eof, S_nested, S_end_nested
@ -224,8 +227,8 @@ private:
std::vector<CPPToken> _saved_tokens;
int _warning_count;
int _error_count;
mutable int _warning_count;
mutable int _error_count;
bool _error_abort;
};

View File

@ -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);

View File

@ -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***";
}

View File

@ -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 {

File diff suppressed because it is too large Load Diff

View File

@ -30,13 +30,12 @@ public:
CPPToken(int token, const YYLTYPE &loc,
const std::string &str = std::string(),
const YYSTYPE &lval = YYSTYPE());
CPPToken(const CPPToken &copy);
void operator = (const CPPToken &copy);
static CPPToken eof();
bool is_eof() const;
void output(std::ostream &out) const;
void output_code(std::ostream &out) const;
int _token;
YYSTYPE _lval;

View File

@ -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"

View File

@ -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;
}
/**

View File

@ -207,8 +207,12 @@ MemoryHook(const MemoryHook &copy) :
_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__

View File

@ -20,6 +20,10 @@
#include "mutexImpl.h"
#include <map>
#ifdef __EMSCRIPTEN__
#include <emscripten/heap.h>
#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"

View File

@ -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

View File

@ -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 {

View File

@ -32,6 +32,15 @@
#include <unistd.h>
#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

View File

@ -62,7 +62,7 @@ extern char **environ;
#include <sys/sysctl.h>
#endif
#if defined(IS_LINUX) || defined(IS_FREEBSD)
#if (defined(IS_LINUX) || defined(IS_FREEBSD)) && !defined(__wasi__)
// For link_map and dlinfo.
#include <link.h>
#include <dlfcn.h>
@ -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;

View File

@ -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
}

View File

@ -134,8 +134,7 @@ PyObject *Extension<Filename>::
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());

View File

@ -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<istream>::
__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<ostream>::
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

View File

@ -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

View File

@ -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__ */

View File

@ -14,6 +14,8 @@
#include "pfstreamBuf.h"
#include <assert.h>
#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__

View File

@ -18,6 +18,9 @@
#include <string>
#include <stdio.h>
// 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__ */

View File

@ -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);

View File

@ -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.

View File

@ -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;

File diff suppressed because it is too large Load Diff

View File

@ -155,7 +155,7 @@ private:
int collapse_default_remaps(std::map<int, std::set<FunctionRemap *> > &map_sets,
int max_required_args);
void write_function_forset(std::ostream &out,
bool write_function_forset(std::ostream &out,
const std::set<FunctionRemap*> &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 {

View File

@ -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;
}

View File

@ -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);
}
}
}

View File

@ -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));

View File

@ -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 */

View File

@ -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) {

View File

@ -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);
}
/**

View File

@ -182,6 +182,16 @@ typedef std::map<std::string, Dtool_PyTypedObject *> 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()

View File

@ -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;

View File

@ -0,0 +1,5 @@
#pragma once
namespace std {
typedef __builtin_va_list va_list;
};

View File

@ -0,0 +1 @@
#include <emscripten/emscripten.h>

View File

@ -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(...)

View File

@ -0,0 +1,3 @@
#pragma once
#define EM_JS(ret, name, params, ...)

View File

@ -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 *);

View File

@ -0,0 +1,7 @@
#pragma once
#include <stdint.h>
#include <emscripten/emscripten.h>
typedef struct asyncify_data_s asyncify_data_t;
typedef struct emscripten_fiber_s emscripten_fiber_t;

View File

View File

@ -0,0 +1,21 @@
#pragma once
#include <stdtypedefs.h>
#include <time.h>
#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;
};

View File

@ -1,6 +1,6 @@
#ifndef STDARG_H
#define STDARG_H
typedef struct {} va_list[1];
typedef __builtin_va_list va_list;
#endif

View File

@ -1,3 +1,8 @@
#pragma once
#include <sys/types.h>
#include <time.h>
struct stat;
int stat(const char *restrict, struct stat *restrict);

View File

@ -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()

View File

@ -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

View File

@ -49,6 +49,8 @@ public:
virtual ~AndroidLogStream();
static std::ostream &out(NotifySeverity severity);
friend class Notify;
};
#endif // ANDROID

View File

@ -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.

View File

@ -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 <emscripten.h>
/**
*
*/
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__

View File

@ -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 <string>
#include <iostream>
/**
* 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

View File

@ -28,10 +28,13 @@
#ifdef ANDROID
#include <android/log.h>
#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
}

View File

@ -18,10 +18,6 @@
#include "configVariableBool.h"
#include "config_prc.h"
#ifdef ANDROID
#include "androidLogStream.h"
#endif
#include <time.h> // for strftime().
#include <assert.h>
@ -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

View File

@ -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"

View File

@ -18,7 +18,13 @@
#include "notifySeverity.h"
#include <map>
#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#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<std::string, NotifyCategory *> 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;
};

View File

@ -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)

View File

@ -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()

View File

@ -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", '"<auto>etc"', '"<auto>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')

View File

@ -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)

Some files were not shown because too many files have changed in this diff Show More