Merged with master, solved conflicts
@ -47,7 +47,7 @@ script:
|
||||
notifications:
|
||||
irc:
|
||||
channels:
|
||||
- "irc.freenode.org#stk"
|
||||
- "irc.freenode.org#supertuxkart"
|
||||
skip_join: false
|
||||
use_notice: true
|
||||
template:
|
||||
|
17
CHANGELOG.md
@ -1,4 +1,19 @@
|
||||
## SupertTuxKart 0.9.1
|
||||
## SuperTuxKart 0.9.2
|
||||
* Ghost replay races by Benau
|
||||
* Battle mode AI by Benau
|
||||
* Soccer mode AI by Benau
|
||||
* New icy soccer field by samuncle and Benau
|
||||
* New subsea track by samuncle
|
||||
* New volcano track by Ponzino
|
||||
* TTF font rendering by Benau
|
||||
* Kart properties refactor by Flakebi
|
||||
* Scripting work under the hood
|
||||
* Work on the track editor by mhp
|
||||
* Tweak to challenges
|
||||
* New farm track song by 0zone0ne and Krobonil
|
||||
* Bugfixes
|
||||
|
||||
## SuperTuxKart 0.9.1
|
||||
* Many bug fixes
|
||||
* Started to use scripting in tracks
|
||||
* Significant audio performance improvements
|
||||
|
@ -68,6 +68,7 @@ add_subdirectory("${PROJECT_SOURCE_DIR}/lib/enet")
|
||||
include_directories("${PROJECT_SOURCE_DIR}/lib/enet/include")
|
||||
|
||||
# Build glew library
|
||||
add_definitions(-DGLEW_NO_GLU)
|
||||
add_subdirectory("${PROJECT_SOURCE_DIR}/lib/glew")
|
||||
include_directories("${PROJECT_SOURCE_DIR}/lib/glew/include")
|
||||
|
||||
@ -117,8 +118,8 @@ endif()
|
||||
include_directories(${STK_SOURCE_DIR})
|
||||
|
||||
if(APPLE)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -arch i386")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -arch i386 -F/Library/Frameworks")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -arch x86_64")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -arch x86_64 -F/Library/Frameworks")
|
||||
elseif(MSVC)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP") # Enable multi-processor compilation (faster)
|
||||
endif()
|
||||
@ -258,7 +259,7 @@ endif()
|
||||
add_definitions(-DHAVE_OGGVORBIS)
|
||||
|
||||
if(WIN32)
|
||||
configure_file("${STK_SOURCE_DIR}/windows_installer/icon_rc.template" "${PROJECT_BINARY_DIR}/tmp/icon.rc")
|
||||
configure_file("${STK_SOURCE_DIR}/../tools/windows_installer/icon_rc.template" "${PROJECT_BINARY_DIR}/tmp/icon.rc")
|
||||
endif()
|
||||
|
||||
# Provides list of source and header files (STK_SOURCES and STK_HEADERS)
|
||||
@ -365,12 +366,17 @@ if(UNIX AND NOT APPLE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# FreeBSD does not search in /usr/local/lib, but at least Freetype is installed there :(
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
|
||||
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L/usr/local/lib")
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
# In theory it would be cleaner to let CMake detect the right dependencies. In practice, this means that if a OSX user has
|
||||
# unix-style installs of Vorbis/Ogg/OpenAL/etc. they will be picked up over our frameworks. This is blocking when I make releases :
|
||||
# the mac I use to make STK releases does have other installs of vorbis/ogg/etc. which aren't compatible with STK, so letting
|
||||
# CMake pick the library it wants essentially means I can't build.
|
||||
set_target_properties(supertuxkart PROPERTIES LINK_FLAGS "-arch i386 -F/Library/Frameworks -framework OpenAL -framework Ogg -framework Vorbis")
|
||||
set_target_properties(supertuxkart PROPERTIES LINK_FLAGS "-arch x86_64 -F/Library/Frameworks -framework OpenAL -framework Ogg -framework Vorbis")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -I/Library/Frameworks/OpenAL.framework/Versions/A/Headers")
|
||||
endif()
|
||||
|
||||
|
10
INSTALL.md
@ -1,6 +1,7 @@
|
||||
# SuperTuxKart Installation Instructions
|
||||
|
||||
Note: If you obtained this source code from Github, you also need to download the game assets from Sourceforge using SVN.
|
||||
Note: If you obtained this source code from Github, you also need to download
|
||||
the game assets from Sourceforge using SVN.
|
||||
|
||||
`svn checkout https://svn.code.sf.net/p/supertuxkart/code/stk-assets stk-assets`
|
||||
|
||||
@ -16,6 +17,7 @@ First, make sure that you have the following packages installed:
|
||||
* OpenAL (recommended: openal-soft-devel)
|
||||
* Ogg (libogg-dev)
|
||||
* Vorbis (libvorbis-dev)
|
||||
* Freetype (libfreetype6-dev)
|
||||
* libcurl (libcurl-devel)
|
||||
* libbluetooth (bluez-devel)
|
||||
* libpng (libpng-devel)
|
||||
@ -25,8 +27,10 @@ First, make sure that you have the following packages installed:
|
||||
Ubuntu command:
|
||||
|
||||
```
|
||||
sudo apt-get install autoconf automake build-essential cmake libogg-dev libvorbis-dev libopenal-dev libxxf86vm-dev \
|
||||
libgl1-mesa-dev libglu1-mesa-dev libcurl4-openssl-dev libfribidi-dev libbluetooth-dev libxrandr-dev
|
||||
sudo apt-get install build-essential cmake libbluetooth-dev \
|
||||
libcurl4-gnutls-dev libfreetype6-dev libfribidi-dev libgl1-mesa-dev \
|
||||
libjpeg-dev libogg-dev libopenal-dev libpng-dev libvorbis-dev libxrandr-dev \
|
||||
mesa-common-dev pkg-config zlib1g-dev
|
||||
```
|
||||
|
||||
Unpack the files from the tarball like this:
|
||||
|
40
README.md
@ -1,59 +1,45 @@
|
||||
# SuperTuxKart
|
||||
[](https://travis-ci.org/supertuxkart/stk-code)
|
||||
|
||||
SuperTuxKart is a free kart racing game. It is focusing on fun and
|
||||
not on realistic kart physics. Instruction can be found on the
|
||||
in-game help page.
|
||||
SuperTuxKart is a free kart racing game. It focuses on fun and not on realistic kart physics. Instructions can be found on the in-game help page.
|
||||
|
||||
The SuperTuxKart homepage can be found at: <http://supertuxkart.sourceforge.net>
|
||||
|
||||
The official SuperTuxKart forum is at <http://supertuxkart.sourceforge.net/forum>. If you need support,
|
||||
this would be the best place to start.
|
||||
The official SuperTuxKart forum is at <http://supertuxkart.sourceforge.net/forum>. If you need support, this would be the best place to start.
|
||||
|
||||
Hope you enjoy the game.
|
||||
|
||||
-- The SuperTuxKart development team.
|
||||
|
||||
|
||||
## Hardware Requirements
|
||||
* You need a 3D graphics card. (NVIDIA GeForce 8xxx and higher, ATI Radeon HD 4xxx and higher or Intel HD 3000 and higher)
|
||||
* You need a 3D graphics card. (NVIDIA GeForce 8xxx and higher, ATI Radeon HD 4xxx and higher or Intel HD 3000 and higher.)
|
||||
* You should have a CPU that's running at 1GHz or better.
|
||||
* You'll need at least 512 MB of free VRAM (video memory).
|
||||
* Disk space: 400MB
|
||||
* Ideally, you want a joystick with at least 6 buttons.
|
||||
|
||||
|
||||
## Compiling SuperTuxKart
|
||||
|
||||
### Windows
|
||||
1. Install VS 2013 (or later). The free express versions work fine.
|
||||
2. Download and install a source package - either a released package or from our [git/svn repositories](http://supertuxkart.sourceforge.net/Source_control)
|
||||
3. Download the latest dependency package depdendencies_for_0.8.2.zip from [here](https://sourceforge.net/projects/supertuxkart/files/SuperTuxKart%20Dependencies/Windows/). Unzip it in the root directory, so that the dependencies directory is next to the src and data directory (if you are updating from a previous dependency package, you can delete the .dll files in the root directory, they are not needed anymore).
|
||||
4. Download cmake and install it. Then start cmake-gui and select the STK root directory as 'Where is the source code', and a new directory in the root directory (next to src, data etc) as build directory (for now I assume that this directory is called bld).
|
||||
5. Click on configure. You will be asked to create the directory (yes), then for your VS version. Make sure to select the right version (be aware of the easy to confuse version numbers: VS 2013 = version 12). Click on configure, then generate. This will create the directory 'bld', and a VS solution in that directory.
|
||||
6. In Visual Studio open the project file generated in the 'bld' folder
|
||||
2. Download and install a source package - either a released package or from our [git/svn repositories](http://supertuxkart.sourceforge.net/Source_control).
|
||||
3. Download the latest dependency package from [here](https://sourceforge.net/projects/supertuxkart/files/SuperTuxKart%20Dependencies/Windows/). Unzip it in the root directory, so that the dependencies directory is next to the src and data directories (if you are updating from a previous dependency package, you can delete the .dll files in the root directory, they are not needed anymore).
|
||||
4. Download cmake and install it. Then start cmake-gui and select the STK root directory as 'Where is the source code', and a new directory in the root directory (next to src, data etc) as the build directory (for now I assume that this directory is called bld).
|
||||
5. Click on configure. You will be asked to create the directory (yes), then for your VS version. Make sure you select the right version (be aware of the easy to confuse version numbers: VS 2013 = version 12). Click on configure, then generate. This will create the directory 'bld', and a VS solution in that directory.
|
||||
6. In Visual Studio open the project file generated in the 'bld' folder.
|
||||
7. Right click on the supertuxkart project in the solution explorer, and select "Set as StartUp Project".
|
||||
8. Select Build->Build Solution (or press F7) to compile.
|
||||
|
||||
Compilation with cygwin is not officially supported, but
|
||||
this has been done (check with the forum for details).
|
||||
Compilation with cygwin is not officially supported, but this has been done (check with the forum for details).
|
||||
|
||||
### Mac OS X
|
||||
The latest information about compilation on Mac are on our wiki:
|
||||
<http://supertuxkart.sourceforge.net/Building_and_packaging_on_OSX>
|
||||
The Xcode project file is in `/src/ide/Xcode/`, but it still
|
||||
requires that all dependencies are installed as explained on the wiki.
|
||||
The latest information about compilation on Mac are on our wiki: <http://supertuxkart.sourceforge.net/Building_and_packaging_on_OSX>
|
||||
|
||||
### UNIX
|
||||
See [`INSTALL.md`](INSTALL.md) for details.
|
||||
|
||||
|
||||
## License
|
||||
This software is released under the GNU General Public License (GPL) which
|
||||
can be found in the file [`COPYING`](/COPYING) in the same directory as this file.
|
||||
Information about the licenses for artwork are contained in
|
||||
`data/licenses`.
|
||||
|
||||
This software is released under the GNU General Public License (GPL) which can be found in the file [`COPYING`](/COPYING) in the same directory as this file. Information about the licenses for artwork are contained in `data/licenses`.
|
||||
|
||||
## 3D coordinates
|
||||
A reminder for those looking at the code and 3d models:
|
||||
@ -62,6 +48,4 @@ STK : X right, Y up, Z forwards
|
||||
|
||||
Blender: X right, Y forwards, Z up
|
||||
|
||||
The exporters perform the needed transform, so in Blender you just work
|
||||
with XY plane as ground, and things will appear fine in STK (using XZ
|
||||
as ground in the code, obviously).
|
||||
The exporters perform the needed transform, so in Blender you just work with XY plane as ground, and things will appear fine in STK (using XZ as ground in the code, obviously).
|
||||
|
BIN
data/CREDITS
@ -1,19 +1,19 @@
|
||||
<?xml version="1.0"?>
|
||||
<challenge version="2">
|
||||
<track id="subsea" laps="2"/>
|
||||
<track id="abyss" laps="3"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="0"/>
|
||||
|
||||
<hard>
|
||||
<karts number="5"/>
|
||||
<requirements position="1" time="205"/>
|
||||
<requirements position="1" time="160"/>
|
||||
</hard>
|
||||
<medium>
|
||||
<karts number="4"/>
|
||||
<requirements time="225"/>
|
||||
<requirements time="185"/>
|
||||
</medium>
|
||||
<easy>
|
||||
<karts number="4"/>
|
||||
<requirements time="290"/>
|
||||
<requirements time="270"/>
|
||||
</easy>
|
||||
</challenge>
|
@ -2,7 +2,7 @@
|
||||
<challenge version="2">
|
||||
<track id="cocoa_temple" laps="3"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="15"/>
|
||||
<requirements trophies="5"/>
|
||||
|
||||
<hard>
|
||||
<karts number="5"/>
|
||||
|
19
data/challenges/volcano_island.challenge
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0"?>
|
||||
<challenge version="2">
|
||||
<track id="volcano_island" laps="2"/>
|
||||
<mode major="single" minor="quickrace"/>
|
||||
<requirements trophies="15"/>
|
||||
|
||||
<hard>
|
||||
<karts number="5"/>
|
||||
<requirements position="1"/>
|
||||
</hard>
|
||||
<medium>
|
||||
<karts number="4"/>
|
||||
<requirements position="1"/>
|
||||
</medium>
|
||||
<easy>
|
||||
<karts number="4"/>
|
||||
<requirements position="1"/>
|
||||
</easy>
|
||||
</challenge>
|
@ -4,7 +4,7 @@
|
||||
<track id="sandtrack" laps="3" reverse="false" />
|
||||
<track id="farm" laps="3" reverse="false" />
|
||||
<track id="olivermath" laps="4" reverse="false" />
|
||||
<track id="subsea" laps="2" reverse="false" />
|
||||
<track id="abyss" laps="3" reverse="false" />
|
||||
<track id="scotland" laps="3" reverse="false" />
|
||||
|
||||
</supertuxkart_grand_prix>
|
||||
|
@ -5,7 +5,7 @@
|
||||
<track id="greenvalley" laps="2" reverse="false" />
|
||||
<track id="mansion" laps="3" reverse="false" />
|
||||
<track id="stk_enterprise" laps="3" reverse="false" />
|
||||
<track id="city" laps="2" reverse="false" />
|
||||
<track id="volcano_island" laps="2" reverse="false" />
|
||||
|
||||
</supertuxkart_grand_prix>
|
||||
|
||||
|
@ -4,21 +4,24 @@
|
||||
<card is="Intel(R) HD Graphics 3000" os="windows" disable="AdvancedPipeline"/>
|
||||
<card is="Intel(R) HD Graphics 3000" os="windows" disable="FramebufferSRGBWorking"/>
|
||||
<card contains="Intel" os="osx" disable="GI"/>
|
||||
<card contains="Intel" os="linux" version="<12.0" disable="ComputeShader"/>
|
||||
<card contains="Intel" os="linux" version="<12.0" disable="FramebufferSRGBCapable"/>
|
||||
<card contains="Intel" disable="TextureCompressionS3TC"/>
|
||||
<card contains="Intel" os="linux" version="<11.2" disable="ComputeShader"/>
|
||||
<card contains="Intel" os="linux" version="<11.2" disable="GeometryShader"/>
|
||||
<card contains="Intel" os="linux" version="<16.0" disable="FramebufferSRGBCapable"/>
|
||||
<card contains="Intel" os="linux" version="<11.2" disable="TextureCompressionS3TC"/>
|
||||
<card contains="Intel" os="windows" disable="TextureCompressionS3TC"/>
|
||||
<card contains="Intel" os="osx" disable="TextureCompressionS3TC"/>
|
||||
<card contains="Intel" os="windows" disable="HighDefinitionTextures"/>
|
||||
<card contains="NVIDIA" os="windows" version="<344.65" disable="BufferStorage"/>
|
||||
<card contains="NVIDIA" os="linux" version="<343.22" disable="BufferStorage"/>
|
||||
<card contains="NVIDIA" disable="ShaderAtomicCounters"/>
|
||||
<card contains="Mesa" os="linux" version="<10.3" disable="BufferStorage"/>
|
||||
<card contains="Mesa" os="linux" version="<10.3" disable="DriverRecentEnough"/>
|
||||
<card contains="Mesa" os="linux" version="<10.6" disable="GeometryShader4"/>
|
||||
<card contains="Mesa" os="linux" disable="TextureCompressionS3TC"/>
|
||||
<card contains="Mesa" os="linux" version="<11.2" disable="GeometryShader"/>
|
||||
<card contains="Mesa" os="linux" version="<11.2" disable="TextureCompressionS3TC"/>
|
||||
<card contains="Gallium" os="linux" version="<10.3" disable="BufferStorage"/>
|
||||
<card contains="Gallium" os="linux" version="<10.3" disable="DriverRecentEnough"/>
|
||||
<card contains="Gallium" os="linux" version="<10.6" disable="GeometryShader4"/>
|
||||
<card contains="Gallium" os="linux" disable="TextureCompressionS3TC"/>
|
||||
<card contains="Gallium" os="linux" version="<11.2" disable="GeometryShader"/>
|
||||
<card contains="Gallium" os="linux" version="<11.2" disable="TextureCompressionS3TC"/>
|
||||
<!-- On osx radeon appears to have different version numbers, e.g.
|
||||
1.32.20 -->
|
||||
<card contains="Radeon" os="linux" version="<14.300" disable="DriverRecentEnough"/>
|
||||
|
40
data/gui/ghost_replay_info_dialog.stkgui
Normal file
@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<stkgui>
|
||||
<div x="5%" y="5%" width="90%" height="90%" layout="vertical-row">
|
||||
<div x="5%" y="0%" width="90%" proportion="6" layout="horizontal-row">
|
||||
<div width="40%" height="100%" layout="vertical-row">
|
||||
<icon id="icon" align="center" width="100%" icon="gui/loading.png" />
|
||||
</div>
|
||||
<div width="60%" height="50%" layout="vertical-row">
|
||||
<label id="name" width="100%" text_align="left"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div width="90%" align="center" layout="vertical-row" height="fit">
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
<checkbox width="fit" id="record-race" I18N="Ghost replay info action" text_align="left"/>
|
||||
<spacer width="10"/>
|
||||
<label proportion="1" id="record-race-text" height="100%" text_align="left" I18N="Ghost replay info action" text="Record the race for ghost replay"/>
|
||||
</div>
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
<checkbox width="fit" id="watch-only" I18N="Ghost replay info action" text_align="left"/>
|
||||
<spacer width="10"/>
|
||||
<label proportion="1" id="watch-only-text" height="100%" text_align="left" I18N="Ghost replay info action" text="Watch replay only"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div width="80%" proportion="5" align="center">
|
||||
<buttonbar id="actions" x="0" y="0" height="100%" width="100%" align="center">
|
||||
<icon-button id="start" width="128" height="128"
|
||||
icon="gui/green_check.png"
|
||||
I18N="Ghost replay info screen action" text="Start Race" />
|
||||
<icon-button id="remove" width="128" height="128"
|
||||
icon="gui/remove.png"
|
||||
I18N="Ghost replay info action" text="Remove" />
|
||||
<icon-button id="back" width="128" height="128"
|
||||
icon="gui/back.png"
|
||||
I18N="Ghost replay info action" text="Back" />
|
||||
</buttonbar>
|
||||
</div>
|
||||
</div>
|
||||
</stkgui>
|
26
data/gui/ghost_replay_selection.stkgui
Normal file
@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<stkgui>
|
||||
<div x="0%" y="1%" width="100%" height="98%" layout="vertical-row" >
|
||||
|
||||
<div x="0" y="0" width="100%" layout="horizontal-row" height="8%">
|
||||
<icon-button id="back" height="100%" icon="gui/back.png"/>
|
||||
<header text_align="center" proportion="1" I18N="In the ghost replay selection screen" text="Ghost Replay Selection" align="center"/>
|
||||
<icon-button id="reload" height="90%" icon="gui/restart.png"/>
|
||||
</div>
|
||||
|
||||
<box proportion="1" width="98%" align="center" layout="vertical-row" padding="6">
|
||||
<list id="replay_list" x="0" y="0" width="100%" height="100%"/>
|
||||
</box>
|
||||
|
||||
<div width="99%" align="center" layout="vertical-row" height="fit">
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
<checkbox width="fit" id="replay_difficulty_toggle" text_align="left"/>
|
||||
<spacer width="10"/>
|
||||
<label proportion="1" height="100%" text_align="left" I18N="In the ghost replay selection screen" text="Only show replays matching the current difficulty"/>
|
||||
</div>
|
||||
</div>
|
||||
<spacer width="100%" height="1%" />
|
||||
<button x="1%" id="record-ghost" I18N="In the ghost replay selection screen" text="Record ghost replay"/>
|
||||
|
||||
</div>
|
||||
</stkgui>
|
@ -1,8 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<stkgui>
|
||||
<div x="2%" y="2%" width="96%" height="96%" layout="horizontal-row">
|
||||
<button id="continue" width="250" align="bottom" text="Continue"/>
|
||||
<spacer width="20"/>
|
||||
<button id="save" width="250" align="bottom" text="Save Grand Prix"/>
|
||||
<div x="2%" y="2%" width="96%" height="96%" layout="vertical-row">
|
||||
<spacer proportion="1"/>
|
||||
<button id="save" width="450" align="center" text="Save Grand Prix"/>
|
||||
<spacer height="20"/>
|
||||
<button id="continue" width="450" align="center" text="Continue"/>
|
||||
</div>
|
||||
</stkgui>
|
||||
|
@ -1,9 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<stkgui>
|
||||
<div x="2%" y="2%" width="96%" height="96%" layout="horizontal-row">
|
||||
<button id="continue" width="250" align="bottom" text="Continue"/>
|
||||
<spacer width="20"/>
|
||||
<button id="save" width="250" align="bottom" text="Save Grand Prix"/>
|
||||
<div x="2%" y="2%" width="96%" height="96%" layout="vertical-row">
|
||||
<spacer proportion="1"/>
|
||||
<button id="save" width="450" align="center" text="Save Grand Prix"/>
|
||||
<spacer height="20"/>
|
||||
<button id="continue" width="450" align="center" text="Continue"/>
|
||||
</div>
|
||||
</stkgui>
|
||||
|
||||
|
BIN
data/gui/mode_ghost.png
Normal file
After Width: | Height: | Size: 11 KiB |
@ -17,6 +17,42 @@
|
||||
<label proportion="1" text_align="left" I18N="In the server creation screen" text="Max. number of players"/>
|
||||
<gauge id="max_players" proportion="1" min_value="2" max_value="12"/>
|
||||
</div>
|
||||
|
||||
<spacer height="20" width="20"/>
|
||||
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
<label proportion="1" text_align="left" I18N="In the server creation screen" text="Password (optional)"/>
|
||||
<textbox proportion="1" id="password" I18N="In the server creation screen"/>
|
||||
</div>
|
||||
|
||||
<spacer height="20" width="20"/>
|
||||
|
||||
<label width="100%" height="fit" text_align="left" I18N="In the server creation screen" text="Difficulty"/>
|
||||
<!--<gauge id="difficulty" proportion="1" min_value="1" max_value="4"/>-->
|
||||
<ribbon id="difficulty" height="135" width="90%" align="center">
|
||||
<icon-button id="novice" width="128" height="128" icon="gui/difficulty_easy.png"
|
||||
I18N="Difficulty" text="Novice"/>
|
||||
<icon-button id="intermediate" width="128" height="128" icon="gui/difficulty_medium.png"
|
||||
I18N="Difficulty" text="Intermediate"/>
|
||||
<icon-button id="expert" width="128" height="128" icon="gui/difficulty_hard.png"
|
||||
I18N="Difficulty" text="Expert"/>
|
||||
<icon-button id="best" width="128" height="128" icon="gui/difficulty_best.png"
|
||||
I18N="Difficulty" text="SuperTux"/>
|
||||
</ribbon>
|
||||
|
||||
<spacer height="20" width="20"/>
|
||||
|
||||
<label width="100%" height="fit" text_align="left" I18N="In the server creation screen" text="Game mode"/>
|
||||
<ribbon id="gamemode" height="135" width="50%" align="center">
|
||||
<icon-button id="normal" width="128" height="128" icon="gui/mode_normal.png"
|
||||
I18N="Multiplayer game mode" text="Normal Race"/>
|
||||
<icon-button id="timetrial" width="128" height="128" icon="gui/mode_tt.png"
|
||||
I18N="Multiplayer game mode" text="Time Trial"/>
|
||||
</ribbon>
|
||||
<!--
|
||||
<scrollable_toolbar id="gamemode" height="135" width="90%" label_location="bottom" align="center"
|
||||
child_width="135" child_height="135" />
|
||||
-->
|
||||
</div>
|
||||
|
||||
<label id="info" proportion="1" width="100%" align="center" text_align="center" word_wrap="true" text=""/>
|
||||
|
@ -10,6 +10,14 @@
|
||||
<label proportion="1" text_align="left" I18N="In the networking lobby" text="Server name:"/>
|
||||
<label proportion="2" text_align="left" id="server_name" text=""/>
|
||||
</div>
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
<label proportion="1" text_align="left" I18N="In the networking lobby" text="Difficulty:"/>
|
||||
<label proportion="2" text_align="left" id="server_difficulty" text=""/>
|
||||
</div>
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
<label proportion="1" text_align="left" I18N="In the networking lobby" text="Game mode:"/>
|
||||
<label proportion="2" text_align="left" id="server_game_mode" text=""/>
|
||||
</div>
|
||||
</box>
|
||||
<spacer width="20" height="20"/>
|
||||
<box proportion="1" height="100%" layout="vertical-row">
|
||||
@ -27,7 +35,7 @@
|
||||
<box id="actions" proportion="1" height="100%" layout="vertical-row">
|
||||
<!-- <label I18N="In networking lobby" word_wrap="true" text="actions" align="center" text-align="center"/>
|
||||
-->
|
||||
<icon-button id="start" width="64" height="64" icon="gui/green_check.png"
|
||||
<icon-button id="start" width="64" height="64" icon="gui/green_check.png" align="center"
|
||||
I18N="In the network lobby" text="Start Race"/>
|
||||
|
||||
</box>
|
||||
|
@ -1,63 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<stkgui>
|
||||
<div x="0" y="0" width="100%" height="fit" layout="vertical-row">
|
||||
<button id="user-id" width="20%" height="fit" align="right"/>
|
||||
</div>
|
||||
|
||||
<div x="2%" y="2%" width="96%" height="96%" layout="vertical-row" >
|
||||
|
||||
<header text_align="center" width="80%" align="center" I18N="In the online multiplayer screen" text="Online Multiplayer"/>
|
||||
|
||||
<spacer height="5%" width="25"/>
|
||||
<box width="100%" height="38%" padding="10" layout="vertical-row">
|
||||
<bright width="100%" text="Local Networking" align="center" text_align="left" />
|
||||
|
||||
<buttonbar id="lan" proportion="2" width="90%" align="center">
|
||||
<icon-button id="find_lan_server" width="128" height="128"
|
||||
icon="gui/online/menu_find_server.png" focus_icon="gui/online/menu_find_server_hover.png"
|
||||
I18N="In the online multiplayer screen" text="Find Server"/>
|
||||
<icon-button id="create_lan_server" width="128" height="128"
|
||||
icon="gui/online/menu_create_server.png" focus_icon="gui/online/menu_create_server_hover.png"
|
||||
I18N="In the online multiplayer screen" text="Create Server"/>
|
||||
<icon-button id="manage_user" width="128" height="128"
|
||||
icon="gui/options_players.png"
|
||||
I18N="In the online multiplayer screen" text="Users"/>
|
||||
</buttonbar>
|
||||
</box>
|
||||
|
||||
<spacer height="5%" width="25"/>
|
||||
|
||||
<box width="100%" height="38%" padding="10" layout="vertical-row">
|
||||
<bright width="100%" text="Global Networking" align="center" text_align="left" />
|
||||
|
||||
<buttonbar id="menu_top_row" proportion="2" width="90%" align="center">
|
||||
<icon-button id="find_wan_server" width="128" height="128"
|
||||
icon="gui/online/menu_find_server.png" focus_icon="gui/online/menu_find_server_hover.png"
|
||||
I18N="In the online multiplayer screen" text="Find Server"/>
|
||||
<icon-button id="create_wan_server" width="128" height="128"
|
||||
icon="gui/online/menu_create_server.png" focus_icon="gui/online/menu_create_server_hover.png"
|
||||
I18N="In the online multiplayer screen" text="Create Server"/>
|
||||
<icon-button id="quick_wan_play" width="128" height="128"
|
||||
icon="gui/online/menu_quick_play.png" focus_icon="gui/online/menu_quick_play_hover.png"
|
||||
I18N="In the online multiplayer screen" text="Quick Play"/>
|
||||
</buttonbar>
|
||||
</box>
|
||||
|
||||
<bottombar x="2%" width="96%" height="10%" layout="horizontal-row">
|
||||
<label text_align="left" align="center" height="100%" id="online_status" proportion="1" text=""/>
|
||||
|
||||
<spacer width="10" height="10" />
|
||||
|
||||
<buttonbar id="menu_bottomrow" x="0" y="0" width="12%" height="100%" align="center">
|
||||
<icon-button id="profile" width="64" height="64" icon="gui/green_check.png" extend_label="50"
|
||||
I18N="In the online multiplayer screen" text="Profile" label_location="hover"/>
|
||||
<icon-button id="sign_out" width="64" height="64" icon="gui/main_quit.png" extend_label="70"
|
||||
I18N="In the online multiplayer screen" text="Log Out" label_location="hover"/>
|
||||
</buttonbar>
|
||||
|
||||
</bottombar>
|
||||
|
||||
</div>
|
||||
|
||||
<icon-button id="back" x="0" y="0" height="8%" icon="gui/back.png"/>
|
||||
</stkgui>
|
@ -9,6 +9,7 @@
|
||||
<spacer height="25" width="10"/>
|
||||
|
||||
<tabs id="profile_tabs" height="10%" max_height="110" x="2%" width="98%" align="center">
|
||||
<icon-button id="tab_servers" width="128" height="128" icon="gui/main_network.png"/>
|
||||
<icon-button id="tab_achievements" width="128" height="128" icon="gui/gp_copy.png"
|
||||
I18N="Section in the profile screen" text="Achievements"/>
|
||||
<icon-button id="tab_friends" width="128" height="128" icon="gui/options_players.png"/>
|
||||
|
@ -9,6 +9,7 @@
|
||||
<spacer height="25" width="10"/>
|
||||
|
||||
<tabs id="profile_tabs" height="10%" max_height="110" x="2%" width="98%" align="center">
|
||||
<icon-button id="tab_servers" width="128" height="128" icon="gui/main_network.png"/>
|
||||
<icon-button id="tab_achievements" width="128" height="128" icon="gui/gp_copy.png"/>
|
||||
<icon-button id="tab_friends" width="128" height="128" icon="gui/options_players.png"
|
||||
I18N="Section in the profile screen" text="Friends"/>
|
||||
|
61
data/gui/online/profile_servers.stkgui
Normal file
@ -0,0 +1,61 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<stkgui>
|
||||
<icon-button id="back" x="0" y="0" height="8%" icon="gui/back.png"/>
|
||||
|
||||
<div x="1%" y="1%" width="98%" height="98%" layout="vertical-row" >
|
||||
<header id="title" text_align="center" width="80%" align="center" text="..."/>
|
||||
|
||||
<spacer height="25" width="10"/>
|
||||
|
||||
<tabs id="profile_tabs" height="10%" max_height="110" x="2%" width="98%" align="center">
|
||||
<icon-button id="tab_servers" width="128" height="128" icon="gui/main_network.png" I18N="Section in the profile screen" text="Servers"/>
|
||||
<icon-button id="tab_achievements" width="128" height="128" icon="gui/gp_copy.png"/>
|
||||
<icon-button id="tab_friends" width="128" height="128" icon="gui/options_players.png" />
|
||||
<icon-button id="tab_settings" width="128" height="128" icon="gui/main_options.png" />
|
||||
</tabs>
|
||||
|
||||
<box proportion="1" width="100%" layout="vertical-row">
|
||||
<div x="1%" y="2%" width="98%" height="96%" layout="vertical-row" >
|
||||
|
||||
<spacer height="5%" width="25"/>
|
||||
|
||||
<box width="100%" proportion="1" padding="10" layout="vertical-row">
|
||||
<bright width="100%" text="Local Networking" align="center" text_align="left" />
|
||||
|
||||
<buttonbar id="lan" proportion="2" width="90%" align="center">
|
||||
<icon-button id="find_lan_server" width="128" height="128"
|
||||
icon="gui/online/menu_find_server.png" focus_icon="gui/online/menu_find_server_hover.png"
|
||||
I18N="In the online multiplayer screen" text="Find Server"/>
|
||||
<icon-button id="create_lan_server" width="128" height="128"
|
||||
icon="gui/online/menu_create_server.png" focus_icon="gui/online/menu_create_server_hover.png"
|
||||
I18N="In the online multiplayer screen" text="Create Server"/>
|
||||
<!--
|
||||
<icon-button id="manage_user" width="128" height="128"
|
||||
icon="gui/options_players.png"
|
||||
I18N="In the online multiplayer screen" text="Users"/>
|
||||
-->
|
||||
</buttonbar>
|
||||
</box>
|
||||
|
||||
<spacer height="5%" width="25"/>
|
||||
|
||||
<box width="100%" proportion="1" padding="10" layout="vertical-row">
|
||||
<bright width="100%" text="Global Networking" align="center" text_align="left" />
|
||||
|
||||
<buttonbar id="wan" proportion="2" width="90%" align="center">
|
||||
<icon-button id="find_wan_server" width="128" height="128"
|
||||
icon="gui/online/menu_find_server.png" focus_icon="gui/online/menu_find_server_hover.png"
|
||||
I18N="In the online multiplayer screen" text="Find Server"/>
|
||||
<icon-button id="create_wan_server" width="128" height="128"
|
||||
icon="gui/online/menu_create_server.png" focus_icon="gui/online/menu_create_server_hover.png"
|
||||
I18N="In the online multiplayer screen" text="Create Server"/>
|
||||
<icon-button id="quick_wan_play" width="128" height="128"
|
||||
icon="gui/online/menu_quick_play.png" focus_icon="gui/online/menu_quick_play_hover.png"
|
||||
I18N="In the online multiplayer screen" text="Quick Play"/>
|
||||
</buttonbar>
|
||||
</box>
|
||||
|
||||
</div>
|
||||
</box>
|
||||
</div>
|
||||
</stkgui>
|
@ -8,6 +8,7 @@
|
||||
<spacer height="25" width="10"/>
|
||||
|
||||
<tabs id="profile_tabs" height="10%" max_height="110" x="2%" width="98%" align="center">
|
||||
<icon-button id="tab_servers" width="128" height="128" icon="gui/main_network.png"/>
|
||||
<icon-button id="tab_achievements" width="128" height="128" icon="gui/gp_copy.png"/>
|
||||
<icon-button id="tab_friends" width="128" height="128" icon="gui/options_players.png" />
|
||||
<icon-button id="tab_settings" width="128" height="128" icon="gui/main_options.png"
|
||||
|
@ -8,10 +8,24 @@
|
||||
<spacer height="20" width="50"/>
|
||||
|
||||
<div width="80%" align="center" layout="vertical-row" height="fit" >
|
||||
<!--
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
<label proportion="1" text_align="left" I18N="In the server info dialog" text="Name"/>
|
||||
<label id="name" proportion="2" text_align="left" text=""/>
|
||||
</div>
|
||||
-->
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
<label proportion="1" text_align="left" I18N="In the networking lobby" text="Server name:"/>
|
||||
<label proportion="2" text_align="left" id="server_name" text=""/>
|
||||
</div>
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
<label proportion="1" text_align="left" I18N="In the networking lobby" text="Difficulty:"/>
|
||||
<label proportion="2" text_align="left" id="server_difficulty" text=""/>
|
||||
</div>
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
<label proportion="1" text_align="left" I18N="In the networking lobby" text="Game mode:"/>
|
||||
<label proportion="2" text_align="left" id="server_game_mode" text=""/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<spacer height="20" width="50"/>
|
||||
|
11
data/gui/online/waiting_for_others.stkgui
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<stkgui>
|
||||
<div x="2%" y="5%" width="96%" height="90%" layout="vertical-row" >
|
||||
|
||||
<header id="title" width="96%" height="fit" text_align="center" I18N="Networking screen" text="Waiting for the others..."/>
|
||||
|
||||
<spacer height="40" width="50"/>
|
||||
|
||||
<label proportion="1" width="100%" text_align="left" id="lblDetails"/>
|
||||
</div>
|
||||
</stkgui>
|
@ -3,9 +3,9 @@
|
||||
<icon-button id="back" x="0" y="0" height="8%" icon="gui/back.png"/>
|
||||
|
||||
<div x="2%" y="2%" width="96%" height="96%" layout="vertical-row">
|
||||
<header id="name" height="5%" width="80%" align="center" text_align="center"/>
|
||||
<header id="name" height="7%" width="80%" align="center" text_align="center"/>
|
||||
|
||||
<spacer width="1" height="5%"/>
|
||||
<spacer width="1" height="1%"/>
|
||||
|
||||
<box width="100%" height="40%" padding="10" layout="horizontal-row">
|
||||
<!-- Left pane -->
|
||||
@ -49,8 +49,8 @@
|
||||
</div>
|
||||
|
||||
</box>
|
||||
<spacer width="1" height="5%"/>
|
||||
<box width="100%" height="25%" padding="15" layout="vertical-row">
|
||||
<spacer width="1" height="1%"/>
|
||||
<box width="100%" height="33%" padding="15" layout="vertical-row">
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
<label id="lap-text" proportion="1" I18N="In the track info screen" text="Number of laps" text_align="right"/>
|
||||
<spacer width="40"/>
|
||||
@ -70,17 +70,26 @@
|
||||
</div>
|
||||
<spacer height="10"/>
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
<label id="reverse-text" proportion="1" I18N="In the track info screen" text="Drive in reverse" text_align="right"/>
|
||||
<label id="option-text" proportion="1" I18N="In the track info screen" text_align="right"/>
|
||||
<spacer width="40"/>
|
||||
<div proportion="1" height="fit" layout="horizontal-row">
|
||||
<div width="50%" height="fit" text-align="center" layout="vertical-row" >
|
||||
<checkbox id="reverse" align="center"/>
|
||||
<checkbox id="option" align="center"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<spacer width="1" height="2%"/>
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
<label id="record-race-text" proportion="1" I18N="In the track info screen" text="Record the race for ghost replay" text_align="right"/>
|
||||
<spacer width="40"/>
|
||||
<div proportion="1" height="fit" layout="horizontal-row">
|
||||
<div width="50%" height="fit" text-align="center" layout="vertical-row" >
|
||||
<checkbox id="record" align="center"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<spacer width="1" height="1%"/>
|
||||
</box>
|
||||
<spacer width="1" height="5%"/>
|
||||
<spacer width="1" height="1%"/>
|
||||
<buttonbar id="buttons" height="15%" width="100%" align="center">
|
||||
<icon-button id="start" width="64" height="64" icon="gui/green_check.png"
|
||||
I18N="In the track info screen" text="Start Race"/>
|
||||
|
Before Width: | Height: | Size: 7.9 KiB After Width: | Height: | Size: 23 KiB |
@ -3,16 +3,7 @@
|
||||
<icon-button id="back" x="0" y="0" height="8%" icon="gui/back.png"/>
|
||||
|
||||
<div x="1%" y="1%" width="98%" height="96%" layout="vertical-row" >
|
||||
|
||||
<header width="80%" I18N="In the track selection screen" text="Grand Prix"
|
||||
align="center" text_align="center" />
|
||||
|
||||
<box width="100%" height="195" padding="0">
|
||||
<scrollable_toolbar id="gps" height="175" y="10" x="10" width="98%" align="center" label_location="each"
|
||||
square_items="true" child_width="175" child_height="120" />
|
||||
</box>
|
||||
|
||||
<header width="100%" I18N="In the track selection screen" text="All Tracks"
|
||||
<header width="80%" I18N="In the track selection screen" text="All Tracks"
|
||||
align="center" text_align="center" />
|
||||
|
||||
<box proportion="1" width="100%" layout="vertical-row" padding="1">
|
||||
|
30
data/gui/tracks_and_gp.stkgui
Normal file
@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<stkgui>
|
||||
<icon-button id="back" x="0" y="0" height="8%" icon="gui/back.png"/>
|
||||
|
||||
<div x="1%" y="1%" width="98%" height="96%" layout="vertical-row" >
|
||||
|
||||
<header width="80%" I18N="In the track and grand prix selection screen" text="Grand Prix"
|
||||
align="center" text_align="center" />
|
||||
|
||||
<box width="100%" height="195" padding="0">
|
||||
<scrollable_toolbar id="gps" height="175" y="10" x="10" width="98%" align="center" label_location="each"
|
||||
square_items="true" child_width="175" child_height="120" />
|
||||
</box>
|
||||
|
||||
<header width="100%" I18N="In the track and grand prix selection screen" text="All Tracks"
|
||||
align="center" text_align="center" />
|
||||
|
||||
<box proportion="1" width="100%" layout="vertical-row" padding="1">
|
||||
<ribbon_grid id="tracks" proportion="1" width="100%" square_items="true"
|
||||
label_location="bottom" align="center" max_rows="4"
|
||||
child_width="160" child_height="120" />
|
||||
<spacer width="20" height="13" />
|
||||
</box>
|
||||
|
||||
<!-- Populated dynamically at runtime -->
|
||||
<tabs width="100%" height="25" id="trackgroups"> </tabs>
|
||||
|
||||
<spacer width="100%" height="2%" />
|
||||
</div>
|
||||
</stkgui>
|
@ -13,7 +13,7 @@
|
||||
square_items="true" child_width="128" child_height="128" />
|
||||
|
||||
<spacer height="15" width="10"/>
|
||||
<div width="90%" align="center" layout="vertical-row" height="fit">
|
||||
<div width="90%" align="center" layout="vertical-row" proportion="1">
|
||||
<div width="100%" height="fit" layout="horizontal-row" >
|
||||
<checkbox width="fit" id="online" I18N="In the user screen" text_align="left"/>
|
||||
<spacer width="10"/>
|
||||
@ -44,23 +44,29 @@
|
||||
I18N="In the user screen" text="Password"/>
|
||||
<textbox id="password" proportion="2" height="fit" I18N="In the user screen"/>
|
||||
</div>
|
||||
|
||||
<spacer height="20" width="20"/>
|
||||
|
||||
<label id="message" width="100%" text_align="center"/>
|
||||
</div>
|
||||
<div width="80%" align="center" layout="vertical-row" height="fit">
|
||||
<label id="message" width="80%" align="center" text_align="left"/>
|
||||
</div>
|
||||
<spacer width="20" height="25"/>
|
||||
<buttonbar id="options" width="90%" height="13%" align="bottom">
|
||||
<icon-button id="ok" width="64" height="64" icon="gui/green_check.png"
|
||||
I18N="In the user screen" text="OK" label_location="bottom"/>
|
||||
<icon-button id="new_user" width="64" height="64" icon="gui/blue_plus.png"
|
||||
I18N="In the user screen" text="Add user" label_location="bottom"/>
|
||||
<icon-button id="delete" width="64" height="64" icon="gui/remove.png"
|
||||
I18N="In the user screen" text="Delete" label_location="bottom"/>
|
||||
<icon-button id="rename" width="64" height="64" icon="gui/rename.png"
|
||||
I18N="In the user screen" text="Rename" label_location="bottom"/>
|
||||
<icon-button id="cancel" width="64" height="64" icon="gui/main_quit.png"
|
||||
I18N="In the user screen" text="Cancel" label_location="bottom"/>
|
||||
</buttonbar>
|
||||
|
||||
<spacer width="20" proportion="1"/>
|
||||
|
||||
<div width="90%" align="center" layout="vertical-row" height="fit">
|
||||
<buttonbar id="options" width="100%" height="80" align="center">
|
||||
<icon-button id="ok" width="64" height="64" icon="gui/green_check.png"
|
||||
I18N="In the user screen" text="OK" label_location="bottom"/>
|
||||
<icon-button id="new_user" width="64" height="64" icon="gui/blue_plus.png"
|
||||
I18N="In the user screen" text="Add user" label_location="bottom"/>
|
||||
<icon-button id="delete" width="64" height="64" icon="gui/remove.png"
|
||||
I18N="In the user screen" text="Delete" label_location="bottom"/>
|
||||
<icon-button id="rename" width="64" height="64" icon="gui/rename.png"
|
||||
I18N="In the user screen" text="Rename" label_location="bottom"/>
|
||||
<icon-button id="cancel" width="64" height="64" icon="gui/main_quit.png"
|
||||
I18N="In the user screen" text="Cancel" label_location="bottom"/>
|
||||
</buttonbar>
|
||||
</div>
|
||||
<spacer width="20" height="25"/>
|
||||
</box>
|
||||
<spacer width="20" height="15"/>
|
||||
</div>
|
||||
|
@ -187,7 +187,7 @@
|
||||
max: maximum leaning (i.e. when steering as much as possible at highest
|
||||
speed), in degrees.
|
||||
speed: Speed with which the leaning changes (in degree/second). -->
|
||||
<lean max="8.6" speed="5.0" />
|
||||
<lean max="6.6" speed="15.0" />
|
||||
|
||||
|
||||
<!-- ********** Items ********** -->
|
||||
|
231
data/localized_name.txt
Normal file
@ -0,0 +1,231 @@
|
||||
aa=ʿAfár af
|
||||
af=Afrikaans
|
||||
af_ZA=0
|
||||
am=ኣማርኛ
|
||||
ar=العربية
|
||||
ar_AR=0
|
||||
ar_OM=0
|
||||
ar_SA=0
|
||||
ar_SY=0
|
||||
ar_TN=0
|
||||
as=অসমীয়া
|
||||
ast=Asturianu
|
||||
ay=aymar aru
|
||||
az=Azərbaycanca
|
||||
az_IR=0
|
||||
be=Беларуская мова
|
||||
bg=български
|
||||
bg_BG=0
|
||||
bn=বাংলা
|
||||
bn_BD=0
|
||||
bn_IN=0
|
||||
bo=བོད་སྐད་
|
||||
br=brezhoneg
|
||||
bs=Bosanski
|
||||
bs_BA=0
|
||||
bs_BS=0
|
||||
ca_ES=0
|
||||
ca=0
|
||||
cmn=0
|
||||
co=corsu
|
||||
cs=Čeština
|
||||
cs_CZ=Čeština (Česká Republika)
|
||||
cy=Welsh
|
||||
cy_GB=Welsh (Great Britain)
|
||||
cz=Unknown language
|
||||
da=Dansk
|
||||
da_DK=Dansk (Danmark)
|
||||
de=Deutsch
|
||||
de_AT=Deutsch (Österreich)
|
||||
de_CH=Deutsch (Schweiz)
|
||||
de_DE=Deutsch (Deutschland)
|
||||
dk=Unknown language
|
||||
dz=རྫོང་ཁ
|
||||
el=ελληνικά
|
||||
el_GR=0
|
||||
en=English
|
||||
en_AU=English (Australia)
|
||||
en_CA=English (Canada)
|
||||
en_GB=English (Great Britain)
|
||||
en_US=English (United States)
|
||||
en_ZA=English (South Africa)
|
||||
en_US=English
|
||||
eo=Esperanto
|
||||
es=Español
|
||||
es_AR=0
|
||||
es_CL=0
|
||||
es_CO=0
|
||||
es_CR=0
|
||||
es_DO=0
|
||||
es_EC=0
|
||||
es_ES=0
|
||||
es_GT=0
|
||||
es_HN=0
|
||||
es_LA=0
|
||||
es_MX=0
|
||||
es_NI=0
|
||||
es_PA=0
|
||||
es_PE=0
|
||||
es_PR=0
|
||||
es_SV=0
|
||||
es_UY=0
|
||||
es_VE=0
|
||||
et=eesti keel
|
||||
et_EE=0
|
||||
et_ET=0
|
||||
eu=euskara
|
||||
eu_ES=0
|
||||
fa=فارسى
|
||||
fa_AF=0
|
||||
fa_IR=0
|
||||
fi=suomi
|
||||
fi_FI=0
|
||||
fo=Føroyskt
|
||||
fo_FO=0
|
||||
fr=Français
|
||||
fr_CA=Français (Canada)
|
||||
fr_CH=Français (Suisse)
|
||||
fr_FR=Français (France)
|
||||
fr_LU=Français (Luxembourg)
|
||||
fy=Frysk
|
||||
ga=Gaeilge
|
||||
gd=Gàidhlig
|
||||
gl=Galego
|
||||
gl_ES=0
|
||||
gn=Avañe'ẽ
|
||||
gu=ગુજરાતી
|
||||
gv=Gaelg
|
||||
ha=حَوْسَ
|
||||
he=עברית
|
||||
he_IL=0
|
||||
hi=हिन्दी
|
||||
hr=Hrvatski
|
||||
hr_HR=0
|
||||
hu=magyar
|
||||
hu_HU=0
|
||||
hy=Հայերեն
|
||||
ia=Interlingua
|
||||
id=Bahasa Indonesia
|
||||
id_ID=0
|
||||
is=Íslenska
|
||||
is_IS=0
|
||||
it=Italiano
|
||||
it_CH=0
|
||||
it_IT=0
|
||||
iu=ᐃᓄᒃᑎᑐᑦ/inuktitut
|
||||
ja=日本語
|
||||
ja_JP=0
|
||||
ka=ქართული
|
||||
kk=Қазақша
|
||||
kl=Kalaallisut
|
||||
km=ភាសាខ្មែរ
|
||||
km_KH=0
|
||||
kn=ಕನ್ನಡ
|
||||
ko=한국어
|
||||
ko_KR=0
|
||||
ku=Kurdî
|
||||
kw=Kernowek
|
||||
ky=кыргызча
|
||||
la=Latina
|
||||
lo=ລາວ
|
||||
lt=Lietuvių
|
||||
lt=0
|
||||
lv=Latviešu
|
||||
lv_LV=0
|
||||
jbo=La .lojban.
|
||||
mg=Malagasy
|
||||
mi=Māori
|
||||
mk=Македонски
|
||||
mk_MK=0
|
||||
ml=മലയാളം
|
||||
mn=Монгол
|
||||
mr=मराठी
|
||||
ms=Bahasa Melayu
|
||||
ms_MY=0
|
||||
mt=Malti
|
||||
my=မြန်မာဘာသာ
|
||||
my_MM=0
|
||||
nb=0
|
||||
nb_NO=0
|
||||
ne=0
|
||||
nl=Nederlands
|
||||
nl_BE=0
|
||||
nl_NL=0
|
||||
nn=Norsk nynorsk
|
||||
nn_NO=0
|
||||
no=Norsk bokmål
|
||||
no_NO=0
|
||||
no_NY=0
|
||||
nr=0
|
||||
oc=Occitan
|
||||
om=Oromoo
|
||||
or=ଓଡ଼ିଆ
|
||||
os=0
|
||||
pa=ਪੰਜਾਬੀ
|
||||
pl=Polski
|
||||
pl_PL=0
|
||||
ps=پښتو
|
||||
pt=Português
|
||||
pt_BR=0
|
||||
pt_PT=0
|
||||
qu=Runa Simi
|
||||
rm=Rumantsch
|
||||
ro=Română
|
||||
ro_RO=0
|
||||
ru=Русский
|
||||
ru_RU=0
|
||||
rw=Kinyarwanda
|
||||
sa=0
|
||||
sd=0
|
||||
se=Sámegiella
|
||||
se_NO=0
|
||||
si=0
|
||||
sk=Slovenčina
|
||||
sk_SK=0
|
||||
sl=Slovenščina
|
||||
sl_SI=0
|
||||
sl_SL=0
|
||||
sm=0
|
||||
so=0
|
||||
sp=0
|
||||
sq=Shqip
|
||||
sq_AL=0
|
||||
sr=Српски
|
||||
sr_YU=0
|
||||
ss=0
|
||||
st=0
|
||||
sv=Svenska
|
||||
sv_SE=0
|
||||
sv_SV=0
|
||||
sw=0
|
||||
ta=தமிழ்
|
||||
te=0
|
||||
tg=0
|
||||
th=ไทย
|
||||
th_TH=0
|
||||
ti=0
|
||||
tk=0
|
||||
tl=0
|
||||
to=0
|
||||
tr=Türkçe
|
||||
tr_TR=0
|
||||
ts=0
|
||||
tt=Татарча
|
||||
ug=0
|
||||
uk=Українська
|
||||
uk_UA=0
|
||||
ur=اردو
|
||||
ur_PK=0
|
||||
uz=0
|
||||
vi=Tiếng Việt
|
||||
vi_VN=0
|
||||
wa=0
|
||||
wo=0
|
||||
xh=0
|
||||
yi=ייִדיש
|
||||
yo=0
|
||||
zh=中文
|
||||
zh_CN=中文(简体)
|
||||
zh_HK=中文(香港)
|
||||
zh_TW=中文(繁體)
|
||||
zu=0
|
3369
data/po/da_DK.po
@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
# A simple script that adds all authors from transifex, which are
|
||||
# listed in comments at the beginning of the file, to the
|
||||
# 'translator-credits' translations - where launchpad added them
|
||||
@ -19,75 +19,79 @@ import re
|
||||
import sys
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv)!=2:
|
||||
if len(sys.argv) < 2:
|
||||
print "Usage: getpo_authors.py PATH_TO_PO_FILE"
|
||||
sys.exit(-1)
|
||||
|
||||
f = open(sys.argv[1], "r")
|
||||
if not f:
|
||||
print "Can not find", sys.argv[1]
|
||||
exit
|
||||
lines = f.readlines()
|
||||
for filename in sys.argv[1:]:
|
||||
print("Processing file ", filename)
|
||||
f = open(filename, "r")
|
||||
if not f:
|
||||
print "Can not find", filename
|
||||
exit
|
||||
lines = f.readlines()
|
||||
|
||||
f.close()
|
||||
f.close()
|
||||
|
||||
new_authors = []
|
||||
found = 0
|
||||
new_authors = []
|
||||
found = 0
|
||||
|
||||
# Find all authors with a simple finite state machine:
|
||||
contributions = -1
|
||||
line_count = 0
|
||||
for i in lines:
|
||||
line = i[:-1] # remove \n
|
||||
if line=="# Translators:":
|
||||
found = 1
|
||||
elif found and line[:2]=="# " and line [:14]!="# FIRST AUTHOR":
|
||||
new_authors.append(line[2:])
|
||||
elif line[:5]=="msgid":
|
||||
found = 0
|
||||
elif line[:31]== "msgstr \"Launchpad Contributions":
|
||||
contributions = line_count
|
||||
line_count = line_count + 1
|
||||
# Find all authors with a simple finite state machine:
|
||||
contributions = -1
|
||||
line_count = 0
|
||||
for i in lines:
|
||||
line = i[:-1] # remove \n
|
||||
if line=="# Translators:":
|
||||
found = 1
|
||||
elif found and line[:2]=="# " and line [:14]!="# FIRST AUTHOR":
|
||||
new_authors.append(line[2:])
|
||||
elif line[:5]=="msgid":
|
||||
found = 0
|
||||
elif line[:31]== "msgstr \"Launchpad Contributions":
|
||||
contributions = line_count
|
||||
line_count = line_count + 1
|
||||
|
||||
|
||||
# Delete all email addresses - not sure if the authors
|
||||
# would want them to be published
|
||||
email=re.compile(" *<.*@.*\..*> *") # one @ and one dot at least
|
||||
for i in range(len(new_authors)):
|
||||
g = email.search(new_authors[i])
|
||||
if g:
|
||||
new_authors[i] = new_authors[i][:g.start()] \
|
||||
+ new_authors[i][g.end():]
|
||||
# Delete all email addresses - not sure if the authors
|
||||
# would want them to be published
|
||||
email=re.compile(" *<.*@.*\..*> *") # one @ and one dot at least
|
||||
for i in range(len(new_authors)):
|
||||
g = email.search(new_authors[i])
|
||||
if g:
|
||||
new_authors[i] = new_authors[i][:g.start()] \
|
||||
+ new_authors[i][g.end():]
|
||||
|
||||
# Get the old authors from the translator-credits string:
|
||||
if contributions>0:
|
||||
# Ignore the first entry, which is "msgstr ...", and the
|
||||
# last two characters, which are the '"\n'.
|
||||
old_authors = lines[contributions][:-2].split("\\n")[1:]
|
||||
for i in range(len(old_authors)):
|
||||
old_authors[i] = old_authors[i].strip()
|
||||
else:
|
||||
old_authors=[]
|
||||
|
||||
all_authors = old_authors + new_authors;
|
||||
all_authors = sorted(all_authors, key=lambda x: x.lower())
|
||||
all_authors_string = reduce(lambda x,y: x+"\\n"+y, all_authors, "")
|
||||
# Get the old authors from the translator-credits string:
|
||||
if contributions>0:
|
||||
# Ignore the first entry, which is "msgstr ...", and the
|
||||
# last two characters, which are the '"\n'.
|
||||
old_authors = lines[contributions][:-2].split("\\n")[1:]
|
||||
for i in range(len(old_authors)):
|
||||
old_authors[i] = old_authors[i].strip()
|
||||
else:
|
||||
old_authors=[]
|
||||
|
||||
all_authors = old_authors + new_authors;
|
||||
all_authors = sorted(all_authors, key=lambda x: x.lower())
|
||||
all_authors_string = reduce(lambda x,y: x+"\\n"+y, all_authors, "")
|
||||
|
||||
credits_line = "msgstr \"Launchpad Contributions:%s\"\n"%all_authors_string
|
||||
# If no old authors exists, write a new entry:
|
||||
if contributions==-1:
|
||||
lines.append("\n")
|
||||
lines.append("#: src/states_screens/credits.cpp:209\n")
|
||||
lines.append("msgid \"translator-credits\"\n")
|
||||
lines.append(credits_line)
|
||||
else:
|
||||
# Otherwise just replace the old contribution string
|
||||
lines[contributions] = credits_line
|
||||
credits_line = "msgstr \"Launchpad Contributions:%s\"\n"%all_authors_string
|
||||
# If no old authors exists, write a new entry:
|
||||
if contributions==-1:
|
||||
lines.append("\n")
|
||||
lines.append("#: src/states_screens/credits.cpp:209\n")
|
||||
lines.append("msgid \"translator-credits\"\n")
|
||||
lines.append(credits_line)
|
||||
else:
|
||||
# Otherwise just replace the old contribution string
|
||||
lines[contributions] = credits_line
|
||||
|
||||
|
||||
# Overwrite old file
|
||||
f = open(sys.argv[1], "w")
|
||||
for i in lines:
|
||||
f.write(i)
|
||||
f.close()
|
||||
# Overwrite old file
|
||||
f = open(filename, "w")
|
||||
for i in lines:
|
||||
f.write(i)
|
||||
f.close()
|
||||
|
||||
print("Done with ", filename)
|
||||
|
||||
|
2867
data/replay/standard_easy_farm.replay
Normal file
4435
data/replay/standard_easy_hacienda.replay
Normal file
3542
data/replay/standard_easy_island.replay
Normal file
2594
data/replay/standard_expert_abyss.replay
Normal file
2378
data/replay/standard_expert_mines.replay
Normal file
2239
data/replay/standard_expert_stkenterprise.replay
Normal file
2281
data/replay/standard_expert_xr591.replay
Normal file
1924
data/replay/standard_intermediate_lighthouse.replay
Normal file
2081
data/replay/standard_intermediate_snowmountain.replay
Normal file
2515
data/replay/standard_intermediate_snowpeak.replay
Normal file
@ -3,7 +3,7 @@
|
||||
uniform sampler2D source;
|
||||
uniform sampler2D depth;
|
||||
uniform vec2 pixel;
|
||||
uniform layout(r16f) volatile restrict writeonly image2D dest;
|
||||
layout(r16f) volatile restrict writeonly uniform image2D dest;
|
||||
uniform float sigma = 5.;
|
||||
|
||||
layout (local_size_x = 8, local_size_y = 8) in;
|
||||
|
@ -3,7 +3,7 @@
|
||||
uniform sampler2D source;
|
||||
uniform sampler2D depth;
|
||||
uniform vec2 pixel;
|
||||
uniform layout(r16f) volatile restrict writeonly image2D dest;
|
||||
layout(r16f) volatile restrict writeonly uniform image2D dest;
|
||||
uniform float sigma = 5.;
|
||||
|
||||
layout (local_size_x = 8, local_size_y = 8) in;
|
||||
|
@ -1,5 +1,5 @@
|
||||
uniform sampler2D source;
|
||||
uniform layout(r32f) restrict writeonly image2D dest;
|
||||
layout(r32f) restrict writeonly uniform image2D dest;
|
||||
uniform vec2 pixel;
|
||||
uniform float weights[7];
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
uniform sampler2D source;
|
||||
uniform layout(r32f) restrict writeonly image2D dest;
|
||||
layout(r32f) restrict writeonly uniform image2D dest;
|
||||
uniform vec2 pixel;
|
||||
uniform float weights[7];
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
uniform sampler2D source;
|
||||
uniform layout(rgba16f) restrict writeonly image2D dest;
|
||||
layout(rgba16f) restrict writeonly uniform image2D dest;
|
||||
uniform vec2 pixel;
|
||||
uniform float weights[7];
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
uniform sampler2D source;
|
||||
uniform layout(rgba16f) restrict writeonly image2D dest;
|
||||
layout(rgba16f) restrict writeonly uniform image2D dest;
|
||||
uniform vec2 pixel;
|
||||
uniform float weights[7];
|
||||
|
||||
|
@ -4,7 +4,7 @@ out vec4 FragColor;
|
||||
|
||||
void main(void)
|
||||
{
|
||||
vec3 eyedir = vec3(gl_FragCoord.xy / screen, 1.);
|
||||
vec3 eyedir = vec3(mod(gl_FragCoord.xy, screen) / screen, 1.);
|
||||
eyedir = 2.0 * eyedir - 1.0;
|
||||
vec4 tmp = (InverseProjectionMatrix * vec4(eyedir, 1.));
|
||||
tmp /= tmp.w;
|
||||
|
@ -40,7 +40,7 @@ void main(void)
|
||||
float bl = 0.0;
|
||||
float m = log2(r) + 6 + log2(invSamples);
|
||||
|
||||
float theta = 2. * 3.14 * tau * .5 * invSamples + phi;
|
||||
float theta = mod(2. * 3.14 * tau * .5 * invSamples + phi, 6.283185307179586);
|
||||
vec2 rotations = vec2(cos(theta), sin(theta)) * screen;
|
||||
vec2 offset = vec2(cos(invSamples), sin(invSamples));
|
||||
|
||||
|
@ -81,6 +81,10 @@ when the border that intersect at this corner are enabled.
|
||||
left_border="128" right_border="13" top_border="13" bottom_border="13"
|
||||
preserve_h_aspect_ratios="true" hborder_out_portion="0" vborder_out_portion="0"/>
|
||||
|
||||
<element type="generic-message" image="forest/generic.png"
|
||||
left_border="128" right_border="13" top_border="13" bottom_border="13"
|
||||
preserve_h_aspect_ratios="true" hborder_out_portion="0" vborder_out_portion="0"/>
|
||||
|
||||
<element type="button" state="neutral" image="forest/glassbutton.png"
|
||||
left_border="13" right_border="13" top_border="13" bottom_border="13"
|
||||
preserve_h_aspect_ratios="true" hborder_out_portion="0" vborder_out_portion="0"/>
|
||||
|
@ -80,6 +80,10 @@ when the border that intersect at this corner are enabled.
|
||||
left_border="128" right_border="13" top_border="13" bottom_border="13"
|
||||
preserve_h_aspect_ratios="true" hborder_out_portion="0" vborder_out_portion="0"/>
|
||||
|
||||
<element type="generic-message" image="ocean/generic.png"
|
||||
left_border="128" right_border="13" top_border="13" bottom_border="13"
|
||||
preserve_h_aspect_ratios="true" hborder_out_portion="0" vborder_out_portion="0"/>
|
||||
|
||||
<element type="button" state="neutral" image="ocean/glassbutton.png"
|
||||
left_border="13" right_border="13" top_border="13" bottom_border="13"
|
||||
preserve_h_aspect_ratios="true" hborder_out_portion="0" vborder_out_portion="0"/>
|
||||
|
@ -80,6 +80,10 @@ when the border that intersect at this corner are enabled.
|
||||
left_border="128" right_border="13" top_border="13" bottom_border="13"
|
||||
preserve_h_aspect_ratios="true" hborder_out_portion="0" vborder_out_portion="0"/>
|
||||
|
||||
<element type="generic-message" image="peach/generic.png"
|
||||
left_border="128" right_border="13" top_border="13" bottom_border="13"
|
||||
preserve_h_aspect_ratios="true" hborder_out_portion="0" vborder_out_portion="0"/>
|
||||
|
||||
<element type="button" state="neutral" image="peach/glassbutton.png"
|
||||
left_border="13" right_border="13" top_border="13" bottom_border="13"
|
||||
preserve_h_aspect_ratios="true" hborder_out_portion="0" vborder_out_portion="0"/>
|
||||
|
@ -81,6 +81,10 @@ when the border that intersect at this corner are enabled.
|
||||
left_border="128" right_border="13" top_border="13" bottom_border="13"
|
||||
preserve_h_aspect_ratios="true" hborder_out_portion="0" vborder_out_portion="0"/>
|
||||
|
||||
<element type="generic-message" image="ruby/generic.png"
|
||||
left_border="128" right_border="13" top_border="13" bottom_border="13"
|
||||
preserve_h_aspect_ratios="true" hborder_out_portion="0" vborder_out_portion="0"/>
|
||||
|
||||
<element type="button" state="neutral" image="ruby/glassbutton.png"
|
||||
left_border="13" right_border="13" top_border="13" bottom_border="13"
|
||||
preserve_h_aspect_ratios="true" hborder_out_portion="0" vborder_out_portion="0"/>
|
||||
|
BIN
data/skins/forest/generic.png
Normal file
After Width: | Height: | Size: 23 KiB |
BIN
data/skins/ocean/generic.png
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
data/skins/peach/generic.png
Normal file
After Width: | Height: | Size: 25 KiB |
BIN
data/skins/ruby/generic.png
Normal file
After Width: | Height: | Size: 20 KiB |
@ -396,13 +396,6 @@
|
||||
post-skid-rotate-factor="1"
|
||||
reduce-turn-min="0.2" reduce-turn-max="0.8"/>
|
||||
|
||||
<!-- Leaning related parameters, i.e. slightly leaning the karts when
|
||||
driving a fast curve.
|
||||
max: maximum leaning (i.e. when steering as much as possible at highest
|
||||
speed), in degrees.
|
||||
sped: Speed with which the leaning changes (in degree/second). -->
|
||||
<lean max="8.6" speed="5.0" />
|
||||
|
||||
<kart-type>
|
||||
<light />
|
||||
<medium />
|
||||
|
@ -8,28 +8,28 @@
|
||||
<summary>A racing game</summary>
|
||||
<description>
|
||||
<p>
|
||||
SuperTuxKart is a fun 3D kart racing game.
|
||||
You can play with up to 4 friends on one PC, racing against each other or
|
||||
just try to beat the computer.
|
||||
Supertuxkart is a free 3D kart racing game, with a focus on having fun over
|
||||
realism. You can play with up to 4 friends on one PC, racing against each
|
||||
other, or try to beat the computer in single-player mode.
|
||||
</p>
|
||||
<p>
|
||||
See the great lighthouse or drive through the sand and visit the pyramids.
|
||||
Race underground or in space, watching the stars passing by.
|
||||
Have some rest under the palms on the beach (watching the other karts
|
||||
overtaking you :) ).
|
||||
But don't eat the bananas! Watch for bowling balls, plungers, bubble gum
|
||||
and cakes thrown by opponents.
|
||||
Race underground or in space, watching the stars pass by. Or rest under the
|
||||
palm trees on the beach, watching the other karts overtake you. But don't eat
|
||||
the bananas! Watch for bowling balls, plungers, bubble gum and cakes thrown by
|
||||
your opponents.
|
||||
</p>
|
||||
<p>
|
||||
You can do a single race against other karts, compete in one of several
|
||||
Grand Prix, try to beat the high score in time trials on your own, play
|
||||
battle mode against your friends, and more!
|
||||
You can do a single race against other karts, compete in one of several Grand
|
||||
Prix, try to beat the high score in time trials on your own, play battle mode
|
||||
against the computer or your friends, and more!
|
||||
</p>
|
||||
</description>
|
||||
<url type="homepage">http://supertuxkart.sourceforge.net/</url>
|
||||
<screenshots>
|
||||
<screenshot type="default">http://supertuxkart.sourceforge.net/persistent/images/4/4d/SuperTuxKart_0.8_screenshot.jpg</screenshot>
|
||||
<screenshot>http://supertuxkart.sourceforge.net/persistent/images/1/1f/SuperTuxKart_0.8_screenshot4.jpg</screenshot>
|
||||
<screenshot type="default">http://supertuxkart.sourceforge.net/persistent/images/4/4e/Supertuxkart-0.9-screenshot-2.jpg</screenshot>
|
||||
<screenshot>http://supertuxkart.sourceforge.net/persistent/images/a/a9/Supertuxkart-0.9-screenshot-1.jpg</screenshot>
|
||||
<screenshot>http://supertuxkart.sourceforge.net/persistent/images/6/63/Supertuxkart-0.9-screenshot-3.jpg</screenshot>
|
||||
</screenshots>
|
||||
<updatecontact>supertuxkart-devel@lists.sourceforge.net</updatecontact>
|
||||
</application>
|
||||
|
@ -58,8 +58,8 @@ BEGIN_AS_NAMESPACE
|
||||
|
||||
// AngelScript version
|
||||
|
||||
#define ANGELSCRIPT_VERSION 23000
|
||||
#define ANGELSCRIPT_VERSION_STRING "2.30.0 WIP"
|
||||
#define ANGELSCRIPT_VERSION 23002
|
||||
#define ANGELSCRIPT_VERSION_STRING "2.30.2"
|
||||
|
||||
// Data types
|
||||
|
||||
@ -543,7 +543,7 @@ struct asSMessageInfo
|
||||
extern "C"
|
||||
{
|
||||
// Engine
|
||||
AS_API asIScriptEngine *asCreateScriptEngine(asDWORD version);
|
||||
AS_API asIScriptEngine *asCreateScriptEngine(asDWORD version = ANGELSCRIPT_VERSION);
|
||||
AS_API const char *asGetLibraryVersion();
|
||||
AS_API const char *asGetLibraryOptions();
|
||||
|
||||
@ -585,20 +585,20 @@ template<typename T>
|
||||
asUINT asGetTypeTraits()
|
||||
{
|
||||
#if defined(_MSC_VER) || defined(_LIBCPP_TYPE_TRAITS) || (__GNUC__ >= 5)
|
||||
// MSVC & XCode/Clang, and gnuc 5+
|
||||
// MSVC, XCode/Clang, and gnuc 5+
|
||||
// C++11 compliant code
|
||||
bool hasConstructor = std::is_default_constructible<T>::value && !std::is_trivially_default_constructible<T>::value;
|
||||
bool hasDestructor = std::is_destructible<T>::value && !std::is_trivially_destructible<T>::value;
|
||||
bool hasAssignmentOperator = std::is_copy_assignable<T>::value && !std::is_trivially_copy_assignable<T>::value;
|
||||
bool hasCopyConstructor = std::is_copy_constructible<T>::value && !std::is_trivially_copy_constructible<T>::value;
|
||||
#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))
|
||||
// gnuc 4.8+
|
||||
// gnuc is using a mix of C++11 standard and pre-standard templates
|
||||
// gnuc 4.8 is using a mix of C++11 standard and pre-standard templates
|
||||
bool hasConstructor = std::is_default_constructible<T>::value && !std::has_trivial_default_constructor<T>::value;
|
||||
bool hasDestructor = std::is_destructible<T>::value && !std::is_trivially_destructible<T>::value;
|
||||
bool hasAssignmentOperator = std::is_copy_assignable<T>::value && !std::has_trivial_copy_assign<T>::value;
|
||||
bool hasCopyConstructor = std::is_copy_constructible<T>::value && !std::has_trivial_copy_constructor<T>::value;
|
||||
#else
|
||||
// All other compilers and versions are assumed to use non C++11 compliant code until proven otherwise
|
||||
// Not fully C++11 compliant. The has_trivial checks were used while the standard was still
|
||||
// being elaborated, but were then removed in favor of the above is_trivially checks
|
||||
// http://stackoverflow.com/questions/12702103/writing-code-that-works-when-has-trivial-destructor-is-defined-instead-of-is
|
||||
@ -1556,8 +1556,8 @@ enum asEBCInstr
|
||||
asBC_POWdi = 197,
|
||||
asBC_POWi64 = 198,
|
||||
asBC_POWu64 = 199,
|
||||
|
||||
asBC_MAXBYTECODE = 200,
|
||||
asBC_Thiscall1 = 200,
|
||||
asBC_MAXBYTECODE = 201,
|
||||
|
||||
// Temporary tokens. Can't be output to the final program
|
||||
asBC_VarDecl = 251,
|
||||
@ -1851,8 +1851,8 @@ const asSBCInfo asBCInfo[256] =
|
||||
asBCINFO(POWdi, wW_rW_rW_ARG, 0),
|
||||
asBCINFO(POWi64, wW_rW_rW_ARG, 0),
|
||||
asBCINFO(POWu64, wW_rW_rW_ARG, 0),
|
||||
asBCINFO(Thiscall1, DW_ARG, -AS_PTR_SIZE-1),
|
||||
|
||||
asBCINFO_DUMMY(200),
|
||||
asBCINFO_DUMMY(201),
|
||||
asBCINFO_DUMMY(202),
|
||||
asBCINFO_DUMMY(203),
|
||||
|
@ -14,11 +14,15 @@ if(APPLE)
|
||||
option(BUILD_FRAMEWORK "Build Framework bundle for OSX" OFF)
|
||||
endif()
|
||||
|
||||
set(ANGELSCRIPT_VERSION_MAJOR 2)
|
||||
set(ANGELSCRIPT_VERSION_MINOR 30)
|
||||
set(ANGELSCRIPT_VERSION_PATCH 0)
|
||||
file(READ ../../include/angelscript.h ANGELSCRIPT_H)
|
||||
string(REGEX MATCH "#define ANGELSCRIPT_VERSION_STRING \"([0-9]*).([0-9]*).([0-9]*)" ANGELSCRIPT_VERSION_REGEX ${ANGELSCRIPT_H})
|
||||
set(ANGELSCRIPT_VERSION_MAJOR ${CMAKE_MATCH_1})
|
||||
set(ANGELSCRIPT_VERSION_MINOR ${CMAKE_MATCH_2})
|
||||
set(ANGELSCRIPT_VERSION_PATCH ${CMAKE_MATCH_3})
|
||||
set(PROJECT_VERSION ${ANGELSCRIPT_VERSION_MAJOR}.${ANGELSCRIPT_VERSION_MINOR}.${ANGELSCRIPT_VERSION_PATCH})
|
||||
|
||||
message(STATUS "Configuring angelscript ${PROJECT_VERSION}")
|
||||
|
||||
find_package(Threads)
|
||||
|
||||
set(ANGELSCRIPT_HEADERS
|
||||
@ -102,12 +106,13 @@ if(MSVC AND CMAKE_CL_64)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(ANDROID)
|
||||
if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "^arm")
|
||||
enable_language(ASM)
|
||||
if(CMAKE_ASM_COMPILER_WORKS)
|
||||
set(ANGELSCRIPT_SOURCE ${ANGELSCRIPT_SOURCE} ../../source/as_callfunc_arm.cpp ../../source/as_callfunc_arm_gcc.S)
|
||||
set_property(SOURCE ../../source/as_callfunc_arm_gcc.S APPEND PROPERTY COMPILE_FLAGS " -Wa,-mimplicit-it=always")
|
||||
else()
|
||||
message(FATAL ERROR "Android target requires a working assembler")
|
||||
message(FATAL ERROR "ARM target requires a working assembler")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@ -156,4 +161,5 @@ endif()
|
||||
|
||||
#set(RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/../../bin)
|
||||
|
||||
#add_subdirectory(../../../samples/game/projects/cmake/ ./game)
|
||||
|
||||
|
@ -363,9 +363,35 @@ int asCBuilder::CompileGlobalVar(const char *sectionName, const char *code, int
|
||||
|
||||
CompileGlobalVariables();
|
||||
|
||||
// It is possible that the global variable initialization included anonymous functions that must be compiled too
|
||||
for( asUINT n = 0; n < functions.GetLength(); n++ )
|
||||
{
|
||||
asCCompiler compiler(engine);
|
||||
asCScriptFunction *func = engine->scriptFunctions[functions[n]->funcId];
|
||||
int r = compiler.CompileFunction(this, functions[n]->script, func->parameterNames, functions[n]->node, func, 0);
|
||||
if( r < 0 )
|
||||
break;
|
||||
}
|
||||
|
||||
if( numWarnings > 0 && engine->ep.compilerWarnings == 2 )
|
||||
WriteError(TXT_WARNINGS_TREATED_AS_ERROR, 0, 0);
|
||||
|
||||
// None of the functions should be added to the module if any error occurred,
|
||||
// or it was requested that the functions wouldn't be added to the scope
|
||||
if( numErrors > 0 )
|
||||
{
|
||||
for( asUINT n = 0; n < functions.GetLength(); n++ )
|
||||
{
|
||||
asCScriptFunction *func = engine->scriptFunctions[functions[n]->funcId];
|
||||
if( module->globalFunctions.GetIndex(func) >= 0 )
|
||||
{
|
||||
module->globalFunctions.Erase(module->globalFunctions.GetIndex(func));
|
||||
module->scriptFunctions.RemoveValue(func);
|
||||
func->ReleaseInternal();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( numErrors > 0 )
|
||||
{
|
||||
// Remove the variable from the module, if it was registered
|
||||
@ -549,22 +575,38 @@ int asCBuilder::CompileFunction(const char *sectionName, const char *code, int l
|
||||
funcDesc->paramNames = func->parameterNames;
|
||||
funcDesc->isExistingShared = false;
|
||||
|
||||
asCCompiler compiler(engine);
|
||||
compiler.CompileFunction(this, functions[0]->script, func->parameterNames, functions[0]->node, func, 0);
|
||||
// This must be done in a loop, as it is possible that additional functions get declared as lambda's in the code
|
||||
for( asUINT n = 0; n < functions.GetLength(); n++ )
|
||||
{
|
||||
asCCompiler compiler(engine);
|
||||
asCScriptFunction *func = engine->scriptFunctions[functions[n]->funcId];
|
||||
int r = compiler.CompileFunction(this, functions[n]->script, func->parameterNames, functions[n]->node, func, 0);
|
||||
if( r < 0 )
|
||||
break;
|
||||
}
|
||||
|
||||
if( numWarnings > 0 && engine->ep.compilerWarnings == 2 )
|
||||
WriteError(TXT_WARNINGS_TREATED_AS_ERROR, 0, 0);
|
||||
|
||||
// None of the functions should be added to the module if any error occurred,
|
||||
// or it was requested that the functions wouldn't be added to the scope
|
||||
if( !(compileFlags & asCOMP_ADD_TO_MODULE) || numErrors > 0 )
|
||||
{
|
||||
for( asUINT n = 0; n < functions.GetLength(); n++ )
|
||||
{
|
||||
asCScriptFunction *func = engine->scriptFunctions[functions[n]->funcId];
|
||||
if( module->globalFunctions.GetIndex(func) >= 0 )
|
||||
{
|
||||
module->globalFunctions.Erase(module->globalFunctions.GetIndex(func));
|
||||
module->scriptFunctions.RemoveValue(func);
|
||||
func->ReleaseInternal();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( numErrors > 0 )
|
||||
{
|
||||
// If the function was added to the module then remove it again
|
||||
if( compileFlags & asCOMP_ADD_TO_MODULE )
|
||||
{
|
||||
module->globalFunctions.Erase(module->globalFunctions.GetIndex(func));
|
||||
module->scriptFunctions.RemoveValue(func);
|
||||
func->ReleaseInternal();
|
||||
}
|
||||
|
||||
// Release the function pointer that would otherwise be returned if no errors occured
|
||||
func->ReleaseInternal();
|
||||
|
||||
return asERROR;
|
||||
@ -965,15 +1007,20 @@ int asCBuilder::VerifyProperty(asCDataType *dt, const char *decl, asCString &nam
|
||||
if( r < 0 )
|
||||
return asINVALID_DECLARATION;
|
||||
|
||||
// Get data type and property name
|
||||
// Get data type
|
||||
asCScriptNode *dataType = parser.GetScriptNode()->firstChild;
|
||||
|
||||
asCScriptNode *nameNode = dataType->next;
|
||||
// Check if the property is declared 'by reference'
|
||||
bool isReference = (dataType->next->tokenType == ttAmp);
|
||||
|
||||
// Get the name of the property
|
||||
asCScriptNode *nameNode = isReference ? dataType->next->next : dataType->next;
|
||||
|
||||
// If an object property is registered, then use the
|
||||
// object's namespace, otherwise use the specified namespace
|
||||
type = CreateDataTypeFromNode(dataType, &source, dt ? dt->GetObjectType()->nameSpace : ns);
|
||||
name.Assign(&decl[nameNode->tokenPos], nameNode->tokenLength);
|
||||
type.MakeReference(isReference);
|
||||
|
||||
// Validate that the type really can be a registered property
|
||||
// We cannot use CanBeInstantiated, as it is allowed to register
|
||||
@ -1458,9 +1505,9 @@ sMixinClass *asCBuilder::GetMixinClass(const char *name, asSNameSpace *ns)
|
||||
|
||||
int asCBuilder::RegisterFuncDef(asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns)
|
||||
{
|
||||
// TODO: 2.30.0: redesign: Allow funcdefs to be explicitly declared as 'shared'. In this case
|
||||
// an error should be given if any of the arguments/return type is not
|
||||
// shared.
|
||||
// TODO: redesign: Allow funcdefs to be explicitly declared as 'shared'. In this case
|
||||
// an error should be given if any of the arguments/return type is not
|
||||
// shared.
|
||||
|
||||
// Find the name
|
||||
asASSERT( node->firstChild->nodeType == snDataType );
|
||||
@ -1516,6 +1563,7 @@ void asCBuilder::CompleteFuncDef(sFuncDef *funcDef)
|
||||
asCScriptFunction *func = module->funcDefs[funcDef->idx];
|
||||
asASSERT( func );
|
||||
|
||||
// TODO: It should be possible to declare funcdef as shared. In this case a compiler error will be given if any of the types it uses are not shared
|
||||
GetParsedFunctionDetails(funcDef->node, funcDef->script, 0, funcDef->name, func->returnType, func->parameterNames, func->parameterTypes, func->inOutFlags, defaultArgs, isConstMethod, isConstructor, isDestructor, isPrivate, isProtected, isOverride, isFinal, isShared, func->nameSpace);
|
||||
|
||||
// There should not be any defaultArgs, but if there are any we need to delete them to avoid leaks
|
||||
@ -1523,27 +1571,47 @@ void asCBuilder::CompleteFuncDef(sFuncDef *funcDef)
|
||||
if( defaultArgs[n] )
|
||||
asDELETE(defaultArgs[n], asCString);
|
||||
|
||||
// TODO: Should we force the use of 'shared' for this check to be done?
|
||||
// Check if there is another identical funcdef from another module and if so reuse that instead
|
||||
for( asUINT n = 0; n < engine->funcDefs.GetLength(); n++ )
|
||||
// All funcdefs are shared, unless one of the parameter types or return type is not shared
|
||||
isShared = true;
|
||||
if( func->returnType.GetObjectType() && !func->returnType.GetObjectType()->IsShared() )
|
||||
isShared = false;
|
||||
if( func->returnType.GetFuncDef() && !func->returnType.GetFuncDef()->IsShared() )
|
||||
isShared = false;
|
||||
for( asUINT n = 0; isShared && n < func->parameterTypes.GetLength(); n++ )
|
||||
{
|
||||
asCScriptFunction *f2 = engine->funcDefs[n];
|
||||
if( f2 == 0 || func == f2 )
|
||||
continue;
|
||||
if( func->parameterTypes[n].GetObjectType() && !func->parameterTypes[n].GetObjectType()->IsShared() )
|
||||
isShared = false;
|
||||
if( func->parameterTypes[n].GetFuncDef() && !func->parameterTypes[n].GetFuncDef()->IsShared() )
|
||||
isShared = false;
|
||||
}
|
||||
func->isShared = isShared;
|
||||
|
||||
if( f2->name == func->name &&
|
||||
f2->nameSpace == func->nameSpace &&
|
||||
f2->IsSignatureExceptNameEqual(func) )
|
||||
// Check if there is another identical funcdef from another module and if so reuse that instead
|
||||
if( func->isShared )
|
||||
{
|
||||
for( asUINT n = 0; n < engine->funcDefs.GetLength(); n++ )
|
||||
{
|
||||
// Replace our funcdef for the existing one
|
||||
funcDef->idx = f2->id;
|
||||
module->funcDefs[module->funcDefs.IndexOf(func)] = f2;
|
||||
f2->AddRefInternal();
|
||||
asCScriptFunction *f2 = engine->funcDefs[n];
|
||||
if( f2 == 0 || func == f2 )
|
||||
continue;
|
||||
|
||||
engine->funcDefs.RemoveValue(func);
|
||||
if( !f2->isShared )
|
||||
continue;
|
||||
|
||||
func->ReleaseInternal();
|
||||
break;
|
||||
if( f2->name == func->name &&
|
||||
f2->nameSpace == func->nameSpace &&
|
||||
f2->IsSignatureExceptNameEqual(func) )
|
||||
{
|
||||
// Replace our funcdef for the existing one
|
||||
funcDef->idx = f2->id;
|
||||
module->funcDefs[module->funcDefs.IndexOf(func)] = f2;
|
||||
f2->AddRefInternal();
|
||||
|
||||
engine->funcDefs.RemoveValue(func);
|
||||
|
||||
func->ReleaseInternal();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2463,7 +2531,7 @@ void asCBuilder::CompileInterfaces()
|
||||
sClassDeclaration *intfDecl = interfaceDeclarations[n];
|
||||
asCObjectType *intfType = intfDecl->objType;
|
||||
|
||||
// TODO: 2.28.1: Is this really at the correct place? Hasn't the vfTableIdx already been set here?
|
||||
// TODO: Is this really at the correct place? Hasn't the vfTableIdx already been set here?
|
||||
// Co-opt the vfTableIdx value in our own methods to indicate the
|
||||
// index the function should have in the table chunk for this interface.
|
||||
for( asUINT d = 0; d < intfType->methods.GetLength(); d++ )
|
||||
@ -4124,6 +4192,34 @@ int asCBuilder::RegisterScriptFunctionFromNode(asCScriptNode *node, asCScriptCod
|
||||
return RegisterScriptFunction(node, file, objType, isInterface, isGlobalFunction, ns, isExistingShared, isMixin, name, returnType, parameterNames, parameterTypes, inOutFlags, defaultArgs, isConstMethod, isConstructor, isDestructor, isPrivate, isProtected, isOverride, isFinal, isShared);
|
||||
}
|
||||
|
||||
asCScriptFunction *asCBuilder::RegisterLambda(asCScriptNode *node, asCScriptCode *file, asCScriptFunction *funcDef, const asCString &name, asSNameSpace *ns)
|
||||
{
|
||||
// Get the parameter names from the node
|
||||
asCArray<asCString> parameterNames;
|
||||
asCArray<asCString*> defaultArgs;
|
||||
asCScriptNode *args = node->firstChild;
|
||||
while( args && args->nodeType == snIdentifier )
|
||||
{
|
||||
asCString argName;
|
||||
argName.Assign(&file->code[args->tokenPos], args->tokenLength);
|
||||
parameterNames.PushLast(argName);
|
||||
defaultArgs.PushLast(0);
|
||||
args = args->next;
|
||||
}
|
||||
|
||||
// The statement block for the function must be disconnected, as the builder is going to be the owner of it
|
||||
args->DisconnectParent();
|
||||
|
||||
// Get the return and parameter types from the funcDef
|
||||
asCString funcName = name;
|
||||
int r = RegisterScriptFunction(args, file, 0, 0, true, ns, false, false, funcName, funcDef->returnType, parameterNames, funcDef->parameterTypes, funcDef->inOutFlags, defaultArgs, false, false, false, false, false, false, false, false);
|
||||
if( r < 0 )
|
||||
return 0;
|
||||
|
||||
// Return the function that was just created (but that will be compiled later)
|
||||
return engine->scriptFunctions[functions[functions.GetLength()-1]->funcId];
|
||||
}
|
||||
|
||||
int asCBuilder::RegisterScriptFunction(asCScriptNode *node, asCScriptCode *file, asCObjectType *objType, bool isInterface, bool isGlobalFunction, asSNameSpace *ns, bool isExistingShared, bool isMixin, asCString &name, asCDataType &returnType, asCArray<asCString> ¶meterNames, asCArray<asCDataType> ¶meterTypes, asCArray<asETypeModifiers> &inOutFlags, asCArray<asCString *> &defaultArgs, bool isConstMethod, bool isConstructor, bool isDestructor, bool isPrivate, bool isProtected, bool isOverride, bool isFinal, bool isShared)
|
||||
{
|
||||
// Determine default namespace if not specified
|
||||
@ -4734,11 +4830,15 @@ void asCBuilder::GetObjectMethodDescriptions(const char *name, asCObjectType *ob
|
||||
// If searching with a scope informed, then the node and script must also be informed for potential error reporting
|
||||
asASSERT( errNode && script );
|
||||
|
||||
// If the scope contains ::identifier, then use the last identifier as the class name and the rest of is as the namespace
|
||||
// If the scope contains ::identifier, then use the last identifier as the class name and the rest of it as the namespace
|
||||
int n = scope.FindLast("::");
|
||||
asCString className = n >= 0 ? scope.SubString(n+2) : scope;
|
||||
asCString nsName = n >= 0 ? scope.SubString(0, n) : "";
|
||||
asSNameSpace *ns = GetNameSpaceByString(nsName, objectType->nameSpace, errNode, script);
|
||||
|
||||
// Check if the namespace actually exist, if not return silently as this cannot be the referring to a base class
|
||||
asSNameSpace *ns = GetNameSpaceByString(nsName, objectType->nameSpace, errNode, script, false);
|
||||
if( ns == 0 )
|
||||
return;
|
||||
|
||||
// Find the base class with the specified scope
|
||||
while( objectType && (objectType->name != className || objectType->nameSpace != ns) )
|
||||
@ -4894,7 +4994,7 @@ asSNameSpace *asCBuilder::GetNameSpaceFromNode(asCScriptNode *node, asCScriptCod
|
||||
return GetNameSpaceByString(scope, implicitNs, node, script);
|
||||
}
|
||||
|
||||
asSNameSpace *asCBuilder::GetNameSpaceByString(const asCString &nsName, asSNameSpace *implicitNs, asCScriptNode *errNode, asCScriptCode *script)
|
||||
asSNameSpace *asCBuilder::GetNameSpaceByString(const asCString &nsName, asSNameSpace *implicitNs, asCScriptNode *errNode, asCScriptCode *script, bool isRequired)
|
||||
{
|
||||
asSNameSpace *ns = implicitNs;
|
||||
if( nsName == "::" )
|
||||
@ -4902,7 +5002,7 @@ asSNameSpace *asCBuilder::GetNameSpaceByString(const asCString &nsName, asSNameS
|
||||
else if( nsName != "" )
|
||||
{
|
||||
ns = engine->FindNameSpace(nsName.AddressOf());
|
||||
if( ns == 0 )
|
||||
if( ns == 0 && isRequired )
|
||||
{
|
||||
asCString msg;
|
||||
msg.Format(TXT_NAMESPACE_s_DOESNT_EXIST, nsName.AddressOf());
|
||||
@ -5073,6 +5173,12 @@ asCDataType asCBuilder::CreateDataTypeFromNode(asCScriptNode *node, asCScriptCod
|
||||
ot = otInstance;
|
||||
}
|
||||
}
|
||||
else if( n && n->next && n->next->nodeType == snDataType )
|
||||
{
|
||||
asCString str;
|
||||
str.Format(TXT_TYPE_s_NOT_TEMPLATE, ot->name.AddressOf());
|
||||
WriteError(str, file, n);
|
||||
}
|
||||
|
||||
// Create object data type
|
||||
if( ot )
|
||||
|
@ -174,7 +174,7 @@ protected:
|
||||
asCString GetCleanExpressionString(asCScriptNode *n, asCScriptCode *file);
|
||||
|
||||
asSNameSpace *GetNameSpaceFromNode(asCScriptNode *node, asCScriptCode *script, asSNameSpace *implicitNs, asCScriptNode **next);
|
||||
asSNameSpace *GetNameSpaceByString(const asCString &nsName, asSNameSpace *implicitNs, asCScriptNode *errNode, asCScriptCode *script);
|
||||
asSNameSpace *GetNameSpaceByString(const asCString &nsName, asSNameSpace *implicitNs, asCScriptNode *errNode, asCScriptCode *script, bool isRequired = true);
|
||||
asCString GetScopeFromNode(asCScriptNode *n, asCScriptCode *script, asCScriptNode **next = 0);
|
||||
|
||||
asCObjectType *GetObjectType(const char *type, asSNameSpace *ns);
|
||||
@ -213,6 +213,7 @@ protected:
|
||||
int RegisterEnum(asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns);
|
||||
int RegisterTypedef(asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns);
|
||||
int RegisterFuncDef(asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns);
|
||||
asCScriptFunction *RegisterLambda(asCScriptNode *node, asCScriptCode *file, asCScriptFunction *funcDef, const asCString &name, asSNameSpace *ns);
|
||||
void CompleteFuncDef(sFuncDef *funcDef);
|
||||
void CompileInterfaces();
|
||||
void CompileClasses(asUINT originalNumTempl);
|
||||
|
@ -1015,6 +1015,21 @@ void asCByteCode::OptimizeLocally(const asCArray<int> &tempVariableOffsets)
|
||||
ChangeFirstDeleteNext(curr, asBC_PSF);
|
||||
instr = GoForward(curr);
|
||||
}
|
||||
// VAR a, GETOBJREF 0 -> PshVPtr a
|
||||
else if( curr->next && curr->next->op == asBC_GETOBJREF && curr->next->wArg[0] == 0 )
|
||||
{
|
||||
ChangeFirstDeleteNext(curr, asBC_PshVPtr);
|
||||
instr = GoForward(curr);
|
||||
}
|
||||
// VAR, PSF, GETREF {PTR_SIZE} -> PSF, PSF
|
||||
if( curr->next && curr->next->op == asBC_PSF &&
|
||||
curr->next->next && curr->next->next->op == asBC_GETREF &&
|
||||
curr->next->next->wArg[0] == AS_PTR_SIZE )
|
||||
{
|
||||
curr->op = asBC_PSF;
|
||||
DeleteInstruction(curr->next->next);
|
||||
instr = GoForward(curr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2220,6 +2235,13 @@ void asCByteCode::DebugOutput(const char *name, asCScriptEngine *engine, asCScri
|
||||
}
|
||||
break;
|
||||
|
||||
case asBC_FuncPtr:
|
||||
{
|
||||
asCScriptFunction *func = *(asCScriptFunction**)ARG_DW(instr->arg);
|
||||
fprintf(file, " %-8s 0x%x (func:%s)\n", asBCInfo[instr->op].name, (asUINT)*ARG_DW(instr->arg), func->GetDeclaration());
|
||||
}
|
||||
break;
|
||||
|
||||
case asBC_PshC4:
|
||||
case asBC_Cast:
|
||||
fprintf(file, " %-8s 0x%x (i:%d, f:%g)\n", asBCInfo[instr->op].name, (asUINT)*ARG_DW(instr->arg), *((int*) ARG_DW(instr->arg)), *((float*) ARG_DW(instr->arg)));
|
||||
@ -2233,6 +2255,7 @@ void asCByteCode::DebugOutput(const char *name, asCScriptEngine *engine, asCScri
|
||||
case asBC_CALLSYS:
|
||||
case asBC_CALLBND:
|
||||
case asBC_CALLINTF:
|
||||
case asBC_Thiscall1:
|
||||
{
|
||||
int funcID = *(int*)ARG_DW(instr->arg);
|
||||
asCString decl = engine->GetFunctionDeclaration(funcID);
|
||||
@ -2268,10 +2291,17 @@ void asCByteCode::DebugOutput(const char *name, asCScriptEngine *engine, asCScri
|
||||
{
|
||||
case asBC_OBJTYPE:
|
||||
{
|
||||
asCObjectType *ot = *(asCObjectType**)ARG_DW(instr->arg);
|
||||
asCObjectType *ot = *(asCObjectType**)ARG_QW(instr->arg);
|
||||
fprintf(file, " %-8s 0x%x (type:%s)\n", asBCInfo[instr->op].name, (asUINT)*ARG_QW(instr->arg), ot->GetName());
|
||||
}
|
||||
break;
|
||||
|
||||
case asBC_FuncPtr:
|
||||
{
|
||||
asCScriptFunction *func = *(asCScriptFunction**)ARG_QW(instr->arg);
|
||||
fprintf(file, " %-8s 0x%x (func:%s)\n", asBCInfo[instr->op].name, (asUINT)*ARG_QW(instr->arg), func->GetDeclaration());
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
#ifdef __GNUC__
|
||||
@ -2288,15 +2318,27 @@ void asCByteCode::DebugOutput(const char *name, asCScriptEngine *engine, asCScri
|
||||
|
||||
case asBCTYPE_wW_QW_ARG:
|
||||
case asBCTYPE_rW_QW_ARG:
|
||||
switch( instr->op )
|
||||
{
|
||||
case asBC_RefCpyV:
|
||||
case asBC_FREE:
|
||||
{
|
||||
asCObjectType *ot = *(asCObjectType**)ARG_QW(instr->arg);
|
||||
fprintf(file, " %-8s v%d, 0x%x (type:%s)\n", asBCInfo[instr->op].name, instr->wArg[0], (asUINT)*ARG_QW(instr->arg), ot->GetName());
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
#ifdef __GNUC__
|
||||
#ifdef _LP64
|
||||
fprintf(file, " %-8s v%d, 0x%lx (i:%ld, f:%g)\n", asBCInfo[instr->op].name, instr->wArg[0], *ARG_QW(instr->arg), *((asINT64*) ARG_QW(instr->arg)), *((double*) ARG_QW(instr->arg)));
|
||||
fprintf(file, " %-8s v%d, 0x%lx (i:%ld, f:%g)\n", asBCInfo[instr->op].name, instr->wArg[0], *ARG_QW(instr->arg), *((asINT64*) ARG_QW(instr->arg)), *((double*) ARG_QW(instr->arg)));
|
||||
#else
|
||||
fprintf(file, " %-8s v%d, 0x%llx (i:%lld, f:%g)\n", asBCInfo[instr->op].name, instr->wArg[0], *ARG_QW(instr->arg), *((asINT64*) ARG_QW(instr->arg)), *((double*) ARG_QW(instr->arg)));
|
||||
fprintf(file, " %-8s v%d, 0x%llx (i:%lld, f:%g)\n", asBCInfo[instr->op].name, instr->wArg[0], *ARG_QW(instr->arg), *((asINT64*) ARG_QW(instr->arg)), *((double*) ARG_QW(instr->arg)));
|
||||
#endif
|
||||
#else
|
||||
fprintf(file, " %-8s v%d, 0x%I64x (i:%I64d, f:%g)\n", asBCInfo[instr->op].name, instr->wArg[0], *ARG_QW(instr->arg), *((asINT64*) ARG_QW(instr->arg)), *((double*) ARG_QW(instr->arg)));
|
||||
fprintf(file, " %-8s v%d, 0x%I64x (i:%I64d, f:%g)\n", asBCInfo[instr->op].name, instr->wArg[0], *ARG_QW(instr->arg), *((asINT64*) ARG_QW(instr->arg)), *((double*) ARG_QW(instr->arg)));
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
case asBCTYPE_DW_DW_ARG:
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
AngelCode Scripting Library
|
||||
Copyright (c) 2003-2012 Andreas Jonsson
|
||||
Copyright (c) 2003-2015 Andreas Jonsson
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any
|
||||
@ -130,6 +130,8 @@ public:
|
||||
int InstrW_W(asEBCInstr bc, int w, int b);
|
||||
int InstrSHORT_DW_DW(asEBCInstr bc, short a, asDWORD b, asDWORD c);
|
||||
|
||||
asCScriptEngine *GetEngine() const { return engine; };
|
||||
|
||||
asCArray<int> lineNumbers;
|
||||
asCArray<int> sectionIdxs;
|
||||
int largestStackUsed;
|
||||
|
@ -130,10 +130,11 @@ int DetectCallingConvention(bool isMethod, const asSFuncPtr &ptr, int callConv,
|
||||
internal->callConv = (internalCallConv)(thisCallConv + 2);
|
||||
#endif
|
||||
internal->baseOffset = ( int )MULTI_BASE_OFFSET(ptr);
|
||||
#if defined(AS_ARM) && (defined(__GNUC__) || defined(AS_PSVITA))
|
||||
#if (defined(AS_ARM) || defined(AS_MIPS)) && (defined(__GNUC__) || defined(AS_PSVITA))
|
||||
// As the least significant bit in func is used to switch to THUMB mode
|
||||
// on ARM processors, the LSB in the __delta variable is used instead of
|
||||
// the one in __pfn on ARM processors.
|
||||
// MIPS also appear to use the base offset to indicate virtual method.
|
||||
if( (size_t(internal->baseOffset) & 1) )
|
||||
internal->callConv = (internalCallConv)(thisCallConv + 2);
|
||||
#endif
|
||||
@ -577,10 +578,11 @@ int CallSystemFunction(int id, asCContext *context)
|
||||
}
|
||||
|
||||
// Add the base offset for multiple inheritance
|
||||
#if (defined(__GNUC__) && defined(AS_ARM)) || defined(AS_PSVITA)
|
||||
#if (defined(__GNUC__) && (defined(AS_ARM) || defined(AS_MIPS))) || defined(AS_PSVITA)
|
||||
// On GNUC + ARM the lsb of the offset is used to indicate a virtual function
|
||||
// and the whole offset is thus shifted one bit left to keep the original
|
||||
// offset resolution
|
||||
// MIPS also work like ARM in this regard
|
||||
obj = (void*)(asPWORD(obj) + (sysFunc->baseOffset>>1));
|
||||
#else
|
||||
obj = (void*)(asPWORD(obj) + sysFunc->baseOffset);
|
||||
@ -634,10 +636,11 @@ int CallSystemFunction(int id, asCContext *context)
|
||||
}
|
||||
|
||||
// Add the base offset for multiple inheritance
|
||||
#if (defined(__GNUC__) && defined(AS_ARM)) || defined(AS_PSVITA)
|
||||
#if (defined(__GNUC__) && (defined(AS_ARM) || defined(AS_MIPS))) || defined(AS_PSVITA)
|
||||
// On GNUC + ARM the lsb of the offset is used to indicate a virtual function
|
||||
// and the whole offset is thus shifted one bit left to keep the original
|
||||
// offset resolution
|
||||
// MIPS also work like ARM in this regard
|
||||
tempPtr = (void*)(asPWORD(tempPtr) + (sysFunc->baseOffset>>1));
|
||||
#else
|
||||
tempPtr = (void*)(asPWORD(tempPtr) + sysFunc->baseOffset);
|
||||
@ -822,7 +825,15 @@ int CallSystemFunction(int id, asCContext *context)
|
||||
if( cleanCount )
|
||||
{
|
||||
args = context->m_regs.stackPointer;
|
||||
if( callConv >= ICC_THISCALL )
|
||||
|
||||
// Skip the hidden argument for the return pointer
|
||||
// TODO: runtime optimize: This check and increment should have been done in PrepareSystemFunction
|
||||
if( descr->DoesReturnOnStack() )
|
||||
args += AS_PTR_SIZE;
|
||||
|
||||
// Skip the object pointer on the stack
|
||||
// TODO: runtime optimize: This check and increment should have been done in PrepareSystemFunction
|
||||
if( callConv >= ICC_THISCALL && sysFunc->objForThiscall == 0 )
|
||||
args += AS_PTR_SIZE;
|
||||
|
||||
asSSystemFunctionInterface::SClean *clean = sysFunc->cleanArgs.AddressOf();
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
AngelCode Scripting Library
|
||||
Copyright (c) 2003-2014 Andreas Jonsson
|
||||
Copyright (c) 2003-2015 Andreas Jonsson
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any
|
||||
@ -39,11 +39,13 @@
|
||||
The assembler routines for Linux were written by Carlos Luna in December 2012
|
||||
*/
|
||||
|
||||
#if !defined(AS_MAX_PORTABILITY)
|
||||
|
||||
#if defined(__arm__) || defined(__ARM__) || defined(I3D_ARCH_ARM)
|
||||
|
||||
#if !defined(__linux__) || defined(__ANDROID__) || defined(ANDROID) || defined(__SOFTFP__)
|
||||
|
||||
/* iOS, Android, and Marmalade goes here */
|
||||
/* iOS, Android, Marmalade, and Linux with soft-float ABI goes here */
|
||||
|
||||
.global armFunc
|
||||
.global armFuncR0
|
||||
@ -85,7 +87,12 @@ stackargsloop:
|
||||
bne stackargsloop
|
||||
mov sp, r12
|
||||
nomoreargs:
|
||||
#if defined (__ARM_ARCH_4T__) || defined (__ARM_ARCH_4__)
|
||||
mov lr, pc /* older ARM didn't support blx */
|
||||
mov pc, r4
|
||||
#else
|
||||
blx r4
|
||||
#endif
|
||||
add sp, sp, r8
|
||||
ldmia sp!, {r4-r8, pc}
|
||||
|
||||
@ -133,7 +140,12 @@ stackargslooparmFuncObjLast:
|
||||
bne stackargslooparmFuncObjLast
|
||||
mov sp, r12
|
||||
nomoreargsarmFuncObjLast:
|
||||
#if defined (__ARM_ARCH_4T__) || defined (__ARM_ARCH_4__)
|
||||
mov lr, pc /* older ARM didn't support blx */
|
||||
mov pc, r4
|
||||
#else
|
||||
blx r4
|
||||
#endif
|
||||
add sp, sp, r8
|
||||
ldmia sp!, {r4-r8, pc}
|
||||
|
||||
@ -180,7 +192,12 @@ stackargslooparmFuncR0ObjLast:
|
||||
bne stackargslooparmFuncR0ObjLast
|
||||
mov sp, r12
|
||||
nomoreargsarmFuncR0ObjLast:
|
||||
#if defined (__ARM_ARCH_4T__) || defined (__ARM_ARCH_4__)
|
||||
mov lr, pc /* older ARM didn't support blx */
|
||||
mov pc, r4
|
||||
#else
|
||||
blx r4
|
||||
#endif
|
||||
add sp, sp, r8
|
||||
ldmia sp!, {r4-r8, pc}
|
||||
|
||||
@ -218,7 +235,12 @@ stackargslooparmFuncR0:
|
||||
bne stackargslooparmFuncR0
|
||||
mov sp, r12
|
||||
nomoreargsarmFuncR0:
|
||||
#if defined (__ARM_ARCH_4T__) || defined (__ARM_ARCH_4__)
|
||||
mov lr, pc /* older ARM didn't support blx */
|
||||
mov pc, r4
|
||||
#else
|
||||
blx r4
|
||||
#endif
|
||||
add sp, sp, r8
|
||||
ldmia sp!, {r4-r8, pc}
|
||||
|
||||
@ -255,14 +277,19 @@ stackargslooparmFuncR0R1:
|
||||
bne stackargslooparmFuncR0R1
|
||||
mov sp, r12
|
||||
nomoreargsarmFuncR0R1:
|
||||
#if defined (__ARM_ARCH_4T__) || defined (__ARM_ARCH_4__)
|
||||
mov lr, pc /* older ARM didn't support blx */
|
||||
mov pc, r4
|
||||
#else
|
||||
blx r4
|
||||
#endif
|
||||
add sp, sp, r8
|
||||
ldmia sp!, {r4-r8, pc}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------*/
|
||||
#elif defined(__linux__) && !defined(__SOFTFP__)
|
||||
|
||||
/* The Linux code goes here */
|
||||
/* The Linux with hard-float ABI code goes here */
|
||||
|
||||
|
||||
/* These codes are suitable for armeabi + vfp / armeabihf */
|
||||
@ -340,7 +367,7 @@ stackargsloop:
|
||||
mov sp, r12
|
||||
|
||||
nomoreargs:
|
||||
#if defined (___ARM_ARCH_4T__) || defined (__ARM_ARCH_4__)
|
||||
#if defined (__ARM_ARCH_4T__) || defined (__ARM_ARCH_4__)
|
||||
mov lr, pc /* older ARM didn't support blx */
|
||||
mov pc, r4
|
||||
#else
|
||||
@ -427,8 +454,8 @@ stackargslooparmFuncObjLast:
|
||||
mov sp, r12
|
||||
|
||||
nomoreargsarmFuncObjLast:
|
||||
#if defined (___ARM_ARCH_4T__) || defined (__ARM_ARCH_4__)
|
||||
mov lr, pc
|
||||
#if defined (__ARM_ARCH_4T__) || defined (__ARM_ARCH_4__)
|
||||
mov lr, pc /* older ARM didn't support blx */
|
||||
mov pc, r4
|
||||
#else
|
||||
blx r4
|
||||
@ -521,8 +548,8 @@ stackargslooparmFuncR0ObjLast:
|
||||
mov sp, r12
|
||||
|
||||
nomoreargsarmFuncR0ObjLast:
|
||||
#if defined (___ARM_ARCH_4T__) || defined (__ARM_ARCH_4__)
|
||||
mov lr, pc
|
||||
#if defined (__ARM_ARCH_4T__) || defined (__ARM_ARCH_4__)
|
||||
mov lr, pc /* older ARM didn't support blx */
|
||||
mov pc, r4
|
||||
#else
|
||||
blx r4
|
||||
@ -597,8 +624,8 @@ stackargslooparmFuncR0:
|
||||
mov sp, r12
|
||||
|
||||
nomoreargsarmFuncR0:
|
||||
#if defined (___ARM_ARCH_4T__) || defined (__ARM_ARCH_4__)
|
||||
mov lr, pc
|
||||
#if defined (__ARM_ARCH_4T__) || defined (__ARM_ARCH_4__)
|
||||
mov lr, pc /* older ARM didn't support blx */
|
||||
mov pc, r4
|
||||
#else
|
||||
blx r4
|
||||
@ -677,8 +704,8 @@ stackargslooparmFuncR0R1:
|
||||
mov sp, r12
|
||||
|
||||
nomoreargsarmFuncR0R1:
|
||||
#if defined (___ARM_ARCH_4T__) || defined (__ARM_ARCH_4__)
|
||||
mov lr, pc
|
||||
#if defined (__ARM_ARCH_4T__) || defined (__ARM_ARCH_4__)
|
||||
mov lr, pc /* older ARM didn't support blx */
|
||||
mov pc, r4
|
||||
#else
|
||||
blx r4
|
||||
@ -697,3 +724,6 @@ nomoreargsarmFuncR0R1:
|
||||
|
||||
#endif /* arm */
|
||||
|
||||
#endif /* !AS_MAX_PORTABILITY */
|
||||
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
AngelCode Scripting Library
|
||||
Copyright (c) 2003-2013 Andreas Jonsson
|
||||
Copyright (c) 2003-2015 Andreas Jonsson
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any
|
||||
@ -34,6 +34,8 @@
|
||||
This code was adapted from as_callfunc_arm_gcc (ARM, Linux hard float) by Brandon Bare on October 2014.
|
||||
*/
|
||||
|
||||
#if !defined(AS_MAX_PORTABILITY)
|
||||
|
||||
#ifdef __psp2__
|
||||
|
||||
.syntax unified
|
||||
@ -61,7 +63,7 @@
|
||||
|
||||
/* --------------------------------------------------------------------------------------------*/
|
||||
armFunc:
|
||||
.fnstart
|
||||
.fnstart
|
||||
|
||||
push {r4-r8, r10, r11, lr} /* sp must be 8-byte alignment for ABI compliance, so the pushed registers must be even */
|
||||
|
||||
@ -81,19 +83,19 @@ armFunc:
|
||||
/* Load the first 4 arguments into r0-r3 */
|
||||
cmp r7, #4
|
||||
|
||||
it ge
|
||||
it ge
|
||||
ldrge r0, [r6]
|
||||
cmp r7, #8
|
||||
|
||||
it ge
|
||||
it ge
|
||||
ldrge r1, [r6, #4]
|
||||
cmp r7, #12
|
||||
|
||||
it ge
|
||||
it ge
|
||||
ldrge r2, [r6, #8]
|
||||
cmp r7, #16
|
||||
|
||||
it ge
|
||||
it ge
|
||||
ldrge r3, [r6, #12]
|
||||
|
||||
stackargs:
|
||||
@ -128,11 +130,11 @@ nomoreargs:
|
||||
|
||||
pop {r4-r8, r10, r11, pc}
|
||||
|
||||
.fnend
|
||||
.fnend
|
||||
|
||||
/* --------------------------------------------------------------------------------------------*/
|
||||
armFuncObjLast:
|
||||
.fnstart
|
||||
.fnstart
|
||||
|
||||
push {r4-r8, r10, r11, lr} /* We´re storing r11 just to keep the stack aligned to an 8 byte boundary */
|
||||
|
||||
@ -157,28 +159,28 @@ armFuncObjLast:
|
||||
/* Load the first 4 arguments into r0-r3 */
|
||||
cmp r7, #4
|
||||
|
||||
it ge
|
||||
it ge
|
||||
ldrge r0, [r6]
|
||||
cmp r7, #8
|
||||
|
||||
it ge
|
||||
it ge
|
||||
ldrge r1, [r6,#4]
|
||||
|
||||
it lt
|
||||
it lt
|
||||
movlt r1, r5
|
||||
cmp r7, #12
|
||||
|
||||
it ge
|
||||
it ge
|
||||
ldrge r2, [r6,#8]
|
||||
|
||||
it lt
|
||||
it lt
|
||||
movlt r2, r5
|
||||
cmp r7, #16
|
||||
|
||||
it ge
|
||||
it ge
|
||||
ldrge r3, [r6,#12]
|
||||
|
||||
ittt lt
|
||||
ittt lt
|
||||
movlt r3, r5
|
||||
movlt r5, #0 /* If objlast got placed into a register, r5 = 0 */
|
||||
blt stackargsFuncObjLast /* If objlast got placed into a register, go to stackargsFuncObjLast */
|
||||
@ -220,11 +222,11 @@ nomoreargsarmFuncObjLast:
|
||||
|
||||
pop {r4-r8, r10,r11, pc}
|
||||
|
||||
.fnend
|
||||
.fnend
|
||||
|
||||
/* --------------------------------------------------------------------------------------------*/
|
||||
armFuncR0ObjLast:
|
||||
.fnstart
|
||||
.fnstart
|
||||
|
||||
push {r4-r8, r10, r11, lr}
|
||||
|
||||
@ -252,35 +254,35 @@ armFuncR0ObjLast:
|
||||
/* Load the first 3 arguments into r1-r3 */
|
||||
cmp r7, #4
|
||||
|
||||
it ge
|
||||
it ge
|
||||
ldrge r1, [r6]
|
||||
cmp r7, #8
|
||||
|
||||
it ge
|
||||
it ge
|
||||
ldrge r2, [r6,#4]
|
||||
|
||||
it lt
|
||||
it lt
|
||||
movlt r2, r5
|
||||
cmp r7, #12
|
||||
|
||||
it ge
|
||||
it ge
|
||||
ldrge r3, [r6,#8]
|
||||
|
||||
ittt lt
|
||||
ittt lt
|
||||
movlt r3, r5
|
||||
movlt r5, #0 /* If objlast got placed into a register, r5 = 0 */
|
||||
blt stackargsFuncR0ObjLast /* If objlast got placed into a register, go to stackargsFuncR0ObjLast */
|
||||
|
||||
cmp r7, #16 /* Else if we have one last arg set the offset accordingly and store the arg in the array */
|
||||
|
||||
itt ge
|
||||
itt ge
|
||||
ldrge r7, [r6, #12]
|
||||
strge r7, [r6, #8]
|
||||
|
||||
str r5, [r6, #12] /* Put objlast in r6 + 12 */
|
||||
mov r5, #0
|
||||
mov r5, #0
|
||||
|
||||
it ge
|
||||
it ge
|
||||
movge r5, #4 /* Set r5 with an offset of #4 if there´s one last arg that couldn´t be placed in r registers */
|
||||
add r5, r5, #4 /* Set r5 with an offset of + #4, so objlast can be loaded into the stack */
|
||||
|
||||
@ -318,11 +320,11 @@ nomoreargsarmFuncR0ObjLast:
|
||||
|
||||
pop {r4-r8, r10, r11, pc}
|
||||
|
||||
.fnend
|
||||
.fnend
|
||||
|
||||
/* --------------------------------------------------------------------------------------------*/
|
||||
armFuncR0:
|
||||
.fnstart
|
||||
.fnstart
|
||||
|
||||
push {r4-r8, r10, r11, lr}
|
||||
|
||||
@ -344,19 +346,19 @@ armFuncR0:
|
||||
/* Load the first 3 arguments into r1-r3 */
|
||||
cmp r7, #4
|
||||
|
||||
it ge
|
||||
it ge
|
||||
ldrge r1, [r6]
|
||||
cmp r7, #8
|
||||
|
||||
it ge
|
||||
it ge
|
||||
ldrge r2, [r6, #4]
|
||||
cmp r7, #12
|
||||
|
||||
it ge
|
||||
it ge
|
||||
ldrge r3, [r6, #8]
|
||||
cmp r7, #16
|
||||
|
||||
it ge
|
||||
it ge
|
||||
movge r11, #4 /* If there is still one arg to be placed, set the offset in r11 to #4 */
|
||||
|
||||
stackargsarmFuncR0:
|
||||
@ -393,11 +395,11 @@ nomoreargsarmFuncR0:
|
||||
|
||||
pop {r4-r8, r10, r11, pc}
|
||||
|
||||
.fnend
|
||||
.fnend
|
||||
|
||||
/* --------------------------------------------------------------------------------------------*/
|
||||
armFuncR0R1:
|
||||
.fnstart
|
||||
.fnstart
|
||||
|
||||
push {r4-r8, r10, r11, lr}
|
||||
|
||||
@ -421,23 +423,23 @@ armFuncR0R1:
|
||||
/* Load the first 2 arguments into r2-r3 */
|
||||
cmp r7, #4
|
||||
|
||||
it ge
|
||||
it ge
|
||||
ldrge r2, [r6]
|
||||
cmp r7, #8
|
||||
|
||||
it ge
|
||||
it ge
|
||||
ldrge r3, [r6, #4]
|
||||
cmp r7, #12
|
||||
|
||||
it ge
|
||||
it ge
|
||||
movge r11, #4 /* If there is a third arg to be placed, set the offset in r11 to #4 */
|
||||
|
||||
cmp r7, #16
|
||||
|
||||
it ge
|
||||
it ge
|
||||
movge r11, #8 /* If there is a fourth arg to be placed, set the offset in r11 to #8 */
|
||||
|
||||
itt lt
|
||||
itt lt
|
||||
ldrlt r7, [r6, #8] /* Else copy the third arg to the correct place in the array */
|
||||
strlt r7, [r6, #12]
|
||||
|
||||
@ -475,6 +477,9 @@ nomoreargsarmFuncR0R1:
|
||||
|
||||
pop {r4-r8, r10, r11, pc}
|
||||
|
||||
.fnend
|
||||
.fnend
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* !AS_MAX_PORTABILITY */
|
||||
|
||||
#endif
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
AngelCode Scripting Library
|
||||
Copyright (c) 2003-2009 Andreas Jonsson
|
||||
Copyright (c) 2003-2015 Andreas Jonsson
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any
|
||||
@ -35,6 +35,8 @@
|
||||
// Adapted to GNUC by darktemplar216 in September 2009
|
||||
// Small fixed to work under XCode GCC by Gilad Novik in October 2009
|
||||
|
||||
#if !defined(AS_MAX_PORTABILITY)
|
||||
|
||||
#if defined(__arm__) || defined(__ARM__)
|
||||
|
||||
.align 2
|
||||
@ -235,3 +237,6 @@ nomoreargsarmFuncR0R1:
|
||||
ldmia sp!, {r4-r8, pc}
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* !AS_MAX_PORTABILITY */
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
AngelCode Scripting Library
|
||||
Copyright (c) 2003-2014 Andreas Jonsson
|
||||
Copyright (c) 2003-2015 Andreas Jonsson
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any
|
||||
@ -35,7 +35,9 @@
|
||||
// These functions handle the actual calling of system functions
|
||||
//
|
||||
// This version is MIPS specific and was originally written
|
||||
// by Manu Evans in April, 2006
|
||||
// by Manu Evans in April, 2006 for Playstation Portable (PSP)
|
||||
//
|
||||
// Support for Linux with MIPS was added by Andreas Jonsson in April, 2015
|
||||
//
|
||||
|
||||
|
||||
@ -52,10 +54,320 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#if !defined(AS_ANDROID)
|
||||
#include <regdef.h>
|
||||
#endif
|
||||
|
||||
BEGIN_AS_NAMESPACE
|
||||
|
||||
#if defined(__linux__) && defined(_ABIO32)
|
||||
|
||||
// The MIPS ABI used by Linux is implemented here
|
||||
// (Tested on CI20 MIPS Creator with Debian Linux)
|
||||
//
|
||||
// ref: SYSTEM V
|
||||
// APPLICATION BINARY INTERFACE
|
||||
// MIPS RISC Processor
|
||||
// http://math-atlas.sourceforge.net/devel/assembly/mipsabi32.pdf
|
||||
//
|
||||
// ref: MIPS Instruction Reference
|
||||
// http://www.mrc.uidaho.edu/mrc/people/jff/digital/MIPSir.html
|
||||
|
||||
union SFloatRegs
|
||||
{
|
||||
union { double d0; struct { float f0; asDWORD dummy0; };};
|
||||
union { double d1; struct { float f1; asDWORD dummy1; };};
|
||||
} ;
|
||||
|
||||
extern "C" asQWORD mipsFunc(asUINT argSize, asDWORD *argBuffer, void *func, SFloatRegs &floatRegs);
|
||||
asDWORD GetReturnedFloat();
|
||||
asQWORD GetReturnedDouble();
|
||||
|
||||
asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr, void *obj, asDWORD *args, void *retPointer, asQWORD &/*retQW2*/, void *secondObject)
|
||||
{
|
||||
asCScriptEngine *engine = context->m_engine;
|
||||
asSSystemFunctionInterface *sysFunc = descr->sysFuncIntf;
|
||||
int callConv = sysFunc->callConv;
|
||||
|
||||
asQWORD retQW = 0;
|
||||
|
||||
void *func = (void*)sysFunc->func;
|
||||
void **vftable;
|
||||
|
||||
asDWORD argBuffer[128]; // Ought to be big enough
|
||||
asASSERT( sysFunc->paramSize < 128 );
|
||||
|
||||
asDWORD argOffset = 0;
|
||||
|
||||
SFloatRegs floatRegs;
|
||||
asDWORD floatOffset = 0;
|
||||
|
||||
// If the application function returns the value in memory then
|
||||
// the first argument must be the pointer to that memory
|
||||
if( sysFunc->hostReturnInMemory )
|
||||
{
|
||||
asASSERT( retPointer );
|
||||
argBuffer[argOffset++] = (asPWORD)retPointer;
|
||||
}
|
||||
|
||||
if( callConv == ICC_CDECL_OBJFIRST || callConv == ICC_CDECL_OBJFIRST_RETURNINMEM ||
|
||||
callConv == ICC_THISCALL || callConv == ICC_THISCALL_RETURNINMEM ||
|
||||
callConv == ICC_VIRTUAL_THISCALL || callConv == ICC_VIRTUAL_THISCALL_RETURNINMEM ||
|
||||
callConv == ICC_THISCALL_OBJFIRST || callConv == ICC_VIRTUAL_THISCALL_OBJFIRST ||
|
||||
callConv == ICC_THISCALL_OBJFIRST_RETURNINMEM || callConv == ICC_VIRTUAL_THISCALL_OBJFIRST_RETURNINMEM ||
|
||||
callConv == ICC_THISCALL_OBJLAST || callConv == ICC_VIRTUAL_THISCALL_OBJLAST ||
|
||||
callConv == ICC_THISCALL_OBJLAST_RETURNINMEM || callConv == ICC_VIRTUAL_THISCALL_OBJLAST_RETURNINMEM )
|
||||
{
|
||||
// Add the object pointer as the first argument
|
||||
argBuffer[argOffset++] = (asPWORD)obj;
|
||||
}
|
||||
|
||||
if( callConv == ICC_THISCALL_OBJFIRST || callConv == ICC_VIRTUAL_THISCALL_OBJFIRST ||
|
||||
callConv == ICC_THISCALL_OBJFIRST_RETURNINMEM || callConv == ICC_VIRTUAL_THISCALL_OBJFIRST_RETURNINMEM )
|
||||
{
|
||||
// Add the second object pointer
|
||||
argBuffer[argOffset++] = (asPWORD)secondObject;
|
||||
}
|
||||
|
||||
int spos = 0;
|
||||
for( asUINT n = 0; n < descr->parameterTypes.GetLength(); n++ )
|
||||
{
|
||||
asCDataType ¶mType = descr->parameterTypes[n];
|
||||
if( paramType.IsObject() && !paramType.IsObjectHandle() && !paramType.IsReference() )
|
||||
{
|
||||
if( paramType.GetObjectType()->flags & COMPLEX_MASK )
|
||||
{
|
||||
// The object is passed by reference
|
||||
argBuffer[argOffset++] = args[spos++];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Ensure 8byte alignment for classes that need it
|
||||
if( (paramType.GetObjectType()->flags & asOBJ_APP_CLASS_ALIGN8) && (argOffset & 1) )
|
||||
argOffset++;
|
||||
|
||||
// Copy the object's memory to the buffer
|
||||
memcpy(&argBuffer[argOffset], *(void**)(args+spos), paramType.GetSizeInMemoryBytes());
|
||||
// Delete the original memory
|
||||
engine->CallFree(*(char**)(args+spos));
|
||||
spos++;
|
||||
argOffset += paramType.GetSizeInMemoryDWords();
|
||||
}
|
||||
}
|
||||
else if( paramType.GetTokenType() == ttQuestion )
|
||||
{
|
||||
// Copy both pointer and type id
|
||||
argBuffer[argOffset++] = args[spos++];
|
||||
argBuffer[argOffset++] = args[spos++];
|
||||
}
|
||||
else
|
||||
{
|
||||
// The first 2 floats or doubles are loaded into the float registers.
|
||||
// Actually this is only done if they are the first arguments to the function,
|
||||
// but it doesn't cause any harm to load them into the registers even if they
|
||||
// won't be used so we don't need to check if they really are the first args.
|
||||
if( floatOffset == 0 )
|
||||
{
|
||||
if( paramType.GetTokenType() == ttFloat )
|
||||
floatRegs.f0 = *reinterpret_cast<float*>(&args[spos]);
|
||||
else if( paramType.GetTokenType() == ttDouble )
|
||||
floatRegs.d0 = *reinterpret_cast<double*>(&args[spos]);
|
||||
floatOffset++;
|
||||
}
|
||||
else if( floatOffset == 1 )
|
||||
{
|
||||
if( paramType.GetTokenType() == ttFloat )
|
||||
floatRegs.f1 = *reinterpret_cast<float*>(&args[spos]);
|
||||
else if( paramType.GetTokenType() == ttDouble )
|
||||
floatRegs.d1 = *reinterpret_cast<double*>(&args[spos]);
|
||||
floatOffset++;
|
||||
}
|
||||
|
||||
// Copy the value directly
|
||||
if( paramType.GetSizeOnStackDWords() > 1 )
|
||||
{
|
||||
// Make sure the argument is 8byte aligned
|
||||
if( argOffset & 1 )
|
||||
argOffset++;
|
||||
*reinterpret_cast<asQWORD*>(&argBuffer[argOffset]) = *reinterpret_cast<asQWORD*>(&args[spos]);
|
||||
argOffset += 2;
|
||||
spos += 2;
|
||||
}
|
||||
else
|
||||
argBuffer[argOffset++] = args[spos++];
|
||||
}
|
||||
}
|
||||
|
||||
if( callConv == ICC_CDECL_OBJLAST || callConv == ICC_CDECL_OBJLAST_RETURNINMEM )
|
||||
{
|
||||
// Add the object pointer as the last argument
|
||||
argBuffer[argOffset++] = (asPWORD)obj;
|
||||
}
|
||||
|
||||
if( callConv == ICC_THISCALL_OBJLAST || callConv == ICC_VIRTUAL_THISCALL_OBJLAST ||
|
||||
callConv == ICC_THISCALL_OBJLAST_RETURNINMEM || callConv == ICC_VIRTUAL_THISCALL_OBJLAST_RETURNINMEM )
|
||||
{
|
||||
// Add the second object pointer
|
||||
argBuffer[argOffset++] = (asPWORD)secondObject;
|
||||
}
|
||||
|
||||
switch( callConv )
|
||||
{
|
||||
case ICC_CDECL:
|
||||
case ICC_CDECL_RETURNINMEM:
|
||||
case ICC_STDCALL:
|
||||
case ICC_STDCALL_RETURNINMEM:
|
||||
case ICC_CDECL_OBJLAST:
|
||||
case ICC_CDECL_OBJLAST_RETURNINMEM:
|
||||
case ICC_CDECL_OBJFIRST:
|
||||
case ICC_CDECL_OBJFIRST_RETURNINMEM:
|
||||
case ICC_THISCALL:
|
||||
case ICC_THISCALL_RETURNINMEM:
|
||||
case ICC_THISCALL_OBJFIRST:
|
||||
case ICC_THISCALL_OBJFIRST_RETURNINMEM:
|
||||
case ICC_THISCALL_OBJLAST:
|
||||
case ICC_THISCALL_OBJLAST_RETURNINMEM:
|
||||
retQW = mipsFunc(argOffset*4, argBuffer, func, floatRegs);
|
||||
break;
|
||||
|
||||
case ICC_VIRTUAL_THISCALL:
|
||||
case ICC_VIRTUAL_THISCALL_RETURNINMEM:
|
||||
case ICC_VIRTUAL_THISCALL_OBJFIRST:
|
||||
case ICC_VIRTUAL_THISCALL_OBJFIRST_RETURNINMEM:
|
||||
case ICC_VIRTUAL_THISCALL_OBJLAST:
|
||||
case ICC_VIRTUAL_THISCALL_OBJLAST_RETURNINMEM:
|
||||
// Get virtual function table from the object pointer
|
||||
vftable = *(void***)obj;
|
||||
retQW = mipsFunc(argOffset*4, argBuffer, vftable[asPWORD(func)>>2], floatRegs);
|
||||
break;
|
||||
default:
|
||||
context->SetInternalException(TXT_INVALID_CALLING_CONVENTION);
|
||||
}
|
||||
|
||||
// If the return is a float value we need to get the value from the FP register
|
||||
if( sysFunc->hostReturnFloat )
|
||||
{
|
||||
if( sysFunc->hostReturnSize == 1 )
|
||||
*(asDWORD*)&retQW = GetReturnedFloat();
|
||||
else
|
||||
retQW = GetReturnedDouble();
|
||||
}
|
||||
|
||||
return retQW;
|
||||
}
|
||||
|
||||
asDWORD GetReturnedFloat()
|
||||
{
|
||||
asDWORD f;
|
||||
|
||||
asm("swc1 $f0, %0\n" : "=m"(f));
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
asQWORD GetReturnedDouble()
|
||||
{
|
||||
asQWORD d = 0;
|
||||
|
||||
asm("sdc1 $f0, %0\n" : "=m"(d));
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
// asQWORD mipsFunc(asUINT argSize, asDWORD *argBuffer, void *func, SFloatRegs &floatRegs);
|
||||
// $2,$3 $4 $5 $6 $7
|
||||
asm(
|
||||
" .text\n"
|
||||
//" .align 2\n"
|
||||
" .cfi_startproc\n"
|
||||
" .global mipsFunc\n"
|
||||
" .ent mipsFunc\n"
|
||||
"mipsFunc:\n"
|
||||
//" .frame $fp,64,$31 # vars= 0, regs= 0/0, args= 0, gp= 0\n"
|
||||
//" .mask 0x00000000,0\n"
|
||||
//" .fmask 0x00000000,0\n"
|
||||
" .set noreorder\n"
|
||||
" .set nomacro\n"
|
||||
|
||||
// align the stack frame to 8 bytes
|
||||
" addiu $12, $4, 7\n" // t4 ($12) = argSize ($4) + 7
|
||||
" li $13, -8\n" // t5 ($13) = 0xfffffffffffffff8
|
||||
" and $12, $12, $13\n" // t4 ($12) &= t5 ($13). t4 holds the size of the argument block
|
||||
// It is required that the caller reserves space for at least 16 bytes even if there are less than 4 arguments
|
||||
// and add 8 bytes for the return pointer and s0 ($16) backup
|
||||
" addiu $13, $12, 24\n" // t5 = t4 + 24. t5 ($13) holds the total size of the stack frame (including return pointer)
|
||||
// save the s0 register (so we can use it to remember where our return pointer is lives)
|
||||
" sw $16, -4($sp)\n" // store the s0 register (so we can use it to remember how big our stack frame is)
|
||||
" .cfi_offset 16, -4\n"
|
||||
// store the return pointer
|
||||
" sw $31, -8($sp)\n"
|
||||
" .cfi_offset 31, -8\n"
|
||||
// keep original stack pointer
|
||||
" move $16, $sp\n"
|
||||
" .cfi_def_cfa_register 16\n"
|
||||
// push the stack
|
||||
" subu $sp, $sp, $13\n"
|
||||
|
||||
// store the argument in temporary registers
|
||||
" addiu $25, $6, 0\n" // t9 ($25) holds the function pointer (must be t9 for position independent code)
|
||||
" addiu $3, $4, 0\n" // v1 ($3) holds the size of the argument buffer
|
||||
" move $15, $5\n" // t7 ($15) holds the pointer to the argBuffer
|
||||
" move $14, $7\n" // t6 ($14) holds the values for the float registers
|
||||
|
||||
// load integer registers
|
||||
" lw $4, 0($15)\n" // a0 ($4)
|
||||
" lw $5, 4($15)\n" // a1 ($5)
|
||||
" lw $6, 8($15)\n" // a2 ($6)
|
||||
" lw $7, 12($15)\n" // a3 ($7)
|
||||
|
||||
// load float registers
|
||||
" ldc1 $f12, 8($14)\n"
|
||||
" ldc1 $f14, 0($14)\n"
|
||||
|
||||
// skip stack parameters if there are 4 or less as they are moved into the registers
|
||||
" addi $14, $3, -16\n" // The first 4 args were already loaded into registers
|
||||
" blez $14, andCall\n"
|
||||
" nop\n"
|
||||
|
||||
// push stack parameters
|
||||
"pushArgs:\n"
|
||||
" addi $3, -4\n"
|
||||
// load from $15 + stack bytes ($3)
|
||||
" addu $14, $15, $3\n"
|
||||
" lw $14, 0($14)\n"
|
||||
// store to $sp + stack bytes ($3)
|
||||
" addu $13, $sp, $3\n"
|
||||
" sw $14, 0($13)\n"
|
||||
// if there are more, loop...
|
||||
" bne $3, $0, pushArgs\n"
|
||||
" nop\n"
|
||||
|
||||
// and call the function
|
||||
"andCall:\n"
|
||||
" jalr $25\n"
|
||||
" nop\n"
|
||||
|
||||
// restore original stack pointer
|
||||
" move $sp, $16\n"
|
||||
// restore the return pointer
|
||||
" lw $31, -8($sp)\n"
|
||||
// restore the original value of $16
|
||||
" lw $16, -4($sp)\n"
|
||||
// and return from the function
|
||||
" jr $31\n"
|
||||
" nop\n"
|
||||
|
||||
" .set macro\n"
|
||||
" .set reorder\n"
|
||||
" .end mipsFunc\n"
|
||||
" .cfi_endproc\n"
|
||||
" .size mipsFunc, .-mipsFunc\n"
|
||||
);
|
||||
|
||||
#else // !(defined(__linux__) && defined(_ABIO32))
|
||||
|
||||
// The MIPS ABI used by PSP and PS2 is implemented here
|
||||
|
||||
#define AS_MIPS_MAX_ARGS 32
|
||||
#define AS_NUM_REG_FLOATS 8
|
||||
#define AS_NUM_REG_INTS 8
|
||||
@ -191,33 +503,12 @@ asDWORD GetReturnedFloat()
|
||||
return f;
|
||||
}
|
||||
|
||||
/*
|
||||
asDWORD GetReturnedFloat();
|
||||
|
||||
asm(
|
||||
" .align 4\n"
|
||||
" .global GetReturnedFloat\n"
|
||||
"GetReturnedFloat:\n"
|
||||
" .set noreorder\n"
|
||||
" .set nomacro\n"
|
||||
" j $ra\n"
|
||||
" mfc1 $v0, $f0\n"
|
||||
" .set macro\n"
|
||||
" .set reorder\n"
|
||||
" .end Func\n"
|
||||
*/
|
||||
|
||||
|
||||
// sizeof(double) == 4 with sh-elf-gcc (3.4.0) -m4
|
||||
// so this isn't really used...
|
||||
asQWORD GetReturnedDouble()
|
||||
{
|
||||
asQWORD d = 0;
|
||||
|
||||
printf("Broken!!!");
|
||||
/*
|
||||
asm("sw $v0, %0\n" : "=m"(d));
|
||||
*/
|
||||
asm("sdc1 $f0, %0\n" : "=m"(d));
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
@ -352,7 +643,7 @@ asm(
|
||||
" .set nomacro\n"
|
||||
// align the stack frame to 8 bytes
|
||||
" addiu $12, $6, 7\n"
|
||||
" li $13, -8\n" // 0xfffffffffffffffc
|
||||
" li $13, -8\n" // 0xfffffffffffffff8
|
||||
" and $12, $12, $13\n" // t4 holds the size of the argument block
|
||||
// and add 8 bytes for the return pointer and s0 backup
|
||||
" addiu $13, $12, 8\n" // t5 holds the total size of the stack frame (including return pointer)
|
||||
@ -432,6 +723,8 @@ asm(
|
||||
" .size mipsFunc, .-mipsFunc\n"
|
||||
);
|
||||
|
||||
#endif // PSP and PS2 MIPS ABI
|
||||
|
||||
END_AS_NAMESPACE
|
||||
|
||||
#endif // AS_MIPS
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
AngelCode Scripting Library
|
||||
Copyright (c) 2003-2014 Andreas Jonsson
|
||||
Copyright (c) 2003-2015 Andreas Jonsson
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any
|
||||
@ -73,14 +73,18 @@ static asQWORD __attribute__((noinline)) X64_CallFunction(const asQWORD *args, i
|
||||
|
||||
__asm__ __volatile__ (
|
||||
|
||||
" movq %0, %%rcx \n" // rcx = cnt
|
||||
" movq %0, %%rcx \n" // rcx = cnt
|
||||
" movq %1, %%r10 \n" // r10 = args
|
||||
" movq %2, %%r11 \n" // r11 = func
|
||||
|
||||
// Backup stack pointer in R15 that is guaranteed to maintain its value over function calls
|
||||
" movq %%rsp, %%r15 \n"
|
||||
#ifdef __OPTIMIZE__
|
||||
// Make sure the stack unwind logic knows we've backed up the stack pointer in register r15
|
||||
// This should only be done if any optimization is done. If no optimization (-O0) is used,
|
||||
// then the compiler already backups the rsp before entering the inline assembler code
|
||||
" .cfi_def_cfa_register r15 \n"
|
||||
#endif
|
||||
|
||||
// Skip the first 128 bytes on the stack frame, called "red zone",
|
||||
// that might be used by the compiler to store temporary values
|
||||
@ -100,7 +104,7 @@ static asQWORD __attribute__((noinline)) X64_CallFunction(const asQWORD *args, i
|
||||
" jle endstack \n"
|
||||
" subl $1, %%esi \n"
|
||||
" xorl %%edx, %%edx \n"
|
||||
" leaq 8(, %%rsi, 8), %%rcx \n"
|
||||
" leaq 8(, %%rsi, 8), %%rcx \n"
|
||||
"loopstack: \n"
|
||||
" movq 112(%%r10, %%rdx), %%rax \n"
|
||||
" pushq %%rax \n"
|
||||
@ -128,12 +132,16 @@ static asQWORD __attribute__((noinline)) X64_CallFunction(const asQWORD *args, i
|
||||
" movsd 56(%%rax), %%xmm7 \n"
|
||||
|
||||
// Call the function
|
||||
" call *%%r11 \n"
|
||||
" call *%%r11 \n"
|
||||
|
||||
// Restore stack pointer
|
||||
" mov %%r15, %%rsp \n"
|
||||
#ifdef __OPTIMIZE__
|
||||
// Inform the stack unwind logic that the stack pointer has been restored
|
||||
// This should only be done if any optimization is done. If no optimization (-O0) is used,
|
||||
// then the compiler already backups the rsp before entering the inline assembler code
|
||||
" .cfi_def_cfa_register rsp \n"
|
||||
#endif
|
||||
|
||||
// Put return value in retQW1 and retQW2, using either RAX:RDX or XMM0:XMM1 depending on type of return value
|
||||
" movl %5, %%ecx \n"
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
AngelCode Scripting Library
|
||||
Copyright (c) 2003-2014 Andreas Jonsson
|
||||
Copyright (c) 2003-2015 Andreas Jonsson
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any
|
||||
@ -1263,13 +1263,13 @@ endcopy:
|
||||
"subl $4, %%ecx \n"
|
||||
"jne copyloop3 \n"
|
||||
"endcopy3: \n"
|
||||
#if defined(__MINGW32__) && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 7) || __GNUC__ > 4)
|
||||
// MinGW made some strange choices with 4.7, and the thiscall calling convention
|
||||
// when returning an object in memory is completely different from when not returning
|
||||
// in memory
|
||||
"pushl 0(%%ebx) \n" // push obj on the stack
|
||||
"movl 16(%%ebx), %%ecx \n" // move the return pointer into ECX
|
||||
"call *12(%%ebx) \n" // call the function
|
||||
#ifdef AS_MINGW47
|
||||
// MinGW made some strange choices with 4.7 and the thiscall calling convention,
|
||||
// returning an object in memory is completely different from when not returning
|
||||
// in memory
|
||||
"pushl 0(%%ebx) \n" // push obj on the stack
|
||||
"movl 16(%%ebx), %%ecx \n" // move the return pointer into ECX
|
||||
"call *12(%%ebx) \n" // call the function
|
||||
#else
|
||||
"movl 0(%%ebx), %%ecx \n" // move obj into ECX
|
||||
#ifdef THISCALL_PASS_OBJECT_POINTER_ON_THE_STACK
|
||||
@ -1286,7 +1286,7 @@ endcopy:
|
||||
"addl $4, %%esp \n" // pop the object pointer
|
||||
#endif
|
||||
#endif
|
||||
#endif // MINGW
|
||||
#endif // AS_MINGW47
|
||||
// Pop the alignment bytes
|
||||
"popl %%esp \n"
|
||||
"popl %%ebx \n"
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
AngelCode Scripting Library
|
||||
Copyright (c) 2003-2014 Andreas Jonsson
|
||||
Copyright (c) 2003-2015 Andreas Jonsson
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any
|
||||
@ -43,7 +43,9 @@
|
||||
// various fixes in asm ppcFunc
|
||||
// fix for variable arguments
|
||||
//
|
||||
|
||||
// Modified by Anthony Clark May 2015
|
||||
// Fixed the issue where int64 and uint64 could not be passed nativly
|
||||
// few minor fixes within asm ppcFunc to handle int64 and uint64
|
||||
|
||||
|
||||
// XBox 360 calling convention
|
||||
@ -87,7 +89,6 @@
|
||||
// References:
|
||||
// https://www-01.ibm.com/chips/techlib/techlib.nsf/techdocs/852569B20050FF77852569970071B0D6/$file/eabi_app.pdf
|
||||
//
|
||||
// TODO: The code doesn't handle int64 and uint64 parameters
|
||||
// TODO: The code doesn't handle objects passed by value (unless they are max 4 bytes in size)
|
||||
|
||||
|
||||
@ -128,7 +129,7 @@ enum argTypes
|
||||
// pArgs is the array of the argument values
|
||||
// pArgTypes is an array containing a byte indicating the type (enum argTypes) for each argument.
|
||||
// dwFunc is the address of the function that will be called
|
||||
asQWORD __declspec( naked ) ppcFunc(const asDWORD* pArgs, asDWORD dwFunc, const asBYTE* pArgTypes)
|
||||
asQWORD __declspec( naked ) ppcFunc(const asQWORD* pArgs, asDWORD dwFunc, const asBYTE* pArgTypes)
|
||||
{
|
||||
__asm
|
||||
{
|
||||
@ -202,7 +203,7 @@ ppcNextArg:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
ppcArgIsInteger:
|
||||
// Get the arg from the stack
|
||||
lwz r12, 0(r26)
|
||||
ld r12, 0(r26)
|
||||
|
||||
// r23 holds the integer arg count so far
|
||||
cmplwi cr6, r23, 0
|
||||
@ -251,11 +252,11 @@ ppcArgIsInteger:
|
||||
b ppcLoadIntRegUpd
|
||||
|
||||
ppcLoadIntRegUpd:
|
||||
stw r12, 0(r31) // push on the stack
|
||||
std r12, 0(r31) // push on the stack
|
||||
addi r31, r31, 8 // inc stack by 1 reg
|
||||
|
||||
addi r23, r23, 1 // Increment used int register count
|
||||
addi r26, r26, 4 // Increment pArgs
|
||||
addi r26, r26, 8 // Increment pArgs
|
||||
b ppcNextArg // Call next arg
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@ -511,7 +512,7 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr,
|
||||
|
||||
// Pack the arguments into an array that ppcFunc() can use to load each CPU register properly
|
||||
asBYTE ppcArgsType[AS_PPC_MAX_ARGS + AS_PPC_RETURNINMEM_REG + AS_PPC_THISCALL_REG + AS_PPC_ENDOFARGS];
|
||||
asDWORD ppcArgs[AS_PPC_MAX_ARGS + AS_PPC_RETURNINMEM_REG + AS_PPC_THISCALL_REG];
|
||||
asQWORD ppcArgs[AS_PPC_MAX_ARGS + AS_PPC_RETURNINMEM_REG + AS_PPC_THISCALL_REG];
|
||||
int argsCnt = 0;
|
||||
|
||||
// If the function returns an object in memory, we allocate the memory and put the ptr to the front (will go to r3)
|
||||
@ -625,35 +626,34 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr,
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: How should int64 and uint64 be passed natively?
|
||||
// Currently the code doesn't handle these types
|
||||
|
||||
// TODO: The code also ignore the fact that large objects
|
||||
// passed by value has been copied to the stack
|
||||
// in the above loop.
|
||||
|
||||
*pCurArgType++ = ppcINTARG;
|
||||
|
||||
*((int*) pCurFixedArgValue) = *((int*) pCurStackArgValue);
|
||||
*((asQWORD*) pCurFixedArgValue) = *((asUINT*) pCurStackArgValue);
|
||||
|
||||
if( !descr->parameterTypes[n].IsReference() )
|
||||
{
|
||||
// If the arg is less that 4 bytes, then move the
|
||||
// bytes to the higher bytes within the dword
|
||||
// If the arg is not 4 bytes which we coppied, lets do it again the right way
|
||||
asUINT numBytes = descr->parameterTypes[n].GetSizeInMemoryBytes();
|
||||
if( numBytes == 1 )
|
||||
{
|
||||
pCurFixedArgValue[3] = pCurFixedArgValue[0];
|
||||
pCurFixedArgValue[0] = 0;
|
||||
*((asQWORD*) pCurFixedArgValue) = *((asBYTE*) pCurStackArgValue);
|
||||
}
|
||||
else if( numBytes == 2 )
|
||||
{
|
||||
*(asWORD*)&pCurFixedArgValue[2] = *(asWORD*)&pCurFixedArgValue[0];
|
||||
*(asWORD*)&pCurFixedArgValue[0] = 0;
|
||||
*((asQWORD*) pCurFixedArgValue) = *((asWORD*) pCurStackArgValue);
|
||||
}
|
||||
else if( numBytes == 8 )
|
||||
{
|
||||
*((asQWORD*) pCurFixedArgValue) = *((asQWORD*) pCurStackArgValue);
|
||||
pCurStackArgValue += 4; // Increase our cur stack arg value by 4 bytes to = 8 total later
|
||||
}
|
||||
}
|
||||
|
||||
pCurFixedArgValue += 4;
|
||||
pCurFixedArgValue += 8;
|
||||
pCurStackArgValue += 4;
|
||||
|
||||
// if it is a variable argument, account for the typeId
|
||||
@ -703,7 +703,7 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr,
|
||||
// Add the object pointer as the last argument
|
||||
ppcArgsType[argsCnt++] = ppcINTARG;
|
||||
ppcArgsType[argsCnt] = ppcENDARG;
|
||||
*((asPWORD*)pCurFixedArgValue) = (asPWORD)obj;
|
||||
*((asQWORD*)pCurFixedArgValue) = (asPWORD)obj;
|
||||
retQW = ppcFunc( ppcArgs, (asDWORD)func, ppcArgsType );
|
||||
break;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
AngelCode Scripting Library
|
||||
Copyright (c) 2003-2014 Andreas Jonsson
|
||||
Copyright (c) 2003-2015 Andreas Jonsson
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any
|
||||
@ -73,14 +73,9 @@ struct asSExprContext
|
||||
{
|
||||
asSExprContext(asCScriptEngine *engine) : bc(engine)
|
||||
{
|
||||
exprNode = 0;
|
||||
origExpr = 0;
|
||||
property_get = 0;
|
||||
property_set = 0;
|
||||
property_const = false;
|
||||
property_handle = false;
|
||||
property_ref = false;
|
||||
property_arg = 0;
|
||||
property_arg = 0;
|
||||
|
||||
Clear();
|
||||
}
|
||||
~asSExprContext()
|
||||
{
|
||||
@ -90,43 +85,95 @@ struct asSExprContext
|
||||
void Clear()
|
||||
{
|
||||
bc.ClearAll();
|
||||
type.SetDummy();
|
||||
type.Set(asCDataType());
|
||||
deferredParams.SetLength(0);
|
||||
if( property_arg )
|
||||
asDELETE(property_arg, asSExprContext);
|
||||
property_arg = 0;
|
||||
deferredParams.SetLength(0);
|
||||
exprNode = 0;
|
||||
origExpr = 0;
|
||||
property_get = 0;
|
||||
property_set = 0;
|
||||
property_const = false;
|
||||
property_handle = false;
|
||||
property_ref = false;
|
||||
methodName = "";
|
||||
enumValue = "";
|
||||
property_arg = 0;
|
||||
exprNode = 0;
|
||||
origExpr = 0;
|
||||
property_get = 0;
|
||||
property_set = 0;
|
||||
property_const = false;
|
||||
property_handle = false;
|
||||
property_ref = false;
|
||||
methodName = "";
|
||||
enumValue = "";
|
||||
isVoidExpression = false;
|
||||
isCleanArg = false;
|
||||
}
|
||||
bool IsClassMethod()
|
||||
bool IsClassMethod() const
|
||||
{
|
||||
if( type.dataType.GetObjectType() == 0 ) return false;
|
||||
if( methodName == "" ) return false;
|
||||
if( type.dataType.GetObjectType() == &type.dataType.GetObjectType()->engine->functionBehaviours ) return false;
|
||||
return true;
|
||||
}
|
||||
bool IsGlobalFunc()
|
||||
bool IsGlobalFunc() const
|
||||
{
|
||||
if( type.dataType.GetObjectType() == 0 ) return false;
|
||||
if( methodName == "" ) return false;
|
||||
if( type.dataType.GetObjectType() != &type.dataType.GetObjectType()->engine->functionBehaviours ) return false;
|
||||
return true;
|
||||
}
|
||||
void SetLambda(asCScriptNode *funcDecl)
|
||||
{
|
||||
asASSERT( funcDecl && funcDecl->nodeType == snFunction );
|
||||
asASSERT( bc.GetLastInstr() == -1 );
|
||||
|
||||
Clear();
|
||||
type.SetUndefinedFuncHandle(bc.GetEngine());
|
||||
exprNode = funcDecl;
|
||||
}
|
||||
bool IsLambda() const
|
||||
{
|
||||
if( type.IsUndefinedFuncHandle() && exprNode && exprNode->nodeType == snFunction )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
void SetVoidExpression()
|
||||
{
|
||||
Clear();
|
||||
type.SetVoid();
|
||||
isVoidExpression = true;
|
||||
}
|
||||
bool IsVoidExpression() const
|
||||
{
|
||||
if( isVoidExpression && type.IsVoid() && exprNode == 0 )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
void Merge(asSExprContext *after)
|
||||
{
|
||||
type = after->type;
|
||||
property_get = after->property_get;
|
||||
property_set = after->property_set;
|
||||
property_const = after->property_const;
|
||||
property_handle = after->property_handle;
|
||||
property_ref = after->property_ref;
|
||||
property_arg = after->property_arg;
|
||||
exprNode = after->exprNode;
|
||||
methodName = after->methodName;
|
||||
enumValue = after->enumValue;
|
||||
isVoidExpression = after->isVoidExpression;
|
||||
isCleanArg = after->isCleanArg;
|
||||
|
||||
after->property_arg = 0;
|
||||
|
||||
// Do not copy the origExpr member
|
||||
}
|
||||
|
||||
asCByteCode bc;
|
||||
asCTypeInfo type;
|
||||
int property_get;
|
||||
int property_set;
|
||||
bool property_const; // If the object that is being accessed through property accessor is read-only
|
||||
bool property_handle; // If the property accessor is called on an object stored in a handle
|
||||
bool property_ref; // If the property accessor is called on a reference
|
||||
bool property_const; // If the object that is being accessed through property accessor is read-only
|
||||
bool property_handle; // If the property accessor is called on an object stored in a handle
|
||||
bool property_ref; // If the property accessor is called on a reference
|
||||
bool isVoidExpression; // Set to true if the expression is an explicit 'void', e.g. used to ignore out parameters in func calls
|
||||
bool isCleanArg; // Set to true if the expression has only been initialized with default constructor
|
||||
asSExprContext *property_arg;
|
||||
asCArray<asSDeferredParam> deferredParams;
|
||||
asCScriptNode *exprNode;
|
||||
@ -212,8 +259,8 @@ protected:
|
||||
int CompileExpressionPostOp(asCScriptNode *node, asSExprContext *out);
|
||||
int CompileExpressionValue(asCScriptNode *node, asSExprContext *out);
|
||||
int CompileFunctionCall(asCScriptNode *node, asSExprContext *out, asCObjectType *objectType, bool objIsConst, const asCString &scope = "");
|
||||
void CompileConstructCall(asCScriptNode *node, asSExprContext *out);
|
||||
void CompileConversion(asCScriptNode *node, asSExprContext *out);
|
||||
int CompileConstructCall(asCScriptNode *node, asSExprContext *out);
|
||||
int CompileConversion(asCScriptNode *node, asSExprContext *out);
|
||||
int CompileOperator(asCScriptNode *node, asSExprContext *l, asSExprContext *r, asSExprContext *out, eTokenType opToken = ttUnrecognizedToken);
|
||||
void CompileOperatorOnHandles(asCScriptNode *node, asSExprContext *l, asSExprContext *r, asSExprContext *out, eTokenType opToken = ttUnrecognizedToken);
|
||||
void CompileMathOperator(asCScriptNode *node, asSExprContext *l, asSExprContext *r, asSExprContext *out, eTokenType opToken = ttUnrecognizedToken);
|
||||
@ -239,6 +286,7 @@ protected:
|
||||
void CompileInitAsCopy(asCDataType &type, int offset, asCByteCode *bc, asSExprContext *arg, asCScriptNode *node, bool derefDestination);
|
||||
|
||||
// Helper functions
|
||||
void ConvertToPostFix(asCScriptNode *expr, asCArray<asCScriptNode *> &postfix);
|
||||
void ProcessPropertyGetAccessor(asSExprContext *ctx, asCScriptNode *node);
|
||||
int ProcessPropertySetAccessor(asSExprContext *ctx, asSExprContext *arg, asCScriptNode *node);
|
||||
int ProcessPropertyGetSetAccessor(asSExprContext *ctx, asSExprContext *lctx, asSExprContext *rctx, eTokenType op, asCScriptNode *errNode);
|
||||
@ -288,6 +336,7 @@ protected:
|
||||
asUINT ImplicitConvObjectValue(asSExprContext *ctx, const asCDataType &to, asCScriptNode *node, EImplicitConv convType, bool generateCode);
|
||||
void ImplicitConversionConstant(asSExprContext *ctx, const asCDataType &to, asCScriptNode *node, EImplicitConv convType);
|
||||
void ImplicitConvObjectToBestMathType(asSExprContext *ctx, asCScriptNode *node);
|
||||
asUINT ImplicitConvLambdaToFunc(asSExprContext *ctx, const asCDataType &to, asCScriptNode *node, EImplicitConv convType, bool generateCode = true);
|
||||
|
||||
void LineInstr(asCByteCode *bc, size_t pos);
|
||||
|
||||
@ -307,16 +356,18 @@ protected:
|
||||
bool hasCompileErrors;
|
||||
|
||||
int nextLabel;
|
||||
int numLambdas;
|
||||
|
||||
asCVariableScope *variables;
|
||||
asCBuilder *builder;
|
||||
asCScriptEngine *engine;
|
||||
asCScriptCode *script;
|
||||
asCVariableScope *variables;
|
||||
asCBuilder *builder;
|
||||
asCScriptEngine *engine;
|
||||
asCScriptCode *script;
|
||||
asCScriptFunction *outFunc;
|
||||
|
||||
bool m_isConstructor;
|
||||
bool m_isConstructorCalled;
|
||||
sClassDeclaration *m_classDecl;
|
||||
bool m_isConstructor;
|
||||
bool m_isConstructorCalled;
|
||||
sClassDeclaration *m_classDecl;
|
||||
sGlobalVariableDescription *m_globalVar;
|
||||
|
||||
asCArray<int> breakLabels;
|
||||
asCArray<int> continueLabels;
|
||||
@ -353,7 +404,7 @@ protected:
|
||||
|
||||
bool isCompilingDefaultArg;
|
||||
bool isProcessingDeferredParams;
|
||||
int noCodeOutput;
|
||||
int noCodeOutput;
|
||||
};
|
||||
|
||||
END_AS_NAMESPACE
|
||||
|
@ -586,6 +586,7 @@
|
||||
#define AS_NO_MEMORY_H
|
||||
#define AS_MIPS
|
||||
#define AS_PSP
|
||||
#define AS_USE_DOUBLE_AS_FLOAT
|
||||
// PSVita
|
||||
#elif defined(__psp2__)
|
||||
#define AS_PSVITA
|
||||
@ -799,6 +800,14 @@
|
||||
// As of version 4.7 MinGW changed the ABI, presumably
|
||||
// to be better aligned with how MSVC works
|
||||
#if (__GNUC__ == 4 && __GNUC_MINOR__ >= 7) || __GNUC__ > 4
|
||||
#define AS_MINGW47
|
||||
#endif
|
||||
|
||||
#if (__clang_major__ == 3 && __clang_minor__ > 4) || __clang_major > 3
|
||||
#define AS_MINGW47
|
||||
#endif
|
||||
|
||||
#ifdef AS_MINGW47
|
||||
#undef CALLEE_POPS_HIDDEN_RETURN_POINTER
|
||||
#define THISCALL_CALLEE_POPS_ARGUMENTS
|
||||
#else
|
||||
@ -845,7 +854,7 @@
|
||||
// STDCALL is not available on 64bit Linux
|
||||
#undef STDCALL
|
||||
#define STDCALL
|
||||
#elif defined(__ARMEL__) || defined(__arm__)
|
||||
#elif (defined(__ARMEL__) || defined(__arm__)) && !(defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__))
|
||||
#define AS_ARM
|
||||
|
||||
// TODO: The stack unwind on exceptions currently fails due to the assembler code in as_callfunc_arm_gcc.S
|
||||
@ -884,11 +893,24 @@
|
||||
|
||||
#elif defined(__mips__)
|
||||
#define AS_MIPS
|
||||
#define AS_BIG_ENDIAN
|
||||
#define AS_USE_DOUBLE_AS_FLOAT
|
||||
#undef STDCALL
|
||||
#define STDCALL
|
||||
|
||||
// Native calling conventions for Linux/Mips do not work yet.
|
||||
#define AS_MAX_PORTABILITY
|
||||
#ifdef _ABIO32
|
||||
#define AS_MIPS
|
||||
|
||||
// All structures are returned in memory regardless of size or complexity
|
||||
#define THISCALL_RETURN_SIMPLE_IN_MEMORY
|
||||
#define THISCALL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE 0
|
||||
#define CDECL_RETURN_SIMPLE_IN_MEMORY
|
||||
#define CDECL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE 0
|
||||
#define STDCALL_RETURN_SIMPLE_IN_MEMORY
|
||||
#define CDECL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE 0
|
||||
#undef AS_NO_THISCALL_FUNCTOR_METHOD
|
||||
#else
|
||||
// For other ABIs the native calling convention is not available (yet)
|
||||
#define AS_MAX_PORTABILITY
|
||||
#endif
|
||||
#else
|
||||
#define AS_MAX_PORTABILITY
|
||||
#endif
|
||||
@ -936,6 +958,7 @@
|
||||
// Support native calling conventions on MIPS architecture
|
||||
#if (defined(_MIPS_ARCH) || defined(_mips) || defined(__MIPSEL__)) && !defined(__LP64__)
|
||||
#define AS_MIPS
|
||||
#define AS_USE_DOUBLE_AS_FLOAT
|
||||
#else
|
||||
#define AS_MAX_PORTABILITY
|
||||
#endif
|
||||
@ -988,6 +1011,9 @@
|
||||
#if (defined(_ARM_) || defined(__arm__))
|
||||
// Android ARM
|
||||
|
||||
// TODO: The stack unwind on exceptions currently fails due to the assembler code in as_callfunc_arm_gcc.S
|
||||
#define AS_NO_EXCEPTIONS
|
||||
|
||||
#undef THISCALL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE
|
||||
#undef CDECL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE
|
||||
#undef STDCALL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE
|
||||
@ -1013,6 +1039,26 @@
|
||||
#define THISCALL_PASS_OBJECT_POINTER_ON_THE_STACK
|
||||
#define AS_X86
|
||||
#undef AS_NO_THISCALL_FUNCTOR_METHOD
|
||||
#elif defined(__mips__)
|
||||
#define AS_MIPS
|
||||
#undef STDCALL
|
||||
#define STDCALL
|
||||
|
||||
#ifdef _ABIO32
|
||||
#define AS_MIPS
|
||||
|
||||
// All structures are returned in memory regardless of size or complexity
|
||||
#define THISCALL_RETURN_SIMPLE_IN_MEMORY
|
||||
#define THISCALL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE 0
|
||||
#define CDECL_RETURN_SIMPLE_IN_MEMORY
|
||||
#define CDECL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE 0
|
||||
#define STDCALL_RETURN_SIMPLE_IN_MEMORY
|
||||
#define CDECL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE 0
|
||||
#undef AS_NO_THISCALL_FUNCTOR_METHOD
|
||||
#else
|
||||
// For other ABIs the native calling convention is not available (yet)
|
||||
#define AS_MAX_PORTABILITY
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Haiku OS
|
||||
@ -1047,7 +1093,7 @@
|
||||
// Support native calling conventions on Intel 32bit CPU
|
||||
#define THISCALL_PASS_OBJECT_POINTER_ON_THE_STACK
|
||||
#define AS_X86
|
||||
#elif defined(__LP64__)
|
||||
#elif defined(__x86_64__)
|
||||
#define AS_X64_GCC
|
||||
#define HAS_128_BIT_PRIMITIVES
|
||||
#define SPLIT_OBJS_BY_MEMBER_TYPES
|
||||
@ -1112,11 +1158,6 @@
|
||||
// Nothing special here
|
||||
#endif
|
||||
|
||||
// MIPS architecture (generally PS2 and PSP consoles, potentially supports N64 as well)
|
||||
#if defined(_MIPS_ARCH) || defined(_mips) || defined(__MIPSEL__) || defined(__PSP__) || defined(__psp__) || defined(_EE_) || defined(_PSP) || defined(_PS2)
|
||||
#define AS_USE_DOUBLE_AS_FLOAT // use 32bit floats instead of doubles
|
||||
#endif
|
||||
|
||||
// PowerPC, e.g. Mac, GameCube, PS3, XBox 360, Wii
|
||||
#if defined(__PPC__) || defined(__ppc__) || defined(_PPC_) || defined(EPPC)
|
||||
#define AS_BIG_ENDIAN
|
||||
|
@ -134,17 +134,32 @@ public:
|
||||
|
||||
#endif
|
||||
|
||||
// interface
|
||||
AS_API asIScriptContext *asGetActiveContext()
|
||||
{
|
||||
asCThreadLocalData *tld = asCThreadManager::GetLocalData();
|
||||
if( tld->activeContexts.GetLength() == 0 )
|
||||
|
||||
// tld can be 0 if asGetActiveContext is called before any engine has been created.
|
||||
|
||||
// Observe! I've seen a case where an application linked with the library twice
|
||||
// and thus ended up with two separate instances of the code and global variables.
|
||||
// The application somehow mixed the two instances so that a function called from
|
||||
// a script ended up calling asGetActiveContext from the other instance that had
|
||||
// never been initialized.
|
||||
|
||||
if( tld == 0 || tld->activeContexts.GetLength() == 0 )
|
||||
return 0;
|
||||
return tld->activeContexts[tld->activeContexts.GetLength()-1];
|
||||
}
|
||||
|
||||
// internal
|
||||
// Note: There is no asPopActiveContext(), just call tld->activeContexts.PopLast() instead
|
||||
asCThreadLocalData *asPushActiveContext(asIScriptContext *ctx)
|
||||
{
|
||||
asCThreadLocalData *tld = asCThreadManager::GetLocalData();
|
||||
asASSERT( tld );
|
||||
if( tld == 0 )
|
||||
return 0;
|
||||
tld->activeContexts.PushLast(ctx);
|
||||
return tld;
|
||||
}
|
||||
@ -1304,8 +1319,9 @@ int asCContext::Execute()
|
||||
}
|
||||
|
||||
// Pop the active context
|
||||
asASSERT(tld->activeContexts[tld->activeContexts.GetLength()-1] == this);
|
||||
tld->activeContexts.PopLast();
|
||||
asASSERT(tld && tld->activeContexts[tld->activeContexts.GetLength()-1] == this);
|
||||
if( tld )
|
||||
tld->activeContexts.PopLast();
|
||||
|
||||
if( m_status == asEXECUTION_FINISHED )
|
||||
{
|
||||
@ -4301,6 +4317,67 @@ void asCContext::ExecuteNext()
|
||||
}
|
||||
l_bc += 2;
|
||||
break;
|
||||
case asBC_Thiscall1:
|
||||
// This instruction is a faster version of asBC_CALLSYS. It is faster because
|
||||
// it has much less runtime overhead with determining the calling convention
|
||||
// and no dynamic code for loading the parameters. The instruction can only
|
||||
// be used to call functions with the following signatures:
|
||||
//
|
||||
// type &obj::func(int)
|
||||
// type &obj::func(uint)
|
||||
// void obj::func(int)
|
||||
// void obj::func(uint)
|
||||
{
|
||||
// Get function ID from the argument
|
||||
int i = asBC_INTARG(l_bc);
|
||||
|
||||
// Need to move the values back to the context as the called functions
|
||||
// may use the debug interface to inspect the registers
|
||||
m_regs.programPointer = l_bc;
|
||||
m_regs.stackPointer = l_sp;
|
||||
m_regs.stackFramePointer = l_fp;
|
||||
|
||||
// Pop the thispointer from the stack
|
||||
void *obj = *(void**)l_sp;
|
||||
l_sp += AS_PTR_SIZE;
|
||||
|
||||
// Pop the int arg from the stack
|
||||
int arg = *(int*)l_sp;
|
||||
l_sp++;
|
||||
|
||||
// Call the method
|
||||
m_callingSystemFunction = m_engine->scriptFunctions[i];
|
||||
void *ptr = m_engine->CallObjectMethodRetPtr(obj, arg, m_callingSystemFunction);
|
||||
m_callingSystemFunction = 0;
|
||||
*(asPWORD*)&m_regs.valueRegister = (asPWORD)ptr;
|
||||
|
||||
// Update the program position after the call so that line number is correct
|
||||
l_bc += 2;
|
||||
|
||||
if( m_regs.doProcessSuspend )
|
||||
{
|
||||
// Should the execution be suspended?
|
||||
if( m_doSuspend )
|
||||
{
|
||||
m_regs.programPointer = l_bc;
|
||||
m_regs.stackPointer = l_sp;
|
||||
m_regs.stackFramePointer = l_fp;
|
||||
|
||||
m_status = asEXECUTION_SUSPENDED;
|
||||
return;
|
||||
}
|
||||
// An exception might have been raised
|
||||
if( m_status != asEXECUTION_ACTIVE )
|
||||
{
|
||||
m_regs.programPointer = l_bc;
|
||||
m_regs.stackPointer = l_sp;
|
||||
m_regs.stackFramePointer = l_fp;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// Don't let the optimizer optimize for size,
|
||||
// since it requires extra conditions and jumps
|
||||
@ -4887,7 +4964,7 @@ int asCContext::GetExceptionLineNumber(int *column, const char **sectionName)
|
||||
|
||||
if( sectionName )
|
||||
{
|
||||
// The section index can be -1 if the exception was raised in a generated function, e.g. factstub for templates
|
||||
// The section index can be -1 if the exception was raised in a generated function, e.g. $fact for templates
|
||||
if( m_exceptionSectionIdx >= 0 )
|
||||
*sectionName = m_engine->scriptSectionNames[m_exceptionSectionIdx]->AddressOf();
|
||||
else
|
||||
|
@ -227,7 +227,7 @@ asCString asCDataType::Format(asSNameSpace *currNs, bool includeNamespace) const
|
||||
str += "const";
|
||||
}
|
||||
|
||||
if( isReference )
|
||||
if( isReference )
|
||||
str += "&";
|
||||
|
||||
return str;
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
AngelCode Scripting Library
|
||||
Copyright (c) 2003-2014 Andreas Jonsson
|
||||
Copyright (c) 2003-2015 Andreas Jonsson
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any
|
||||
@ -74,11 +74,19 @@ typedef double float64_t;
|
||||
#include <direct.h>
|
||||
#endif
|
||||
|
||||
#endif // AS_PSVITA
|
||||
#endif // _WIN32_WCE
|
||||
#endif // AS_WII
|
||||
|
||||
#endif // !defined(AS_DEBUG)
|
||||
|
||||
|
||||
|
||||
#if defined(_MSC_VER) && defined(AS_PROFILE)
|
||||
// Currently only do profiling with MSVC++
|
||||
|
||||
#include <mmsystem.h>
|
||||
#include <direct.h>
|
||||
#include "as_string.h"
|
||||
#include "as_map.h"
|
||||
#include "as_string_util.h"
|
||||
@ -144,7 +152,7 @@ public:
|
||||
return time;
|
||||
}
|
||||
|
||||
void End(const char *name, double beginTime)
|
||||
void End(const char * /*name*/, double beginTime)
|
||||
{
|
||||
double time = GetTime();
|
||||
|
||||
@ -247,7 +255,7 @@ protected:
|
||||
|
||||
END_AS_NAMESPACE
|
||||
|
||||
#else // _MSC_VER && AS_PROFILE
|
||||
#else // !(_MSC_VER && AS_PROFILE)
|
||||
|
||||
// Define it so nothing is done
|
||||
#define TimeIt(x)
|
||||
@ -257,20 +265,6 @@ END_AS_NAMESPACE
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // AS_PSVITA
|
||||
#endif // _WIN32_WCE
|
||||
#endif // AS_WII
|
||||
|
||||
#else // !defined(AS_DEBUG)
|
||||
|
||||
// Define it so nothing is done
|
||||
#define TimeIt(x)
|
||||
|
||||
#endif // !defined(AS_DEBUG)
|
||||
|
||||
#endif
|
||||
#endif // defined(AS_DEBUG_H)
|
||||
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
AngelCode Scripting Library
|
||||
Copyright (c) 2003-2014 Andreas Jonsson
|
||||
Copyright (c) 2003-2015 Andreas Jonsson
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any
|
||||
@ -486,23 +486,18 @@ int asCGarbageCollector::ReportAndReleaseUndestroyedObjects()
|
||||
engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, msg.AddressOf());
|
||||
|
||||
// Add additional info for builtin types
|
||||
if( gcObj.type->name == "_builtin_function_" )
|
||||
if( gcObj.type->name == "$func" )
|
||||
{
|
||||
// Unfortunately we can't show the function declaration here, because the engine may have released the parameter list already so the declaration would only be misleading
|
||||
// We need to show the function type too as for example delegates do not have a name
|
||||
msg.Format(TXT_PREV_FUNC_IS_NAMED_s_TYPE_IS_d, reinterpret_cast<asCScriptFunction*>(gcObj.obj)->GetName(), reinterpret_cast<asCScriptFunction*>(gcObj.obj)->GetFuncType());
|
||||
engine->WriteMessage("", 0, 0, asMSGTYPE_INFORMATION, msg.AddressOf());
|
||||
}
|
||||
else if( gcObj.type->name == "_builtin_objecttype_" )
|
||||
else if( gcObj.type->name == "$obj" )
|
||||
{
|
||||
msg.Format(TXT_PREV_TYPE_IS_NAMED_s, reinterpret_cast<asCObjectType*>(gcObj.obj)->GetName());
|
||||
engine->WriteMessage("", 0, 0, asMSGTYPE_INFORMATION, msg.AddressOf());
|
||||
}
|
||||
else if( gcObj.type->name == "_builtin_globalprop_" )
|
||||
{
|
||||
msg.Format(TXT_PREV_TYPE_IS_NAMED_s, reinterpret_cast<asCGlobalProperty*>(gcObj.obj)->name.AddressOf());
|
||||
engine->WriteMessage("", 0, 0, asMSGTYPE_INFORMATION, msg.AddressOf());
|
||||
}
|
||||
|
||||
// Release the reference that the GC holds if the release functions is still available
|
||||
if( gcObj.type->beh.release && engine->scriptFunctions[gcObj.type->beh.release] )
|
||||
|
@ -46,32 +46,6 @@
|
||||
|
||||
BEGIN_AS_NAMESPACE
|
||||
|
||||
// TODO: 2.30.0: redesign: Improved method for discarding modules (faster clean-up, less abuse of garbage collector)
|
||||
//
|
||||
// I need to separate the reference counter for internal references and outside references:
|
||||
//
|
||||
// - Internal references are for example, when the module refers to a function or object since it is declared in the module, or when
|
||||
// a function refers to another function since it is being called in the code.
|
||||
// - Outside references are for example object instances holding a reference to the object type, or a context currently
|
||||
// executing a function.
|
||||
//
|
||||
// If no object instances are alive or no contexts are alive it is known that functions from a discarded module
|
||||
// can be called, so they can be destroyed without any need to execute the complex garbage collection routines.
|
||||
//
|
||||
// If there are live objects, the entire module should be kept for safe keeping, though no longer visible.
|
||||
//
|
||||
// TODO: It may not be necessary to keep track of internal references. Without keeping track of internal references, can I still
|
||||
// handle RemoveFunction and RemoveGlobalVariable correctly?
|
||||
//
|
||||
// TODO: How to avoid global variables keeping code alive? For example a script object, or a funcdef?
|
||||
// Can I do a quick check of the object types and functions to count number of outside references, and then do another
|
||||
// check over the global variables to subtract the outside references coming from these? What if the outside reference
|
||||
// is added by an application type in a global variable that the engine doesn't know about? Example, a global dictionary
|
||||
// holding object instances. Should discarding a module immediately destroy the content of the global variables? What if
|
||||
// a live object tries to access the global variable after it has been discarded? Throwing a script exception is acceptable?
|
||||
// Perhaps I need to allow the user to provide a clean-up routine that will be executed before destroying the objects.
|
||||
// Or I might just put that responsibility on the application.
|
||||
|
||||
|
||||
// internal
|
||||
asCModule::asCModule(const char *name, asCScriptEngine *engine)
|
||||
@ -315,7 +289,7 @@ int asCModule::Build()
|
||||
|
||||
// Don't allow the module to be rebuilt if there are still
|
||||
// external references that will need the previous code
|
||||
// TODO: 2.30.0: interface: The asIScriptModule must have a method for querying if the module is used
|
||||
// TODO: interface: The asIScriptModule must have a method for querying if the module is used
|
||||
if( HasExternalReferences(false) )
|
||||
{
|
||||
engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_MODULE_IS_IN_USE);
|
||||
@ -944,9 +918,6 @@ int asCModule::GetGlobalVarIndexByName(const char *name) const
|
||||
// interface
|
||||
int asCModule::RemoveGlobalVar(asUINT index)
|
||||
{
|
||||
// TODO: 2.30.0: redesign: Before removing the variable, clear it to free the object
|
||||
// The property shouldn't be orphaned.
|
||||
|
||||
asCGlobalProperty *prop = scriptGlobals.Get(index);
|
||||
if( !prop )
|
||||
return asINVALID_ARG;
|
||||
@ -1273,6 +1244,33 @@ int asCModule::AddScriptFunction(asCScriptFunction *func)
|
||||
func->AddRefInternal();
|
||||
engine->AddScriptFunction(func);
|
||||
|
||||
// If the function that is being added is an already compiled shared function
|
||||
// then it is necessary to look for anonymous functions that may be declared
|
||||
// within it and add those as well
|
||||
if( func->isShared && func->funcType == asFUNC_SCRIPT )
|
||||
{
|
||||
// Loop through the byte code and check all the
|
||||
// asBC_FuncPtr instructions for anonymous functions
|
||||
asDWORD *bc = func->scriptData->byteCode.AddressOf();
|
||||
asUINT bcLength = (asUINT)func->scriptData->byteCode.GetLength();
|
||||
for( asUINT n = 0; n < bcLength; )
|
||||
{
|
||||
int c = *(asBYTE*)&bc[n];
|
||||
if( c == asBC_FuncPtr )
|
||||
{
|
||||
asCScriptFunction *f = reinterpret_cast<asCScriptFunction*>(asBC_PTRARG(&bc[n]));
|
||||
// Anonymous functions start with $
|
||||
// There are never two equal anonymous functions so it is not necessary to look for duplicates
|
||||
if( f && f->name[0] == '$' )
|
||||
{
|
||||
AddScriptFunction(f);
|
||||
globalFunctions.Put(f);
|
||||
}
|
||||
}
|
||||
n += asBCTypeSize[asBCInfo[c].type];
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1700,16 +1698,6 @@ int asCModule::CompileFunction(const char *sectionName, const char *code, int li
|
||||
// interface
|
||||
int asCModule::RemoveFunction(asIScriptFunction *func)
|
||||
{
|
||||
// TODO: 2.30.0: redesign: Check if there are any references before removing the function
|
||||
// if there are, just hide it from the visible but do not destroy or
|
||||
// remove it from the module.
|
||||
//
|
||||
// Only if the function has no live references, nor internal references
|
||||
// can it be immediately removed, and its internal references released.
|
||||
//
|
||||
// Check if any previously hidden functions are without references,
|
||||
// if so they should removed too.
|
||||
|
||||
// Find the global function
|
||||
asCScriptFunction *f = static_cast<asCScriptFunction*>(func);
|
||||
int idx = globalFunctions.GetIndex(f);
|
||||
@ -1734,6 +1722,7 @@ int asCModule::AddFuncDef(const asCString &name, asSNameSpace *ns)
|
||||
|
||||
func->name = name;
|
||||
func->nameSpace = ns;
|
||||
func->module = this;
|
||||
|
||||
funcDefs.PushLast(func);
|
||||
|
||||
|
@ -53,6 +53,7 @@ asCObjectType::asCObjectType()
|
||||
module = 0;
|
||||
derivedFrom = 0;
|
||||
size = 0;
|
||||
typeId = -1; // start as -1 to signal that it hasn't been defined
|
||||
|
||||
acceptValueSubType = true;
|
||||
acceptRefSubType = true;
|
||||
@ -74,6 +75,7 @@ asCObjectType::asCObjectType(asCScriptEngine *engine)
|
||||
this->engine = engine;
|
||||
module = 0;
|
||||
derivedFrom = 0;
|
||||
typeId = -1; // start as -1 to signal that it hasn't been defined
|
||||
|
||||
acceptValueSubType = true;
|
||||
acceptRefSubType = true;
|
||||
@ -241,7 +243,8 @@ void asCObjectType::DestroyInternal()
|
||||
userData.SetLength(0);
|
||||
|
||||
// Remove the type from the engine
|
||||
engine->RemoveFromTypeIdMap(this);
|
||||
if( typeId != -1 )
|
||||
engine->RemoveFromTypeIdMap(this);
|
||||
|
||||
// Clear the engine pointer to mark the object type as invalid
|
||||
engine = 0;
|
||||
@ -252,7 +255,6 @@ asCObjectType::~asCObjectType()
|
||||
if( engine == 0 )
|
||||
return;
|
||||
|
||||
// TODO: 2.30.0: redesign: Shouldn't this have been done already?
|
||||
DestroyInternal();
|
||||
}
|
||||
|
||||
@ -322,12 +324,18 @@ asUINT asCObjectType::GetSize() const
|
||||
// interface
|
||||
int asCObjectType::GetTypeId() const
|
||||
{
|
||||
// We need a non const pointer to create the asCDataType object.
|
||||
// We're not breaking anything here because this function is not
|
||||
// modifying the object, so this const cast is safe.
|
||||
asCObjectType *ot = const_cast<asCObjectType*>(this);
|
||||
if( typeId == -1 )
|
||||
{
|
||||
// We need a non const pointer to create the asCDataType object.
|
||||
// We're not breaking anything here because this function is not
|
||||
// modifying the object, so this const cast is safe.
|
||||
asCObjectType *ot = const_cast<asCObjectType*>(this);
|
||||
|
||||
return engine->GetTypeIdFromDataType(asCDataType::CreateObject(ot, false));
|
||||
// The engine will define the typeId for this object type
|
||||
engine->GetTypeIdFromDataType(asCDataType::CreateObject(ot, false));
|
||||
}
|
||||
|
||||
return typeId;
|
||||
}
|
||||
|
||||
// interface
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
AngelCode Scripting Library
|
||||
Copyright (c) 2003-2014 Andreas Jonsson
|
||||
Copyright (c) 2003-2015 Andreas Jonsson
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any
|
||||
@ -191,6 +191,7 @@ public:
|
||||
#ifdef WIP_16BYTE_ALIGN
|
||||
int alignment;
|
||||
#endif
|
||||
mutable int typeId;
|
||||
asCArray<asCObjectProperty*> properties;
|
||||
asCArray<int> methods;
|
||||
asCArray<asCObjectType*> interfaces;
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
AngelCode Scripting Library
|
||||
Copyright (c) 2003-2014 Andreas Jonsson
|
||||
Copyright (c) 2003-2015 Andreas Jonsson
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any
|
||||
@ -261,6 +261,13 @@ int asCParser::ParsePropertyDeclaration(asCScriptCode *script)
|
||||
scriptNode->AddChildLast(ParseType(true));
|
||||
if( isSyntaxError ) return -1;
|
||||
|
||||
// Allow optional '&' to indicate that the property is indirect, i.e. stored as reference
|
||||
sToken t;
|
||||
GetToken(&t);
|
||||
RewindTo(&t);
|
||||
if( t.type == ttAmp )
|
||||
scriptNode->AddChildLast(ParseToken(ttAmp));
|
||||
|
||||
// Allow optional namespace to be defined before the identifier in case
|
||||
// the declaration is to be used for searching for an existing property
|
||||
ParseOptionalScope(scriptNode);
|
||||
@ -269,7 +276,6 @@ int asCParser::ParsePropertyDeclaration(asCScriptCode *script)
|
||||
if( isSyntaxError ) return -1;
|
||||
|
||||
// The declaration should end after the identifier
|
||||
sToken t;
|
||||
GetToken(&t);
|
||||
if( t.type != ttEnd )
|
||||
{
|
||||
@ -402,9 +408,11 @@ asCScriptNode *asCParser::ParseType(bool allowConst, bool allowVariableType, boo
|
||||
if( isSyntaxError ) return node;
|
||||
|
||||
// If the datatype is a template type, then parse the subtype within the < >
|
||||
GetToken(&t);
|
||||
RewindTo(&t);
|
||||
asCScriptNode *type = node->lastChild;
|
||||
tempString.Assign(&script->code[type->tokenPos], type->tokenLength);
|
||||
if( engine->IsTemplateType(tempString.AddressOf()) )
|
||||
if( engine->IsTemplateType(tempString.AddressOf()) && t.type == ttLessThan )
|
||||
{
|
||||
GetToken(&t);
|
||||
if( t.type != ttLessThan )
|
||||
@ -602,7 +610,7 @@ asCScriptNode *asCParser::ParseIdentifier()
|
||||
return node;
|
||||
}
|
||||
|
||||
// BNF: PARAMLIST ::= '(' ('void' | (TYPE TYPEMOD [IDENTIFIER] ['=' EXPR] {',' TYPE TYPEMOD [IDENTIFIER] ['=' EXPR]}) ')'
|
||||
// BNF: PARAMLIST ::= '(' ['void' | (TYPE TYPEMOD [IDENTIFIER] ['=' EXPR] {',' TYPE TYPEMOD [IDENTIFIER] ['=' EXPR]})] ')'
|
||||
asCScriptNode *asCParser::ParseParameterList()
|
||||
{
|
||||
asCScriptNode *node = CreateNode(snParameterList);
|
||||
@ -1104,10 +1112,13 @@ bool asCParser::CheckTemplateType(sToken &t)
|
||||
tempString.Assign(&script->code[t.pos], t.length);
|
||||
if( engine->IsTemplateType(tempString.AddressOf()) )
|
||||
{
|
||||
// Expect the sub type within < >
|
||||
// If the next token is a < then parse the sub-type too
|
||||
GetToken(&t);
|
||||
if( t.type != ttLessThan )
|
||||
return false;
|
||||
{
|
||||
RewindTo(&t);
|
||||
return true;
|
||||
}
|
||||
|
||||
for(;;)
|
||||
{
|
||||
@ -1232,7 +1243,7 @@ asCScriptNode *asCParser::ParseCast()
|
||||
return node;
|
||||
}
|
||||
|
||||
// BNF: EXPRVALUE ::= 'void' | CONSTRUCTCALL | FUNCCALL | VARACCESS | CAST | LITERAL | '(' ASSIGN ')'
|
||||
// BNF: EXPRVALUE ::= 'void' | CONSTRUCTCALL | FUNCCALL | VARACCESS | CAST | LITERAL | '(' ASSIGN ')' | LAMBDA
|
||||
asCScriptNode *asCParser::ParseExprValue()
|
||||
{
|
||||
asCScriptNode *node = CreateNode(snExprValue);
|
||||
@ -1250,44 +1261,54 @@ asCScriptNode *asCParser::ParseExprValue()
|
||||
node->AddChildLast(ParseConstructCall());
|
||||
else if( t1.type == ttIdentifier || t1.type == ttScope )
|
||||
{
|
||||
// Determine the last identifier in order to check if it is a type
|
||||
sToken t;
|
||||
if( t1.type == ttScope ) t = t2; else t = t1;
|
||||
RewindTo(&t);
|
||||
GetToken(&t2);
|
||||
while( t.type == ttIdentifier )
|
||||
// Check if the expression is an anonymous function
|
||||
if( IsLambda() )
|
||||
{
|
||||
t2 = t;
|
||||
GetToken(&t);
|
||||
if( t.type == ttScope )
|
||||
GetToken(&t);
|
||||
else
|
||||
break;
|
||||
node->AddChildLast(ParseLambda());
|
||||
}
|
||||
|
||||
bool isDataType = IsDataType(t2);
|
||||
bool isTemplateType = false;
|
||||
if( isDataType )
|
||||
{
|
||||
// Is this a template type?
|
||||
tempString.Assign(&script->code[t2.pos], t2.length);
|
||||
if( engine->IsTemplateType(tempString.AddressOf()) )
|
||||
isTemplateType = true;
|
||||
}
|
||||
|
||||
// Rewind so the real parsing can be done, after deciding what to parse
|
||||
RewindTo(&t1);
|
||||
|
||||
// Check if this is a construct call
|
||||
if( isDataType && (t.type == ttOpenParanthesis || // type()
|
||||
t.type == ttOpenBracket) ) // type[]()
|
||||
node->AddChildLast(ParseConstructCall());
|
||||
else if( isTemplateType && t.type == ttLessThan ) // type<t>()
|
||||
node->AddChildLast(ParseConstructCall());
|
||||
else if( IsFunctionCall() )
|
||||
node->AddChildLast(ParseFunctionCall());
|
||||
else
|
||||
node->AddChildLast(ParseVariableAccess());
|
||||
{
|
||||
// Determine the last identifier in order to check if it is a type
|
||||
sToken t;
|
||||
if( t1.type == ttScope ) t = t2; else t = t1;
|
||||
RewindTo(&t);
|
||||
GetToken(&t2);
|
||||
while( t.type == ttIdentifier )
|
||||
{
|
||||
t2 = t;
|
||||
GetToken(&t);
|
||||
if( t.type == ttScope )
|
||||
GetToken(&t);
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
bool isDataType = IsDataType(t2);
|
||||
bool isTemplateType = false;
|
||||
if( isDataType )
|
||||
{
|
||||
// Is this a template type?
|
||||
tempString.Assign(&script->code[t2.pos], t2.length);
|
||||
if( engine->IsTemplateType(tempString.AddressOf()) )
|
||||
isTemplateType = true;
|
||||
}
|
||||
|
||||
GetToken(&t2);
|
||||
|
||||
// Rewind so the real parsing can be done, after deciding what to parse
|
||||
RewindTo(&t1);
|
||||
|
||||
// Check if this is a construct call
|
||||
if( isDataType && (t.type == ttOpenParanthesis || // type()
|
||||
(t.type == ttOpenBracket && t2.type == ttCloseBracket)) ) // type[]()
|
||||
node->AddChildLast(ParseConstructCall());
|
||||
else if( isTemplateType && t.type == ttLessThan ) // type<t>()
|
||||
node->AddChildLast(ParseConstructCall());
|
||||
else if( IsFunctionCall() )
|
||||
node->AddChildLast(ParseFunctionCall());
|
||||
else
|
||||
node->AddChildLast(ParseVariableAccess());
|
||||
}
|
||||
}
|
||||
else if( t1.type == ttCast )
|
||||
node->AddChildLast(ParseCast());
|
||||
@ -1355,6 +1376,83 @@ asCScriptNode *asCParser::ParseConstant()
|
||||
return node;
|
||||
}
|
||||
|
||||
bool asCParser::IsLambda()
|
||||
{
|
||||
bool isLambda = false;
|
||||
sToken t;
|
||||
GetToken(&t);
|
||||
if( t.type == ttIdentifier && IdentifierIs(t, FUNCTION_TOKEN) )
|
||||
{
|
||||
sToken t2;
|
||||
GetToken(&t2);
|
||||
if( t2.type == ttOpenParanthesis )
|
||||
{
|
||||
// Skip until )
|
||||
while( t2.type != ttCloseParanthesis && t2.type != ttEnd )
|
||||
GetToken(&t2);
|
||||
|
||||
// The next token must be a {
|
||||
GetToken(&t2);
|
||||
if( t2.type == ttStartStatementBlock )
|
||||
isLambda = true;
|
||||
}
|
||||
}
|
||||
|
||||
RewindTo(&t);
|
||||
return isLambda;
|
||||
}
|
||||
|
||||
// BNF: LAMBDA ::= 'function' '(' [IDENTIFIER {',' IDENTIFIER}] ')' STATBLOCK
|
||||
asCScriptNode *asCParser::ParseLambda()
|
||||
{
|
||||
asCScriptNode *node = CreateNode(snFunction);
|
||||
if( node == 0 ) return 0;
|
||||
|
||||
sToken t;
|
||||
GetToken(&t);
|
||||
|
||||
if( t.type != ttIdentifier || !IdentifierIs(t, FUNCTION_TOKEN) )
|
||||
{
|
||||
Error(ExpectedToken("function"), &t);
|
||||
return node;
|
||||
}
|
||||
|
||||
GetToken(&t);
|
||||
if( t.type != ttOpenParanthesis )
|
||||
{
|
||||
Error(ExpectedToken("("), &t);
|
||||
return node;
|
||||
}
|
||||
|
||||
GetToken(&t);
|
||||
if( t.type == ttIdentifier )
|
||||
{
|
||||
RewindTo(&t);
|
||||
node->AddChildLast(ParseIdentifier());
|
||||
|
||||
GetToken(&t);
|
||||
while( t.type == ttListSeparator )
|
||||
{
|
||||
node->AddChildLast(ParseIdentifier());
|
||||
if( isSyntaxError ) return node;
|
||||
|
||||
GetToken(&t);
|
||||
}
|
||||
}
|
||||
|
||||
if( t.type != ttCloseParanthesis )
|
||||
{
|
||||
Error(ExpectedToken(")"), &t);
|
||||
return node;
|
||||
}
|
||||
|
||||
// We should just find the end of the statement block here. The statements
|
||||
// will be parsed on request by the compiler once it starts the compilation.
|
||||
node->AddChildLast(SuperficiallyParseStatementBlock());
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
asCScriptNode *asCParser::ParseStringConstant()
|
||||
{
|
||||
asCScriptNode *node = CreateNode(snConstant);
|
||||
@ -1618,7 +1716,7 @@ asCScriptNode *asCParser::ParseCondition()
|
||||
return node;
|
||||
}
|
||||
|
||||
// BNF: EXPR ::= (TYPE '=' INILIST) | (EXPRTERM {EXPROP EXPRTERM})
|
||||
// BNF: EXPR ::= (TYPE '=' INITLIST) | (EXPRTERM {EXPROP EXPRTERM})
|
||||
asCScriptNode *asCParser::ParseExpression()
|
||||
{
|
||||
asCScriptNode *node = CreateNode(snExpression);
|
||||
@ -2459,7 +2557,22 @@ bool asCParser::IsVirtualPropertyDecl()
|
||||
// as it may wrongly identify the statement as a non-declaration if the user typed
|
||||
// the name incorrectly. The real type is validated in ParseDeclaration where a
|
||||
// proper error message can be given.
|
||||
if( !IsRealType(t1.type) && t1.type != ttIdentifier )
|
||||
if( t1.type == ttScope )
|
||||
GetToken(&t1);
|
||||
|
||||
if( t1.type == ttIdentifier )
|
||||
{
|
||||
sToken t2;
|
||||
GetToken(&t2);
|
||||
while( t1.type == ttIdentifier && t2.type == ttScope )
|
||||
{
|
||||
GetToken(&t1);
|
||||
GetToken(&t2);
|
||||
}
|
||||
|
||||
RewindTo(&t2);
|
||||
}
|
||||
else if( !IsRealType(t1.type) )
|
||||
{
|
||||
RewindTo(&t);
|
||||
return false;
|
||||
@ -3201,61 +3314,37 @@ asCScriptNode *asCParser::SuperficiallyParseVarInit()
|
||||
if( t.type == ttAssignment )
|
||||
{
|
||||
GetToken(&t);
|
||||
if( t.type == ttStartStatementBlock )
|
||||
sToken start = t;
|
||||
|
||||
// Find the end of the expression
|
||||
int indentParan = 0;
|
||||
int indentBrace = 0;
|
||||
while( indentParan || indentBrace || (t.type != ttListSeparator && t.type != ttEndStatement && t.type != ttEndStatementBlock) )
|
||||
{
|
||||
sToken start = t;
|
||||
|
||||
// Find the end of the initialization list
|
||||
int indent = 1;
|
||||
while( indent )
|
||||
if( t.type == ttOpenParanthesis )
|
||||
indentParan++;
|
||||
else if( t.type == ttCloseParanthesis )
|
||||
indentParan--;
|
||||
else if( t.type == ttStartStatementBlock )
|
||||
indentBrace++;
|
||||
else if( t.type == ttEndStatementBlock )
|
||||
indentBrace--;
|
||||
else if( t.type == ttNonTerminatedStringConstant )
|
||||
{
|
||||
GetToken(&t);
|
||||
if( t.type == ttStartStatementBlock )
|
||||
indent++;
|
||||
else if( t.type == ttEndStatementBlock )
|
||||
indent--;
|
||||
else if( t.type == ttNonTerminatedStringConstant )
|
||||
{
|
||||
Error(TXT_NONTERMINATED_STRING, &t);
|
||||
break;
|
||||
}
|
||||
else if( t.type == ttEnd )
|
||||
{
|
||||
Error(TXT_UNEXPECTED_END_OF_FILE, &t);
|
||||
Info(TXT_WHILE_PARSING_INIT_LIST, &start);
|
||||
break;
|
||||
}
|
||||
Error(TXT_NONTERMINATED_STRING, &t);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sToken start = t;
|
||||
|
||||
// Find the end of the expression
|
||||
int indent = 0;
|
||||
while( indent || (t.type != ttListSeparator && t.type != ttEndStatement && t.type != ttEndStatementBlock) )
|
||||
else if( t.type == ttEnd )
|
||||
{
|
||||
if( t.type == ttOpenParanthesis )
|
||||
indent++;
|
||||
else if( t.type == ttCloseParanthesis )
|
||||
indent--;
|
||||
else if( t.type == ttNonTerminatedStringConstant )
|
||||
{
|
||||
Error(TXT_NONTERMINATED_STRING, &t);
|
||||
break;
|
||||
}
|
||||
else if( t.type == ttEnd )
|
||||
{
|
||||
Error(TXT_UNEXPECTED_END_OF_FILE, &t);
|
||||
Info(TXT_WHILE_PARSING_EXPRESSION, &start);
|
||||
break;
|
||||
}
|
||||
GetToken(&t);
|
||||
Error(TXT_UNEXPECTED_END_OF_FILE, &t);
|
||||
Info(TXT_WHILE_PARSING_EXPRESSION, &start);
|
||||
break;
|
||||
}
|
||||
|
||||
// Rewind so that the next token read is the list separator, end statement, or end statement block
|
||||
RewindTo(&t);
|
||||
GetToken(&t);
|
||||
}
|
||||
|
||||
// Rewind so that the next token read is the list separator, end statement, or end statement block
|
||||
RewindTo(&t);
|
||||
}
|
||||
else if( t.type == ttOpenParanthesis )
|
||||
{
|
||||
@ -3872,7 +3961,7 @@ asCScriptNode *asCParser::ParseIf()
|
||||
return node;
|
||||
}
|
||||
|
||||
// BNF: FOR ::= 'for' '(' (VAR | EXPRSTAT) EXPRSTAT [ASSIGN] ')' STATEMENT
|
||||
// BNF: FOR ::= 'for' '(' (VAR | EXPRSTAT) EXPRSTAT [ASSIGN {',' ASSIGN}] ')' STATEMENT
|
||||
asCScriptNode *asCParser::ParseFor()
|
||||
{
|
||||
asCScriptNode *node = CreateNode(snFor);
|
||||
@ -3911,18 +4000,27 @@ asCScriptNode *asCParser::ParseFor()
|
||||
{
|
||||
RewindTo(&t);
|
||||
|
||||
asCScriptNode *n = CreateNode(snExpressionStatement);
|
||||
if( n == 0 ) return 0;
|
||||
node->AddChildLast(n);
|
||||
n->AddChildLast(ParseAssignment());
|
||||
if( isSyntaxError ) return node;
|
||||
|
||||
GetToken(&t);
|
||||
if( t.type != ttCloseParanthesis )
|
||||
// Parse N increment statements separated by ,
|
||||
for(;;)
|
||||
{
|
||||
Error(ExpectedToken(")"), &t);
|
||||
Error(InsteadFound(t), &t);
|
||||
return node;
|
||||
asCScriptNode *n = CreateNode(snExpressionStatement);
|
||||
if( n == 0 ) return 0;
|
||||
node->AddChildLast(n);
|
||||
n->AddChildLast(ParseAssignment());
|
||||
if( isSyntaxError ) return node;
|
||||
|
||||
GetToken(&t);
|
||||
if( t.type == ttListSeparator )
|
||||
continue;
|
||||
else if( t.type == ttCloseParanthesis )
|
||||
break;
|
||||
else
|
||||
{
|
||||
const char *tokens[] = {",", ")"};
|
||||
Error(ExpectedOneOf(tokens, 2), &t);
|
||||
Error(InsteadFound(t), &t);
|
||||
return node;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
AngelCode Scripting Library
|
||||
Copyright (c) 2003-2014 Andreas Jonsson
|
||||
Copyright (c) 2003-2015 Andreas Jonsson
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any
|
||||
@ -133,6 +133,8 @@ protected:
|
||||
bool IsVarDecl();
|
||||
bool IsVirtualPropertyDecl();
|
||||
bool IsFuncDecl(bool isMethod);
|
||||
bool IsLambda();
|
||||
bool IsFunctionCall();
|
||||
|
||||
// Expressions
|
||||
asCScriptNode *ParseAssignment();
|
||||
@ -151,13 +153,13 @@ protected:
|
||||
asCScriptNode *ParseCast();
|
||||
asCScriptNode *ParseConstant();
|
||||
asCScriptNode *ParseStringConstant();
|
||||
asCScriptNode *ParseLambda();
|
||||
|
||||
bool IsConstant(int tokenType);
|
||||
bool IsOperator(int tokenType);
|
||||
bool IsPreOperator(int tokenType);
|
||||
bool IsPostOperator(int tokenType);
|
||||
bool IsAssignOperator(int tokenType);
|
||||
bool IsFunctionCall();
|
||||
|
||||
bool CheckTemplateType(sToken &t);
|
||||
#endif
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include "as_bytecode.h"
|
||||
#include "as_scriptobject.h"
|
||||
#include "as_texts.h"
|
||||
#include "as_debug.h"
|
||||
|
||||
BEGIN_AS_NAMESPACE
|
||||
|
||||
@ -65,6 +66,8 @@ void asCReader::ReadData(void *data, asUINT size)
|
||||
|
||||
int asCReader::Read(bool *wasDebugInfoStripped)
|
||||
{
|
||||
TimeIt("asCReader::Read");
|
||||
|
||||
// Before starting the load, make sure that
|
||||
// any existing resources have been freed
|
||||
module->InternalReset();
|
||||
@ -124,6 +127,8 @@ int asCReader::Error(const char *msg)
|
||||
|
||||
int asCReader::ReadInner()
|
||||
{
|
||||
TimeIt("asCReader::ReadInner");
|
||||
|
||||
// This function will load each entity one by one from the stream.
|
||||
// If any error occurs, it will return to the caller who is
|
||||
// responsible for cleaning up the partially loaded entities.
|
||||
@ -258,31 +263,38 @@ int asCReader::ReadInner()
|
||||
asCScriptFunction *func = ReadFunction(isNew, false, true);
|
||||
if( func )
|
||||
{
|
||||
func->module = module;
|
||||
module->funcDefs.PushLast(func);
|
||||
engine->funcDefs.PushLast(func);
|
||||
|
||||
// TODO: clean up: This is also done by the builder. It should probably be moved to a method in the module
|
||||
// Check if there is another identical funcdef from another module and if so reuse that instead
|
||||
for( asUINT n = 0; n < engine->funcDefs.GetLength(); n++ )
|
||||
if( func->isShared )
|
||||
{
|
||||
asCScriptFunction *f2 = engine->funcDefs[n];
|
||||
if( f2 == 0 || func == f2 )
|
||||
continue;
|
||||
|
||||
if( f2->name == func->name &&
|
||||
f2->nameSpace == func->nameSpace &&
|
||||
f2->IsSignatureExceptNameEqual(func) )
|
||||
for( asUINT n = 0; n < engine->funcDefs.GetLength(); n++ )
|
||||
{
|
||||
// Replace our funcdef for the existing one
|
||||
module->funcDefs[module->funcDefs.IndexOf(func)] = f2;
|
||||
f2->AddRefInternal();
|
||||
asCScriptFunction *f2 = engine->funcDefs[n];
|
||||
if( f2 == 0 || func == f2 )
|
||||
continue;
|
||||
|
||||
engine->funcDefs.RemoveValue(func);
|
||||
if( !f2->isShared )
|
||||
continue;
|
||||
|
||||
savedFunctions[savedFunctions.IndexOf(func)] = f2;
|
||||
if( f2->name == func->name &&
|
||||
f2->nameSpace == func->nameSpace &&
|
||||
f2->IsSignatureExceptNameEqual(func) )
|
||||
{
|
||||
// Replace our funcdef for the existing one
|
||||
module->funcDefs[module->funcDefs.IndexOf(func)] = f2;
|
||||
f2->AddRefInternal();
|
||||
|
||||
func->ReleaseInternal();
|
||||
break;
|
||||
engine->funcDefs.RemoveValue(func);
|
||||
|
||||
savedFunctions[savedFunctions.IndexOf(func)] = f2;
|
||||
|
||||
func->ReleaseInternal();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -549,6 +561,8 @@ int asCReader::ReadInner()
|
||||
|
||||
void asCReader::ReadUsedStringConstants()
|
||||
{
|
||||
TimeIt("asCReader::ReadUsedStringConstants");
|
||||
|
||||
asCString str;
|
||||
|
||||
asUINT count;
|
||||
@ -563,6 +577,8 @@ void asCReader::ReadUsedStringConstants()
|
||||
|
||||
void asCReader::ReadUsedFunctions()
|
||||
{
|
||||
TimeIt("asCReader::ReadUsedFunctions");
|
||||
|
||||
asUINT count;
|
||||
count = ReadEncodedUInt();
|
||||
usedFunctions.SetLength(count);
|
||||
@ -606,25 +622,44 @@ void asCReader::ReadUsedFunctions()
|
||||
for( asUINT i = 0; i < module->bindInformations.GetLength(); i++ )
|
||||
{
|
||||
asCScriptFunction *f = module->bindInformations[i]->importedFunctionSignature;
|
||||
if( !func.IsSignatureEqual(f) ||
|
||||
func.objectType != f->objectType ||
|
||||
if( func.objectType != f->objectType ||
|
||||
func.funcType != f->funcType ||
|
||||
func.nameSpace != f->nameSpace )
|
||||
func.nameSpace != f->nameSpace ||
|
||||
!func.IsSignatureEqual(f) )
|
||||
continue;
|
||||
|
||||
usedFunctions[n] = f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if( func.funcType == asFUNC_FUNCDEF )
|
||||
{
|
||||
const asCArray<asCScriptFunction *> &funcs = module->funcDefs;
|
||||
for( asUINT i = 0; i < funcs.GetLength(); i++ )
|
||||
{
|
||||
asCScriptFunction *f = funcs[i];
|
||||
if( f == 0 || func.name != f->name || !func.IsSignatureExceptNameAndObjectTypeEqual(f) )
|
||||
continue;
|
||||
|
||||
// Funcdefs are always global so there is no need to compare object type
|
||||
asASSERT( f->objectType == 0 );
|
||||
|
||||
usedFunctions[n] = f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: optimize: Global functions should be searched for in module->globalFunctions
|
||||
// TODO: optimize: funcdefs should be searched for in module->funcDefs
|
||||
// TODO: optimize: object methods should be searched for directly in the object type
|
||||
for( asUINT i = 0; i < module->scriptFunctions.GetLength(); i++ )
|
||||
{
|
||||
asCScriptFunction *f = module->scriptFunctions[i];
|
||||
if( !func.IsSignatureEqual(f) ||
|
||||
func.objectType != f->objectType ||
|
||||
if( func.objectType != f->objectType ||
|
||||
func.funcType != f->funcType ||
|
||||
func.nameSpace != f->nameSpace )
|
||||
func.nameSpace != f->nameSpace ||
|
||||
!func.IsSignatureEqual(f) )
|
||||
continue;
|
||||
|
||||
usedFunctions[n] = f;
|
||||
@ -634,17 +669,157 @@ void asCReader::ReadUsedFunctions()
|
||||
}
|
||||
else
|
||||
{
|
||||
for( asUINT i = 0; i < engine->scriptFunctions.GetLength(); i++ )
|
||||
if( func.funcType == asFUNC_FUNCDEF )
|
||||
{
|
||||
asCScriptFunction *f = engine->scriptFunctions[i];
|
||||
if( f == 0 ||
|
||||
!func.IsSignatureEqual(f) ||
|
||||
func.objectType != f->objectType ||
|
||||
func.nameSpace != f->nameSpace )
|
||||
continue;
|
||||
// This is a funcdef (registered or shared)
|
||||
const asCArray<asCScriptFunction *> &funcs = engine->funcDefs;
|
||||
for( asUINT i = 0; i < funcs.GetLength(); i++ )
|
||||
{
|
||||
asCScriptFunction *f = funcs[i];
|
||||
if( f == 0 || func.name != f->name || !func.IsSignatureExceptNameAndObjectTypeEqual(f) )
|
||||
continue;
|
||||
|
||||
usedFunctions[n] = f;
|
||||
break;
|
||||
// Funcdefs are always global so there is no need to compare object type
|
||||
asASSERT( f->objectType == 0 );
|
||||
|
||||
usedFunctions[n] = f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if( func.name[0] == '$' )
|
||||
{
|
||||
// This is a special function
|
||||
|
||||
// Check for string factory
|
||||
if( func.name == "$str" && engine->stringFactory &&
|
||||
func.IsSignatureExceptNameAndObjectTypeEqual(engine->stringFactory) )
|
||||
usedFunctions[n] = engine->stringFactory;
|
||||
else if( func.name == "$beh0" && func.objectType )
|
||||
{
|
||||
// This is a class constructor, so we can search directly in the object type's constructors
|
||||
for( asUINT i = 0; i < func.objectType->beh.constructors.GetLength(); i++ )
|
||||
{
|
||||
asCScriptFunction *f = engine->scriptFunctions[func.objectType->beh.constructors[i]];
|
||||
if( f == 0 ||
|
||||
!func.IsSignatureExceptNameAndObjectTypeEqual(f) )
|
||||
continue;
|
||||
|
||||
usedFunctions[n] = f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if( func.name == "$fact" || func.name == "$beh3" )
|
||||
{
|
||||
// This is a factory (or stub), so look for the function in the return type's factories
|
||||
asCObjectType *objType = func.returnType.GetObjectType();
|
||||
if( objType )
|
||||
{
|
||||
for( asUINT i = 0; i < objType->beh.factories.GetLength(); i++ )
|
||||
{
|
||||
asCScriptFunction *f = engine->scriptFunctions[objType->beh.factories[i]];
|
||||
if( f == 0 ||
|
||||
!func.IsSignatureExceptNameAndObjectTypeEqual(f) )
|
||||
continue;
|
||||
|
||||
usedFunctions[n] = f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( func.name == "$list" )
|
||||
{
|
||||
// listFactory is used for both factory is global and returns a handle and constructor that is a method
|
||||
asCObjectType *objType = func.objectType ? func.objectType : func.returnType.GetObjectType();
|
||||
if( objType )
|
||||
{
|
||||
asCScriptFunction *f = engine->scriptFunctions[objType->beh.listFactory];
|
||||
if( f && func.IsSignatureExceptNameAndObjectTypeEqual(f) )
|
||||
usedFunctions[n] = f;
|
||||
}
|
||||
}
|
||||
else if( func.name == "$beh2" )
|
||||
{
|
||||
// This is a destructor, so check the object type's destructor
|
||||
asCObjectType *objType = func.objectType;
|
||||
if( objType )
|
||||
{
|
||||
asCScriptFunction *f = engine->scriptFunctions[objType->beh.destruct];
|
||||
if( f && func.IsSignatureExceptNameAndObjectTypeEqual(f) )
|
||||
usedFunctions[n] = f;
|
||||
}
|
||||
}
|
||||
else if( func.name == "$beh4" )
|
||||
{
|
||||
// This is a list factory, so check the return type's list factory
|
||||
asCObjectType *objType = func.returnType.GetObjectType();
|
||||
if( objType )
|
||||
{
|
||||
asCScriptFunction *f = engine->scriptFunctions[objType->beh.listFactory];
|
||||
if( f && func.IsSignatureExceptNameAndObjectTypeEqual(f) )
|
||||
usedFunctions[n] = f;
|
||||
}
|
||||
}
|
||||
else if( func.name == "$dlgte" )
|
||||
{
|
||||
// This is the delegate factory
|
||||
asCScriptFunction *f = engine->registeredGlobalFuncs.GetFirst(engine->nameSpaces[0], DELEGATE_FACTORY);
|
||||
asASSERT( f && func.IsSignatureEqual(f) );
|
||||
usedFunctions[n] = f;
|
||||
}
|
||||
}
|
||||
else if( func.objectType == 0 )
|
||||
{
|
||||
// This is a global function
|
||||
const asCArray<asUINT> &funcs = engine->registeredGlobalFuncs.GetIndexes(func.nameSpace, func.name);
|
||||
for( asUINT i = 0; i < funcs.GetLength(); i++ )
|
||||
{
|
||||
asCScriptFunction *f = engine->registeredGlobalFuncs.Get(funcs[i]);
|
||||
if( f == 0 ||
|
||||
!func.IsSignatureExceptNameAndObjectTypeEqual(f) )
|
||||
continue;
|
||||
|
||||
usedFunctions[n] = f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if( func.objectType )
|
||||
{
|
||||
// It is a class member, so we can search directly in the object type's members
|
||||
// TODO: virtual function is different that implemented method
|
||||
for( asUINT i = 0; i < func.objectType->methods.GetLength(); i++ )
|
||||
{
|
||||
asCScriptFunction *f = engine->scriptFunctions[func.objectType->methods[i]];
|
||||
if( f == 0 ||
|
||||
!func.IsSignatureEqual(f) )
|
||||
continue;
|
||||
|
||||
usedFunctions[n] = f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( usedFunctions[n] == 0 )
|
||||
{
|
||||
// TODO: clean up: This part of the code should never happen. All functions should
|
||||
// be found in the above logic. The only valid reason to come here
|
||||
// is if the bytecode is wrong and the function doesn't exist anyway.
|
||||
// This loop is kept temporarily until we can be certain all scenarios
|
||||
// are covered.
|
||||
for( asUINT i = 0; i < engine->scriptFunctions.GetLength(); i++ )
|
||||
{
|
||||
asCScriptFunction *f = engine->scriptFunctions[i];
|
||||
if( f == 0 ||
|
||||
func.objectType != f->objectType ||
|
||||
func.nameSpace != f->nameSpace ||
|
||||
!func.IsSignatureEqual(f) )
|
||||
continue;
|
||||
|
||||
usedFunctions[n] = f;
|
||||
break;
|
||||
}
|
||||
|
||||
// No function is expected to be found
|
||||
asASSERT(usedFunctions[n] == 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -973,6 +1148,13 @@ asCScriptFunction *asCReader::ReadFunction(bool &isNew, bool addToModule, bool a
|
||||
{
|
||||
func->vfTableIdx = ReadEncodedUInt();
|
||||
}
|
||||
else if( func->funcType == asFUNC_FUNCDEF )
|
||||
{
|
||||
asBYTE bits;
|
||||
ReadData(&bits, 1);
|
||||
if( bits )
|
||||
func->isShared = true;
|
||||
}
|
||||
|
||||
if( addToModule )
|
||||
{
|
||||
@ -1520,28 +1702,25 @@ asQWORD asCReader::ReadEncodedUInt64()
|
||||
|
||||
void asCReader::ReadString(asCString* str)
|
||||
{
|
||||
char b;
|
||||
ReadData(&b, 1);
|
||||
if( b == '\0' )
|
||||
asUINT len = ReadEncodedUInt();
|
||||
if( len & 1 )
|
||||
{
|
||||
str->SetLength(0);
|
||||
asUINT idx = len/2;
|
||||
if( idx < savedStrings.GetLength() )
|
||||
*str = savedStrings[idx];
|
||||
else
|
||||
Error(TXT_INVALID_BYTECODE_d);
|
||||
}
|
||||
else if( b == 'n' )
|
||||
else if( len > 0 )
|
||||
{
|
||||
asUINT len = ReadEncodedUInt();
|
||||
len /= 2;
|
||||
str->SetLength(len);
|
||||
stream->Read(str->AddressOf(), len);
|
||||
|
||||
savedStrings.PushLast(*str);
|
||||
}
|
||||
else
|
||||
{
|
||||
asUINT n = ReadEncodedUInt();
|
||||
if( n < savedStrings.GetLength() )
|
||||
*str = savedStrings[n];
|
||||
else
|
||||
Error(TXT_INVALID_BYTECODE_d);
|
||||
}
|
||||
str->SetLength(0);
|
||||
}
|
||||
|
||||
void asCReader::ReadGlobalProperty()
|
||||
@ -1625,7 +1804,7 @@ void asCReader::ReadDataType(asCDataType *dt)
|
||||
ReadData(&bits, 1);
|
||||
|
||||
asCScriptFunction *funcDef = 0;
|
||||
if( tokenType == ttIdentifier && objType && objType->name == "_builtin_function_" )
|
||||
if( tokenType == ttIdentifier && objType && objType->name == "$func" )
|
||||
{
|
||||
asCScriptFunction func(engine, module, asFUNC_DUMMY);
|
||||
ReadFunctionSignature(&func);
|
||||
@ -1790,7 +1969,7 @@ asCObjectType* asCReader::ReadObjectType()
|
||||
ReadString(&ns);
|
||||
asSNameSpace *nameSpace = engine->AddNameSpace(ns.AddressOf());
|
||||
|
||||
if( typeName.GetLength() && typeName != "_builtin_object_" && typeName != "_builtin_function_" )
|
||||
if( typeName.GetLength() && typeName != "$obj" && typeName != "$func" )
|
||||
{
|
||||
// Find the object type
|
||||
ot = module->GetObjectType(typeName.AddressOf(), nameSpace);
|
||||
@ -1806,11 +1985,11 @@ asCObjectType* asCReader::ReadObjectType()
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if( typeName == "_builtin_object_" )
|
||||
else if( typeName == "$obj" )
|
||||
{
|
||||
ot = &engine->scriptTypeBehaviours;
|
||||
}
|
||||
else if( typeName == "_builtin_function_" )
|
||||
else if( typeName == "$func" )
|
||||
{
|
||||
ot = &engine->functionBehaviours;
|
||||
}
|
||||
@ -2073,6 +2252,8 @@ void asCReader::ReadByteCode(asCScriptFunction *func)
|
||||
|
||||
void asCReader::ReadUsedTypeIds()
|
||||
{
|
||||
TimeIt("asCReader::ReadUsedTypeIds");
|
||||
|
||||
asUINT count = ReadEncodedUInt();
|
||||
usedTypeIds.Allocate(count, false);
|
||||
for( asUINT n = 0; n < count; n++ )
|
||||
@ -2085,6 +2266,8 @@ void asCReader::ReadUsedTypeIds()
|
||||
|
||||
void asCReader::ReadUsedGlobalProps()
|
||||
{
|
||||
TimeIt("asCReader::ReadUsedGlobalProps");
|
||||
|
||||
int c = ReadEncodedUInt();
|
||||
|
||||
usedGlobalProperties.Allocate(c, false);
|
||||
@ -2124,6 +2307,8 @@ void asCReader::ReadUsedGlobalProps()
|
||||
|
||||
void asCReader::ReadUsedObjectProps()
|
||||
{
|
||||
TimeIt("asCReader::ReadUsedObjectProps");
|
||||
|
||||
asUINT c = ReadEncodedUInt();
|
||||
|
||||
usedObjectProperties.SetLength(c);
|
||||
@ -2293,7 +2478,8 @@ void asCReader::TranslateFunction(asCScriptFunction *func)
|
||||
}
|
||||
else if( c == asBC_CALL ||
|
||||
c == asBC_CALLINTF ||
|
||||
c == asBC_CALLSYS )
|
||||
c == asBC_CALLSYS ||
|
||||
c == asBC_Thiscall1 )
|
||||
{
|
||||
// Translate the index to the func id
|
||||
int *fid = (int*)&bc[n+1];
|
||||
@ -2800,7 +2986,8 @@ void asCReader::CalculateStackNeeded(asCScriptFunction *func)
|
||||
{
|
||||
// Determine the true delta from the instruction arguments
|
||||
if( bc == asBC_CALL ||
|
||||
bc == asBC_CALLSYS ||
|
||||
bc == asBC_CALLSYS ||
|
||||
bc == asBC_Thiscall1 ||
|
||||
bc == asBC_CALLBND ||
|
||||
bc == asBC_ALLOC ||
|
||||
bc == asBC_CALLINTF ||
|
||||
@ -3030,6 +3217,7 @@ asCScriptFunction *asCReader::GetCalledFunction(asCScriptFunction *func, asDWORD
|
||||
|
||||
if( bc == asBC_CALL ||
|
||||
bc == asBC_CALLSYS ||
|
||||
bc == asBC_Thiscall1 ||
|
||||
bc == asBC_CALLINTF )
|
||||
{
|
||||
// Find the function from the function id in bytecode
|
||||
@ -3085,11 +3273,13 @@ int asCReader::AdjustGetOffset(int offset, asCScriptFunction *func, asDWORD prog
|
||||
|
||||
// Find out which function that will be called
|
||||
asCScriptFunction *calledFunc = 0;
|
||||
int stackDelta = 0;
|
||||
for( asUINT n = programPos; func->scriptData->byteCode.GetLength(); )
|
||||
{
|
||||
asBYTE bc = *(asBYTE*)&func->scriptData->byteCode[n];
|
||||
if( bc == asBC_CALL ||
|
||||
bc == asBC_CALLSYS ||
|
||||
bc == asBC_Thiscall1 ||
|
||||
bc == asBC_CALLINTF ||
|
||||
bc == asBC_ALLOC ||
|
||||
bc == asBC_CALLBND ||
|
||||
@ -3106,6 +3296,10 @@ int asCReader::AdjustGetOffset(int offset, asCScriptFunction *func, asDWORD prog
|
||||
return offset - (1 - AS_PTR_SIZE);
|
||||
}
|
||||
|
||||
// Keep track of the stack size between the
|
||||
// instruction that needs to be adjusted and the call
|
||||
stackDelta += asBCInfo[bc].stackInc;
|
||||
|
||||
n += asBCTypeSize[asBCInfo[bc].type];
|
||||
}
|
||||
|
||||
@ -3118,16 +3312,30 @@ int asCReader::AdjustGetOffset(int offset, asCScriptFunction *func, asDWORD prog
|
||||
// Count the number of pointers pushed on the stack above the
|
||||
// current offset, and then adjust the offset accordingly
|
||||
asUINT numPtrs = 0;
|
||||
int currOffset = 0;
|
||||
int currOffset = -stackDelta;
|
||||
if( offset > currOffset && calledFunc->GetObjectType() )
|
||||
{
|
||||
numPtrs++;
|
||||
currOffset++;
|
||||
if( currOffset > 0 )
|
||||
numPtrs++;
|
||||
#if AS_PTR_SIZE == 2
|
||||
// For 64bit platforms it is necessary to increment the currOffset by one more
|
||||
// DWORD since the stackDelta was counting the full 64bit size of the pointer
|
||||
else if( stackDelta )
|
||||
currOffset++;
|
||||
#endif
|
||||
}
|
||||
if( offset > currOffset && calledFunc->DoesReturnOnStack() )
|
||||
{
|
||||
numPtrs++;
|
||||
currOffset++;
|
||||
if( currOffset > 0 )
|
||||
numPtrs++;
|
||||
#if AS_PTR_SIZE == 2
|
||||
// For 64bit platforms it is necessary to increment the currOffset by one more
|
||||
// DWORD since the stackDelta was counting the full 64bit size of the pointer
|
||||
else if( stackDelta )
|
||||
currOffset++;
|
||||
#endif
|
||||
}
|
||||
for( asUINT p = 0; p < calledFunc->parameterTypes.GetLength(); p++ )
|
||||
{
|
||||
@ -3136,8 +3344,15 @@ int asCReader::AdjustGetOffset(int offset, asCScriptFunction *func, asDWORD prog
|
||||
if( !calledFunc->parameterTypes[p].IsPrimitive() ||
|
||||
calledFunc->parameterTypes[p].IsReference() )
|
||||
{
|
||||
numPtrs++;
|
||||
currOffset++;
|
||||
if( currOffset > 0 )
|
||||
numPtrs++;
|
||||
#if AS_PTR_SIZE == 2
|
||||
// For 64bit platforms it is necessary to increment the currOffset by one more
|
||||
// DWORD since the stackDelta was counting the full 64bit size of the pointer
|
||||
else if( stackDelta )
|
||||
currOffset++;
|
||||
#endif
|
||||
|
||||
// The variable arg ? has an additiona 32bit integer with the typeid
|
||||
if( calledFunc->parameterTypes[p].IsAnyType() )
|
||||
@ -3197,6 +3412,8 @@ void asCWriter::WriteData(const void *data, asUINT size)
|
||||
|
||||
int asCWriter::Write()
|
||||
{
|
||||
TimeIt("asCWriter::Write");
|
||||
|
||||
unsigned long i, count;
|
||||
|
||||
// Store everything in the same order that the builder parses scripts
|
||||
@ -3207,101 +3424,149 @@ int asCWriter::Write()
|
||||
WriteData(&stripDebugInfo, sizeof(stripDebugInfo));
|
||||
|
||||
// Store enums
|
||||
count = (asUINT)module->enumTypes.GetLength();
|
||||
WriteEncodedInt64(count);
|
||||
for( i = 0; i < count; i++ )
|
||||
{
|
||||
WriteObjectTypeDeclaration(module->enumTypes[i], 1);
|
||||
WriteObjectTypeDeclaration(module->enumTypes[i], 2);
|
||||
TimeIt("store enums");
|
||||
|
||||
count = (asUINT)module->enumTypes.GetLength();
|
||||
WriteEncodedInt64(count);
|
||||
for( i = 0; i < count; i++ )
|
||||
{
|
||||
WriteObjectTypeDeclaration(module->enumTypes[i], 1);
|
||||
WriteObjectTypeDeclaration(module->enumTypes[i], 2);
|
||||
}
|
||||
}
|
||||
|
||||
// Store type declarations first
|
||||
count = (asUINT)module->classTypes.GetLength();
|
||||
WriteEncodedInt64(count);
|
||||
for( i = 0; i < count; i++ )
|
||||
{
|
||||
// Store only the name of the class/interface types
|
||||
WriteObjectTypeDeclaration(module->classTypes[i], 1);
|
||||
TimeIt("type declarations");
|
||||
|
||||
count = (asUINT)module->classTypes.GetLength();
|
||||
WriteEncodedInt64(count);
|
||||
for( i = 0; i < count; i++ )
|
||||
{
|
||||
// Store only the name of the class/interface types
|
||||
WriteObjectTypeDeclaration(module->classTypes[i], 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Store func defs
|
||||
count = (asUINT)module->funcDefs.GetLength();
|
||||
WriteEncodedInt64(count);
|
||||
for( i = 0; i < count; i++ )
|
||||
WriteFunction(module->funcDefs[i]);
|
||||
{
|
||||
TimeIt("func defs");
|
||||
|
||||
count = (asUINT)module->funcDefs.GetLength();
|
||||
WriteEncodedInt64(count);
|
||||
for( i = 0; i < count; i++ )
|
||||
WriteFunction(module->funcDefs[i]);
|
||||
}
|
||||
|
||||
// Now store all interface methods
|
||||
count = (asUINT)module->classTypes.GetLength();
|
||||
for( i = 0; i < count; i++ )
|
||||
{
|
||||
if( module->classTypes[i]->IsInterface() )
|
||||
WriteObjectTypeDeclaration(module->classTypes[i], 2);
|
||||
TimeIt("interface methods");
|
||||
|
||||
count = (asUINT)module->classTypes.GetLength();
|
||||
for( i = 0; i < count; i++ )
|
||||
{
|
||||
if( module->classTypes[i]->IsInterface() )
|
||||
WriteObjectTypeDeclaration(module->classTypes[i], 2);
|
||||
}
|
||||
}
|
||||
|
||||
// Then store the class methods and behaviours
|
||||
for( i = 0; i < count; ++i )
|
||||
{
|
||||
if( !module->classTypes[i]->IsInterface() )
|
||||
WriteObjectTypeDeclaration(module->classTypes[i], 2);
|
||||
TimeIt("class methods and behaviours");
|
||||
|
||||
for( i = 0; i < count; ++i )
|
||||
{
|
||||
if( !module->classTypes[i]->IsInterface() )
|
||||
WriteObjectTypeDeclaration(module->classTypes[i], 2);
|
||||
}
|
||||
}
|
||||
|
||||
// Then store the class properties
|
||||
for( i = 0; i < count; ++i )
|
||||
{
|
||||
if( !module->classTypes[i]->IsInterface() )
|
||||
WriteObjectTypeDeclaration(module->classTypes[i], 3);
|
||||
TimeIt("class properties");
|
||||
|
||||
for( i = 0; i < count; ++i )
|
||||
{
|
||||
if( !module->classTypes[i]->IsInterface() )
|
||||
WriteObjectTypeDeclaration(module->classTypes[i], 3);
|
||||
}
|
||||
}
|
||||
|
||||
// Store typedefs
|
||||
count = (asUINT)module->typeDefs.GetLength();
|
||||
WriteEncodedInt64(count);
|
||||
for( i = 0; i < count; i++ )
|
||||
{
|
||||
WriteObjectTypeDeclaration(module->typeDefs[i], 1);
|
||||
WriteObjectTypeDeclaration(module->typeDefs[i], 2);
|
||||
TimeIt("type defs");
|
||||
|
||||
count = (asUINT)module->typeDefs.GetLength();
|
||||
WriteEncodedInt64(count);
|
||||
for( i = 0; i < count; i++ )
|
||||
{
|
||||
WriteObjectTypeDeclaration(module->typeDefs[i], 1);
|
||||
WriteObjectTypeDeclaration(module->typeDefs[i], 2);
|
||||
}
|
||||
}
|
||||
|
||||
// scriptGlobals[]
|
||||
count = (asUINT)module->scriptGlobals.GetSize();
|
||||
WriteEncodedInt64(count);
|
||||
asCSymbolTable<asCGlobalProperty>::iterator it = module->scriptGlobals.List();
|
||||
for( ; it; it++ )
|
||||
WriteGlobalProperty(*it);
|
||||
{
|
||||
TimeIt("script globals");
|
||||
|
||||
count = (asUINT)module->scriptGlobals.GetSize();
|
||||
WriteEncodedInt64(count);
|
||||
asCSymbolTable<asCGlobalProperty>::iterator it = module->scriptGlobals.List();
|
||||
for( ; it; it++ )
|
||||
WriteGlobalProperty(*it);
|
||||
}
|
||||
|
||||
// scriptFunctions[]
|
||||
count = 0;
|
||||
for( i = 0; i < module->scriptFunctions.GetLength(); i++ )
|
||||
if( module->scriptFunctions[i]->objectType == 0 )
|
||||
count++;
|
||||
WriteEncodedInt64(count);
|
||||
for( i = 0; i < module->scriptFunctions.GetLength(); ++i )
|
||||
if( module->scriptFunctions[i]->objectType == 0 )
|
||||
WriteFunction(module->scriptFunctions[i]);
|
||||
{
|
||||
TimeIt("scriptFunctions");
|
||||
|
||||
count = 0;
|
||||
for( i = 0; i < module->scriptFunctions.GetLength(); i++ )
|
||||
if( module->scriptFunctions[i]->objectType == 0 )
|
||||
count++;
|
||||
WriteEncodedInt64(count);
|
||||
for( i = 0; i < module->scriptFunctions.GetLength(); ++i )
|
||||
if( module->scriptFunctions[i]->objectType == 0 )
|
||||
WriteFunction(module->scriptFunctions[i]);
|
||||
}
|
||||
|
||||
// globalFunctions[]
|
||||
count = (int)module->globalFunctions.GetSize();
|
||||
asCSymbolTable<asCScriptFunction>::iterator funcIt = module->globalFunctions.List();
|
||||
WriteEncodedInt64(count);
|
||||
while( funcIt )
|
||||
{
|
||||
WriteFunction(*funcIt);
|
||||
funcIt++;
|
||||
TimeIt("globalFunctions");
|
||||
|
||||
count = (int)module->globalFunctions.GetSize();
|
||||
asCSymbolTable<asCScriptFunction>::iterator funcIt = module->globalFunctions.List();
|
||||
WriteEncodedInt64(count);
|
||||
while( funcIt )
|
||||
{
|
||||
WriteFunction(*funcIt);
|
||||
funcIt++;
|
||||
}
|
||||
}
|
||||
|
||||
// bindInformations[]
|
||||
count = (asUINT)module->bindInformations.GetLength();
|
||||
WriteEncodedInt64(count);
|
||||
for( i = 0; i < count; ++i )
|
||||
{
|
||||
WriteFunction(module->bindInformations[i]->importedFunctionSignature);
|
||||
WriteString(&module->bindInformations[i]->importFromModule);
|
||||
TimeIt("bindInformations");
|
||||
|
||||
count = (asUINT)module->bindInformations.GetLength();
|
||||
WriteEncodedInt64(count);
|
||||
for( i = 0; i < count; ++i )
|
||||
{
|
||||
WriteFunction(module->bindInformations[i]->importedFunctionSignature);
|
||||
WriteString(&module->bindInformations[i]->importFromModule);
|
||||
}
|
||||
}
|
||||
|
||||
// usedTypes[]
|
||||
count = (asUINT)usedTypes.GetLength();
|
||||
WriteEncodedInt64(count);
|
||||
for( i = 0; i < count; ++i )
|
||||
WriteObjectType(usedTypes[i]);
|
||||
{
|
||||
TimeIt("usedTypes");
|
||||
|
||||
count = (asUINT)usedTypes.GetLength();
|
||||
WriteEncodedInt64(count);
|
||||
for( i = 0; i < count; ++i )
|
||||
WriteObjectType(usedTypes[i]);
|
||||
}
|
||||
|
||||
// usedTypeIds[]
|
||||
WriteUsedTypeIds();
|
||||
@ -3335,6 +3600,8 @@ int asCWriter::FindStringConstantIndex(int id)
|
||||
|
||||
void asCWriter::WriteUsedStringConstants()
|
||||
{
|
||||
TimeIt("asCWriter::WriteUsedStringConstants");
|
||||
|
||||
asUINT count = (asUINT)usedStringConstants.GetLength();
|
||||
WriteEncodedInt64(count);
|
||||
for( asUINT i = 0; i < count; ++i )
|
||||
@ -3343,6 +3610,8 @@ void asCWriter::WriteUsedStringConstants()
|
||||
|
||||
void asCWriter::WriteUsedFunctions()
|
||||
{
|
||||
TimeIt("asCWriter::WriteUsedFunctions");
|
||||
|
||||
asUINT count = (asUINT)usedFunctions.GetLength();
|
||||
WriteEncodedInt64(count);
|
||||
|
||||
@ -3572,6 +3841,12 @@ void asCWriter::WriteFunction(asCScriptFunction* func)
|
||||
// TODO: Do we really need to store this? It can probably be reconstructed by the reader
|
||||
WriteEncodedInt64(func->vfTableIdx);
|
||||
}
|
||||
else if( func->funcType == asFUNC_FUNCDEF )
|
||||
{
|
||||
char bits = 0;
|
||||
bits += func->isShared ? 1 : 0;
|
||||
WriteData(&bits,1);
|
||||
}
|
||||
}
|
||||
|
||||
void asCWriter::WriteObjectTypeDeclaration(asCObjectType *ot, int phase)
|
||||
@ -3755,39 +4030,28 @@ void asCWriter::WriteEncodedInt64(asINT64 i)
|
||||
|
||||
void asCWriter::WriteString(asCString* str)
|
||||
{
|
||||
// TODO: All strings should be stored in a separate section, and when
|
||||
// they are used an offset into that section should be stored.
|
||||
// This will make it unnecessary to store the extra byte to
|
||||
// identify new versus old strings.
|
||||
|
||||
if( str->GetLength() == 0 )
|
||||
{
|
||||
char z = '\0';
|
||||
WriteData(&z, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
// First check if the string hasn't been saved already
|
||||
asSMapNode<asCStringPointer, int> *cursor = 0;
|
||||
if (stringToIdMap.MoveTo(&cursor, asCStringPointer(str)))
|
||||
{
|
||||
// Save a reference to the existing string
|
||||
char b = 'r';
|
||||
WriteData(&b, 1);
|
||||
WriteEncodedInt64(cursor->value);
|
||||
// The lowest bit is set to 1 to indicate a reference
|
||||
WriteEncodedInt64(cursor->value*2+1);
|
||||
return;
|
||||
}
|
||||
|
||||
// Save a new string
|
||||
char b = 'n';
|
||||
WriteData(&b, 1);
|
||||
|
||||
// The lowest bit is set to 0 to indicate a new string
|
||||
asUINT len = (asUINT)str->GetLength();
|
||||
WriteEncodedInt64(len);
|
||||
stream->Write(str->AddressOf(), (asUINT)len);
|
||||
WriteEncodedInt64(len*2);
|
||||
|
||||
savedStrings.PushLast(*str);
|
||||
stringToIdMap.Insert(asCStringPointer(str), int(savedStrings.GetLength()) - 1);
|
||||
if( len > 0 )
|
||||
{
|
||||
stream->Write(str->AddressOf(), (asUINT)len);
|
||||
|
||||
savedStrings.PushLast(*str);
|
||||
stringToIdMap.Insert(asCStringPointer(str), int(savedStrings.GetLength()) - 1);
|
||||
}
|
||||
}
|
||||
|
||||
void asCWriter::WriteGlobalProperty(asCGlobalProperty* prop)
|
||||
@ -3851,7 +4115,7 @@ void asCWriter::WriteDataType(const asCDataType *dt)
|
||||
bits.isReadOnly = dt->IsReadOnly();
|
||||
WriteData(&bits, 1);
|
||||
|
||||
if( t == ttIdentifier && dt->GetObjectType()->name == "_builtin_function_" )
|
||||
if( t == ttIdentifier && dt->GetObjectType()->name == "$func" )
|
||||
{
|
||||
WriteFunctionSignature(dt->GetFuncDef());
|
||||
}
|
||||
@ -3883,17 +4147,17 @@ void asCWriter::WriteObjectType(asCObjectType* ot)
|
||||
WriteEncodedInt64(ot->templateSubTypes.GetLength());
|
||||
for( asUINT n = 0; n < ot->templateSubTypes.GetLength(); n++ )
|
||||
{
|
||||
if( ot->templateSubTypes[0].IsObject() || ot->templateSubTypes[0].IsEnumType() )
|
||||
if( ot->templateSubTypes[n].IsObject() || ot->templateSubTypes[n].IsEnumType() )
|
||||
{
|
||||
ch = 's';
|
||||
WriteData(&ch, 1);
|
||||
WriteDataType(&ot->templateSubTypes[0]);
|
||||
WriteDataType(&ot->templateSubTypes[n]);
|
||||
}
|
||||
else
|
||||
{
|
||||
ch = 't';
|
||||
WriteData(&ch, 1);
|
||||
eTokenType t = ot->templateSubTypes[0].GetTokenType();
|
||||
eTokenType t = ot->templateSubTypes[n].GetTokenType();
|
||||
WriteEncodedInt64(t);
|
||||
}
|
||||
}
|
||||
@ -4053,11 +4317,13 @@ int asCWriter::AdjustGetOffset(int offset, asCScriptFunction *func, asDWORD prog
|
||||
|
||||
// Find out which function that will be called
|
||||
asCScriptFunction *calledFunc = 0;
|
||||
int stackDelta = 0;
|
||||
for( asUINT n = programPos; n < func->scriptData->byteCode.GetLength(); )
|
||||
{
|
||||
asBYTE bc = *(asBYTE*)&func->scriptData->byteCode[n];
|
||||
if( bc == asBC_CALL ||
|
||||
bc == asBC_CALLSYS ||
|
||||
bc == asBC_Thiscall1 ||
|
||||
bc == asBC_CALLINTF )
|
||||
{
|
||||
// Find the function from the function id in bytecode
|
||||
@ -4120,6 +4386,10 @@ int asCWriter::AdjustGetOffset(int offset, asCScriptFunction *func, asDWORD prog
|
||||
return offset + (1 - AS_PTR_SIZE);
|
||||
}
|
||||
|
||||
// Keep track of the stack size between the
|
||||
// instruction that needs to be adjusted and the call
|
||||
stackDelta += asBCInfo[bc].stackInc;
|
||||
|
||||
n += asBCTypeSize[asBCInfo[bc].type];
|
||||
}
|
||||
|
||||
@ -4128,16 +4398,18 @@ int asCWriter::AdjustGetOffset(int offset, asCScriptFunction *func, asDWORD prog
|
||||
// Count the number of pointers pushed on the stack above the
|
||||
// current offset, and then adjust the offset accordingly
|
||||
asUINT numPtrs = 0;
|
||||
int currOffset = 0;
|
||||
int currOffset = -stackDelta;
|
||||
if( offset > currOffset && calledFunc->GetObjectType() )
|
||||
{
|
||||
numPtrs++;
|
||||
currOffset += AS_PTR_SIZE;
|
||||
if( currOffset > 0 )
|
||||
numPtrs++;
|
||||
}
|
||||
if( offset > currOffset && calledFunc->DoesReturnOnStack() )
|
||||
{
|
||||
numPtrs++;
|
||||
currOffset += AS_PTR_SIZE;
|
||||
if( currOffset > 0 )
|
||||
numPtrs++;
|
||||
}
|
||||
for( asUINT p = 0; p < calledFunc->parameterTypes.GetLength(); p++ )
|
||||
{
|
||||
@ -4147,8 +4419,9 @@ int asCWriter::AdjustGetOffset(int offset, asCScriptFunction *func, asDWORD prog
|
||||
calledFunc->parameterTypes[p].IsReference() )
|
||||
{
|
||||
// objects and references are passed by pointer
|
||||
numPtrs++;
|
||||
currOffset += AS_PTR_SIZE;
|
||||
if( currOffset > 0 )
|
||||
numPtrs++;
|
||||
|
||||
// The variable arg ? has an additional 32bit int with the typeid
|
||||
if( calledFunc->parameterTypes[p].IsAnyType() )
|
||||
@ -4262,7 +4535,8 @@ void asCWriter::WriteByteCode(asCScriptFunction *func)
|
||||
}
|
||||
else if( c == asBC_CALL || // DW_ARG
|
||||
c == asBC_CALLINTF || // DW_ARG
|
||||
c == asBC_CALLSYS ) // DW_ARG
|
||||
c == asBC_CALLSYS || // DW_ARG
|
||||
c == asBC_Thiscall1 ) // DW_ARG
|
||||
{
|
||||
// Translate the function id
|
||||
*(int*)(tmp+1) = FindFunctionIndex(engine->scriptFunctions[*(int*)(tmp+1)]);
|
||||
@ -4772,6 +5046,8 @@ void asCWriter::SListAdjuster::SetNextType(int typeId)
|
||||
|
||||
void asCWriter::WriteUsedTypeIds()
|
||||
{
|
||||
TimeIt("asCWriter::WriteUsedTypeIds");
|
||||
|
||||
asUINT count = (asUINT)usedTypeIds.GetLength();
|
||||
WriteEncodedInt64(count);
|
||||
for( asUINT n = 0; n < count; n++ )
|
||||
@ -4792,6 +5068,8 @@ int asCWriter::FindGlobalPropPtrIndex(void *ptr)
|
||||
|
||||
void asCWriter::WriteUsedGlobalProps()
|
||||
{
|
||||
TimeIt("asCWriter::WriteUsedGlobalProps");
|
||||
|
||||
int c = (int)usedGlobalProperties.GetLength();
|
||||
WriteEncodedInt64(c);
|
||||
|
||||
@ -4799,32 +5077,12 @@ void asCWriter::WriteUsedGlobalProps()
|
||||
{
|
||||
asPWORD *p = (asPWORD*)usedGlobalProperties[n];
|
||||
|
||||
// First search for the global in the module
|
||||
char moduleProp = 0;
|
||||
// Find the property descriptor from the address
|
||||
asCGlobalProperty *prop = 0;
|
||||
asCSymbolTable<asCGlobalProperty>::iterator it = module->scriptGlobals.List();
|
||||
for( ; it; it++ )
|
||||
asSMapNode<void*, asCGlobalProperty*> *cursor;
|
||||
if( engine->varAddressMap.MoveTo(&cursor, p) )
|
||||
{
|
||||
if( p == (*it)->GetAddressOfValue() )
|
||||
{
|
||||
prop = (*it);
|
||||
moduleProp = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If it is not in the module, it must be an application registered property
|
||||
if( !prop )
|
||||
{
|
||||
asCSymbolTable<asCGlobalProperty>::iterator it = engine->registeredGlobalProps.List();
|
||||
for( ; it; it++ )
|
||||
{
|
||||
if( it->GetAddressOfValue() == p )
|
||||
{
|
||||
prop = *it;
|
||||
break;
|
||||
}
|
||||
}
|
||||
prop = engine->varAddressMap.GetValue(cursor);
|
||||
}
|
||||
|
||||
asASSERT(prop);
|
||||
@ -4835,12 +5093,17 @@ void asCWriter::WriteUsedGlobalProps()
|
||||
WriteDataType(&prop->type);
|
||||
|
||||
// Also store whether the property is a module property or a registered property
|
||||
char moduleProp = 0;
|
||||
if( prop->realAddress == 0 )
|
||||
moduleProp = 1;
|
||||
WriteData(&moduleProp, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void asCWriter::WriteUsedObjectProps()
|
||||
{
|
||||
TimeIt("asCWriter::WriteUsedObjectProps");
|
||||
|
||||
int c = (int)usedObjectProperties.GetLength();
|
||||
WriteEncodedInt64(c);
|
||||
|
||||
|
@ -118,6 +118,9 @@ AS_API const char * asGetLibraryOptions()
|
||||
#ifdef WIP_16BYTE_ALIGN
|
||||
"WIP_16BYTE_ALIGN "
|
||||
#endif
|
||||
#ifdef AS_BIG_ENDIAN
|
||||
"AS_BIG_ENDIAN "
|
||||
#endif
|
||||
|
||||
// Target system
|
||||
#ifdef AS_WIN
|
||||
@ -584,21 +587,22 @@ asCScriptEngine::asCScriptEngine()
|
||||
// Reserve function id 0 for no function
|
||||
scriptFunctions.PushLast(0);
|
||||
|
||||
// Reserve the first typeIds for the primitive types
|
||||
typeIdSeqNbr = asTYPEID_DOUBLE + 1;
|
||||
|
||||
// Make sure typeId for the built-in primitives are defined according to asETypeIdFlags
|
||||
int id = 0;
|
||||
UNUSED_VAR(id); // It is only used in debug mode
|
||||
id = GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttVoid, false)); asASSERT( id == asTYPEID_VOID );
|
||||
id = GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttBool, false)); asASSERT( id == asTYPEID_BOOL );
|
||||
id = GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttInt8, false)); asASSERT( id == asTYPEID_INT8 );
|
||||
id = GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttInt16, false)); asASSERT( id == asTYPEID_INT16 );
|
||||
id = GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttInt, false)); asASSERT( id == asTYPEID_INT32 );
|
||||
id = GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttInt64, false)); asASSERT( id == asTYPEID_INT64 );
|
||||
id = GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttUInt8, false)); asASSERT( id == asTYPEID_UINT8 );
|
||||
id = GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttUInt16, false)); asASSERT( id == asTYPEID_UINT16 );
|
||||
id = GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttUInt, false)); asASSERT( id == asTYPEID_UINT32 );
|
||||
id = GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttUInt64, false)); asASSERT( id == asTYPEID_UINT64 );
|
||||
id = GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttFloat, false)); asASSERT( id == asTYPEID_FLOAT );
|
||||
id = GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttDouble, false)); asASSERT( id == asTYPEID_DOUBLE );
|
||||
asASSERT( GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttVoid, false)) == asTYPEID_VOID );
|
||||
asASSERT( GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttBool, false)) == asTYPEID_BOOL );
|
||||
asASSERT( GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttInt8, false)) == asTYPEID_INT8 );
|
||||
asASSERT( GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttInt16, false)) == asTYPEID_INT16 );
|
||||
asASSERT( GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttInt, false)) == asTYPEID_INT32 );
|
||||
asASSERT( GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttInt64, false)) == asTYPEID_INT64 );
|
||||
asASSERT( GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttUInt8, false)) == asTYPEID_UINT8 );
|
||||
asASSERT( GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttUInt16, false)) == asTYPEID_UINT16 );
|
||||
asASSERT( GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttUInt, false)) == asTYPEID_UINT32 );
|
||||
asASSERT( GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttUInt64, false)) == asTYPEID_UINT64 );
|
||||
asASSERT( GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttFloat, false)) == asTYPEID_FLOAT );
|
||||
asASSERT( GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttDouble, false)) == asTYPEID_DOUBLE );
|
||||
|
||||
defaultArrayObjectType = 0;
|
||||
|
||||
@ -608,9 +612,9 @@ asCScriptEngine::asCScriptEngine()
|
||||
|
||||
void asCScriptEngine::DeleteDiscardedModules()
|
||||
{
|
||||
// TODO: 2.30.0: redesign: Prevent more than one thread from entering this function at the same time.
|
||||
// If a thread is already doing the work for the clean-up the other thread should
|
||||
// simply return, as the first thread will continue.
|
||||
// TODO: redesign: Prevent more than one thread from entering this function at the same time.
|
||||
// If a thread is already doing the work for the clean-up the other thread should
|
||||
// simply return, as the first thread will continue.
|
||||
|
||||
ACQUIRESHARED(engineRWLock);
|
||||
asUINT maxCount = discardedModules.GetLength();
|
||||
@ -646,7 +650,7 @@ void asCScriptEngine::DeleteDiscardedModules()
|
||||
|
||||
asCScriptEngine::~asCScriptEngine()
|
||||
{
|
||||
// TODO: 2.30.0: redesign: Clean up redundant code
|
||||
// TODO: clean-up: Clean up redundant code
|
||||
|
||||
asUINT n = 0;
|
||||
inDestructor = true;
|
||||
@ -690,12 +694,8 @@ asCScriptEngine::~asCScriptEngine()
|
||||
if( refCount.get() > 0 )
|
||||
WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_ENGINE_REF_COUNT_ERROR_DURING_SHUTDOWN);
|
||||
|
||||
asSMapNode<int,asCDataType*> *cursor = 0;
|
||||
while( mapTypeIdToDataType.MoveFirst(&cursor) )
|
||||
{
|
||||
asDELETE(mapTypeIdToDataType.GetValue(cursor),asCDataType);
|
||||
mapTypeIdToDataType.Erase(cursor);
|
||||
}
|
||||
mapTypeIdToObjectType.EraseAll();
|
||||
mapTypeIdToFunction.EraseAll();
|
||||
|
||||
// First remove what is not used, so that other groups can be deleted safely
|
||||
defaultGroup.RemoveConfiguration(this, true);
|
||||
@ -1976,7 +1976,7 @@ int asCScriptEngine::RegisterBehaviourToObjectType(asCObjectType *objectType, as
|
||||
listPattern->Destroy(this);
|
||||
return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
|
||||
}
|
||||
func.name.Format("_beh_%d_", behaviour);
|
||||
func.name.Format("$beh%d", behaviour);
|
||||
|
||||
if( behaviour != asBEHAVE_FACTORY && behaviour != asBEHAVE_LIST_FACTORY )
|
||||
{
|
||||
@ -3229,7 +3229,7 @@ int asCScriptEngine::RegisterStringFactory(const char *datatype, const asSFuncPt
|
||||
return ConfigError(asOUT_OF_MEMORY, "RegisterStringFactory", datatype, 0);
|
||||
}
|
||||
|
||||
func->name = "_string_factory_";
|
||||
func->name = "$str";
|
||||
func->sysFuncIntf = newInterface;
|
||||
|
||||
asCBuilder bld(this, 0);
|
||||
@ -3590,6 +3590,9 @@ asCObjectType *asCScriptEngine::GetTemplateInstanceType(asCObjectType *templateT
|
||||
if( templateType->beh.listFactory )
|
||||
{
|
||||
asCScriptFunction *func = GenerateTemplateFactoryStub(templateType, ot, templateType->beh.listFactory);
|
||||
|
||||
// Rename the function to easily identify it in LoadByteCode
|
||||
func->name = "$list";
|
||||
|
||||
ot->beh.listFactory = func->id;
|
||||
}
|
||||
@ -3787,7 +3790,7 @@ asCScriptFunction *asCScriptEngine::GenerateTemplateFactoryStub(asCObjectType *t
|
||||
|
||||
func->funcType = asFUNC_SCRIPT;
|
||||
func->AllocateScriptFunctionData();
|
||||
func->name = "factstub";
|
||||
func->name = "$fact";
|
||||
func->id = GetNextScriptFunctionId();
|
||||
AddScriptFunction(func);
|
||||
|
||||
@ -4230,6 +4233,62 @@ void *asCScriptEngine::CallObjectMethodRetPtr(void *obj, int func) const
|
||||
#endif
|
||||
}
|
||||
|
||||
void *asCScriptEngine::CallObjectMethodRetPtr(void *obj, int param1, asCScriptFunction *func) const
|
||||
{
|
||||
asASSERT( func != 0 );
|
||||
asSSystemFunctionInterface *i = func->sysFuncIntf;
|
||||
|
||||
#ifndef AS_NO_CLASS_METHODS
|
||||
if( i->callConv == ICC_THISCALL || i->callConv == ICC_VIRTUAL_THISCALL )
|
||||
{
|
||||
#if defined(__GNUC__) || defined(AS_PSVITA)
|
||||
// For virtual thiscalls we must call the method as a true class method so that the compiler will lookup the function address in the vftable
|
||||
union
|
||||
{
|
||||
asSIMPLEMETHOD_t mthd;
|
||||
struct
|
||||
{
|
||||
asFUNCTION_t func;
|
||||
asPWORD baseOffset;
|
||||
} f;
|
||||
} p;
|
||||
p.f.func = (asFUNCTION_t)(i->func);
|
||||
p.f.baseOffset = asPWORD(i->baseOffset);
|
||||
void *(asCSimpleDummy::*f)(int) = (void *(asCSimpleDummy::*)(int))(p.mthd);
|
||||
return (((asCSimpleDummy*)obj)->*f)(param1);
|
||||
#else
|
||||
union
|
||||
{
|
||||
asSIMPLEMETHOD_t mthd;
|
||||
asFUNCTION_t func;
|
||||
} p;
|
||||
p.func = (asFUNCTION_t)(i->func);
|
||||
void *(asCSimpleDummy::*f)(int) = (void *(asCSimpleDummy::*)(int))p.mthd;
|
||||
obj = (void*)(asPWORD(obj) + i->baseOffset);
|
||||
return (((asCSimpleDummy*)obj)->*f)(param1);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if( i->callConv == ICC_GENERIC_METHOD )
|
||||
{
|
||||
asCGeneric gen(const_cast<asCScriptEngine*>(this), func, obj, reinterpret_cast<asDWORD*>(¶m1));
|
||||
void (*f)(asIScriptGeneric *) = (void (*)(asIScriptGeneric *))(i->func);
|
||||
f(&gen);
|
||||
return *(void **)gen.GetReturnPointer();
|
||||
}
|
||||
else if( i->callConv == ICC_CDECL_OBJLAST )
|
||||
{
|
||||
void *(*f)(int, void *) = (void *(*)(int, void *))(i->func);
|
||||
return f(param1, obj);
|
||||
}
|
||||
else /*if( i->callConv == ICC_CDECL_OBJFIRST )*/
|
||||
{
|
||||
void *(*f)(void *, int) = (void *(*)(void *, int))(i->func);
|
||||
return f(obj, param1);
|
||||
}
|
||||
}
|
||||
|
||||
void *asCScriptEngine::CallGlobalFunctionRetPtr(int func) const
|
||||
{
|
||||
asCScriptFunction *s = scriptFunctions[func];
|
||||
@ -4496,82 +4555,154 @@ void asCScriptEngine::GCEnumCallback(void *reference)
|
||||
}
|
||||
|
||||
|
||||
// TODO: multithread: The mapTypeIdToDataType must be protected with critical sections in all functions that access it
|
||||
int asCScriptEngine::GetTypeIdFromDataType(const asCDataType &dtIn) const
|
||||
{
|
||||
if( dtIn.IsNullHandle() ) return 0;
|
||||
if( dtIn.IsNullHandle() ) return asTYPEID_VOID;
|
||||
|
||||
// Register the base form
|
||||
asCDataType dt(dtIn);
|
||||
if( dt.GetObjectType() )
|
||||
dt.MakeHandle(false);
|
||||
|
||||
// Find the existing type id
|
||||
asSMapNode<int,asCDataType*> *cursor = 0;
|
||||
mapTypeIdToDataType.MoveFirst(&cursor);
|
||||
while( cursor )
|
||||
if( dtIn.GetObjectType() == 0 )
|
||||
{
|
||||
if( mapTypeIdToDataType.GetValue(cursor)->IsEqualExceptRefAndConst(dt) )
|
||||
// Primitives have pre-fixed typeIds
|
||||
switch( dtIn.GetTokenType() )
|
||||
{
|
||||
int typeId = mapTypeIdToDataType.GetKey(cursor);
|
||||
if( dtIn.GetObjectType() && !(dtIn.GetObjectType()->flags & asOBJ_ASHANDLE) )
|
||||
case ttVoid: return asTYPEID_VOID;
|
||||
case ttBool: return asTYPEID_BOOL;
|
||||
case ttInt8: return asTYPEID_INT8;
|
||||
case ttInt16: return asTYPEID_INT16;
|
||||
case ttInt: return asTYPEID_INT32;
|
||||
case ttInt64: return asTYPEID_INT64;
|
||||
case ttUInt8: return asTYPEID_UINT8;
|
||||
case ttUInt16: return asTYPEID_UINT16;
|
||||
case ttUInt: return asTYPEID_UINT32;
|
||||
case ttUInt64: return asTYPEID_UINT64;
|
||||
case ttFloat: return asTYPEID_FLOAT;
|
||||
case ttDouble: return asTYPEID_DOUBLE;
|
||||
default:
|
||||
// All types should be covered by the above. The variable type is not really a type
|
||||
asASSERT(dtIn.GetTokenType() == ttQuestion);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int typeId = -1;
|
||||
asCObjectType *ot = dtIn.GetObjectType();
|
||||
if( ot != &functionBehaviours )
|
||||
{
|
||||
// Object's hold the typeId themselves
|
||||
typeId = ot->typeId;
|
||||
|
||||
if( typeId == -1 )
|
||||
{
|
||||
ACQUIREEXCLUSIVE(engineRWLock);
|
||||
// Make sure another thread didn't determine the typeId while we were waiting for the lock
|
||||
if( ot->typeId == -1 )
|
||||
{
|
||||
// The ASHANDLE types behave like handles, but are really
|
||||
// value types so the typeId is never returned as a handle
|
||||
if( dtIn.IsObjectHandle() )
|
||||
typeId |= asTYPEID_OBJHANDLE;
|
||||
if( dtIn.IsHandleToConst() )
|
||||
typeId |= asTYPEID_HANDLETOCONST;
|
||||
typeId = typeIdSeqNbr++;
|
||||
if( ot->flags & asOBJ_SCRIPT_OBJECT ) typeId |= asTYPEID_SCRIPTOBJECT;
|
||||
else if( ot->flags & asOBJ_TEMPLATE ) typeId |= asTYPEID_TEMPLATE;
|
||||
else if( ot->flags & asOBJ_ENUM ) {} // TODO: Should we have a specific bit for this?
|
||||
else typeId |= asTYPEID_APPOBJECT;
|
||||
|
||||
ot->typeId = typeId;
|
||||
|
||||
mapTypeIdToObjectType.Insert(typeId, ot);
|
||||
}
|
||||
RELEASEEXCLUSIVE(engineRWLock);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// This a funcdef, so we'll need to look in the map for the funcdef
|
||||
|
||||
// TODO: optimize: It shouldn't be necessary to exclusive lock when the typeId already exists
|
||||
ACQUIREEXCLUSIVE(engineRWLock);
|
||||
|
||||
// Find the existing type id
|
||||
asCScriptFunction *func = dtIn.GetFuncDef();
|
||||
asASSERT(func);
|
||||
asSMapNode<int,asCScriptFunction*> *cursor = 0;
|
||||
mapTypeIdToFunction.MoveFirst(&cursor);
|
||||
while( cursor )
|
||||
{
|
||||
if( mapTypeIdToFunction.GetValue(cursor) == func )
|
||||
{
|
||||
typeId = mapTypeIdToFunction.GetKey(cursor);
|
||||
break;
|
||||
}
|
||||
|
||||
return typeId;
|
||||
mapTypeIdToFunction.MoveNext(&cursor, cursor);
|
||||
}
|
||||
|
||||
mapTypeIdToDataType.MoveNext(&cursor, cursor);
|
||||
// The type id doesn't exist, create it
|
||||
if( typeId == -1 )
|
||||
{
|
||||
// Setup the type id for the funcdef
|
||||
typeId = typeIdSeqNbr++;
|
||||
typeId |= asTYPEID_APPOBJECT;
|
||||
mapTypeIdToFunction.Insert(typeId, func);
|
||||
}
|
||||
|
||||
RELEASEEXCLUSIVE(engineRWLock);
|
||||
}
|
||||
|
||||
// The type id doesn't exist, create it
|
||||
|
||||
// Setup the basic type id
|
||||
int typeId = typeIdSeqNbr++;
|
||||
if( dt.GetObjectType() )
|
||||
// Add flags according to the requested type
|
||||
if( dtIn.GetObjectType() && !(dtIn.GetObjectType()->flags & asOBJ_ASHANDLE) )
|
||||
{
|
||||
if( dt.GetObjectType()->flags & asOBJ_SCRIPT_OBJECT ) typeId |= asTYPEID_SCRIPTOBJECT;
|
||||
else if( dt.GetObjectType()->flags & asOBJ_TEMPLATE ) typeId |= asTYPEID_TEMPLATE;
|
||||
else if( dt.GetObjectType()->flags & asOBJ_ENUM ) {} // TODO: Should we have a specific bit for this?
|
||||
else typeId |= asTYPEID_APPOBJECT;
|
||||
// The ASHANDLE types behave like handles, but are really
|
||||
// value types so the typeId is never returned as a handle
|
||||
if( dtIn.IsObjectHandle() )
|
||||
typeId |= asTYPEID_OBJHANDLE;
|
||||
if( dtIn.IsHandleToConst() )
|
||||
typeId |= asTYPEID_HANDLETOCONST;
|
||||
}
|
||||
|
||||
// Insert the basic object type
|
||||
asCDataType *newDt = asNEW(asCDataType)(dt);
|
||||
if( newDt == 0 )
|
||||
{
|
||||
// Out of memory
|
||||
return 0;
|
||||
}
|
||||
|
||||
newDt->MakeReference(false);
|
||||
newDt->MakeReadOnly(false);
|
||||
newDt->MakeHandle(false);
|
||||
|
||||
mapTypeIdToDataType.Insert(typeId, newDt);
|
||||
|
||||
// Call recursively to get the correct typeId
|
||||
return GetTypeIdFromDataType(dtIn);
|
||||
return typeId;
|
||||
}
|
||||
|
||||
asCDataType asCScriptEngine::GetDataTypeFromTypeId(int typeId) const
|
||||
{
|
||||
int baseId = typeId & (asTYPEID_MASK_OBJECT | asTYPEID_MASK_SEQNBR);
|
||||
|
||||
asSMapNode<int,asCDataType*> *cursor = 0;
|
||||
if( mapTypeIdToDataType.MoveTo(&cursor, baseId) )
|
||||
if( typeId <= asTYPEID_DOUBLE )
|
||||
{
|
||||
asCDataType dt(*mapTypeIdToDataType.GetValue(cursor));
|
||||
eTokenType type[] = {ttVoid, ttBool, ttInt8, ttInt16, ttInt, ttInt64, ttUInt8, ttUInt16, ttUInt, ttUInt64, ttFloat, ttDouble};
|
||||
return asCDataType::CreatePrimitive(type[typeId], false);
|
||||
}
|
||||
|
||||
// First check if the typeId is an object type
|
||||
asCObjectType *ot = 0;
|
||||
ACQUIRESHARED(engineRWLock);
|
||||
asSMapNode<int,asCObjectType*> *cursor = 0;
|
||||
if( mapTypeIdToObjectType.MoveTo(&cursor, baseId) )
|
||||
ot = mapTypeIdToObjectType.GetValue(cursor);
|
||||
RELEASESHARED(engineRWLock);
|
||||
|
||||
if( ot )
|
||||
{
|
||||
asCDataType dt = asCDataType::CreateObject(ot, false);
|
||||
if( typeId & asTYPEID_OBJHANDLE )
|
||||
dt.MakeHandle(true, true);
|
||||
if( typeId & asTYPEID_HANDLETOCONST )
|
||||
dt.MakeHandleToConst(true);
|
||||
|
||||
return dt;
|
||||
}
|
||||
|
||||
// Then check if it is a funcdef
|
||||
asCScriptFunction *func = 0;
|
||||
ACQUIRESHARED(engineRWLock);
|
||||
asSMapNode<int,asCScriptFunction*> *cursor2 = 0;
|
||||
if( mapTypeIdToFunction.MoveTo(&cursor2, baseId) )
|
||||
func = mapTypeIdToFunction.GetValue(cursor2);
|
||||
RELEASESHARED(engineRWLock);
|
||||
|
||||
if( func )
|
||||
{
|
||||
asCDataType dt = asCDataType::CreateFuncDef(func);
|
||||
if( typeId & asTYPEID_OBJHANDLE )
|
||||
dt.MakeHandle(true, true);
|
||||
if( typeId & asTYPEID_HANDLETOCONST )
|
||||
dt.MakeHandleToConst(true);
|
||||
|
||||
return dt;
|
||||
}
|
||||
|
||||
@ -4586,19 +4717,19 @@ asCObjectType *asCScriptEngine::GetObjectTypeFromTypeId(int typeId) const
|
||||
|
||||
void asCScriptEngine::RemoveFromTypeIdMap(asCObjectType *type)
|
||||
{
|
||||
asSMapNode<int,asCDataType*> *cursor = 0;
|
||||
mapTypeIdToDataType.MoveFirst(&cursor);
|
||||
ACQUIREEXCLUSIVE(engineRWLock);
|
||||
asSMapNode<int,asCObjectType*> *cursor = 0;
|
||||
mapTypeIdToObjectType.MoveFirst(&cursor);
|
||||
while( cursor )
|
||||
{
|
||||
asCDataType *dt = mapTypeIdToDataType.GetValue(cursor);
|
||||
asSMapNode<int,asCDataType*> *old = cursor;
|
||||
mapTypeIdToDataType.MoveNext(&cursor, cursor);
|
||||
if( dt->GetObjectType() == type )
|
||||
if( mapTypeIdToObjectType.GetValue(cursor) == type )
|
||||
{
|
||||
asDELETE(dt,asCDataType);
|
||||
mapTypeIdToDataType.Erase(old);
|
||||
mapTypeIdToObjectType.Erase(cursor);
|
||||
break;
|
||||
}
|
||||
mapTypeIdToObjectType.MoveNext(&cursor, cursor);
|
||||
}
|
||||
RELEASEEXCLUSIVE(engineRWLock);
|
||||
}
|
||||
|
||||
// interface
|
||||
@ -5318,7 +5449,6 @@ void asCScriptEngine::RemoveScriptFunction(asCScriptFunction *func)
|
||||
// internal
|
||||
void asCScriptEngine::RemoveFuncdef(asCScriptFunction *funcdef)
|
||||
{
|
||||
// TODO: 2.30.0: redesign: How to avoid removing a funcdef that is shared by multiple modules?
|
||||
funcDefs.RemoveValue(funcdef);
|
||||
}
|
||||
|
||||
|
@ -238,6 +238,7 @@ public:
|
||||
bool CallObjectMethodRetBool(void *obj, int func) const;
|
||||
int CallObjectMethodRetInt(void *obj, int func) const;
|
||||
void *CallObjectMethodRetPtr(void *obj, int func) const;
|
||||
void *CallObjectMethodRetPtr(void *obj, int param1, asCScriptFunction *func) const;
|
||||
void CallGlobalFunction(void *param1, void *param2, asSSystemFunctionInterface *func, asCScriptFunction *desc) const;
|
||||
bool CallGlobalFunctionRetBool(void *param1, void *param2, asSSystemFunctionInterface *func, asCScriptFunction *desc) const;
|
||||
|
||||
@ -400,16 +401,17 @@ public:
|
||||
// This array stores the template instances types that have been automatically generated from template types
|
||||
asCArray<asCObjectType *> generatedTemplateTypes;
|
||||
// Stores the funcdefs
|
||||
// TODO: 2.30.0: redesign: Only shared funcdefs should be stored here
|
||||
// a funcdef becomes shared if all arguments and the return type are shared (or application registered)
|
||||
// TODO: redesign: Only shared funcdefs should be stored here
|
||||
// a funcdef becomes shared if all arguments and the return type are shared (or application registered)
|
||||
asCArray<asCScriptFunction *> funcDefs; // doesn't increase ref count
|
||||
|
||||
// Stores the names of the script sections for debugging purposes
|
||||
asCArray<asCString *> scriptSectionNames;
|
||||
|
||||
// Type identifiers
|
||||
mutable int typeIdSeqNbr;
|
||||
mutable asCMap<int, asCDataType*> mapTypeIdToDataType;
|
||||
mutable int typeIdSeqNbr;
|
||||
mutable asCMap<int, asCObjectType*> mapTypeIdToObjectType;
|
||||
mutable asCMap<int, asCScriptFunction*> mapTypeIdToFunction;
|
||||
|
||||
// Garbage collector
|
||||
asCGarbageCollector gc;
|
||||
|
@ -105,7 +105,7 @@ static void ScriptFunction_CreateDelegate_Generic(asIScriptGeneric *gen)
|
||||
gen->SetReturnAddress(CreateDelegate(func, obj));
|
||||
}
|
||||
|
||||
// TODO: 2.29.0: operator==
|
||||
// TODO: operator==
|
||||
/*static void ScriptFunction_opEquals_Generic(asIScriptGeneric *gen)
|
||||
{
|
||||
asCScriptFunction *funcSelf = (asCScriptFunction*)gen->GetObject();
|
||||
@ -124,7 +124,7 @@ void RegisterScriptFunction(asCScriptEngine *engine)
|
||||
UNUSED_VAR(r); // It is only used in debug mode
|
||||
engine->functionBehaviours.engine = engine;
|
||||
engine->functionBehaviours.flags = asOBJ_REF | asOBJ_GC | asOBJ_SCRIPT_FUNCTION;
|
||||
engine->functionBehaviours.name = "_builtin_function_";
|
||||
engine->functionBehaviours.name = "$func";
|
||||
#ifndef AS_MAX_PORTABILITY
|
||||
r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_ADDREF, "void f()", asMETHOD(asCScriptFunction,AddRef), asCALL_THISCALL, 0); asASSERT( r >= 0 );
|
||||
r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_RELEASE, "void f()", asMETHOD(asCScriptFunction,Release), asCALL_THISCALL, 0); asASSERT( r >= 0 );
|
||||
@ -133,7 +133,7 @@ void RegisterScriptFunction(asCScriptEngine *engine)
|
||||
r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_GETGCFLAG, "bool f()", asMETHOD(asCScriptFunction,GetFlag), asCALL_THISCALL, 0); asASSERT( r >= 0 );
|
||||
r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_ENUMREFS, "void f(int&in)", asMETHOD(asCScriptFunction,EnumReferences), asCALL_THISCALL, 0); asASSERT( r >= 0 );
|
||||
r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_RELEASEREFS, "void f(int&in)", asMETHOD(asCScriptFunction,ReleaseAllHandles), asCALL_THISCALL, 0); asASSERT( r >= 0 );
|
||||
// TODO: 2.29.0: Need some way to allow the arg type to adapt when the funcdefs are instantiated
|
||||
// TODO: Need some way to allow the arg type to adapt when the funcdefs are instantiated
|
||||
// r = engine->RegisterMethodToObjectType(&engine->functionBehaviours, "bool opEquals(const int &in)", asMETHOD(asCScriptFunction,operator==), asCALL_THISCALL); asASSERT( r >= 0 );
|
||||
#else
|
||||
r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_ADDREF, "void f()", asFUNCTION(ScriptFunction_AddRef_Generic), asCALL_GENERIC, 0); asASSERT( r >= 0 );
|
||||
@ -226,7 +226,7 @@ asIScriptFunction *asCScriptFunction::GetDelegateFunction() const
|
||||
return funcForDelegate;
|
||||
}
|
||||
|
||||
// TODO: 2.29.0: operator==
|
||||
// TODO: operator==
|
||||
/*
|
||||
// internal
|
||||
bool asCScriptFunction::operator==(const asCScriptFunction &other) const
|
||||
@ -419,7 +419,6 @@ asCScriptFunction::~asCScriptFunction()
|
||||
// If the engine pointer is 0, then DestroyInternal has already been called and there is nothing more to do
|
||||
if( engine == 0 ) return;
|
||||
|
||||
// TODO: 2.30.0: redesign: Shouldn't this have been done already?
|
||||
DestroyInternal();
|
||||
|
||||
// Finally set the engine pointer to 0 because it must not be accessed again
|
||||
@ -678,7 +677,7 @@ asCString asCScriptFunction::GetDeclarationStr(bool includeObjectName, bool incl
|
||||
if( !(returnType.GetTokenType() == ttVoid &&
|
||||
objectType &&
|
||||
(name == objectType->name || (name.GetLength() > 0 && name[0] == '~') ||
|
||||
name == "_beh_0_" || name == "_beh_2_")) )
|
||||
name == "$beh0" || name == "$beh2")) )
|
||||
{
|
||||
str = returnType.Format(nameSpace, includeNamespace);
|
||||
str += " ";
|
||||
@ -699,13 +698,13 @@ asCString asCScriptFunction::GetDeclarationStr(bool includeObjectName, bool incl
|
||||
}
|
||||
if( name == "" )
|
||||
str += "_unnamed_function_(";
|
||||
else if( name.SubString(0,5) == "_beh_" && name.GetLength() == 7 )
|
||||
else if( name.SubString(0,4) == "$beh" && name.GetLength() == 5 )
|
||||
{
|
||||
if( name[5] == '0' + asBEHAVE_CONSTRUCT )
|
||||
if( name[4] == '0' + asBEHAVE_CONSTRUCT )
|
||||
str += objectType->name + "(";
|
||||
else if( name[5] == '0' + asBEHAVE_FACTORY )
|
||||
else if( name[4] == '0' + asBEHAVE_FACTORY )
|
||||
str += returnType.GetObjectType()->name + "(";
|
||||
else if( name[5] == '0' + asBEHAVE_DESTRUCT )
|
||||
else if( name[4] == '0' + asBEHAVE_DESTRUCT )
|
||||
str += "~" + objectType->name + "(";
|
||||
else
|
||||
str += name + "(";
|
||||
@ -1008,7 +1007,7 @@ void asCScriptFunction::ComputeSignatureId()
|
||||
// internal
|
||||
bool asCScriptFunction::IsSignatureEqual(const asCScriptFunction *func) const
|
||||
{
|
||||
if( !IsSignatureExceptNameEqual(func) || name != func->name ) return false;
|
||||
if( name != func->name || !IsSignatureExceptNameEqual(func) ) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -1043,9 +1042,9 @@ bool asCScriptFunction::IsSignatureExceptNameAndReturnTypeEqual(const asCScriptF
|
||||
bool asCScriptFunction::IsSignatureExceptNameAndReturnTypeEqual(const asCArray<asCDataType> ¶mTypes, const asCArray<asETypeModifiers> ¶mInOut, const asCObjectType *objType, bool readOnly) const
|
||||
{
|
||||
if( this->isReadOnly != readOnly ) return false;
|
||||
if( (this->objectType != 0) != (objType != 0) ) return false;
|
||||
if( this->inOutFlags != paramInOut ) return false;
|
||||
if( this->parameterTypes != paramTypes ) return false;
|
||||
if( (this->objectType != 0) != (objType != 0) ) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -1299,7 +1298,11 @@ void asCScriptFunction::ReleaseReferences()
|
||||
if( group != 0 ) group->Release();
|
||||
|
||||
if( funcId )
|
||||
engine->scriptFunctions[funcId]->ReleaseInternal();
|
||||
{
|
||||
asCScriptFunction *fptr = engine->scriptFunctions[funcId];
|
||||
if( fptr )
|
||||
fptr->ReleaseInternal();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
AngelCode Scripting Library
|
||||
Copyright (c) 2003-2014 Andreas Jonsson
|
||||
Copyright (c) 2003-2015 Andreas Jonsson
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any
|
||||
@ -186,12 +186,12 @@ public:
|
||||
|
||||
void DestroyHalfCreated();
|
||||
|
||||
// TODO: 2.29.0: operator==
|
||||
// TODO: 2.29.0: The asIScriptFunction should provide operator== and operator!= that should do a
|
||||
// a value comparison. Two delegate objects that point to the same object and class method should compare as equal
|
||||
// TODO: 2.29.0: The operator== should also be provided in script as opEquals to allow the same comparison in script
|
||||
// To do this we'll need some way to adapt the argtype for opEquals for each funcdef, preferrably without instantiating lots of different methods
|
||||
// Perhaps reusing 'auto' to mean the same type as the object
|
||||
// TODO: operator==
|
||||
// TODO: The asIScriptFunction should provide operator== and operator!= that should do a
|
||||
// a value comparison. Two delegate objects that point to the same object and class method should compare as equal
|
||||
// TODO: The operator== should also be provided in script as opEquals to allow the same comparison in script
|
||||
// To do this we'll need some way to adapt the argtype for opEquals for each funcdef, preferrably without instantiating lots of different methods
|
||||
// Perhaps reusing 'auto' to mean the same type as the object
|
||||
//bool operator==(const asCScriptFunction &other) const;
|
||||
|
||||
void DestroyInternal();
|
||||
@ -329,7 +329,7 @@ public:
|
||||
asSSystemFunctionInterface *sysFuncIntf;
|
||||
};
|
||||
|
||||
const char * const DELEGATE_FACTORY = "%delegate_factory";
|
||||
const char * const DELEGATE_FACTORY = "$dlgte";
|
||||
asCScriptFunction *CreateDelegate(asCScriptFunction *func, void *obj);
|
||||
|
||||
END_AS_NAMESPACE
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
AngelCode Scripting Library
|
||||
Copyright (c) 2003-2014 Andreas Jonsson
|
||||
Copyright (c) 2003-2015 Andreas Jonsson
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any
|
||||
@ -173,6 +173,24 @@ static void ScriptObject_ReleaseAllHandles_Generic(asIScriptGeneric *gen)
|
||||
self->ReleaseAllHandles(engine);
|
||||
}
|
||||
|
||||
static void ScriptObject_Assignment_Generic(asIScriptGeneric *gen)
|
||||
{
|
||||
asCScriptObject *other = *(asCScriptObject**)gen->GetAddressOfArg(0);
|
||||
asCScriptObject *self = (asCScriptObject*)gen->GetObject();
|
||||
|
||||
*self = *other;
|
||||
|
||||
*(asCScriptObject**)gen->GetAddressOfReturnLocation() = self;
|
||||
}
|
||||
|
||||
static void ScriptObject_Construct_Generic(asIScriptGeneric *gen)
|
||||
{
|
||||
asCObjectType *objType = *(asCObjectType**)gen->GetAddressOfArg(0);
|
||||
asCScriptObject *self = (asCScriptObject*)gen->GetObject();
|
||||
|
||||
ScriptObject_Construct(objType, self);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void RegisterScriptObject(asCScriptEngine *engine)
|
||||
@ -182,7 +200,7 @@ void RegisterScriptObject(asCScriptEngine *engine)
|
||||
UNUSED_VAR(r); // It is only used in debug mode
|
||||
engine->scriptTypeBehaviours.engine = engine;
|
||||
engine->scriptTypeBehaviours.flags = asOBJ_SCRIPT_OBJECT | asOBJ_REF | asOBJ_GC;
|
||||
engine->scriptTypeBehaviours.name = "_builtin_object_";
|
||||
engine->scriptTypeBehaviours.name = "$obj";
|
||||
#ifndef AS_MAX_PORTABILITY
|
||||
r = engine->RegisterBehaviourToObjectType(&engine->scriptTypeBehaviours, asBEHAVE_CONSTRUCT, "void f(int&in)", asFUNCTION(ScriptObject_Construct), asCALL_CDECL_OBJLAST, 0); asASSERT( r >= 0 );
|
||||
r = engine->RegisterBehaviourToObjectType(&engine->scriptTypeBehaviours, asBEHAVE_ADDREF, "void f()", asMETHOD(asCScriptObject,AddRef), asCALL_THISCALL, 0); asASSERT( r >= 0 );
|
||||
@ -216,14 +234,6 @@ void RegisterScriptObject(asCScriptEngine *engine)
|
||||
#endif
|
||||
}
|
||||
|
||||
void ScriptObject_Construct_Generic(asIScriptGeneric *gen)
|
||||
{
|
||||
asCObjectType *objType = *(asCObjectType**)gen->GetAddressOfArg(0);
|
||||
asCScriptObject *self = (asCScriptObject*)gen->GetObject();
|
||||
|
||||
ScriptObject_Construct(objType, self);
|
||||
}
|
||||
|
||||
void ScriptObject_Construct(asCObjectType *objType, asCScriptObject *self)
|
||||
{
|
||||
new(self) asCScriptObject(objType);
|
||||
@ -744,16 +754,6 @@ void asCScriptObject::ReleaseAllHandles(asIScriptEngine *engine)
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptObject_Assignment_Generic(asIScriptGeneric *gen)
|
||||
{
|
||||
asCScriptObject *other = *(asCScriptObject**)gen->GetAddressOfArg(0);
|
||||
asCScriptObject *self = (asCScriptObject*)gen->GetObject();
|
||||
|
||||
*self = *other;
|
||||
|
||||
*(asCScriptObject**)gen->GetAddressOfReturnLocation() = self;
|
||||
}
|
||||
|
||||
asCScriptObject &ScriptObject_Assignment(asCScriptObject *other, asCScriptObject *self)
|
||||
{
|
||||
return (*self = *other);
|
||||
|