Merged with master, solved conflicts

This commit is contained in:
Elderme 2016-06-18 19:28:54 +02:00
parent da5529f5bb
commit b359e8f9fd
406 changed files with 43018 additions and 11640 deletions

View File

@ -47,7 +47,7 @@ script:
notifications:
irc:
channels:
- "irc.freenode.org#stk"
- "irc.freenode.org#supertuxkart"
skip_join: false
use_notice: true
template:

View File

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

View File

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

View File

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

View File

@ -1,59 +1,45 @@
# SuperTuxKart
[![Build Status](https://travis-ci.org/supertuxkart/stk-code.png?branch=master)](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).

Binary file not shown.

View File

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

View File

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

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

View File

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

View File

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

View File

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

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

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

View File

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

View File

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

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
data/gui/mode_ghost.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

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

View File

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.9 KiB

After

Width:  |  Height:  |  Size: 23 KiB

View File

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

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

BIN
data/skins/ruby/generic.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View File

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

View File

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

View File

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

View File

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

View File

@ -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> &parameterNames, asCArray<asCDataType> &parameterTypes, 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 )

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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 &paramType = 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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

@ -227,7 +227,7 @@ asCString asCDataType::Format(asSNameSpace *currNs, bool includeNamespace) const
str += "const";
}
if( isReference )
if( isReference )
str += "&";
return str;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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*>(&param1));
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);
}

View File

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

View File

@ -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> &paramTypes, const asCArray<asETypeModifiers> &paramInOut, 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;

View File

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

View File

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

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