modernize-cmake-1
Fiftytwo 2020-04-07 14:46:43 +02:00
commit e5d994b9e2
178 changed files with 6097 additions and 2628 deletions

4
.gitignore vendored
View File

@ -38,3 +38,7 @@ CMakeLists.txt.user.*
# Ignore Visual Studio Code files
/.vscode
# Ignore Visual Studio files
/CMakeSettings.json
/.vs

View File

@ -13,7 +13,7 @@ project(colobot C CXX)
set(COLOBOT_VERSION_CODENAME "Gold")
set(COLOBOT_VERSION_MAJOR 0)
set(COLOBOT_VERSION_MINOR 1)
set(COLOBOT_VERSION_REVISION 11)
set(COLOBOT_VERSION_REVISION 12)
# Used on official releases
#set(COLOBOT_VERSION_RELEASE_CODENAME "-alpha")
@ -60,6 +60,7 @@ if("${CMAKE_SYSTEM_NAME}" MATCHES "Windows")
set(PLATFORM_GNU 0)
set(PLATFORM_LINUX 0)
set(PLATFORM_MACOSX 0)
set(PLATFORM_FREEBSD 0)
set(PLATFORM_OTHER 0)
# Platform-dependent implementation of system.h
@ -71,6 +72,7 @@ elseif("${CMAKE_SYSTEM_NAME}" MATCHES "Linux")
set(PLATFORM_LINUX 1)
set(PLATFORM_GNU 1)
set(PLATFORM_MACOSX 0)
set(PLATFORM_FREEBSD 0)
set(PLATFORM_OTHER 0)
# Platform-dependent implementation of system.h
@ -82,6 +84,7 @@ elseif("${CMAKE_SYSTEM_NAME}" MATCHES "kFreeBSD" OR "${CMAKE_SYSTEM_NAME}" STREQ
set(PLATFORM_LINUX 0)
set(PLATFORM_GNU 1)
set(PLATFORM_MACOSX 0)
set(PLATFORM_FREEBSD 0)
set(PLATFORM_OTHER 0)
# Platform-dependent implementation of system.h
@ -94,18 +97,35 @@ elseif("${CMAKE_SYSTEM_NAME}" MATCHES "Darwin")
set(PLATFORM_GNU 0)
set(PLATFORM_MACOSX 1)
set(PLATFORM_OTHER 0)
set(PLATFORM_FREEBSD 0)
# Platform-dependent implementation of system.h
set(SYSTEM_CPP_MODULE "system_macosx.cpp")
set(SYSTEM_H_MODULE "system_macosx.h")
# To avoid CMake warning
set(CMAKE_MACOSX_RPATH 1)
elseif("${CMAKE_SYSTEM_NAME}" MATCHES "FreeBSD")
message(STATUS "Build for FreeBSD system")
set(PLATFORM_WINDOWS 0)
set(PLATFORM_LINUX 0)
set(PLATFORM_GNU 0)
set(PLATFORM_MACOSX 0)
set(PLATFORM_FREEBSD 1)
set(PLATFORM_OTHER 0)
# Platform-dependent implementation of system.h
# On FreeBSD we can use *_other
set(SYSTEM_CPP_MODULE "system_other.cpp")
set(SYSTEM_H_MODULE "system_other.h")
# To avoid CMake warning
set(CMAKE_MACOSX_RPATH 1)
else()
message(STATUS "Build for other system")
set(PLATFORM_WINDOWS 0)
set(PLATFORM_LINUX 0)
set(PLATFORM_GNU 0)
set(PLATFORM_MACOSX 0)
set(PLATFORM_FREEBSD 0)
set(PLATFORM_OTHER 1)
# Platform-dependent implementation of system.h
@ -124,6 +144,9 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
# Include cmake directory with some additional scripts
set(CMAKE_MODULE_PATH "${colobot_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
# MSVC needs different flags if linking statically
option(MSVC_STATIC "Link statically when using MSVC" OFF)
# Compiler detection
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.7)
@ -150,6 +173,10 @@ elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
message(STATUS "Detected Clang version 3.1+")
if (${PLATFORM_FREEBSD})
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=bfd")
endif()
set(NORMAL_CXX_FLAGS "-std=c++11 -Wall -Werror -Wold-style-cast -pedantic-errors -Wmissing-prototypes")
set(NORMAL_CXX_FLAGS "${NORMAL_CXX_FLAGS} -Wno-error=deprecated-declarations") # updated version of physfs is not available on some platforms so we keep using deprecated functions, see #958
set(RELEASE_CXX_FLAGS "-O2")
@ -160,14 +187,19 @@ elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
message(STATUS "Detected MSVC compiler")
set(NORMAL_CXX_FLAGS "/wd\"4244\" /wd\"4309\" /wd\"4800\" /wd\"4996\" /wd\"4351\" /EHsc") # disable some useless warnings
set(RELEASE_CXX_FLAGS "/MD")
set(DEBUG_CXX_FLAGS "/MDd /ZI")
if(MSVC_STATIC)
set(RELEASE_CXX_FLAGS "/MT /Ox")
set(DEBUG_CXX_FLAGS "/MTd /ZI")
else(MSVC_STATIC)
set(RELEASE_CXX_FLAGS "/MD /Ox")
set(DEBUG_CXX_FLAGS "/MDd /ZI")
endif()
set(TEST_CXX_FLAGS "")
add_definitions(-DNOEXCEPT= -DHAS_MSVC_EXCEPTION_BUG)
# Needed for Debug information (it's set to "No" by default for some reason)
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "/DEBUG")
set(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "/DEBUG")
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS} /DEBUG")
set(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_EXE_LINKER_FLAGS} /DEBUG")
else()
message(FATAL_ERROR "Your C++ compiler doesn't seem to be supported.")
endif()
@ -196,11 +228,14 @@ option(DEV_BUILD "Enable development build (enables some debugging tools, local
# Official build - changes text on the crash screen
# PLEASE DO NOT USE ON UNOFFICIAL BUILDS. Thanks.
option(OFFICIAL_BUILD "Official build (changes crash screen text)" OFF)
option(OFFICIAL_COLOBOT_BUILD "Official build (changes crash screen text)" OFF)
# Portable build - load all data from current directory
option(PORTABLE "Portable build" OFF)
# Portable saves - suitable for e.g. putting the whole game on external storage and moving your saves with it
option(PORTABLE_SAVES "Portable saves" OFF)
# Building tests can be enabled/disabled
option(TESTS "Build tests" OFF)
@ -312,6 +347,11 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
set(CBOT_STATIC 1) # only this works for some reason
set(WINGETOPT 1) # use wingetopt library
# Hide console in release builds
if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
set(CMAKE_WIN32_EXECUTABLE 1)
endif()
endif()
##
@ -350,21 +390,19 @@ endif()
##
# Installation paths defined before compiling sources
if(PLATFORM_WINDOWS)
if(MXE)
# We need to use STRING because PATH doesn't accept relative paths
set(COLOBOT_INSTALL_BIN_DIR ./ CACHE STRING "Colobot binary directory")
set(COLOBOT_INSTALL_LIB_DIR ./ CACHE STRING "Colobot libraries directory")
set(COLOBOT_INSTALL_DATA_DIR ./data CACHE STRING "Colobot shared data directory")
set(COLOBOT_INSTALL_I18N_DIR ./lang CACHE STRING "Colobot translations directory")
set(COLOBOT_INSTALL_DOC_DIR ./doc CACHE STRING "Colobot documentation directory")
else()
set(COLOBOT_INSTALL_BIN_DIR ${CMAKE_INSTALL_PREFIX}/ CACHE PATH "Colobot binary directory")
set(COLOBOT_INSTALL_LIB_DIR ${CMAKE_INSTALL_PREFIX}/ CACHE PATH "Colobot libraries directory")
set(COLOBOT_INSTALL_DATA_DIR ${CMAKE_INSTALL_PREFIX}/data CACHE PATH "Colobot shared data directory")
set(COLOBOT_INSTALL_I18N_DIR ${CMAKE_INSTALL_PREFIX}/lang CACHE PATH "Colobot translations directory")
set(COLOBOT_INSTALL_DOC_DIR ${CMAKE_INSTALL_PREFIX}/doc CACHE PATH "Colobot documentation directory")
endif()
if(PORTABLE OR (PLATFORM_WINDOWS AND MXE))
# We need to use STRING because PATH doesn't accept relative paths
set(COLOBOT_INSTALL_BIN_DIR ./ CACHE STRING "Colobot binary directory")
set(COLOBOT_INSTALL_LIB_DIR ./ CACHE STRING "Colobot libraries directory")
set(COLOBOT_INSTALL_DATA_DIR ./data CACHE STRING "Colobot shared data directory")
set(COLOBOT_INSTALL_I18N_DIR ./lang CACHE STRING "Colobot translations directory")
set(COLOBOT_INSTALL_DOC_DIR ./doc CACHE STRING "Colobot documentation directory")
elseif(PLATFORM_WINDOWS)
set(COLOBOT_INSTALL_BIN_DIR ${CMAKE_INSTALL_PREFIX}/ CACHE PATH "Colobot binary directory")
set(COLOBOT_INSTALL_LIB_DIR ${CMAKE_INSTALL_PREFIX}/ CACHE PATH "Colobot libraries directory")
set(COLOBOT_INSTALL_DATA_DIR ${CMAKE_INSTALL_PREFIX}/data CACHE PATH "Colobot shared data directory")
set(COLOBOT_INSTALL_I18N_DIR ${CMAKE_INSTALL_PREFIX}/lang CACHE PATH "Colobot translations directory")
set(COLOBOT_INSTALL_DOC_DIR ${CMAKE_INSTALL_PREFIX}/doc CACHE PATH "Colobot documentation directory")
elseif(PLATFORM_MACOSX)
set(COLOBOT_INSTALL_BIN_DIR ../MacOS CACHE STRING "Colobot binary directory")
set(COLOBOT_INSTALL_LIB_DIR ../MacOS CACHE STRING "Colobot libraries directory")

View File

@ -71,7 +71,7 @@ You will need:
On Ubuntu (and probably any other Debian-based system), you can use the following command to install all required packages:
```
$ apt-get install build-essential cmake libsdl2-dev libsdl2-image-dev libsdl2-ttf-dev libsndfile1-dev libvorbis-dev libogg-dev libpng12-dev libglew-dev libopenal-dev libboost-dev libboost-system-dev libboost-filesystem-dev libboost-regex-dev libphysfs-dev gettext git po4a vorbis-tools
$ apt-get install build-essential cmake libsdl2-dev libsdl2-image-dev libsdl2-ttf-dev libsndfile1-dev libvorbis-dev libogg-dev libpng-dev libglew-dev libopenal-dev libboost-dev libboost-system-dev libboost-filesystem-dev libboost-regex-dev libphysfs-dev gettext git po4a vorbis-tools
```
Make sure you install the packages along with header files (often distributed in separate *-dev packages). If you miss any requirements,

60
Jenkinsfile vendored
View File

@ -1,7 +1,7 @@
#!/usr/bin/env groovy
pipeline {
agent { label 'colobot-build' }
agent none
options {
buildDiscarder(logRotator(artifactDaysToKeepStr: '30', artifactNumToKeepStr: '20'))
}
@ -19,13 +19,17 @@ pipeline {
stage('Build') {
parallel {
stage('Build Windows') {
agent {
docker { image 'krzysh/colobot-build:latest' }
}
steps {
sh 'mkdir -p build/windows'
dir('build/windows') {
sh '''
cmake \
# FIXME: without -lsetupapi linking sdl2 fails
/opt/mxe/usr/bin/i686-w64-mingw32.static-cmake \
-DCMAKE_CXX_STANDARD_LIBRARIES="-lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32 -lsetupapi" \
-DCMAKE_INSTALL_PREFIX=/install \
-DCMAKE_TOOLCHAIN_FILE=/opt/mxe/usr/i686-w64-mingw32.static/share/cmake/mxe-conf.cmake \
-DCMAKE_BUILD_TYPE=RelWithDebInfo -DDEV_BUILD=1 -DPORTABLE=1 -DTOOLS=1 -DTESTS=0 ../..
make
rm -rf install
@ -42,14 +46,16 @@ pipeline {
}
stage('Build Linux') {
agent {
docker { image 'krzysh/colobot-build:latest' }
}
steps {
sh 'mkdir -p build/linux'
dir('build/linux') {
sh '''
cmake \
-DCMAKE_INSTALL_PREFIX=/install -DCOLOBOT_INSTALL_BIN_DIR=/install -DCOLOBOT_INSTALL_LIB_DIR=/install -DCOLOBOT_INSTALL_DATA_DIR=/install/data -DCOLOBOT_INSTALL_I18N_DIR=/install/lang -DCMAKE_SKIP_INSTALL_RPATH=ON \
-DBOOST_STATIC=ON -DGLEW_STATIC=ON -DGLEW_LIBRARY=/usr/lib64/libGLEW.a \
-DCMAKE_BUILD_TYPE=RelWithDebInfo -DDEV_BUILD=1 -DPORTABLE=1 -DTOOLS=1 -DTESTS=1 -DDESKTOP=0 ../..
-DCMAKE_INSTALL_PREFIX=/install -DCMAKE_SKIP_INSTALL_RPATH=ON \
-DCMAKE_BUILD_TYPE=RelWithDebInfo -DDEV_BUILD=1 -DPORTABLE=1 -DTOOLS=1 -DTESTS=1 -DDESKTOP=1 ../..
make
rm -rf install
DESTDIR=. make install
@ -60,7 +66,33 @@ pipeline {
post {
success {
sh 'rm -f linux-debug.zip'
zip zipFile: 'linux-debug.zip', archive: true, dir: 'build/linux/install'
dir('build/linux') {
sh '''
# Clean up
rm -rf squashfs-root
rm -rf colobot.AppDir
rm -rf appimage
rm -f Colobot-x86_64.AppImage
# Download app image tool
wget -N https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage
chmod +x linuxdeploy-x86_64.AppImage
./linuxdeploy-x86_64.AppImage --appimage-extract
# Create AppImage
NO_STRIP=1 ./squashfs-root/AppRun -e colobot --output appimage --appdir colobot.AppDir -d desktop/colobot.desktop -i ../../desktop/colobot.svg
#rename AppImage file to avoid "No such file or directory" errors
find . -maxdepth 1 -type f -name '*AppImage' -name 'Colobot*' -exec sh -c 'x="{}"; mv "$x" "Colobot-x86_64.AppImage"' \\;
chmod +x Colobot-x86_64.AppImage
# Prepare folder for zip
mkdir -p appimage
cp -rp install/data appimage/data
cp -rp install/lang appimage/lang
cp -p Colobot-x86_64.AppImage appimage/colobot
'''
}
zip zipFile: 'linux-debug.zip', archive: true, dir: 'build/linux/appimage'
}
}
}
@ -68,6 +100,9 @@ pipeline {
}
stage('Generate docs') {
agent {
docker { image 'krzysh/colobot-build:latest' }
}
steps {
dir('build/linux') {
sh 'make doc'
@ -81,6 +116,9 @@ pipeline {
}
stage('Run tests') {
agent {
docker { image 'krzysh/colobot-build:latest' }
}
steps {
dir('build/linux') {
sh './colobot_ut --gtest_output=xml:gtestresults.xml || true'
@ -91,6 +129,9 @@ pipeline {
}
stage('Run colobot-lint') {
agent {
label 'colobot-build'
}
environment {
CC = '/usr/lib/llvm-3.6/bin/clang'
CXX = '/usr/lib/llvm-3.6/bin/clang++'
@ -245,11 +286,10 @@ exit $ret
}
}
// TODO: cppcheck publisher STILL doesn't have pipeline support
// There is an open pull request though, merged but no release yet... https://github.com/jenkinsci/cppcheck-plugin/pull/36
publishCppcheck pattern: 'build/lint/colobot_lint_report.xml'
publishHTML([reportName: 'Colobot-lint HTML report', reportDir: 'build/lint/html_report', reportFiles: 'index.html', reportTitles: '', allowMissing: false, alwaysLinkToLastBuild: true, keepAll: true])
}
}
}
}

View File

@ -5,7 +5,7 @@
FIND_PATH(LIBSNDFILE_INCLUDE_DIR sndfile.h)
SET(LIBSNDFILE_NAMES ${LIBSNDFILE_NAMES} sndfile libsndfile)
SET(LIBSNDFILE_NAMES ${LIBSNDFILE_NAMES} sndfile libsndfile libsndfile-1)
FIND_LIBRARY(LIBSNDFILE_LIBRARY NAMES ${LIBSNDFILE_NAMES} PATH)
IF(LIBSNDFILE_INCLUDE_DIR AND LIBSNDFILE_LIBRARY)

View File

@ -7,7 +7,7 @@ IF (WIN32)
FIND_PATH( PHYSFS_INCLUDE_PATH physfs.h
DOC "The directory where physfs.h resides")
FIND_LIBRARY( PHYSFS_LIBRARY
NAMES physfs
NAMES physfs physfs-static
PATHS /mingw/lib
DOC "The PhysFS library")
ELSE (WIN32)

2
data

@ -1 +1 @@
Subproject commit b2792c325a6e6871311207559199f77f35bbe524
Subproject commit c467bd994e60fb54cf977fbe8583f92957330695

View File

@ -70,26 +70,18 @@ if(PLATFORM_GNU)
DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications/
)
# Install appdata
install(
FILES info.colobot.Colobot.appdata.xml
DESTINATION ${CMAKE_INSTALL_PREFIX}/share/metainfo/
)
# Install Icon
install(
FILES ${COLOBOT_ICON_FILE}
DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/scalable/apps/
)
# Translate translatable material
find_program(PO4A po4a)
if(NOT PO4A)
message(WARNING "po4a not found; desktop and manpage files will not be translated")
endif()
if(PO4A)
add_custom_target(desktop_po4a
COMMAND ${PO4A} po4a.cfg
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)
add_dependencies(desktopfile desktop_po4a)
endif()
# Create manpage from pod-formatted file
find_program(POD2MAN pod2man)
if(NOT POD2MAN)
@ -127,11 +119,30 @@ if(PLATFORM_GNU)
# Create the english manpage
podman(PODFILE colobot.pod)
# Translate translatable material
find_program(PO4A po4a)
if(NOT PO4A)
message(WARNING "po4a not found; desktop and manpage files will not be translated")
endif()
if(PO4A)
# Translate the manpage to other languages
add_dependencies(man desktop_po4a)
file(GLOB LINGUAS_PO RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/po/ ${CMAKE_CURRENT_SOURCE_DIR}/po/*.po)
string(REGEX REPLACE ".po$" "" LINGUAS ${LINGUAS_PO})
set(PO4A_OUTPUTS)
foreach(LOCALE ${LINGUAS})
list(APPEND PO4A_OUTPUTS ${CMAKE_CURRENT_SOURCE_DIR}/lang/${LOCALE}/colobot.pod)
endforeach()
add_custom_command(
OUTPUT ${PO4A_OUTPUTS}
COMMAND ${PO4A} po4a.cfg
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)
add_custom_target(desktop_po4a DEPENDS ${PO4A_OUTPUTS})
add_dependencies(man desktop_po4a)
add_dependencies(desktopfile desktop_po4a)
foreach(LOCALE ${LINGUAS})
podman(PODFILE lang/${LOCALE}/colobot.pod LOCALE ${LOCALE})
add_dependencies(man${PM_LOCALE} desktop_po4a)
@ -145,7 +156,12 @@ if(PLATFORM_MACOSX)
endif(PLATFORM_MACOSX)
if(PLATFORM_WINDOWS)
set(COLOBOT_VERSION_4COMMAS "${COLOBOT_VERSION_MAJOR},${COLOBOT_VERSION_MINOR},${COLOBOT_VERSION_REVISION},0")
if(COLOBOT_VERSION_REVISION MATCHES "([0-9]+)\\.([0-9]+)")
string(REGEX REPLACE "([0-9]+)\\.([0-9]+)" "\\1,\\2" COLOBOT_VERSION_REVISION_COMMA "${COLOBOT_VERSION_REVISION}")
set(COLOBOT_VERSION_4COMMAS "${COLOBOT_VERSION_MAJOR},${COLOBOT_VERSION_MINOR},${COLOBOT_VERSION_REVISION_COMMA}")
else()
set(COLOBOT_VERSION_4COMMAS "${COLOBOT_VERSION_MAJOR},${COLOBOT_VERSION_MINOR},${COLOBOT_VERSION_REVISION},0")
endif()
configure_file(colobot.rc.cmake ${CMAKE_CURRENT_BINARY_DIR}/colobot.rc)
endif(PLATFORM_WINDOWS)

View File

@ -1,4 +1,4 @@
Name="Colobot"
GenericName="Game to learn programming"
Comment="Colonize with bots"
Keywords="robots;3d;space;astronaut;java;c++"
Keywords="robots;3d;space;astronaut;java;c++;"

View File

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<component>
<id>info.colobot.Colobot</id>
<metadata_license>CC0-1.0</metadata_license>
<project_license>GPL-3.0</project_license>
<developer_name>TerranovaTeam</developer_name>
<update_contact>contact@colobot.info</update_contact>
<name>Colobot</name>
<summary>Colonize with bots</summary>
<description>
<p>Colobot (Colonize with Bots) is an educational game aiming to teach programming through entertainment. You are playing as an astronaut on a journey with robot helpers to find a planet for colonization. It features 3D real-time graphics and a C++ and Java-like, object-oriented language, CBOT, which can be used to program the robots available in the game.</p>
</description>
<launchable type="desktop-id">colobot.desktop</launchable>
<screenshots>
<screenshot type="default">
<caption>Alpha 0.1.5</caption>
<image type="source" height="600" width="800">https://colobot.info/wordpress/wp-content/uploads/alpha-0.1.5.png</image>
</screenshot>
</screenshots>
<url type="homepage">https://colobot.info/</url>
<url type="bugtracker">https://github.com/colobot/colobot/issues</url>
<url type="help">http://colobot.info/forum/</url>
<url type="donation">https://colobot.info/donate/</url>
<content_rating type="oars-1.1">
<content_attribute id="violence-cartoon">moderate</content_attribute>
<content_attribute id="violence-fantasy">moderate</content_attribute>
<content_attribute id="violence-bloodshed">mild</content_attribute>
</content_rating>
<releases>
<release date="2018-04-10" version="0.1.11.1"/>
</releases>
</component>

View File

@ -37,7 +37,7 @@ msgstr ""
#. type: Keywords=
#: colobot.ini:4
#, no-wrap
msgid "robots;3d;space;astronaut;java;c++"
msgid "robots;3d;space;astronaut;java;c++;"
msgstr ""
#. type: =head1

View File

@ -3,18 +3,20 @@
# This file is distributed under the same license as the Colobot package.
#
# Didier Raboud <odyx@debian.org>, 2012, 2016.
# B-CE <.>, 2019.
msgid ""
msgstr ""
"Project-Id-Version: colobot 0.1.7\n"
"Project-Id-Version: colobot 0.1.12\n"
"POT-Creation-Date: 2016-03-30 13:45+0200\n"
"PO-Revision-Date: 2016-03-30 13:49+0100\n"
"Last-Translator: Didier Raboud <odyx@debian.org>\n"
"PO-Revision-Date: 2019-06-01 09:43+0200\n"
"Last-Translator: BCE <.>\n"
"Language-Team: French <kde-i18n-doc@kde.org>\n"
"Language: fr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
"X-Generator: Lokalize 2.0\n"
"X-Generator: Lokalize 18.12.3\n"
#. type: Name=
#: colobot.ini:1
@ -32,13 +34,13 @@ msgstr "Apprentissage de la programmation par le jeu"
#: colobot.ini:3
#, no-wrap
msgid "Colonize with bots"
msgstr "Colonise avec des roBots"
msgstr "COlonise avec des roBOTs"
#. type: Keywords=
#: colobot.ini:4
#, no-wrap
msgid "robots;3d;space;astronaut;java;c++"
msgstr "robots;3d;espace;astronaute;cosmonaute;java;c++"
msgid "robots;3d;space;astronaut;java;c++;"
msgstr "robots;3d;espace;astronaute;cosmonaute;java;c++;programmation;jeux"
#. type: =head1
#: colobot.pod:3
@ -74,12 +76,12 @@ msgid ""
"real-time graphics and a C++ and Java-like, object-oriented language, CBOT, "
"which can be used to program the robots available in the game."
msgstr ""
"Colobot (Colonise avec des roBots) est un jeu éducatif visant à "
"l'enseignement de la programmation par le jeu. Vous jouez un astronaute en "
"Colobot (Colonise avec des roBots) est un jeu éducatif visant "
"à l'enseignement de la programmation par le jeu. Vous jouez un astronaute en "
"voyage avec des robots à la recherche d'une planète à coloniser. Son "
"interface est en trois-dimensions et en temps réel; le language utilisé "
"(CBOT) ressemble au C++ et à Java et peut être utilisé pour programmer les "
"robots disponibles dans le jeu."
"interface est en trois-dimensions et en temps réel. Le langage utilisé "
"(CBOT), orienté objet , ressemble au C++ et à Java. Il peut être utilisé "
"pour programmer les robots disponibles dans le jeu."
#. type: =head1
#: colobot.pod:19
@ -208,9 +210,9 @@ msgid ""
"Enable debug mode (more info printed in logs). Possible values are as "
"follows, as well as any comma-separated combination"
msgstr ""
"Active le mode de I<debug> (plus d'informations dans les logs). Les valeurs"
" possibles sont les suivantes, ainsi que toute combinaison séparée par des"
" virgules"
"Active le mode de I<debug> (plus d'informations dans les logs). "
"Les valeurs possibles sont les suivantes, "
"ainsi que toute combinaison séparée par des virgules"
#. type: =item
#: colobot.pod:81
@ -260,7 +262,7 @@ msgstr "models"
#. type: textblock
#: colobot.pod:99
msgid "Models-related debugging"
msgstr "Debug pour les modèles"
msgstr "Débug pour les modèles"
#. type: =item
#: colobot.pod:101
@ -270,7 +272,7 @@ msgstr "all"
#. type: textblock
#: colobot.pod:103
msgid "All above debugging statements"
msgstr "Tout les messages de debug ci-dessus"
msgstr "Tous les messages de debug ci-dessus"
#. type: =item
#: colobot.pod:107
@ -280,9 +282,7 @@ msgstr "B<-headless>"
#. type: textblock
#: colobot.pod:109
msgid "Run in headless mode - disables graphics, sound and user interaction"
msgstr ""
"Lance en mode I<headless> - désactive les graphiques, sons et interactions"
" utilisateurs"
msgstr "Lance en mode I<headless> - désactive les graphiques, sons et interactions utilisateurs"
#. type: =item
#: colobot.pod:111
@ -292,7 +292,7 @@ msgstr "B<-runscene> I<scenecodename>"
#. type: textblock
#: colobot.pod:113
msgid "Run given scene on start (skip menus)"
msgstr "Lance une scène donnée au lancement (saute les menus)"
msgstr "Démarre directement une scène (saute les menus)"
#. type: =item
#: colobot.pod:115
@ -317,7 +317,7 @@ msgstr "LC_MESSAGES"
#. type: textblock
#: colobot.pod:127
msgid "Used to determine the runtime language."
msgstr "Utilisé pour déterminer la langue au lancement"
msgstr "Utilisé pour déterminer la langue au lancement."
#. type: =head1
#: colobot.pod:131

View File

@ -266,6 +266,10 @@ msgstr ""
msgid "The battle has ended"
msgstr ""
#, c-format
msgid "Time: %s"
msgstr ""
#, c-format
msgid "%s: %d pts"
msgstr ""
@ -447,6 +451,9 @@ msgstr ""
msgid "Shadow resolution\\Higher means better range and quality, but slower"
msgstr ""
msgid "Vertical Synchronization\\Limits the number of frames per second to display frequency"
msgstr ""
msgid "Standard controls\\Standard key functions"
msgstr ""
@ -1788,6 +1795,12 @@ msgstr ""
msgid "Invalid universal character name"
msgstr ""
msgid "Empty character constant"
msgstr ""
msgid "Duplicate label in switch"
msgstr ""
msgid "Dividing by zero"
msgstr ""

View File

@ -8,7 +8,7 @@ msgstr ""
"Project-Id-Version: 0.1.11\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: DATE\n"
"PO-Revision-Date: 2018-02-24 20:39+01\n"
"PO-Revision-Date: 2018-08-20 22:48+02\n"
"Last-Translator: next_ghost <next_ghost@quick.cz>\n"
"Language-Team: Czech <next_ghost@quick.cz>\n"
"Language: Czech\n"
@ -489,6 +489,9 @@ msgstr "Dolů (\\key gdown;)"
msgid "Drawer bot"
msgstr "Tužkobot"
msgid "Duplicate label in switch"
msgstr ""
msgid "Dust\\Dust and dirt on bots and buildings"
msgstr "Prach\\Prach a špína na robotech a budovách"
@ -507,6 +510,9 @@ msgstr "Upravit vybraný program"
msgid "Egg"
msgstr "Vejce"
msgid "Empty character constant"
msgstr ""
msgid "End of block missing"
msgstr "Chybí konec bloku"
@ -1193,7 +1199,7 @@ msgid "Programming help\\Gives more detailed help with programming"
msgstr "Nápověda\\Zobrazí nápovědu pro psaní programů"
msgid "Programs dispatched by Houston"
msgstr "Program poslaný z Houstonu"
msgstr "Programy poslané z Houstonu"
msgid "Public required"
msgstr "Tato definice musí být veřejná (public)"
@ -1546,6 +1552,10 @@ msgstr "Úder (\\key action;)"
msgid "Thumper"
msgstr "Buchar"
#, c-format
msgid "Time: %s"
msgstr "Čas: %s"
msgid "Titanium"
msgstr "Titan"
@ -1660,6 +1670,9 @@ msgstr "Proměnná nebyla nastavena"
msgid "Vault"
msgstr "Trezor"
msgid "Vertical Synchronization\\Limits the number of frames per second to display frequency"
msgstr ""
msgid "Violet flag"
msgstr "Fialová vlajka"
@ -1737,7 +1750,7 @@ msgid "You cannot use \"%s\" in this exercise (used: %d)"
msgstr "V tomto cvičení nesmíte použít \"%s\" (použito: %dx)"
msgid "You found a usable object"
msgstr "Našli jste fungující objekt"
msgstr "Našli jste použitelný objekt"
#, c-format
msgid "You have to use \"%1$s\" at least once in this exercise (used: %2$d)"

View File

@ -490,6 +490,9 @@ msgstr "Sinkt (\\key gdown;)"
msgid "Drawer bot"
msgstr "Zeichner"
msgid "Duplicate label in switch"
msgstr ""
msgid "Dust\\Dust and dirt on bots and buildings"
msgstr "Schmutz\\Schmutz auf Robotern und Bauten"
@ -508,6 +511,9 @@ msgstr "Gewähltes Programm bearbeiten"
msgid "Egg"
msgstr "Ei"
msgid "Empty character constant"
msgstr ""
msgid "End of block missing"
msgstr "Es fehlt eine geschlossene geschweifte Klammer \"}\" (Ende des Blocks)"
@ -1563,6 +1569,10 @@ msgstr "Stampfen (\\key action;)"
msgid "Thumper"
msgstr "Stampfer"
#, c-format
msgid "Time: %s"
msgstr ""
msgid "Titanium"
msgstr "Titan"
@ -1677,6 +1687,9 @@ msgstr "Der Wert dieser Variable wurde nicht definiert"
msgid "Vault"
msgstr "Bunker"
msgid "Vertical Synchronization\\Limits the number of frames per second to display frequency"
msgstr ""
msgid "Violet flag"
msgstr "Violette Fahne"

175
po/fr.po
View File

@ -1,20 +1,21 @@
# Didier Raboud <odyx@debian.org>, 2012, 2015, 2016.
# Martin Quinson <mquinson@debian.org>, 2016
# B-CE, 2018
# Martin Quinson <mquinson@debian.org>, 2016.
# B-CE <.>, 2018, 2019.
# Pascal Audoux <pascal.audoux@gmail.com>, 2018.
msgid ""
msgstr ""
"Project-Id-Version: Colobot 0.1.11\n"
"Project-Id-Version: Colobot 0.1.12\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: DATE\n"
"PO-Revision-Date: 2018-02-28 20:00+0100\n"
"Last-Translator: B-CE\n"
"PO-Revision-Date: 2019-06-13 01:31+0200\n"
"Last-Translator: BCE <.>\n"
"Language-Team: French <>\n"
"Language: fr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
"X-Generator: Lokalize 2.0\n"
"X-Generator: Lokalize 18.12.3\n"
"X-Language: fr_FR\n"
"X-Source-Language: en_US\n"
@ -38,7 +39,7 @@ msgid "..in front"
msgstr "..devant"
msgid "..power cell"
msgstr "..pile"
msgstr "..batterie"
msgid "1) First click on the key you want to redefine."
msgstr "1) Cliquez d'abord sur la touche à redéfinir."
@ -140,10 +141,10 @@ msgid "Automatic indent\\When program editing"
msgstr "Indentation automatique\\Pendant l'édition d'un programme"
msgid "Autosave interval\\How often your game will autosave"
msgstr "Interval d'auto-sauvegarde\\À quels intervals les parties vont-t-elles êtres sauvegardées automatiquement"
msgstr "Interval auto-sauvegarde\\À quels intervals les parties vont-t-elles êtres sauvegardées automatiquement"
msgid "Autosave slots\\How many autosave slots you'll have"
msgstr "Nombre d'auto-sauvegardes\\Combien d'auto-sauvegarde seront conservées"
msgstr "Nb auto-sauvegardes\\Combien d'auto-sauvegarde seront conservées"
msgid "Autosave\\Enables autosave"
msgstr "Auto-sauvegarde\\Activer l'auto-sauvegarde"
@ -174,10 +175,10 @@ msgstr "Sang\\Afficher du sang quand le cosmonaute est touché"
msgid "Blue"
msgstr "Bleue"
# tocheck : for team (fem): bleue
# tocheck : for flag/pen/bot (masc): bleu
# + capital also to check
msgid "Blue flag"
msgstr "Drapeau bleu"
@ -185,13 +186,13 @@ msgid "Bot destroyed"
msgstr "Robot détruit"
msgid "Bot factory"
msgstr "Fabrique de robots"
msgstr "Usine de robots"
msgid "Build a bot factory"
msgstr "Construire une fabrique de robots"
msgstr "Construire une usine de robots"
msgid "Build a converter"
msgstr "Construire un convertisseur"
msgstr "Construire une raffinerie"
msgid "Build a defense tower"
msgstr "Construire une tour"
@ -203,10 +204,10 @@ msgid "Build a destroyer"
msgstr "Construire un destructeur"
msgid "Build a exchange post"
msgstr "Construire une borne d'information"
msgstr "Construire une station relais"
msgid "Build a legged grabber"
msgstr "Fabriquer un déménageur à pattes"
msgstr "Fabriquer un préhenseur à pattes"
msgid "Build a legged orga shooter"
msgstr "Fabriquer un tireur organique à pattes"
@ -224,10 +225,10 @@ msgid "Build a nuclear power plant"
msgstr "Construire une centrale nucléaire"
msgid "Build a phazer shooter"
msgstr "Fabriquer un robot canon à phases"
msgstr "Fabriquer un robot canon hachoir"
msgid "Build a power cell factory"
msgstr "Construire une fabrique de piles"
msgstr "Construire une fabrique de batteries"
msgid "Build a power station"
msgstr "Construire une station de recharge"
@ -254,7 +255,7 @@ msgid "Build a thumper"
msgstr "Fabriquer un robot secoueur"
msgid "Build a tracked grabber"
msgstr "Fabriquer un déménageur à chenilles"
msgstr "Fabriquer un préhenseur à chenilles"
msgid "Build a tracked orga shooter"
msgstr "Fabriquer un tireur organique à chenilles"
@ -266,7 +267,7 @@ msgid "Build a tracked sniffer"
msgstr "Fabriquer un renifleur à chenilles"
msgid "Build a wheeled grabber"
msgstr "Fabriquer un déménageur à roues"
msgstr "Fabriquer un préhenseur à roues"
msgid "Build a wheeled orga shooter"
msgstr "Fabriquer un tireur organique à roues"
@ -278,7 +279,7 @@ msgid "Build a wheeled sniffer"
msgstr "Fabriquer un renifleur à roues"
msgid "Build a winged grabber"
msgstr "Fabriquer un déménageur volant"
msgstr "Fabriquer un préhenseur volant"
msgid "Build a winged orga shooter"
msgstr "Fabriquer un tireur organique volant"
@ -314,19 +315,19 @@ msgid "Camera border scrolling\\Scrolling when the mouse touches right or left b
msgstr "Défilement dans les bords\\Défilement lorsque la souris touche les bords gauche ou droite"
msgid "Camera closer\\Moves the camera forward"
msgstr "Caméra plus proche\\Avance la caméra"
msgstr "Plus proche\\Avance la caméra"
msgid "Camera down\\Turns the camera down"
msgstr "Baisser caméra\\Baisse la caméra"
msgstr "Plus bas\\Tourne la caméra vers le bas"
msgid "Camera left\\Turns the camera left"
msgstr "Caméra à gauche\\Tourne la caméra vers la gauche"
msgstr "À gauche\\Tourne la caméra vers la gauche"
msgid "Camera right\\Turns the camera right"
msgstr "Caméra à droite\\Tourne la caméra vers la droite"
msgstr "À droite\\Tourne la caméra vers la droite"
msgid "Camera up\\Turns the camera up"
msgstr "Lever caméra\\Monte la caméra"
msgstr "Plus haut\\Tourne la caméra vers le haut"
msgid "Can not produce not researched object"
msgstr "Impossible de créer un objet n'ayant pas été recherché"
@ -365,7 +366,7 @@ msgid "Cheat console\\Show cheat console"
msgstr "Console de triche\\Montre la console de triche"
msgid "Checkpoint"
msgstr "Indicateur"
msgstr "Point de passage"
msgid "Class name expected"
msgstr "Nom de classe attendu"
@ -385,9 +386,8 @@ msgstr "Fermer"
msgid "Closing bracket missing"
msgstr "Il manque une parenthèse fermante"
#, fuzzy
msgid "Code battle"
msgstr "Batailles de code"
msgstr "Bataille de code"
msgid "Code battles"
msgstr "Batailles de code"
@ -420,7 +420,7 @@ msgid "Controls\\Keyboard, joystick and mouse settings"
msgstr "Commandes\\Touches du clavier"
msgid "Converts ore to titanium"
msgstr "Conversion de minerai en titane"
msgstr "Raffinage de minerai en titane"
msgid "Copy"
msgstr "Copier"
@ -492,6 +492,9 @@ msgstr "Descend (\\key gdown;)"
msgid "Drawer bot"
msgstr "Robot dessinateur"
msgid "Duplicate label in switch"
msgstr ""
msgid "Dust\\Dust and dirt on bots and buildings"
msgstr "Salissures\\Salissures des robots et bâtiments"
@ -502,7 +505,7 @@ msgid "Dynamic shadows ++\\Dynamic shadows + self shadowing"
msgstr "Ombres dynamiques ++\\Active les ombres dynamiques et l'auto-ombrage"
msgid "Dynamic shadows\\Beautiful shadows!"
msgstr "Ombres dynamiques\\Magnifiques ombres !"
msgstr "Ombres dynamiques\\Magnifiques ombres !"
msgid "Edit the selected program"
msgstr "Éditer le programme sélectionné"
@ -510,11 +513,14 @@ msgstr "Éditer le programme sélectionné"
msgid "Egg"
msgstr "Oeuf"
msgid "Empty character constant"
msgstr ""
msgid "End of block missing"
msgstr "Il manque la fin du bloc"
msgid "Energy deposit (site for power station)"
msgstr "Emplacement pour une station de recharge ou une fabrique de pile"
msgstr "Sous sol énergétique (Emplacement pour une station de recharge ou une fabrique de batteries)"
msgid "Energy level"
msgstr "Niveau d'énergie"
@ -566,10 +572,10 @@ msgstr "Séquences cinématiques\\Films avant ou après une mission"
msgid "Finish"
msgstr "But/Objectif"
# OBJECT_END : GoalArea
# OBJECT_END : GoalArea
msgid "Fixed mine"
msgstr "Mine fixe"
msgstr "Mine anti-personnel"
msgid "Flat ground not large enough"
msgstr "Sol plat pas assez grand"
@ -600,7 +606,7 @@ msgid "Found a site for a derrick"
msgstr "Emplacement pour un derrick trouvé"
msgid "Found a site for power station"
msgstr "Emplacement pour station de recharge ou fabrique de pile trouvé"
msgstr "Emplacement pour station de recharge ou fabrique de batteries trouvé"
msgid "Found key A (site for derrick)"
msgstr "Emplacement pour un derrick (clé A)"
@ -648,7 +654,7 @@ msgid "Generating"
msgstr "Génération"
msgid "Gold Edition development by:"
msgstr "Édition Gold développée par :"
msgstr "Édition Gold développée par :"
msgid "Goto: destination occupied"
msgstr "Goto: destination occupée"
@ -686,9 +692,8 @@ msgstr "Bulles d'aide\\Bulles explicatives"
msgid "Hex value out of range"
msgstr "Valeur hexadécimale impossible"
#, fuzzy
msgid "Higher speed\\Doubles speed"
msgstr "Vitesse 2.0x\\Deux fois plus rapide"
msgstr "Vitesse augmentée\\Deux fois plus rapide"
msgid "Highest\\Highest graphic quality (lowest frame rate)"
msgstr "Maxi\\Haute qualité (+ lent)"
@ -721,7 +726,7 @@ msgid "Inappropriate bot"
msgstr "Robot inadapté"
msgid "Inappropriate cell type"
msgstr "Pas le bon type de pile"
msgstr "Source d'énergie non adapté"
msgid "Inappropriate object"
msgstr "Pas le bon objet"
@ -733,7 +738,7 @@ msgid "Infected by a virus; temporarily out of order"
msgstr "Infecté par un virus; ne fonctionne plus temporairement"
msgid "Information exchange post"
msgstr "Borne d'information"
msgstr "Station relais"
msgid "Instruction \"break\" outside a loop"
msgstr "Instruction \"break\" en dehors d'une boucle"
@ -796,7 +801,7 @@ msgid "LOADING"
msgstr "CHARGEMENT"
msgid "Legged grabber"
msgstr "Robot déménageur à pattes"
msgstr "Robot préhenseur à pattes"
msgid "Legged orga shooter"
msgstr "Robot tireur organique à pattes"
@ -832,7 +837,7 @@ msgid "Loading basic level settings"
msgstr "Chargement des configurations de base du niveau"
msgid "Loading finished!"
msgstr "Chargement terminé !"
msgstr "Chargement terminé !"
msgid "Loading music"
msgstr "Chargement de la musique"
@ -857,7 +862,6 @@ msgstr "Chargement du terrain"
# msgstr ""
# msgid "Speed 6.0x\\Sextuple speed"
# msgstr ""
msgid "Lower speed\\Decrease speed by half"
msgstr "Moins rapide\\Diminuer la vitesse de moitié"
@ -868,7 +872,7 @@ msgid "Lunar Roving Vehicle"
msgstr "Véhicule d'exploration lunaire"
msgid "MSAA\\Multisample anti-aliasing"
msgstr "ACME\\Anticrénelage multiéchantillon"
msgstr "ACME\\Anticrénelage multiéchantillon (MSAA: Multisample anti-aliasing)"
msgid "Maximize"
msgstr "Taille maximale"
@ -955,7 +959,7 @@ msgid "No function with this name accepts this number of parameters"
msgstr "Aucune fonction de ce nom n'accepte ce nombre de paramètres"
msgid "No information exchange post within range"
msgstr "Pas de borne d'information accessible"
msgstr "Pas de station relais accessible"
msgid "No more energy"
msgstr "Plus d'énergie"
@ -964,7 +968,7 @@ msgid "No ore in the subsoil"
msgstr "Pas de minerai en sous-sol"
msgid "No power cell"
msgstr "Pas de pile"
msgstr "Pas de source d'énergie"
msgid "No titanium"
msgstr "Pas de titane"
@ -973,7 +977,7 @@ msgid "No titanium around"
msgstr "Pas de titane accessible"
msgid "No titanium ore to convert"
msgstr "Pas de minerai de titane à convertir"
msgstr "Pas de minerai de titane à raffiner"
msgid "No titanium to transform"
msgstr "Pas de titane à transformer"
@ -982,7 +986,7 @@ msgid "No uranium to transform"
msgstr "Pas de minerai d'uranium à transformer"
msgid "No userlevels installed!"
msgstr "Pas de niveaux spéciaux installés !"
msgstr "Pas de niveaux spéciaux installés !"
msgid "Non-void function needs \"return;\""
msgstr "Les fonctions avec retour autre que void doivent comporter l'instruction \"return;\""
@ -1018,10 +1022,10 @@ msgid "Nothing to recycle"
msgstr "Rien à recycler"
msgid "Nuclear power cell"
msgstr "Pile nucléaire"
msgstr "Pile atomique"
msgid "Nuclear power cell available"
msgstr "Pile nucléaire disponible"
msgstr "Pile atomique disponible"
msgid "Nuclear power station"
msgstr "Centrale nucléaire"
@ -1042,7 +1046,7 @@ msgid "OK\\Choose the selected player"
msgstr "D'accord\\Choisir le joueur"
msgid "OK\\Close program editor and return to game"
msgstr "D'accord\\Compiler le programme"
msgstr "D'accord\\Compiler le programme et fermer la fenêtre d'édition"
msgid "Object too close"
msgstr "Objet trop proche"
@ -1105,7 +1109,7 @@ msgid "Pause\\Pause the game without opening menu"
msgstr "Pause\\Mettre le jeu en pause sans ouvrir le menu"
msgid "Phazer shooter"
msgstr "Robot canon à phases"
msgstr "Robot canon hachoir"
msgid "Photography"
msgstr "Vue de la mission"
@ -1123,7 +1127,7 @@ msgid "Plans for nuclear power plant available"
msgstr "Construction d'une centrale nucléaire possible"
msgid "Plans for phazer shooter available"
msgstr "Fabrication des robots canon à phases possible"
msgstr "Fabrication des robots canon hachoir possible"
msgid "Plans for shielder available"
msgstr "Fabrication d'un robot bouclier possible"
@ -1153,13 +1157,13 @@ msgid "Player's name"
msgstr "Nom du joueur"
msgid "Power cell"
msgstr "Pile normale"
msgstr "Batterie standard"
msgid "Power cell available"
msgstr "Pile disponible"
msgstr "Batterie disponible"
msgid "Power cell factory"
msgstr "Fabrique de piles"
msgstr "Fabrique de batteries"
msgid "Power station"
msgstr "Station de recharge"
@ -1230,15 +1234,14 @@ msgstr "Chargement rapide\\Chargement direct d'une sauvegarde"
msgid "Quick save\\Immediately save game"
msgstr "Sauvegarde rapide\\Sauvegarde direct"
#, fuzzy
msgid "Quicksave slot not found"
msgstr "Objet n'existe pas"
msgstr "Emplacement de sauvegarde rapide non trouvé"
msgid "Quit\\Quit Colobot: Gold Edition"
msgstr "Quitter\\Quitter Colobot : Édition Gold"
msgstr "Quitter\\Quitter Colobot : Édition Gold"
msgid "Quit\\Quit the current mission or exercise"
msgstr "Quitter la mission en cours\\Terminer un exercice ou une mssion"
msgstr "Quitter la mission en cours\\Terminer un exercice ou une mission"
msgid "Radar station"
msgstr "Radar"
@ -1257,8 +1260,8 @@ msgstr "Robot recycleur"
msgid "Red"
msgstr "Rouge"
# toCheck : capital (for team?)
# toCheck : capital (for team?)
msgid "Red flag"
msgstr "Drapeau rouge"
@ -1323,34 +1326,34 @@ msgid "Ruin"
msgstr "Bâtiment en ruine"
msgid "Run research program for defense tower"
msgstr "Recherche la tour de défense"
msgstr "Lancer la recherche de la tour de défense"
msgid "Run research program for legged bots"
msgstr "Recherche du fonctionnement des pattes"
msgstr "Lancer la recherche du fonctionnement des pattes"
msgid "Run research program for nuclear power"
msgstr "Recherche du programme nucléaire"
msgstr "Lancer la recherche du programme nucléaire"
msgid "Run research program for orga shooter"
msgstr "Recherche le canon organique"
msgstr "Lancer la recherche du canon organique"
msgid "Run research program for phazer shooter"
msgstr "Recherche le canon à phases"
msgstr "Lancer la recherche du canon hachoir"
msgid "Run research program for shielder"
msgstr "Recherche le bouclier"
msgstr "Lancer la recherche du bouclier"
msgid "Run research program for shooter"
msgstr "Recherche le canon de tir"
msgstr "Lancer la recherche du canon de tir"
msgid "Run research program for thumper"
msgstr "Recherche le secoueur"
msgstr "Lancer la recherche du secoueur"
msgid "Run research program for tracked bots"
msgstr "Recherche du fonctionnement des chenilles"
msgstr "Lancer la recherche du fonctionnement des chenilles"
msgid "Run research program for winged bots"
msgstr "Recherche du fonctionnement du jet"
msgstr "Lancer la recherche du fonctionnement du jet"
msgid "SatCom"
msgstr "SatCom"
@ -1443,7 +1446,7 @@ msgid "Spaceship"
msgstr "Vaisseau spatial"
msgid "Spaceship ruin"
msgstr "Epave de vaisseau spatial"
msgstr "Épave de vaisseau spatial"
msgid "Spider"
msgstr "Araignée"
@ -1500,7 +1503,7 @@ msgid "Switch bots <-> buildings"
msgstr "Permute robots <-> bâtiments"
msgid "Take off to finish the mission"
msgstr "Décolle pour terminer la mission"
msgstr "Décollage pour terminer la mission"
msgid "Target"
msgstr "Cible"
@ -1563,11 +1566,15 @@ msgid "This program is read-only, clone it to edit"
msgstr "Ce programme est en lecture-seule, le dupliquer pour pouvoir le modifier"
msgid "Thump (\\key action;)"
msgstr "Secoue (\\key action;)"
msgstr "Secouer (\\key action;)"
msgid "Thumper"
msgstr "Robot secoueur"
#, c-format
msgid "Time: %s"
msgstr "Temps : %s"
msgid "Titanium"
msgstr "Titane"
@ -1602,7 +1609,7 @@ msgid "Too many parameters"
msgstr "Trop de paramètres"
msgid "Tracked grabber"
msgstr "Robot déménageur à chenilles"
msgstr "Robot préhenseur à chenilles"
msgid "Tracked orga shooter"
msgstr "Robot tireur organique à chenilles"
@ -1653,7 +1660,7 @@ msgid "Unknown command"
msgstr "Commande inconnue"
msgid "Unknown escape sequence"
msgstr ""
msgstr "Séquence d'échappement inconnue"
msgid "Unknown function"
msgstr "Routine inconnue"
@ -1682,6 +1689,9 @@ msgstr "Variable non initialisée"
msgid "Vault"
msgstr "Coffre-fort"
msgid "Vertical Synchronization\\Limits the number of frames per second to display frequency"
msgstr "Synchronisation verticale :\\Réduit la fréquence d'images par seconde à afficher."
msgid "Violet flag"
msgstr "Drapeau violet"
@ -1698,7 +1708,7 @@ msgid "Waste"
msgstr "Déchet"
msgid "Wheeled grabber"
msgstr "Robot déménageur à roues"
msgstr "Robot préhenseur à roues"
msgid "Wheeled orga shooter"
msgstr "Robot tireur organique à roues"
@ -1710,7 +1720,7 @@ msgid "Wheeled sniffer"
msgstr "Robot renifleur à roues"
msgid "Winged grabber"
msgstr "Robot déménageur volant"
msgstr "Robot préhenseur volant"
msgid "Winged orga shooter"
msgstr "Robot tireur organique volant"
@ -1731,7 +1741,7 @@ msgid "Worm fatally wounded"
msgstr "Ver mortellement touché"
msgid "Wreckage"
msgstr "Epave de robot"
msgstr "Épave de robot"
msgid "Write error"
msgstr "Erreur lors de l'écriture"
@ -1816,7 +1826,7 @@ msgid "\\New player name"
msgstr "\\Nom du joueur à créer"
msgid "\\No eyeglasses"
msgstr "\\Pas de lunettes"
msgstr "\\Pas de lunette"
msgid "\\Raise the pencil"
msgstr "\\Relève le crayon"
@ -1825,7 +1835,7 @@ msgid "\\Red flags"
msgstr "\\Drapeaux rouges"
msgid "\\Return to Colobot: Gold Edition"
msgstr "\\Revenir à Colobot : Édition Gold"
msgstr "\\Revenir à Colobot : Édition Gold"
msgid "\\SatCom on standby"
msgstr "\\Mettre le SatCom en veille"
@ -1878,9 +1888,6 @@ msgstr "colobot.info"
msgid "epsitec.com"
msgstr "epsitec.com"
#~ msgid " "
#~ msgstr " "
#~ msgid " Drivers:"
#~ msgstr " Pilotes :"

View File

@ -365,7 +365,7 @@ msgid "Checkpoint"
msgstr "Punkt kontrolny"
msgid "Class name expected"
msgstr ""
msgstr "Oczekiwano nazwy klasy"
msgid "Climb\\Increases the power of the jet"
msgstr "W górę\\Zwiększa moc silnika"
@ -488,6 +488,9 @@ msgstr "Dół (\\key gdown;)"
msgid "Drawer bot"
msgstr "Robot rysownik"
msgid "Duplicate label in switch"
msgstr ""
msgid "Dust\\Dust and dirt on bots and buildings"
msgstr "Kurz\\Kurz i bród na robotach i budynkach"
@ -506,6 +509,9 @@ msgstr "Edytuj zaznaczony program"
msgid "Egg"
msgstr "Jajo"
msgid "Empty character constant"
msgstr ""
msgid "End of block missing"
msgstr "Brak końca bloku"
@ -628,7 +634,7 @@ msgid "Function name missing"
msgstr "Brakująca nazwa funkcji"
msgid "Function needs return type \"void\""
msgstr ""
msgstr "Funkcja potrzebuje typu zwracanego \"void\""
msgid "Game speed"
msgstr "Prędkość gry"
@ -679,7 +685,7 @@ msgid "Help balloons\\Explain the function of the buttons"
msgstr "Dymki pomocy\\Wyjaśnia funkcje przycisków"
msgid "Hex value out of range"
msgstr ""
msgstr "Wartość heksadecymalna poza zakresem"
msgid "Higher speed\\Doubles speed"
msgstr "Zwiększ prędkość\\Podwaja prędkość"
@ -859,10 +865,10 @@ msgid "Mipmap level\\Mipmap level"
msgstr "Poziom mipmap\\Poziom mipmap"
msgid "Missing end quote"
msgstr ""
msgstr "Brak cudzysłowu zamykającego"
msgid "Missing hex digits after escape sequence"
msgstr ""
msgstr "Brak cyfr heksadecymalnych po znaku ucieczki"
msgid "Mission name"
msgstr "Nazwa misji"
@ -964,7 +970,7 @@ msgid "No userlevels installed!"
msgstr "Brak zainstalowanych poziomów użytkownika!"
msgid "Non-void function needs \"return;\""
msgstr ""
msgstr "Funkcja zwracająca typ inny, niż \"void\", wymaga \"return;\""
msgid "Normal size"
msgstr "Normalna wielkość"
@ -1027,7 +1033,7 @@ msgid "Object too close"
msgstr "Obiekt za blisko"
msgid "Octal value out of range"
msgstr ""
msgstr "Wartość ósemkowa poza zakresem"
msgid "One step"
msgstr "Jeden krok"
@ -1072,7 +1078,7 @@ msgid "Paste (Ctrl+V)"
msgstr "Wklej (Ctrl+V)"
msgid "Pause blur\\Blur the background on the pause screen"
msgstr ""
msgstr "Rozmyta pauza\\Rozmyj tło na ekranie pauzy"
msgid "Pause in background\\Pause the game when the window is unfocused"
msgstr "Wstrzymaj w tle\\Wstrzymaj grę gdy okno stanie się nieaktywne"
@ -1534,7 +1540,7 @@ msgid "This object is not a member of a class"
msgstr "Ten obiekt nie jest członkiem klasy"
msgid "This parameter needs a default value"
msgstr ""
msgstr "Ten parametr wymaga podania domyślnej wartości"
msgid "This program is read-only, clone it to edit"
msgstr "Ten program jest tylko do odczytu, skopiuj go, aby edytować"
@ -1545,6 +1551,10 @@ msgstr "Uderz (\\key action;)"
msgid "Thumper"
msgstr "Uderzacz"
#, c-format
msgid "Time: %s"
msgstr "Czas: %s"
msgid "Titanium"
msgstr "Tytan"
@ -1659,6 +1669,9 @@ msgstr "Zmienna nie została zainicjalizowana"
msgid "Vault"
msgstr "Skrytka"
msgid "Vertical Synchronization\\Limits the number of frames per second to display frequency"
msgstr "Synchronizacja pionowa\\Ogranicza ilość klatek na sekundę do wartości odświeżania ekranu"
msgid "Violet flag"
msgstr "Fioletowa flaga"

2055
po/pt.po Normal file

File diff suppressed because it is too large Load Diff

View File

@ -496,6 +496,9 @@ msgstr "Вниз (\\key gdown;)"
msgid "Drawer bot"
msgstr "Рисовальщик"
msgid "Duplicate label in switch"
msgstr ""
msgid "Dust\\Dust and dirt on bots and buildings"
msgstr "Пыль\\Пыль и грязь на ботах и зданиях"
@ -514,6 +517,9 @@ msgstr "Изменить выбранную программу"
msgid "Egg"
msgstr "Яйцо"
msgid "Empty character constant"
msgstr ""
msgid "End of block missing"
msgstr "Отсутствует конец блока"
@ -1576,6 +1582,10 @@ msgstr "Удар (\\key action;)"
msgid "Thumper"
msgstr "Ударник"
#, c-format
msgid "Time: %s"
msgstr ""
msgid "Titanium"
msgstr "Титан"
@ -1690,6 +1700,9 @@ msgstr "Переменная не инициализирована"
msgid "Vault"
msgstr "Хранилище"
msgid "Vertical Synchronization\\Limits the number of frames per second to display frequency"
msgstr ""
msgid "Violet flag"
msgstr "Фиолетовый флаг"

View File

@ -36,7 +36,6 @@
#include "CBot/CBotCStack.h"
#include "CBot/CBotDefParam.h"
#include "CBot/CBotUtils.h"
#include "CBot/CBotFileUtils.h"
#include <algorithm>
@ -364,69 +363,70 @@ void CBotClass::RestoreMethode(long& nIdent,
}
////////////////////////////////////////////////////////////////////////////////
bool CBotClass::SaveStaticState(FILE* pf)
bool CBotClass::SaveStaticState(std::ostream &ostr)
{
if (!WriteWord( pf, CBOTVERSION*2)) return false;
if (!WriteLong(ostr, CBOTVERSION*2)) return false;
// saves the state of static variables in classes
for (CBotClass* p : m_publicClasses)
{
if (!WriteWord( pf, 1 )) return false;
if (!WriteWord(ostr, 1)) return false;
// save the name of the class
if (!WriteString( pf, p->GetName() )) return false;
if (!WriteString(ostr, p->GetName())) return false;
CBotVar* pv = p->GetVar();
while( pv != nullptr )
{
if ( pv->IsStatic() )
{
if (!WriteWord( pf, 1 )) return false;
if (!WriteString( pf, pv->GetName() )) return false;
if (!WriteWord(ostr, 1)) return false;
if (!WriteString(ostr, pv->GetName())) return false;
if ( !pv->Save0State(pf) ) return false; // common header
if ( !pv->Save1State(pf) ) return false; // saves as the child class
if ( !WriteWord( pf, 0 ) ) return false;
if (!pv->Save0State(ostr)) return false; // common header
if (!pv->Save1State(ostr)) return false; // saves as the child class
if (!WriteWord(ostr, 0)) return false;
}
pv = pv->GetNext();
}
if (!WriteWord( pf, 0 )) return false;
if (!WriteWord(ostr, 0)) return false;
}
if (!WriteWord( pf, 0 )) return false;
if (!WriteWord(ostr, 0)) return false;
return true;
}
////////////////////////////////////////////////////////////////////////////////
bool CBotClass::RestoreStaticState(FILE* pf)
bool CBotClass::RestoreStaticState(std::istream &istr)
{
std::string ClassName, VarName;
CBotClass* pClass;
unsigned short w;
if (!ReadWord( pf, w )) return false;
if ( w != CBOTVERSION*2 ) return false;
long version;
if (!ReadLong(istr, version)) return false;
if (version != CBOTVERSION*2) return false;
while (true)
{
if (!ReadWord( pf, w )) return false;
if (!ReadWord(istr, w)) return false;
if ( w == 0 ) return true;
if (!ReadString( pf, ClassName )) return false;
if (!ReadString(istr, ClassName)) return false;
pClass = Find(ClassName);
while (true)
{
if (!ReadWord( pf, w )) return false;
if (!ReadWord(istr, w)) return false;
if ( w == 0 ) break;
CBotVar* pVar = nullptr;
CBotVar* pv = nullptr;
if (!ReadString( pf, VarName )) return false;
if (!ReadString(istr, VarName)) return false;
if ( pClass != nullptr ) pVar = pClass->GetItem(VarName);
if (!CBotVar::RestoreState(pf, pv)) return false; // the temp variable
if (!CBotVar::RestoreState(istr, pv)) return false; // the temp variable
if ( pVar != nullptr ) pVar->Copy(pv);
delete pv;

View File

@ -331,18 +331,18 @@ public:
static void ClearPublic();
/*!
* \brief SaveStaticState
* \param pf
* \return
* \brief Save all static variables from each public class
* \param ostr Output stream
* \return true on success
*/
static bool SaveStaticState(FILE* pf);
static bool SaveStaticState(std::ostream &ostr);
/*!
* \brief RestoreStaticState
* \param pf
* \return
* \brief Restore all static variables in each public class
* \param istr Input stream
* \return true on success
*/
static bool RestoreStaticState(FILE* pf);
static bool RestoreStaticState(std::istream &istr);
/**
* \brief Request a lock on this class (for "synchronized" keyword)

View File

@ -23,6 +23,7 @@
#include "CBot/CBotInstr/CBotFunction.h"
#include "CBot/CBotInstr/CBotInstrCall.h"
#include <functional>
#include <sstream>
#include <iostream>
#include <iomanip>

View File

@ -173,14 +173,34 @@ bool CBotDefParam::Execute(CBotVar** ppVars, CBotStack* &pj)
{
switch (p->m_type.GetType())
{
case CBotTypByte:
newvar->SetValByte(pVar->GetValByte());
newvar->SetInit(pVar->GetInit()); // copy nan
break;
case CBotTypShort:
newvar->SetValShort(pVar->GetValShort());
newvar->SetInit(pVar->GetInit()); // copy nan
break;
case CBotTypChar:
newvar->SetValChar(pVar->GetValChar());
newvar->SetInit(pVar->GetInit()); // copy nan
break;
case CBotTypInt:
newvar->SetValInt(pVar->GetValInt());
newvar->SetInit(pVar->GetInit()); // copy nan
break;
case CBotTypLong:
newvar->SetValLong(pVar->GetValLong());
newvar->SetInit(pVar->GetInit()); // copy nan
break;
case CBotTypFloat:
newvar->SetValFloat(pVar->GetValFloat());
newvar->SetInit(pVar->GetInit()); // copy nan
break;
case CBotTypDouble:
newvar->SetValDouble(pVar->GetValDouble());
newvar->SetInit(pVar->GetInit()); // copy nan
break;
case CBotTypString:
newvar->SetValString(pVar->GetValString());
break;

View File

@ -35,13 +35,13 @@ namespace CBot
enum CBotType
{
CBotTypVoid = 0, //!< void
CBotTypByte = 1, //!< byte (NOT IMPLEMENTED)
CBotTypShort = 2, //!< short (NOT IMPLEMENTED)
CBotTypChar = 3, //!< char (NOT IMPLEMENTED)
CBotTypByte = 1, //!< byte
CBotTypShort = 2, //!< short
CBotTypChar = 3, //!< char
CBotTypInt = 4, //!< int
CBotTypLong = 5, //!< long (NOT IMPLEMENTED)
CBotTypLong = 5, //!< long
CBotTypFloat = 6, //!< float
CBotTypDouble = 7, //!< double (NOT IMPLEMENTED)
CBotTypDouble = 7, //!< double
CBotTypBoolean = 8, //!< bool
CBotTypString = 9, //!< string
@ -106,6 +106,11 @@ enum TokenId
ID_STRING,
ID_VOID,
ID_BOOL,
ID_BYTE,
ID_SHORT,
ID_CHAR,
ID_LONG,
ID_DOUBLE,
TokenKeyVal = 2200, //!< keywords that represent values (true, false, null, nan)
ID_TRUE = 2200,
@ -177,7 +182,8 @@ enum TokenType
TokenTypNum = 2, //!< number
TokenTypString = 3, //!< string
TokenTypVar = 4, //!< a variable name
TokenTypDef = 5 //!< value according DefineNum
TokenTypDef = 5, //!< value according DefineNum
TokenTypChar = 6, //!< character literal
};
/**
@ -247,6 +253,8 @@ enum CBotError : int
CBotErrHexDigits = 5052, //!< missing hex digits after escape sequence
CBotErrHexRange = 5053, //!< hex value out of range
CBotErrUnicodeName = 5054, //!< invalid universal character name
CBotErrCharEmpty = 5055, //!< empty character constant
CBotErrRedefCase = 5056, //!< duplicate label in switch
// Runtime errors
CBotErrZeroDiv = 6000, //!< division by zero

View File

@ -21,129 +21,261 @@
#include "CBot/CBotClass.h"
#include "CBot/CBotEnums.h"
#include "CBot/CBotUtils.h"
namespace CBot
{
// file management
// necessary because it is not possible to do the fopen in the main program
// fwrite and fread in a dll or using the FILE * returned.
////////////////////////////////////////////////////////////////////////////////
FILE* fOpen(const char* name, const char* mode)
template<typename T>
static bool WriteBinary(std::ostream &ostr, T value, unsigned padTo = 0)
{
return fopen(name, mode);
}
////////////////////////////////////////////////////////////////////////////////
int fClose(FILE* filehandle)
{
return fclose(filehandle);
}
////////////////////////////////////////////////////////////////////////////////
std::size_t fWrite(const void *buffer,
std::size_t elemsize,
std::size_t length,
FILE* filehandle)
{
return fwrite(buffer, elemsize, length, filehandle);
}
////////////////////////////////////////////////////////////////////////////////
std::size_t fRead(void *buffer,
std::size_t elemsize,
std::size_t length,
FILE* filehandle)
{
return fread(buffer, elemsize, length, filehandle);
}
////////////////////////////////////////////////////////////////////////////////
bool ReadWord(FILE* pf, unsigned short& w)
{
size_t lg;
lg = fread(&w, sizeof( unsigned short ), 1, pf );
return (lg == 1);
}
////////////////////////////////////////////////////////////////////////////////
bool ReadFloat(FILE* pf, float& w)
{
size_t lg;
lg = fread(&w, sizeof( float ), 1, pf );
return (lg == 1);
}
////////////////////////////////////////////////////////////////////////////////
bool WriteLong(FILE* pf, long w)
{
size_t lg;
lg = fwrite(&w, sizeof( long ), 1, pf );
return (lg == 1);
}
////////////////////////////////////////////////////////////////////////////////
bool ReadLong(FILE* pf, long& w)
{
size_t lg;
lg = fread(&w, sizeof( long ), 1, pf );
return (lg == 1);
}
////////////////////////////////////////////////////////////////////////////////
bool ReadString(FILE* pf, std::string& s)
{
unsigned short w;
char buf[1000];
size_t lg1, lg2;
if (!ReadWord(pf, w)) return false;
lg1 = w;
lg2 = fread(buf, 1, lg1, pf );
buf[lg2] = 0;
s = buf;
return (lg1 == lg2);
}
////////////////////////////////////////////////////////////////////////////////
bool WriteType(FILE* pf, const CBotTypResult &type)
{
int typ = type.GetType();
if ( typ == CBotTypIntrinsic ) typ = CBotTypClass;
if ( !WriteWord(pf, typ) ) return false;
if ( typ == CBotTypClass )
unsigned char chr;
unsigned count = 1;
while (value > 127) // unsigned LEB128
{
CBotClass* p = type.GetClass();
if ( !WriteString(pf, p->GetName()) ) return false;
++count;
chr = (value & 0x7F) | 0x80;
if (!ostr.write(reinterpret_cast<char*>(&chr), 1)) return false;
value >>= 7;
}
if ( type.Eq( CBotTypArrayBody ) ||
type.Eq( CBotTypArrayPointer ) )
chr = value & 0x7F;
if (count < padTo) chr |= 0x80;
if (!ostr.write(reinterpret_cast<char*>(&chr), 1)) return false;
if (count < padTo)
{
if ( !WriteWord(pf, type.GetLimite()) ) return false;
if ( !WriteType(pf, type.GetTypElem()) ) return false;
while (++count < padTo)
if (!(ostr << '\x80')) return false;
if (!(ostr << '\x00')) return false;
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
bool ReadType(FILE* pf, CBotTypResult &type)
template<typename T>
static bool ReadBinary(std::istream &istr, T &value)
{
value = 0;
unsigned char chr;
unsigned shift = 0;
while (true) // unsigned LEB128
{
if (!istr.read(reinterpret_cast<char*>(&chr), 1)) return false;
if (shift < sizeof(T) * 8 - 1)
value |= static_cast<T>(chr & 0x7F) << shift;
shift += 7;
if ((chr & 0x80) == 0) break;
}
return true;
}
template<typename T>
static bool WriteSignedBinary(std::ostream &ostr, T value, unsigned padTo = 0)
{
signed char sign = value >> (8 * sizeof(T) - 1);
unsigned count = 0;
while (true) // signed LEB128
{
++count;
unsigned char chr = value & 0x7F;
value >>= 7;
if (!(value != sign || ((chr ^ sign) & 0x40) != 0))
{
if (count < padTo) chr |= 0x80;
if (!ostr.write(reinterpret_cast<char*>(&chr), 1)) return false;
break;
}
chr |= 0x80;
if (!ostr.put(chr)) return false;
}
if (count < padTo)
{
char chr = (sign < 0) ? 0x7F : 0x00;
while (++count < padTo)
if (!ostr.put(chr | 0x80)) return false;
if (!ostr.put(chr)) return false;
}
return true;
}
template<typename T>
static bool ReadSignedBinary(std::istream &istr, T &value)
{
value = 0;
unsigned char chr;
unsigned shift = 0;
while (true) // signed LEB128
{
if (!istr.read(reinterpret_cast<char*>(&chr), 1)) return false;
if (shift < sizeof(T) * 8 - 1)
value |= (static_cast<T>(chr & 0x7F) << shift);
shift += 7;
if ((chr & 0x80) == 0) break;
}
if (shift >= 8 * sizeof(T) - 1) shift = 8 * sizeof(T) - 1;
if ((chr & 0x40) != 0)
value |= static_cast<T>(-1) << shift;
return true;
}
bool WriteWord(std::ostream &ostr, unsigned short w)
{
return WriteBinary<unsigned short>(ostr, w);
}
bool ReadWord(std::istream &istr, unsigned short &w)
{
return ReadBinary<unsigned short>(istr, w);
}
bool WriteByte(std::ostream &ostr, char c)
{
if (!ostr.put(c)) return false;
return true;
}
bool ReadByte(std::istream &istr, char& c)
{
if (!istr.get(c)) return false;
return true;
}
bool WriteShort(std::ostream &ostr, short s)
{
return WriteSignedBinary<short>(ostr, s);
}
bool ReadShort(std::istream &istr, short &s)
{
return ReadSignedBinary<short>(istr, s);
}
bool WriteUInt32(std::ostream &ostr, uint32_t i)
{
return WriteBinary<uint32_t>(ostr, i);
}
bool ReadUInt32(std::istream &istr, uint32_t &i)
{
return ReadBinary<uint32_t>(istr, i);
}
bool WriteInt(std::ostream &ostr, int i)
{
return WriteSignedBinary<int>(ostr, i);
}
bool ReadInt(std::istream &istr, int &i)
{
return ReadSignedBinary<int>(istr, i);
}
bool WriteLong(std::ostream &ostr, long l, unsigned padTo)
{
return WriteSignedBinary<long>(ostr, l, padTo);
}
bool ReadLong(std::istream &istr, long &l)
{
return ReadSignedBinary<long>(istr, l);
}
bool WriteFloat(std::ostream &ostr, float f)
{
union {float fValue; unsigned int iValue;} u;
u.fValue = 0.0f;
u.iValue = 0;
u.fValue = f;
return WriteBinary<unsigned int>(ostr, u.iValue);
}
bool ReadFloat(std::istream &istr, float &f)
{
union {float fValue; unsigned int iValue;} u;
u.fValue = 0.0f;
u.iValue = 0;
if (!ReadBinary<unsigned int>(istr, u.iValue)) return false;
f = u.fValue;
return true;
}
bool WriteDouble(std::ostream &ostr, double d)
{
union {double dValue; unsigned long iValue;} u;
u.dValue = 0.0;
u.iValue = 0;
u.dValue = d;
return WriteBinary<unsigned long>(ostr, u.iValue);
}
bool ReadDouble(std::istream &istr, double &d)
{
union {double dValue; unsigned long iValue;} u;
u.dValue = 0.0;
u.iValue = 0;
if (!ReadBinary<unsigned long>(istr, u.iValue)) return false;
d = u.dValue;
return true;
}
bool WriteString(std::ostream &ostr, const std::string &s)
{
if (!WriteBinary<size_t>(ostr, s.size())) return false;
if (!ostr.write(&(s[0]), s.size())) return false;
return true;
}
bool ReadString(std::istream &istr, std::string &s)
{
size_t length = 0;
if (!ReadBinary<size_t>(istr, length)) return false;
s.resize(length);
if (length != 0)
{
if (!istr.read(&(s[0]), length)) return false;
}
return true;
}
bool WriteType(std::ostream &ostr, const CBotTypResult &type)
{
int typ = type.GetType();
if ( typ == CBotTypIntrinsic ) typ = CBotTypClass;
if ( !WriteWord(ostr, typ) ) return false;
if ( typ == CBotTypClass )
{
CBotClass* p = type.GetClass();
if (!WriteString(ostr, p->GetName())) return false;
}
if ( type.Eq( CBotTypArrayBody ) ||
type.Eq( CBotTypArrayPointer ) )
{
if (!WriteWord(ostr, type.GetLimite())) return false;
if (!WriteType(ostr, type.GetTypElem())) return false;
}
if ( type.Eq(CBotTypPointer) )
{
if (type.GetClass() != nullptr)
{
if (!WriteString(ostr, type.GetClass()->GetName())) return false;
}
else if (!WriteString(ostr, "")) return false;
}
return true;
}
bool ReadType(std::istream &istr, CBotTypResult &type)
{
unsigned short w, ww;
if ( !ReadWord(pf, w) ) return false;
if (!ReadWord(istr, w)) return false;
type.SetType(w);
if ( type.Eq( CBotTypIntrinsic ) )
@ -154,7 +286,7 @@ bool ReadType(FILE* pf, CBotTypResult &type)
if ( type.Eq( CBotTypClass ) )
{
std::string s;
if ( !ReadString(pf, s) ) return false;
if (!ReadString(istr, s)) return false;
type = CBotTypResult( w, s );
}
@ -162,11 +294,45 @@ bool ReadType(FILE* pf, CBotTypResult &type)
type.Eq( CBotTypArrayBody ) )
{
CBotTypResult r;
if ( !ReadWord(pf, ww) ) return false;
if ( !ReadType(pf, r) ) return false;
if (!ReadWord(istr, ww)) return false;
if (!ReadType(istr, r)) return false;
type = CBotTypResult( w, r );
type.SetLimite(static_cast<short>(ww));
}
if ( type.Eq(CBotTypPointer) )
{
std::string className;
if (!ReadString(istr, className)) return false;
type = CBotTypResult(w, className);
}
return true;
}
bool WriteStream(std::ostream &ostr, std::istream& istr)
{
if (!istr.seekg(0, istr.end)) return false;
auto size = istr.tellg();
if (size == 0) return WriteLong(ostr, 0);
if (!WriteLong(ostr, size)) return false;
if (!istr.seekg(0, istr.beg)) return false;
if (!(ostr << istr.rdbuf())) return false;
return true;
}
bool ReadStream(std::istream& istr, std::ostream &ostr)
{
long length;
if (!ReadLong(istr, length)) return false;
if (length == 0) return true;
while (length-- > 0)
{
if (!(ostr << istr.get())) return false;
}
return true;
}

View File

@ -19,7 +19,7 @@
#pragma once
#include <cstdio>
#include <iostream>
#include <string>
namespace CBot
@ -28,128 +28,189 @@ namespace CBot
class CBotVar;
class CBotTypResult;
///////////////////////////////////////////////////////////////////////////////
// routines for file management (* FILE)
/*!
* \brief fOpen
* \param name
* \param mode
* \return
* \brief Save a linked list if variables
* \param ostr Output stream
* \param pVar First variable in the list
* \return true on success
*/
FILE* fOpen(const char* name, const char* mode);
/*!
* \brief fClose
* \param filehandle
* \return
*/
int fClose(FILE* filehandle);
/*!
* \brief fWrite
* \param buffer
* \param elemsize
* \param length
* \param filehandle
* \return
*/
std::size_t fWrite(const void *buffer,
std::size_t elemsize,
std::size_t length,
FILE* filehandle);
/*!
* \brief fRead
* \param buffer
* \param elemsize
* \param length
* \param filehandle
* \return
*/
std::size_t fRead(void *buffer,
std::size_t elemsize,
std::size_t length,
FILE* filehandle);
/*!
* \brief SaveVars
* \param pf
* \param pVar
* \return
*/
bool SaveVars(FILE* pf, CBotVar* pVar);
bool SaveVars(std::ostream &ostr, CBotVar* pVar);
/*!
* \brief WriteWord
* \param pf
* \param ostr Output stream
* \param w
* \return
* \return true on success
*/
bool WriteWord(FILE* pf, unsigned short w);
bool WriteWord(std::ostream &ostr, unsigned short w);
/*!
* \brief ReadWord
* \param pf
* \param w
* \return
* \param istr Input stream
* \param[out] w
* \return true on success
*/
bool ReadWord(FILE* pf, unsigned short& w);
bool ReadWord(std::istream &istr, unsigned short &w);
/*!
* \brief ReadLong
* \param pf
* \param w
* \return
* \brief WriteByte
* \param ostr Output stream
* \param c
* \return true on success
*/
bool ReadLong(FILE* pf, long& w);
bool WriteByte(std::ostream &ostr, char c);
/*!
* \brief WriteFloat
* \param pf
* \param w
* \return
* \brief ReadByte
* \param istr Input stream
* \param[out] c
* \return true on success
*/
bool WriteFloat(FILE* pf, float w);
bool ReadByte(std::istream &istr, char& c);
/*!
* \brief WriteShort
* \param ostr Output stream
* \param s
* \return true on success
*/
bool WriteShort(std::ostream &ostr, short s);
/*!
* \brief ReadShort
* \param istr Input stream
* \param[out] s
* \return true on success
*/
bool ReadShort(std::istream &istr, short &s);
/*!
* \brief WriteUInt32
* \param ostr Output stream
* \param i
* \return true on success
*/
bool WriteUInt32(std::ostream &ostr, uint32_t i);
/*!
* \brief ReadUInt32
* \param istr Input stream
* \param[out] i
* \return true on success
*/
bool ReadUInt32(std::istream &istr, uint32_t &i);
/*!
* \brief WriteInt
* \param ostr Output stream
* \param i
* \return true on success
*/
bool WriteInt(std::ostream &ostr, int i);
/*!
* \brief ReadInt
* \param istr Input stream
* \param[out] i
* \return true on success
*/
bool ReadInt(std::istream &istr, int &i);
/*!
* \brief WriteLong
* \param pf
* \param w
* \return
* \param ostr Output stream
* \param l
* \param padTo minimum number of bytes to write
* \return true on success
*/
bool WriteLong(FILE* pf, long w);
bool WriteLong(std::ostream &ostr, long l, unsigned padTo = 0);
/*!
* \brief ReadLong
* \param istr Input stream
* \param[out] l
* \return true on success
*/
bool ReadLong(std::istream &istr, long &l);
/*!
* \brief WriteFloat
* \param ostr Output stream
* \param f
* \return true on success
*/
bool WriteFloat(std::ostream &ostr, float f);
/*!
* \brief ReadFloat
* \param pf
* \param w
* \return
* \param istr Input stream
* \param[out] f
* \return true on success
*/
bool ReadFloat(FILE* pf, float& w);
bool ReadFloat(std::istream &istr, float &f);
/*!
* \brief WriteDouble
* \param ostr Output stream
* \param d
* \return true on success
*/
bool WriteDouble(std::ostream &ostr, double d);
/*!
* \brief ReadDouble
* \param istr Input stream
* \param[out] d
* \return true on success
*/
bool ReadDouble(std::istream &istr, double &d);
/*!
* \brief WriteString
* \param ostr Output stream
* \param s
* \return true on success
*/
bool WriteString(std::ostream &ostr, const std::string &s);
/*!
* \brief ReadString
* \param pf
* \param s
* \return
* \param istr Input stream
* \param[out] s
* \return true on success
*/
bool ReadString(FILE* pf, std::string& s);
bool ReadString(std::istream &istr, std::string &s);
/*!
* \brief WriteType
* \param pf
* \param ostr Output stream
* \param type
* \return
* \return true on success
*/
bool WriteType(FILE* pf, const CBotTypResult &type);
bool WriteType(std::ostream &ostr, const CBotTypResult &type);
/*!
* \brief ReadType
* \param pf
* \param type
* \return
* \param istr Input stream
* \param[out] type
* \return true on success
*/
bool ReadType(FILE* pf, CBotTypResult &type);
bool ReadType(std::istream &istr, CBotTypResult &type);
/*!
* \brief WriteStream
* \param ostr Output stream
* \param istr Input stream
* \return true on success
*/
bool WriteStream(std::ostream &ostr, std::istream& istr);
/*!
* \brief ReadStream
* \param istr Input stream
* \param ostr Output stream
* \return true on success
*/
bool ReadStream(std::istream& istr, std::ostream &ostr);
} // namespace CBot

View File

@ -19,7 +19,7 @@
#include "CBot/CBotInstr/CBotCase.h"
#include "CBot/CBotInstr/CBotExprLitNum.h"
#include "CBot/CBotInstr/CBotTwoOpExpr.h"
#include "CBot/CBotStack.h"
#include "CBot/CBotCStack.h"
@ -30,69 +30,107 @@ namespace CBot
////////////////////////////////////////////////////////////////////////////////
CBotCase::CBotCase()
{
m_value = nullptr;
m_instr = nullptr;
}
////////////////////////////////////////////////////////////////////////////////
CBotCase::~CBotCase()
{
delete m_value;
delete m_instr;
}
////////////////////////////////////////////////////////////////////////////////
CBotInstr* CBotCase::Compile(CBotToken* &p, CBotCStack* pStack)
CBotInstr* CBotCase::Compile(CBotToken* &p, CBotCStack* pStack, std::unordered_map<long, CBotInstr*>& labels)
{
CBotCase* inst = new CBotCase(); // creates the object
CBotToken* pp = p; // preserves at the ^ token (starting position)
inst->SetToken(p);
if (!IsOfType(p, ID_CASE, ID_DEFAULT)) return nullptr; // should never happen
pStack->SetStartError(pp->GetStart());
if ( pp->GetType() == ID_CASE )
long labelValue = 0;
if (pp->GetType() == ID_CASE)
{
pp = p;
inst->m_value = CBotExprLitNum::Compile(p, pStack);
if (inst->m_value == nullptr )
CBotInstr* i = nullptr;
if (nullptr != (i = CBotTwoOpExpr::Compile(p, pStack, nullptr, true)))
{
pStack->SetError( CBotErrBadNum, pp );
delete inst;
return nullptr;
if (pStack->GetType() <= CBotTypLong)
{
CBotStack* pile = CBotStack::AllocateStack();
while ( !i->Execute(pile) );
labelValue = pile->GetVar()->GetValLong();
pile->Delete();
if (labels.count(labelValue) > 0)
{
pStack->SetError(CBotErrRedefCase, p->GetStart());
}
}
else
pStack->SetError(CBotErrBadNum, p->GetStart());
delete i;
}
}
if ( !IsOfType( p, ID_DOTS ))
{
pStack->SetError( CBotErrNoDoubleDots, p->GetStart() );
delete inst;
return nullptr;
else
pStack->SetError(CBotErrBadNum, p->GetStart());
}
return inst;
if (pStack->IsOk() && IsOfType(p, ID_DOTS))
{
CBotCase* newCase = new CBotCase();
newCase->SetToken(pp);
if (pp->GetType() == ID_CASE)
labels[labelValue] = newCase;
return newCase;
}
pStack->SetError(CBotErrNoDoubleDots, p->GetStart());
return nullptr;
}
////////////////////////////////////////////////////////////////////////////////
bool CBotCase::Execute(CBotStack* &pj)
{
return true; // the "case" statement does nothing!
if (m_instr == nullptr) return true;
CBotStack* pile = pj->AddStack(this, CBotStack::BlockVisibilityType::BLOCK);
int state = pile->GetState();
CBotInstr* p = m_instr;
while (state-- > 0) p = p->GetNext();
while (p != nullptr)
{
if (!p->Execute(pile)) return false;
pile->IncState();
p = p->GetNext();
}
pile->Delete();
return pj->IsOk();
}
////////////////////////////////////////////////////////////////////////////////
void CBotCase::RestoreState(CBotStack* &pj, bool bMain)
{
}
if (!bMain) return;
////////////////////////////////////////////////////////////////////////////////
bool CBotCase::CompCase(CBotStack* &pile, int val)
{
if (m_value == nullptr ) return true; // "default" case
CBotStack* pile = pj->RestoreStack(this);
if (pile == nullptr) return;
while (!m_value->Execute(pile)); // puts the value on the correspondent stack (without interruption)
return (pile->GetVal() == val); // compared with the given value
CBotInstr* p = m_instr;
int state = pile->GetState();
while (p != nullptr && state-- > 0)
{
p->RestoreState(pile, bMain);
p = p->GetNext();
}
if (p != nullptr) p->RestoreState(pile, bMain);
}
std::map<std::string, CBotInstr*> CBotCase::GetDebugLinks()
{
auto links = CBotInstr::GetDebugLinks();
links["m_value"] = m_value;
links["m_instr"] = m_instr;
return links;
}

View File

@ -21,6 +21,8 @@
#include "CBot/CBotInstr/CBotInstr.h"
#include <unordered_map>
namespace CBot
{
@ -42,7 +44,7 @@ public:
* \param pStack
* \return
*/
static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack);
static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack, std::unordered_map<long, CBotInstr*>& labels);
/*!
* \brief Execute Execution of instruction "case".
@ -58,22 +60,15 @@ public:
*/
void RestoreState(CBotStack* &pj, bool bMain) override;
/*!
* \brief CompCase Routine to find the entry point of "case" corresponding
* to the value seen.
* \param pj
* \param val
* \return
*/
bool CompCase(CBotStack* &pj, int val) override;
protected:
virtual const std::string GetDebugName() override { return "CBotCase"; }
virtual std::map<std::string, CBotInstr*> GetDebugLinks() override;
private:
//! Value to compare.
CBotInstr* m_value;
//! List of instructions after case label
CBotInstr* m_instr;
friend class CBotSwitch;
};
} // namespace CBot

View File

@ -140,7 +140,7 @@ CBotInstr* CBotDefClass::Compile(CBotToken* &p, CBotCStack* pStack, CBotClass* p
if (typ == CBotErrUndefCall)
{
// si le constructeur n'existe pas
// if the ctor don't exist
if (inst->m_parameters != nullptr) // with parameters
{
pStk->SetError(CBotErrNoConstruct, vartoken);

View File

@ -46,13 +46,22 @@ CBotDefFloat::~CBotDefFloat()
}
////////////////////////////////////////////////////////////////////////////////
CBotInstr* CBotDefFloat::Compile(CBotToken* &p, CBotCStack* pStack, bool cont, bool noskip)
CBotInstr* CBotDefFloat::Compile(CBotToken* &p, CBotCStack* pStack, bool cont, bool noskip, CBotTypResult vartype)
{
CBotToken* pp = cont ? nullptr : p;
if (!cont && !IsOfType(p, ID_FLOAT)) return nullptr;
if (!cont)
{
switch (p->GetType())
{
case ID_FLOAT: vartype.SetType(CBotTypFloat ); break;
case ID_DOUBLE: vartype.SetType(CBotTypDouble); break;
default: return nullptr;
}
p = p->GetNext();
}
CBotDefFloat* inst = static_cast<CBotDefFloat*>(CompileArray(p, pStack, CBotTypFloat));
CBotDefFloat* inst = static_cast<CBotDefFloat*>(CompileArray(p, pStack, vartype));
if (inst != nullptr || !pStack->IsOk()) return inst;
CBotCStack* pStk = pStack->TokenStack(pp);
@ -67,7 +76,7 @@ CBotInstr* CBotDefFloat::Compile(CBotToken* &p, CBotCStack* pStack, bool cont, b
if (nullptr != (inst->m_var = CBotLeftExprVar::Compile( p, pStk )))
{
(static_cast<CBotLeftExprVar*>(inst->m_var))->m_typevar = CBotTypFloat;
(static_cast<CBotLeftExprVar*>(inst->m_var))->m_typevar = vartype;
if (pStk->CheckVarLocal(vartoken)) // redefinition of a variable
{
pStk->SetStartError(vartoken->GetStart());
@ -79,7 +88,7 @@ CBotInstr* CBotDefFloat::Compile(CBotToken* &p, CBotCStack* pStack, bool cont, b
{
delete inst;
p = vartoken;
inst = static_cast<CBotDefFloat*>(CBotDefArray::Compile(p, pStk, CBotTypFloat));
inst = static_cast<CBotDefFloat*>(CBotDefArray::Compile(p, pStk, vartype));
goto suite; // no assignment, variable already created
}
@ -103,7 +112,7 @@ CBotInstr* CBotDefFloat::Compile(CBotToken* &p, CBotCStack* pStack, bool cont, b
}
}
var = CBotVar::Create(*vartoken, CBotTypFloat);
var = CBotVar::Create(*vartoken, vartype);
var->SetInit(inst->m_expr != nullptr ? CBotVar::InitType::DEF : CBotVar::InitType::UNDEF);
var->SetUniqNum(
(static_cast<CBotLeftExprVar*>(inst->m_var))->m_nIdent = CBotVar::NextUniqNum());
@ -111,7 +120,7 @@ CBotInstr* CBotDefFloat::Compile(CBotToken* &p, CBotCStack* pStack, bool cont, b
suite:
if (pStk->IsOk() && IsOfType(p, ID_COMMA))
{
if (nullptr != ( inst->m_next2b = CBotDefFloat::Compile(p, pStk, true, noskip)))
if (nullptr != ( inst->m_next2b = CBotDefFloat::Compile(p, pStk, true, noskip, vartype)))
{
return pStack->Return(inst, pStk);
}

View File

@ -41,7 +41,7 @@ public:
* \param noskip
* \return
*/
static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack, bool cont = false, bool noskip=false);
static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack, bool cont = false, bool noskip=false, CBotTypResult vartype = CBotTypFloat);
/*!
* \brief Execute Executes the definition of a real variable.

View File

@ -47,13 +47,25 @@ CBotDefInt::~CBotDefInt()
}
////////////////////////////////////////////////////////////////////////////////
CBotInstr* CBotDefInt::Compile(CBotToken* &p, CBotCStack* pStack, bool cont, bool noskip)
CBotInstr* CBotDefInt::Compile(CBotToken* &p, CBotCStack* pStack, bool cont, bool noskip, CBotTypResult vartype)
{
CBotToken* pp = cont ? nullptr : p; // no repetition of the token "int"
if (!cont && !IsOfType(p, ID_INT)) return nullptr;
if (!cont)
{
switch (p->GetType())
{
case ID_BYTE: vartype.SetType(CBotTypByte ); break;
case ID_SHORT: vartype.SetType(CBotTypShort); break;
case ID_CHAR: vartype.SetType(CBotTypChar ); break;
case ID_INT: vartype.SetType(CBotTypInt ); break;
case ID_LONG: vartype.SetType(CBotTypLong ); break;
default: return nullptr;
}
p = p->GetNext();
}
CBotDefInt* inst = static_cast<CBotDefInt*>(CompileArray(p, pStack, CBotTypInt));
CBotDefInt* inst = static_cast<CBotDefInt*>(CompileArray(p, pStack, vartype));
if (inst != nullptr || !pStack->IsOk()) return inst;
CBotCStack* pStk = pStack->TokenStack(pp);
@ -68,7 +80,7 @@ CBotInstr* CBotDefInt::Compile(CBotToken* &p, CBotCStack* pStack, bool cont, boo
// determines the expression is valid for the item on the left side
if (nullptr != (inst->m_var = CBotLeftExprVar::Compile( p, pStk )))
{
(static_cast<CBotLeftExprVar*>(inst->m_var))->m_typevar = CBotTypInt;
(static_cast<CBotLeftExprVar*>(inst->m_var))->m_typevar = vartype;
if (pStk->CheckVarLocal(vartoken)) // redefinition of the variable
{
pStk->SetError(CBotErrRedefVar, vartoken);
@ -82,7 +94,7 @@ CBotInstr* CBotDefInt::Compile(CBotToken* &p, CBotCStack* pStack, bool cont, boo
// compiles an array declaration
CBotInstr* inst2 = CBotDefArray::Compile(p, pStk, CBotTypInt);
CBotInstr* inst2 = CBotDefArray::Compile(p, pStk, vartype);
inst = static_cast<CBotDefInt*>(inst2);
goto suite; // no assignment, variable already created
@ -108,7 +120,7 @@ CBotInstr* CBotDefInt::Compile(CBotToken* &p, CBotCStack* pStack, bool cont, boo
}
{
CBotVar* var = CBotVar::Create(*vartoken, CBotTypInt);// create the variable (evaluated after the assignment)
CBotVar* var = CBotVar::Create(*vartoken, vartype); // create the variable (evaluated after the assignment)
var->SetInit(inst->m_expr != nullptr ? CBotVar::InitType::DEF : CBotVar::InitType::UNDEF); // if initialized with assignment
var->SetUniqNum( //set it with a unique number
(static_cast<CBotLeftExprVar*>(inst->m_var))->m_nIdent = CBotVar::NextUniqNum());
@ -117,7 +129,7 @@ CBotInstr* CBotDefInt::Compile(CBotToken* &p, CBotCStack* pStack, bool cont, boo
suite:
if (pStk->IsOk() && IsOfType(p, ID_COMMA)) // chained several definitions
{
if (nullptr != ( inst->m_next2b = CBotDefInt::Compile(p, pStk, true, noskip))) // compile next one
if (nullptr != ( inst->m_next2b = CBotDefInt::Compile(p, pStk, true, noskip, vartype))) // compile next one
{
return pStack->Return(inst, pStk);
}

View File

@ -41,7 +41,7 @@ public:
* \param noskip
* \return
*/
static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack, bool cont = false, bool noskip = false);
static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack, bool cont = false, bool noskip = false, CBotTypResult vartype = CBotTypInt);
/*!
* \brief Execute Execute the definition of the integer variable.

View File

@ -57,7 +57,7 @@ CBotInstr* CBotDo::Compile(CBotToken* &p, CBotCStack* pStack)
inst->SetToken(p);
if (!IsOfType(p, ID_DO)) return nullptr; // should never happen
CBotCStack* pStk = pStack->TokenStack(pp); // un petit bout de pile svp
CBotCStack* pStk = pStack->TokenStack(pp); // some space for a stack, plz
// looking for a statement block after the do

View File

@ -0,0 +1,151 @@
/*
* This file is part of the Colobot: Gold Edition source code
* Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://gnu.org/licenses
*/
#include "CBot/CBotInstr/CBotExprLitChar.h"
#include "CBot/CBotStack.h"
#include "CBot/CBotCStack.h"
#include "CBot/CBotVar/CBotVar.h"
namespace CBot
{
CBotExprLitChar::CBotExprLitChar()
{
}
CBotExprLitChar::~CBotExprLitChar()
{
}
CBotInstr* CBotExprLitChar::Compile(CBotToken* &p, CBotCStack* pStack)
{
CBotCStack* pStk = pStack->TokenStack();
const auto& s = p->GetString();
auto it = s.cbegin();
if (++it != s.cend())
{
if (*it != '\'') // not empty quotes ?
{
uint32_t valchar = 0;
int pos = p->GetStart() + 1;
if (*it != '\\') valchar = *(it++); // not escape sequence ?
else if (++it != s.cend())
{
pStk->SetStartError(pos++);
unsigned char c = *(it++);
if (c == '\"' || c == '\'' || c == '\\') valchar = c;
else if (c == 'a') valchar = '\a'; // alert bell
else if (c == 'b') valchar = '\b'; // backspace
else if (c == 'f') valchar = '\f'; // form feed
else if (c == 'n') valchar = '\n'; // new line
else if (c == 'r') valchar = '\r'; // carriage return
else if (c == 't') valchar = '\t'; // horizontal tab
else if (c == 'v') valchar = '\v'; // vertical tab
else if (c == 'u' || c == 'U') // unicode escape
{
if (it != s.cend())
{
std::string hex = "";
size_t maxlen = (c == 'u') ? 4 : 8;
for (size_t i = 0; i < maxlen; i++)
{
if (!CharInList(*it, "0123456789ABCDEFabcdef")) break;
++pos;
hex += *it;
if (++it == s.cend()) break;
}
if (maxlen == hex.length()) // unicode character
{
try
{
valchar = std::stoi(hex, nullptr, 16);
if (0x10FFFF < valchar || (0xD7FF < valchar && valchar < 0xE000))
pStk->SetError(CBotErrUnicodeName, pos + 1);
}
catch (const std::out_of_range& e)
{
pStk->SetError(CBotErrHexRange, pos + 1);
}
}
else
pStk->SetError(CBotErrHexDigits, pos + 1);
}
else
pStk->SetError(CBotErrHexDigits, pos + 1);
}
else
pStk->SetError(CBotErrBadEscape, pos + 1);
}
if (it == s.cend() || *it != '\'')
pStk->SetError(CBotErrEndQuote, p);
if (pStk->IsOk())
{
CBotExprLitChar* inst = new CBotExprLitChar();
inst->m_valchar = valchar;
inst->SetToken(p);
p = p->GetNext();
CBotVar* var = CBotVar::Create("", CBotTypChar);
pStk->SetVar(var);
return pStack->Return(inst, pStk);
}
}
pStk->SetError(CBotErrCharEmpty, p);
}
pStk->SetError(CBotErrEndQuote, p);
return pStack->Return(nullptr, pStk);
}
bool CBotExprLitChar::Execute(CBotStack* &pj)
{
CBotStack* pile = pj->AddStack(this);
if (pile->IfStep()) return false;
CBotVar* var = CBotVar::Create("", CBotTypChar);
var->SetValChar(m_valchar);
pile->SetVar(var);
return pj->Return(pile);
}
void CBotExprLitChar::RestoreState(CBotStack* &pj, bool bMain)
{
if (bMain) pj->RestoreStack(this);
}
std::string CBotExprLitChar::GetDebugData()
{
return m_token.GetString();
}
} // namespace CBot

View File

@ -0,0 +1,60 @@
/*
* This file is part of the Colobot: Gold Edition source code
* Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://gnu.org/licenses
*/
#pragma once
#include "CBot/CBotInstr/CBotInstr.h"
namespace CBot
{
/**
* \brief A character literal
* \verbatim 'a', '\n', '\t', '\uFFFD', '\U0000FFFD', etc. \endverbatim
*/
class CBotExprLitChar : public CBotInstr
{
public:
CBotExprLitChar();
~CBotExprLitChar();
/*!
* \brief Compile a character literal
*/
static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack);
/*!
* \brief Execute, returns the corresponding char.
*/
bool Execute(CBotStack* &pj) override;
/*!
* \brief RestoreState
*/
void RestoreState(CBotStack* &pj, bool bMain) override;
protected:
virtual const std::string GetDebugName() override { return "CBotExprLitChar"; }
virtual std::string GetDebugData() override;
private:
uint32_t m_valchar = 0;
};
} // namespace CBot

View File

@ -25,52 +25,85 @@
#include "CBot/CBotUtils.h"
#include <limits>
#include <sstream>
namespace CBot
{
////////////////////////////////////////////////////////////////////////////////
CBotExprLitNum::CBotExprLitNum()
template <>
CBotExprLitNum<int>::CBotExprLitNum(int val) : m_numtype(CBotTypInt), m_value(val)
{
}
////////////////////////////////////////////////////////////////////////////////
CBotExprLitNum::~CBotExprLitNum()
template <>
CBotExprLitNum<long>::CBotExprLitNum(long val) : m_numtype(CBotTypLong), m_value(val)
{
}
////////////////////////////////////////////////////////////////////////////////
CBotInstr* CBotExprLitNum::Compile(CBotToken* &p, CBotCStack* pStack)
template <>
CBotExprLitNum<float>::CBotExprLitNum(float val) : m_numtype(CBotTypFloat), m_value(val)
{
}
template <>
CBotExprLitNum<double>::CBotExprLitNum(double val) : m_numtype(CBotTypDouble), m_value(val)
{
}
template <typename T>
CBotExprLitNum<T>::~CBotExprLitNum()
{
}
CBotInstr* CompileExprLitNum(CBotToken* &p, CBotCStack* pStack)
{
CBotCStack* pStk = pStack->TokenStack();
CBotExprLitNum* inst = new CBotExprLitNum();
const auto& s = p->GetString();
inst->SetToken(p);
std::string s = p->GetString();
CBotInstr* inst = nullptr;
CBotType numtype = CBotTypInt;
inst->m_numtype = CBotTypInt;
if (p->GetType() == TokenTypDef)
{
inst->m_valint = p->GetKeywordId();
inst = new CBotExprLitNum<int>(static_cast<int>(p->GetKeywordId()));
}
else
{
if (s.find('.') != std::string::npos || ( s.find('x') == std::string::npos && ( s.find_first_of("eE") != std::string::npos ) ))
{
inst->m_numtype = CBotTypFloat;
inst->m_valfloat = GetNumFloat(s);
double val = GetNumFloat(s);
if (val > static_cast<double>(std::numeric_limits<float>::max()))
{
numtype = CBotTypDouble;
inst = new CBotExprLitNum<double>(val);
}
else
{
numtype = CBotTypFloat;
inst = new CBotExprLitNum<float>(static_cast<float>(val));
}
}
else
{
inst->m_valint = GetNumInt(s);
long val = GetNumInt(s);
if (val > std::numeric_limits<int>::max())
{
numtype = CBotTypLong;
inst = new CBotExprLitNum<long>(val);
}
else
{
inst = new CBotExprLitNum<int>(static_cast<int>(val));
}
}
}
inst->SetToken(p);
if (pStk->NextToken(p))
{
CBotVar* var = CBotVar::Create("", inst->m_numtype);
CBotVar* var = CBotVar::Create("", numtype);
pStk->SetVar(var);
return pStack->Return(inst, pStk);
@ -79,8 +112,48 @@ CBotInstr* CBotExprLitNum::Compile(CBotToken* &p, CBotCStack* pStack)
return pStack->Return(nullptr, pStk);
}
////////////////////////////////////////////////////////////////////////////////
bool CBotExprLitNum::Execute(CBotStack* &pj)
CBotInstr* CompileSizeOf(CBotToken* &p, CBotCStack* pStack)
{
CBotToken* pp = p;
if (!IsOfType(p, TokenTypVar)) return nullptr;
if (pp->GetString() == "sizeof" && IsOfType(p, ID_OPENPAR))
{
CBotCStack* pStk = pStack->TokenStack();
int value;
if (IsOfType(p, ID_BYTE)) value = sizeof(signed char);
else if (IsOfType(p, ID_SHORT)) value = sizeof(short);
else if (IsOfType(p, ID_CHAR)) value = sizeof(uint32_t);
else if (IsOfType(p, ID_INT)) value = sizeof(int);
else if (IsOfType(p, ID_LONG)) value = sizeof(long);
else if (IsOfType(p, ID_FLOAT)) value = sizeof(float);
else if (IsOfType(p, ID_DOUBLE)) value = sizeof(double);
else
{
p = pp;
return pStack->Return(nullptr, pStk);
}
if (IsOfType(p, ID_CLOSEPAR))
{
auto inst = new CBotExprLitNum<int>(value);
inst->SetToken(pp);
CBotVar* var = CBotVar::Create("", CBotTypInt);
pStk->SetVar(var);
return pStack->Return(inst, pStk);
}
pStk->SetError(CBotErrClosePar, p->GetStart());
return pStack->Return(nullptr, pStk);
}
p = pp;
return nullptr;
}
template <typename T>
bool CBotExprLitNum<T>::Execute(CBotStack* &pj)
{
CBotStack* pile = pj->AddStack(this);
@ -88,39 +161,38 @@ bool CBotExprLitNum::Execute(CBotStack* &pj)
CBotVar* var = CBotVar::Create("", m_numtype);
std::string nombre ;
if (m_token.GetType() == TokenTypDef)
{
nombre = m_token.GetString();
var->SetValInt(m_value, m_token.GetString());
}
switch (m_numtype)
else
{
case CBotTypShort:
case CBotTypInt:
var->SetValInt(m_valint, nombre);
break;
case CBotTypFloat:
var->SetValFloat(m_valfloat);
break;
default:
assert(false);
*var = m_value;
}
pile->SetVar(var); // place on the stack
return pj->Return(pile); // it's ok
}
////////////////////////////////////////////////////////////////////////////////
void CBotExprLitNum::RestoreState(CBotStack* &pj, bool bMain)
template <typename T>
void CBotExprLitNum<T>::RestoreState(CBotStack* &pj, bool bMain)
{
if (bMain) pj->RestoreStack(this);
}
std::string CBotExprLitNum::GetDebugData()
template <typename T>
std::string CBotExprLitNum<T>::GetDebugData()
{
std::stringstream ss;
ss << "(" << (m_numtype == CBotTypFloat ? "float" : "int") << ") " << (m_numtype == CBotTypFloat ? m_valfloat : m_valint);
switch (m_numtype)
{
case CBotTypInt : ss << "(int) "; break;
case CBotTypLong : ss << "(long) "; break;
case CBotTypFloat : ss << "(float) "; break;
case CBotTypDouble: ss << "(double) "; break;
default: assert(false);
}
ss << m_value;
return ss.str();
}

View File

@ -24,26 +24,23 @@
namespace CBot
{
CBotInstr* CompileExprLitNum(CBotToken* &p, CBotCStack* pStack);
CBotInstr* CompileSizeOf(CBotToken* &p, CBotCStack* pStack);
/**
* \brief A number literal - 5, 1, 2.5, 3.75, etc. or a predefined numerical constant (see CBotToken::DefineNum())
*
* Can be of type ::CBotTypInt or ::CBotTypFloat
* Can be of type ::CBotTypInt, ::CBotTypLong, ::CBotTypFloat, or ::CBotTypDouble
*/
template <typename T>
class CBotExprLitNum : public CBotInstr
{
public:
CBotExprLitNum();
CBotExprLitNum(T val);
~CBotExprLitNum();
/*!
* \brief Compile
* \param p
* \param pStack
* \return
*/
static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack);
/*!
* \brief Execute Execute, returns the corresponding number.
* \param pj
@ -65,10 +62,8 @@ protected:
private:
//! The type of number.
CBotType m_numtype;
//! Value for an int.
long m_valint;
//! Value for a float.
float m_valfloat;
//! Value
T m_value;
};

View File

@ -24,6 +24,8 @@
#include "CBot/CBotVar/CBotVar.h"
#include <stdexcept>
namespace CBot
{
@ -42,7 +44,7 @@ CBotInstr* CBotExprLitString::Compile(CBotToken* &p, CBotCStack* pStack)
{
CBotCStack* pStk = pStack->TokenStack();
std::string s = p->GetString();
const auto& s = p->GetString();
auto it = s.cbegin();
if (++it != s.cend())
@ -51,7 +53,7 @@ CBotInstr* CBotExprLitString::Compile(CBotToken* &p, CBotCStack* pStack)
std::string valstring = "";
while (it != s.cend() && *it != '\"')
{
pStk->SetStartError(++pos);
++pos;
if (*it != '\\') // not escape sequence ?
{
valstring += *(it++);
@ -59,6 +61,7 @@ CBotInstr* CBotExprLitString::Compile(CBotToken* &p, CBotCStack* pStack)
}
if (++it == s.cend()) break;
pStk->SetStartError(pos);
if (CharInList(*it, "01234567")) // octal
{

View File

@ -40,8 +40,7 @@ CBotExprUnaire::~CBotExprUnaire()
delete m_expr;
}
////////////////////////////////////////////////////////////////////////////////
CBotInstr* CBotExprUnaire::Compile(CBotToken* &p, CBotCStack* pStack, bool bLiteral)
CBotInstr* CBotExprUnaire::Compile(CBotToken* &p, CBotCStack* pStack, bool bLiteral, bool bConstExpr)
{
int op = p->GetType();
CBotToken* pp = p;
@ -52,8 +51,10 @@ CBotInstr* CBotExprUnaire::Compile(CBotToken* &p, CBotCStack* pStack, bool bLite
CBotExprUnaire* inst = new CBotExprUnaire();
inst->SetToken(pp);
if (!bLiteral) inst->m_expr = CBotParExpr::Compile(p, pStk);
else inst->m_expr = CBotParExpr::CompileLitExpr(p, pStk);
if (bConstExpr || !bLiteral)
inst->m_expr = CBotParExpr::Compile(p, pStk, bConstExpr);
else
inst->m_expr = CBotParExpr::CompileLitExpr(p, pStk);
if (inst->m_expr != nullptr)
{

View File

@ -40,7 +40,7 @@ public:
* \param bLiteral If true, compiles only literal expressions Ex: ~11, -4.0, !false, not true
* \return The compiled instruction or nullptr
*/
static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack, bool bLiteral = false);
static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack, bool bLiteral = false, bool bConstExpr = false);
/*!
* \brief Execute

View File

@ -67,7 +67,7 @@ CBotInstr* CBotFor::Compile(CBotToken* &p, CBotCStack* pStack)
return nullptr;
}
CBotCStack* pStk = pStack->TokenStack(pp, true); // un petit bout de pile svp
CBotCStack* pStk = pStack->TokenStack(pp, true); // some size for a stack, plz
// compiles instructions for initialization
inst->m_init = CBotListExpression::Compile(p, pStk );

View File

@ -169,7 +169,7 @@ CBotFunction* CBotFunction::Compile(CBotToken* &p, CBotCStack* pStack, CBotFunct
func->m_token = d;
}
// un nom de fonction est-il là ?
// is there a function name here ?
if (IsOfType(p, TokenTypVar))
{
if ( IsOfType( p, ID_DBLDOTS ) ) // method for a class
@ -284,7 +284,7 @@ CBotFunction* CBotFunction::Compile1(CBotToken* &p, CBotCStack* pStack, CBotClas
func->m_token = d;
}
// un nom de fonction est-il là ?
// is there a function name here ?
if (IsOfType(p, TokenTypVar))
{
if ( IsOfType( p, ID_DBLDOTS ) ) // method for a class
@ -584,7 +584,7 @@ CBotFunction* CBotFunction::FindLocalOrPublic(const std::list<CBotFunction*>& lo
{
int i = 0;
int alpha = 0; // signature of parameters
// parameters sont-ils compatibles ?
// are parameters compatible ?
CBotDefParam* pv = pt->m_param; // list of expected parameters
CBotVar* pw = ppVars[i++]; // list of provided parameters
while ( pv != nullptr && (pw != nullptr || pv->HasDefault()) )

View File

@ -208,10 +208,15 @@ CBotInstr* CBotInstr::Compile(CBotToken* &p, CBotCStack* pStack)
case ID_THROW:
return CBotThrow::Compile(p, pStack);
case ID_BYTE:
case ID_SHORT:
case ID_CHAR:
case ID_INT:
case ID_LONG:
return CBotDefInt::Compile(p, pStack);
case ID_FLOAT:
case ID_DOUBLE:
return CBotDefFloat::Compile(p, pStack);
case ID_STRING:
@ -312,13 +317,6 @@ void CBotInstr::RestoreStateVar(CBotStack* &pile, bool bMain)
assert(0); // dad do not know, see the girls
}
////////////////////////////////////////////////////////////////////////////////
bool CBotInstr::CompCase(CBotStack* &pj, int val)
{
return false;
}
////////////////////////////////////////////////////////////////////////////////
CBotInstr* CBotInstr::CompileArray(CBotToken* &p, CBotCStack* pStack, CBotTypResult type, bool first)
{
if (IsOfType(p, ID_OPBRK))

View File

@ -191,17 +191,6 @@ public:
virtual void RestoreStateVar(CBotStack* &pile,
bool bMain);
/**
* \brief CompCase This routine is defined only for the subclass CBotCase
* this allows to make the call on all instructions CompCase to see if it's
* a case to the desired value..
* \param pj
* \param val
* \return
*/
virtual bool CompCase(CBotStack* &pj,
int val);
/**
* \brief SetToken Set the token corresponding to the instruction.
* \param p

View File

@ -129,6 +129,13 @@ bool TypeCompatible(CBotTypResult& type1, CBotTypResult& type2, int op)
return true;
}
if (op == ID_ASR || op == ID_SR || op == ID_SL ||
op == ID_ASSOR || op == ID_ASSSL || op == ID_ASSSR ||
op == ID_ASSAND || op == ID_ASSXOR || op == ID_ASSASR)
{
if (max > CBotTypLong) return false;
}
type1.SetType(max);
type2.SetType(max);
return true;

View File

@ -21,6 +21,7 @@
#include "CBot/CBotInstr/CBotExpression.h"
#include "CBot/CBotInstr/CBotExprLitBool.h"
#include "CBot/CBotInstr/CBotExprLitChar.h"
#include "CBot/CBotInstr/CBotExprLitNan.h"
#include "CBot/CBotInstr/CBotExprLitNull.h"
#include "CBot/CBotInstr/CBotExprLitNum.h"
@ -31,6 +32,7 @@
#include "CBot/CBotInstr/CBotNew.h"
#include "CBot/CBotInstr/CBotPostIncExpr.h"
#include "CBot/CBotInstr/CBotPreIncExpr.h"
#include "CBot/CBotInstr/CBotTwoOpExpr.h"
#include "CBot/CBotVar/CBotVar.h"
@ -39,13 +41,15 @@
namespace CBot
{
////////////////////////////////////////////////////////////////////////////////
CBotInstr* CBotParExpr::Compile(CBotToken* &p, CBotCStack* pStack)
CBotInstr* CBotParExpr::Compile(CBotToken* &p, CBotCStack* pStack, bool bConstExpr)
{
CBotCStack* pStk = pStack->TokenStack();
pStk->SetStartError(p->GetStart());
if (bConstExpr)
return CBotParExpr::CompileConstExpr(p, pStack);
// is it an expression in parentheses?
if (IsOfType(p, ID_OPENPAR))
{
@ -68,6 +72,13 @@ CBotInstr* CBotParExpr::Compile(CBotToken* &p, CBotCStack* pStack)
if (inst != nullptr || !pStk->IsOk())
return pStack->Return(inst, pStk);
// is it sizeof operator ?
inst = CBot::CompileSizeOf(p, pStk);
if (inst != nullptr || !pStk->IsOk())
{
return pStack->Return(inst, pStk);
}
// is it a variable name?
if (p->GetType() == TokenTypVar)
{
@ -83,7 +94,7 @@ CBotInstr* CBotParExpr::Compile(CBotToken* &p, CBotCStack* pStack)
CBotToken* pvar = p;
// no, it an "ordinaty" variable
// no, it's an "ordinaty" variable
inst = CBotExprVar::Compile(p, pStk);
CBotToken* pp = p;
@ -151,7 +162,21 @@ CBotInstr* CBotParExpr::CompileLitExpr(CBotToken* &p, CBotCStack* pStack)
if (p->GetType() == TokenTypNum ||
p->GetType() == TokenTypDef )
{
CBotInstr* inst = CBotExprLitNum::Compile(p, pStk);
CBotInstr* inst = CBot::CompileExprLitNum(p, pStk);
return pStack->Return(inst, pStk);
}
// is it sizeof operator ?
inst = CBot::CompileSizeOf(p, pStk);
if (inst != nullptr || !pStk->IsOk())
{
return pStack->Return(inst, pStk);
}
// is this a character?
if (p->GetType() == TokenTypChar)
{
CBotInstr* inst = CBotExprLitChar::Compile(p, pStk);
return pStack->Return(inst, pStk);
}
@ -202,4 +227,55 @@ CBotInstr* CBotParExpr::CompileLitExpr(CBotToken* &p, CBotCStack* pStack)
return pStack->Return(nullptr, pStk);
}
CBotInstr* CBotParExpr::CompileConstExpr(CBotToken* &p, CBotCStack* pStack)
{
CBotCStack* pStk = pStack->TokenStack();
// is it an expression in parentheses?
if (IsOfType(p, ID_OPENPAR))
{
CBotInstr* inst = CBotTwoOpExpr::Compile(p, pStk, nullptr, true);
if (nullptr != inst)
{
if (IsOfType(p, ID_CLOSEPAR))
{
return pStack->Return(inst, pStk);
}
pStk->SetError(CBotErrClosePar, p->GetStart());
}
delete inst;
return pStack->Return(nullptr, pStk);
}
// is this a unary operation?
CBotInstr* inst = CBotExprUnaire::Compile(p, pStk, true, true);
if (inst != nullptr || !pStk->IsOk())
return pStack->Return(inst, pStk);
// is it a number or DefineNum?
if (p->GetType() == TokenTypNum ||
p->GetType() == TokenTypDef )
{
CBotInstr* inst = CBot::CompileExprLitNum(p, pStk);
return pStack->Return(inst, pStk);
}
// is this a character?
if (p->GetType() == TokenTypChar)
{
CBotInstr* inst = CBotExprLitChar::Compile(p, pStk);
return pStack->Return(inst, pStk);
}
// is it sizeof operator ?
inst = CBot::CompileSizeOf(p, pStk);
if (inst != nullptr || !pStk->IsOk())
{
return pStack->Return(inst, pStk);
}
return pStack->Return(nullptr, pStk);
}
} // namespace CBot

View File

@ -52,7 +52,7 @@ public:
* \param pStack
* \return
*/
static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack);
static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack, bool bConstExpr = false);
/*!
* \brief Compile a literal expression ("string", number, true, false, null, nan, new)
@ -62,6 +62,8 @@ public:
*/
static CBotInstr* CompileLitExpr(CBotToken* &p, CBotCStack* pStack);
static CBotInstr* CompileConstExpr(CBotToken* &p, CBotCStack* pStack);
private:
CBotParExpr() = delete;
CBotParExpr(const CBotParExpr&) = delete;

View File

@ -51,13 +51,13 @@ CBotInstr* CBotSwitch::Compile(CBotToken* &p, CBotCStack* pStack)
inst->SetToken(p);
if (!IsOfType(p, ID_SWITCH)) return nullptr; // should never happen
CBotCStack* pStk = pStack->TokenStack(pp); // un petit bout de pile svp
CBotCStack* pStk = pStack->TokenStack(pp); // some space for a stack, plz
if ( IsOfType(p, ID_OPENPAR ) )
{
if ( nullptr != (inst->m_value = CBotExpression::Compile(p, pStk )) )
{
if ( pStk->GetType() < CBotTypLong )
if ( pStk->GetType() <= CBotTypLong )
{
if ( IsOfType(p, ID_CLOSEPAR ) )
{
@ -65,21 +65,35 @@ CBotInstr* CBotSwitch::Compile(CBotToken* &p, CBotCStack* pStack)
{
IncLvl();
CBotCase* caseInst = nullptr;
CBotCStack* pStk2 = nullptr;
while( !IsOfType( p, ID_CLBLK ) )
{
if ( p->GetType() == ID_CASE || p->GetType() == ID_DEFAULT)
{
CBotCStack* pStk2 = pStk->TokenStack(p); // un petit bout de pile svp
delete pStk2;
pStk2 = pStk->TokenStack(p, true); // some space for a stack, plz
CBotInstr* i = CBotCase::Compile( p, pStk2 );
if (i == nullptr)
caseInst = static_cast<CBotCase*>(CBotCase::Compile(p, pStk2, inst->m_labels));
if (caseInst == nullptr)
{
delete inst;
return pStack->Return(nullptr, pStk2);
}
delete pStk2;
if (inst->m_block == nullptr ) inst->m_block = i;
else inst->m_block->AddNext(i);
if (inst->m_block == nullptr ) inst->m_block = caseInst;
else inst->m_block->AddNext(caseInst);
if (ID_DEFAULT == caseInst->GetTokenType())
{
if (inst->m_default != nullptr)
{
pStk->SetError(CBotErrRedefCase, caseInst->GetToken());
delete inst;
return pStack->Return(nullptr, pStk);
}
inst->m_default = caseInst;
}
continue;
}
@ -90,13 +104,14 @@ CBotInstr* CBotSwitch::Compile(CBotToken* &p, CBotCStack* pStack)
return pStack->Return(nullptr, pStk);
}
CBotInstr* i = CBotBlock::CompileBlkOrInst( p, pStk, true );
if ( !pStk->IsOk() )
CBotInstr* i = CBotBlock::CompileBlkOrInst(p, pStk2);
if ( !pStk2->IsOk() )
{
delete inst;
return pStack->Return(nullptr, pStk);
return pStack->Return(nullptr, pStk2);
}
inst->m_block->AddNext(i);
if (caseInst->m_instr == nullptr ) caseInst->m_instr = i;
else caseInst->m_instr->AddNext(i);
if ( p == nullptr )
{
@ -133,40 +148,21 @@ CBotInstr* CBotSwitch::Compile(CBotToken* &p, CBotCStack* pStack)
bool CBotSwitch :: Execute(CBotStack* &pj)
{
CBotStack* pile1 = pj->AddStack(this); // adds an item to the stack
// if ( pile1 == EOX ) return true;
CBotInstr* p = m_block; // first expression
int state = pile1->GetState();
if (state == 0)
{
if ( !m_value->Execute(pile1) ) return false;
pile1->SetState(state = -1);
pile1->SetState(state = 1);
}
if ( pile1->IfStep() ) return false;
if ( state == -1 )
{
state = 0;
int val = pile1->GetVal(); // result of the value
auto it = m_labels.find(pile1->GetVar()->GetValLong());
CBotStack* pile2 = pile1->AddStack();
while ( p != nullptr ) // search for the corresponding case in a list
{
state++;
if ( p->CompCase( pile2, val ) ) break; // found the case
p = p->GetNext();
}
pile2->Delete();
CBotInstr* p = (it != m_labels.end()) ? it->second : m_default;
if ( p == nullptr ) return pj->Return(pile1); // completed if nothing
if ( !pile1->SetState(state) ) return false;
}
p = m_block; // returns to the beginning
while (state-->0) p = p->GetNext(); // advance in the list
while (--state > 0) p = p->GetNext();
while( p != nullptr )
{
@ -185,8 +181,6 @@ void CBotSwitch :: RestoreState(CBotStack* &pj, bool bMain)
CBotStack* pile1 = pj->RestoreStack(this); // adds an item to the stack
if ( pile1 == nullptr ) return;
CBotInstr* p = m_block; // first expression
int state = pile1->GetState();
if (state == 0)
{
@ -194,13 +188,11 @@ void CBotSwitch :: RestoreState(CBotStack* &pj, bool bMain)
return;
}
if ( state == -1 )
{
return;
}
auto it = m_labels.find(pile1->GetVar()->GetValLong());
// p = m_block; // returns to the beginning
while ( p != nullptr && state-- > 0 )
CBotInstr* p = (it != m_labels.end()) ? it->second : m_default;
while (p != nullptr && --state > 0)
{
p->RestoreState(pile1, false);
p = p->GetNext(); // advance in the list

View File

@ -21,6 +21,8 @@
#include "CBot/CBotInstr/CBotInstr.h"
#include <unordered_map>
namespace CBot
{
@ -64,8 +66,12 @@ protected:
private:
//! Value to seek
CBotInstr* m_value;
//! Instructions
CBotInstr* m_block;
//! List of case instructions
CBotInstr* m_block = nullptr;
//! Pointer to default label
CBotInstr* m_default = nullptr;
//! Map of case labels
std::unordered_map<long, CBotInstr*> m_labels;
};
} // namespace CBot

View File

@ -52,7 +52,7 @@ CBotInstr* CBotTry::Compile(CBotToken* &p, CBotCStack* pStack)
inst->SetToken(p);
if (!IsOfType(p, ID_TRY)) return nullptr; // should never happen
CBotCStack* pStk = pStack->TokenStack(pp); // un petit bout de pile svp
CBotCStack* pStk = pStack->TokenStack(pp); // some space for a stack, plz
inst->m_block = CBotBlock::CompileBlkOrInst(p, pStk );
CBotCatch** pn = &inst->m_catchList;
@ -102,11 +102,11 @@ bool CBotTry::Execute(CBotStack* &pj)
val = pile1->GetError();
if ( val == CBotNoErr && pile1->GetTimer() == 0 ) // mode step?
return false; // does not make the catch
return false; // don't jump to the catch
pile1->IncState();
pile2->SetState(val); // stores the error number
pile1->SetError(CBotNoErr); // for now there is are more errors!
pile1->SetError(CBotNoErr); // for now there are more errors!
if ( val == CBotNoErr && pile1->GetTimer() < 0 ) // mode step?
return false; // does not make the catch
@ -124,8 +124,7 @@ bool CBotTry::Execute(CBotStack* &pj)
{
if ( --state <= 0 )
{
// request to the catch block if they feel concerned
// demande au bloc catch s'il se sent concerné
// ask to the catch block if it feels concerned
if ( !pc->TestCatch(pile2, val) ) return false; // suspend !
pile1->IncState();
}
@ -200,8 +199,7 @@ void CBotTry::RestoreState(CBotStack* &pj, bool bMain)
{
if ( --state <= 0 )
{
// request to the catch block if they feel concerned
// demande au bloc catch s'il se sent concerné
// ask to the catch block if it feels concerned
pc->RestoreCondState(pile2, bMain); // suspend !
return;
}

View File

@ -133,8 +133,7 @@ static bool TypeOk(int type, int test)
}
}
////////////////////////////////////////////////////////////////////////////////
CBotInstr* CBotTwoOpExpr::Compile(CBotToken* &p, CBotCStack* pStack, int* pOperations)
CBotInstr* CBotTwoOpExpr::Compile(CBotToken* &p, CBotCStack* pStack, int* pOperations, bool bConstExpr)
{
int typeMask;
@ -146,8 +145,8 @@ CBotInstr* CBotTwoOpExpr::Compile(CBotToken* &p, CBotCStack* pStack, int* pOpera
// search the intructions that may be suitable to the left of the operation
CBotInstr* left = (*pOp == 0) ?
CBotParExpr::Compile( p, pStk ) : // expression (...) left
CBotTwoOpExpr::Compile( p, pStk, pOp ); // expression A * B left
CBotParExpr::Compile(p, pStk, bConstExpr) : // expression (...) left
CBotTwoOpExpr::Compile(p, pStk, pOp, bConstExpr); // expression A * B left
if (left == nullptr) return pStack->Return(nullptr, pStk); // if error, transmit
@ -158,7 +157,7 @@ CBotInstr* CBotTwoOpExpr::Compile(CBotToken* &p, CBotCStack* pStack, int* pOpera
CBotTypResult type1, type2;
type1 = pStk->GetTypResult(); // what kind of the first operand?
if (typeOp == ID_LOGIC) // special case provided for: ? op1: op2;
if (!bConstExpr && typeOp == ID_LOGIC) // special case provided for: ? op1: op2;
{
if ( !type1.Eq(CBotTypBoolean) )
{
@ -207,7 +206,7 @@ CBotInstr* CBotTwoOpExpr::Compile(CBotToken* &p, CBotCStack* pStack, int* pOpera
// looking statements that may be suitable for right
if ( nullptr != (inst->m_rightop = CBotTwoOpExpr::Compile( p, pStk, pOp )) )
if ( nullptr != (inst->m_rightop = CBotTwoOpExpr::Compile(p, pStk, pOp, bConstExpr)) )
// expression (...) right
{
// there is an second operand acceptable
@ -264,7 +263,7 @@ CBotInstr* CBotTwoOpExpr::Compile(CBotToken* &p, CBotCStack* pStack, int* pOpera
type1 = TypeRes;
p = p->GetNext(); // advance after
i->m_rightop = CBotTwoOpExpr::Compile( p, pStk, pOp );
i->m_rightop = CBotTwoOpExpr::Compile(p, pStk, pOp, bConstExpr);
type2 = pStk->GetTypResult();
if ( !TypeCompatible (type1, type2, typeOp) ) // the results are compatible
@ -359,7 +358,7 @@ bool CBotTwoOpExpr::Execute(CBotStack* &pStack)
CBotStack* pStk2 = pStk1->AddStack(); // adds an item to the stack
// or return in case of recovery
// 2e état, évalue l'opérande de droite
// 2nd state, evalute right operand
if ( pStk2->GetState() == 0 )
{
if ( !m_rightop->Execute(pStk2) ) return false; // interrupted here?
@ -399,7 +398,10 @@ bool CBotTwoOpExpr::Execute(CBotStack* &pStack)
TypeRes = CBotTypBoolean;
break;
case ID_DIV:
TypeRes = std::max(TypeRes, static_cast<int>(CBotTypFloat));
if (TypeRes == CBotTypFloat)
{
if (type1.Eq(CBotTypLong) || type2.Eq(CBotTypLong)) TypeRes = CBotTypDouble;
}
}
// creates a variable for the result

View File

@ -65,7 +65,7 @@ public:
* \param pOperations
* \return
*/
static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack, int* pOperations = nullptr);
static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack, int* pOperations = nullptr, bool bConstExpr = false);
/*!
* \brief Execute Performes the operation on two operands.

View File

@ -56,8 +56,7 @@ CBotInstr* CBotWhile::Compile(CBotToken* &p, CBotCStack* pStack)
inst->SetToken(p);
if (!IsOfType(p, ID_WHILE)) return nullptr; // should never happen
CBotCStack* pStk = pStack->TokenStack(pp); // un petit bout de pile svp
// a bit of battery please (??)
CBotCStack* pStk = pStack->TokenStack(pp); // some space for a stack, plz
if ( nullptr != (inst->m_condition = CBotCondition::Compile(p, pStk )) )
{

View File

@ -24,7 +24,6 @@
#include "CBot/CBotCStack.h"
#include "CBot/CBotClass.h"
#include "CBot/CBotUtils.h"
#include "CBot/CBotFileUtils.h"
#include "CBot/CBotInstr/CBotFunction.h"
@ -332,51 +331,56 @@ bool CBotProgram::DefineNum(const std::string& name, long val)
}
////////////////////////////////////////////////////////////////////////////////
bool CBotProgram::SaveState(FILE* pf)
bool CBotProgram::SaveState(std::ostream &ostr)
{
if (!WriteWord( pf, CBOTVERSION)) return false;
if (!WriteLong(ostr, CBOTVERSION)) return false;
if (m_stack != nullptr )
{
if (!WriteWord( pf, 1)) return false;
if (!WriteString( pf, m_entryPoint->GetName() )) return false;
if (!m_stack->SaveState(pf)) return false;
if (!WriteWord(ostr, 1)) return false;
if (!WriteString(ostr, m_entryPoint->GetName())) return false;
if (!m_stack->SaveState(ostr)) return false;
}
else
{
if (!WriteWord( pf, 0)) return false;
if (!WriteWord(ostr, 0)) return false;
}
return true;
}
bool CBotProgram::RestoreState(FILE* pf)
bool CBotProgram::RestoreState(std::istream &istr)
{
unsigned short w;
std::string s;
Stop();
if (!ReadWord( pf, w )) return false;
if ( w != CBOTVERSION ) return false;
long version;
if (!ReadLong(istr, version)) return false;
if ( version != CBOTVERSION ) return false;
if (!ReadWord( pf, w )) return false;
if (!ReadWord(istr, w)) return false;
if ( w == 0 ) return true;
if (!ReadString( pf, s )) return false;
Start(s); // point de reprise
// don't restore if compile error exists
if (m_error != CBotNoErr) return false;
if (m_stack != nullptr)
if (!ReadString(istr, s)) return false;
if (!Start(s)) return false; // point de reprise
// Start() already created the new stack
// and called m_stack->SetProgram(this);
// retrieves the stack from the memory
if (!m_stack->RestoreState(istr, m_stack))
{
m_stack->Delete();
m_stack = nullptr;
m_stack = CBotStack::AllocateStack(); // start from the top
m_stack->SetProgram(this);
return false; // signal error
}
// retrieves the stack from the memory
m_stack = CBotStack::AllocateStack();
if (!m_stack->RestoreState(pf, m_stack)) return false;
m_stack->SetProgram(this); // bases for routines
// restored some states in the stack according to the structure
m_entryPoint->RestoreState(nullptr, m_stack, m_thisVar);
return true;

View File

@ -282,27 +282,20 @@ public:
/**
* \brief Save the current execution status into a file
* \param pf
* \parblock
* file handle
*
* This file handle must have been opened by this library! Otherwise crashes on Windows
*
* TODO: Verify this
* \endparblock
* \param ostr Output stream
* \return true on success, false on write error
*/
bool SaveState(FILE* pf);
bool SaveState(std::ostream &ostr);
/**
* \brief Restore the execution state from a file
*
* The previous program code must already have been recompiled with Compile() before calling this function
*
* \param pf file handle
* \param istr Input stream
* \return true on success, false on read error
*/
bool RestoreState(FILE* pf);
bool RestoreState(std::istream &istr);
/**
* \brief GetPosition Gives the position of a routine in the original text

View File

@ -26,7 +26,6 @@
#include "CBot/CBotVar/CBotVarPointer.h"
#include "CBot/CBotVar/CBotVarClass.h"
#include "CBot/CBotFileUtils.h"
#include "CBot/CBotUtils.h"
#include "CBot/CBotExternalCall.h"
@ -687,108 +686,106 @@ CBotVar* CBotStack::GetStackVars(std::string& functionName, int level)
}
////////////////////////////////////////////////////////////////////////////////
bool CBotStack::SaveState(FILE* pf)
bool CBotStack::SaveState(std::ostream &ostr)
{
if (m_next2 != nullptr)
{
if (!WriteWord(pf, 2)) return false; // a marker of type (m_next2)
if (!m_next2->SaveState(pf)) return false; // saves the next element
if (!WriteWord(ostr, 2)) return false; // a marker of type (m_next2)
if (!m_next2->SaveState(ostr)) return false; // saves the next element
}
else
{
if (!WriteWord(pf, 1)) return false; // a marker of type (m_next)
if (!WriteWord(ostr, 1)) return false; // a marker of type (m_next)
}
if (!WriteWord(pf, static_cast<unsigned short>(m_block))) return false;
if (!WriteWord(pf, m_state)) return false;
if (!WriteWord(pf, 0)) return false; // for backwards combatibility (m_bDontDelete)
if (!WriteWord(pf, m_step)) return false;
if (!WriteWord(ostr, static_cast<unsigned short>(m_block))) return false;
if (!WriteInt(ostr, m_state)) return false;
if (!WriteWord(ostr, 0)) return false; // for backwards combatibility (m_bDontDelete)
if (!WriteInt(ostr, m_step)) return false;
if (!SaveVars(pf, m_var)) return false; // current result
if (!SaveVars(pf, m_listVar)) return false; // local variables
if (!SaveVars(ostr, m_var)) return false; // current result
if (!SaveVars(ostr, m_listVar)) return false; // local variables
if (m_next != nullptr)
{
if (!m_next->SaveState(pf)) return false; // saves the next element
if (!m_next->SaveState(ostr)) return false; // saves the next element
}
else
{
if (!WriteWord(pf, 0)) return false; // terminator
if (!WriteWord(ostr, 0)) return false; // 0 - CBotStack::SaveState terminator
}
return true;
}
bool SaveVars(FILE* pf, CBotVar* pVar)
bool SaveVars(std::ostream &ostr, CBotVar* pVar)
{
while (pVar != nullptr)
{
if (!pVar->Save0State(pf)) return false; // common header
if (!pVar->Save1State(pf)) return false; // saves the data
if (!pVar->Save0State(ostr)) return false; // common header
if (!pVar->Save1State(ostr)) return false; // saves the data
pVar = pVar->GetNext();
}
return WriteWord(pf, 0); // terminator
return WriteWord(ostr, 0); // 0 - CBot::SaveVars terminator
}
////////////////////////////////////////////////////////////////////////////////
bool CBotStack::RestoreState(FILE* pf, CBotStack* &pStack)
bool CBotStack::RestoreState(std::istream &istr, CBotStack* &pStack)
{
unsigned short w;
if (pStack != this) pStack = nullptr;
if (!ReadWord(pf, w)) return false;
if ( w == 0 ) return true; // 0 - terminator
if (!ReadWord(istr, w)) return false;
if ( w == 0 ) return true; // 0 - CBotStack::SaveState terminator
if (pStack == nullptr) pStack = AddStack();
if ( w == 2 ) // 2 - m_next2
{
if (!pStack->RestoreState(pf, pStack->m_next2)) return false;
if (!pStack->RestoreState(istr, pStack->m_next2)) return false;
}
if (!ReadWord(pf, w)) return false;
if (!ReadWord(istr, w)) return false;
pStack->m_block = static_cast<BlockVisibilityType>(w);
if (!ReadWord(pf, w)) return false;
pStack->SetState(static_cast<short>(w));
int state;
if (!ReadInt(istr, state)) return false;
pStack->SetState(state);
if (!ReadWord(pf, w)) return false; // backwards compatibility (m_bDontDelete)
if (!ReadWord(istr, w)) return false; // backwards compatibility (m_bDontDelete)
if (!ReadWord(pf, w)) return false;
pStack->m_step = w;
if (!ReadInt(istr, state)) return false;
pStack->m_step = state;
if (!CBotVar::RestoreState(pf, pStack->m_var)) return false; // temp variable
if (!CBotVar::RestoreState(pf, pStack->m_listVar)) return false;// local variables
if (!CBotVar::RestoreState(istr, pStack->m_var)) return false; // temp variable
if (!CBotVar::RestoreState(istr, pStack->m_listVar)) return false; // local variables
return pStack->RestoreState(pf, pStack->m_next);
return pStack->RestoreState(istr, pStack->m_next);
}
////////////////////////////////////////////////////////////////////////////////
bool CBotVar::Save0State(FILE* pf)
bool CBotVar::Save0State(std::ostream &ostr)
{
if (!WriteWord(pf, 100+static_cast<int>(m_mPrivate)))return false; // private variable?
if (!WriteWord(pf, m_bStatic))return false; // static variable?
if (!WriteWord(pf, m_type.GetType()))return false; // saves the type (always non-zero)
if (!WriteWord(ostr, 100+static_cast<int>(m_mPrivate)))return false; // private variable?
if (!WriteWord(ostr, m_bStatic))return false; // static variable?
if (!WriteWord(ostr, m_type.GetType()))return false; // saves the type (always non-zero)
if (m_type.Eq(CBotTypPointer) && GetPointer() != nullptr)
{
if (GetPointer()->m_bConstructor) // constructor was called?
{
if (!WriteWord(pf, (2000 + static_cast<unsigned short>(m_binit)) )) return false;
return WriteString(pf, m_token->GetString()); // and variable name
if (!WriteWord(ostr, (2000 + static_cast<unsigned short>(m_binit)) )) return false;
return WriteString(ostr, m_token->GetString()); // and variable name
}
}
if (!WriteWord(pf, static_cast<unsigned short>(m_binit))) return false; // variable defined?
return WriteString(pf, m_token->GetString()); // and variable name
if (!WriteWord(ostr, static_cast<unsigned short>(m_binit))) return false; // variable defined?
return WriteString(ostr, m_token->GetString()); // and variable name
}
////////////////////////////////////////////////////////////////////////////////
bool CBotVar::RestoreState(FILE* pf, CBotVar* &pVar)
bool CBotVar::RestoreState(std::istream &istr, CBotVar* &pVar)
{
unsigned short w, wi, prv, st;
float ww;
std::string name, s;
delete pVar;
@ -798,27 +795,27 @@ bool CBotVar::RestoreState(FILE* pf, CBotVar* &pVar)
while ( true ) // retrieves a list
{
if (!ReadWord(pf, w)) return false; // private or type?
if ( w == 0 ) return true;
if (!ReadWord(istr, w)) return false; // private or type?
if ( w == 0 ) return true; // 0 - CBot::SaveVars terminator
std::string defnum;
if ( w == 200 )
{
if (!ReadString(pf, defnum)) return false; // number with identifier
if (!ReadWord(pf, w)) return false; // type
if (!ReadString(istr, defnum)) return false; // number with identifier
if (!ReadWord(istr, w)) return false; // type
}
prv = 100; st = 0;
if ( w >= 100 )
{
prv = w;
if (!ReadWord(pf, st)) return false; // static
if (!ReadWord(pf, w)) return false; // type
if (!ReadWord(istr, st)) return false; // static
if (!ReadWord(istr, w)) return false; // type
}
if ( w == CBotTypClass ) w = CBotTypIntrinsic; // necessarily intrinsic
if (!ReadWord(pf, wi)) return false; // init ?
if (!ReadWord(istr, wi)) return false; // init ?
bool bConstructor = false;
if (w == CBotTypPointer && wi >= 2000)
{
@ -827,31 +824,70 @@ bool CBotVar::RestoreState(FILE* pf, CBotVar* &pVar)
}
CBotVar::InitType initType = static_cast<CBotVar::InitType>(wi);
if (!ReadString(pf, name)) return false; // variable name
CBotToken token(name, std::string());
std::string varname;
if (!ReadString(istr, varname)) return false; // variable name
CBotToken token(varname, std::string());
bool isClass = false;
switch (w)
{
case CBotTypInt:
case CBotTypBoolean:
char valBool;
if (!ReadByte(istr, valBool)) return false;
pNew = CBotVar::Create(token, w); // creates a variable
if (!ReadWord(pf, w)) return false;
pNew->SetValInt(static_cast<short>(w), defnum);
pNew->SetValInt(valBool);
break;
case CBotTypByte:
char valByte;
if (!ReadByte(istr, valByte)) return false;
pNew = CBotVar::Create(token, w); // creates a variable
pNew->SetValByte(valByte);
break;
case CBotTypShort:
short valShort;
if (!ReadShort(istr, valShort)) return false;
pNew = CBotVar::Create(token, w); // creates a variable
pNew->SetValShort(valShort);
break;
case CBotTypChar:
uint32_t valChar;
if (!ReadUInt32(istr, valChar)) return false;
pNew = CBotVar::Create(token, w); // creates a variable
pNew->SetValChar(valChar);
break;
case CBotTypInt:
int valInt;
if (!ReadInt(istr, valInt)) return false;
pNew = CBotVar::Create(token, w); // creates a variable
pNew->SetValInt(valInt, defnum);
break;
case CBotTypLong:
long valLong;
if (!ReadLong(istr, valLong)) return false;
pNew = CBotVar::Create(token, w); // creates a variable
pNew->SetValInt(valLong);
break;
case CBotTypFloat:
float valFloat;
if (!ReadFloat(istr, valFloat)) return false;
pNew = CBotVar::Create(token, w); // creates a variable
if (!ReadFloat(pf, ww)) return false;
pNew->SetValFloat(ww);
pNew->SetValFloat(valFloat);
break;
case CBotTypDouble:
double valDouble;
if (!ReadDouble(istr, valDouble)) return false;
pNew = CBotVar::Create(token, w); // creates a variable
pNew->SetValDouble(valDouble);
break;
case CBotTypString:
pNew = CBotVar::Create(token, w); // creates a variable
if (!ReadString(pf, s)) return false;
pNew->SetValString(s);
break;
{
std::string valString;
if (!ReadString(istr, valString)) return false;
pNew = CBotVar::Create(token, w); // creates a variable
pNew->SetValString(valString);
break;
}
// returns an intrinsic object or element of an array
case CBotTypIntrinsic:
isClass = true;
@ -859,17 +895,16 @@ bool CBotVar::RestoreState(FILE* pf, CBotVar* &pVar)
{
CBotTypResult r;
long id;
if (!ReadType(pf, r)) return false; // complete type
if (!ReadLong(pf, id) ) return false;
if (!ReadType(istr, r)) return false; // complete type
if (!ReadLong(istr, id)) return false;
// if (!ReadString(pf, s)) return false;
{
CBotVar* p = nullptr;
if ( id ) p = CBotVarClass::Find(id) ;
pNew = new CBotVarClass(token, r); // directly creates an instance
// attention cptuse = 0
if ( !RestoreState(pf, (static_cast<CBotVarClass*>(pNew))->m_pVar)) return false;
if (!RestoreState(istr, (static_cast<CBotVarClass*>(pNew))->m_pVar)) return false;
pNew->SetIdent(id);
if (isClass && p == nullptr) // set id for each item in this instance
@ -895,18 +930,20 @@ bool CBotVar::RestoreState(FILE* pf, CBotVar* &pVar)
case CBotTypPointer:
case CBotTypNullPointer:
if (!ReadString(pf, s)) return false; // name of the class
{
std::string className;
if (!ReadString(istr, className)) return false; // name of the class
{
CBotTypResult ptrType(w, s);
pNew = CBotVar::Create(token, ptrType);// creates a variable
// CBotVarClass* p = nullptr;
long id;
ReadLong(pf, id);
if (!ReadLong(istr, id)) return false;
// if ( id ) p = CBotVarClass::Find(id); // found the instance (made by RestoreInstance)
CBotTypResult ptrType(w, className);
pNew = CBotVar::Create(token, ptrType); // creates a variable
// returns a copy of the original instance
CBotVar* pInstance = nullptr;
if ( !CBotVar::RestoreState( pf, pInstance ) ) return false;
if (!CBotVar::RestoreState(istr, pInstance)) return false;
(static_cast<CBotVarPointer*>(pNew))->SetPointer( pInstance ); // and point over
if (bConstructor) pNew->ConstructorSet(); // constructor was called
@ -916,22 +953,22 @@ bool CBotVar::RestoreState(FILE* pf, CBotVar* &pVar)
}
break;
}
case CBotTypArrayPointer:
{
CBotTypResult r;
if (!ReadType(pf, r)) return false;
if (!ReadType(istr, r)) return false;
pNew = CBotVar::Create(token, r); // creates a variable
// returns a copy of the original instance
CBotVar* pInstance = nullptr;
if ( !CBotVar::RestoreState( pf, pInstance ) ) return false;
if (!CBotVar::RestoreState(istr, pInstance)) return false;
(static_cast<CBotVarPointer*>(pNew))->SetPointer( pInstance ); // and point over
}
break;
default:
assert(0);
return false; // signal error
}
if ( pPrev != nullptr ) pPrev->m_next = pNew;

View File

@ -434,8 +434,8 @@ public:
//! \name Write to file
//@{
bool SaveState(FILE* pf);
bool RestoreState(FILE* pf, CBotStack* &pStack);
bool SaveState(std::ostream &ostr);
bool RestoreState(std::istream &istr, CBotStack* &pStack);
//@}

View File

@ -26,7 +26,8 @@
namespace CBot
{
namespace {
namespace
{
template <typename L, typename R>
boost::bimap<L, R> makeBimap(std::initializer_list<typename boost::bimap<L, R>::value_type> list)
{
@ -70,6 +71,11 @@ static const boost::bimap<TokenId, std::string> KEYWORDS = makeBimap<TokenId, st
{ID_STRING, "string"},
{ID_VOID, "void"},
{ID_BOOL, "bool"},
{ID_BYTE, "byte"},
{ID_SHORT, "short"},
{ID_CHAR, "char"},
{ID_LONG, "long"},
{ID_DOUBLE, "double"},
{ID_TRUE, "true"},
{ID_FALSE, "false"},
{ID_NULL, "null"},
@ -102,7 +108,7 @@ static const boost::bimap<TokenId, std::string> KEYWORDS = makeBimap<TokenId, st
{ID_ASSSR, ">>>="},
{ID_ASSASR, ">>="},
{ID_SL, "<<"},
{ID_SR, ">>"},
{ID_SR, ">>>"},
{ID_ASR, ">>"},
{ID_INC, "++"},
{ID_DEC, "--"},
@ -298,12 +304,53 @@ CBotToken* CBotToken::NextToken(const char*& program, bool first)
stop = true;
}
// special case for characters
if (token[0] == '\'')
{
if (c == '\\') // escape sequence
{
token += c;
c = *(program++);
if (c == 'u' || c == 'U') // unicode escape
{
int maxlen = (c == 'u') ? 4 : 8;
token += c;
c = *(program++);
for (int i = 0; i < maxlen; i++)
{
if (c == 0 || !CharInList(c, hexnum)) break;
token += c;
c = *(program++);
}
}
else if (c != 0 && !CharInList(c, nch)) // other escape char
{
token += c;
c = *(program++);
}
}
else if (c != 0 && c != '\'' && !CharInList(c, nch)) // single character
{
token += c;
c = *(program++);
}
if (c == '\'') // close quote
{
token += c;
c = *(program++);
}
stop = true;
}
// special case for numbers
if ( CharInList(token[0], num ))
{
bool bdot = false; // found a point?
bool bexp = false; // found an exponent?
char bin[] = "01";
char* liste = num;
if (token[0] == '0' && c == 'x') // hexadecimal value?
{
@ -311,6 +358,12 @@ CBotToken* CBotToken::NextToken(const char*& program, bool first)
c = *(program++); // next character
liste = hexnum;
}
else if (token[0] == '0' && c == 'b') // binary literal
{
liste = bin;
token += c;
c = *(program++);
}
cw:
while (c != 0 && CharInList(c, liste))
{
@ -393,6 +446,7 @@ bis:
if (CharInList(token[0], num )) t->m_type = TokenTypNum;
if (token[0] == '\"') t->m_type = TokenTypString;
if (token[0] == '\'') t->m_type = TokenTypChar;
if (first) t->m_type = TokenTypNone;
t->m_keywordId = GetKeyWord(token);
@ -449,10 +503,11 @@ std::unique_ptr<CBotToken> CBotToken::CompileTokens(const std::string& program)
////////////////////////////////////////////////////////////////////////////////
int CBotToken::GetKeyWord(const std::string& w)
{
auto it = KEYWORDS.right.find(w);
if (it != KEYWORDS.right.end()) {
return it->second;
}
auto it = KEYWORDS.right.find(w);
if (it != KEYWORDS.right.end())
{
return it->second;
}
return -1;
}

View File

@ -185,8 +185,13 @@ std::string CBotTypResult::ToString()
switch (m_type)
{
case CBotTypVoid: return "void";
case CBotTypByte: return "byte";
case CBotTypShort: return "short";
case CBotTypChar: return "char";
case CBotTypInt: return "int";
case CBotTypLong: return "long";
case CBotTypFloat: return "float";
case CBotTypDouble: return "double";
case CBotTypBoolean: return "bool";
case CBotTypString: return "string";
case CBotTypArrayPointer: return m_next->ToString() + "[]";

View File

@ -62,12 +62,27 @@ CBotTypResult TypeParam(CBotToken* &p, CBotCStack* pile)
switch (p->GetType())
{
case ID_BYTE:
p = p->GetNext();
return ArrayType(p, pile, CBotTypResult( CBotTypByte ));
case ID_SHORT:
p = p->GetNext();
return ArrayType(p, pile, CBotTypResult( CBotTypShort ));
case ID_CHAR:
p = p->GetNext();
return ArrayType(p, pile, CBotTypResult( CBotTypChar ));
case ID_INT:
p = p->GetNext();
return ArrayType(p, pile, CBotTypResult( CBotTypInt ));
case ID_LONG:
p = p->GetNext();
return ArrayType(p, pile, CBotTypResult( CBotTypLong ));
case ID_FLOAT:
p = p->GetNext();
return ArrayType(p, pile, CBotTypResult( CBotTypFloat ));
case ID_DOUBLE:
p = p->GetNext();
return ArrayType(p, pile, CBotTypResult( CBotTypDouble ));
case ID_BOOLEAN:
case ID_BOOL:
p = p->GetNext();
@ -108,38 +123,6 @@ CBotTypResult ArrayType(CBotToken* &p, CBotCStack* pile, CBotTypResult type)
return type;
}
////////////////////////////////////////////////////////////////////////////////
bool WriteWord(FILE* pf, unsigned short w)
{
size_t lg;
lg = fwrite(&w, sizeof( unsigned short ), 1, pf );
return (lg == 1);
}
////////////////////////////////////////////////////////////////////////////////
bool WriteString(FILE* pf, std::string s)
{
size_t lg1, lg2;
lg1 = s.size();
if (!WriteWord(pf, lg1)) return false;
lg2 = fwrite(s.c_str(), 1, lg1, pf );
return (lg1 == lg2);
}
////////////////////////////////////////////////////////////////////////////////
bool WriteFloat(FILE* pf, float w)
{
size_t lg;
lg = fwrite(&w, sizeof( float ), 1, pf );
return (lg == 1);
}
////////////////////////////////////////////////////////////////////////////////
long GetNumInt(const std::string& str)
{
@ -172,11 +155,23 @@ long GetNumInt(const std::string& str)
break;
}
}
else if (*p == 'b')
{
while (*++p != 0)
{
if (*p == '0' || *p == '1')
{
num = (num << 1) + *p - '0';
continue;
}
break;
}
}
return num;
}
////////////////////////////////////////////////////////////////////////////////
float GetNumFloat(const std::string& str)
double GetNumFloat(const std::string& str)
{
const char* p = str.c_str();
double num = 0;
@ -233,7 +228,7 @@ float GetNumFloat(const std::string& str)
}
if (bNeg) num = -num;
return static_cast<float>(num);
return num;
}
bool CharInList(const char c, const char* list)

View File

@ -19,9 +19,8 @@
#pragma once
#include "CBot/CBotTypResult.h"
#include "CBot/CBotFileUtils.h"
#include <cstdio>
#include <string>
#include <cassert>
@ -31,6 +30,8 @@ namespace CBot
class CBotVar;
class CBotToken;
class CBotCStack;
class CBotTypResult;
/*!
* \brief MakeListVars Transforms the array of pointers to variables in a
@ -58,30 +59,6 @@ CBotTypResult TypeParam(CBotToken* &p, CBotCStack* pile);
*/
CBotTypResult ArrayType(CBotToken* &p, CBotCStack* pile, CBotTypResult type);
/*!
* \brief WriteWord
* \param pf
* \param w
* \return
*/
bool WriteWord(FILE* pf, unsigned short w);
/*!
* \brief WriteString
* \param pf
* \param s
* \return
*/
bool WriteString(FILE* pf, std::string s);
/*!
* \brief WriteFloat
* \param pf
* \param w
* \return
*/
bool WriteFloat(FILE* pf, float w);
/*!
* \brief GetNumInt Converts a string into integer may be of the form 0xabc123.
* \param str
@ -94,7 +71,7 @@ long GetNumInt(const std::string& str);
* \param str
* \return
*/
float GetNumFloat(const std::string& str);
double GetNumFloat(const std::string& str);
/*!
* \brief Search a null-terminated string for a char value.

View File

@ -24,12 +24,17 @@
#include "CBot/CBotInstr/CBotInstr.h"
#include "CBot/CBotVar/CBotVarArray.h"
#include "CBot/CBotVar/CBotVarPointer.h"
#include "CBot/CBotVar/CBotVarClass.h"
#include "CBot/CBotVar/CBotVarBoolean.h"
#include "CBot/CBotVar/CBotVarString.h"
#include "CBot/CBotVar/CBotVarByte.h"
#include "CBot/CBotVar/CBotVarChar.h"
#include "CBot/CBotVar/CBotVarClass.h"
#include "CBot/CBotVar/CBotVarDouble.h"
#include "CBot/CBotVar/CBotVarFloat.h"
#include "CBot/CBotVar/CBotVarInt.h"
#include "CBot/CBotVar/CBotVarLong.h"
#include "CBot/CBotVar/CBotVarPointer.h"
#include "CBot/CBotVar/CBotVarShort.h"
#include "CBot/CBotVar/CBotVarString.h"
#include "CBot/CBotClass.h"
#include "CBot/CBotToken.h"
@ -134,7 +139,7 @@ void* CBotVar::GetUserPtr()
}
////////////////////////////////////////////////////////////////////////////////
bool CBotVar::Save1State(FILE* pf)
bool CBotVar::Save1State(std::ostream &ostr)
{
// this routine "virtual" must never be called,
// there must be a routine for each of the subclasses (CBotVarInt, CBotVarFloat, etc)
@ -160,11 +165,20 @@ CBotVar* CBotVar::Create(const CBotToken& name, CBotTypResult type)
{
switch (type.GetType())
{
case CBotTypByte:
return new CBotVarByte(name);
case CBotTypShort:
return new CBotVarShort(name);
case CBotTypChar:
return new CBotVarChar(name);
case CBotTypInt:
return new CBotVarInt(name);
case CBotTypLong:
return new CBotVarLong(name);
case CBotTypFloat:
return new CBotVarFloat(name);
case CBotTypDouble:
return new CBotVarDouble(name);
case CBotTypBoolean:
return new CBotVarBoolean(name);
case CBotTypString:
@ -223,11 +237,20 @@ CBotVar* CBotVar::Create(const std::string& n, CBotTypResult type)
switch (type.GetType())
{
case CBotTypByte:
return new CBotVarByte(name);
case CBotTypShort:
return new CBotVarShort(name);
case CBotTypChar:
return new CBotVarChar(name);
case CBotTypInt:
return new CBotVarInt(name);
case CBotTypLong:
return new CBotVarLong(name);
case CBotTypFloat:
return new CBotVarFloat(name);
case CBotTypDouble:
return new CBotVarDouble(name);
case CBotTypBoolean:
return new CBotVarBoolean(name);
case CBotTypString:
@ -359,7 +382,7 @@ CBotVar::InitType CBotVar::GetInit() const
void CBotVar::SetInit(CBotVar::InitType initType)
{
m_binit = initType;
if (initType == CBotVar::InitType::IS_POINTER ) m_binit = CBotVar::InitType::DEF; // cas spécial
if (initType == CBotVar::InitType::IS_POINTER ) m_binit = CBotVar::InitType::DEF; // special case
if ( m_type.Eq(CBotTypPointer) && initType == CBotVar::InitType::IS_POINTER )
{
@ -472,12 +495,27 @@ void CBotVar::SetVal(CBotVar* var)
case CBotTypBoolean:
SetValInt(var->GetValInt());
break;
case CBotTypByte:
SetValByte(var->GetValByte());
break;
case CBotTypShort:
SetValShort(var->GetValShort());
break;
case CBotTypChar:
SetValChar(var->GetValChar());
break;
case CBotTypInt:
SetValInt(var->GetValInt(), (static_cast<CBotVarInt*>(var))->m_defnum);
break;
case CBotTypLong:
SetValLong(var->GetValLong());
break;
case CBotTypFloat:
SetValFloat(var->GetValFloat());
break;
case CBotTypDouble:
SetValDouble(var->GetValDouble());
break;
case CBotTypString:
SetValString(var->GetValString());
break;
@ -497,7 +535,7 @@ void CBotVar::SetVal(CBotVar* var)
assert(0);
}
m_binit = var->m_binit; // copie l'état nan s'il y a
m_binit = var->m_binit; // copy the nan status if it has
}
////////////////////////////////////////////////////////////////////////////////
@ -545,33 +583,84 @@ CBotVarClass* CBotVar::GetPointer()
// All these functions must be defined in the subclasses
// derived from class CBotVar
////////////////////////////////////////////////////////////////////////////////
signed char CBotVar::GetValByte()
{
assert(0);
return 0;
}
short CBotVar::GetValShort()
{
assert(0);
return 0;
}
uint32_t CBotVar::GetValChar()
{
assert(0);
return 0;
}
int CBotVar::GetValInt()
{
assert(0);
return 0;
}
////////////////////////////////////////////////////////////////////////////////
long CBotVar::GetValLong()
{
assert(0);
return 0;
}
float CBotVar::GetValFloat()
{
assert(0);
return 0;
}
////////////////////////////////////////////////////////////////////////////////
double CBotVar::GetValDouble()
{
assert(0);
return 0;
}
void CBotVar::SetValByte(signed char val)
{
assert(false);
}
void CBotVar::SetValShort(short val)
{
assert(false);
}
void CBotVar::SetValChar(uint32_t val)
{
assert(false);
}
void CBotVar::SetValInt(int c, const std::string& s)
{
assert(0);
}
////////////////////////////////////////////////////////////////////////////////
void CBotVar::SetValLong(long val)
{
assert(false);
}
void CBotVar::SetValFloat(float c)
{
assert(0);
}
////////////////////////////////////////////////////////////////////////////////
void CBotVar::SetValDouble(double val)
{
assert(false);
}
void CBotVar::Mul(CBotVar* left, CBotVar* right)
{
assert(0);
@ -752,16 +841,46 @@ CBotClass* CBotVar::GetClass()
return nullptr;
}
CBotVar::operator bool()
{
return static_cast<bool>(GetValInt());
}
CBotVar::operator signed char()
{
return GetValByte();
}
CBotVar::operator short()
{
return GetValShort();
}
CBotVar::operator uint32_t()
{
return GetValChar();
}
CBotVar::operator int()
{
return GetValInt();
}
CBotVar::operator long()
{
return GetValLong();
}
CBotVar::operator float()
{
return GetValFloat();
}
CBotVar::operator double()
{
return GetValDouble();
}
CBotVar::operator std::string()
{
return GetValString();
@ -772,16 +891,41 @@ void CBotVar::operator=(const CBotVar &var)
SetVal(const_cast<CBotVar*>(&var));
}
void CBotVar::operator=(signed char x)
{
SetValByte(x);
}
void CBotVar::operator=(short x)
{
SetValShort(x);
}
void CBotVar::operator=(uint32_t x)
{
SetValChar(x);
}
void CBotVar::operator=(int x)
{
SetValInt(x);
}
void CBotVar::operator=(long x)
{
SetValLong(x);
}
void CBotVar::operator=(float x)
{
SetValFloat(x);
}
void CBotVar::operator=(double x)
{
SetValDouble(x);
}
void CBotVar::operator=(const std::string &x)
{
SetValString(x);

View File

@ -444,12 +444,23 @@ public:
*/
//@{
operator bool();
operator signed char();
operator short();
operator uint32_t();
operator int();
operator long();
operator float();
operator double();
operator std::string();
void operator=(const CBotVar& var);
void operator=(signed char x);
void operator=(short x);
void operator=(uint32_t x);
void operator=(int x);
void operator=(long x);
void operator=(float x);
void operator=(double x);
void operator=(const std::string &x);
/**
@ -465,6 +476,12 @@ public:
*/
virtual void Copy(CBotVar* pSrc, bool bName = true);
virtual void SetValByte(signed char val);
virtual void SetValShort(short val);
virtual void SetValChar(uint32_t val);
/**
* \brief Set value as an integer
*
@ -475,30 +492,44 @@ public:
*/
virtual void SetValInt(int val, const std::string& name = "");
virtual void SetValLong(long val);
/**
* \brief Set value as float
* \param val New value
*/
virtual void SetValFloat(float val);
virtual void SetValDouble(double val);
/**
* \brief Set value as string
* \param val New value
*/
virtual void SetValString(const std::string& val);
virtual signed char GetValByte();
virtual short GetValShort();
virtual uint32_t GetValChar();
/**
* \brief Get value as integer
* \return Current value
*/
virtual int GetValInt();
virtual long GetValLong();
/**
* \brief Get value as float
* \return Current value
*/
virtual float GetValFloat();
virtual double GetValDouble();
/**
* \brief Get value as string
*
@ -623,28 +654,28 @@ public:
/**
* \brief Save common variable header (name, type, etc.)
* \param pf file pointer
* \param ostr Output stream
* \return false on write error
*/
virtual bool Save0State(FILE* pf);
virtual bool Save0State(std::ostream &ostr);
/**
* \brief Save variable data
*
* Overriden in child classes
*
* \param pf file pointer
* \param ostr Output stream
* \return false on write error
*/
virtual bool Save1State(FILE* pf);
virtual bool Save1State(std::ostream &ostr);
/**
* \brief Restore variable
* \param pf file pointer
* \param istr Input stream
* \param[out] pVar Pointer to recieve the variable
* \return false on read error
*/
static bool RestoreState(FILE* pf, CBotVar* &pVar);
static bool RestoreState(std::istream &istr, CBotVar* &pVar);
//@}

View File

@ -20,7 +20,6 @@
#include "CBot/CBotVar/CBotVarArray.h"
#include "CBot/CBotVar/CBotVarClass.h"
#include "CBot/CBotToken.h"
#include "CBot/CBotFileUtils.h"
#include "CBot/CBotEnums.h"
@ -94,7 +93,7 @@ void CBotVarArray::SetPointer(CBotVar* pVarClass)
!pVarClass->m_type.Eq(CBotTypArrayBody))
assert(0);
(static_cast<CBotVarClass*>(pVarClass))->IncrementUse(); // incement the reference
(static_cast<CBotVarClass*>(pVarClass))->IncrementUse(); // increment the reference
}
if ( m_pInstance != nullptr ) m_pInstance->DecrementUse();
@ -137,10 +136,10 @@ std::string CBotVarArray::GetValString()
}
////////////////////////////////////////////////////////////////////////////////
bool CBotVarArray::Save1State(FILE* pf)
bool CBotVarArray::Save1State(std::ostream &ostr)
{
if ( !WriteType(pf, m_type) ) return false;
return SaveVars(pf, m_pInstance); // saves the instance that manages the table
if (!WriteType(ostr, m_type)) return false;
return SaveVars(ostr, m_pInstance); // saves the instance that manages the table
}
} // namespace CBot

View File

@ -51,7 +51,7 @@ public:
std::string GetValString() override;
bool Save1State(FILE* pf) override;
bool Save1State(std::ostream &ostr) override;
private:
//! Array data

View File

@ -40,9 +40,9 @@ void CBotVarBoolean::Not()
SetValInt(!GetValInt());
}
bool CBotVarBoolean::Save1State(FILE* pf)
bool CBotVarBoolean::Save1State(std::ostream &ostr)
{
return WriteWord(pf, m_val); // the value of the variable
return WriteByte(ostr, m_val); // the value of the variable
}
} // namespace CBot

View File

@ -37,7 +37,7 @@ public:
void XOr(CBotVar* left, CBotVar* right) override;
void Not() override;
bool Save1State(FILE* pf) override;
bool Save1State(std::ostream &ostr) override;
};
} // namespace CBot

View File

@ -0,0 +1,46 @@
/*
* This file is part of the Colobot: Gold Edition source code
* Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://gnu.org/licenses
*/
#pragma once
#include "CBot/CBotVar/CBotVarValue.h"
namespace CBot
{
/**
* \brief CBotVar subclass for managing 1-byte integer values (::CBotTypByte)
*/
class CBotVarByte : public CBotVarInteger<signed char, CBotTypByte>
{
public:
CBotVarByte(const CBotToken &name) : CBotVarInteger(name) {}
void SR(CBotVar* left, CBotVar* right) override
{
SetValByte(static_cast<unsigned char>(left->GetValByte()) >> right->GetValInt());
}
bool Save1State(std::ostream &ostr) override
{
return WriteByte(ostr, m_val);
}
};
} // namespace CBot

View File

@ -0,0 +1,59 @@
/*
* This file is part of the Colobot: Gold Edition source code
* Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://gnu.org/licenses
*/
#pragma once
#include "CBot/CBotVar/CBotVarValue.h"
namespace CBot
{
/**
* \brief CBotVar subclass for managing 32-bit Unicode values (::CBotTypChar)
*/
class CBotVarChar : public CBotVarInteger<uint32_t, CBotTypChar>
{
public:
CBotVarChar(const CBotToken &name) : CBotVarInteger(name) {}
std::string GetValString() override
{
if (m_binit == CBotVar::InitType::UNDEF)
return LoadString(TX_UNDEF);
if (m_binit == CBotVar::InitType::IS_NAN)
return LoadString(TX_NAN);
if (0x10FFFF < m_val || (0xD7FF < m_val && m_val < 0xE000))
return "\xEF\xBF\xBD"; // replacement character U+FFFD
return CodePointToUTF8(m_val);
}
void SR(CBotVar* left, CBotVar* right) override
{
SetValChar(left->GetValChar() >> right->GetValInt());
}
bool Save1State(std::ostream &ostr) override
{
return WriteUInt32(ostr, m_val);
}
};
} // namespace CBot

View File

@ -23,8 +23,6 @@
#include "CBot/CBotStack.h"
#include "CBot/CBotDefines.h"
#include "CBot/CBotFileUtils.h"
#include "CBot/CBotInstr/CBotInstr.h"
#include <cassert>
@ -53,7 +51,7 @@ CBotVarClass::CBotVarClass(const CBotToken& name, const CBotTypResult& type) : C
m_type = type;
if ( type.Eq(CBotTypArrayPointer) ) m_type.SetType( CBotTypArrayBody );
else if ( !type.Eq(CBotTypArrayBody) ) m_type.SetType( CBotTypClass );
// officel type for this object
// official type for this object
m_pClass = nullptr;
m_pParent = nullptr;
@ -464,12 +462,12 @@ bool CBotVarClass::Ne(CBotVar* left, CBotVar* right)
}
////////////////////////////////////////////////////////////////////////////////
bool CBotVarClass::Save1State(FILE* pf)
bool CBotVarClass::Save1State(std::ostream &ostr)
{
if ( !WriteType(pf, m_type) ) return false;
if ( !WriteLong(pf, m_ItemIdent) ) return false;
if (!WriteType(ostr, m_type)) return false;
if (!WriteLong(ostr, m_ItemIdent)) return false;
return SaveVars(pf, m_pVar); // content of the object
return SaveVars(ostr, m_pVar); // content of the object
}
} // namespace CBot

View File

@ -54,7 +54,7 @@ public:
CBotVar* GetItemList() override;
std::string GetValString() override;
bool Save1State(FILE* pf) override;
bool Save1State(std::ostream &ostr) override;
void Update(void* pUser) override;

View File

@ -0,0 +1,41 @@
/*
* This file is part of the Colobot: Gold Edition source code
* Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://gnu.org/licenses
*/
#pragma once
#include "CBot/CBotVar/CBotVarValue.h"
namespace CBot
{
/**
* \brief CBotVar subclass for managing double values (::CBotTypDouble)
*/
class CBotVarDouble : public CBotVarNumber<double, CBotTypDouble>
{
public:
CBotVarDouble(const CBotToken &name) : CBotVarNumber(name) {}
bool Save1State(std::ostream &ostr) override
{
return WriteDouble(ostr, m_val);
}
};
} // namespace CBot

View File

@ -22,9 +22,9 @@
namespace CBot
{
bool CBotVarFloat::Save1State(FILE* pf)
bool CBotVarFloat::Save1State(std::ostream &ostr)
{
return WriteFloat(pf, m_val); // the value of the variable
return WriteFloat(ostr, m_val); // the value of the variable
}
} // namespace CBot

View File

@ -32,7 +32,7 @@ class CBotVarFloat : public CBotVarNumber<float, CBotTypFloat>
public:
CBotVarFloat(const CBotToken &name) : CBotVarNumber(name) {}
bool Save1State(FILE* pf) override;
bool Save1State(std::ostream &ostr) override;
};
} // namespace CBot

View File

@ -45,67 +45,44 @@ std::string CBotVarInt::GetValString()
void CBotVarInt::Neg()
{
CBotVarNumber::Neg();
m_defnum.empty();
m_defnum.clear();
}
void CBotVarInt::Inc()
{
CBotVarNumber::Inc();
m_defnum.empty();
m_defnum.clear();
}
void CBotVarInt::Dec()
{
CBotVarNumber::Dec();
m_defnum.empty();
m_defnum.clear();
}
void CBotVarInt::XOr(CBotVar* left, CBotVar* right)
{
SetValInt(left->GetValInt() ^ right->GetValInt());
}
void CBotVarInt::And(CBotVar* left, CBotVar* right)
{
SetValInt(left->GetValInt() & right->GetValInt());
}
void CBotVarInt::Or(CBotVar* left, CBotVar* right)
{
SetValInt(left->GetValInt() | right->GetValInt());
}
void CBotVarInt::SL(CBotVar* left, CBotVar* right)
{
SetValInt(left->GetValInt() << right->GetValInt());
}
void CBotVarInt::ASR(CBotVar* left, CBotVar* right)
{
SetValInt(left->GetValInt() >> right->GetValInt());
}
void CBotVarInt::SR(CBotVar* left, CBotVar* right)
{
int source = left->GetValInt();
int shift = right->GetValInt();
if (shift >= 1) source &= 0x7fffffff;
SetValInt(source >> shift);
SetValInt(static_cast<unsigned>(left->GetValInt()) >> right->GetValInt());
}
void CBotVarInt::Not()
{
m_val = ~m_val;
m_defnum.clear();
}
bool CBotVarInt::Save0State(FILE* pf)
bool CBotVarInt::Save0State(std::ostream &ostr)
{
if (!m_defnum.empty())
{
if(!WriteWord(pf, 200)) return false; // special marker
if(!WriteString(pf, m_defnum)) return false;
if(!WriteWord(ostr, 200)) return false; // special marker
if(!WriteString(ostr, m_defnum)) return false;
}
return CBotVar::Save0State(pf);
return CBotVar::Save0State(ostr);
}
bool CBotVarInt::Save1State(FILE* pf)
bool CBotVarInt::Save1State(std::ostream &ostr)
{
return WriteWord(pf, m_val);
return WriteInt(ostr, m_val);
}
} // namespace CBot

View File

@ -27,10 +27,10 @@ namespace CBot
/**
* \brief CBotVar subclass for managing integer values (::CBotTypInt)
*/
class CBotVarInt : public CBotVarNumber<int, CBotTypInt>
class CBotVarInt : public CBotVarInteger<int, CBotTypInt>
{
public:
CBotVarInt(const CBotToken &name) : CBotVarNumber(name) {}
CBotVarInt(const CBotToken &name) : CBotVarInteger(name) {}
void SetValInt(int val, const std::string& s = "") override;
std::string GetValString() override;
@ -40,18 +40,20 @@ public:
void Neg() override;
void Inc() override;
void Dec() override;
void XOr(CBotVar* left, CBotVar* right) override;
void Or(CBotVar* left, CBotVar* right) override;
void And(CBotVar* left, CBotVar* right) override;
void Not() override;
void SL(CBotVar* left, CBotVar* right) override;
void SR(CBotVar* left, CBotVar* right) override;
void ASR(CBotVar* left, CBotVar* right) override;
bool Save0State(FILE* pf) override;
bool Save1State(FILE* pf) override;
bool Save0State(std::ostream &ostr) override;
bool Save1State(std::ostream &ostr) override;
protected:
void SetValue(int val) override
{
CBotVarNumberBase::SetValue(val);
m_defnum.clear();
}
protected:
//! The name if given by DefineNum.

View File

@ -0,0 +1,46 @@
/*
* This file is part of the Colobot: Gold Edition source code
* Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://gnu.org/licenses
*/
#pragma once
#include "CBot/CBotVar/CBotVarValue.h"
namespace CBot
{
/**
* \brief CBotVar subclass for managing long integer values (::CBotTypLong)
*/
class CBotVarLong : public CBotVarInteger<long, CBotTypLong>
{
public:
CBotVarLong(const CBotToken &name) : CBotVarInteger(name) {}
void SR(CBotVar* left, CBotVar* right) override
{
SetValLong(static_cast<unsigned long>(left->GetValLong()) >> right->GetValInt());
}
bool Save1State(std::ostream &ostr) override
{
return WriteLong(ostr, m_val);
}
};
} // namespace CBot

View File

@ -24,7 +24,6 @@
#include "CBot/CBotEnums.h"
#include "CBot/CBotUtils.h"
#include "CBot/CBotFileUtils.h"
#include <cassert>
@ -171,21 +170,21 @@ CBotClass* CBotVarPointer::GetClass()
}
////////////////////////////////////////////////////////////////////////////////
bool CBotVarPointer::Save1State(FILE* pf)
bool CBotVarPointer::Save1State(std::ostream &ostr)
{
if ( m_type.GetClass() != nullptr )
{
if (!WriteString(pf, m_type.GetClass()->GetName())) return false; // name of the class
if (!WriteString(ostr, m_type.GetClass()->GetName())) return false; // name of the class
}
else
{
if (!WriteString(pf, "")) return false;
if (!WriteString(ostr, "")) return false;
}
if (!WriteLong(pf, GetIdent())) return false; // the unique reference
if (!WriteLong(ostr, GetIdent())) return false; // the unique reference
// also saves the proceedings copies
return SaveVars(pf, GetPointer());
return SaveVars(ostr, GetPointer());
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -61,7 +61,7 @@ public:
void ConstructorSet() override;
bool Save1State(FILE* pf) override;
bool Save1State(std::ostream &ostr) override;
void Update(void* pUser) override;

View File

@ -0,0 +1,46 @@
/*
* This file is part of the Colobot: Gold Edition source code
* Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://gnu.org/licenses
*/
#pragma once
#include "CBot/CBotVar/CBotVarValue.h"
namespace CBot
{
/**
* \brief CBotVar subclass for managing short integer values (::CBotTypShort)
*/
class CBotVarShort : public CBotVarInteger<short, CBotTypShort>
{
public:
CBotVarShort(const CBotToken &name) : CBotVarInteger(name) {}
void SR(CBotVar* left, CBotVar* right) override
{
SetValShort(static_cast<unsigned short>(left->GetValShort()) >> right->GetValInt());
}
bool Save1State(std::ostream &ostr) override
{
return WriteShort(ostr, m_val);
}
};
} // namespace CBot

View File

@ -37,9 +37,9 @@ bool CBotVarString::Ne(CBotVar* left, CBotVar* right)
return left->GetValString() != right->GetValString();
}
bool CBotVarString::Save1State(FILE* pf)
bool CBotVarString::Save1State(std::ostream &ostr)
{
return WriteString(pf, m_val);
return WriteString(ostr, m_val);
}
} // namespace CBot

View File

@ -63,7 +63,7 @@ public:
bool Eq(CBotVar* left, CBotVar* right) override;
bool Ne(CBotVar* left, CBotVar* right) override;
bool Save1State(FILE* pf) override;
bool Save1State(std::ostream &ostr) override;
private:
template<typename T>

View File

@ -74,6 +74,13 @@ public:
return s.str();
}
protected:
virtual void SetValue(T val)
{
this->m_val = val;
this->m_binit = CBotVar::InitType::DEF;
}
protected:
//! The value
T m_val;
@ -86,18 +93,59 @@ template <typename T, CBotType type>
class CBotVarNumberBase : public CBotVarValue<T, type>
{
public:
CBotVarNumberBase(const CBotToken &name) : CBotVarValue<T, type>(name) {}
CBotVarNumberBase(const CBotToken &name) : CBotVarValue<T, type>(name)
{
this->m_val = static_cast<T>(0);
}
void SetValByte(signed char val) override
{
this->SetValue(static_cast<T>(val));
}
void SetValShort(short val) override
{
this->SetValue(static_cast<T>(val));
}
void SetValChar(uint32_t val) override
{
this->SetValue(static_cast<T>(val));
}
void SetValInt(int val, const std::string &s = "") override
{
this->m_val = static_cast<T>(val);
this->m_binit = CBotVar::InitType::DEF;
this->SetValue(static_cast<T>(val));
}
void SetValLong(long val) override
{
this->SetValue(static_cast<T>(val));
}
void SetValFloat(float val) override
{
this->m_val = static_cast<T>(val);
this->m_binit = CBotVar::InitType::DEF;
this->SetValue(static_cast<T>(val));
}
void SetValDouble(double val) override
{
this->SetValue(static_cast<T>(val));
}
signed char GetValByte() override
{
return static_cast<signed char>(this->m_val);
}
short GetValShort() override
{
return static_cast<short>(this->m_val);
}
uint32_t GetValChar() override
{
return static_cast<uint32_t>(this->m_val);
}
int GetValInt() override
@ -105,19 +153,28 @@ public:
return static_cast<int>(this->m_val);
}
long GetValLong() override
{
return static_cast<long>(this->m_val);
}
float GetValFloat() override
{
return static_cast<float>(this->m_val);
}
double GetValDouble() override
{
return static_cast<double>(this->m_val);
}
bool Eq(CBotVar* left, CBotVar* right) override
{
return left->GetValFloat() == right->GetValFloat();
return static_cast<T>(*left) == static_cast<T>(*right);
}
bool Ne(CBotVar* left, CBotVar* right) override
{
return left->GetValFloat() != right->GetValFloat();
return static_cast<T>(*left) != static_cast<T>(*right);
}
};
@ -132,33 +189,33 @@ public:
void Mul(CBotVar* left, CBotVar* right) override
{
this->SetValFloat(left->GetValFloat() * right->GetValFloat());
this->SetValue(static_cast<T>(*left) * static_cast<T>(*right));
}
void Power(CBotVar* left, CBotVar* right) override
{
this->SetValFloat(pow(left->GetValFloat(), right->GetValFloat()));
this->SetValue(pow(static_cast<T>(*left), static_cast<T>(*right)));
}
CBotError Div(CBotVar* left, CBotVar* right) override
{
float r = right->GetValFloat();
if (r == 0) return CBotErrZeroDiv;
this->SetValFloat(left->GetValFloat() / r);
T r = static_cast<T>(*right);
if ( r == static_cast<T>(0) ) return CBotErrZeroDiv;
this->SetValue(static_cast<T>(*left) / r);
return CBotNoErr;
}
CBotError Modulo(CBotVar* left, CBotVar* right) override
{
float r = right->GetValFloat();
if (r == 0) return CBotErrZeroDiv;
this->SetValFloat(fmod(left->GetValFloat(), r));
T r = static_cast<T>(*right);
if ( r == static_cast<T>(0) ) return CBotErrZeroDiv;
this->SetValue(fmod(static_cast<T>(*left), r));
return CBotNoErr;
}
void Add(CBotVar* left, CBotVar* right) override
{
this->SetValFloat(left->GetValFloat() + right->GetValFloat());
this->SetValue(static_cast<T>(*left) + static_cast<T>(*right));
}
void Sub(CBotVar* left, CBotVar* right) override
{
this->SetValFloat(left->GetValFloat() - right->GetValFloat());
this->SetValue(static_cast<T>(*left) - static_cast<T>(*right));
}
void Neg() override
@ -176,21 +233,65 @@ public:
bool Lo(CBotVar* left, CBotVar* right) override
{
return left->GetValFloat() < right->GetValFloat();
return static_cast<T>(*left) < static_cast<T>(*right);
}
bool Hi(CBotVar* left, CBotVar* right) override
{
return left->GetValFloat() > right->GetValFloat();
return static_cast<T>(*left) > static_cast<T>(*right);
}
bool Ls(CBotVar* left, CBotVar* right) override
{
return left->GetValFloat() <= right->GetValFloat();
return static_cast<T>(*left) <= static_cast<T>(*right);
}
bool Hs(CBotVar* left, CBotVar* right) override
{
return left->GetValFloat() >= right->GetValFloat();
return static_cast<T>(*left) >= static_cast<T>(*right);
}
};
}
/**
* \brief An integer variable (byte, short, char, int, long)
*/
template <typename T, CBotType type>
class CBotVarInteger : public CBotVarNumber<T, type>
{
public:
CBotVarInteger(const CBotToken &name) : CBotVarNumber<T, type>(name) {}
CBotError Modulo(CBotVar* left, CBotVar* right) override
{
T r = static_cast<T>(*right);
if ( r == static_cast<T>(0) ) return CBotErrZeroDiv;
this->SetValue(static_cast<T>(*left) % r);
return CBotNoErr;
}
void XOr(CBotVar* left, CBotVar* right) override
{
this->SetValue(static_cast<T>(*left) ^ static_cast<T>(*right));
}
void And(CBotVar* left, CBotVar* right) override
{
this->SetValue(static_cast<T>(*left) & static_cast<T>(*right));
}
void Or(CBotVar* left, CBotVar* right) override
{
this->SetValue(static_cast<T>(*left) | static_cast<T>(*right));
}
void SL(CBotVar* left, CBotVar* right) override
{
this->SetValue(static_cast<T>(*left) << right->GetValInt());
}
void ASR(CBotVar* left, CBotVar* right) override
{
this->SetValue(static_cast<T>(*left) >> right->GetValInt());
}
void Not() override
{
this->m_val = ~(this->m_val);
}
};
} // namespace CBot

View File

@ -44,6 +44,8 @@ set(SOURCES
CBotInstr/CBotEmpty.h
CBotInstr/CBotExprLitBool.cpp
CBotInstr/CBotExprLitBool.h
CBotInstr/CBotExprLitChar.cpp
CBotInstr/CBotExprLitChar.h
CBotInstr/CBotExprLitNan.cpp
CBotInstr/CBotExprLitNan.h
CBotInstr/CBotExprLitNull.cpp
@ -127,14 +129,19 @@ set(SOURCES
CBotVar/CBotVarArray.h
CBotVar/CBotVarBoolean.cpp
CBotVar/CBotVarBoolean.h
CBotVar/CBotVarByte.h
CBotVar/CBotVarChar.h
CBotVar/CBotVarClass.cpp
CBotVar/CBotVarClass.h
CBotVar/CBotVarDouble.h
CBotVar/CBotVarFloat.cpp
CBotVar/CBotVarFloat.h
CBotVar/CBotVarInt.cpp
CBotVar/CBotVarInt.h
CBotVar/CBotVarLong.h
CBotVar/CBotVarPointer.cpp
CBotVar/CBotVarPointer.h
CBotVar/CBotVarShort.h
CBotVar/CBotVarString.cpp
CBotVar/CBotVarString.h
stdlib/Compilation.cpp
@ -151,7 +158,12 @@ set(LOCAL_INCLUDES
${CMAKE_CURRENT_SOURCE_DIR}/..
)
set(SYSTEM_INCLUDES
${Boost_INCLUDE_DIRS}
)
include_directories(${LOCAL_INCLUDES})
include_directories(SYSTEM ${SYSTEM_INCLUDES})
if(CBOT_STATIC)

View File

@ -181,7 +181,7 @@ CBotTypResult cfopen (CBotVar* pThis, CBotVar* &pVar)
// process FILE :: close
// execeution
// execution
bool rfclose (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception, void* user)
{
// it shouldn't be any parameters

View File

@ -44,8 +44,49 @@ if(MXE) # MXE requires special treatment
elseif(PLATFORM_WINDOWS)
# because it isn't included in standard linking libraries
if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
find_library(LIBINTL_LIBRARY NAMES intl.lib)
set(PLATFORM_LIBS ${LIBINTL_LIBRARY})
find_library(LIBINTL_LIBRARY NAMES intl.lib libintl)
if(${MSVC_STATIC})
if (${OPENAL_SOUND})
find_library(FLAC_LIBRARY NAMES flac.lib)
find_library(VORBIS_LIBRARY NAMES vorbis.lib)
find_library(VORBISENC_LIBRARY NAMES vorbisenc.lib)
find_library(OGG_LIBRARY NAMES ogg.lib)
set(OPENAL_MSVC_LIBS
${FLAC_LIBRARY}
${VORBIS_LIBRARY}
${VORBISENC_LIBRARY}
${OGG_LIBRARY}
)
endif()
find_library(BZ2_LIBRARY NAMES bz2.lib)
find_library(JPEG_LIBRARY NAMES jpeg.lib)
find_library(TIFF_LIBRARY NAMES tiff.lib)
find_library(LZMA_LIBRARY NAMES lzma.lib)
find_library(FREETYPE_LIBRARY NAMES freetype.lib)
set(MSVC_LIBS
${LIBINTL_LIBRARY}
${OPENAL_MSVC_LIBS}
${JPEG_LIBRARY}
${TIFF_LIBRARY}
${BZ2_LIBRARY}
${LZMA_LIBRARY}
${FREETYPE_LIBRARY}
winmm.lib
dxguid.lib
imm32.lib
ole32.lib
oleaut32.lib
version.lib
wsock32.lib
ws2_32.lib
)
else(${MSVC_STATIC})
set(MSVC_LIBS ${LIBINTL_LIBRARY})
endif()
set(PLATFORM_LIBS ${MSVC_LIBS})
else()
set(PLATFORM_LIBS "-lintl")
endif()
@ -58,6 +99,10 @@ elseif(PLATFORM_MACOSX)
find_library(LIBINTL_LIBRARY NAMES intl libintl)
find_path(LIBINTL_INCLUDE_PATH NAMES libintl.h)
set(PLATFORM_LIBS ${LIBINTL_LIBRARY})
elseif(PLATFORM_FREEBSD)
find_library(LIBINTL_LIBRARY NAMES intl libintl)
find_path(LIBINTL_INCLUDE_PATH NAMES libintl.h)
set(PLATFORM_LIBS ${LIBINTL_LIBRARY})
endif()
@ -106,6 +151,8 @@ set(BASE_SOURCES
common/error.h
common/event.cpp
common/event.h
common/font_loader.h
common/font_loader.cpp
common/global.h
common/image.cpp
common/image.h

View File

@ -815,11 +815,29 @@ bool CApplication::CreateVideoSurface()
m_private->glcontext = SDL_GL_CreateContext(m_private->window);
int vsync = 0;
if (GetConfigFile().GetIntProperty("Experimental", "VSync", vsync))
if (GetConfigFile().GetIntProperty("Setup", "VSync", vsync))
{
SDL_GL_SetSwapInterval(vsync);
while (SDL_GL_SetSwapInterval(vsync) == -1)
{
switch(vsync)
{
case -1: //failed with adaptive sync?
GetLogger()->Warn("Adaptive sync not supported.\n");
vsync = 1;
break;
case 1: //failed with VSync enabled?
GetLogger()->Warn("Couldn't enable VSync.\n");
vsync = 0;
break;
case 0: //failed with VSync disabled?
GetLogger()->Warn("Couldn't disable VSync.\n");
vsync = 1;
break;
}
}
GetConfigFile().SetIntProperty("Setup", "VSync", vsync);
GetLogger()->Info("Using Vsync: %s\n", (vsync ? "true" : "false"));
GetLogger()->Info("Using Vsync: %s\n", (vsync == -1 ? "adaptive" : (vsync ? "true" : "false")));
}
return true;
@ -833,6 +851,27 @@ bool CApplication::ChangeVideoConfig(const Gfx::DeviceConfig &newConfig)
SDL_SetWindowSize(m_private->window, m_deviceConfig.size.x, m_deviceConfig.size.y);
SDL_SetWindowFullscreen(m_private->window, m_deviceConfig.fullScreen ? SDL_WINDOW_FULLSCREEN : 0);
int vsync = m_engine->GetVSync();
while (SDL_GL_SetSwapInterval(vsync) == -1)
{
switch(vsync)
{
case -1: //failed with adaptive sync?
GetLogger()->Warn("Adaptive sync not supported.\n");
vsync = 1;
break;
case 1: //failed with VSync enabled?
GetLogger()->Warn("Couldn't enable VSync.\n");
vsync = 0;
break;
case 0: //failed with VSync disabled?
GetLogger()->Warn("Couldn't disable VSync.\n");
vsync = 1;
break;
}
}
m_engine->SetVSync(vsync);
m_device->ConfigChanged(m_deviceConfig);
m_eventQueue->AddEvent(Event(EVENT_RESOLUTION_CHANGED));
@ -1718,6 +1757,11 @@ char CApplication::GetLanguageChar() const
case LANGUAGE_RUSSIAN:
langChar = 'R';
break;
case LANGUAGE_PORTUGUESE_BRAZILIAN:
langChar = 'B';
break;
}
return langChar;
}
@ -1774,6 +1818,10 @@ void CApplication::SetLanguage(Language language)
{
m_language = LANGUAGE_RUSSIAN;
}
else if (strncmp(envLang,"pt",2) == 0)
{
m_language = LANGUAGE_PORTUGUESE_BRAZILIAN;
}
else
{
GetLogger()->Warn("Enviromnent locale ('%s') is not supported, setting default language\n", envLang);
@ -1812,6 +1860,10 @@ void CApplication::SetLanguage(Language language)
case LANGUAGE_RUSSIAN:
locale = "ru_RU.utf8";
break;
case LANGUAGE_PORTUGUESE_BRAZILIAN:
locale = "pt_BR.utf8";
break;
}
std::string langStr = "LANGUAGE=";
@ -1832,7 +1884,12 @@ void CApplication::SetLanguage(Language language)
// Update C++ locale
try
{
#if defined(_MSC_VER) && defined(_DEBUG)
// Avoids failed assertion in VS debugger
throw -1;
#else
std::locale::global(std::locale(systemLocale.c_str()));
#endif
}
catch (...)
{

View File

@ -61,7 +61,7 @@ object-oriented language, CBOT, which can be used to program the robots availabl
The original version of the game was developed by [Epsitec](http://www.epsitec.ch/) and released in 2001.
Later, in 2005 another version named Ceebot was released. In March 2012, through attempts
by Polish Colobot fans, Epsitec agreeed to release the source code of the game on GPLv3 license.
The license was given specfifically to our community, <b>TerranovaTeam</b>,
The license was given specifically to our community, <b>TerranovaTeam</b>,
part of <b>International Colobot Community (ICC)</b> (previously known as <i>Polish Portal of Colobot (PPC)</i>;
Polish: <i>Polski Portal Colobota</i>) with our website at http://colobot.info/.

View File

@ -38,46 +38,41 @@
#include <boost/filesystem.hpp>
CPathManager::CPathManager(CSystemUtils* systemUtils)
: m_systemUtils(systemUtils)
: m_dataPath(systemUtils->GetDataPath())
, m_langPath(systemUtils->GetLangPath())
, m_savePath(systemUtils->GetSaveDir())
, m_modAutoloadDir{ m_dataPath + "/mods", m_savePath + "/mods" }
, m_mods{}
{
#ifdef PORTABLE
m_dataPath = "./data";
m_langPath = "./lang";
m_savePath = "./saves";
#else
m_dataPath = m_systemUtils->GetDataPath();
m_langPath = m_systemUtils->GetLangPath();
#ifdef DEV_BUILD
m_savePath = "./saves";
#else
m_savePath = m_systemUtils->GetSaveDir();
#endif
#endif
}
CPathManager::~CPathManager()
{
}
void CPathManager::SetDataPath(std::string dataPath)
void CPathManager::SetDataPath(const std::string &dataPath)
{
m_dataPath = dataPath;
}
void CPathManager::SetLangPath(std::string langPath)
void CPathManager::SetLangPath(const std::string &langPath)
{
m_langPath = langPath;
}
void CPathManager::SetSavePath(std::string savePath)
void CPathManager::SetSavePath(const std::string &savePath)
{
m_savePath = savePath;
}
void CPathManager::AddMod(std::string modPath)
void CPathManager::AddModAutoloadDir(const std::string &modAutoloadDirPath)
{
GetLogger()->Info("Loading mod: '%s'\n", modPath.c_str());
CResourceManager::AddLocation(modPath, true);
m_modAutoloadDir.push_back(modAutoloadDirPath);
}
void CPathManager::AddMod(const std::string &modPath)
{
m_mods.push_back(modPath);
}
const std::string& CPathManager::GetDataPath()
@ -106,8 +101,8 @@ std::string CPathManager::VerifyPaths()
{
GetLogger()->Error("Data directory '%s' doesn't exist or is not a directory\n", m_dataPath.c_str());
return std::string("Could not read from data directory:\n") +
std::string("'") + m_dataPath + std::string("'\n") +
std::string("Please check your installation, or supply a valid data directory by -datadir option.");
std::string("'") + m_dataPath + std::string("'\n") +
std::string("Please check your installation, or supply a valid data directory by -datadir option.");
}
#if PLATFORM_WINDOWS
@ -133,19 +128,51 @@ std::string CPathManager::VerifyPaths()
void CPathManager::InitPaths()
{
LoadModsFromDir(m_dataPath+"/mods");
LoadModsFromDir(m_savePath+"/mods");
GetLogger()->Info("Data path: %s\n", m_dataPath.c_str());
GetLogger()->Info("Save path: %s\n", m_savePath.c_str());
CResourceManager::AddLocation(m_dataPath, false);
if (!m_modAutoloadDir.empty())
{
GetLogger()->Info("Mod autoload dirs:\n");
for(const std::string& modAutoloadDir : m_modAutoloadDir)
GetLogger()->Info(" * %s\n", modAutoloadDir.c_str());
}
if (!m_mods.empty())
{
GetLogger()->Info("Mods:\n");
for(const std::string& modPath : m_mods)
GetLogger()->Info(" * %s\n", modPath.c_str());
}
CResourceManager::AddLocation(m_dataPath);
for (const std::string& modAutoloadDir : m_modAutoloadDir)
{
GetLogger()->Trace("Searching for mods in '%s'...\n", modAutoloadDir.c_str());
for (const std::string& modPath : FindModsInDir(modAutoloadDir))
{
GetLogger()->Info("Autoloading mod: '%s'\n", modPath.c_str());
CResourceManager::AddLocation(modPath);
}
}
for (const std::string& modPath : m_mods)
{
GetLogger()->Info("Loading mod: '%s'\n", modPath.c_str());
CResourceManager::AddLocation(modPath);
}
CResourceManager::SetSaveLocation(m_savePath);
CResourceManager::AddLocation(m_savePath, true);
CResourceManager::AddLocation(m_savePath);
GetLogger()->Debug("Finished initalizing data paths\n");
GetLogger()->Debug("PHYSFS search path is:\n");
for (const std::string& path : CResourceManager::GetLocations())
GetLogger()->Debug(" * %s\n", path.c_str());
}
void CPathManager::LoadModsFromDir(const std::string &dir)
std::vector<std::string> CPathManager::FindModsInDir(const std::string &dir)
{
GetLogger()->Trace("Looking for mods in '%s' ...\n", dir.c_str());
std::vector<std::string> ret;
try
{
#if PLATFORM_WINDOWS
@ -156,9 +183,9 @@ void CPathManager::LoadModsFromDir(const std::string &dir)
for(; iterator != boost::filesystem::directory_iterator(); ++iterator)
{
#if PLATFORM_WINDOWS
AddMod(CSystemUtilsWindows::UTF8_Encode(iterator->path().wstring()));
ret.push_back(CSystemUtilsWindows::UTF8_Encode(iterator->path().wstring()));
#else
AddMod(iterator->path().string());
ret.push_back(iterator->path().string());
#endif
}
}
@ -166,4 +193,5 @@ void CPathManager::LoadModsFromDir(const std::string &dir)
{
GetLogger()->Warn("Unable to load mods from directory '%s': %s\n", dir.c_str(), e.what());
}
return ret;
}

View File

@ -17,16 +17,10 @@
* along with this program. If not, see http://gnu.org/licenses
*/
/**
* \file app/pathman.h
* \brief Class for managing data/lang/save paths
*/
#pragma once
#include "common/singleton.h"
#include <string>
#include <vector>
class CSystemUtils;
@ -34,16 +28,17 @@ class CSystemUtils;
* \class CPathManager
* \brief Class for managing data/lang/save paths
*/
class CPathManager : public CSingleton<CPathManager>
class CPathManager
{
public:
CPathManager(CSystemUtils* systemUtils);
~CPathManager();
void SetDataPath(std::string dataPath);
void SetLangPath(std::string langPath);
void SetSavePath(std::string savePath);
void AddMod(std::string modPath);
void SetDataPath(const std::string &dataPath);
void SetLangPath(const std::string &langPath);
void SetSavePath(const std::string &savePath);
void AddModAutoloadDir(const std::string &modAutoloadDirPath);
void AddMod(const std::string &modPath);
const std::string& GetDataPath();
const std::string& GetLangPath();
@ -56,14 +51,17 @@ public:
private:
//! Loads all mods from given directory
void LoadModsFromDir(const std::string &dir);
std::vector<std::string> FindModsInDir(const std::string &dir);
private:
CSystemUtils* m_systemUtils;
//! Data path
std::string m_dataPath;
//! Lang path
std::string m_langPath;
//! Save path
std::string m_savePath;
//! Mod autoload paths
std::vector<std::string> m_modAutoloadDir;
//! Mod paths
std::vector<std::string> m_mods;
};

View File

@ -133,7 +133,7 @@ void CSignalHandlers::ReportError(const std::string& errorMessage)
msg << "including information on what you were doing before this happened and all the information below." << std::endl;
msg << "==============================" << std::endl;
#if BUILD_NUMBER == 0
#ifdef OFFICIAL_BUILD
#ifdef OFFICIAL_COLOBOT_BUILD
msg << "You are running official " << COLOBOT_VERSION_DISPLAY << " build." << std::endl;
#else
// COLOBOT_VERSION_DISPLAY doesn't update if you don't run CMake after "git pull"

View File

@ -16,7 +16,7 @@
#cmakedefine OPENAL_SOUND
#cmakedefine PORTABLE @PORTABLE@
#cmakedefine PORTABLE_SAVES @PORTABLE_SAVES@
#define COLOBOT_DEFAULT_DATADIR "@COLOBOT_INSTALL_DATA_DIR@"
#define COLOBOT_I18N_DIR "@COLOBOT_INSTALL_I18N_DIR@"

View File

@ -232,6 +232,7 @@ void InitializeEventTypeTexts()
EVENT_TYPE_TEXT[EVENT_INTERFACE_SHADOW_MAPPING_QUALITY] = "EVENT_INTERFACE_SHADOW_MAPPING_QUALITY";
EVENT_TYPE_TEXT[EVENT_INTERFACE_SHADOW_MAPPING_BUFFER] = "EVENT_INTERFACE_SHADOW_MAPPING_BUFFER";
EVENT_TYPE_TEXT[EVENT_INTERFACE_LANGUAGE] = "EVENT_INTERFACE_LANGUAGE";
EVENT_TYPE_TEXT[EVENT_INTERFACE_VSYNC] = "EVENT_INTERFACE_VSYNC";
EVENT_TYPE_TEXT[EVENT_INTERFACE_KINFO1] = "EVENT_INTERFACE_KINFO1";
EVENT_TYPE_TEXT[EVENT_INTERFACE_KINFO2] = "EVENT_INTERFACE_KINFO2";

View File

@ -268,6 +268,7 @@ enum EventType
EVENT_INTERFACE_SHADOW_MAPPING_QUALITY = 788,
EVENT_INTERFACE_SHADOW_MAPPING_BUFFER = 789,
EVENT_INTERFACE_LANGUAGE = 790,
EVENT_INTERFACE_VSYNC = 791,
EVENT_INTERFACE_KINFO1 = 500,
EVENT_INTERFACE_KINFO2 = 501,

115
src/common/font_loader.cpp Normal file
View File

@ -0,0 +1,115 @@
/*
* This file is part of the Colobot: Gold Edition source code
* Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://gnu.org/licenses
*/
#include "common/font_loader.h"
#include "common/logger.h"
#include "common/make_unique.h"
#include "common/resources/inputstream.h"
#include "common/resources/outputstream.h"
#include "common/system/system.h"
#include "graphics/engine/text.h"
#include <map>
#include <memory>
#include <utility>
#include <cstring>
#include <boost/property_tree/ini_parser.hpp>
#include <boost/regex.hpp>
namespace bp = boost::property_tree;
const std::map<Gfx::FontType, std::string> DEFAULT_FONT =
{
{ Gfx::FONT_COMMON, "dvu_sans.ttf" },
{ Gfx::FONT_COMMON_BOLD, "dvu_sans_bold.ttf" },
{ Gfx::FONT_COMMON_ITALIC, "dvu_sans_italic.ttf" },
{ Gfx::FONT_STUDIO, "dvu_sans_mono.ttf" },
{ Gfx::FONT_STUDIO_BOLD, "dvu_sans_mono_bold.ttf" },
{ Gfx::FONT_STUDIO_ITALIC, "dvu_sans_mono.ttf" }, //placeholder for future use, DejaVu Sans Mono doesn't have italic variant
{ Gfx::FONT_SATCOM, "dvu_sans.ttf" },
{ Gfx::FONT_SATCOM_BOLD, "dvu_sans_bold.ttf" },
{ Gfx::FONT_SATCOM_ITALIC, "dvu_sans_italic.ttf" },
};
const std::map<Gfx::FontType, std::string> FONT_TYPE =
{
{ Gfx::FONT_COMMON, "FontCommon" },
{ Gfx::FONT_COMMON_BOLD, "FontCommonBold" },
{ Gfx::FONT_COMMON_ITALIC, "FontCommonItalic" },
{ Gfx::FONT_STUDIO, "FontStudio" },
{ Gfx::FONT_STUDIO_BOLD, "FontStudioBold" },
{ Gfx::FONT_STUDIO_ITALIC, "FontStudioItalic" },
{ Gfx::FONT_SATCOM, "FontSatCom" },
{ Gfx::FONT_SATCOM_BOLD, "FontSatComBold" },
{ Gfx::FONT_SATCOM_ITALIC, "FontSatComItalic" },
};
CFontLoader::CFontLoader()
{
}
CFontLoader::~CFontLoader()
{
}
bool CFontLoader::Init()
{
try
{
std::unique_ptr<std::istream> stream;
auto inputStream = MakeUnique<CInputStream>("/fonts/fonts.ini");
bool good = inputStream->is_open();
stream = std::move(inputStream);
if (good)
{
bp::ini_parser::read_ini(*stream, m_propertyTree);
GetLogger()->Debug("Fonts config file loaded correctly. \n");
}
else
{
return false;
}
}
catch (std::exception & e)
{
GetLogger()->Error("Error on parsing config file: %s\n", e.what());
return false;
}
return true;
}
std::string CFontLoader::GetFont(Gfx::FontType type)
{
return std::string("/fonts/") + m_propertyTree.get<std::string>(GetFontType(type), GetDefaultFont(type));
}
std::string CFontLoader::GetDefaultFont(Gfx::FontType type) const
{
return DEFAULT_FONT.at(type);
}
std::string CFontLoader::GetFontType(Gfx::FontType type) const
{
return FONT_TYPE.at(type);
}

72
src/common/font_loader.h Normal file
View File

@ -0,0 +1,72 @@
/*
* This file is part of the Colobot: Gold Edition source code
* Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://gnu.org/licenses
*/
/**
* \file common/font_loader.h
* \brief Class for loading fonts from /data/fonts/fonts.ini
*/
#pragma once
#include "common/singleton.h"
#include "graphics/engine/text.h"
#include <boost/property_tree/ptree.hpp>
#include <string>
/**
* \class CFontLoader
*
* \brief Class for loading config file
*
*/
class CFontLoader
{
public:
CFontLoader();
virtual ~CFontLoader();
/** Loads fonts.ini
* \return return true on success
*/
bool Init();
/** Reads given font from file
* \return return path to font file
*/
std::string GetFont(Gfx::FontType type);
/** Const type method to read filenames of fonts from defaultFont map
* used as a fallback if it wasn't possible to read font from fonts.ini
* \return return filename of default path
*/
std::string GetDefaultFont(Gfx::FontType type) const;
/** Const type method converting Gfx::FontType to string
* \return return id of font used in fonts.ini file
*/
std::string GetFontType(Gfx::FontType type) const;
private:
boost::property_tree::ptree m_propertyTree;
};

View File

@ -27,7 +27,8 @@ const std::map<Language, std::string> LANGUAGE_MAP = {
{ LANGUAGE_GERMAN, "de" },
{ LANGUAGE_FRENCH, "fr" },
{ LANGUAGE_POLISH, "pl" },
{ LANGUAGE_RUSSIAN, "ru" }
{ LANGUAGE_RUSSIAN, "ru" },
{ LANGUAGE_PORTUGUESE_BRAZILIAN, "pt" }
};
bool ParseLanguage(const std::string& str, Language& language)

View File

@ -33,7 +33,8 @@ enum Language
LANGUAGE_GERMAN = 2,
LANGUAGE_POLISH = 3,
LANGUAGE_RUSSIAN = 4,
LANGUAGE_CZECH = 5
LANGUAGE_CZECH = 5,
LANGUAGE_PORTUGUESE_BRAZILIAN = 6
};
bool ParseLanguage(const std::string& str, Language& language);

View File

@ -85,6 +85,16 @@ bool CResourceManager::RemoveLocation(const std::string &location)
return true;
}
std::vector<std::string> CResourceManager::GetLocations()
{
std::vector<std::string> ret;
char **list = PHYSFS_getSearchPath();
for (char **it = list; *it != nullptr; ++it)
ret.push_back(*it);
PHYSFS_freeList(list);
return ret;
}
bool CResourceManager::SetSaveLocation(const std::string &location)
{

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